Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 import os
00011 import sys
00012 import re
00013 import shutil
00014 import subprocess
00015 
00016 
00017 import roslib
00018 roslib.load_manifest('rocon_hub')
00019 import rospy
00020 import rospkg
00021 try:
00022     import redis
00023 except ImportError:
00024     
00025     sys.exit("\n[ERROR] No python-redis found - 'rosdep install rocon_hub'\n")
00026 
00027 
00028 import utils
00029 
00030 
00031 
00032 
00033 
00034 
00035 class RedisServer:
00036     def __init__(self, parameters):
00037         self._parameters = parameters
00038         self._process = None
00039         self._home_dir = os.path.join(rospkg.get_ros_home(), 'redis', self._parameters['name'].lower().replace(" ", "_"))
00040         self._files = {}
00041         self._files['redis_conf'] = os.path.join(self._home_dir, 'redis.conf')
00042         self._files['redis_conf_local'] = os.path.join(self._home_dir, 'redis.conf.local')
00043         self._files['redis_server_log'] = os.path.join(self._home_dir, 'redis-server.log')
00044         self._server = None
00045 
00046         self._setup()
00047 
00048     def _setup(self):
00049         '''
00050           Clear and configure redis conf, log files in the ros home
00051           directories under a subdirectory styled by the name of this hub.
00052         '''
00053         if os.path.isdir(self._home_dir):
00054             shutil.rmtree(self._home_dir)
00055         os.makedirs(self._home_dir)
00056         rospack = rospkg.RosPack()
00057         redis_conf_template = utils.read_template(os.path.join(rospack.get_path('rocon_hub'), 'redis', 'redis.conf'))
00058         redis_conf_template = instantiate_redis_conf_template(redis_conf_template, self._files['redis_conf_local'])
00059         redis_local_template = utils.read_template(os.path.join(rospack.get_path('rocon_hub'), 'redis', 'redis.conf.local'))
00060         redis_local_template = instantiate_local_conf_template(redis_local_template,
00061                                                                self._parameters['port'],
00062                                                                self._parameters['max_memory'],
00063                                                                self._files['redis_server_log'])
00064         try:
00065             f = open(self._files['redis_conf'], 'w')
00066             f.write(redis_conf_template.encode('utf-8'))
00067         finally:
00068             f.close()
00069         try:
00070             f = open(self._files['redis_conf_local'], 'w')
00071             f.write(redis_local_template.encode('utf-8'))
00072         finally:
00073             f.close()
00074 
00075     def start(self):
00076         '''
00077           Start the server. Also connect, delete all rocon:xxx
00078           variables and reinitialise with specified values.
00079 
00080           Aborts the program if the connection fails.
00081         '''
00082         self._process = subprocess.Popen(["redis-server", self._files['redis_conf']])
00083         pool = redis.ConnectionPool(host='localhost', port=int(self._parameters['port']), db=0)
00084         no_attempts = 5
00085         count = 0
00086         while count < no_attempts:
00087             try:
00088                 self._server = redis.Redis(connection_pool=pool)
00089                 rocon_keys = self._server.keys("rocon:*")
00090                 pattern = re.compile("rocon:*")
00091                 keys_to_delete = []
00092                 for key in rocon_keys:
00093                     if pattern.match(key):
00094                         keys_to_delete.append(key)
00095                 pipe = self._server.pipeline()
00096                 if len(keys_to_delete) != 0:
00097                     pipe.delete(*keys_to_delete)  
00098                 pipe.set("rocon:hub:index", 0)
00099                 pipe.set("rocon:hub:name", self._parameters['name'])
00100                 pipe.execute()
00101                 rospy.loginfo("Hub : reset hub variables on the redis server.")
00102                 break
00103             except redis.ConnectionError:
00104                 count += 1
00105                 if count == no_attempts:
00106                     self.shutdown()
00107                     sys.exit(utils.logfatal("Hub : could not connect to the redis server - is it running?"))
00108                 else:
00109                     rospy.sleep(0.1)
00110 
00111     def shutdown(self):
00112         '''
00113           Clears rocon: keys on the server.
00114         '''
00115         try:
00116             rocon_keys = self._server.keys("rocon:*")
00117             pattern = re.compile("rocon:*")
00118             keys_to_delete = []
00119             for key in rocon_keys:
00120                 if pattern.match(key):
00121                     keys_to_delete.append(key)
00122             pipe = self._server.pipeline()
00123             if len(keys_to_delete) != 0:
00124                 pipe.delete(*keys_to_delete)  
00125             pipe.execute()
00126             rospy.logdebug("Hub : clearing hub variables on the redis server.")
00127         except redis.ConnectionError:
00128             pass
00129         self._process.terminate()
00130 
00131 
00132 
00133 
00134 
00135 
00136 def instantiate_redis_conf_template(template, local_conf_filename):
00137     '''
00138       Variable substitution in a template file.
00139 
00140       @param local_conf_filename : where to find the local redis configuration file
00141       @type string
00142     '''
00143     return template % locals()
00144 
00145 
00146 def instantiate_local_conf_template(template, port, max_memory, logfile):
00147     '''
00148       Variable substitution in a template file.
00149 
00150       @param port : port on which the server will run
00151       @type int
00152       @param pid_file : pathname to where the pid file will be stored
00153       @type string
00154       @param max_memory: how much memory to allocate to the redis server in bytes
00155       @type string (e.g. 10mb)
00156     '''
00157     return template % locals()
00158 
00159 if __name__ == "__main__":
00160     pool = redis.ConnectionPool(host='localhost', port='6380', db=0)
00161     try:
00162         print "dude"
00163     except redis.exceptions.ConnectionError:
00164         print "err"