X-Git-Url: https://git.mxchange.org/?p=quix0rs-apt-p2p.git;a=blobdiff_plain;f=apt_dht_Khashmir%2Fnode.py;h=49b8fe75a06923379d5bfecad8d86f083262a5aa;hp=3f04ef2724b8466e14fed017e8618e02878aa29a;hb=5ae15cb5cc24c1fd9a75ea7a8b416f733d1c79be;hpb=8f102eb1964db2ac18d4bac9e399c069a4cb616e diff --git a/apt_dht_Khashmir/node.py b/apt_dht_Khashmir/node.py index 3f04ef2..49b8fe7 100644 --- a/apt_dht_Khashmir/node.py +++ b/apt_dht_Khashmir/node.py @@ -1,6 +1,12 @@ ## Copyright 2002-2003 Andrew Loewenstern, All Rights Reserved # see LICENSE.txt for license information +"""Represents a node in the DHT. + +@type NULL_ID: C{string} +@var NULL_ID: the node ID to use until one is known +""" + from datetime import datetime, MINYEAR from types import InstanceType @@ -13,8 +19,42 @@ from util import compact NULL_ID = 20 * '\0' class Node: - """encapsulate contact info""" + """Encapsulate a node's contact info. + + @ivar conn: the connection to the remote node (added externally) + @ivar table: the routing table (added externally) + @type fails: C{int} + @ivar fails: number of times this node has failed in a row + @type lastSeen: C{datetime.datetime} + @ivar lastSeen: the last time a response was received from this node + @type id: C{string} + @ivar id: the node's ID in the DHT + @type num: C{long} + @ivar num: the node's ID in number form + @type host: C{string} + @ivar host: the IP address of the node + @type port: C{int} + @ivar port: the port of the node + @type token: C{string} + @ivar token: the last received token from the node + @type num_values: C{int} + @ivar num_values: the number of values the node has for the key in the + currently executing action + """ + def __init__(self, id, host = None, port = None): + """Initialize the node. + + @type id: C{string} or C{dictionary} + @param id: the node's ID in the DHT, or a dictionary containing the + node's id, host and port + @type host: C{string} + @param host: the IP address of the node + (optional, but must be specified if id is not a dictionary) + @type port: C{int} + @param port: the port of the node + (optional, but must be specified if id is not a dictionary) + """ self.fails = 0 self.lastSeen = datetime(MINYEAR, 1, 1) @@ -31,20 +71,33 @@ class Node: self.host = host self.port = int(port) self.token = '' + self.num_values = 0 self._contactInfo = None def updateLastSeen(self): + """Updates the last contact time of the node and resets the number of failures.""" self.lastSeen = datetime.now() self.fails = 0 def updateToken(self, token): + """Update the token for the node.""" self.token = token + def updateNumValues(self, num_values): + """Update how many values the node has in the current search for a value.""" + self.num_values = num_values + def msgFailed(self): + """Log a failed attempt to contact this node. + + @rtype: C{int} + @return: the number of consecutive failures this node has + """ self.fails = self.fails + 1 return self.fails def contactInfo(self): + """Get the compact contact info for the node.""" if self._contactInfo is None: self._contactInfo = compact(self.id, self.host, self.port) return self._contactInfo @@ -52,7 +105,7 @@ class Node: def __repr__(self): return `(self.id, self.host, self.port)` - ## these comparators let us bisect/index a list full of nodes with either a node or an int/long + #{ Comparators to bisect/index a list of nodes with either a node or a long def __lt__(self, a): if type(a) == InstanceType: a = a.num @@ -80,6 +133,7 @@ class Node: class TestNode(unittest.TestCase): + """Unit tests for the node implementation.""" def setUp(self): self.node = Node(khash.newID(), '127.0.0.1', 2002) def testUpdateLastSeen(self):