def __init__(self, node, peersParams): """ Constructor node : node using this manager peersParams : initialization parameters of the peer manager, a list [entitiesFileName, maxPeers, logger] """ self.node = node self.entitiesFileName = peersParams[0] self.maxPeers = peersParams[1] self.logger = peersParams[2] # hash table of peers indexed by ID self.peers = {} # clountercloclwise ordered list of peers self.ccwPeers = CcwList() # distance ordered list of peers self.distPeers = DistList()
class PeersManager: """ Manage all the neighbours of a node """ def __init__(self, node, peersParams): """ Constructor node : node using this manager peersParams : initialization parameters of the peer manager, a list [entitiesFileName, maxPeers, logger] """ self.node = node self.entitiesFileName = peersParams[0] self.maxPeers = peersParams[1] self.logger = peersParams[2] # hash table of peers indexed by ID self.peers = {} # clountercloclwise ordered list of peers self.ccwPeers = CcwList() # distance ordered list of peers self.distPeers = DistList() def createPeer(self, netAddress): """ create a new Peer object netAddress : the network address of this peer, e.g. '193.168.25.36:2456' Return a Peer object""" host, port = netAddress.split(":") return Peer(netAddress, host, int(port)) def getRandomPeer(self): """ Return a peer randomly chosen from a file Read the entities file and return a random peer """ try: f = file(self.entitiesFileName, 'r') # read file list = f.readlines() # retrieve peer peer = random.choice(list) host, stringPort = string.splitfields(peer) port = int(stringPort) f.close() except: self.logger.critical("Cannot read file " + self.entitiesFileName) raise id = host + ":" + stringPort return Peer(id, host, port) def addPeer(self, p): """ add a new peer p : a peer object """ referencePosition = self.node.position p.setLocalPosition(referencePosition) id = p.getId() if not id: raise SolipsisInternalError("Error peer has no id") if self.peers.has_key(id): raise SolipsisInternalError("Error duplicate peer id:" + id) self.peers[p.getId()] = p self.ccwPeers.insert(p) self.distPeers.insert(p) def removePeer(self, p): """ remove a peer p : peer to remove """ id = p.getId() if not id: raise SolipsisInternalError("Error peer has no id") if not self.peers.has_key(id): raise SolipsisInternalError("Error removing peer - no peer with id:" + id) del self.peers[id] self.ccwPeers.delete(p) self.distPeers.delete(p) def updatePeer(self, p): """ update information on a peer. """ self.removePeer(p) self.addPeer(p) def getPeer(self, netAddress): """ Return the peer associated with this net address """ # TODO check exception if this peer doesn't exist id = Node.createId(address[0], address[1]) return self.peers[id] def heartbeat(self, id): """ Update status of a peer id : id of the peer that sent us a HEARTBEAT message """ peer = self.peers[id] peer.setActiveTime(time.time()) def getPeerFromAddress(self, address): """ Get the peer with address 'address' address: address of the peer we are looking at Return : a peer, or None if no such peer was found """ # Iterate through list of peers ids = self.peers.keys() for id in ids: p = self.peers[id] if p.address == address: return p # no peer with this address was found return None def getClosestPeer(self, target): """ Return the peer that is the closest to a target position """ closestPeer = self.peers.values()[0] for p in self.peers.values(): if p.isCloser(closestPeer, target): closestPeer = p return closestPeer def getPeerAround(self, nodePosition, targetPosition): """ Return the peer that is the closest to a target position and that is in the right half plane. nodePosition : position of the node asking for a peer around targetPosition : target position which we are looking around Return : a peer or None if there is no peer in the right half plane """ found = False around = None distClosest = 0 for p in self.peers.values(): if Geometry.inHalfPlane(nodePosition, targetPosition, p.position): # first entity in right half-plane if not found: found = True around = p distClosest = Geometry.distance(targetPosition, p.position) else: dist = Geometry.distance(targetPosition, p.position) # this peer is closer if dist < distClosest: around = p distClosest = dist return around def hasTooManyPeers(self): """ Check if we have too many neighbours Return True if we have too many peers""" return len(self.peers) > self.maxPeers def getWorstPeer(self): """ Choose a peer for removal. Removing this must NOT break the global connectivity rule. """ # filter list of neighbors # keep only entities not in Awareness Area which do not provoke mis-respect # of Global Connectivity Rule FilterList = [] endFilter = 1 indexFilter = self.distPeers.length - 1 nodePos = self.node.position while endFilter and indexFilter > 0: ent = self.distPeers.ll[indexFilter] distEnt = Geometry.distance(ent.position, nodePos) # first, verify that ent is not in Awareness Area if distEnt > self.node.awarenessRadius : if distEnt > ent.awarenessRadius: indInCcw = self.ccwPeers.ll.index(ent) successor = self.ccwPeers.ll[(indInCcw + 1) % self.ccwPeers.length] predecessor = self.ccwPeers.ll[indInCcw - 1] # then verify that ent is not mandatory for Rule respect if Geometry.inHalfPlane(predecessor.position, nodePos, successor.position): FilterList.append(ent) else: # stop iteration because all following entities are in Awareness Radius endFilter = 0 indexFilter -= 1 if FilterList <> []: # there is a posibility to remove any entity in FilterList. # By default, we decide to remove the farthest entity. # In article presented at RESH'02, we proposed several other possibilities # for more efficient choice. result = FilterList[0] else: result = 0 return result def enumerate(self): """ return a list with all peers """ return self.distPeers def update(self): """ position of the node has changed rrecompute all neighbours postion """ self.logger.critical("manager.update NOT IMPLEMENTED") raise SolipsisInternalError("manager.update NOT IMPLEMENTED")