1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #ifndef _THRIFT_TPROCESSOR_H_
21 #define _THRIFT_TPROCESSOR_H_ 1
22 
23 #include <string>
24 #include <thrift/protocol/TProtocol.h>
25 
26 namespace apache {
27 namespace thrift {
28 
29 /**
30  * Virtual interface class that can handle events from the processor. To
31  * use this you should subclass it and implement the methods that you care
32  * about. Your subclass can also store local data that you may care about,
33  * such as additional "arguments" to these methods (stored in the object
34  * instance's state).
35  */
36 class TProcessorEventHandler {
37 public:
38   virtual ~TProcessorEventHandler() = default;
39 
40   /**
41    * Called before calling other callback methods.
42    * Expected to return some sort of context object.
43    * The return value is passed to all other callbacks
44    * for that function invocation.
45    */
getContext(const char * fn_name,void * serverContext)46   virtual void* getContext(const char* fn_name, void* serverContext) {
47     (void)fn_name;
48     (void)serverContext;
49     return nullptr;
50   }
51 
52   /**
53    * Expected to free resources associated with a context.
54    */
freeContext(void * ctx,const char * fn_name)55   virtual void freeContext(void* ctx, const char* fn_name) {
56     (void)ctx;
57     (void)fn_name;
58   }
59 
60   /**
61    * Called before reading arguments.
62    */
preRead(void * ctx,const char * fn_name)63   virtual void preRead(void* ctx, const char* fn_name) {
64     (void)ctx;
65     (void)fn_name;
66   }
67 
68   /**
69    * Called between reading arguments and calling the handler.
70    */
postRead(void * ctx,const char * fn_name,uint32_t bytes)71   virtual void postRead(void* ctx, const char* fn_name, uint32_t bytes) {
72     (void)ctx;
73     (void)fn_name;
74     (void)bytes;
75   }
76 
77   /**
78    * Called between calling the handler and writing the response.
79    */
preWrite(void * ctx,const char * fn_name)80   virtual void preWrite(void* ctx, const char* fn_name) {
81     (void)ctx;
82     (void)fn_name;
83   }
84 
85   /**
86    * Called after writing the response.
87    */
postWrite(void * ctx,const char * fn_name,uint32_t bytes)88   virtual void postWrite(void* ctx, const char* fn_name, uint32_t bytes) {
89     (void)ctx;
90     (void)fn_name;
91     (void)bytes;
92   }
93 
94   /**
95    * Called when an async function call completes successfully.
96    */
asyncComplete(void * ctx,const char * fn_name)97   virtual void asyncComplete(void* ctx, const char* fn_name) {
98     (void)ctx;
99     (void)fn_name;
100   }
101 
102   /**
103    * Called if the handler throws an undeclared exception.
104    */
handlerError(void * ctx,const char * fn_name)105   virtual void handlerError(void* ctx, const char* fn_name) {
106     (void)ctx;
107     (void)fn_name;
108   }
109 
110 protected:
111   TProcessorEventHandler() = default;
112 };
113 
114 /**
115  * A helper class used by the generated code to free each context.
116  */
117 class TProcessorContextFreer {
118 public:
TProcessorContextFreer(TProcessorEventHandler * handler,void * context,const char * method)119   TProcessorContextFreer(TProcessorEventHandler* handler, void* context, const char* method)
120     : handler_(handler), context_(context), method_(method) {}
~TProcessorContextFreer()121   ~TProcessorContextFreer() {
122     if (handler_ != nullptr)
123       handler_->freeContext(context_, method_);
124   }
unregister()125   void unregister() { handler_ = nullptr; }
126 
127 private:
128   apache::thrift::TProcessorEventHandler* handler_;
129   void* context_;
130   const char* method_;
131 };
132 
133 /**
134  * A processor is a generic object that acts upon two streams of data, one
135  * an input and the other an output. The definition of this object is loose,
136  * though the typical case is for some sort of server that either generates
137  * responses to an input stream or forwards data from one pipe onto another.
138  *
139  */
140 class TProcessor {
141 public:
142   virtual ~TProcessor() = default;
143 
144   virtual bool process(std::shared_ptr<protocol::TProtocol> in,
145                        std::shared_ptr<protocol::TProtocol> out,
146                        void* connectionContext) = 0;
147 
process(std::shared_ptr<apache::thrift::protocol::TProtocol> io,void * connectionContext)148   bool process(std::shared_ptr<apache::thrift::protocol::TProtocol> io, void* connectionContext) {
149     return process(io, io, connectionContext);
150   }
151 
getEventHandler()152   std::shared_ptr<TProcessorEventHandler> getEventHandler() const { return eventHandler_; }
153 
setEventHandler(std::shared_ptr<TProcessorEventHandler> eventHandler)154   void setEventHandler(std::shared_ptr<TProcessorEventHandler> eventHandler) {
155     eventHandler_ = eventHandler;
156   }
157 
158 protected:
159   TProcessor() = default;
160 
161   std::shared_ptr<TProcessorEventHandler> eventHandler_;
162 };
163 
164 /**
165  * This is a helper class to allow std::shared_ptr to be used with handler
166  * pointers returned by the generated handler factories.
167  *
168  * The handler factory classes generated by the thrift compiler return raw
169  * pointers, and factory->releaseHandler() must be called when the handler is
170  * no longer needed.
171  *
172  * A ReleaseHandler object can be instantiated and passed as the second
173  * parameter to a shared_ptr, so that factory->releaseHandler() will be called
174  * when the object is no longer needed, instead of deleting the pointer.
175  */
176 template <typename HandlerFactory_>
177 class ReleaseHandler {
178 public:
ReleaseHandler(const std::shared_ptr<HandlerFactory_> & handlerFactory)179   ReleaseHandler(const std::shared_ptr<HandlerFactory_>& handlerFactory)
180     : handlerFactory_(handlerFactory) {}
181 
operator()182   void operator()(typename HandlerFactory_::Handler* handler) {
183     if (handler) {
184       handlerFactory_->releaseHandler(handler);
185     }
186   }
187 
188 private:
189   std::shared_ptr<HandlerFactory_> handlerFactory_;
190 };
191 
192 struct TConnectionInfo {
193   // The input and output protocols
194   std::shared_ptr<protocol::TProtocol> input;
195   std::shared_ptr<protocol::TProtocol> output;
196   // The underlying transport used for the connection
197   // This is the transport that was returned by TServerTransport::accept(),
198   // and it may be different than the transport pointed to by the input and
199   // output protocols.
200   std::shared_ptr<transport::TTransport> transport;
201 };
202 
203 class TProcessorFactory {
204 public:
205   virtual ~TProcessorFactory() = default;
206 
207   /**
208    * Get the TProcessor to use for a particular connection.
209    *
210    * This method is always invoked in the same thread that the connection was
211    * accepted on.  This generally means that this call does not need to be
212    * thread safe, as it will always be invoked from a single thread.
213    */
214   virtual std::shared_ptr<TProcessor> getProcessor(const TConnectionInfo& connInfo) = 0;
215 };
216 
217 class TSingletonProcessorFactory : public TProcessorFactory {
218 public:
TSingletonProcessorFactory(std::shared_ptr<TProcessor> processor)219   TSingletonProcessorFactory(std::shared_ptr<TProcessor> processor) : processor_(processor) {}
220 
getProcessor(const TConnectionInfo &)221   std::shared_ptr<TProcessor> getProcessor(const TConnectionInfo&) override { return processor_; }
222 
223 private:
224   std::shared_ptr<TProcessor> processor_;
225 };
226 }
227 } // apache::thrift
228 
229 #endif // #ifndef _THRIFT_TPROCESSOR_H_
230