def add_to_vessel_status_monitor(monitorhandle, vesselhandle_list): """ <Purpose> Adds the vesselhandles in vesselhandle_list to the specified monitor. If any already are watched by the monitor, they are silently ignored. There is no removal of previously added vesselhandles other than automatic removal done when vessels are unreachable or otherwise invalid. One intention of this function is that new vessels found via a lookup_node_locations_by_identity and then find_vessels_on_nodes can be passed to this function as a way of making sure the monitor knows about new vessels that a user has just obtained access to or which have recently come online. <Arguments> monitorhandle A monitorhandle returned by register_vessel_status_monitor. vesselhandle_list A list of vesselhandles to add to the monitor. <Side Effects> The next run of the monitor will include the provided vesselhandles. <Exceptions> ValueError If no such monitorhandle exists (including if it was already removed). <Returns> None """ experimentlib._validate_vesselhandle_list(vesselhandle_list) _monitor_lock.acquire() try: # Ensure the monitorhandle is valid. if not monitorhandle in _vessel_monitors: raise ValueError("The provided monitorhandle is invalid: " + str(monitorhandle)) for vesselhandle in vesselhandle_list: if vesselhandle not in _vessel_monitors[monitorhandle][ 'vesselhandle_list']: _vessel_monitors[monitorhandle]['vesselhandle_list'].append( vesselhandle) _vessel_monitors[monitorhandle]['vessels'][vesselhandle] = {} finally: _monitor_lock.release()
def add_to_vessel_status_monitor(monitorhandle, vesselhandle_list): """ <Purpose> Adds the vesselhandles in vesselhandle_list to the specified monitor. If any already are watched by the monitor, they are silently ignored. There is no removal of previously added vesselhandles other than automatic removal done when vessels are unreachable or otherwise invalid. One intention of this function is that new vessels found via a lookup_node_locations_by_identity and then find_vessels_on_nodes can be passed to this function as a way of making sure the monitor knows about new vessels that a user has just obtained access to or which have recently come online. <Arguments> monitorhandle A monitorhandle returned by register_vessel_status_monitor. vesselhandle_list A list of vesselhandles to add to the monitor. <Side Effects> The next run of the monitor will include the provided vesselhandles. <Exceptions> ValueError If no such monitorhandle exists (including if it was already removed). <Returns> None """ experimentlib._validate_vesselhandle_list(vesselhandle_list) _monitor_lock.acquire() try: # Ensure the monitorhandle is valid. if not monitorhandle in _vessel_monitors: raise ValueError("The provided monitorhandle is invalid: " + str(monitorhandle)) for vesselhandle in vesselhandle_list: if vesselhandle not in _vessel_monitors[monitorhandle]['vesselhandle_list']: _vessel_monitors[monitorhandle]['vesselhandle_list'].append(vesselhandle) _vessel_monitors[monitorhandle]['vessels'][vesselhandle] = {} finally: _monitor_lock.release()
def register_vessel_status_monitor(identity, vesselhandle_list, callback, waittime=300, concurrency=10): """ <Purpose> Registers a vessel status monitor. Once registered, a monitor occassionally checks the status of each vessel. If the vessel's status has changed or was never checked before, the provided callback function is called with information about the status change. <Arguments> identity The identity to be used when looking checking vessel status. This is mostly needed to determine whether the vessel exists but no longer is usable by the identity (that is, if the public key of the identity is no longer neither the owner or a user of the vessel). vesselhandle_list A list of vesselhandles of the vessels to be monitored. callback The callback function. This should accept three arguments: (vesselhandle, oldstatus, newstatus) where oldstatus and newstatus are both strings. Any exceptions raised by the callback will be silently ignored, so the callback should implement exception handling. waittime How many seconds to wait between status checks. This will be the time between finishing a check of all vessels and starting another round of checking. concurrency The number of threads to use for communicating with nodes. This will be the maximum number of vessels that can be checked simultaneously. <Exceptions> None <Side Effects> Immediately starts a vessel monitor running. <Returns> A monitorhandle which can be used to update or cancel this monitor. """ experimentlib._validate_vesselhandle_list(vesselhandle_list) experimentlib._validate_identity(identity) # We copy the vesselhandle_list so that the user doesn't directly modify. vesselhandle_list = vesselhandle_list[:] _monitor_lock.acquire() try: # Create a new monitor key in the the _vessel_monitors dict. for attempt in range(10): id = "MONITOR_" + str(random.random()) if id not in _vessel_monitors: break else: # I don't intend users to need to worry about this exception. I also # don't know of a more specific built-in exception to use and I don't # feel this should raise a SeattleExperimentException. Therefore, # intentionally raising a generic Exception here. raise Exception("Can't generate a unique vessel monitor id. " + "This probably means a bug in experimentlib.py") _vessel_monitors[id] = {} _vessel_monitors[id]['vesselhandle_list'] = vesselhandle_list _vessel_monitors[id]['waittime'] = waittime _vessel_monitors[id]['callback'] = callback _vessel_monitors[id]['concurrency'] = concurrency _vessel_monitors[id]['identity'] = identity # Whether the monitor was canceled/removed. Used to indicate to a running # monitor that it should stop doing work. _vessel_monitors[id]['canceled'] = False # Keeps track of the status of individual vessels. This is used by # vessel monitors to determine when the status has changed. _vessel_monitors[id]['vessels'] = {} for handle in vesselhandle_list: _vessel_monitors[id]['vessels'][handle] = {} # The first time we run it we don't delay. Storing the timer handle is a # bit useless in this case but we do it for consistency. _vessel_monitors[id]['timerhandle'] = settimer(0, _run_monitor, [_vessel_monitors[id]]) return id finally: _monitor_lock.release()