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