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