Package node_manager_fkie :: Module launch_server_handler
[frames] | no frames]

Source Code for Module node_manager_fkie.launch_server_handler

  1  # Software License Agreement (BSD License) 
  2  # 
  3  # Copyright (c) 2012, Fraunhofer FKIE/US, Alexander Tiderko 
  4  # All rights reserved. 
  5  # 
  6  # Redistribution and use in source and binary forms, with or without 
  7  # modification, are permitted provided that the following conditions 
  8  # are met: 
  9  # 
 10  #  * Redistributions of source code must retain the above copyright 
 11  #    notice, this list of conditions and the following disclaimer. 
 12  #  * Redistributions in binary form must reproduce the above 
 13  #    copyright notice, this list of conditions and the following 
 14  #    disclaimer in the documentation and/or other materials provided 
 15  #    with the distribution. 
 16  #  * Neither the name of Fraunhofer nor the names of its 
 17  #    contributors may be used to endorse or promote products derived 
 18  #    from this software without specific prior written permission. 
 19  # 
 20  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 21  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 22  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 23  # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 24  # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 25  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 26  # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 27  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 28  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 29  # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 30  # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 31  # POSSIBILITY OF SUCH DAMAGE. 
 32   
 33  import time 
 34  import socket 
 35  import random 
 36  import threading 
 37  import xmlrpclib 
 38   
 39  from python_qt_binding import QtCore 
 40  import rospy 
 41   
42 -class LaunchServerHandler(QtCore.QObject):
43 ''' 44 A class to retrieve the state of launch servers. To retrieve the state a new 45 thread will be created. 46 ''' 47 launch_server_signal = QtCore.Signal(str, int, list) 48 ''' 49 @ivar: launch_server_signal is a signal (serveruri, pid, nodes), which is emitted, if a info from 50 launch server was successful retrieved. 51 ''' 52 error_signal = QtCore.Signal(str, str) 53 ''' 54 @ivar: error_signal is a signal (serveruri, error message), which is emitted, 55 if an error while retrieving a launch server info was occurred. 56 ''' 57
58 - def __init__(self):
59 QtCore.QObject.__init__(self) 60 self.__updateThreads = {} 61 self.__requestedUpdates = {} 62 self._lock = threading.RLock()
63
64 - def stop(self):
65 print " Shutdown launch update threads..." 66 self.__requestedUpdates.clear() 67 for key, thread in self.__updateThreads.iteritems(): 68 thread.join(3) 69 print " Launch update threads are off!"
70
71 - def updateLaunchServerInfo(self, serveruri, delayed_exec=0.0):
72 ''' 73 This method starts a thread to get the informations about the launch server by 74 the given RCP uri of the launch server. If all informations are 75 retrieved, a C{launch_server_signal} of this class will be emitted. If for given 76 serveruri a thread is already running, it will be inserted to the requested 77 updates. For the same serveruri only one requested update can be stored. 78 On update error the requested update will be ignored. 79 This method is thread safe. 80 81 @param serveruri: the URI of the remote launch server 82 @type serveruri: C{str} 83 @param delayed_exec: Delay the execution of the request for given seconds. 84 @type delayed_exec: C{float} 85 ''' 86 with self._lock: 87 try: 88 if (self.__updateThreads.has_key(serveruri)): 89 self.__requestedUpdates[serveruri] = delayed_exec 90 else: 91 self.__create_update_thread(serveruri, delayed_exec) 92 except: 93 pass
94
95 - def _on_launch_server_info(self, serveruri, pid, nodes):
96 self.launch_server_signal.emit(serveruri, pid, nodes) 97 self.__handle_requests(serveruri)
98
99 - def _on_error(self, serveruri, error):
100 self.error_signal.emit(serveruri, error) 101 self.__handle_requests(serveruri)
102
103 - def __handle_requests(self, serveruri):
104 with self._lock: 105 try: 106 thread = self.__updateThreads.pop(serveruri) 107 del thread 108 delayed_exec = self.__requestedUpdates.pop(serveruri) 109 self.__create_update_thread(serveruri, delayed_exec) 110 except KeyError: 111 # import traceback 112 # print traceback.format_exc() 113 pass 114 except: 115 import traceback 116 print traceback.format_exc()
117
118 - def __create_update_thread(self, serveruri, delayed_exec):
119 upthread = LaunchServerUpdateThread(serveruri, delayed_exec) 120 self.__updateThreads[serveruri] = upthread 121 upthread.launch_server_signal.connect(self._on_launch_server_info) 122 upthread.error_signal.connect(self._on_error) 123 upthread.start()
124 125
126 -class LaunchServerUpdateThread(QtCore.QObject, threading.Thread):
127 ''' 128 A thread to retrieve the list of pid and nodes from launch server and publish 129 it by sending a QT signal. 130 ''' 131 launch_server_signal = QtCore.Signal(str, int, list) 132 error_signal = QtCore.Signal(str, str) 133
134 - def __init__(self, launch_serveruri, delayed_exec=0.0, parent=None):
135 QtCore.QObject.__init__(self) 136 threading.Thread.__init__(self) 137 self._launch_serveruri = launch_serveruri 138 self._delayed_exec = delayed_exec 139 self.setDaemon(True)
140
141 - def run(self):
142 ''' 143 ''' 144 try: 145 delay = self._delayed_exec+0.5+random.random() 146 time.sleep(delay) 147 socket.setdefaulttimeout(25) 148 server = xmlrpclib.ServerProxy(self._launch_serveruri) 149 code, msg, pid = server.get_pid() 150 code, msg, nodes = server.get_node_names() 151 self.launch_server_signal.emit(self._launch_serveruri, pid, nodes) 152 except: 153 import traceback 154 # print traceback.print_exc() 155 formatted_lines = traceback.format_exc().splitlines() 156 rospy.logwarn("Connection to launch server @ %s failed:\n\t%s", str(self._launch_serveruri), formatted_lines[-1]) 157 #'print "request failed", self._monitoruri 158 self.error_signal.emit(self._launch_serveruri, formatted_lines[-1]) 159 finally: 160 if not socket is None: 161 socket.setdefaulttimeout(None)
162