"""Find the index of the bucket that should hold the node's ID number."""
return bisect_left(self.buckets, num)
- def findNodes(self, id):
- """Find the K nodes in our own local table closest to the ID.
+ def _nodeNum(self, id):
+ """Takes different types of input and converts to the node ID number.
@type id: C{string} of C{int} or L{node.Node}
@param id: the ID to find nodes that are close to
# Get the ID number from the input
if isinstance(id, str):
- num = khash.intify(id)
+ return khash.intify(id)
elif isinstance(id, Node):
- num = id.num
+ return id.num
elif isinstance(id, int) or isinstance(id, long):
- num = id
+ return id
else:
- raise TypeError, "findNodes requires an int, string, or Node"
+ raise TypeError, "requires an int, string, or Node input"
- nodes = []
- i = self._bucketIndexForInt(num)
-
- # If this node is already in our table then return it
- try:
- index = self.buckets[i].l.index(num)
- except ValueError:
- pass
- else:
- return [self.buckets[i].l[index]]
+ def findNodes(self, id):
+ """Find the K nodes in our own local table closest to the ID.
+
+ @type id: C{string} of C{int} or L{node.Node}
+ @param id: the ID to find nodes that are close to
+ """
+
+ # Get the ID number from the input
+ num = self._nodeNum(id)
- # Don't have the node, get the K closest nodes from the appropriate bucket
- nodes = nodes + self.buckets[i].l
+ # Get the K closest nodes from the appropriate bucket
+ i = self._bucketIndexForInt(num)
+ nodes = list(self.buckets[i].l)
# Make sure we have enough
if len(nodes) < self.config['K']:
try:
it = self.buckets[i].l.index(stale.num)
except ValueError:
- return
-
- # Remove the stale node and insert the new one
- del(self.buckets[i].l[it])
- if new:
+ pass
+ else:
+ # Remove the stale node
+ del(self.buckets[i].l[it])
+
+ # Insert the new node
+ if new and self._bucketIndexForInt(new.num) == i and len(self.buckets[i].l) < self.config['K']:
self.buckets[i].l.append(new)
def insertNode(self, node, contacted = True):
if node.id == self.node.id: return
# Get the bucket for this node
- i = self. _bucketIndexForInt(node.num)
+ i = self._bucketIndexForInt(node.num)
# Check to see if node is in the bucket already
try:
@rtype: C{datetime.datetime}
@return: the old lastSeen time of the node, or None if it's not in the table
"""
+ # Get the bucket number
+ num = self._nodeNum(id)
+ i = self._bucketIndexForInt(num)
+
+ # Check to see if node is in the bucket
try:
- n = self.findNodes(id)[0]
- except IndexError:
+ it = self.buckets[i].l.index(num)
+ except ValueError:
return None
else:
+ # The node is in the bucket
+ n = self.buckets[i].l[it]
tstamp = n.lastSeen
n.updateLastSeen()
+
+ # Move the node to the end and touch the bucket
+ del(self.buckets[i].l[it])
+ self.buckets[i].l.append(n)
+ self.buckets[i].touch()
+
return tstamp
def invalidateNode(self, n):
def nodeFailed(self, node):
"""Mark a node as having failed once, and remove it if it has failed too much."""
+ # Get the bucket number
+ num = self._nodeNum(node)
+ i = self._bucketIndexForInt(num)
+
+ # Check to see if node is in the bucket
try:
- n = self.findNodes(node.num)[0]
- except IndexError:
+ it = self.buckets[i].l.index(num)
+ except ValueError:
return None
else:
+ # The node is in the bucket
+ n = self.buckets[i].l[it]
if n.msgFailed() >= self.config['MAX_FAILURES']:
self.invalidateNode(n)