DHT = __import__(config.get('DEFAULT', 'DHT'), globals(), locals(), ['DHT'])
assert(IDHT.implementedBy(DHT.DHT), "You must provide a DHT implementation that implements the IDHT interface.")
myDHT = DHT.DHT()
+myDHT.loadConfig(config)
+myDHT.join()
if not config.getboolean('DEFAULT', 'DHT-only'):
from apt_dht.apt_dht import AptDHT
class IDHT(Interface):
"""An abstract interface for using a DHT implementation."""
- def loadConfig(self, config):
+ def loadConfig(self, config, section):
"""Load the DHTs configuration from a dictionary.
- @type config: C{dictionary}
+ @type config: C{SafeConfigParser}
@param config: the dictionary of config values
"""
- def join(self, bootstrap_nodes):
+ def join(self):
"""Bootstrap the new DHT node into the DHT.
- @type bootstrap_nodes: C{list} of (C{string}, C{int})
- @param bootstrap_nodes: a list of the nodes to contact to join the DHT
- @rtype: C{Deffered}
+ @rtype: C{Deferred}
@return: a deferred that will fire when the node has joined
"""
def leave(self):
"""Depart gracefully from the DHT.
- @rtype: C{Deffered}
- @return: a deferred that will fire when the node has joined
+ @rtype: C{Deferred}
+ @return: a deferred that will fire when the node has left
"""
def getValue(self, key):
- """Get a value from the DHT for the specified key."""
+ """Get a value from the DHT for the specified key.
+
+ @rtype: C{Deferred}
+ @return: a deferred that will fire with the stored values
+ """
def storeValue(self, key, value):
"""Store a value in the DHT for the specified key."""
+from twisted.internet import defer
from zope.interface import implements
from apt_dht.interfaces import IDHT
+from khashmir import Khashmir
+
+class DHTError(Exception):
+ """Represents errors that occur in the DHT."""
class DHT:
implements(IDHT)
def __init__(self):
- pass
\ No newline at end of file
+ self.config = None
+
+ def loadConfig(self, config, section):
+ """See L{apt_dht.interfaces.IDHT}."""
+ self.config = config
+ self.section = section
+ if self.config.has_option(section, 'port'):
+ self.port = self.config.get(section, 'port')
+ else:
+ self.port = self.config.get('DEFAULT', 'port')
+
+ def join(self):
+ """See L{apt_dht.interfaces.IDHT}."""
+ if self.config is None:
+ raise DHTError, "configuration not loaded"
+
+ self.khashmir = Khashmir('', self.port)
+
+ for node in self.config.get(self.section, 'bootstrap'):
+ host, port = node.rsplit(':', 1)
+ self.khashmir.addContact(host, port)
+
+ self.khashmir.findCloseNodes()
+
+ def leave(self):
+ """See L{apt_dht.interfaces.IDHT}."""
+ if self.config is None:
+ raise DHTError, "configuration not loaded"
+
+ self.khashmir.listenport.stopListening()
+
+ def getValue(self, key):
+ """See L{apt_dht.interfaces.IDHT}."""
+ if self.config is None:
+ raise DHTError, "configuration not loaded"
+
+ d = defer.Deferred()
+ self.khashmir.valueForKey(key, d.callback)
+ return d
+
+ def storeValue(self, key, value):
+ """See L{apt_dht.interfaces.IDHT}."""
+ if self.config is None:
+ raise DHTError, "configuration not loaded"
+
+ self.khashmir.storeValueForKey(key, value)