| Home | Trees | Indices | Help |
|
|---|
|
|
1 """GNUmed scripting listener.
2
3 This module implements threaded listening for scripting.
4 """
5 #=====================================================================
6 # $Source: /home/ncq/Projekte/cvs2git/vcs-mirror/gnumed/gnumed/client/pycommon/gmScriptingListener.py,v $
7 __version__ = "$Revision: 1.7 $"
8 __author__ = "K.Hilbert <karsten.hilbert@gmx.net>"
9
10 import sys, time, threading, SimpleXMLRPCServer, select, logging
11
12
13 _log = logging.getLogger('gm.scripting')
14 _log.info(__version__)
15 #=====================================================================
17
18 # FIXME: this should use /var/run/gnumed/xml-rpc-port.pid
19 # FIXME: and store the current port there
20
21 """This class handles how GNUmed listens for external requests.
22
23 It starts an XML-RPC server and forks a thread which
24 listens for incoming requests. Those requests are then
25 handed over to a macro executor and the results handed
26 back to the caller.
27 """
29 # listener thread will regularly try to acquire
30 # this lock, when it succeeds it will quit
31 self._quit_lock = threading.Lock()
32 if not self._quit_lock.acquire(0):
33 _log.error('cannot acquire thread quit lock !?! aborting')
34 import thread
35 raise thread.error("cannot acquire thread quit-lock")
36
37 # check for data every 'poll_interval' seconds
38 self._poll_interval = poll_interval
39 # localhost only for somewhat better security
40 self._listener_address = '127.0.0.1'
41 self._port = int(port)
42 self._macro_executor = macro_executor
43
44 self._server = SimpleXMLRPCServer.SimpleXMLRPCServer(addr=(self._listener_address, self._port), logRequests=False)
45 self._server.register_instance(self._macro_executor)
46 self._server.allow_reuse_address = True
47
48 self._thread = threading.Thread (
49 target = self._process_RPCs,
50 name = self.__class__.__name__
51 )
52 self._thread.setDaemon(True)
53 self._thread.start()
54
55 _log.info('scripting listener started on [%s:%s]' % (self._listener_address, self._port))
56 _log.info('macro executor: %s' % self._macro_executor)
57 _log.info('poll interval: %s seconds', self._poll_interval)
58 #-------------------------------
59 # public API
60 #-------------------------------
62 """Cleanly shut down. Complement to __init__()."""
63
64 if self._thread is None:
65 return
66
67 _log.info('stopping frontend scripting listener thread')
68 self._quit_lock.release()
69 try:
70 # give the worker thread time to terminate
71 self._thread.join(self._poll_interval+5)
72 try:
73 if self._thread.isAlive():
74 _log.error('listener thread still alive after join()')
75 _log.debug('active threads: %s' % threading.enumerate())
76 except:
77 pass
78 except:
79 print sys.exc_info()
80
81 self._thread = None
82
83 try:
84 self._server.socket.shutdown(2)
85 except:
86 _log.exception('cannot cleanly shutdown(5) scripting listener socket')
87
88 try:
89 self._server.socket.close()
90 except:
91 _log.exception('cannot cleanly close() scripting listener socket')
92 #-------------------------------
93 # internal helpers
94 #-------------------------------
96 """The actual thread code."""
97 while 1:
98 if self._quit_lock.acquire(0):
99 break
100 time.sleep(0.35) # give others time to acquire lock
101 if self._quit_lock.acquire(0):
102 break
103 # wait at most self.__poll_interval for new data
104 ready_input_sockets = select.select([self._server.socket], [], [], self._poll_interval)[0]
105 # any input available ?
106 if len(ready_input_sockets) != 0:
107 # we may be in __del__ so we might fail here
108 try:
109 self._server.handle_request()
110 except:
111 print "cannot serve RPC"
112 break
113 if self._quit_lock.acquire(0):
114 break
115 time.sleep(0.25)
116 if self._quit_lock.acquire(0):
117 break
118 else:
119 time.sleep(0.35)
120 if self._quit_lock.acquire(0):
121 break
122
123 # exit thread activity
124 return
125 #=====================================================================
126 # main
127 #=====================================================================
128 if __name__ == "__main__":
129
130 #-------------------------------
134 #-------------------------------
135 if (len(sys.argv) > 1) and (sys.argv[1] == u'test'):
136 import xmlrpclib
137
138 try:
139 listener = cScriptingListener(macro_executor=runner(), port=9999)
140 except:
141 _log.exception('cannot instantiate scripting listener')
142 sys.exit(1)
143
144 s = xmlrpclib.ServerProxy('http://localhost:9999')
145 try:
146 t = s.tell_time()
147 print t
148 except:
149 _log.exception('cannot interact with server')
150
151 listener.shutdown()
152 #=====================================================================
153 # $Log: gmScriptingListener.py,v $
154 # Revision 1.7 2009-01-15 11:34:17 ncq
155 # - improved logging
156 #
157 # Revision 1.6 2008/06/23 21:49:58 ncq
158 # - clean up thread handling
159 #
160 # Revision 1.5 2007/12/12 16:17:16 ncq
161 # - better logger names
162 #
163 # Revision 1.4 2007/12/11 15:39:01 ncq
164 # - use std lib logging
165 #
166 # Revision 1.3 2007/12/03 20:43:53 ncq
167 # - lots of cleanup
168 # - fix/enhance test suite
169 #
170 # Revision 1.2 2004/09/13 08:51:03 ncq
171 # - make sure port is an integer
172 # - start XML RPC server with logRequests=False
173 # - socket allow_reuse_address
174 #
175 # Revision 1.1 2004/02/25 09:30:13 ncq
176 # - moved here from python-common
177 #
178 # Revision 1.3 2004/02/05 23:46:21 ncq
179 # - use serverproxy() instead of server() as is recommended
180 #
181 # Revision 1.2 2004/02/05 18:40:01 ncq
182 # - quit thread if we can't handle_request()
183 #
184 # Revision 1.1 2004/02/02 21:58:20 ncq
185 # - first cut
186 #
187
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Mon Dec 5 03:59:50 2011 | http://epydoc.sourceforge.net |