summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2011-04-12 13:37:04 +0100
committerLars Wirzenius <liw@liw.fi>2011-04-12 13:37:04 +0100
commited3dad684a7edf557a406735b423326d95aac34a (patch)
tree2466f18bf79dabef6c32a05e36adf19231874f1d
parent13b89c1dfdb32162cdbddec65297b94e04ff42fd (diff)
downloadobnam-ed3dad684a7edf557a406735b423326d95aac34a.tar.gz
Change ClientList to have a three part key.
The third part is new: it's a subkey, so we can store more metadata about clients in the list, particularly the client's own public key id.
-rw-r--r--obnamlib/clientlist.py37
-rw-r--r--obnamlib/clientlist_tests.py7
2 files changed, 26 insertions, 18 deletions
diff --git a/obnamlib/clientlist.py b/obnamlib/clientlist.py
index c25ef6f2..2ab09f91 100644
--- a/obnamlib/clientlist.py
+++ b/obnamlib/clientlist.py
@@ -35,13 +35,18 @@ class ClientList(obnamlib.RepositoryTree):
The client's identifier is a random, unique 64-bit integer.
'''
+
+ # subkey values
+ CLIENT_NAME = 0
+ SUBKEY_MAX = 255
def __init__(self, fs, node_size, upload_queue_size, lru_size, hooks):
self.hash_len = len(self.hashfunc(''))
- self.fmt = '!%dsQ' % self.hash_len
- self.key_bytes = len(self.key('', 0))
- self.minkey = self.hashkey('\x00' * self.hash_len, 0)
- self.maxkey = self.hashkey('\xff' * self.hash_len, obnamlib.MAX_ID)
+ self.fmt = '!%dsQB' % self.hash_len
+ self.key_bytes = len(self.key('', 0, 0))
+ self.minkey = self.hashkey('\x00' * self.hash_len, 0, 0)
+ self.maxkey = self.hashkey('\xff' * self.hash_len, obnamlib.MAX_ID,
+ self.SUBKEY_MAX)
obnamlib.RepositoryTree.__init__(self, fs, 'clientlist',
self.key_bytes, node_size,
upload_queue_size, lru_size, hooks)
@@ -50,12 +55,12 @@ class ClientList(obnamlib.RepositoryTree):
def hashfunc(self, string):
return hashlib.new('md5', string).digest()
- def hashkey(self, namehash, client_id):
- return struct.pack(self.fmt, namehash, client_id)
+ def hashkey(self, namehash, client_id, subkey):
+ return struct.pack(self.fmt, namehash, client_id, subkey)
- def key(self, client_name, client_id):
+ def key(self, client_name, client_id, subkey):
h = self.hashfunc(client_name)
- return self.hashkey(h, client_id)
+ return self.hashkey(h, client_id, subkey)
def unkey(self, key):
return struct.unpack(self.fmt, key)
@@ -71,11 +76,11 @@ class ClientList(obnamlib.RepositoryTree):
return []
def find_client_id(self, t, client_name):
- minkey = self.key(client_name, 0)
- maxkey = self.key(client_name, obnamlib.MAX_ID)
+ minkey = self.key(client_name, 0, 0)
+ maxkey = self.key(client_name, obnamlib.MAX_ID, self.SUBKEY_MAX)
for k, v in t.lookup_range(minkey, maxkey):
- checksum, client_id = self.unkey(k)
- if v == client_name:
+ checksum, client_id, subkey = self.unkey(k)
+ if subkey == self.CLIENT_NAME and v == client_name:
return client_id
return None
@@ -90,16 +95,18 @@ class ClientList(obnamlib.RepositoryTree):
if self.find_client_id(self.tree, client_name) is None:
while True:
candidate_id = self.random_id()
- key = self.key(client_name, candidate_id)
+ key = self.key(client_name, candidate_id, self.CLIENT_NAME)
try:
self.tree.lookup(key)
except KeyError:
break
- self.tree.insert(self.key(client_name, candidate_id), client_name)
+ key = self.key(client_name, candidate_id, self.CLIENT_NAME)
+ self.tree.insert(key, client_name)
def remove_client(self, client_name):
self.start_changes()
client_id = self.find_client_id(self.tree, client_name)
if client_id is not None:
- self.tree.remove(self.key(client_name, client_id))
+ key = self.key(client_name, client_id, self.CLIENT_NAME)
+ self.tree.remove(key)
diff --git a/obnamlib/clientlist_tests.py b/obnamlib/clientlist_tests.py
index d54f46ed..9c19aeaa 100644
--- a/obnamlib/clientlist_tests.py
+++ b/obnamlib/clientlist_tests.py
@@ -38,12 +38,13 @@ class ClientListTests(unittest.TestCase):
def test_key_bytes_is_correct_length(self):
self.assertEqual(self.list.key_bytes,
- len(self.list.key('foo', 12765)))
+ len(self.list.key('foo', 12765, 0)))
def test_unkey_unpacks_key_correctly(self):
- key = self.list.key('client name', 12765)
- client_hash, client_id = self.list.unkey(key)
+ key = self.list.key('client name', 12765, 42)
+ client_hash, client_id, subkey = self.list.unkey(key)
self.assertEqual(client_id, 12765)
+ self.assertEqual(subkey, 42)
def test_reports_none_as_id_for_nonexistent_client(self):
self.assertEqual(self.list.get_client_id('foo'), None)