def update(self, remote_connections, unique_name): ''' Computes a new pulled interface from the incoming connections list and returns two dictionaries - removed and newly added pulls so the watcher thread can take appropriate action ((un)registrations). This is run in the watcher thread (warning: take care - other additions come from ros service calls in different threads!) @param remote_gateway_hub_index : full gateway-hub database index to parse @type gateway hash names keyed into a dic with a list of their hubs ''' # SLOW, EASY METHOD # Totally regenerate a new pulled interface, compare with old pulled = utils.create_empty_connection_type_dictionary() new_pulls = utils.create_empty_connection_type_dictionary() removed_pulls = utils.create_empty_connection_type_dictionary() diff = lambda l1,l2: [x for x in l1 if x not in l2] # diff of lists self._lock.acquire() # Totally regenerate a new pulled interface, compare with old for remote_gateway in remote_connections.keys(): connections = remote_connections[remote_gateway] for connection_type in connections: for connection in connections[connection_type]: pulled[connection_type].extend(self._generate_pulls(connection.rule.type, connection.rule.name, connection.rule.node, remote_gateway, unique_name)) for connection_type in utils.connection_types: new_pulls[connection_type] = diff(pulled[connection_type], self.pulled[connection_type]) removed_pulls[connection_type] = diff(self.pulled[connection_type], pulled[connection_type]) self.pulled = copy.deepcopy(pulled) self._lock.release() return new_pulls, removed_pulls
def __init__(self, default_rule_blacklist, default_rules): ''' Initialises the public interface @param default_rule_blacklist : connection type keyed dictionary of rules @type str keyed dictionary of gateway_msgs.msg.Rule[] @param default_rules : connection type keyed dictionary of rules @type str keyed dictionary of gateway_msgs.msg.Rule[] ''' # List of rules to be monitored and (un)advertised as they # become (un)available self.watchlist = utils.create_empty_connection_type_dictionary() # Default rules that cannot be advertised - used in AdvertiseAll mode self._default_blacklist = default_rule_blacklist # Default + custom blacklist - used in AdvertiseAll mode self.blacklist = self._default_blacklist # list of fully qualified connections currently being advertised self.public = utils.create_empty_connection_type_dictionary() self.advertise_all_enabled = False self.lock = threading.Lock() # Load up static rules. for connection_type in utils.connection_types: for rule in default_rules[connection_type]: self.add_rule(rule)
def update(self, connections): ''' Checks a list of rules and determines which ones should be added/removed to the public interface. Modifies the public interface accordingly, and returns the list of rules to the gateway for hub operations @param rules: the list of rules available locally @type dict of lists of Rule objects @return: new public connections, as well as connections to be removed @rtype: Connection[], Connection[] ''' # SLOW, EASY METHOD public = utils.create_empty_connection_type_dictionary() new_public = utils.create_empty_connection_type_dictionary() removed_public = utils.create_empty_connection_type_dictionary() diff = lambda l1, l2: [x for x in l1 if x not in l2] # diff of lists for connection_type in connections: for connection in connections[connection_type]: if self._allowRule(connection.rule): public[connection_type].append(connection) new_public[connection_type] = diff(public[connection_type], self.public[connection_type]) removed_public[connection_type] = diff( self.public[connection_type], public[connection_type]) self.lock.acquire() self.public = public self.lock.release() return new_public, removed_public
def __init__(self, default_rule_blacklist, default_rules, all_targets): ''' @param default_rule_blacklist : used when in flip/pull all mode @type dictionary of gateway @param default_rules : static rules to flip/pull on startup @type gateway_msgs.msg.RemoteRule[] @param all_targets : static flip/pull all targets to flip/pull to on startup @type string[] ''' # Rules that are active, ie have been flipped or pulled from remote gateways # keys are connection_types, elements are lists of RemoteRule objects # This gets aliased to self.flipped or self.pulled as necessary in # the subclasses self.active = utils.create_empty_connection_type_dictionary() # Default rules used in the xxxAll modes self._default_blacklist = default_rule_blacklist # dictionary of gateway-gateway_msgs.msg.Rule lists, not RemoteRules! # keys are connection_types, elements are lists of gateway_msgs.msg.RemoteRule objects self.watchlist = utils.create_empty_connection_type_dictionary() # Specific rules used to determine what local rules to flip # keys are connection_types, elements are lists of utils.Registration objects self.registrations = utils.create_empty_connection_type_dictionary() # Flips from remote gateways that have been locally registered # Blacklists when doing flip all - different for each gateway, each value is one of our usual rule type dictionaries self._blacklist = {} self._lock = threading.Lock() # Load up static rules. for rule in default_rules: self.add_rule(rule) for gateway in all_targets: self.add_all(gateway, []) # don't add the complexity of extra blacklists yet, maybe later
def update(self, connections, remote_gateway_hub_index, unique_name): ''' Computes a new flipped interface and returns two dictionaries - removed and newly added flips so the watcher thread can take appropriate action (inform the remote gateways). This is run in the watcher thread (warning: take care - other additions come from ros service calls in different threads!) @param connections : list of all the system state connections from the local master @type connection type keyed dictionary of utils.Connection lists. @param remote_gateway_hub_index : full gateway-hub database index to parse @type gateway hash names keyed into a dic with a list of their hubs @param unique_name : this gateway's unique hash name @type string @return new_flips, removed_flips (i.e. those that are no longer on the local master) @rtype pair of connection type keyed dictionary of gateway_msgs.msg.Rule lists. ''' # SLOW, EASY METHOD flipped = utils.create_empty_connection_type_dictionary() new_flips = utils.create_empty_connection_type_dictionary() removed_flips = utils.create_empty_connection_type_dictionary() remote_gateways = remote_gateway_hub_index.keys() diff = lambda l1, l2: [x for x in l1 if x not in l2] # diff of lists self._lock.acquire() # Prune locally cached flip list for flips that have lost their remotes, keep the rules though for connection_type in utils.connection_types: # flip.gateway is a hash name, so is the remote_gateways list self.flipped[connection_type] = [ flip for flip in self.flipped[connection_type] if flip.gateway in remote_gateways ] # Totally regenerate a new flipped interface, compare with old for connection_type in connections: for connection in connections[connection_type]: flipped[connection_type].extend( self._generate_flips(connection.rule.type, connection.rule.name, connection.rule.node, remote_gateways, unique_name)) new_flips[connection_type] = diff(flipped[connection_type], self.flipped[connection_type]) removed_flips[connection_type] = diff( self.flipped[connection_type], flipped[connection_type]) self.flipped = copy.deepcopy(flipped) self._lock.release() return new_flips, removed_flips
def __init__(self, get_system_state): self._get_system_state = get_system_state # function call to the local master self._connections = {} # self._system_state = {} # self._system_state[PUBLISHER] = [] # self._system_state[SUBSCRIBER] = [] # self._system_state[SERVICE] = [] self._connections = utils.create_empty_connection_type_dictionary()
def update(self, new_system_state=None): ''' Currently completely regenerating the connections dictionary and then taking diffs. Could be faster if we took diffs on the system state instead, but that's a bit more awkward since each element has a variable list of nodes that we'd have to check against to get good diffs. e.g. old_publishers = ['/chatter', ['/talker']] new_publishers = ['/chatter', ['/talker', '/babbler']] ''' if new_system_state is None: publishers, subscribers, services = self._get_system_state() else: publishers = new_system_state[PUBLISHER] subscribers = new_system_state[SUBSCRIBER] services = new_system_state[SERVICE] action_servers, publishers, subscribers = self._get_action_servers( publishers, subscribers) action_clients, publishers, subscribers = self._get_action_clients( publishers, subscribers) connections = utils.create_empty_connection_type_dictionary() connections[PUBLISHER] = self._get_connections_from_pub_sub_list( publishers, PUBLISHER) connections[SUBSCRIBER] = self._get_connections_from_pub_sub_list( subscribers, SUBSCRIBER) connections[SERVICE] = self._get_connections_from_service_list( services, SERVICE) connections[ACTION_SERVER] = self._get_connections_from_action_list( action_servers, ACTION_SERVER) connections[ACTION_CLIENT] = self._get_connections_from_action_list( action_clients, ACTION_CLIENT) # Will probably need to check not just in, but only name, node equal diff = lambda l1, l2: [x for x in l1 if x not in l2] new_connections = utils.create_empty_connection_type_dictionary() lost_connections = utils.create_empty_connection_type_dictionary() for connection_type in utils.connection_types: new_connections[connection_type] = diff( connections[connection_type], self._connections[connection_type]) lost_connections[connection_type] = diff( self._connections[connection_type], connections[connection_type]) self._connections = connections return new_connections, lost_connections
def get_local_advertisements(self): ''' Retrieves the local list of advertisements from the hub. This gets used to sync across multiple hubs. @return dictionary of remote advertisements @rtype dictionary of connection type keyed connection values ''' connections = utils.create_empty_connection_type_dictionary() key = hub_api.create_rocon_gateway_key(self._unique_gateway_name, 'advertisements') public_interface = self._redis_server.smembers(key) for connection_str in public_interface: connection = utils.deserialize_connection(connection_str) connections[connection.rule.type].append(connection) return connections
def unadvertise_all(self): ''' Disallow the allow all mode, if enabled. If allow all mode is not enabled, remove everything from the public interface ''' rospy.loginfo( "Gateway : received a request to remove all advertisements!") self.lock.acquire() # stop advertising all self.advertise_all_enabled = False # easy hack for resetting the watchlist and blacklist self.watchlist = utils.create_empty_connection_type_dictionary() self.blacklist = self._default_blacklist self.lock.release()
def get_remote_connection_state(self, remote_gateway): ''' Equivalent to get_connection_state, but generates it from the public interface of a remote gateway @param remote_gateway : hash name for a remote gateway @type str @return dictionary of remote advertisements @rtype dictionary of connection type keyed connection values ''' connections = utils.create_empty_connection_type_dictionary() key = hub_api.create_rocon_gateway_key(remote_gateway, 'advertisements') public_interface = self._redis_server.smembers(key) for connection_str in public_interface: connection = utils.deserialize_connection(connection_str) connections[connection.rule.type].append(connection) return connections
def generate_rules(param): ''' Converts a param of the suitable type (see default_blacklist.yaml) into a dictionary of Rule types. @return all rules as gateway_msgs.msg.Rule objects in our usual keyed dictionary format @rtype type keyed dictionary of Rule lists ''' rules = utils.create_empty_connection_type_dictionary() for value in param: rule = Rule() rule.name = value['name'] # maybe also check for '' here? pattern = re.compile("None", re.IGNORECASE) if pattern.match(value['node']): rule.node = '' # ROS Message fields should not be None, maybe not a problem here though, see below else: rule.node = value['node'] rule.type = value['type'] rules[rule.type].append(rule) return rules
def get_remote_connection_state(self, remote_gateway): ''' Equivalent to get_connection_state, but generates it from the public interface of a remote gateway @param remote_gateway : hash name for a remote gateway @type str @return dictionary of remote advertisements @rtype dictionary of connection type keyed connection values ''' connections = utils.create_empty_connection_type_dictionary() key = hub_api.create_rocon_gateway_key(remote_gateway, 'advertisements') try: public_interface = self._redis_server.smembers(key) for connection_str in public_interface: connection = utils.deserialize_connection(connection_str) connections[connection.rule.type].append(connection) except redis.exceptions.ConnectionError: # will arrive here if the hub happens to have been lost last update and arriving here pass return connections
def advertise_all(self, blacklist): ''' Allow all rules apart from the ones in the provided blacklist + default blacklist @param blacklist : list of Rule objects @type list : list of Rule objects @return failure if already advertising all, success otherwise @rtype bool ''' rospy.loginfo("Gateway : received a request advertise everything!") self.lock.acquire() # Check if advertise all already enabled if self.advertise_all_enabled: self.lock.release() return False self.advertise_all_enabled = True # generate watchlist self.watchlist = utils.create_empty_connection_type_dictionary( ) # easy hack for getting a clean watchlist for connection_type in utils.connection_types: allow_all_rule = Rule() allow_all_rule.name = '.*' allow_all_rule.type = connection_type allow_all_rule.node = '.*' self.watchlist[connection_type].append(allow_all_rule) # generate blacklist (while making sure only unique rules get added) self.blacklist = copy.deepcopy(self._default_blacklist) for rule in blacklist: if not publicRuleExists(rule, self.blacklist[rule.type]): self.blacklist[rule.type].append(rule) self.lock.release() return True