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 module thrift.protocol.processor;
20 
21 // Use selective import once DMD @@BUG314@@ is fixed.
22 import std.variant /+ : Variant +/;
23 import thrift.protocol.base;
24 import thrift.transport.base;
25 
26 /**
27  * A processor is a generic object which operates upon an input stream and
28  * writes to some output stream.
29  *
30  * The definition of this object is loose, though the typical case is for some
31  * sort of server that either generates responses to an input stream or
32  * forwards data from one pipe onto another.
33  *
34  * An implementation can optionally allow one or more TProcessorEventHandlers
35  * to be attached, providing an interface to hook custom code into the
36  * handling process, which can be used e.g. for gathering statistics.
37  */
38 interface TProcessor {
39   ///
40   bool process(TProtocol iprot, TProtocol oprot,
41     Variant connectionContext = Variant()
42   ) in {
43     assert(iprot);
44     assert(oprot);
45   }
46 
47   ///
48   final bool process(TProtocol prot, Variant connectionContext = Variant()) {
49     return process(prot, prot, connectionContext);
50   }
51 }
52 
53 /**
54  * Handles events from a processor.
55  */
56 interface TProcessorEventHandler {
57   /**
58    * Called before calling other callback methods.
59    *
60    * Expected to return some sort of »call context«, which is passed to all
61    * other callbacks for that function invocation.
62    */
63   Variant createContext(string methodName, Variant connectionContext);
64 
65   /**
66    * Called when handling the method associated with a context has been
67    * finished – can be used to perform clean up work.
68    */
69   void deleteContext(Variant callContext, string methodName);
70 
71   /**
72    * Called before reading arguments.
73    */
74   void preRead(Variant callContext, string methodName);
75 
76   /**
77    * Called between reading arguments and calling the handler.
78    */
79   void postRead(Variant callContext, string methodName);
80 
81   /**
82    * Called between calling the handler and writing the response.
83    */
84   void preWrite(Variant callContext, string methodName);
85 
86   /**
87    * Called after writing the response.
88    */
89   void postWrite(Variant callContext, string methodName);
90 
91   /**
92    * Called when handling a one-way function call is completed successfully.
93    */
94   void onewayComplete(Variant callContext, string methodName);
95 
96   /**
97    * Called if the handler throws an undeclared exception.
98    */
99   void handlerError(Variant callContext, string methodName, Exception e);
100 }
101 
102 struct TConnectionInfo {
103   /// The input and output protocols.
104   TProtocol input;
105   TProtocol output; /// Ditto.
106 
107   /// The underlying transport used for the connection
108   /// This is the transport that was returned by TServerTransport.accept(),
109   /// and it may be different than the transport pointed to by the input and
110   /// output protocols.
111   TTransport transport;
112 }
113 
114 interface TProcessorFactory {
115   /**
116    * Get the TProcessor to use for a particular connection.
117    *
118    * This method is always invoked in the same thread that the connection was
119    * accepted on, which is always the same thread for all current server
120    * implementations.
121    */
122   TProcessor getProcessor(ref const(TConnectionInfo) connInfo);
123 }
124 
125 /**
126  * The default processor factory which always returns the same instance.
127  */
128 class TSingletonProcessorFactory : TProcessorFactory {
129   /**
130    * Creates a new instance.
131    *
132    * Params:
133    *   processor = The processor object to return from getProcessor().
134    */
this(TProcessor processor)135   this(TProcessor processor) {
136     processor_ = processor;
137   }
138 
getProcessor(ref const (TConnectionInfo)connInfo)139   override TProcessor getProcessor(ref const(TConnectionInfo) connInfo) {
140     return processor_;
141   }
142 
143 private:
144   TProcessor processor_;
145 }
146