def evaluate_leaderboard(follower_service): """ Starts/changes/stops the time follower service according to who the current clock master is. """ if not leaderboard: logger.debug("nobody on the leader board.") if follower_service is not None: follower_service.terminate() return None current_leader = leaderboard[0] leader_ep = discovery.peer_address(current_leader.uuid) leader_addr = urlparse(leader_ep).netloc.split(':')[0] logger.info('Following <{}>'.format(current_leader)) if follower_service is None: # make new follower follower_service = Clock_Sync_Follower(leader_addr, port=current_leader.port, interval=10, time_fn=time_fn, jump_fn=jump_fn, slew_fn=slew_fn) else: # update follower_service follower_service.host = leader_addr follower_service.port = current_leader.port return follower_service
def evaluate_leaderboard(self): if not self.leaderboard: logger.debug("nobody on the leader board.") return current_leader = self.leaderboard[0] if self.discovery.uuid() != current_leader.uuid: # we are not the leader! leader_ep = self.discovery.peer_address(current_leader.uuid) leader_addr = urlparse(leader_ep).netloc.split(':')[0] if self.follower_service is None: # make new follower self.follower_service = Clock_Sync_Follower(leader_addr, port=current_leader.port, interval=10, time_fn=self.get_time, jump_fn=self.jump_time, slew_fn=self.slew_time) else: # update follower_service self.follower_service.host = leader_addr self.follower_service.port = current_leader.port return # we are the leader logger.debug("we are the leader") if self.follower_service is not None: self.follower_service.terminate() self.follower_service = None if not self.has_been_master: self.has_been_master = 1. logger.debug('Become clock master with rank {}'.format(self.rank)) self.announce_clock_master_info()
def _handle_msg(self, uuid, name, msg, node): #Clock Sync master announce logic if SYNC_TIME_MASTER_ANNOUNCE in msg: self.last_master_announce = self.get_unadjusted_time() worthiness, port = msg.replace(SYNC_TIME_MASTER_ANNOUNCE, '').split(msg_delimeter) foreign_master_worthiness = float(worthiness) foreign_master_port = int(port) forein_master_uuid = UUID(bytes=uuid) foreign_master_address = node.peer_address(forein_master_uuid) foreign_master_ip = foreign_master_address.split('//')[-1].split( ':')[0] # tcp://10.0.1.68:59149 if isinstance(self.time_sync_node, Clock_Sync_Master): # who should yield? if self.clock_master_worthiness() == foreign_master_worthiness: should_yield = node.uuid().int < forein_master_uuid.int else: should_yield = self.clock_master_worthiness( ) < foreign_master_worthiness if should_yield: logger.warning("Yield Clock_Sync_Master to %s@%s" % (name, foreign_master_ip)) self.time_sync_node.stop() self.time_sync_node = Clock_Sync_Follower( foreign_master_ip, port=foreign_master_port, interval=10, time_fn=self.get_time, jump_fn=self.jump_time, slew_fn=self.set_time) else: logger.warning("Dominate as Clock_Sync_Master") node.shouts( self.group, SYNC_TIME_MASTER_ANNOUNCE + "%s" % self.clock_master_worthiness() + msg_delimeter + '%s' % self.time_sync_node.port) elif isinstance(self.time_sync_node, Clock_Sync_Follower): self.time_sync_node.host = foreign_master_ip self.time_sync_node.port = foreign_master_port else: self.time_sync_node = Clock_Sync_Follower( foreign_master_ip, port=foreign_master_port, interval=10, time_fn=self.get_time, jump_fn=self.jump_time, slew_fn=self.set_time) logger.debug("Clock synced with %s" % foreign_master_ip) elif TIMESTAMP_REQ in msg: node.whisper(UUID(bytes=uuid), TIMESTAMP + '%s' % self.get_time()) elif NOTIFICATION in msg: notification_str = msg.replace(NOTIFICATION, '') try: notification = eval(notification_str) except Exception as e: logger.error( 'Recevied mal-formed remote notification. Payload:"%s"' % notification_str) else: # This remote notification does not need to be network propagated again. notification['network_propagate'] = False # We also add some info on where it came from. notification['source'] = 'pupil_sync' notification['sync_node_name'] = name notification['sync_node_uuid'] = uuid # Finally we fire it. self.notify_all(notification) else: logger.warning('Received unknown message pattern. Payload:"%s"' % msg)
def on_notify(self, notification): """Synchronize time of Actors across local network. The notification scheme is used to handle interal timing and to talk to remote pers via the `Pupil_Groups` plugin. Reacts to notifications: ``time_sync.master_announcement``: React accordingly to annouce notification from remote peer. ``time_sync.master_announce_interval``: Re-annouce clock masterhood. ``time_sync.master_announce_timeout``: React accordingly when no master announcement has appeard whithin timeout. Emits notifications: ``time_sync.master_announcement``: Announce masterhood to remote peers (remote notification). ``time_sync.master_announce_interval``: Re-announce masterhood reminder (delayed notification). ``time_sync.master_announce_timeout``: Timeout for foreind master announcement (delayed notification). """ if notification['subject'].startswith('time_sync.master_announcement'): if self.is_master: if notification['worthiness'] > self.clock_master_worthiness(): #We need to yield. self.time_sync_node.stop() self.time_sync_node = None else: #Denounce the lesser competition. n = { 'subject': 'time_sync.master_announcement', 'host': self.time_sync_node.host, 'port': self.time_sync_node.port, 'worthiness': self.clock_master_worthiness(), 'remote_notify': 'all' } self.notify_all(n) if self.is_follower: # update follower info self.time_sync_node.host = notification['host'] self.time_sync_node.port = notification['port'] if self.is_nothing: # Create follower. logger.debug("Clock will sync with {}".format( notification['host'])) self.time_sync_node = Clock_Sync_Follower( notification['host'], port=notification['port'], interval=10, time_fn=self.get_time, jump_fn=self.jump_time, slew_fn=self.slew_time) if not self.is_master: #(Re)set the timer. self.notify_all(self.master_announce_timeout_notification) elif notification['subject'].startswith( 'time_sync.master_announce_timeout'): if self.is_master: pass else: #We have not heard from a master in too long. logger.info("Elevate self to clock master.") self.time_sync_node = Clock_Sync_Master( self.g_pool.get_timestamp) n = { 'subject': 'time_sync.master_announcement', 'host': self.time_sync_node.host, 'port': self.time_sync_node.port, 'worthiness': self.clock_master_worthiness(), 'remote_notify': 'all' } self.notify_all(n) self.notify_all(self.master_announce_interval_notification) elif notification['subject'].startswith( 'time_sync.master_announce_interval'): # The time has come to remind others of our master hood. if self.is_master: n = { 'subject': 'time_sync.master_announcement', 'host': self.time_sync_node.host, 'port': self.time_sync_node.port, 'worthiness': self.clock_master_worthiness(), 'remote_notify': 'all' } self.notify_all(n) # Set the next annouce timer. self.notify_all(self.master_announce_interval_notification)