class Listener(Thread): '''PyTroll listener class for reading messages for Trollduction ''' def __init__(self, address, topics, callback, *args, **kwargs): '''Init Listener object ''' super(Listener, self).__init__() self.topics = topics self.callback = callback self.subscriber = None self.address = address self.create_subscriber() self.running = False self.cargs = args self.ckwargs = kwargs def create_subscriber(self): '''Create a subscriber instance using specified addresses and message types. ''' if self.subscriber is None: if self.topics: LOGGER.info("Subscribing to %s with topics %s", str(self.address), str(self.topics)) self.subscriber = Subscriber(self.address, self.topics) def run(self): '''Run listener ''' self.running = True for msg in self.subscriber(timeout=1): if msg is None: if self.running: continue else: break self.callback(msg, *self.cargs, **self.ckwargs) LOGGER.debug("exiting listener %s", str(self.address)) def stop(self): '''Stop subscriber and delete the instance ''' self.running = False time.sleep(1) if self.subscriber is not None: self.subscriber.close() self.subscriber = None
class Listener(object): '''PyTroll listener class for reading messages for Trollduction ''' def __init__(self, address_list=None, msg_type_list=None, ip=None, port=None, pipe=None): '''Init Listener object ''' self.address_list = [] self.add_address_list(address_list) self.add_address(ip, port) self.msg_type_list = [] if msg_type_list is not None: self.msg_type_list = msg_type_list self.deque = deque() self.pipe = pipe self.subscriber = None self.create_subscriber() self.running = False def add_address(self, ip, port): '''Add address that will be listened ''' if ip is not None and port is not None: self.address_list.append('tcp://'+ip+':%04d' % port) def add_address_list(self, address_list): '''Add a list of addresses that will be listened ''' for address in address_list: self.address_list.append(address) def create_subscriber(self): '''Create a subscriber instance using specified addresses and message types. ''' if self.subscriber is None: if len(self.address_list) > 0: if len(self.msg_type_list) > 0: self.subscriber = Subscriber(self.address_list, *self.msg_type_list) def send_to_pipe(self, msg): '''Send message to parent via a Pipe() ''' self.pipe.send(msg) def run(self): '''Run listener ''' # TODO: add logging print "Starting Listener" self.running = True for msg in self.subscriber.recv(): print "New message received" if msg.subject == '/stop_listener': break if self.pipe is None: self.deque.append(msg) else: while len(self.deque) > 0: self.send_to_pipe(self.deque.popleft()) self.send_to_pipe(msg) def stop(self): '''Stop subscriber and delete the instance ''' # TODO: add logging self.subscriber.stop() self.subscriber.close() self.subscriber = None self.running = False def restart(self): '''Restart subscriber ''' self.stop() self.create_subscriber() self.run()
class Listener(Thread): '''PyTroll listener class for reading messages for Trollduction ''' def __init__(self, address, topics, callback, *args, **kwargs): '''Init Listener object ''' super(Listener, self).__init__() self.topics = topics self.callback = callback self.subscriber = None self.address = address self.running = False self.cargs = args self.ckwargs = kwargs self.restart_event = Event() def create_subscriber(self): '''Create a subscriber instance using specified addresses and message types. ''' if self.subscriber is None: if self.topics: LOGGER.info("Subscribing to %s with topics %s", str(self.address), str(self.topics)) self.subscriber = Subscriber(self.address, self.topics) LOGGER.debug("Subscriber %s", str(self.subscriber)) def run(self): '''Run listener ''' with heartbeat_monitor.Monitor(self.restart_event, **self.ckwargs) as beat_monitor: self.running = True while self.running: # Loop for restart. LOGGER.debug("Starting listener %s", str(self.address)) self.create_subscriber() for msg in self.subscriber(timeout=1): if not self.running: break if self.restart_event.is_set(): self.restart_event.clear() self.stop() self.running = True break if msg is None: continue LOGGER.debug("Receiving (SUB) %s", str(msg)) beat_monitor(msg) if msg.type == "beat": continue self.callback(msg, *self.cargs, **self.ckwargs) LOGGER.debug("Exiting listener %s", str(self.address)) def stop(self): '''Stop subscriber and delete the instance ''' self.running = False time.sleep(1) if self.subscriber is not None: self.subscriber.close() self.subscriber = None
class Listener(object): '''PyTroll listener class for reading messages for Trollduction ''' def __init__(self, address_list=None, msg_type_list=None, ip=None, port=None, pipe=None): '''Init Listener object ''' self.address_list = [] self.add_address_list(address_list) self.add_address(ip, port) self.msg_type_list = [] if msg_type_list is not None: self.msg_type_list = msg_type_list self.deque = deque() self.pipe = pipe self.subscriber = None self.create_subscriber() self.running = False def add_address(self, ip, port): '''Add address that will be listened ''' if ip is not None and port is not None: self.address_list.append('tcp://' + ip + ':%04d' % port) def add_address_list(self, address_list): '''Add a list of addresses that will be listened ''' for address in address_list: self.address_list.append(address) def create_subscriber(self): '''Create a subscriber instance using specified addresses and message types. ''' if self.subscriber is None: if len(self.address_list) > 0: if len(self.msg_type_list) > 0: self.subscriber = Subscriber(self.address_list, *self.msg_type_list) def send_to_pipe(self, msg): '''Send message to parent via a Pipe() ''' self.pipe.send(msg) def run(self): '''Run listener ''' # TODO: add logging print "Starting Listener" self.running = True for msg in self.subscriber.recv(): print "New message received" if msg.subject == '/stop_listener': break if self.pipe is None: self.deque.append(msg) else: while len(self.deque) > 0: self.send_to_pipe(self.deque.popleft()) self.send_to_pipe(msg) def stop(self): '''Stop subscriber and delete the instance ''' # TODO: add logging self.subscriber.stop() self.subscriber.close() self.subscriber = None self.running = False def restart(self): '''Restart subscriber ''' self.stop() self.create_subscriber() self.run()
class Listener(Thread): """PyTroll listener class for reading messages for Trollduction.""" def __init__(self, address, topics, callback, *args, **kwargs): """Init Listener object.""" super(Listener, self).__init__() self.topics = topics self.callback = callback self.subscriber = None self.address = address self.running = False self.cargs = args self.ckwargs = kwargs self.restart_event = Event() def create_subscriber(self): """Create a subscriber using specified addresses and message types.""" if self.subscriber is None: if self.topics: LOGGER.info("Subscribing to %s with topics %s", str(self.address), str(self.topics)) self.subscriber = Subscriber(self.address, self.topics) LOGGER.debug("Subscriber %s", str(self.subscriber)) def run(self): """Run listener.""" with heartbeat_monitor.Monitor(self.restart_event, **self.ckwargs) as beat_monitor: self.running = True while self.running: # Loop for restart. LOGGER.debug("Starting listener %s", str(self.address)) self.create_subscriber() for msg in self.subscriber(timeout=1): if not self.running: break if self.restart_event.is_set(): self.restart_event.clear() self.stop() self.running = True break if msg is None: continue LOGGER.debug("Receiving (SUB) %s", str(msg)) beat_monitor(msg) if msg.type == "beat": continue # Handle public "push" messages as a hot spare client if msg.type == "push": # TODO: these need to be checked and acted if # the transfers are not finished on primary # client and are not cleared LOGGER.debug("Primary client published 'push'") add_to_ongoing(msg) # Handle public "ack" messages as a hot spare client if msg.type == "ack": LOGGER.debug("Primary client finished transfer") _ = add_to_file_cache(msg) _ = clean_ongoing_transfer(get_msg_uid(msg)) # If this is a hot spare client, wait for a while # for a public "push" message which will update # the ongoing transfers before starting processing here delay = self.ckwargs.get("processing_delay", False) if delay: add_timer(float(delay), self.callback, msg, *self.cargs, **self.ckwargs) else: self.callback(msg, *self.cargs, **self.ckwargs) LOGGER.debug("Exiting listener %s", str(self.address)) def stop(self): """Stop subscriber and delete the instance.""" self.running = False time.sleep(1) if self.subscriber is not None: self.subscriber.close() self.subscriber = None
class Listener(Thread): """PyTroll listener class for reading messages for Trollduction.""" def __init__(self, address, topics, *args, die_event=None, **kwargs): """Init Listener object.""" super(Listener, self).__init__() self.topics = topics self.subscriber = None self.address = address self.running = False self.die_event = die_event self.cargs = args self.ckwargs = kwargs self.restart_event = Event() self.cause_of_death = None self.death_count = 0 def restart(self): """Restart the listener, returns a new running instance.""" self.stop() new_listener = self.__class__(self.address, self.topics, *self.cargs, die_event=self.die_event, **self.ckwargs) new_listener.death_count = self.death_count + 1 new_listener.start() return new_listener def create_subscriber(self): """Create a subscriber using specified addresses and message types.""" if self.subscriber is None: if self.topics: LOGGER.info("Subscribing to %s with topics %s", str(self.address), str(self.topics)) self.subscriber = Subscriber(self.address, self.topics) LOGGER.debug("Subscriber %s", str(self.subscriber)) def run(self): """Run listener.""" try: with heartbeat_monitor.Monitor(self.restart_event, **self.ckwargs) as beat_monitor: self.running = True while self.running: LOGGER.debug("Starting listener %s", str(self.address)) self.create_subscriber() self._get_messages(beat_monitor) except Exception as err: LOGGER.exception("Listener died.") self.cause_of_death = err with suppress(AttributeError): self.die_event.set() def _get_messages(self, beat_monitor): for msg in self.subscriber(timeout=1): if not self.running: break if not self._check_heartbeat(): break if msg is None: continue LOGGER.debug("Receiving (SUB) %s", str(msg)) beat_monitor(msg) if self._is_message_already_handled(msg): continue self._process_message(msg) LOGGER.debug("Exiting listener %s", str(self.address)) def _check_heartbeat(self): if self.restart_event.is_set(): LOGGER.warning( "Missing a heartbeat, restarting the subscriber to %s.", str(self.subscriber.addresses)) self.restart_event.clear() self.stop() self.running = True return False return True def _is_message_already_handled(self, msg): return (self._handle_beat_message(msg) or _handle_push_message(msg) or _handle_ack_message(msg) or _handle_message_from_another_client(msg)) def _handle_beat_message(self, msg): if msg.type == "beat": self.death_count = 0 return True return False def _process_message(self, msg): delay = self.ckwargs.get("processing_delay", False) if delay: # If this is a hot spare client, wait for a while # for a public "push" message which will update # the ongoing transfers before starting processing here add_request_push_timer(float(delay), msg, *self.cargs, **self.ckwargs) else: request_push(msg, *self.cargs, **self.ckwargs) def stop(self): """Stop subscriber and delete the instance.""" self.running = False time.sleep(1) if self.subscriber is not None: self.subscriber.close() self.subscriber = None