1 """
2 __version__ = '$Revision: 1.3 $'
3 __date__ = '$Date: 2004-11-24 20:15:11 +0000 (Wed, 24 Nov 2004) $'
4 __author__ = 'Peter Arwanitis'
5 __license__ = 'pyBlaster is under LGPL, see http://www.xmlBlaster.org/license.html'
6
7 last change by $Author: ruff $
8
9 """
10
11 # mixin classes
12 from BaseService import BaseService
13 from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
14 from ResponsiveThreadingTCPServer import ResponsiveThreadingTCPServer
15
16 # helper function
17 from socket import gethostname
18
19 import threading
20
21 import sys
22
23 # XMLRPC Server Mixin ###########################################################
24
25 class ThreadedXMLRPCServer(SimpleXMLRPCServer, BaseService):
26 """First and very simple try, but thread cannot be regulary joined,
27 cause of blocking get_request()
28 """
29
30 def __init__(self, port, dispatcherClass, callbackInstance):
31
32 # INIT Superclasses without logging
33 SimpleXMLRPCServer.__init__(self, (gethostname(), port), logRequests=0)
34 BaseService.__init__(self, 'XMLRPCService')
35
36 # Connect the dispatcher
37 dispatcher = dispatcherClass(callbackInstance)
38
39 # Register the dispatcher
40 self.register_instance(dispatcher)
41 #print "[XMLRPCServer.init]", self
42
43 def run(self) :
44
45 print "%s starts" % (self.getName(),)
46 count = 0
47 while self.isNotStopped():
48 sys.stdout.flush()
49 if count % 100 == 0: print '.'
50 count += 1
51 self.handle_request()
52
53
54 print "%s ends" % (self.getName(),)
55
56
57
58 class ResponsiveThreadedXMLRPCServer(threading.Thread):
59 """Reimplement (mixin) MasterControlThread with SimpleXMLRPCRequestHandler
60
61 To bypass blocking get_request implementation, that cannot IMHO be joined.
62 Please read the doc in ResponsiveThreadingTCPServer
63
64 Thanks to Robin Munn
65
66 The dispatcherClass is a way to restrict registering a complete instance,
67 and the possibility to facade the real implementation, to get a stable
68 interface.
69
70 Example for an dispatcherClass to communicate with XmlBlaster
71 It is simple :-) and you have a single place of connecting your code with
72 the interface to XMLRPC.
73
74 This code is living part of the pyBlaster project
75 (http://www.xmlblaster.org/index.html)
76 Look at the news dating [Apr 13, 2003]
77
78 have a nice day
79 Peter
80 (=PA=)
81
82 # Dispatcher Class (XMLRPC Server Interface) ###############################
83
84 class XB_CallbackDispatcher:
85 def __init__(self, xb_CallbackInstance):
86 self.xb_CallbackInstance=xb_CallbackInstance
87 def update(self, *attrs):
88 return self.xb_CallbackInstance.update(*attrs)
89 def updateOneway(self, *attrs):
90 return self.xb_CallbackInstance.updateOneway(*attrs)
91 def ping(self, *attrs):
92 return self.xb_CallbackInstance.ping(*attrs)
93
94 """
95
96 def __init__(self, port, dispatcherClass, callbackInstance, logRequests=0, timeout=5.0):
97
98 # from MasterControlThread
99 threading.Thread.__init__(self)
100 self.port = port
101 self.timeout = timeout
102 self.lock = threading.RLock()
103
104 # from SimpleXMLRPCServer
105 self.funcs = {}
106 self.logRequests = logRequests
107 self.instance = None
108
109 # Connect the dispatcher
110 dispatcher = dispatcherClass(callbackInstance)
111
112 # Register the dispatcher
113 self.register_instance(dispatcher)
114 #print "[XMLRPCServer.init]", self
115
116
117 print "%s starts" % (self.getName(),)
118 # encapsulate this server to get discrete control over this thread, in the thread
119 self.server = ResponsiveThreadingTCPServer((gethostname(), self.port), SimpleXMLRPCRequestHandler, self.lock, self.timeout)
120
121
122 def getConnectedPort(self):
123 # thanks to Doug Palmer
124 return self.server.socket.getsockname()[1]
125
126
127 def register_instance(self, instance):
128 # from SimpleXMLRPCServer
129 self.instance = instance
130
131 def register_function(self, function, name = None):
132 # from SimpleXMLRPCServer
133 if name is None:
134 name = function.__name__
135 self.funcs[name] = function
136
137 def run(self):
138 # from ResponsiveThreadingTCPServer.MasterControlThread
139 #print "%s starts" % (self.getName(),)
140 #self.server = ResponsiveThreadingTCPServer((gethostname(), self.port), SimpleXMLRPCRequestHandler, self.lock, self.timeout)
141
142 # Routing
143 self.server.logRequests = self.logRequests # to control RequestHandler behaviour
144 self.server.instance = self.instance
145 self.server.funcs = self.funcs
146
147 # Note: Five seconds timeout instead of a minute, for testing.
148 self.thread = threading.Thread(target=self.server.serve_forever)
149 self.thread.start()
150 print "%s ends" % (self.getName(),)
151
152 def stop(self):
153 # from ResponsiveThreadingTCPServer.MasterControlThread
154 # Tell the server it's time to shut down
155 self.server.lock.acquire()
156 self.server.QuitFlag = 1
157 self.server.lock.release()
158 print "Waiting for server to shut down (could take several seconds, till %0.2f seconds)..." % self.timeout
159 self.thread.join()
160
161
162
163
syntax highlighted by Code2HTML, v. 0.9.1