def AROUND(self, event): """ A peer sent us an AROUND message """ # cancel timer since we got our response self.timer.cancel() peer = event.createRemotePeer() # current number of neighbours nbNeighbours = len(self.neighbours) # last neighbour found last = self.neighbours[nbNeighbours-1] nodePos = self.node.getPosition() # our position bestPos = self.best.getPosition() # position of best node peerPos = Geometry.relativePosition(peer.getPosition(), self.node.getPosition()) # check if turn ends : we have at least 3 neighbours and either we got back # to the first peer (=> turn completed) or our last neighbour was in the # left half plane and this peer is in the right half plane if ( nbNeighbours > 2 ) and (peer.getId() == self.best.getId()) or ( not Geometry.inHalfPlane(bestPos, nodePos, last.getPosition()) and Geometry.inHalfPlane(bestPos, nodePos, peerPos) ): # Our awarenesse radius is the distance between us and our closest # neighbour, because we are sure to know all the entities between us # and the best. bestRelativePos = Geometry.relativePosition(bestPos, nodePos) minDistance = Geometry.distance(bestRelativePos, nodePos) self.node.setAwarenessRadius(minDistance) # register these peers with the peerManager and connect ! manager = self.node.getPeersManager() for p in self.neighbours: # FIXME : should we add the peer upon receiving the CONNECT msg? manager.addPeer(p) factory = EventFactory.getInstance(PeerEvent.TYPE) hello = factory.createHELLO() hello.setRecipientAddress(p.getAddress()) self.node.dispatch(hello) self.node.setState(Connecting()) else: # add this peer to our list of neighbours self.addPeerAround(peer) # send this peer a queryaround message bestDist = Geometry.distance(bestPos, nodePos) factory = EventFactory.getInstance(PeerEvent.TYPE) queryaround = factory.createQUERYAROUND(self.best.getId(), bestDist) queryaround.setRecipientAddress(peer.getAddress()) self.node.dispatch(queryaround) self.startTimer()
def getBadGlobalConnectivityPeers(self): """ Check if global connectivity is ensured Return a pair of entities not respecting property or an empty set. First entity should be used to search clockwise and the second one ccw""" result = [] nodePos = self.node.getPosition() length = self.getNumberOfPeers() if length == 0: return [] if length == 1: (peer,) = self.peers.values() return [peer, peer] for index in range(length): ent = self.ccwPeers.ll[index] nextEnt = self.ccwPeers.ll[ (index+1) % length ] entPos = ent.getPosition() nextEntPos = nextEnt.getPosition() if not Geometry.inHalfPlane(entPos, nodePos, nextEntPos): return [ent, nextEnt] return []
def getPeerAround(self, targetPosition, emitter_id, isClockWise=True): """ Return the peer that is the closest to a target position and that is in the right half plane. targetPosition : target position which we are looking around isClockWise : boolean indicating if we we searching in the right or the left half-plane - optional Return : a peer or None if there is no peer in the half plane """ found = False around = None distClosest = 0 nodePosition = self.node.getPosition() for p in self.peers.values(): if p.getId() == emitter_id: continue if Geometry.inHalfPlane(nodePosition, targetPosition, p.getPosition()) == isClockWise: # first entity in right half-plane if not found: found = True around = p distClosest = Geometry.distance(targetPosition, p.getPosition()) else: dist = Geometry.distance(targetPosition, p.getPosition()) # this peer is closer if dist < distClosest: around = p distClosest = dist return around
def necessaryPeers(self): """ Returns the list of peers that are necessary for our global connectivity. """ n = len(self.ccwPeers) if n < 4: return self.enumeratePeers() result = [] for i in xrange(n): pred_pos = self.ccwPeers.ll[i - 2].getPosition() pos = self.node.getPosition() succ_pos = self.ccwPeers.ll[i].getPosition() if not Geometry.inHalfPlane(pred_pos, pos, succ_pos): result.append(self.ccwPeers.ll[i - 1]) return result
def getWorstPeers(self): """ Return a list of peers with which we should disconnect. Removing these peers must NOT break the global connectivity rule. Return a list of peers or [] if we cannot remove a peer """ if not self.hasTooManyPeers(): return [] # filter list of neighbors # keep only entities not in Awareness Area which do not provoke mis-respect # of Global Connectivity Rule FilterList = [] endFilter = True indexFilter = len(self.distPeers) - 1 nodePos = self.node.getPosition() while endFilter and indexFilter > 0: ent = self.distPeers.ll[indexFilter] distEnt = Geometry.distance(ent.getPosition(), nodePos) # first, verify that ent is not in Awareness Area if distEnt > self.node.getAwarenessRadius() : # and that we are not in its AR if distEnt > ent.getAwarenessRadius(): indInCcw = self.ccwPeers.ll.index(ent) successor = self.ccwPeers.ll[(indInCcw + 1) % len(self.ccwPeers)] predecessor = self.ccwPeers.ll[indInCcw - 1] # then verify that ent is not mandatory for Rule respect if Geometry.inHalfPlane(predecessor.getPosition(), nodePos, successor.getPosition()): FilterList.append(ent) else: # stop iteration because all following entities are in Awareness # Radius endFilter = False indexFilter -= 1 return FilterList