import os, sha, random
-from twisted.internet import defer
+from twisted.internet import defer, reactor
+from twisted.internet.abstract import isIPAddress
from twisted.trial import unittest
from zope.interface import implements
self.config_parser = config
self.section = section
self.config = {}
- self.cache_dir = self.config_parser.get('DEFAULT', 'cache_dir')
+ self.cache_dir = self.config_parser.get(section, 'cache_dir')
self.bootstrap = self.config_parser.getstringlist(section, 'BOOTSTRAP')
self.bootstrap_node = self.config_parser.getboolean(section, 'BOOTSTRAP_NODE')
for k in self.config_parser.options(section):
self.config[k] = self.config_parser.gettime(section, k)
else:
self.config[k] = self.config_parser.get(section, k)
- if 'PORT' not in self.config:
- self.config['PORT'] = self.config_parser.getint('DEFAULT', 'PORT')
def join(self):
"""See L{apt_dht.interfaces.IDHT}."""
for node in self.bootstrap:
host, port = node.rsplit(':', 1)
port = int(port)
- self.khashmir.addContact(host, port, self._join_single)
+ if isIPAddress(host):
+ self._join_gotIP(host, port)
+ else:
+ reactor.resolve(host).addCallback(self._join_gotIP, port)
return self.joining
+
+ def _join_gotIP(self, ip, port):
+ """Called after an IP address has been found for a single bootstrap node."""
+ self.khashmir.addContact(ip, port, self._join_single)
def _join_single(self):
"""Called when a single bootstrap node has been added."""
self.joined = False
self.khashmir.shutdown()
+ def normalizeKey(self, key):
+ """Normalize a key's length suitable for insertion in the DHT."""
+ key_bytes = (self.config['HASH_LENGTH'] - 1) // 8 + 1
+ if len(key) < key_bytes:
+ key = key + '\000'*(key_bytes - len(key))
+ elif len(key) > key_bytes:
+ key = key[:key_bytes]
+ return key
+
def getValue(self, key):
"""See L{apt_dht.interfaces.IDHT}."""
if self.config is None:
raise DHTError, "have not joined a network yet"
d = defer.Deferred()
+ key = self.normalizeKey(key)
if key not in self.retrieving:
self.khashmir.valueForKey(key, self._getValue)
self.retrieving.setdefault(key, []).append(d)
if not self.joined:
raise DHTError, "have not joined a network yet"
+ key = self.normalizeKey(key)
if key in self.storing and value in self.storing[key]:
raise DHTError, "already storing that key with the same value"
self.b.bootstrap = ["127.0.0.1:4044"]
self.b.cache_dir = '/tmp'
+ def test_normalizeKey(self):
+ self.failUnless(self.a.normalizeKey('12345678901234567890') == '12345678901234567890')
+ self.failUnless(self.a.normalizeKey('12345678901234567') == '12345678901234567\000\000\000')
+ self.failUnless(self.a.normalizeKey('1234567890123456789012345') == '12345678901234567890')
+ self.failUnless(self.a.normalizeKey('1234567890123456789') == '1234567890123456789\000')
+ self.failUnless(self.a.normalizeKey('123456789012345678901') == '12345678901234567890')
+
def test_bootstrap_join(self):
d = self.a.join()
return d
def tearDown(self):
self.a.leave()
try:
- os.unlink(self.a.khashmir.db)
+ os.unlink(self.a.khashmir.store.db)
except:
pass
self.b.leave()
try:
- os.unlink(self.b.khashmir.db)
+ os.unlink(self.b.khashmir.store.db)
except:
pass
def get_values(self):
self.checked = 0
for i in range(len(self.l)):
- for j in random.sample(xrange(len(self.l)), 4):
+ for j in random.sample(xrange(len(self.l)), max(len(self.l), 4)):
self.checked += 1
d = self.l[i].getValue(sha.new(str(self.startport+j)).digest())
check = []
for i in self.l:
try:
i.leave()
- os.unlink(i.khashmir.db)
+ os.unlink(i.khashmir.store.db)
except:
pass