diff options
author | Muxi Yan <mxyan@google.com> | 2017-12-06 18:47:16 -0800 |
---|---|---|
committer | Muxi Yan <mxyan@google.com> | 2017-12-06 18:47:16 -0800 |
commit | 4a117f0be7feb1779bd0bb0b65c6e2d930f07e80 (patch) | |
tree | 30ca52f7141db8fc8543a5a0bc7842766fab5c12 /include | |
parent | 1b1c9b387bcd98f08b8c17f6ee15095c099dd665 (diff) | |
parent | 4f22c919e1207af206fc83e7378f04e047f7c78d (diff) |
Merge e759d2a^
Diffstat (limited to 'include')
32 files changed, 812 insertions, 861 deletions
diff --git a/include/grpc++/alarm.h b/include/grpc++/alarm.h index 2d88d868e5..b43425e224 100644 --- a/include/grpc++/alarm.h +++ b/include/grpc++/alarm.h @@ -92,7 +92,7 @@ class Alarm : private GrpcLibraryCodegen { } private: - class AlarmEntry : public CompletionQueueTag { + class AlarmEntry : public internal::CompletionQueueTag { public: AlarmEntry(void* tag) : tag_(tag) {} void Set(void* tag) { tag_ = tag; } diff --git a/include/grpc++/channel.h b/include/grpc++/channel.h index c50091d6ac..e9fb5a5d09 100644 --- a/include/grpc++/channel.h +++ b/include/grpc++/channel.h @@ -32,7 +32,7 @@ struct grpc_channel; namespace grpc { /// Channels represent a connection to an endpoint. Created by \a CreateChannel. class Channel final : public ChannelInterface, - public CallHook, + public internal::CallHook, public std::enable_shared_from_this<Channel>, private GrpcLibraryCodegen { public: @@ -51,18 +51,16 @@ class Channel final : public ChannelInterface, private: template <class InputMessage, class OutputMessage> - friend Status BlockingUnaryCall(ChannelInterface* channel, - const RpcMethod& method, - ClientContext* context, - const InputMessage& request, - OutputMessage* result); + friend class internal::BlockingUnaryCallImpl; friend std::shared_ptr<Channel> CreateChannelInternal( const grpc::string& host, grpc_channel* c_channel); Channel(const grpc::string& host, grpc_channel* c_channel); - Call CreateCall(const RpcMethod& method, ClientContext* context, - CompletionQueue* cq) override; - void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) override; + internal::Call CreateCall(const internal::RpcMethod& method, + ClientContext* context, + CompletionQueue* cq) override; + void PerformOpsOnCall(internal::CallOpSetInterface* ops, + internal::Call* call) override; void* RegisterMethod(const char* method) override; void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, diff --git a/include/grpc++/impl/codegen/async_stream.h b/include/grpc++/impl/codegen/async_stream.h index e60572fc93..4476033463 100644 --- a/include/grpc++/impl/codegen/async_stream.h +++ b/include/grpc++/impl/codegen/async_stream.h @@ -30,6 +30,7 @@ namespace grpc { class CompletionQueue; +namespace internal { /// Common interface for all client side asynchronous streaming. class ClientAsyncStreamingInterface { public: @@ -151,15 +152,16 @@ class AsyncWriterInterface { } }; +} // namespace internal + template <class R> -class ClientAsyncReaderInterface : public ClientAsyncStreamingInterface, - public AsyncReaderInterface<R> {}; +class ClientAsyncReaderInterface + : public internal::ClientAsyncStreamingInterface, + public internal::AsyncReaderInterface<R> {}; -/// Async client-side API for doing server-streaming RPCs, -/// where the incoming message stream coming from the server has -/// messages of type \a R. +namespace internal { template <class R> -class ClientAsyncReader final : public ClientAsyncReaderInterface<R> { +class ClientAsyncReaderFactory { public: /// Create a stream object. /// Write the first request out if \a start is set. @@ -169,16 +171,25 @@ class ClientAsyncReader final : public ClientAsyncReaderInterface<R> { /// Note that \a context will be used to fill in custom initial metadata /// used to send to the server when starting the call. template <class W> - static ClientAsyncReader* Create(ChannelInterface* channel, - CompletionQueue* cq, const RpcMethod& method, - ClientContext* context, const W& request, - bool start, void* tag) { - Call call = channel->CreateCall(method, context, cq); + static ClientAsyncReader<R>* Create(ChannelInterface* channel, + CompletionQueue* cq, + const ::grpc::internal::RpcMethod& method, + ClientContext* context, const W& request, + bool start, void* tag) { + ::grpc::internal::Call call = channel->CreateCall(method, context, cq); return new (g_core_codegen_interface->grpc_call_arena_alloc( - call.call(), sizeof(ClientAsyncReader))) - ClientAsyncReader(call, context, request, start, tag); + call.call(), sizeof(ClientAsyncReader<R>))) + ClientAsyncReader<R>(call, context, request, start, tag); } +}; +} // namespace internal +/// Async client-side API for doing server-streaming RPCs, +/// where the incoming message stream coming from the server has +/// messages of type \a R. +template <class R> +class ClientAsyncReader final : public ClientAsyncReaderInterface<R> { + public: // always allocated against a call arena, no memory free required static void operator delete(void* ptr, std::size_t size) { assert(size == sizeof(ClientAsyncReader)); @@ -233,9 +244,10 @@ class ClientAsyncReader final : public ClientAsyncReaderInterface<R> { } private: + friend class internal::ClientAsyncReaderFactory<R>; template <class W> - ClientAsyncReader(Call call, ClientContext* context, const W& request, - bool start, void* tag) + ClientAsyncReader(::grpc::internal::Call call, ClientContext* context, + const W& request, bool start, void* tag) : context_(context), call_(call), started_(start) { // TODO(ctiller): don't assert GPR_CODEGEN_ASSERT(init_ops_.SendMessage(request).ok()); @@ -255,19 +267,27 @@ class ClientAsyncReader final : public ClientAsyncReaderInterface<R> { } ClientContext* context_; - Call call_; + ::grpc::internal::Call call_; bool started_; - CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpClientSendClose> + ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata, + ::grpc::internal::CallOpSendMessage, + ::grpc::internal::CallOpClientSendClose> init_ops_; - CallOpSet<CallOpRecvInitialMetadata> meta_ops_; - CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> read_ops_; - CallOpSet<CallOpRecvInitialMetadata, CallOpClientRecvStatus> finish_ops_; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata> + meta_ops_; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata, + ::grpc::internal::CallOpRecvMessage<R>> + read_ops_; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata, + ::grpc::internal::CallOpClientRecvStatus> + finish_ops_; }; /// Common interface for client side asynchronous writing. template <class W> -class ClientAsyncWriterInterface : public ClientAsyncStreamingInterface, - public AsyncWriterInterface<W> { +class ClientAsyncWriterInterface + : public internal::ClientAsyncStreamingInterface, + public internal::AsyncWriterInterface<W> { public: /// Signal the client is done with the writes (half-close the client stream). /// Thread-safe with respect to \a AsyncReaderInterface::Read @@ -276,11 +296,9 @@ class ClientAsyncWriterInterface : public ClientAsyncStreamingInterface, virtual void WritesDone(void* tag) = 0; }; -/// Async API on the client side for doing client-streaming RPCs, -/// where the outgoing message stream going to the server contains -/// messages of type \a W. +namespace internal { template <class W> -class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> { +class ClientAsyncWriterFactory { public: /// Create a stream object. /// Start the RPC if \a start is set @@ -294,16 +312,25 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> { /// message from the server upon a successful call to the \a Finish /// method of this instance. template <class R> - static ClientAsyncWriter* Create(ChannelInterface* channel, - CompletionQueue* cq, const RpcMethod& method, - ClientContext* context, R* response, - bool start, void* tag) { - Call call = channel->CreateCall(method, context, cq); + static ClientAsyncWriter<W>* Create(ChannelInterface* channel, + CompletionQueue* cq, + const ::grpc::internal::RpcMethod& method, + ClientContext* context, R* response, + bool start, void* tag) { + ::grpc::internal::Call call = channel->CreateCall(method, context, cq); return new (g_core_codegen_interface->grpc_call_arena_alloc( - call.call(), sizeof(ClientAsyncWriter))) - ClientAsyncWriter(call, context, response, start, tag); + call.call(), sizeof(ClientAsyncWriter<W>))) + ClientAsyncWriter<W>(call, context, response, start, tag); } +}; +} // namespace internal +/// Async API on the client side for doing client-streaming RPCs, +/// where the outgoing message stream going to the server contains +/// messages of type \a W. +template <class W> +class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> { + public: // always allocated against a call arena, no memory free required static void operator delete(void* ptr, std::size_t size) { assert(size == sizeof(ClientAsyncWriter)); @@ -376,9 +403,10 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> { } private: + friend class internal::ClientAsyncWriterFactory<W>; template <class R> - ClientAsyncWriter(Call call, ClientContext* context, R* response, bool start, - void* tag) + ClientAsyncWriter(::grpc::internal::Call call, ClientContext* context, + R* response, bool start, void* tag) : context_(context), call_(call), started_(start) { finish_ops_.RecvMessage(response); finish_ops_.AllowNoMessage(); @@ -401,13 +429,17 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> { } ClientContext* context_; - Call call_; + ::grpc::internal::Call call_; bool started_; - CallOpSet<CallOpRecvInitialMetadata> meta_ops_; - CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpClientSendClose> + ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata> + meta_ops_; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata, + ::grpc::internal::CallOpSendMessage, + ::grpc::internal::CallOpClientSendClose> write_ops_; - CallOpSet<CallOpRecvInitialMetadata, CallOpGenericRecvMessage, - CallOpClientRecvStatus> + ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata, + ::grpc::internal::CallOpGenericRecvMessage, + ::grpc::internal::CallOpClientRecvStatus> finish_ops_; }; @@ -415,9 +447,10 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> { /// where the client-to-server message stream has messages of type \a W, /// and the server-to-client message stream has messages of type \a R. template <class W, class R> -class ClientAsyncReaderWriterInterface : public ClientAsyncStreamingInterface, - public AsyncWriterInterface<W>, - public AsyncReaderInterface<R> { +class ClientAsyncReaderWriterInterface + : public internal::ClientAsyncStreamingInterface, + public internal::AsyncWriterInterface<W>, + public internal::AsyncReaderInterface<R> { public: /// Signal the client is done with the writes (half-close the client stream). /// Thread-safe with respect to \a AsyncReaderInterface::Read @@ -426,13 +459,9 @@ class ClientAsyncReaderWriterInterface : public ClientAsyncStreamingInterface, virtual void WritesDone(void* tag) = 0; }; -/// Async client-side interface for bi-directional streaming, -/// where the outgoing message stream going to the server -/// has messages of type \a W, and the incoming message stream coming -/// from the server has messages of type \a R. +namespace internal { template <class W, class R> -class ClientAsyncReaderWriter final - : public ClientAsyncReaderWriterInterface<W, R> { +class ClientAsyncReaderWriterFactory { public: /// Create a stream object. /// Start the RPC request if \a start is set. @@ -441,18 +470,27 @@ class ClientAsyncReaderWriter final /// nullptr and the actual call must be initiated by StartCall /// Note that \a context will be used to fill in custom initial metadata /// used to send to the server when starting the call. - static ClientAsyncReaderWriter* Create(ChannelInterface* channel, - CompletionQueue* cq, - const RpcMethod& method, - ClientContext* context, bool start, - void* tag) { - Call call = channel->CreateCall(method, context, cq); + static ClientAsyncReaderWriter<W, R>* Create( + ChannelInterface* channel, CompletionQueue* cq, + const ::grpc::internal::RpcMethod& method, ClientContext* context, + bool start, void* tag) { + ::grpc::internal::Call call = channel->CreateCall(method, context, cq); return new (g_core_codegen_interface->grpc_call_arena_alloc( - call.call(), sizeof(ClientAsyncReaderWriter))) - ClientAsyncReaderWriter(call, context, start, tag); + call.call(), sizeof(ClientAsyncReaderWriter<W, R>))) + ClientAsyncReaderWriter<W, R>(call, context, start, tag); } +}; +} // namespace internal +/// Async client-side interface for bi-directional streaming, +/// where the outgoing message stream going to the server +/// has messages of type \a W, and the incoming message stream coming +/// from the server has messages of type \a R. +template <class W, class R> +class ClientAsyncReaderWriter final + : public ClientAsyncReaderWriterInterface<W, R> { + public: // always allocated against a call arena, no memory free required static void operator delete(void* ptr, std::size_t size) { assert(size == sizeof(ClientAsyncReaderWriter)); @@ -532,8 +570,9 @@ class ClientAsyncReaderWriter final } private: - ClientAsyncReaderWriter(Call call, ClientContext* context, bool start, - void* tag) + friend class internal::ClientAsyncReaderWriterFactory<W, R>; + ClientAsyncReaderWriter(::grpc::internal::Call call, ClientContext* context, + bool start, void* tag) : context_(context), call_(call), started_(start) { if (start) { StartCallInternal(tag); @@ -554,18 +593,26 @@ class ClientAsyncReaderWriter final } ClientContext* context_; - Call call_; + ::grpc::internal::Call call_; bool started_; - CallOpSet<CallOpRecvInitialMetadata> meta_ops_; - CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> read_ops_; - CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpClientSendClose> + ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata> + meta_ops_; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata, + ::grpc::internal::CallOpRecvMessage<R>> + read_ops_; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata, + ::grpc::internal::CallOpSendMessage, + ::grpc::internal::CallOpClientSendClose> write_ops_; - CallOpSet<CallOpRecvInitialMetadata, CallOpClientRecvStatus> finish_ops_; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata, + ::grpc::internal::CallOpClientRecvStatus> + finish_ops_; }; template <class W, class R> -class ServerAsyncReaderInterface : public ServerAsyncStreamingInterface, - public AsyncReaderInterface<R> { +class ServerAsyncReaderInterface + : public internal::ServerAsyncStreamingInterface, + public internal::AsyncReaderInterface<R> { public: /// Indicate that the stream is to be finished with a certain status code /// and also send out \a msg response to the client. @@ -692,20 +739,23 @@ class ServerAsyncReader final : public ServerAsyncReaderInterface<W, R> { } private: - void BindCall(Call* call) override { call_ = *call; } + void BindCall(::grpc::internal::Call* call) override { call_ = *call; } - Call call_; + ::grpc::internal::Call call_; ServerContext* ctx_; - CallOpSet<CallOpSendInitialMetadata> meta_ops_; - CallOpSet<CallOpRecvMessage<R>> read_ops_; - CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, - CallOpServerSendStatus> + ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata> + meta_ops_; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvMessage<R>> read_ops_; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata, + ::grpc::internal::CallOpSendMessage, + ::grpc::internal::CallOpServerSendStatus> finish_ops_; }; template <class W> -class ServerAsyncWriterInterface : public ServerAsyncStreamingInterface, - public AsyncWriterInterface<W> { +class ServerAsyncWriterInterface + : public internal::ServerAsyncStreamingInterface, + public internal::AsyncWriterInterface<W> { public: /// Indicate that the stream is to be finished with a certain status code. /// Request notification for when the server has sent the appropriate @@ -823,7 +873,7 @@ class ServerAsyncWriter final : public ServerAsyncWriterInterface<W> { } private: - void BindCall(Call* call) override { call_ = *call; } + void BindCall(::grpc::internal::Call* call) override { call_ = *call; } template <class T> void EnsureInitialMetadataSent(T* ops) { @@ -837,20 +887,25 @@ class ServerAsyncWriter final : public ServerAsyncWriterInterface<W> { } } - Call call_; + ::grpc::internal::Call call_; ServerContext* ctx_; - CallOpSet<CallOpSendInitialMetadata> meta_ops_; - CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, - CallOpServerSendStatus> + ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata> + meta_ops_; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata, + ::grpc::internal::CallOpSendMessage, + ::grpc::internal::CallOpServerSendStatus> write_ops_; - CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> finish_ops_; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata, + ::grpc::internal::CallOpServerSendStatus> + finish_ops_; }; /// Server-side interface for asynchronous bi-directional streaming. template <class W, class R> -class ServerAsyncReaderWriterInterface : public ServerAsyncStreamingInterface, - public AsyncWriterInterface<W>, - public AsyncReaderInterface<R> { +class ServerAsyncReaderWriterInterface + : public internal::ServerAsyncStreamingInterface, + public internal::AsyncWriterInterface<W>, + public internal::AsyncReaderInterface<R> { public: /// Indicate that the stream is to be finished with a certain status code. /// Request notification for when the server has sent the appropriate @@ -980,7 +1035,7 @@ class ServerAsyncReaderWriter final private: friend class ::grpc::Server; - void BindCall(Call* call) override { call_ = *call; } + void BindCall(::grpc::internal::Call* call) override { call_ = *call; } template <class T> void EnsureInitialMetadataSent(T* ops) { @@ -994,14 +1049,18 @@ class ServerAsyncReaderWriter final } } - Call call_; + ::grpc::internal::Call call_; ServerContext* ctx_; - CallOpSet<CallOpSendInitialMetadata> meta_ops_; - CallOpSet<CallOpRecvMessage<R>> read_ops_; - CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, - CallOpServerSendStatus> + ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata> + meta_ops_; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvMessage<R>> read_ops_; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata, + ::grpc::internal::CallOpSendMessage, + ::grpc::internal::CallOpServerSendStatus> write_ops_; - CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> finish_ops_; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata, + ::grpc::internal::CallOpServerSendStatus> + finish_ops_; }; } // namespace grpc diff --git a/include/grpc++/impl/codegen/async_unary_call.h b/include/grpc++/impl/codegen/async_unary_call.h index e472f04f56..6d51c78d5c 100644 --- a/include/grpc++/impl/codegen/async_unary_call.h +++ b/include/grpc++/impl/codegen/async_unary_call.h @@ -69,11 +69,9 @@ class ClientAsyncResponseReaderInterface { virtual void Finish(R* msg, Status* status, void* tag) = 0; }; -/// Async API for client-side unary RPCs, where the message response -/// received from the server is of type \a R. +namespace internal { template <class R> -class ClientAsyncResponseReader final - : public ClientAsyncResponseReaderInterface<R> { +class ClientAsyncResponseReaderFactory { public: /// Start a call and write the request out if \a start is set. /// \a tag will be notified on \a cq when the call has been started (i.e. @@ -82,17 +80,24 @@ class ClientAsyncResponseReader final /// Note that \a context will be used to fill in custom initial metadata /// used to send to the server when starting the call. template <class W> - static ClientAsyncResponseReader* Create(ChannelInterface* channel, - CompletionQueue* cq, - const RpcMethod& method, - ClientContext* context, - const W& request, bool start) { - Call call = channel->CreateCall(method, context, cq); + static ClientAsyncResponseReader<R>* Create( + ChannelInterface* channel, CompletionQueue* cq, + const ::grpc::internal::RpcMethod& method, ClientContext* context, + const W& request, bool start) { + ::grpc::internal::Call call = channel->CreateCall(method, context, cq); return new (g_core_codegen_interface->grpc_call_arena_alloc( - call.call(), sizeof(ClientAsyncResponseReader))) - ClientAsyncResponseReader(call, context, request, start); + call.call(), sizeof(ClientAsyncResponseReader<R>))) + ClientAsyncResponseReader<R>(call, context, request, start); } +}; +} // namespace internal +/// Async API for client-side unary RPCs, where the message response +/// received from the server is of type \a R. +template <class R> +class ClientAsyncResponseReader final + : public ClientAsyncResponseReaderInterface<R> { + public: // always allocated against a call arena, no memory free required static void operator delete(void* ptr, std::size_t size) { assert(size == sizeof(ClientAsyncResponseReader)); @@ -137,13 +142,14 @@ class ClientAsyncResponseReader final } private: + friend class internal::ClientAsyncResponseReaderFactory<R>; ClientContext* const context_; - Call call_; + ::grpc::internal::Call call_; bool started_; template <class W> - ClientAsyncResponseReader(Call call, ClientContext* context, const W& request, - bool start) + ClientAsyncResponseReader(::grpc::internal::Call call, ClientContext* context, + const W& request, bool start) : context_(context), call_(call), started_(start) { // Bind the metadata at time of StartCallInternal but set up the rest here // TODO(ctiller): don't assert @@ -162,19 +168,23 @@ class ClientAsyncResponseReader final static void* operator new(std::size_t size); static void* operator new(std::size_t size, void* p) { return p; } - SneakyCallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, - CallOpClientSendClose> + ::grpc::internal::SneakyCallOpSet<::grpc::internal::CallOpSendInitialMetadata, + ::grpc::internal::CallOpSendMessage, + ::grpc::internal::CallOpClientSendClose> init_buf; - CallOpSet<CallOpRecvInitialMetadata> meta_buf; - CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>, - CallOpClientRecvStatus> + ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata> + meta_buf; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata, + ::grpc::internal::CallOpRecvMessage<R>, + ::grpc::internal::CallOpClientRecvStatus> finish_buf; }; /// Async server-side API for handling unary calls, where the single /// response message sent to the client is of type \a W. template <class W> -class ServerAsyncResponseWriter final : public ServerAsyncStreamingInterface { +class ServerAsyncResponseWriter final + : public internal::ServerAsyncStreamingInterface { public: explicit ServerAsyncResponseWriter(ServerContext* ctx) : call_(nullptr, nullptr, nullptr), ctx_(ctx) {} @@ -262,13 +272,15 @@ class ServerAsyncResponseWriter final : public ServerAsyncStreamingInterface { } private: - void BindCall(Call* call) override { call_ = *call; } + void BindCall(::grpc::internal::Call* call) override { call_ = *call; } - Call call_; + ::grpc::internal::Call call_; ServerContext* ctx_; - CallOpSet<CallOpSendInitialMetadata> meta_buf_; - CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, - CallOpServerSendStatus> + ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata> + meta_buf_; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata, + ::grpc::internal::CallOpSendMessage, + ::grpc::internal::CallOpServerSendStatus> finish_buf_; }; diff --git a/include/grpc++/impl/codegen/byte_buffer.h b/include/grpc++/impl/codegen/byte_buffer.h index 57d731be18..fe73ce7a83 100644 --- a/include/grpc++/impl/codegen/byte_buffer.h +++ b/include/grpc++/impl/codegen/byte_buffer.h @@ -31,18 +31,19 @@ namespace grpc { +namespace internal { +class CallOpSendMessage; template <class R> class CallOpRecvMessage; +class CallOpGenericRecvMessage; class MethodHandler; template <class ServiceType, class RequestType, class ResponseType> class RpcMethodHandler; template <class ServiceType, class RequestType, class ResponseType> class ServerStreamingHandler; -namespace CallOpGenericRecvMessageHelper { template <class R> class DeserializeFuncType; -} // namespace CallOpGenericRecvMessageHelper - +} // namespace internal /// A sequence of bytes. class ByteBuffer final { public: @@ -97,17 +98,17 @@ class ByteBuffer final { private: friend class SerializationTraits<ByteBuffer, void>; - friend class CallOpSendMessage; + friend class internal::CallOpSendMessage; template <class R> - friend class CallOpRecvMessage; - friend class CallOpGenericRecvMessage; - friend class MethodHandler; + friend class internal::CallOpRecvMessage; + friend class internal::CallOpGenericRecvMessage; + friend class internal::MethodHandler; template <class ServiceType, class RequestType, class ResponseType> - friend class RpcMethodHandler; + friend class internal::RpcMethodHandler; template <class ServiceType, class RequestType, class ResponseType> - friend class ServerStreamingHandler; + friend class internal::ServerStreamingHandler; template <class R> - friend class CallOpGenericRecvMessageHelper::DeserializeFuncType; + friend class internal::DeserializeFuncType; grpc_byte_buffer* buffer_; diff --git a/include/grpc++/impl/codegen/call.h b/include/grpc++/impl/codegen/call.h index 0e7ad0b60a..63caf90d39 100644 --- a/include/grpc++/impl/codegen/call.h +++ b/include/grpc++/impl/codegen/call.h @@ -43,11 +43,13 @@ namespace grpc { class ByteBuffer; -class Call; -class CallHook; class CompletionQueue; extern CoreCodegenInterface* g_core_codegen_interface; +namespace internal { +class Call; +class CallHook; + const char kBinaryErrorDetailsKey[] = "grpc-status-details-bin"; // TODO(yangg) if the map is changed before we send, the pointers will be a @@ -75,6 +77,7 @@ inline grpc_metadata* FillMetadataArray( } return metadata_array; } +} // namespace internal /// Per-message write options. class WriteOptions { @@ -163,7 +166,7 @@ class WriteOptions { /// Clears flag indicating that this is the last message in a stream, /// disabling coalescing. - inline WriteOptions& clear_last_messsage() { + inline WriteOptions& clear_last_message() { last_message_ = false; return *this; } @@ -199,6 +202,7 @@ class WriteOptions { bool last_message_; }; +namespace internal { /// Default argument for CallOpSet. I is unused by the class, but can be /// used for generating multiple names for the same thing. template <int I> @@ -301,7 +305,11 @@ template <class M> Status CallOpSendMessage::SendMessage(const M& message, WriteOptions options) { write_options_ = options; bool own_buf; - Status result = SerializationTraits<M>::Serialize( + // TODO(vjpai): Remove the void below when possible + // The void in the template parameter below should not be needed + // (since it should be implicit) but is needed due to an observed + // difference in behavior between clang and gcc for certain internal users + Status result = SerializationTraits<M, void>::Serialize( message, send_buf_.bbuf_ptr(), &own_buf); if (!own_buf) { send_buf_.Duplicate(); @@ -366,7 +374,6 @@ class CallOpRecvMessage { bool allow_not_getting_message_; }; -namespace CallOpGenericRecvMessageHelper { class DeserializeFunc { public: virtual Status Deserialize(ByteBuffer* buf) = 0; @@ -386,7 +393,6 @@ class DeserializeFuncType final : public DeserializeFunc { private: R* message_; // Not a managed pointer because management is external to this }; -} // namespace CallOpGenericRecvMessageHelper class CallOpGenericRecvMessage { public: @@ -397,8 +403,7 @@ class CallOpGenericRecvMessage { void RecvMessage(R* message) { // Use an explicit base class pointer to avoid resolution error in the // following unique_ptr::reset for some old implementations. - CallOpGenericRecvMessageHelper::DeserializeFunc* func = - new CallOpGenericRecvMessageHelper::DeserializeFuncType<R>(message); + DeserializeFunc* func = new DeserializeFuncType<R>(message); deserialize_.reset(func); } @@ -438,7 +443,7 @@ class CallOpGenericRecvMessage { } private: - std::unique_ptr<CallOpGenericRecvMessageHelper::DeserializeFunc> deserialize_; + std::unique_ptr<DeserializeFunc> deserialize_; ByteBuffer recv_buf_; bool allow_not_getting_message_; }; @@ -693,7 +698,7 @@ class Call final { grpc_call* call_; int max_receive_message_size_; }; - +} // namespace internal } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_CALL_H diff --git a/include/grpc++/impl/codegen/call_hook.h b/include/grpc++/impl/codegen/call_hook.h index d026cc8b58..44e9de220e 100644 --- a/include/grpc++/impl/codegen/call_hook.h +++ b/include/grpc++/impl/codegen/call_hook.h @@ -21,6 +21,7 @@ namespace grpc { +namespace internal { class CallOpSetInterface; class Call; @@ -31,6 +32,7 @@ class CallHook { virtual ~CallHook() {} virtual void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) = 0; }; +} // namespace internal } // namespace grpc diff --git a/include/grpc++/impl/codegen/channel_interface.h b/include/grpc++/impl/codegen/channel_interface.h index 1b7590bf0c..769f853974 100644 --- a/include/grpc++/impl/codegen/channel_interface.h +++ b/include/grpc++/impl/codegen/channel_interface.h @@ -24,10 +24,8 @@ #include <grpc/impl/codegen/connectivity_state.h> namespace grpc { -class Call; +class ChannelInterface; class ClientContext; -class RpcMethod; -class CallOpSetInterface; class CompletionQueue; template <class R> @@ -36,14 +34,22 @@ template <class W> class ClientWriter; template <class W, class R> class ClientReaderWriter; + +namespace internal { +class Call; +class CallOpSetInterface; +class RpcMethod; +template <class InputMessage, class OutputMessage> +class BlockingUnaryCallImpl; template <class R> -class ClientAsyncReader; +class ClientAsyncReaderFactory; template <class W> -class ClientAsyncWriter; +class ClientAsyncWriterFactory; template <class W, class R> -class ClientAsyncReaderWriter; +class ClientAsyncReaderWriterFactory; template <class R> -class ClientAsyncResponseReader; +class ClientAsyncResponseReaderFactory; +} // namespace internal /// Codegen interface for \a grpc::Channel. class ChannelInterface { @@ -88,23 +94,21 @@ class ChannelInterface { template <class W, class R> friend class ::grpc::ClientReaderWriter; template <class R> - friend class ::grpc::ClientAsyncReader; + friend class ::grpc::internal::ClientAsyncReaderFactory; template <class W> - friend class ::grpc::ClientAsyncWriter; + friend class ::grpc::internal::ClientAsyncWriterFactory; template <class W, class R> - friend class ::grpc::ClientAsyncReaderWriter; + friend class ::grpc::internal::ClientAsyncReaderWriterFactory; template <class R> - friend class ::grpc::ClientAsyncResponseReader; + friend class ::grpc::internal::ClientAsyncResponseReaderFactory; template <class InputMessage, class OutputMessage> - friend Status BlockingUnaryCall(ChannelInterface* channel, - const RpcMethod& method, - ClientContext* context, - const InputMessage& request, - OutputMessage* result); - friend class ::grpc::RpcMethod; - virtual Call CreateCall(const RpcMethod& method, ClientContext* context, - CompletionQueue* cq) = 0; - virtual void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) = 0; + friend class ::grpc::internal::BlockingUnaryCallImpl; + friend class ::grpc::internal::RpcMethod; + virtual internal::Call CreateCall(const internal::RpcMethod& method, + ClientContext* context, + CompletionQueue* cq) = 0; + virtual void PerformOpsOnCall(internal::CallOpSetInterface* ops, + internal::Call* call) = 0; virtual void* RegisterMethod(const char* method) = 0; virtual void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline, @@ -112,7 +116,6 @@ class ChannelInterface { virtual bool WaitForStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline) = 0; }; - } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_CHANNEL_INTERFACE_H diff --git a/include/grpc++/impl/codegen/client_context.h b/include/grpc++/impl/codegen/client_context.h index 6d7e13bbf2..22b581cbc5 100644 --- a/include/grpc++/impl/codegen/client_context.h +++ b/include/grpc++/impl/codegen/client_context.h @@ -60,7 +60,16 @@ class Channel; class ChannelInterface; class CompletionQueue; class CallCredentials; +class ClientContext; + +namespace internal { class RpcMethod; +class CallOpClientRecvStatus; +class CallOpRecvInitialMetadata; +template <class InputMessage, class OutputMessage> +class BlockingUnaryCallImpl; +} // namespace internal + template <class R> class ClientReader; template <class W> @@ -345,8 +354,8 @@ class ClientContext { ClientContext& operator=(const ClientContext&); friend class ::grpc::testing::InteropClientContextInspector; - friend class CallOpClientRecvStatus; - friend class CallOpRecvInitialMetadata; + friend class ::grpc::internal::CallOpClientRecvStatus; + friend class ::grpc::internal::CallOpRecvInitialMetadata; friend class Channel; template <class R> friend class ::grpc::ClientReader; @@ -363,11 +372,7 @@ class ClientContext { template <class R> friend class ::grpc::ClientAsyncResponseReader; template <class InputMessage, class OutputMessage> - friend Status BlockingUnaryCall(ChannelInterface* channel, - const RpcMethod& method, - ClientContext* context, - const InputMessage& request, - OutputMessage* result); + friend class ::grpc::internal::BlockingUnaryCallImpl; grpc_call* call() const { return call_; } void set_call(grpc_call* call, const std::shared_ptr<Channel>& channel); @@ -399,8 +404,8 @@ class ClientContext { mutable std::shared_ptr<const AuthContext> auth_context_; struct census_context* census_context_; std::multimap<grpc::string, grpc::string> send_initial_metadata_; - MetadataMap recv_initial_metadata_; - MetadataMap trailing_metadata_; + internal::MetadataMap recv_initial_metadata_; + internal::MetadataMap trailing_metadata_; grpc_call* propagate_from_call_; PropagationOptions propagation_options_; diff --git a/include/grpc++/impl/codegen/client_unary_call.h b/include/grpc++/impl/codegen/client_unary_call.h index 7c540fade9..170c562cf3 100644 --- a/include/grpc++/impl/codegen/client_unary_call.h +++ b/include/grpc++/impl/codegen/client_unary_call.h @@ -30,43 +30,60 @@ namespace grpc { class Channel; class ClientContext; class CompletionQueue; -class RpcMethod; +namespace internal { +class RpcMethod; /// Wrapper that performs a blocking unary call template <class InputMessage, class OutputMessage> Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method, ClientContext* context, const InputMessage& request, OutputMessage* result) { - CompletionQueue cq(grpc_completion_queue_attributes{ - GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, - GRPC_CQ_DEFAULT_POLLING}); // Pluckable completion queue - Call call(channel->CreateCall(method, context, &cq)); - CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, - CallOpRecvInitialMetadata, CallOpRecvMessage<OutputMessage>, - CallOpClientSendClose, CallOpClientRecvStatus> - ops; - Status status = ops.SendMessage(request); - if (!status.ok()) { - return status; - } - ops.SendInitialMetadata(context->send_initial_metadata_, - context->initial_metadata_flags()); - ops.RecvInitialMetadata(context); - ops.RecvMessage(result); - ops.ClientSendClose(); - ops.ClientRecvStatus(context, &status); - call.PerformOps(&ops); - if (cq.Pluck(&ops)) { - if (!ops.got_message && status.ok()) { - return Status(StatusCode::UNIMPLEMENTED, - "No message returned for unary request"); + return BlockingUnaryCallImpl<InputMessage, OutputMessage>( + channel, method, context, request, result) + .status(); +}; + +template <class InputMessage, class OutputMessage> +class BlockingUnaryCallImpl { + public: + BlockingUnaryCallImpl(ChannelInterface* channel, const RpcMethod& method, + ClientContext* context, const InputMessage& request, + OutputMessage* result) { + CompletionQueue cq(grpc_completion_queue_attributes{ + GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, + GRPC_CQ_DEFAULT_POLLING}); // Pluckable completion queue + Call call(channel->CreateCall(method, context, &cq)); + CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, + CallOpRecvInitialMetadata, CallOpRecvMessage<OutputMessage>, + CallOpClientSendClose, CallOpClientRecvStatus> + ops; + status_ = ops.SendMessage(request); + if (!status_.ok()) { + return; + } + ops.SendInitialMetadata(context->send_initial_metadata_, + context->initial_metadata_flags()); + ops.RecvInitialMetadata(context); + ops.RecvMessage(result); + ops.ClientSendClose(); + ops.ClientRecvStatus(context, &status_); + call.PerformOps(&ops); + if (cq.Pluck(&ops)) { + if (!ops.got_message && status_.ok()) { + status_ = Status(StatusCode::UNIMPLEMENTED, + "No message returned for unary request"); + } + } else { + GPR_CODEGEN_ASSERT(!status_.ok()); } - } else { - GPR_CODEGEN_ASSERT(!status.ok()); } - return status; -} + Status status() { return status_; } + + private: + Status status_; +}; +} // namespace internal } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_CLIENT_UNARY_CALL_H diff --git a/include/grpc++/impl/codegen/completion_queue.h b/include/grpc++/impl/codegen/completion_queue.h index ca757e2a9c..14de30a62e 100644 --- a/include/grpc++/impl/codegen/completion_queue.h +++ b/include/grpc++/impl/codegen/completion_queue.h @@ -56,7 +56,19 @@ class ServerWriter; namespace internal { template <class W, class R> class ServerReaderWriterBody; -} +} // namespace internal + +class Channel; +class ChannelInterface; +class ClientContext; +class CompletionQueue; +class Server; +class ServerBuilder; +class ServerContext; + +namespace internal { +class CompletionQueueTag; +class RpcMethod; template <class ServiceType, class RequestType, class ResponseType> class RpcMethodHandler; template <class ServiceType, class RequestType, class ResponseType> @@ -66,16 +78,11 @@ class ServerStreamingHandler; template <class ServiceType, class RequestType, class ResponseType> class BidiStreamingHandler; class UnknownMethodHandler; - -class Channel; -class ChannelInterface; -class ClientContext; -class CompletionQueueTag; -class CompletionQueue; -class RpcMethod; -class Server; -class ServerBuilder; -class ServerContext; +template <class Streamer, bool WriteNeeded> +class TemplatedBidiStreamingHandler; +template <class InputMessage, class OutputMessage> +class BlockingUnaryCallImpl; +} // namespace internal extern CoreCodegenInterface* g_core_codegen_interface; @@ -109,6 +116,30 @@ class CompletionQueue : private GrpcLibraryCodegen { TIMEOUT ///< deadline was reached. }; + /// EXPERIMENTAL + /// First executes \a F, then reads from the queue, blocking up to + /// \a deadline (or the queue's shutdown). + /// Both \a tag and \a ok are updated upon success (if an event is available + /// within the \a deadline). A \a tag points to an arbitrary location usually + /// employed to uniquely identify an event. + /// + /// \param F[in] Function to execute before calling AsyncNext on this queue. + /// \param tag[out] Upon sucess, updated to point to the event's tag. + /// \param ok[out] Upon sucess, true if read a regular event, false otherwise. + /// \param deadline[in] How long to block in wait for an event. + /// + /// \return The type of event read. + template <typename T, typename F> + NextStatus DoThenAsyncNext(F&& f, void** tag, bool* ok, const T& deadline) { + CompletionQueueTLSCache cache = CompletionQueueTLSCache(this); + f(); + if (cache.Flush(tag, ok)) { + return GOT_EVENT; + } else { + return AsyncNext(tag, ok, deadline); + } + } + /// Read from the queue, blocking up to \a deadline (or the queue's shutdown). /// Both \a tag and \a ok are updated upon success (if an event is available /// within the \a deadline). A \a tag points to an arbitrary location usually @@ -196,28 +227,39 @@ class CompletionQueue : private GrpcLibraryCodegen { template <class W, class R> friend class ::grpc::internal::ServerReaderWriterBody; template <class ServiceType, class RequestType, class ResponseType> - friend class RpcMethodHandler; + friend class ::grpc::internal::RpcMethodHandler; template <class ServiceType, class RequestType, class ResponseType> - friend class ClientStreamingHandler; + friend class ::grpc::internal::ClientStreamingHandler; template <class ServiceType, class RequestType, class ResponseType> - friend class ServerStreamingHandler; + friend class ::grpc::internal::ServerStreamingHandler; template <class Streamer, bool WriteNeeded> - friend class TemplatedBidiStreamingHandler; - friend class UnknownMethodHandler; + friend class ::grpc::internal::TemplatedBidiStreamingHandler; + friend class ::grpc::internal::UnknownMethodHandler; friend class ::grpc::Server; friend class ::grpc::ServerContext; template <class InputMessage, class OutputMessage> - friend Status BlockingUnaryCall(ChannelInterface* channel, - const RpcMethod& method, - ClientContext* context, - const InputMessage& request, - OutputMessage* result); + friend class ::grpc::internal::BlockingUnaryCallImpl; + + /// EXPERIMENTAL + /// Creates a Thread Local cache to store the first event + /// On this completion queue queued from this thread. Once + /// initialized, it must be flushed on the same thread. + class CompletionQueueTLSCache { + public: + CompletionQueueTLSCache(CompletionQueue* cq); + ~CompletionQueueTLSCache(); + bool Flush(void** tag, bool* ok); + + private: + CompletionQueue* cq_; + bool flushed_; + }; NextStatus AsyncNextInternal(void** tag, bool* ok, gpr_timespec deadline); /// Wraps \a grpc_completion_queue_pluck. /// \warning Must not be mixed with calls to \a Next. - bool Pluck(CompletionQueueTag* tag) { + bool Pluck(internal::CompletionQueueTag* tag) { auto deadline = g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME); auto ev = g_core_codegen_interface->grpc_completion_queue_pluck( @@ -238,7 +280,7 @@ class CompletionQueue : private GrpcLibraryCodegen { /// implementation to simple call the other TryPluck function with a zero /// timeout. i.e: /// TryPluck(tag, gpr_time_0(GPR_CLOCK_REALTIME)) - void TryPluck(CompletionQueueTag* tag) { + void TryPluck(internal::CompletionQueueTag* tag) { auto deadline = g_core_codegen_interface->gpr_time_0(GPR_CLOCK_REALTIME); auto ev = g_core_codegen_interface->grpc_completion_queue_pluck( cq_, tag, deadline, nullptr); @@ -254,7 +296,7 @@ class CompletionQueue : private GrpcLibraryCodegen { /// /// This exects tag->FinalizeResult (if called) to return 'false' i.e expects /// that the tag is internal not something that is returned to the user. - void TryPluck(CompletionQueueTag* tag, gpr_timespec deadline) { + void TryPluck(internal::CompletionQueueTag* tag, gpr_timespec deadline) { auto ev = g_core_codegen_interface->grpc_completion_queue_pluck( cq_, tag, deadline, nullptr); if (ev.type == GRPC_QUEUE_TIMEOUT || ev.type == GRPC_QUEUE_SHUTDOWN) { diff --git a/include/grpc++/impl/codegen/completion_queue_tag.h b/include/grpc++/impl/codegen/completion_queue_tag.h index 4d7d3a98dd..cb16bcf9ff 100644 --- a/include/grpc++/impl/codegen/completion_queue_tag.h +++ b/include/grpc++/impl/codegen/completion_queue_tag.h @@ -21,6 +21,7 @@ namespace grpc { +namespace internal { /// An interface allowing implementors to process and filter event tags. class CompletionQueueTag { public: @@ -31,6 +32,7 @@ class CompletionQueueTag { /// queue virtual bool FinalizeResult(void** tag, bool* status) = 0; }; +} // namespace internal } // namespace grpc diff --git a/include/grpc++/impl/codegen/metadata_map.h b/include/grpc++/impl/codegen/metadata_map.h index b73985967d..fd4750efdd 100644 --- a/include/grpc++/impl/codegen/metadata_map.h +++ b/include/grpc++/impl/codegen/metadata_map.h @@ -23,6 +23,7 @@ namespace grpc { +namespace internal { class MetadataMap { public: MetadataMap() { memset(&arr_, 0, sizeof(arr_)); } @@ -50,6 +51,7 @@ class MetadataMap { grpc_metadata_array arr_; std::multimap<grpc::string_ref, grpc::string_ref> map_; }; +} // namespace internal } // namespace grpc diff --git a/include/grpc++/impl/codegen/method_handler_impl.h b/include/grpc++/impl/codegen/method_handler_impl.h index e14cb0e926..c0af4ca130 100644 --- a/include/grpc++/impl/codegen/method_handler_impl.h +++ b/include/grpc++/impl/codegen/method_handler_impl.h @@ -26,6 +26,7 @@ namespace grpc { +namespace internal { /// A wrapper class of an application provided rpc method handler. template <class ServiceType, class RequestType, class ResponseType> class RpcMethodHandler : public MethodHandler { @@ -266,6 +267,7 @@ class UnknownMethodHandler : public MethodHandler { } }; +} // namespace internal } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H diff --git a/include/grpc++/impl/codegen/rpc_method.h b/include/grpc++/impl/codegen/rpc_method.h index ac13ac56c7..54e52364ef 100644 --- a/include/grpc++/impl/codegen/rpc_method.h +++ b/include/grpc++/impl/codegen/rpc_method.h @@ -24,7 +24,7 @@ #include <grpc++/impl/codegen/channel_interface.h> namespace grpc { - +namespace internal { /// Descriptor of an RPC method class RpcMethod { public: @@ -55,6 +55,7 @@ class RpcMethod { void* const channel_tag_; }; +} // namespace internal } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_RPC_METHOD_H diff --git a/include/grpc++/impl/codegen/rpc_service_method.h b/include/grpc++/impl/codegen/rpc_service_method.h index d356012ad6..5ba11e8559 100644 --- a/include/grpc++/impl/codegen/rpc_service_method.h +++ b/include/grpc++/impl/codegen/rpc_service_method.h @@ -32,8 +32,8 @@ namespace grpc { class ServerContext; -class StreamContextInterface; +namespace internal { /// Base class for running an RPC handler. class MethodHandler { public: @@ -71,6 +71,7 @@ class RpcServiceMethod : public RpcMethod { void* server_tag_; std::unique_ptr<MethodHandler> handler_; }; +} // namespace internal } // namespace grpc diff --git a/include/grpc++/impl/codegen/server_context.h b/include/grpc++/impl/codegen/server_context.h index b5e37fd12b..a2d6967bf8 100644 --- a/include/grpc++/impl/codegen/server_context.h +++ b/include/grpc++/impl/codegen/server_context.h @@ -55,7 +55,6 @@ class ServerWriter; namespace internal { template <class W, class R> class ServerReaderWriterBody; -} template <class ServiceType, class RequestType, class ResponseType> class RpcMethodHandler; template <class ServiceType, class RequestType, class ResponseType> @@ -65,9 +64,11 @@ class ServerStreamingHandler; template <class ServiceType, class RequestType, class ResponseType> class BidiStreamingHandler; class UnknownMethodHandler; - +template <class Streamer, bool WriteNeeded> +class TemplatedBidiStreamingHandler; class Call; -class CallOpBuffer; +} // namespace internal + class CompletionQueue; class Server; class ServerInterface; @@ -247,14 +248,14 @@ class ServerContext { template <class W, class R> friend class ::grpc::internal::ServerReaderWriterBody; template <class ServiceType, class RequestType, class ResponseType> - friend class RpcMethodHandler; + friend class ::grpc::internal::RpcMethodHandler; template <class ServiceType, class RequestType, class ResponseType> - friend class ClientStreamingHandler; + friend class ::grpc::internal::ClientStreamingHandler; template <class ServiceType, class RequestType, class ResponseType> - friend class ServerStreamingHandler; + friend class ::grpc::internal::ServerStreamingHandler; template <class Streamer, bool WriteNeeded> - friend class TemplatedBidiStreamingHandler; - friend class UnknownMethodHandler; + friend class ::grpc::internal::TemplatedBidiStreamingHandler; + friend class ::grpc::internal::UnknownMethodHandler; friend class ::grpc::ClientContext; /// Prevent copying. @@ -263,9 +264,9 @@ class ServerContext { class CompletionOp; - void BeginCompletionOp(Call* call); + void BeginCompletionOp(internal::Call* call); /// Return the tag queued by BeginCompletionOp() - CompletionQueueTag* GetCompletionOpTag(); + internal::CompletionQueueTag* GetCompletionOpTag(); ServerContext(gpr_timespec deadline, grpc_metadata_array* arr); @@ -282,7 +283,7 @@ class ServerContext { CompletionQueue* cq_; bool sent_initial_metadata_; mutable std::shared_ptr<const AuthContext> auth_context_; - MetadataMap client_metadata_; + internal::MetadataMap client_metadata_; std::multimap<grpc::string, grpc::string> initial_metadata_; std::multimap<grpc::string, grpc::string> trailing_metadata_; @@ -290,7 +291,9 @@ class ServerContext { grpc_compression_level compression_level_; grpc_compression_algorithm compression_algorithm_; - CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage> pending_ops_; + internal::CallOpSet<internal::CallOpSendInitialMetadata, + internal::CallOpSendMessage> + pending_ops_; bool has_pending_ops_; }; diff --git a/include/grpc++/impl/codegen/server_interface.h b/include/grpc++/impl/codegen/server_interface.h index 55937f19d7..3bcf4c87e7 100644 --- a/include/grpc++/impl/codegen/server_interface.h +++ b/include/grpc++/impl/codegen/server_interface.h @@ -30,20 +30,21 @@ namespace grpc { class AsyncGenericService; class Channel; class GenericServerContext; -class RpcService; -class ServerAsyncStreamingInterface; class ServerCompletionQueue; class ServerContext; class ServerCredentials; class Service; -class ThreadPoolInterface; extern CoreCodegenInterface* g_core_codegen_interface; /// Models a gRPC server. /// /// Servers are configured and started via \a grpc::ServerBuilder. -class ServerInterface : public CallHook { +namespace internal { +class ServerAsyncStreamingInterface; +} // namespace internal + +class ServerInterface : public internal::CallHook { public: virtual ~ServerInterface() {} @@ -78,7 +79,7 @@ class ServerInterface : public CallHook { virtual void Wait() = 0; protected: - friend class Service; + friend class ::grpc::Service; /// Register a service. This call does not take ownership of the service. /// The service must exist for the lifetime of the Server instance. @@ -116,12 +117,13 @@ class ServerInterface : public CallHook { virtual grpc_server* server() = 0; - virtual void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) = 0; + virtual void PerformOpsOnCall(internal::CallOpSetInterface* ops, + internal::Call* call) = 0; - class BaseAsyncRequest : public CompletionQueueTag { + class BaseAsyncRequest : public internal::CompletionQueueTag { public: BaseAsyncRequest(ServerInterface* server, ServerContext* context, - ServerAsyncStreamingInterface* stream, + internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, void* tag, bool delete_on_finalize); virtual ~BaseAsyncRequest(); @@ -131,7 +133,7 @@ class ServerInterface : public CallHook { protected: ServerInterface* const server_; ServerContext* const context_; - ServerAsyncStreamingInterface* const stream_; + internal::ServerAsyncStreamingInterface* const stream_; CompletionQueue* const call_cq_; void* const tag_; const bool delete_on_finalize_; @@ -141,7 +143,7 @@ class ServerInterface : public CallHook { class RegisteredAsyncRequest : public BaseAsyncRequest { public: RegisteredAsyncRequest(ServerInterface* server, ServerContext* context, - ServerAsyncStreamingInterface* stream, + internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, void* tag); // uses BaseAsyncRequest::FinalizeResult @@ -155,7 +157,7 @@ class ServerInterface : public CallHook { public: NoPayloadAsyncRequest(void* registered_method, ServerInterface* server, ServerContext* context, - ServerAsyncStreamingInterface* stream, + internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, ServerCompletionQueue* notification_cq, void* tag) : RegisteredAsyncRequest(server, context, stream, call_cq, tag) { @@ -170,7 +172,7 @@ class ServerInterface : public CallHook { public: PayloadAsyncRequest(void* registered_method, ServerInterface* server, ServerContext* context, - ServerAsyncStreamingInterface* stream, + internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, ServerCompletionQueue* notification_cq, void* tag, Message* request) @@ -212,7 +214,7 @@ class ServerInterface : public CallHook { void* const registered_method_; ServerInterface* const server_; ServerContext* const context_; - ServerAsyncStreamingInterface* const stream_; + internal::ServerAsyncStreamingInterface* const stream_; CompletionQueue* const call_cq_; ServerCompletionQueue* const notification_cq_; void* const tag_; @@ -223,7 +225,7 @@ class ServerInterface : public CallHook { class GenericAsyncRequest : public BaseAsyncRequest { public: GenericAsyncRequest(ServerInterface* server, GenericServerContext* context, - ServerAsyncStreamingInterface* stream, + internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, ServerCompletionQueue* notification_cq, void* tag, bool delete_on_finalize); @@ -235,8 +237,9 @@ class ServerInterface : public CallHook { }; template <class Message> - void RequestAsyncCall(RpcServiceMethod* method, ServerContext* context, - ServerAsyncStreamingInterface* stream, + void RequestAsyncCall(internal::RpcServiceMethod* method, + ServerContext* context, + internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, ServerCompletionQueue* notification_cq, void* tag, Message* message) { @@ -246,8 +249,9 @@ class ServerInterface : public CallHook { message); } - void RequestAsyncCall(RpcServiceMethod* method, ServerContext* context, - ServerAsyncStreamingInterface* stream, + void RequestAsyncCall(internal::RpcServiceMethod* method, + ServerContext* context, + internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, ServerCompletionQueue* notification_cq, void* tag) { GPR_CODEGEN_ASSERT(method); @@ -256,7 +260,7 @@ class ServerInterface : public CallHook { } void RequestAsyncGenericCall(GenericServerContext* context, - ServerAsyncStreamingInterface* stream, + internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, ServerCompletionQueue* notification_cq, void* tag) { diff --git a/include/grpc++/impl/codegen/service_type.h b/include/grpc++/impl/codegen/service_type.h index 2dc4ea0ea6..71c3d99d5c 100644 --- a/include/grpc++/impl/codegen/service_type.h +++ b/include/grpc++/impl/codegen/service_type.h @@ -28,13 +28,14 @@ namespace grpc { -class Call; class CompletionQueue; class Server; class ServerInterface; class ServerCompletionQueue; class ServerContext; +namespace internal { +class Call; class ServerAsyncStreamingInterface { public: virtual ~ServerAsyncStreamingInterface() {} @@ -48,9 +49,10 @@ class ServerAsyncStreamingInterface { virtual void SendInitialMetadata(void* tag) = 0; private: - friend class ServerInterface; + friend class ::grpc::ServerInterface; virtual void BindCall(Call* call) = 0; }; +} // namespace internal /// Desriptor of an RPC service and its various RPC methods class Service { @@ -88,40 +90,38 @@ class Service { protected: template <class Message> void RequestAsyncUnary(int index, ServerContext* context, Message* request, - ServerAsyncStreamingInterface* stream, + internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, ServerCompletionQueue* notification_cq, void* tag) { server_->RequestAsyncCall(methods_[index].get(), context, stream, call_cq, notification_cq, tag, request); } - void RequestAsyncClientStreaming(int index, ServerContext* context, - ServerAsyncStreamingInterface* stream, - CompletionQueue* call_cq, - ServerCompletionQueue* notification_cq, - void* tag) { + void RequestAsyncClientStreaming( + int index, ServerContext* context, + internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, + ServerCompletionQueue* notification_cq, void* tag) { server_->RequestAsyncCall(methods_[index].get(), context, stream, call_cq, notification_cq, tag); } template <class Message> - void RequestAsyncServerStreaming(int index, ServerContext* context, - Message* request, - ServerAsyncStreamingInterface* stream, - CompletionQueue* call_cq, - ServerCompletionQueue* notification_cq, - void* tag) { + void RequestAsyncServerStreaming( + int index, ServerContext* context, Message* request, + internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, + ServerCompletionQueue* notification_cq, void* tag) { server_->RequestAsyncCall(methods_[index].get(), context, stream, call_cq, notification_cq, tag, request); } - void RequestAsyncBidiStreaming(int index, ServerContext* context, - ServerAsyncStreamingInterface* stream, - CompletionQueue* call_cq, - ServerCompletionQueue* notification_cq, - void* tag) { + void RequestAsyncBidiStreaming( + int index, ServerContext* context, + internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, + ServerCompletionQueue* notification_cq, void* tag) { server_->RequestAsyncCall(methods_[index].get(), context, stream, call_cq, notification_cq, tag); } - void AddMethod(RpcServiceMethod* method) { methods_.emplace_back(method); } + void AddMethod(internal::RpcServiceMethod* method) { + methods_.emplace_back(method); + } void MarkMethodAsync(int index) { GPR_CODEGEN_ASSERT( @@ -139,7 +139,7 @@ class Service { methods_[index].reset(); } - void MarkMethodStreamed(int index, MethodHandler* streamed_method) { + void MarkMethodStreamed(int index, internal::MethodHandler* streamed_method) { GPR_CODEGEN_ASSERT(methods_[index] && methods_[index]->handler() && "Cannot mark an async or generic method Streamed"); methods_[index]->SetHandler(streamed_method); @@ -148,14 +148,14 @@ class Service { // case of BIDI_STREAMING that has 1 read and 1 write, in that order, // and split server-side streaming is BIDI_STREAMING with 1 read and // any number of writes, in that order. - methods_[index]->SetMethodType(::grpc::RpcMethod::BIDI_STREAMING); + methods_[index]->SetMethodType(internal::RpcMethod::BIDI_STREAMING); } private: friend class Server; friend class ServerInterface; ServerInterface* server_; - std::vector<std::unique_ptr<RpcServiceMethod>> methods_; + std::vector<std::unique_ptr<internal::RpcServiceMethod>> methods_; }; } // namespace grpc diff --git a/include/grpc++/impl/codegen/sync_stream.h b/include/grpc++/impl/codegen/sync_stream.h index c1784f1820..a6dd26fb00 100644 --- a/include/grpc++/impl/codegen/sync_stream.h +++ b/include/grpc++/impl/codegen/sync_stream.h @@ -30,6 +30,7 @@ namespace grpc { +namespace internal { /// Common interface for all synchronous client side streaming. class ClientStreamingInterface { public: @@ -141,10 +142,12 @@ class WriterInterface { } }; +} // namespace internal + /// Client-side interface for streaming reads of message of type \a R. template <class R> -class ClientReaderInterface : public ClientStreamingInterface, - public ReaderInterface<R> { +class ClientReaderInterface : public internal::ClientStreamingInterface, + public internal::ReaderInterface<R> { public: /// Block to wait for initial metadata from server. The received metadata /// can only be accessed after this call returns. Should only be called before @@ -153,35 +156,25 @@ class ClientReaderInterface : public ClientStreamingInterface, virtual void WaitForInitialMetadata() = 0; }; +namespace internal { +template <class R> +class ClientReaderFactory { + public: + template <class W> + static ClientReader<R>* Create(ChannelInterface* channel, + const ::grpc::internal::RpcMethod& method, + ClientContext* context, const W& request) { + return new ClientReader<R>(channel, method, context, request); + } +}; +} // namespace internal + /// Synchronous (blocking) client-side API for doing server-streaming RPCs, /// where the stream of messages coming from the server has messages /// of type \a R. template <class R> class ClientReader final : public ClientReaderInterface<R> { public: - /// Block to create a stream and write the initial metadata and \a request - /// out. Note that \a context will be used to fill in custom initial - /// metadata used to send to the server when starting the call. - template <class W> - ClientReader(ChannelInterface* channel, const RpcMethod& method, - ClientContext* context, const W& request) - : context_(context), - cq_(grpc_completion_queue_attributes{ - GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, - GRPC_CQ_DEFAULT_POLLING}), // Pluckable cq - call_(channel->CreateCall(method, context, &cq_)) { - CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, - CallOpClientSendClose> - ops; - ops.SendInitialMetadata(context->send_initial_metadata_, - context->initial_metadata_flags()); - // TODO(ctiller): don't assert - GPR_CODEGEN_ASSERT(ops.SendMessage(request).ok()); - ops.ClientSendClose(); - call_.PerformOps(&ops); - cq_.Pluck(&ops); - } - /// See the \a ClientStreamingInterface.WaitForInitialMetadata method for /// semantics. /// @@ -192,7 +185,8 @@ class ClientReader final : public ClientReaderInterface<R> { void WaitForInitialMetadata() override { GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_); - CallOpSet<CallOpRecvInitialMetadata> ops; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata> + ops; ops.RecvInitialMetadata(context_); call_.PerformOps(&ops); cq_.Pluck(&ops); /// status ignored @@ -209,7 +203,9 @@ class ClientReader final : public ClientReaderInterface<R> { /// already received (if initial metadata is received, it can be then /// accessed through the \a ClientContext associated with this call). bool Read(R* msg) override { - CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> ops; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata, + ::grpc::internal::CallOpRecvMessage<R>> + ops; if (!context_->initial_metadata_received_) { ops.RecvInitialMetadata(context_); } @@ -224,7 +220,7 @@ class ClientReader final : public ClientReaderInterface<R> { /// The \a ClientContext associated with this call is updated with /// possible metadata received from the server. Status Finish() override { - CallOpSet<CallOpClientRecvStatus> ops; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpClientRecvStatus> ops; Status status; ops.ClientRecvStatus(context_, &status); call_.PerformOps(&ops); @@ -233,15 +229,41 @@ class ClientReader final : public ClientReaderInterface<R> { } private: + friend class internal::ClientReaderFactory<R>; ClientContext* context_; CompletionQueue cq_; - Call call_; + ::grpc::internal::Call call_; + + /// Block to create a stream and write the initial metadata and \a request + /// out. Note that \a context will be used to fill in custom initial + /// metadata used to send to the server when starting the call. + template <class W> + ClientReader(::grpc::ChannelInterface* channel, + const ::grpc::internal::RpcMethod& method, + ClientContext* context, const W& request) + : context_(context), + cq_(grpc_completion_queue_attributes{ + GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, + GRPC_CQ_DEFAULT_POLLING}), // Pluckable cq + call_(channel->CreateCall(method, context, &cq_)) { + ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata, + ::grpc::internal::CallOpSendMessage, + ::grpc::internal::CallOpClientSendClose> + ops; + ops.SendInitialMetadata(context->send_initial_metadata_, + context->initial_metadata_flags()); + // TODO(ctiller): don't assert + GPR_CODEGEN_ASSERT(ops.SendMessage(request).ok()); + ops.ClientSendClose(); + call_.PerformOps(&ops); + cq_.Pluck(&ops); + } }; /// Client-side interface for streaming writes of message type \a W. template <class W> -class ClientWriterInterface : public ClientStreamingInterface, - public WriterInterface<W> { +class ClientWriterInterface : public internal::ClientStreamingInterface, + public internal::WriterInterface<W> { public: /// Half close writing from the client. (signal that the stream of messages /// coming from the client is complete). @@ -252,37 +274,25 @@ class ClientWriterInterface : public ClientStreamingInterface, virtual bool WritesDone() = 0; }; +namespace internal { +template <class W> +class ClientWriterFactory { + public: + template <class R> + static ClientWriter<W>* Create(::grpc::ChannelInterface* channel, + const ::grpc::internal::RpcMethod& method, + ClientContext* context, R* response) { + return new ClientWriter<W>(channel, method, context, response); + } +}; +} // namespace internal + /// Synchronous (blocking) client-side API for doing client-streaming RPCs, /// where the outgoing message stream coming from the client has messages of /// type \a W. template <class W> class ClientWriter : public ClientWriterInterface<W> { public: - /// Block to create a stream (i.e. send request headers and other initial - /// metadata to the server). Note that \a context will be used to fill - /// in custom initial metadata. \a response will be filled in with the - /// single expected response message from the server upon a successful - /// call to the \a Finish method of this instance. - template <class R> - ClientWriter(ChannelInterface* channel, const RpcMethod& method, - ClientContext* context, R* response) - : context_(context), - cq_(grpc_completion_queue_attributes{ - GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, - GRPC_CQ_DEFAULT_POLLING}), // Pluckable cq - call_(channel->CreateCall(method, context, &cq_)) { - finish_ops_.RecvMessage(response); - finish_ops_.AllowNoMessage(); - - if (!context_->initial_metadata_corked_) { - CallOpSet<CallOpSendInitialMetadata> ops; - ops.SendInitialMetadata(context->send_initial_metadata_, - context->initial_metadata_flags()); - call_.PerformOps(&ops); - cq_.Pluck(&ops); - } - } - /// See the \a ClientStreamingInterface.WaitForInitialMetadata method for /// semantics. /// @@ -292,7 +302,8 @@ class ClientWriter : public ClientWriterInterface<W> { void WaitForInitialMetadata() { GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_); - CallOpSet<CallOpRecvInitialMetadata> ops; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata> + ops; ops.RecvInitialMetadata(context_); call_.PerformOps(&ops); cq_.Pluck(&ops); // status ignored @@ -304,10 +315,11 @@ class ClientWriter : public ClientWriterInterface<W> { /// Side effect: /// Also sends initial metadata if not already sent (using the /// \a ClientContext associated with this call). - using WriterInterface<W>::Write; + using ::grpc::internal::WriterInterface<W>::Write; bool Write(const W& msg, WriteOptions options) override { - CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, - CallOpClientSendClose> + ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata, + ::grpc::internal::CallOpSendMessage, + ::grpc::internal::CallOpClientSendClose> ops; if (options.is_last_message()) { @@ -328,7 +340,7 @@ class ClientWriter : public ClientWriterInterface<W> { } bool WritesDone() override { - CallOpSet<CallOpClientSendClose> ops; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpClientSendClose> ops; ops.ClientSendClose(); call_.PerformOps(&ops); return cq_.Pluck(&ops); @@ -352,21 +364,51 @@ class ClientWriter : public ClientWriterInterface<W> { } private: + friend class internal::ClientWriterFactory<W>; + + /// Block to create a stream (i.e. send request headers and other initial + /// metadata to the server). Note that \a context will be used to fill + /// in custom initial metadata. \a response will be filled in with the + /// single expected response message from the server upon a successful + /// call to the \a Finish method of this instance. + template <class R> + ClientWriter(ChannelInterface* channel, + const ::grpc::internal::RpcMethod& method, + ClientContext* context, R* response) + : context_(context), + cq_(grpc_completion_queue_attributes{ + GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, + GRPC_CQ_DEFAULT_POLLING}), // Pluckable cq + call_(channel->CreateCall(method, context, &cq_)) { + finish_ops_.RecvMessage(response); + finish_ops_.AllowNoMessage(); + + if (!context_->initial_metadata_corked_) { + ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata> + ops; + ops.SendInitialMetadata(context->send_initial_metadata_, + context->initial_metadata_flags()); + call_.PerformOps(&ops); + cq_.Pluck(&ops); + } + } + ClientContext* context_; - CallOpSet<CallOpRecvInitialMetadata, CallOpGenericRecvMessage, - CallOpClientRecvStatus> + ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata, + ::grpc::internal::CallOpGenericRecvMessage, + ::grpc::internal::CallOpClientRecvStatus> finish_ops_; CompletionQueue cq_; - Call call_; + ::grpc::internal::Call call_; }; /// Client-side interface for bi-directional streaming with /// client-to-server stream messages of type \a W and /// server-to-client stream messages of type \a R. template <class W, class R> -class ClientReaderWriterInterface : public ClientStreamingInterface, - public WriterInterface<W>, - public ReaderInterface<R> { +class ClientReaderWriterInterface : public internal::ClientStreamingInterface, + public internal::WriterInterface<W>, + public internal::ReaderInterface<R> { public: /// Block to wait for initial metadata from server. The received metadata /// can only be accessed after this call returns. Should only be called before @@ -375,7 +417,7 @@ class ClientReaderWriterInterface : public ClientStreamingInterface, virtual void WaitForInitialMetadata() = 0; /// Half close writing from the client. (signal that the stream of messages - /// coming from the client is complete). + /// coming from the clinet is complete). /// Blocks until currently-pending writes are completed. /// Thread-safe with respect to \a ReaderInterface::Read /// @@ -383,6 +425,18 @@ class ClientReaderWriterInterface : public ClientStreamingInterface, virtual bool WritesDone() = 0; }; +namespace internal { +template <class W, class R> +class ClientReaderWriterFactory { + public: + static ClientReaderWriter<W, R>* Create( + ::grpc::ChannelInterface* channel, + const ::grpc::internal::RpcMethod& method, ClientContext* context) { + return new ClientReaderWriter<W, R>(channel, method, context); + } +}; +} // namespace internal + /// Synchronous (blocking) client-side API for bi-directional streaming RPCs, /// where the outgoing message stream coming from the client has messages of /// type \a W, and the incoming messages stream coming from the server has @@ -390,25 +444,6 @@ class ClientReaderWriterInterface : public ClientStreamingInterface, template <class W, class R> class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> { public: - /// Block to create a stream and write the initial metadata and \a request - /// out. Note that \a context will be used to fill in custom initial metadata - /// used to send to the server when starting the call. - ClientReaderWriter(ChannelInterface* channel, const RpcMethod& method, - ClientContext* context) - : context_(context), - cq_(grpc_completion_queue_attributes{ - GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, - GRPC_CQ_DEFAULT_POLLING}), // Pluckable cq - call_(channel->CreateCall(method, context, &cq_)) { - if (!context_->initial_metadata_corked_) { - CallOpSet<CallOpSendInitialMetadata> ops; - ops.SendInitialMetadata(context->send_initial_metadata_, - context->initial_metadata_flags()); - call_.PerformOps(&ops); - cq_.Pluck(&ops); - } - } - /// Block waiting to read initial metadata from the server. /// This call is optional, but if it is used, it cannot be used concurrently /// with or after the \a Finish method. @@ -418,7 +453,8 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> { void WaitForInitialMetadata() override { GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_); - CallOpSet<CallOpRecvInitialMetadata> ops; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata> + ops; ops.RecvInitialMetadata(context_); call_.PerformOps(&ops); cq_.Pluck(&ops); // status ignored @@ -434,7 +470,9 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> { /// Also receives initial metadata if not already received (updates the \a /// ClientContext associated with this call in that case). bool Read(R* msg) override { - CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> ops; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata, + ::grpc::internal::CallOpRecvMessage<R>> + ops; if (!context_->initial_metadata_received_) { ops.RecvInitialMetadata(context_); } @@ -448,10 +486,11 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> { /// Side effect: /// Also sends initial metadata if not already sent (using the /// \a ClientContext associated with this call to fill in values). - using WriterInterface<W>::Write; + using ::grpc::internal::WriterInterface<W>::Write; bool Write(const W& msg, WriteOptions options) override { - CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, - CallOpClientSendClose> + ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata, + ::grpc::internal::CallOpSendMessage, + ::grpc::internal::CallOpClientSendClose> ops; if (options.is_last_message()) { @@ -472,7 +511,7 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> { } bool WritesDone() override { - CallOpSet<CallOpClientSendClose> ops; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpClientSendClose> ops; ops.ClientSendClose(); call_.PerformOps(&ops); return cq_.Pluck(&ops); @@ -484,7 +523,9 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> { /// - the \a ClientContext associated with this call is updated with /// possible trailing metadata sent from the server. Status Finish() override { - CallOpSet<CallOpRecvInitialMetadata, CallOpClientRecvStatus> ops; + ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata, + ::grpc::internal::CallOpClientRecvStatus> + ops; if (!context_->initial_metadata_received_) { ops.RecvInitialMetadata(context_); } @@ -496,15 +537,38 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> { } private: + friend class internal::ClientReaderWriterFactory<W, R>; + ClientContext* context_; CompletionQueue cq_; - Call call_; + ::grpc::internal::Call call_; + + /// Block to create a stream and write the initial metadata and \a request + /// out. Note that \a context will be used to fill in custom initial metadata + /// used to send to the server when starting the call. + ClientReaderWriter(::grpc::ChannelInterface* channel, + const ::grpc::internal::RpcMethod& method, + ClientContext* context) + : context_(context), + cq_(grpc_completion_queue_attributes{ + GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, + GRPC_CQ_DEFAULT_POLLING}), // Pluckable cq + call_(channel->CreateCall(method, context, &cq_)) { + if (!context_->initial_metadata_corked_) { + ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata> + ops; + ops.SendInitialMetadata(context->send_initial_metadata_, + context->initial_metadata_flags()); + call_.PerformOps(&ops); + cq_.Pluck(&ops); + } + } }; /// Server-side interface for streaming reads of message of type \a R. template <class R> -class ServerReaderInterface : public ServerStreamingInterface, - public ReaderInterface<R> {}; +class ServerReaderInterface : public internal::ServerStreamingInterface, + public internal::ReaderInterface<R> {}; /// Synchronous (blocking) server-side API for doing client-streaming RPCs, /// where the incoming message stream coming from the client has messages of @@ -512,15 +576,13 @@ class ServerReaderInterface : public ServerStreamingInterface, template <class R> class ServerReader final : public ServerReaderInterface<R> { public: - ServerReader(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {} - /// See the \a ServerStreamingInterface.SendInitialMetadata method /// for semantics. Note that initial metadata will be affected by the /// \a ServerContext associated with this call. void SendInitialMetadata() override { GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_); - CallOpSet<CallOpSendInitialMetadata> ops; + internal::CallOpSet<internal::CallOpSendInitialMetadata> ops; ops.SendInitialMetadata(ctx_->initial_metadata_, ctx_->initial_metadata_flags()); if (ctx_->compression_level_set()) { @@ -537,21 +599,27 @@ class ServerReader final : public ServerReaderInterface<R> { } bool Read(R* msg) override { - CallOpSet<CallOpRecvMessage<R>> ops; + internal::CallOpSet<internal::CallOpRecvMessage<R>> ops; ops.RecvMessage(msg); call_->PerformOps(&ops); return call_->cq()->Pluck(&ops) && ops.got_message; } private: - Call* const call_; + internal::Call* const call_; ServerContext* const ctx_; + + template <class ServiceType, class RequestType, class ResponseType> + friend class internal::ClientStreamingHandler; + + ServerReader(internal::Call* call, ServerContext* ctx) + : call_(call), ctx_(ctx) {} }; /// Server-side interface for streaming writes of message of type \a W. template <class W> -class ServerWriterInterface : public ServerStreamingInterface, - public WriterInterface<W> {}; +class ServerWriterInterface : public internal::ServerStreamingInterface, + public internal::WriterInterface<W> {}; /// Synchronous (blocking) server-side API for doing for doing a /// server-streaming RPCs, where the outgoing message stream coming from the @@ -559,8 +627,6 @@ class ServerWriterInterface : public ServerStreamingInterface, template <class W> class ServerWriter final : public ServerWriterInterface<W> { public: - ServerWriter(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {} - /// See the \a ServerStreamingInterface.SendInitialMetadata method /// for semantics. /// Note that initial metadata will be affected by the @@ -568,7 +634,7 @@ class ServerWriter final : public ServerWriterInterface<W> { void SendInitialMetadata() override { GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_); - CallOpSet<CallOpSendInitialMetadata> ops; + internal::CallOpSet<internal::CallOpSendInitialMetadata> ops; ops.SendInitialMetadata(ctx_->initial_metadata_, ctx_->initial_metadata_flags()); if (ctx_->compression_level_set()) { @@ -584,11 +650,12 @@ class ServerWriter final : public ServerWriterInterface<W> { /// Side effect: /// Also sends initial metadata if not already sent (using the /// \a ClientContext associated with this call to fill in values). - using WriterInterface<W>::Write; + using internal::WriterInterface<W>::Write; bool Write(const W& msg, WriteOptions options) override { if (options.is_last_message()) { options.set_buffer_hint(); } + if (!ctx_->pending_ops_.SendMessage(msg, options).ok()) { return false; } @@ -613,15 +680,21 @@ class ServerWriter final : public ServerWriterInterface<W> { } private: - Call* const call_; + internal::Call* const call_; ServerContext* const ctx_; + + template <class ServiceType, class RequestType, class ResponseType> + friend class internal::ServerStreamingHandler; + + ServerWriter(internal::Call* call, ServerContext* ctx) + : call_(call), ctx_(ctx) {} }; /// Server-side interface for bi-directional streaming. template <class W, class R> -class ServerReaderWriterInterface : public ServerStreamingInterface, - public WriterInterface<W>, - public ReaderInterface<R> {}; +class ServerReaderWriterInterface : public internal::ServerStreamingInterface, + public internal::WriterInterface<W>, + public internal::ReaderInterface<R> {}; /// Actual implementation of bi-directional streaming namespace internal { @@ -688,6 +761,7 @@ class ServerReaderWriterBody final { Call* const call_; ServerContext* const ctx_; }; + } // namespace internal /// Synchronous (blocking) server-side API for a bidirectional @@ -697,8 +771,6 @@ class ServerReaderWriterBody final { template <class W, class R> class ServerReaderWriter final : public ServerReaderWriterInterface<W, R> { public: - ServerReaderWriter(Call* call, ServerContext* ctx) : body_(call, ctx) {} - /// See the \a ServerStreamingInterface.SendInitialMetadata method /// for semantics. Note that initial metadata will be affected by the /// \a ServerContext associated with this call. @@ -715,13 +787,18 @@ class ServerReaderWriter final : public ServerReaderWriterInterface<W, R> { /// Side effect: /// Also sends initial metadata if not already sent (using the \a /// ServerContext associated with this call). - using WriterInterface<W>::Write; + using internal::WriterInterface<W>::Write; bool Write(const W& msg, WriteOptions options) override { return body_.Write(msg, options); } private: internal::ServerReaderWriterBody<W, R> body_; + + friend class internal::TemplatedBidiStreamingHandler<ServerReaderWriter<W, R>, + false>; + ServerReaderWriter(internal::Call* call, ServerContext* ctx) + : body_(call, ctx) {} }; /// A class to represent a flow-controlled unary call. This is something @@ -736,9 +813,6 @@ template <class RequestType, class ResponseType> class ServerUnaryStreamer final : public ServerReaderWriterInterface<ResponseType, RequestType> { public: - ServerUnaryStreamer(Call* call, ServerContext* ctx) - : body_(call, ctx), read_done_(false), write_done_(false) {} - /// Block to send initial metadata to client. /// Implicit input parameter: /// - the \a ServerContext associated with this call will be used for @@ -775,7 +849,7 @@ class ServerUnaryStreamer final /// \param options The WriteOptions affecting the write operation. /// /// \return \a true on success, \a false when the stream has been closed. - using WriterInterface<ResponseType>::Write; + using internal::WriterInterface<ResponseType>::Write; bool Write(const ResponseType& response, WriteOptions options) override { if (write_done_ || !read_done_) { return false; @@ -788,6 +862,11 @@ class ServerUnaryStreamer final internal::ServerReaderWriterBody<ResponseType, RequestType> body_; bool read_done_; bool write_done_; + + friend class internal::TemplatedBidiStreamingHandler< + ServerUnaryStreamer<RequestType, ResponseType>, true>; + ServerUnaryStreamer(internal::Call* call, ServerContext* ctx) + : body_(call, ctx), read_done_(false), write_done_(false) {} }; /// A class to represent a flow-controlled server-side streaming call. @@ -799,9 +878,6 @@ template <class RequestType, class ResponseType> class ServerSplitStreamer final : public ServerReaderWriterInterface<ResponseType, RequestType> { public: - ServerSplitStreamer(Call* call, ServerContext* ctx) - : body_(call, ctx), read_done_(false) {} - /// Block to send initial metadata to client. /// Implicit input parameter: /// - the \a ServerContext associated with this call will be used for @@ -838,7 +914,7 @@ class ServerSplitStreamer final /// \param options The WriteOptions affecting the write operation. /// /// \return \a true on success, \a false when the stream has been closed. - using WriterInterface<ResponseType>::Write; + using internal::WriterInterface<ResponseType>::Write; bool Write(const ResponseType& response, WriteOptions options) override { return read_done_ && body_.Write(response, options); } @@ -846,6 +922,11 @@ class ServerSplitStreamer final private: internal::ServerReaderWriterBody<ResponseType, RequestType> body_; bool read_done_; + + friend class internal::TemplatedBidiStreamingHandler< + ServerSplitStreamer<RequestType, ResponseType>, false>; + ServerSplitStreamer(internal::Call* call, ServerContext* ctx) + : body_(call, ctx), read_done_(false) {} }; } // namespace grpc diff --git a/include/grpc++/impl/codegen/time.h b/include/grpc++/impl/codegen/time.h index 589deb4f03..d464d6ea13 100644 --- a/include/grpc++/impl/codegen/time.h +++ b/include/grpc++/impl/codegen/time.h @@ -19,6 +19,8 @@ #ifndef GRPCXX_IMPL_CODEGEN_TIME_H #define GRPCXX_IMPL_CODEGEN_TIME_H +#include <chrono> + #include <grpc++/impl/codegen/config.h> #include <grpc/impl/codegen/grpc_types.h> @@ -59,10 +61,6 @@ class TimePoint<gpr_timespec> { } // namespace grpc -#include <chrono> - -#include <grpc/impl/codegen/grpc_types.h> - namespace grpc { // from and to should be absolute time. diff --git a/include/grpc++/server.h b/include/grpc++/server.h index 0a3aae8241..01c4a60d21 100644 --- a/include/grpc++/server.h +++ b/include/grpc++/server.h @@ -175,7 +175,8 @@ class Server final : public ServerInterface, private GrpcLibraryCodegen { /// \param num_cqs How many completion queues does \a cqs hold. void Start(ServerCompletionQueue** cqs, size_t num_cqs) override; - void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) override; + void PerformOpsOnCall(internal::CallOpSetInterface* ops, + internal::Call* call) override; void ShutdownInternal(gpr_timespec deadline) override; diff --git a/include/grpc++/server_builder.h b/include/grpc++/server_builder.h index bbf45b3e74..0888bef0d9 100644 --- a/include/grpc++/server_builder.h +++ b/include/grpc++/server_builder.h @@ -40,7 +40,6 @@ namespace grpc { class AsyncGenericService; class ResourceQuota; class CompletionQueue; -class RpcService; class Server; class ServerCompletionQueue; class ServerCredentials; @@ -140,7 +139,7 @@ class ServerBuilder { /// please use IPv6 any, i.e., [::]:<port>, which also accepts IPv4 /// connections. Valid values include dns:///localhost:1234, / /// 192.168.1.1:31416, dns:///[::1]:27182, etc.). - /// \params creds The credentials associated with the server. + /// \param creds The credentials associated with the server. /// \param selected_port[out] If not `nullptr`, gets populated with the port /// number bound to the \a grpc::Server for the corresponding endpoint after /// it is successfully bound, 0 otherwise. diff --git a/include/grpc/census.h b/include/grpc/census.h index de8e7a6617..2258af8898 100644 --- a/include/grpc/census.h +++ b/include/grpc/census.h @@ -16,10 +16,6 @@ * */ -/** RPC-internal Census API's. These are designed to be generic enough that - * they can (ultimately) be used in many different RPC systems (with differing - * implementations). */ - #ifndef GRPC_CENSUS_H #define GRPC_CENSUS_H @@ -29,439 +25,12 @@ extern "C" { #endif -/** Identify census features that can be enabled via census_initialize(). */ -enum census_features { - CENSUS_FEATURE_NONE = 0, /** Do not enable census. */ - CENSUS_FEATURE_TRACING = 1, /** Enable census tracing. */ - CENSUS_FEATURE_STATS = 2, /** Enable Census stats collection. */ - CENSUS_FEATURE_CPU = 4, /** Enable Census CPU usage collection. */ - CENSUS_FEATURE_ALL = - CENSUS_FEATURE_TRACING | CENSUS_FEATURE_STATS | CENSUS_FEATURE_CPU -}; - -/** Shutdown and startup census subsystem. The 'features' argument should be - * the OR (|) of census_features values. If census fails to initialize, then - * census_initialize() will return -1, otherwise the set of enabled features - * (which may be smaller than that provided in the `features` argument, see - * census_supported()) is returned. It is an error to call census_initialize() - * more than once (without an intervening census_shutdown()). These functions - * are not thread-safe. */ -CENSUSAPI int census_initialize(int features); -CENSUSAPI void census_shutdown(void); - -/** Return the features supported by the current census implementation (not all - * features will be available on all platforms). */ -CENSUSAPI int census_supported(void); - -/** Return the census features currently enabled. */ -CENSUSAPI int census_enabled(void); - /** A Census Context is a handle used by Census to represent the current tracing and stats collection information. Contexts should be propagated across RPC's - (this is the responsibility of the local RPC system). A context is typically - used as the first argument to most census functions. Conceptually, they - should be thought of as specific to a single RPC/thread. The user visible - context representation is that of a collection of key:value string pairs, - each of which is termed a 'tag'; these form the basis against which Census - metrics will be recorded. Keys are unique within a context. */ + (this is the responsibility of the local RPC system). */ typedef struct census_context census_context; -/** A tag is a key:value pair. Both keys and values are nil-terminated strings, - containing printable ASCII characters (decimal 32-126). Keys must be at - least one character in length. Both keys and values can have at most - CENSUS_MAX_TAG_KB_LEN characters (including the terminating nil). The - maximum number of tags that can be propagated is - CENSUS_MAX_PROPAGATED_TAGS. Users should also remember that some systems - may have limits on, e.g., the number of bytes that can be transmitted as - metadata, and that larger tags means more memory consumed and time in - processing. */ -typedef struct { - const char *key; - const char *value; - uint8_t flags; -} census_tag; - -/** Maximum length of a tag's key or value. */ -#define CENSUS_MAX_TAG_KV_LEN 255 -/** Maximum number of propagatable tags. */ -#define CENSUS_MAX_PROPAGATED_TAGS 255 - -/** Tag flags. */ -#define CENSUS_TAG_PROPAGATE 1 /** Tag should be propagated over RPC */ -#define CENSUS_TAG_STATS 2 /** Tag will be used for statistics aggregation */ -#define CENSUS_TAG_RESERVED 4 /** Reserved for internal use. */ -/** Flag values 4,8,16,32,64,128 are reserved for future/internal use. Clients - should not use or rely on their values. */ - -#define CENSUS_TAG_IS_PROPAGATED(flags) (flags & CENSUS_TAG_PROPAGATE) -#define CENSUS_TAG_IS_STATS(flags) (flags & CENSUS_TAG_STATS) - -/** An instance of this structure is kept by every context, and records the - basic information associated with the creation of that context. */ -typedef struct { - int n_propagated_tags; /** number of propagated tags */ - int n_local_tags; /** number of non-propagated (local) tags */ - int n_deleted_tags; /** number of tags that were deleted */ - int n_added_tags; /** number of tags that were added */ - int n_modified_tags; /** number of tags that were modified */ - int n_invalid_tags; /** number of tags with bad keys or values (e.g. - longer than CENSUS_MAX_TAG_KV_LEN) */ - int n_ignored_tags; /** number of tags ignored because of - CENSUS_MAX_PROPAGATED_TAGS limit. */ -} census_context_status; - -/** Create a new context, adding and removing tags from an existing context. - This will copy all tags from the 'tags' input, so it is recommended - to add as many tags in a single operation as is practical for the client. - @param base Base context to build upon. Can be NULL. - @param tags A set of tags to be added/changed/deleted. Tags with keys that - are in 'tags', but not 'base', are added to the context. Keys that are in - both 'tags' and 'base' will have their value/flags modified. Tags with keys - in both, but with NULL values, will be deleted from the context. Tags with - invalid (too long or short) keys or values will be ignored. - If adding a tag will result in more than CENSUS_MAX_PROPAGATED_TAGS in either - binary or non-binary tags, they will be ignored, as will deletions of - tags that don't exist. - @param ntags number of tags in 'tags' - @param status If not NULL, will return a pointer to a census_context_status - structure containing information about the new context and status of the - tags used in its creation. - @return A new, valid census_context. -*/ -CENSUSAPI census_context *census_context_create( - const census_context *base, const census_tag *tags, int ntags, - census_context_status const **status); - -/** Destroy a context. Once this function has been called, the context cannot - be reused. */ -CENSUSAPI void census_context_destroy(census_context *context); - -/** Get a pointer to the original status from the context creation. */ -CENSUSAPI const census_context_status *census_context_get_status( - const census_context *context); - -/** Structure used for iterating over the tags in a context. API clients should - not use or reference internal fields - neither their contents or - presence/absence are guaranteed. */ -typedef struct { - const census_context *context; - int base; - int index; - char *kvm; -} census_context_iterator; - -/** Initialize a census_tag_iterator. Must be called before first use. */ -CENSUSAPI void census_context_initialize_iterator( - const census_context *context, census_context_iterator *iterator); - -/** Get the contents of the "next" tag in the context. If there are no more - tags, returns 0 (and 'tag' contents will be unchanged), otherwise returns 1. - */ -CENSUSAPI int census_context_next_tag(census_context_iterator *iterator, - census_tag *tag); - -/** Get a context tag by key. Returns 0 if the key is not present. */ -CENSUSAPI int census_context_get_tag(const census_context *context, - const char *key, census_tag *tag); - -/** Tag set encode/decode functionality. These functions are intended - for use by RPC systems only, for purposes of transmitting/receiving contexts. - */ - -/** Encode a context into a buffer. - @param context context to be encoded - @param buffer buffer into which the context will be encoded. - @param buf_size number of available bytes in buffer. - @return The number of buffer bytes consumed for the encoded context, or - zero if the buffer was of insufficient size. */ -CENSUSAPI size_t census_context_encode(const census_context *context, - char *buffer, size_t buf_size); - -/** Decode context buffer encoded with census_context_encode(). Returns NULL - if there is an error in parsing either buffer. */ -CENSUSAPI census_context *census_context_decode(const char *buffer, - size_t size); - -/** Distributed traces can have a number of options. */ -enum census_trace_mask_values { - CENSUS_TRACE_MASK_NONE = 0, /** Default, empty flags */ - CENSUS_TRACE_MASK_IS_SAMPLED = 1 /** RPC tracing enabled for this context. */ -}; - -/** Get the current trace mask associated with this context. The value returned - will be the logical OR of census_trace_mask_values values. */ -CENSUSAPI int census_trace_mask(const census_context *context); - -/** Set the trace mask associated with a context. */ -CENSUSAPI void census_set_trace_mask(int trace_mask); - -/** The concept of "operation" is a fundamental concept for Census. In an RPC - system, an operation typically represents a single RPC, or a significant - sub-part thereof (e.g. a single logical "read" RPC to a distributed storage - system might do several other actions in parallel, from looking up metadata - indices to making requests of other services - each of these could be a - sub-operation with the larger RPC operation). Census uses operations for the - following: - - CPU accounting: If enabled, census will measure the thread CPU time - consumed between operation start and end times. - - Active operations: Census will maintain information on all currently - active operations. - - Distributed tracing: Each operation serves as a logical trace span. - - Stats collection: Stats are broken down by operation (e.g. latency - breakdown for each unique RPC path). - - The following functions serve to delineate the start and stop points for - each logical operation. */ - -/** - This structure represents a timestamp as used by census to record the time - at which an operation begins. -*/ -typedef struct { - /** Use gpr_timespec for default implementation. High performance - * implementations should use a cycle-counter based timestamp. */ - gpr_timespec ts; -} census_timestamp; - -/** - Mark the beginning of an RPC operation. The information required to call the - functions to record the start of RPC operations (both client and server) may - not be callable at the true start time of the operation, due to information - not being available (e.g. the census context data will not be available in a - server RPC until at least initial metadata has been processed). To ensure - correct CPU accounting and latency recording, RPC systems can call this - function to get the timestamp of operation beginning. This can later be used - as an argument to census_start_{client,server}_rpc_op(). NB: for correct - CPU accounting, the system must guarantee that the same thread is used - for all request processing after this function is called. - - @return A timestamp representing the operation start time. -*/ -CENSUSAPI census_timestamp census_start_rpc_op_timestamp(void); - -/** - Represent functions to map RPC name ID to service/method names. Census - breaks down all RPC stats by service and method names. We leave the - definition and format of these to the RPC system. For efficiency purposes, - we encode these as a single 64 bit identifier, and allow the RPC system to - provide a structure for functions that can convert these to service and - method strings. - - TODO(aveitch): Instead of providing this as an argument to the rpc_start_op() - functions, maybe it should be set once at census initialization. -*/ -typedef struct { - const char *(*get_rpc_service_name)(int64_t id); - const char *(*get_rpc_method_name)(int64_t id); -} census_rpc_name_info; - -/** - Start a client rpc operation. This function should be called as early in the - client RPC path as possible. This function will create a new context. If - the context argument is non-null, then the new context will inherit all - its properties, with the following changes: - - create a new operation ID for the new context, marking it as a child of - the previous operation. - - use the new RPC path and peer information for tracing and stats - collection purposes, rather than those from the original context - - If the context argument is NULL, then a new root context is created. This - is particularly important for tracing purposes (the trace spans generated - will be unassociated with any other trace spans, except those - downstream). The trace_mask will be used for tracing operations associated - with the new context. - - In some RPC systems (e.g. where load balancing is used), peer information - may not be available at the time the operation starts. In this case, use a - NULL value for peer, and set it later using the - census_set_rpc_client_peer() function. - - @param context The parent context. Can be NULL. - @param rpc_name_id The rpc name identifier to be associated with this RPC. - @param rpc_name_info Used to decode rpc_name_id. - @param peer RPC peer. If not available at the time, NULL can be used, - and a later census_set_rpc_client_peer() call made. - @param trace_mask An OR of census_trace_mask_values values. Only used in - the creation of a new root context (context == NULL). - @param start_time A timestamp returned from census_start_rpc_op_timestamp(). - Can be NULL. Used to set the true time the operation - begins. - - @return A new census context. - */ -CENSUSAPI census_context *census_start_client_rpc_op( - const census_context *context, int64_t rpc_name_id, - const census_rpc_name_info *rpc_name_info, const char *peer, int trace_mask, - const census_timestamp *start_time); - -/** - Add peer information to a context representing a client RPC operation. -*/ -CENSUSAPI void census_set_rpc_client_peer(census_context *context, - const char *peer); - -/** - Start a server RPC operation. Returns a new context to be used in future - census calls. If buffer is non-NULL, then the buffer contents should - represent the client context, as generated by census_context_serialize(). - If buffer is NULL, a new root context is created. - - @param buffer Buffer containing bytes output from census_context_serialize(). - @param rpc_name_id The rpc name identifier to be associated with this RPC. - @param rpc_name_info Used to decode rpc_name_id. - @param peer RPC peer. - @param trace_mask An OR of census_trace_mask_values values. Only used in - the creation of a new root context (buffer == NULL). - @param start_time A timestamp returned from census_start_rpc_op_timestamp(). - Can be NULL. Used to set the true time the operation - begins. - - @return A new census context. - */ -CENSUSAPI census_context *census_start_server_rpc_op( - const char *buffer, int64_t rpc_name_id, - const census_rpc_name_info *rpc_name_info, const char *peer, int trace_mask, - census_timestamp *start_time); - -/** - Start a new, non-RPC operation. In general, this function works very - similarly to census_start_client_rpc_op, with the primary difference being - the replacement of host/path information with the more generic family/name - tags. If the context argument is non-null, then the new context will - inherit all its properties, with the following changes: - - create a new operation ID for the new context, marking it as a child of - the previous operation. - - use the family and name information for tracing and stats collection - purposes, rather than those from the original context - - If the context argument is NULL, then a new root context is created. This - is particularly important for tracing purposes (the trace spans generated - will be unassociated with any other trace spans, except those - downstream). The trace_mask will be used for tracing - operations associated with the new context. - - @param context The base context. Can be NULL. - @param family Family name to associate with the trace - @param name Name within family to associate with traces/stats - @param trace_mask An OR of census_trace_mask_values values. Only used if - context is NULL. - - @return A new census context. - */ -CENSUSAPI census_context *census_start_op(census_context *context, - const char *family, const char *name, - int trace_mask); - -/** - End an operation started by any of the census_start_*_op*() calls. The - context used in this call will no longer be valid once this function - completes. - - @param context Context associated with operation which is ending. - @param status status associated with the operation. Not interpreted by - census. -*/ -CENSUSAPI void census_end_op(census_context *context, int status); - -#define CENSUS_TRACE_RECORD_START_OP ((uint32_t)0) -#define CENSUS_TRACE_RECORD_END_OP ((uint32_t)1) - -/** Insert a trace record into the trace stream. The record consists of an - arbitrary size buffer, the size of which is provided in 'n'. - @param context Trace context - @param type User-defined type to associate with trace entry. - @param buffer Pointer to buffer to use - @param n Number of bytes in buffer -*/ -CENSUSAPI void census_trace_print(census_context *context, uint32_t type, - const char *buffer, size_t n); - -/** Trace record. */ -typedef struct { - census_timestamp timestamp; /** Time of record creation */ - uint64_t trace_id; /** Trace ID associated with record */ - uint64_t op_id; /** Operation ID associated with record */ - uint32_t type; /** Type (as used in census_trace_print() */ - const char *buffer; /** Buffer (from census_trace_print() */ - size_t buf_size; /** Number of bytes inside buffer */ -} census_trace_record; - -/** Start a scan of existing trace records. While a scan is ongoing, addition - of new trace records will be blocked if the underlying trace buffers - fill up, so trace processing systems should endeavor to complete - reading as soon as possible. - @param consume if non-zero, indicates that reading records also "consumes" - the previously read record - i.e. releases space in the trace log - while scanning is ongoing. - @returns 0 on success, non-zero on failure (e.g. if a scan is already ongoing) -*/ -CENSUSAPI int census_trace_scan_start(int consume); - -/** Get a trace record. The data pointed to by the trace buffer is guaranteed - stable until the next census_get_trace_record() call (if the consume - argument to census_trace_scan_start was non-zero) or census_trace_scan_end() - is called (otherwise). - @param trace_record structure that will be filled in with oldest trace record. - @returns -1 if an error occurred (e.g. no previous call to - census_trace_scan_start()), 0 if there is no more trace data (and - trace_record will not be modified) or 1 otherwise. -*/ -CENSUSAPI int census_get_trace_record(census_trace_record *trace_record); - -/** End a scan previously started by census_trace_scan_start() */ -CENSUSAPI void census_trace_scan_end(); - -/** Core stats collection API's. The following concepts are used: - * Resource: Users record measurements for a single resource. Examples - include RPC latency, CPU seconds consumed, and bytes transmitted. - * Aggregation: An aggregation of a set of measurements. Census supports the - following aggregation types: - * Distribution - statistical distribution information, used for - recording average, standard deviation etc. Can include a histogram. - * Interval - a count of events that happen in a rolling time window. - * View: A view is a combination of a Resource, a set of tag keys and an - Aggregation. When a measurement for a Resource matches the View tags, it is - recorded (for each unique set of tag values) using the Aggregation type. - Each resource can have an arbitrary number of views by which it will be - broken down. - - Census uses protos to define each of the above, and output results. This - ensures unification across the different language and runtime - implementations. The proto definitions can be found in src/proto/census. -*/ - -/** Define a new resource. `resource_pb` should contain an encoded Resource - protobuf, `resource_pb_size` being the size of the buffer. Returns a -ve - value on error, or a positive (>= 0) resource id (for use in - census_delete_resource() and census_record_values()). In order to be valid, a - resource must have a name, and at least one numerator in its unit type. The - resource name must be unique, and an error will be returned if it is not. */ -CENSUSAPI int32_t census_define_resource(const uint8_t *resource_pb, - size_t resource_pb_size); - -/** Delete a resource created by census_define_resource(). */ -CENSUSAPI void census_delete_resource(int32_t resource_id); - -/** Determine the id of a resource, given its name. returns -1 if the resource - does not exist. */ -CENSUSAPI int32_t census_resource_id(const char *name); - -/** A single value to be recorded comprises two parts: an ID for the particular - * resource and the value to be recorded against it. */ -typedef struct { - int32_t resource_id; - double value; -} census_value; - -/** Record new usage values against the given context. */ -CENSUSAPI void census_record_values(census_context *context, - census_value *values, size_t nvalues); - #ifdef __cplusplus } #endif diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index 1de289fba4..6df3b8086e 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -143,6 +143,23 @@ GRPCAPI void grpc_completion_queue_shutdown(grpc_completion_queue *cq); drained and no threads are executing grpc_completion_queue_next */ GRPCAPI void grpc_completion_queue_destroy(grpc_completion_queue *cq); +/*********** EXPERIMENTAL API ************/ +/** Initializes a thread local cache for \a cq. + * grpc_flush_cq_tls_cache() MUST be called on the same thread, + * with the same cq. + */ +GRPCAPI void grpc_completion_queue_thread_local_cache_init( + grpc_completion_queue *cq); + +/*********** EXPERIMENTAL API ************/ +/** Flushes the thread local cache for \a cq. + * Returns 1 if there was contents in the cache. If there was an event + * in \a cq tls cache, its tag is placed in tag, and ok is set to the + * event success. + */ +GRPCAPI int grpc_completion_queue_thread_local_cache_flush( + grpc_completion_queue *cq, void **tag, int *ok); + /** Create a completion queue alarm instance */ GRPCAPI grpc_alarm *grpc_alarm_create(void *reserved); diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h index 95b1447935..758aaf5b6c 100644 --- a/include/grpc/grpc_security.h +++ b/include/grpc/grpc_security.h @@ -316,6 +316,43 @@ typedef struct grpc_server_credentials grpc_server_credentials; */ GRPCAPI void grpc_server_credentials_release(grpc_server_credentials *creds); +/** Server certificate config object holds the server's public certificates and + associated private keys, as well as any CA certificates needed for client + certificate validation (if applicable). Create using + grpc_ssl_server_certificate_config_create(). */ +typedef struct grpc_ssl_server_certificate_config + grpc_ssl_server_certificate_config; + +/** Creates a grpc_ssl_server_certificate_config object. + - pem_roots_cert is the NULL-terminated string containing the PEM encoding of + the client root certificates. This parameter may be NULL if the server does + not want the client to be authenticated with SSL. + - pem_key_cert_pairs is an array private key / certificate chains of the + server. This parameter cannot be NULL. + - num_key_cert_pairs indicates the number of items in the private_key_files + and cert_chain_files parameters. It must be at least 1. + - It is the caller's responsibility to free this object via + grpc_ssl_server_certificate_config_destroy(). */ +GRPCAPI grpc_ssl_server_certificate_config * +grpc_ssl_server_certificate_config_create( + const char *pem_root_certs, + const grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, + size_t num_key_cert_pairs); + +/** Destroys a grpc_ssl_server_certificate_config object. */ +GRPCAPI void grpc_ssl_server_certificate_config_destroy( + grpc_ssl_server_certificate_config *config); + +/** Callback to retrieve updated SSL server certificates, private keys, and + trusted CAs (for client authentication). + - user_data parameter, if not NULL, contains opaque data to be used by the + callback. + - Use grpc_ssl_server_certificate_config_create to create the config. + - The caller assumes ownership of the config. */ +typedef grpc_ssl_certificate_config_reload_status ( + *grpc_ssl_server_certificate_config_callback)( + void *user_data, grpc_ssl_server_certificate_config **config); + /** Deprecated in favor of grpc_ssl_server_credentials_create_ex. Creates an SSL server_credentials object. - pem_roots_cert is the NULL-terminated string containing the PEM encoding of @@ -332,7 +369,8 @@ GRPCAPI grpc_server_credentials *grpc_ssl_server_credentials_create( const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, size_t num_key_cert_pairs, int force_client_auth, void *reserved); -/** Same as grpc_ssl_server_credentials_create method except uses +/** Deprecated in favor of grpc_ssl_server_credentials_create_with_options. + Same as grpc_ssl_server_credentials_create method except uses grpc_ssl_client_certificate_request_type enum to support more ways to authenticate client cerificates.*/ GRPCAPI grpc_server_credentials *grpc_ssl_server_credentials_create_ex( @@ -341,6 +379,40 @@ GRPCAPI grpc_server_credentials *grpc_ssl_server_credentials_create_ex( grpc_ssl_client_certificate_request_type client_certificate_request, void *reserved); +typedef struct grpc_ssl_server_credentials_options + grpc_ssl_server_credentials_options; + +/** Creates an options object using a certificate config. Use this method when + the certificates and keys of the SSL server will not change during the + server's lifetime. + - Takes ownership of the certificate_config parameter. */ +GRPCAPI grpc_ssl_server_credentials_options * +grpc_ssl_server_credentials_create_options_using_config( + grpc_ssl_client_certificate_request_type client_certificate_request, + grpc_ssl_server_certificate_config *certificate_config); + +/** Creates an options object using a certificate config fetcher. Use this + method to reload the certificates and keys of the SSL server without + interrupting the operation of the server. Initial certificate config will be + fetched during server initialization. + - user_data parameter, if not NULL, contains opaque data which will be passed + to the fetcher (see definition of + grpc_ssl_server_certificate_config_callback). */ +GRPCAPI grpc_ssl_server_credentials_options * +grpc_ssl_server_credentials_create_options_using_config_fetcher( + grpc_ssl_client_certificate_request_type client_certificate_request, + grpc_ssl_server_certificate_config_callback cb, void *user_data); + +/** Destroys a grpc_ssl_server_credentials_options object. */ +GRPCAPI void grpc_ssl_server_credentials_options_destroy( + grpc_ssl_server_credentials_options *options); + +/** Creates an SSL server_credentials object using the provided options struct. + - Takes ownership of the options parameter. */ +GRPCAPI grpc_server_credentials * +grpc_ssl_server_credentials_create_with_options( + grpc_ssl_server_credentials_options *options); + /** --- Server-side secure ports. --- */ /** Add a HTTP2 over an encrypted link over tcp listener. diff --git a/include/grpc/grpc_security_constants.h b/include/grpc/grpc_security_constants.h index fde300dfb1..60e167eb88 100644 --- a/include/grpc/grpc_security_constants.h +++ b/include/grpc/grpc_security_constants.h @@ -48,6 +48,13 @@ typedef enum { GRPC_SSL_ROOTS_OVERRIDE_FAIL } grpc_ssl_roots_override_result; +/** Callback results for dynamically loading a SSL certificate config. */ +typedef enum { + GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED, + GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW, + GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL +} grpc_ssl_certificate_config_reload_status; + typedef enum { /** Server does not request client certificate. A client can present a self signed or signed certificates if it wishes to do so and they would be diff --git a/include/grpc/impl/codegen/connectivity_state.h b/include/grpc/impl/codegen/connectivity_state.h index 545b4fdbcc..b70dbef356 100644 --- a/include/grpc/impl/codegen/connectivity_state.h +++ b/include/grpc/impl/codegen/connectivity_state.h @@ -25,8 +25,6 @@ extern "C" { /** Connectivity state of a channel. */ typedef enum { - /** channel has just been initialized */ - GRPC_CHANNEL_INIT = -1, /** channel is idle */ GRPC_CHANNEL_IDLE, /** channel is connecting */ diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h index baea4bcf52..fb4bfc3162 100644 --- a/include/grpc/impl/codegen/port_platform.h +++ b/include/grpc/impl/codegen/port_platform.h @@ -241,6 +241,29 @@ #else /* _LP64 */ #define GPR_ARCH_32 1 #endif /* _LP64 */ +#elif defined(__OpenBSD__) +#define GPR_PLATFORM_STRING "openbsd" +#ifndef _BSD_SOURCE +#define _BSD_SOURCE +#endif +#define GPR_OPENBSD 1 +#define GPR_CPU_POSIX 1 +#define GPR_GCC_ATOMIC 1 +#define GPR_GCC_TLS 1 +#define GPR_POSIX_LOG 1 +#define GPR_POSIX_ENV 1 +#define GPR_POSIX_TMPFILE 1 +#define GPR_POSIX_STRING 1 +#define GPR_POSIX_SUBPROCESS 1 +#define GPR_POSIX_SYNC 1 +#define GPR_POSIX_TIME 1 +#define GPR_GETPID_IN_UNISTD_H 1 +#define GPR_SUPPORT_CHANNELS_FROM_FD 1 +#ifdef _LP64 +#define GPR_ARCH_64 1 +#else /* _LP64 */ +#define GPR_ARCH_32 1 +#endif /* _LP64 */ #elif defined(__native_client__) #define GPR_PLATFORM_STRING "nacl" #ifndef _BSD_SOURCE diff --git a/include/grpc/module.modulemap b/include/grpc/module.modulemap index 1ac1804084..65de47f938 100644 --- a/include/grpc/module.modulemap +++ b/include/grpc/module.modulemap @@ -4,7 +4,6 @@ framework module grpc { header "support/alloc.h" header "support/atm.h" - header "support/atm_gcc_atomic.h" header "support/avl.h" header "support/cmdline.h" header "support/cpu.h" @@ -16,23 +15,17 @@ framework module grpc { header "support/string_util.h" header "support/subprocess.h" header "support/sync.h" - header "support/sync_custom.h" header "support/sync_generic.h" - header "support/sync_posix.h" header "support/thd.h" header "support/time.h" header "support/tls.h" - header "support/tls_pthread.h" header "support/useful.h" header "impl/codegen/atm.h" - header "impl/codegen/atm_gcc_atomic.h" header "impl/codegen/gpr_slice.h" header "impl/codegen/gpr_types.h" header "impl/codegen/port_platform.h" header "impl/codegen/sync.h" - header "impl/codegen/sync_custom.h" header "impl/codegen/sync_generic.h" - header "impl/codegen/sync_posix.h" header "impl/codegen/byte_buffer.h" header "impl/codegen/byte_buffer_reader.h" header "impl/codegen/compression_types.h" @@ -43,14 +36,11 @@ framework module grpc { header "impl/codegen/slice.h" header "impl/codegen/status.h" header "impl/codegen/atm.h" - header "impl/codegen/atm_gcc_atomic.h" header "impl/codegen/gpr_slice.h" header "impl/codegen/gpr_types.h" header "impl/codegen/port_platform.h" header "impl/codegen/sync.h" - header "impl/codegen/sync_custom.h" header "impl/codegen/sync_generic.h" - header "impl/codegen/sync_posix.h" header "grpc_security.h" header "byte_buffer.h" header "byte_buffer_reader.h" @@ -66,6 +56,28 @@ framework module grpc { header "support/workaround_list.h" header "census.h" + textual header "support/atm_gcc_atomic.h" + textual header "support/atm_gcc_sync.h" + textual header "support/atm_windows.h" + textual header "support/sync_custom.h" + textual header "support/sync_posix.h" + textual header "support/sync_windows.h" + textual header "support/tls_gcc.h" + textual header "support/tls_msvc.h" + textual header "support/tls_pthread.h" + textual header "impl/codegen/atm_gcc_atomic.h" + textual header "impl/codegen/atm_gcc_sync.h" + textual header "impl/codegen/atm_windows.h" + textual header "impl/codegen/sync_custom.h" + textual header "impl/codegen/sync_posix.h" + textual header "impl/codegen/sync_windows.h" + textual header "impl/codegen/atm_gcc_atomic.h" + textual header "impl/codegen/atm_gcc_sync.h" + textual header "impl/codegen/atm_windows.h" + textual header "impl/codegen/sync_custom.h" + textual header "impl/codegen/sync_posix.h" + textual header "impl/codegen/sync_windows.h" + export * module * { export * } } diff --git a/include/grpc/slice.h b/include/grpc/slice.h index 3f3cff1408..2203e3887b 100644 --- a/include/grpc/slice.h +++ b/include/grpc/slice.h @@ -137,7 +137,6 @@ GPRAPI int grpc_slice_eq(grpc_slice a, grpc_slice b); versions of the API. */ GPRAPI int grpc_slice_cmp(grpc_slice a, grpc_slice b); GPRAPI int grpc_slice_str_cmp(grpc_slice a, const char *b); -GPRAPI int grpc_slice_buf_cmp(grpc_slice a, const void *b, size_t blen); /** return non-zero if the first blen bytes of a are equal to b */ GPRAPI int grpc_slice_buf_start_eq(grpc_slice a, const void *b, size_t blen); diff --git a/include/grpc/support/sync.h b/include/grpc/support/sync.h index fe8a59a5d6..ddb85808c7 100644 --- a/include/grpc/support/sync.h +++ b/include/grpc/support/sync.h @@ -274,7 +274,23 @@ GPRAPI intptr_t gpr_stats_read(const gpr_stats_counter *c); #endif /* 0 */ #ifdef __cplusplus -} +} // extern "C" + +namespace grpc_core { + +class mu_guard { + public: + mu_guard(gpr_mu *mu) : mu_(mu) { gpr_mu_lock(mu); } + ~mu_guard() { gpr_mu_unlock(mu_); } + + mu_guard(const mu_guard &) = delete; + mu_guard &operator=(const mu_guard &) = delete; + + private: + gpr_mu *const mu_; +}; + +} // namespace grpc_core #endif #endif /* GRPC_SUPPORT_SYNC_H */ |