aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar jboeuf <jboeuf@users.noreply.github.com>2015-12-02 20:55:37 -0800
committerGravatar jboeuf <jboeuf@users.noreply.github.com>2015-12-02 20:55:37 -0800
commit6f9b17184246ccd29e1a5b0271058c3ccfd63887 (patch)
tree69590632cff7364e99392940096822606af0d905
parent5bf6b02385f427454f23b750839123c6a565bf23 (diff)
parent06dd04cfd30f3ea1f3e9cb0ad2be079f87e6b7b3 (diff)
Merge pull request #4204 from ctiller/emergency-cheese-and-crackers
Global hook for doing something in response to a synchronous server call
-rw-r--r--include/grpc++/server.h18
-rw-r--r--src/cpp/server/server.cc25
2 files changed, 43 insertions, 0 deletions
diff --git a/include/grpc++/server.h b/include/grpc++/server.h
index 1a62df5698..7bb3cdf915 100644
--- a/include/grpc++/server.h
+++ b/include/grpc++/server.h
@@ -56,6 +56,7 @@ class AsyncGenericService;
class RpcService;
class RpcServiceMethod;
class ServerAsyncStreamingInterface;
+class ServerContext;
class ThreadPoolInterface;
/// Models a gRPC server.
@@ -84,6 +85,23 @@ class Server GRPC_FINAL : public GrpcLibrary, private CallHook {
/// call \a Shutdown for this function to ever return.
void Wait();
+ /// Global Callbacks
+ ///
+ /// Can be set exactly once per application to install hooks whenever
+ /// a server event occurs
+ class GlobalCallbacks {
+ public:
+ virtual ~GlobalCallbacks() {}
+ /// Called before application callback for each synchronous server request
+ virtual void PreSynchronousRequest(ServerContext* context) = 0;
+ /// Called after application callback for each synchronous server request
+ virtual void PostSynchronousRequest(ServerContext* context) = 0;
+ };
+ /// Set the global callback object. Can only be called once. Does not take
+ /// ownership of callbacks, and expects the pointed to object to be alive
+ /// until all server objects in the process have been destroyed.
+ static void SetGlobalCallbacks(GlobalCallbacks* callbacks);
+
private:
friend class AsyncGenericService;
friend class AsynchronousService;
diff --git a/src/cpp/server/server.cc b/src/cpp/server/server.cc
index 695e811654..377c1ed167 100644
--- a/src/cpp/server/server.cc
+++ b/src/cpp/server/server.cc
@@ -51,6 +51,22 @@
namespace grpc {
+class DefaultGlobalCallbacks GRPC_FINAL : public Server::GlobalCallbacks {
+ public:
+ void PreSynchronousRequest(ServerContext* context) GRPC_OVERRIDE {}
+ void PostSynchronousRequest(ServerContext* context) GRPC_OVERRIDE {}
+};
+
+static Server::GlobalCallbacks* g_callbacks = nullptr;
+static gpr_once g_once_init_callbacks = GPR_ONCE_INIT;
+
+static void InitGlobalCallbacks() {
+ if (g_callbacks == nullptr) {
+ static DefaultGlobalCallbacks default_global_callbacks;
+ g_callbacks = &default_global_callbacks;
+ }
+}
+
class Server::UnimplementedAsyncRequestContext {
protected:
UnimplementedAsyncRequestContext() : generic_stream_(&server_context_) {}
@@ -220,8 +236,10 @@ class Server::SyncRequest GRPC_FINAL : public CompletionQueueTag {
void Run() {
ctx_.BeginCompletionOp(&call_);
+ g_callbacks->PreSynchronousRequest(&ctx_);
method_->handler()->RunHandler(MethodHandler::HandlerParameter(
&call_, &ctx_, request_payload_, call_.max_message_size()));
+ g_callbacks->PostSynchronousRequest(&ctx_);
request_payload_ = nullptr;
void* ignored_tag;
bool ignored_ok;
@@ -283,6 +301,7 @@ Server::Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned,
server_(CreateServer(max_message_size, compression_options)),
thread_pool_(thread_pool),
thread_pool_owned_(thread_pool_owned) {
+ gpr_once_init(&g_once_init_callbacks, InitGlobalCallbacks);
grpc_server_register_completion_queue(server_, cq_.cq(), nullptr);
}
@@ -304,6 +323,12 @@ Server::~Server() {
delete sync_methods_;
}
+void Server::SetGlobalCallbacks(GlobalCallbacks* callbacks) {
+ GPR_ASSERT(g_callbacks == nullptr);
+ GPR_ASSERT(callbacks != nullptr);
+ g_callbacks = callbacks;
+}
+
bool Server::RegisterService(const grpc::string* host, RpcService* service) {
for (int i = 0; i < service->GetMethodCount(); ++i) {
RpcServiceMethod* method = service->GetMethod(i);