+ df.addCallbacks(self._freshNodeHandler, self._staleNodeHandler,
+ callbackArgs = (old, datetime.now()),
+ errbackArgs = (old, datetime.now(), node, contacted))
+ elif not old and not contacted:
+ # There's room, we just need to contact the node first
+ self.stats.startedAction('ping')
+ df = node.ping(self.node.id)
+ # Convert the returned contact info into a node
+ df.addCallback(self._pongHandler, datetime.now())
+ # Try adding the contacted node
+ df.addCallbacks(self.insertNode, self._pongError,
+ errbackArgs = (node, datetime.now()))
+
+ def _freshNodeHandler(self, dict, old, start):
+ """Got a pong from the old node, so update it."""
+ self.stats.completedAction('ping', start)
+ if dict['id'] == old.id:
+ self.table.justSeenNode(old.id)
+
+ def _staleNodeHandler(self, err, old, start, node, contacted):
+ """The pinged node never responded, so replace it."""
+ log.msg("action ping failed on %s/%s: %s" % (old.host, old.port, err.getErrorMessage()))
+ self.stats.completedAction('ping', start)
+ self.table.invalidateNode(old)
+ self.insertNode(node, contacted)
+
+ def _pongHandler(self, dict, start):
+ """Node responded properly, change response into a node to insert."""
+ self.stats.completedAction('ping', start)
+ # Create the node using the returned contact info
+ n = self.Node(dict['id'], dict['_krpc_sender'][0], dict['_krpc_sender'][1])
+ return n