LogCabin
|
00001 /* Copyright (c) 2012 Stanford University 00002 * Copyright (c) 2014 Diego Ongaro 00003 * 00004 * Permission to use, copy, modify, and distribute this software for any 00005 * purpose with or without fee is hereby granted, provided that the above 00006 * copyright notice and this permission notice appear in all copies. 00007 * 00008 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES 00009 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 00010 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR 00011 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 00012 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 00013 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 00014 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00015 */ 00016 00017 #include <cinttypes> 00018 #include <google/protobuf/message.h> 00019 #include <iostream> 00020 #include <memory> 00021 #include <string> 00022 00023 #include "RPC/OpaqueClientRPC.h" 00024 00025 #ifndef LOGCABIN_RPC_CLIENTRPC_H 00026 #define LOGCABIN_RPC_CLIENTRPC_H 00027 00028 namespace LogCabin { 00029 namespace RPC { 00030 00031 class ClientSession; // forward declaration 00032 00033 /** 00034 * This class represents an asynchronous remote procedure call. Unlike 00035 * OpaqueClientRPC, this executes a particular method on a particular service. 00036 * 00037 * TODO(ongaro): This abstraction should ideally contain protocol version 00038 * negotiation for the higher layer. To do so, we'd want to be able to 00039 * associate a small amount of state with the session. 00040 */ 00041 class ClientRPC { 00042 public: 00043 /// Clock used for timeouts. 00044 typedef OpaqueClientRPC::Clock Clock; 00045 /// Type for absolute time values used for timeouts. 00046 typedef OpaqueClientRPC::TimePoint TimePoint; 00047 00048 /** 00049 * Issue an RPC to a remote service. 00050 * \param session 00051 * A connection to the remote server. 00052 * \param service 00053 * Identifies the service running on the server. 00054 * See Protocol::Common::ServiceId. 00055 * \param serviceSpecificErrorVersion 00056 * This tells the Service what service-specific errors the client 00057 * understands. Clients can expect services to not send 00058 * service-specific errors introduced in newer versions, but they 00059 * should remain compatible with older versions. 00060 * \param opCode 00061 * Identifies the remote procedure within the Service to execute. 00062 * \param request 00063 * The arguments to the remote procedure. 00064 */ 00065 ClientRPC(std::shared_ptr<RPC::ClientSession> session, 00066 uint16_t service, 00067 uint8_t serviceSpecificErrorVersion, 00068 uint16_t opCode, 00069 const google::protobuf::Message& request); 00070 00071 /** 00072 * Default constructor. This doesn't create a valid RPC, but it is useful 00073 * as a placeholder. 00074 */ 00075 ClientRPC(); 00076 00077 /** 00078 * Move constructor. 00079 */ 00080 ClientRPC(ClientRPC&&); 00081 00082 /** 00083 * Destructor. 00084 */ 00085 ~ClientRPC(); 00086 00087 /** 00088 * Move assignment. 00089 */ 00090 ClientRPC& operator=(ClientRPC&&); 00091 00092 /** 00093 * Abort the RPC. 00094 * The caller is no longer interested in its reply. 00095 */ 00096 void cancel(); 00097 00098 /** 00099 * Indicate whether a response or error has been received for 00100 * the RPC. 00101 * \return 00102 * True means the reply is ready or an error has occurred; false 00103 * otherwise. 00104 */ 00105 bool isReady(); 00106 00107 /** 00108 * The return type of waitForReply(). 00109 */ 00110 enum class Status { 00111 /** 00112 * The service returned a normal response. This is available in 00113 * 'response'. 00114 */ 00115 OK, 00116 /** 00117 * The service threw an error (but at the transport level, the RPC 00118 * succeeded). Service-specific details may be available in 00119 * 'serviceSpecificError'. 00120 */ 00121 SERVICE_SPECIFIC_ERROR, 00122 /** 00123 * The server could not be contacted or did not reply. It is unknown 00124 * whether or not the server executed the RPC. More information is 00125 * available with getErrorMessage(). 00126 */ 00127 RPC_FAILED, 00128 /** 00129 * The RPC was aborted using #cancel(). It is unknown whether the 00130 * server executed or will execute the RPC. 00131 */ 00132 RPC_CANCELED, 00133 /** 00134 * The RPC did not complete before the given timeout elapsed. It is 00135 * unknown whether or not the server executed the RPC (yet). 00136 */ 00137 TIMEOUT, 00138 /** 00139 * The server is not running the requested service. 00140 */ 00141 INVALID_SERVICE, 00142 /** 00143 * The server rejected the request, probably because it doesn't support 00144 * the opcode, or maybe the request arguments were invalid. 00145 */ 00146 INVALID_REQUEST, 00147 }; 00148 00149 /** 00150 * Wait for a reply to the RPC or an error. 00151 * Panics if the server responds but is not running the same protocol. 00152 * 00153 * \param[out] response 00154 * If not NULL, this will be filled in if this method returns OK. 00155 * \param[out] serviceSpecificError 00156 * If not NULL, this will be filled in if this method returns 00157 * SERVICE_SPECIFIC_ERROR. 00158 * \param[in] timeout 00159 * After this time has elapsed, stop waiting and return TIMEOUT. 00160 * In this case, response and serviceSpecificError will be left 00161 * unmodified. 00162 * \return 00163 * See the individual values of #Status. 00164 */ 00165 Status waitForReply(google::protobuf::Message* response, 00166 google::protobuf::Message* serviceSpecificError, 00167 TimePoint timeout); 00168 00169 /** 00170 * If an RPC failure occurred, return a message describing that error. 00171 * 00172 * All errors indicate that it is unknown whether or not the server 00173 * executed the RPC. Unless the RPC was canceled with #cancel(), the 00174 * ClientSession has been disconnected and is no longer useful for 00175 * initiating new RPCs. 00176 * 00177 * \return 00178 * If an RPC failure has occurred, a message describing that error. 00179 * Otherwise, an empty string. 00180 */ 00181 std::string getErrorMessage() const; 00182 00183 private: 00184 /** 00185 * Identifies the service running on the server. 00186 * See Protocol::Common::ServiceId. 00187 */ 00188 uint16_t service; 00189 00190 /** 00191 * Identifies the remote procedure within the Service to execute. 00192 */ 00193 uint16_t opCode; 00194 00195 OpaqueClientRPC opaqueRPC; 00196 00197 // ClientRPC is non-copyable. 00198 ClientRPC(const ClientRPC&) = delete; 00199 ClientRPC& operator=(const ClientRPC&) = delete; 00200 00201 }; // class ClientRPC 00202 00203 /** 00204 * Output a ClientRPC::Status to a stream. 00205 * This is helpful for google test output. 00206 */ 00207 ::std::ostream& 00208 operator<<(::std::ostream& os, ClientRPC::Status status); 00209 00210 } // namespace LogCabin::RPC 00211 } // namespace LogCabin 00212 00213 #endif /* LOGCABIN_RPC_CLIENTRPC_H */