///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2019- Equinor ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License at // for more details. // ////////////////////////////////////////////////////////////////////////////////// #pragma once #include #include #include #include #include #include #include using grpc::CompletionQueue; using grpc::ServerAsyncReader; using grpc::ServerAsyncResponseWriter; using grpc::ServerAsyncWriter; using grpc::ServerCompletionQueue; using grpc::ServerContext; using grpc::Status; //================================================================================================== // // Base class for all gRPC-callbacks // //================================================================================================== class RiaGrpcCallbackInterface { public: enum CallState { CREATE_HANDLER, INIT_REQUEST_STARTED, INIT_REQUEST_COMPLETED, PROCESS_REQUEST, FINISH_REQUEST }; public: inline RiaGrpcCallbackInterface(); virtual ~RiaGrpcCallbackInterface() {} virtual QString name() const = 0; virtual RiaGrpcCallbackInterface* createNewFromThis() const = 0; virtual void createRequestHandler( ServerCompletionQueue* completionQueue ) = 0; virtual void onInitRequestStarted() {} virtual void onInitRequestCompleted() {} virtual void onProcessRequest() = 0; virtual void onFinishRequest() {} // Callbacks that touch no application state can be served directly on the gRPC completion // queue thread, instead of being queued for the main thread. This keeps liveness requests // answerable while the main thread is occupied by a long-running request. Only override for // methods that read no project/PDM data - anything touching the data model must be processed // on the main thread. virtual bool runsOnServerThread() const { return false; } inline CallState callState() const; inline const Status& status() const; inline void setNextCallState( CallState state ); protected: CallState m_state; Status m_status; }; //================================================================================================== // // Templated gRPC-callback base class // //================================================================================================== template class RiaGrpcServiceCallback : public RiaGrpcCallbackInterface { public: RiaGrpcServiceCallback( ServiceT* service ); ~RiaGrpcServiceCallback() override; QString name() const override; const RequestT& request() const; ReplyT& reply(); protected: virtual QString methodType() const = 0; protected: ServiceT* m_service; RequestT m_request; ReplyT m_reply; }; //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template RiaGrpcServiceCallback::~RiaGrpcServiceCallback() { } //================================================================================================== // // Templated gRPC-callback for non-streaming services // //================================================================================================== template class RiaGrpcUnaryCallback : public RiaGrpcServiceCallback { public: using ResponseWriterT = ServerAsyncResponseWriter; using MethodImplT = std::function; using MethodRequestT = std::function< void( ServiceT&, ServerContext*, RequestT*, ResponseWriterT*, CompletionQueue*, ServerCompletionQueue*, void* )>; RiaGrpcUnaryCallback( ServiceT* service, MethodImplT methodImpl, MethodRequestT methodRequest, bool runsOnServerThread = false ); RiaGrpcCallbackInterface* createNewFromThis() const override; void createRequestHandler( ServerCompletionQueue* completionQueue ) override; void onProcessRequest() override; bool runsOnServerThread() const override { return m_runsOnServerThread; } protected: QString methodType() const override; private: ServerContext m_context; ResponseWriterT m_responder; MethodImplT m_methodImpl; MethodRequestT m_methodRequest; bool m_runsOnServerThread; }; //================================================================================================== // // Templated server->client *streaming* gRPC-callback calling service implementation callbacks // // The streaming callback needs a state handler for setting up and maintaining order. // // A fully functional state handler for server->client streaming needs to implement the following methods: // 1. Default Constructor // 2. grpc::Status init(const grpc::Message* request) // //================================================================================================== template class RiaGrpcServerToClientStreamCallback : public RiaGrpcServiceCallback { public: using ResponseWriterT = ServerAsyncWriter; using MethodImplT = std::function; using MethodRequestT = std::function< void( ServiceT&, ServerContext*, RequestT*, ResponseWriterT*, CompletionQueue*, ServerCompletionQueue*, void* )>; RiaGrpcServerToClientStreamCallback( ServiceT* service, MethodImplT methodImpl, MethodRequestT methodRequest, StateHandlerT* stateHandler ); RiaGrpcCallbackInterface* createNewFromThis() const override; void createRequestHandler( ServerCompletionQueue* completionQueue ) override; void onInitRequestCompleted() override; void onProcessRequest() override; protected: QString methodType() const override; private: ServerContext m_context; ResponseWriterT m_responder; MethodImplT m_methodImpl; MethodRequestT m_methodRequest; std::unique_ptr m_stateHandler; }; //================================================================================================== // // Templated client->server *streaming* gRPC-callback calling service implementation callbacks // // The streaming callback needs a state handler for setting up and maintaining order. // // A fully functional state handler for client->server streaming needs to implement the following methods: // 1. Default Constructor // 2. grpc::Status init(const grpc::Message* request) // 3. void finish() any updates required after completion // //================================================================================================== template class RiaGrpcClientToServerStreamCallback : public RiaGrpcServiceCallback { public: using RequestReaderT = ServerAsyncReader; using MethodImplT = std::function; using MethodRequestT = std::function; RiaGrpcClientToServerStreamCallback( ServiceT* service, MethodImplT methodImpl, MethodRequestT methodRequest, StateHandlerT* stateHandler ); RiaGrpcCallbackInterface* createNewFromThis() const override; void createRequestHandler( ServerCompletionQueue* completionQueue ) override; void onInitRequestStarted() override; void onInitRequestCompleted() override; void onProcessRequest() override; void onFinishRequest() override; protected: QString methodType() const override; private: ServerContext m_context; RequestReaderT m_reader; MethodImplT m_methodImpl; MethodRequestT m_methodRequest; std::unique_ptr m_stateHandler; }; #include "RiaGrpcCallbacks.inl"