1 /***************************************************************************
2            ulxr_mtrpc_server.h  -  a simple multithreaded rpc server
3                              -------------------
4     begin                : Wed Oct 10 2003
5     copyright            : (C) 2002-2007 by Ewald Arnold
6     email                : ulxmlrpcpp@ewald-arnold.de
7 
8     $Id: ulxr_mtrpc_server.h 1076 2007-09-02 08:07:32Z ewald-arnold $
9 
10  ***************************************************************************/
11 
12 /**************************************************************************
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU Lesser General Public License as
16  * published by the Free Software Foundation; either version 2 of the License,
17  * or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27  *
28  ***************************************************************************/
29 
30 #ifndef ULXR_MTRPC_SERVER_H
31 #define ULXR_MTRPC_SERVER_H
32 
33 #include <ulxmlrpcpp/ulxmlrpcpp.h>  // always first header
34 
35 #ifdef ULXR_MULTITHREADED
36 
37 #include <vector>
38 
39 #include <ulxmlrpcpp/ulxr_dispatcher.h>
40 #include <ulxmlrpcpp/ulxr_method_adder.h>
41 
42 #ifdef __WIN32__
43 #include <process.h>
44 #include <windows.h>
45 #endif
46 
47 #ifdef __unix__
48 #include <pthread.h>
49 #endif
50 
51 
52 namespace ulxr {
53 
54 
55 class Exception;
56 class Protocol;
57 
58 /** A multi threaded xml rpc server.
59   * @ingroup grp_ulxr_rpc
60   */
61 class ULXR_API_DECL0 MultiThreadRpcServer : public MethodAdder
62 {
63   public:
64     class ThreadData;
65 
66     typedef void* (*ThreadLoopFunction)(ThreadData*);
67 
68   /** Constructs the rpc server.
69     * @param  prot        communication object
70     * @param  num         number of simultanous threads to handle requests
71     * @param   wbxml_mode  true: data is sent as wbxml
72     */
73     MultiThreadRpcServer(Protocol *prot, unsigned num, bool wbxml_mode = false);
74 
75   /** Destrcuts the rpc server.
76     */
77     virtual ~MultiThreadRpcServer();
78 
79   /** Lauch the rpc server threads which wait for requests.
80     * @return  number of threads started
81     */
82     unsigned dispatchAsync();
83 
84   /** Gets the number of installed threads.
85     * @return number of threads
86     */
87     unsigned numThreads() const;
88 
89   /** Terminates all threads.
90     * The threads only get a message and must terminate themselves.
91     * @param time  planned: time in ms to wait before killing.
92     */
93     void terminateAllThreads(unsigned time = 0);
94 
95   /** Signals termination and shuts down all ports.
96     * This is a rather rude way to terminate to stop the servers
97     * @param time  planned: time in ms to wait before killing.
98     */
99     void shutdownAllThreads(unsigned time = 0);
100 
101   /** Waits for all threads to complete.
102     * @param  term  true: signal all threads to shut down as soon as possible.
103     * @param  stat  true: print some statistical data to stdout.
104     */
105     void waitAsync(bool term, bool stat = false);
106 
107  /** Adds a user defined (static) method to the dispatcher.
108    * You access a remote method by sending the "official" name. Sometimes
109    * a method accepts different parameter sets (overloading in C++).
110    * In this case you add the according signature. Finally you can
111    * add a description to show the usage of this method.
112    * @param  adr            the pointer to the implementation of the method
113    * @param  ret_signature  the signature of the return value
114    * @param  name           the name of the method
115    * @param  signature      the signature of the parameters
116    * @param  help           short usage description
117    */
118    void addMethod (MethodAdder::StaticMethodCall_t adr,
119                    const CppString &ret_signature,
120                    const CppString &name,
121                    const CppString &signature,
122                    const CppString &help);
123 
124  /** Adds a user defined (dynamic) method to the dispatcher.
125    * You access a remote method by sending the "official" name. Sometimes
126    * a method accepts different parameter sets (overloading in C++).
127    * In this case you add the according signature. Finally you can
128    * add a description to show the usage of this method.
129    * @param  wrapper        the pointer to the wrapper to the method.
130    *                        Important: Dispatcher owns now and deletes this wrapper object!
131    * @param  ret_signature  the signature of the return value
132    * @param  name           the name of the method
133    * @param  signature      the signature of the parameters
134    * @param  help           short usage description
135    */
136    void addMethod (MethodAdder::DynamicMethodCall_t wrapper,
137                    const CppString &ret_signature,
138                    const CppString &name,
139                    const CppString &signature,
140                    const CppString &help);
141 
142  /** Adds a system internal method to the dispatcher.
143    * You access a remote method by sending the "official" name. Sometimes
144    * a method accepts different parameter sets (overloading in C++).
145    * In this case you add the according signature. Finally you can
146    * add a description to show the usage of this method.
147    * @param  adr            the pointer to the implementation of the method
148    * @param  ret_signature  the signature of the return value
149    * @param  name           the name of the method
150    * @param  signature      the signature of the parameters
151    * @param  help           short usage description
152    */
153    void addMethod (MethodAdder::SystemMethodCall_t adr,
154                    const CppString &ret_signature,
155                    const CppString &name,
156                    const CppString &signature,
157                    const CppString &help);
158 
159  /** Adds a user defined (static) method to the dispatcher.
160    * You access a remote method by sending the "official" name. Sometimes
161    * a method accepts different parameter sets (overloading in C++).
162    * In this case you add the according signature. Finally you can
163    * add a description to show the usage of this method.
164    * @param  adr            the pointer to the implementation of the method
165    * @param  ret_signature  the signature of the return value
166    * @param  name           the name of the method
167    * @param  signature      the signature of the parameters
168    * @param  help           short usage description
169    */
170    void addMethod (MethodAdder::StaticMethodCall_t adr,
171                    const Signature &ret_signature,
172                    const CppString &name,
173                    const Signature &signature,
174                    const CppString &help);
175 
176  /** Adds a user defined (dynamic) method to the dispatcher.
177    * You access a remote method by sending the "official" name. Sometimes
178    * a method accepts different parameter sets (overloading in C++).
179    * In this case you add the according signature. Finally you can
180    * add a description to show the usage of this method.
181    * @param  wrapper        the pointer to the wrapper to the method.
182    *                        Important: Dispatcher owns now and deletes this wrapper object!
183    * @param  ret_signature  the signature of the return value
184    * @param  name           the name of the method
185    * @param  signature      the signature of the parameters
186    * @param  help           short usage description
187    */
188    void addMethod (MethodAdder::DynamicMethodCall_t wrapper,
189                    const Signature &ret_signature,
190                    const CppString &name,
191                    const Signature &signature,
192                    const CppString &help);
193 
194  /** Adds a system internal method to the dispatcher.
195    * You access a remote method by sending the "official" name. Sometimes
196    * a method accepts different parameter sets (overloading in C++).
197    * In this case you add the according signature. Finally you can
198    * add a description to show the usage of this method.
199    * @param  adr            the pointer to the implementation of the method
200    * @param  ret_signature  the signature of the return value
201    * @param  name           the name of the method
202    * @param  signature      the signature of the parameters
203    * @param  help           short usage description
204    */
205    void addMethod (MethodAdder::SystemMethodCall_t adr,
206                    const Signature &ret_signature,
207                    const CppString &name,
208                    const Signature &signature,
209                    const CppString &help);
210 
211  /** Removes a method if available
212    * @param name   method name
213    */
214    void removeMethod(const CppString &name);
215 
216   protected:
217 
218  /** Forwards error that happen within threads.
219    * @param ex   Exception that occured
220    */
221    virtual void forwardThreadedError(const Exception &ex) const;
222 
223   /* The threaded function that does the work.
224    * @param  conn  pointer to communication object
225    * @param  td    pointer to working data
226    */
227    void *serverLoop(Protocol *protocol, ThreadData *td);
228 
229  /** Prints some statistics about the running threads.
230    */
231    void printStatistics() const;
232 
233  /** Called when the thread is started and enters the server loop
234   */
235    virtual void enterLoop();
236 
237  /** Called when the server loop is terminating
238   */
239    virtual void leaveLoop();
240 
241  /** Processes a call after it has been recieved and before it is dispatched.
242    * @param  call   last received call
243    */
244    virtual void preProcessCall(MethodCall &call);
245 
246  /** Processes a method response before it is sent back.
247    * @param  resp   response to send back
248    */
249    virtual void preProcessResponse(MethodResponse &resp);
250 
251   private:
252 
253  /** Helper method to start a thread.
254    * @param td  pointer to thread data
255    */
256    static void *startThread(ThreadData *td);
257 
258  /** Deletes all allocated thread objects.
259    */
260    void releaseThreads();
261 
262    typedef void *(Thread_t) (ThreadData*);
263 
264    std::vector<ThreadData*>       threads;
265    Dispatcher                     dispatcher;
266    bool                           wbxml_mode;
267 
268  private:
269 
270    // forbid them all due to internal pointers
271    MultiThreadRpcServer(const MultiThreadRpcServer&);
272    MultiThreadRpcServer& operator=(const MultiThreadRpcServer&);
273 };
274 
275 
276 }  // namespace ulxr
277 
278 
279 #endif // ULXR_MULTITHREADED
280 
281 
282 #endif // ULXR_MTRPC_SERVER_H
283