def find_successor(self, id): self.log("find_successor of {}".format(id)) # if self._predecessor exists, and _predecessor.id < id < self.id, the successor is current node if self._predecessor and inrange(id, self._predecessor.id(), self.id()): return self return self.find_predecessor(id).successor()
def init_finger(self, remote_address=None): if remote_address: # get the arbitrary node in which the target node want to join remote_node = self._remote.getRemoteNode(remote_address) # successor successor = self.successor() if successor is None: successor = remote_node.find_successor(self.id()) self._successor = successor # initialize finger table for x in range(1, M_BIT): start_id = (self.id() + 2**x) % NUM_SLOTS self._finger[x] = FingerEntry(start_id, None) for x in range(0, M_BIT - 1): start_id = self._finger[x + 1].start if inrange(start_id, self.id(), self._finger[x].node.id()): self._finger[x + 1].node = self._finger[x].node else: # successor = self.find_successor(start_id) self._finger[x + 1] = FingerEntry(start_id, successor) else: # n is the only node in the network for x in range(0, M_BIT): start_id = math.floor((self.id() + 2**x) % NUM_SLOTS) self._finger[x] = FingerEntry(start_id, self) self.print_finger('init_finger')
def closest_preceding_finger(self, id): # first fingers in decreasing distance, then successors in # increasing distance. self.log("closest_preceding_finger") for remote in reversed(self.successors_ + self.finger_): if remote != None and inrange(remote.id(), self.id(1), id) and remote.ping(): return remote return self
def find_predecessor(self, id): self.log("find_predecessor") node = self # If we are alone in the ring, we are the pred(id) if node.successor().id() == node.id(): return node while not inrange(id, node.id(1), node.successor().id(1)): node = node.closest_preceding_finger(id) return node
def _closest_preceding_node(self, id): # from m down to 1 for x in reversed(range(len(self._finger))): entry = self._finger[x] if entry != None and entry.node != None and inrange( entry.node.id(), self.id(), id): return entry.node return self
def find_successor(self, id): # The successor of a key can be us iff # - we have a pred(n) # - id is in (pred(n), n] self.log("find_successor") if self.predecessor() and \ inrange(id, self.predecessor().id(1), self.id(1)): return self node = self.find_predecessor(id) return node.successor()
def findPredecessor(self, id): node = self if node.successor().id() == node.id(): return node try: while node and not address.inrange(id, node.id(1), node.successor().id(1)): node = node.closestPrecedingFinger(id) return node except: pass
def find_predecessor(self, id): lg = "find_predecessor of: {}".format(id) self.log(lg) node = self # when the ring only has one node, node.id is the same as node.successor.id, # if we are alone in the ring, we are the pred(id) if node.id() == node.successor().id(): return node while not inrange(id, node.id(), node.successor().id() + 1): node = node._closest_preceding_node(id) return node
def stabilize(self, ret = True): suc = self.successor() if suc.id() != self._finger[0].id(): self._finger[0] = suc x = suc.predecessor() if x != None and \ address.inrange(x.id(), self.id(1), suc.id()) and \ self.id(1) != suc.id() and \ x.ping(): self._finger[0] = x self.successor().notify(self) return ret
def notify(self, remote): # Someone thinks they are our predecessor, they are iff # - we don't have a predecessor # OR # - the new node r is in the range (pred(n), n) # OR # - our previous predecessor is dead self.log("notify") if self.predecessor() == None or \ inrange(remote.id(), self.predecessor().id(1), self.id()) or \ not self.predecessor().ping(): self.predecessor_ = remote
def stabilize(self): if self._leave: return # prevent successor failure successor = self.successor() pre = successor._predecessor if pre is not None and inrange(pre.id(), self.id(), successor.id()): self.log('stabilize calls update_successor') self.update_successor(pre) successor.notify(self) self.print_finger('stabilize') threading.Timer(2, self.stabilize).start()
def notify(self, remote): # Someone thinks they are our predecessor, they are iff # - we don't have a predecessor # OR # - the new node r is in the range (pred(n), n) # OR # - our previous predecessor is dead self.log("notified by: " + str(remote.address_)) if self.predecessor_ == None or \ inrange(remote.id(), self.predecessor_.id(1), self.id()) or \ not self.predecessor_.ping(): self.predecessor_ = remote self.log('notify: new predecessor set: ' + str(remote.address_)) if self.notify_handler_ is not None: self.notify_handler_(self.predecessor_)
def stabilize(self): self.log("stabilize") suc = self.successor() # We may have found that x is our new successor iff # - x = pred(suc(n)) # - x exists # - x is in range (n, suc(n)) # - [n+1, suc(n)) is non-empty # fix finger_[0] if successor failed if suc.id() != self.finger_[0].id(): self.finger_[0] = suc x = suc.predecessor() if x != None and \ inrange(x.id(), self.id(1), suc.id()) and \ self.id(1) != suc.id() and \ x.ping(): self.finger_[0] = x # We notify our new successor about us self.successor().notify(self) # Keep calling us return True
def is_ours(self, id): assert id >= 0 and id < SIZE return inrange(id, self.predecessor_.id(1), self.id(1))
def update_finger(self, successor, index): if self._finger[index] is not None: if inrange(successor.id(), self.id() - 1, self._finger[index].node.id()): self._finger[index].node = successor self._predecessor.update_finger(successor, index)
def notify(self, pre): # check if pre is the new predecessor if (self._predecessor is None or inrange(pre.id(), self._predecessor.id(), self.id())): self._predecessor = pre
def isOurs(self, id): assert id >= 0 and id < SIZE return address.inrange(id, self._pred.id(1), self.id(1))
def notify(self, remote): if self.predecessor() == None or \ address.inrange(remote.id(), self.predecessor().id(1), self.id()) or \ not self.predecessor().ping(): self._pred = remote
def is_ours(self, id): assert id >= 0 and id < SIZE pred = self.predecessor_ if pred is None: return True return inrange(id, pred.id(1), self.id(1))
def closestPrecedingFinger(self, id): lists = self._succ + self._finger for remote in reversed(lists): if remote != None and address.inrange(remote.id(), self.id(1), id) and remote.ping(): return remote return self