summaryrefslogtreecommitdiff
path: root/obnamlib/repo_interface.py
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2015-08-01 14:19:09 +0300
committerLars Wirzenius <liw@liw.fi>2015-08-01 15:30:18 +0300
commit7dae91d21285265554f937db9b0b677624889bde (patch)
tree9765d26bcedb59dce3a6dbc3f9a0e0e749f05f93 /obnamlib/repo_interface.py
parent8cef27a5693e3031915ee86887b6544c5e662f5a (diff)
downloadobnam-7dae91d21285265554f937db9b0b677624889bde.tar.gz
Redefine commit_* to NOT unlock
Update all callers to call unlock_foo after every commit_foo. Add tests to check that commit_* do not unlock. Fix some tests that were meaningless. Change commit_* implementations to not unlock. This allows us to commit, then continue, e.g., for forget or backup checkpoints. The checkpoints still unlock and re-lock, however, due to tests failing otherwise, indicating a problem elswewhere.
Diffstat (limited to 'obnamlib/repo_interface.py')
-rw-r--r--obnamlib/repo_interface.py115
1 files changed, 93 insertions, 22 deletions
diff --git a/obnamlib/repo_interface.py b/obnamlib/repo_interface.py
index 4cb05d44..7c00a0fe 100644
--- a/obnamlib/repo_interface.py
+++ b/obnamlib/repo_interface.py
@@ -389,7 +389,13 @@ class RepositoryInterface(object):
raise
def unlock_everything(self):
- '''Unock every part of the repository to which we hold a lock.'''
+ '''Unock every part of the repository to which we hold a lock.
+
+ This also discards any changes made to each part made after
+ the latest lock or commit of that part.
+
+ '''
+
if self.got_client_list_lock():
self.unlock_client_list()
@@ -411,11 +417,21 @@ class RepositoryInterface(object):
raise NotImplementedError()
def commit_client_list(self):
- '''Commit changes to client list and unlock it.'''
+ '''Commit changes to client list and DO NOT unlock it.
+
+ Note that the caller MUST also call unlock_client_list.
+ Otherwise the client list remains locked.
+
+ '''
raise NotImplementedError()
def unlock_client_list(self):
- '''Forget changes to client list and unlock it.'''
+ '''Forget changes to client list and unlock it.
+
+ The changes that are forgotten are those made after the latest
+ lock_client_list or commit_client_list.
+
+ '''
raise NotImplementedError()
def got_client_list_lock(self):
@@ -479,11 +495,21 @@ class RepositoryInterface(object):
raise NotImplementedError()
def commit_client(self, client_name):
- '''Commit changes to client and unlock it.'''
+ '''Commit changes to client and DO NOT unlock it.
+
+ Note that the caller MUST also call unlock_client. Otherwise
+ the client list remains locked.
+
+ '''
raise NotImplementedError()
def unlock_client(self, client_name):
- '''Forget changes to client and unlock it.'''
+ '''Forget changes to client and unlock it.
+
+ The changes that are forgotten are those made after the latest
+ lock_client or commit_client.
+
+ '''
raise NotImplementedError()
def got_client_lock(self, client_name):
@@ -754,7 +780,12 @@ class RepositoryInterface(object):
raise NotImplementedError()
def unlock_chunk_indexes(self):
- '''Unlocks chunk indexes without committing them.'''
+ '''Forget any changes to and and unlock chunk indexes.
+
+ The changes that are forgotten are those made after the latest
+ lock_chunk_indexes or commit_chunk_indexes.
+
+ '''
raise NotImplementedError()
def got_chunk_indexes_lock(self):
@@ -766,7 +797,12 @@ class RepositoryInterface(object):
raise NotImplementedError()
def commit_chunk_indexes(self):
- '''Commit changes to chunk indexes.'''
+ '''Commit changes to chunk indexes and DO NOT unlock it.
+
+ Note that the caller MUST also call unlock_chunk_indexes.
+ Otherwise the client list remains locked.
+
+ '''
raise NotImplementedError()
def prepare_chunk_for_indexes(self, data):
@@ -948,6 +984,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
self.repo.lock_client_list()
self.repo.add_client('foo')
self.repo.commit_client_list()
+ self.repo.unlock_client_list()
self.repo.lock_client_list()
self.repo.rename_client('foo', 'bar')
@@ -982,6 +1019,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
self.repo.add_client('foo')
self.repo.add_client('bar')
self.repo.commit_client_list()
+ self.repo.unlock_client_list()
self.repo.lock_client_list()
self.assertRaises(
@@ -1006,6 +1044,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
self.repo.lock_client_list()
self.repo.add_client('foo')
self.repo.commit_client_list()
+ self.repo.unlock_client_list()
self.assertRaises(
obnamlib.RepositoryClientListNotLocked,
self.repo.rename_client, 'foo', 'bar')
@@ -1029,6 +1068,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
self.repo.lock_client_list()
self.repo.add_client('foo')
self.repo.commit_client_list()
+ self.repo.unlock_client_list()
self.repo.lock_client_list()
self.repo.rename_client('foo', 'bar')
@@ -1042,6 +1082,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
self.repo.lock_client_list()
self.repo.add_client('foo')
self.repo.commit_client_list()
+ self.repo.unlock_client_list()
self.repo.lock_client_list()
self.repo.remove_client('foo')
@@ -1054,6 +1095,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
self.repo.lock_client_list()
self.repo.add_client('foo')
self.repo.commit_client_list()
+ self.repo.unlock_client_list()
self.assertEqual(self.repo.get_client_names(), ['foo'])
def test_committing_client_list_renames_client(self):
@@ -1062,10 +1104,12 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
self.repo.lock_client_list()
self.repo.add_client('foo')
self.repo.commit_client_list()
+ self.repo.unlock_client_list()
self.repo.lock_client_list()
self.repo.rename_client('foo', 'bar')
self.repo.commit_client_list()
+ self.repo.unlock_client_list()
self.assertEqual(self.repo.get_client_names(), ['bar'])
@@ -1075,30 +1119,26 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
self.repo.lock_client_list()
self.repo.add_client('foo')
self.repo.commit_client_list()
+ self.repo.unlock_client_list()
self.repo.lock_client_list()
self.repo.remove_client('foo')
self.repo.commit_client_list()
+ self.repo.unlock_client_list()
self.assertEqual(self.repo.get_client_names(), [])
- def test_commiting_client_list_removes_lock(self):
+ def test_commiting_client_list_does_NOT_remove_lock(self):
self.repo.init_repo()
-
self.repo.lock_client_list()
self.repo.commit_client_list()
-
- self.repo.lock_client_list()
- self.assertEqual(self.repo.get_client_names(), [])
+ self.assertTrue(self.repo.got_client_list_lock())
def test_unlocking_client_list_removes_lock(self):
self.repo.init_repo()
-
self.repo.lock_client_list()
self.repo.unlock_client_list()
-
- self.repo.lock_client_list()
- self.assertEqual(self.repo.get_client_names(), [])
+ self.assertFalse(self.repo.got_client_list_lock())
def test_locking_client_list_twice_fails(self):
self.repo.init_repo()
@@ -1167,12 +1207,14 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
self.repo.lock_client_list()
self.repo.add_client('fooclient')
self.repo.commit_client_list()
+ self.repo.unlock_client_list()
def setup_two_clients(self):
self.repo.lock_client_list()
self.repo.add_client('fooclient')
self.repo.add_client('barclient')
self.repo.commit_client_list()
+ self.repo.unlock_client_list()
def test_have_not_got_client_lock_initially(self):
self.setup_client()
@@ -1235,17 +1277,17 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
obnamlib.RepositoryClientDoesNotExist,
self.repo.commit_client, 'notexist')
- def test_unlocking_client_removes_lock(self):
+ def test_committing_client_does_NOT_remove_lock(self):
self.setup_client()
self.repo.lock_client('fooclient')
- self.repo.unlock_client('fooclient')
- self.assertEqual(self.repo.lock_client('fooclient'), None)
+ self.repo.commit_client('fooclient')
+ self.assertTrue(self.repo.got_client_lock('fooclient'))
- def test_committing_client_removes_lock(self):
+ def test_unlocking_client_removes_lock(self):
self.setup_client()
self.repo.lock_client('fooclient')
- self.repo.commit_client('fooclient')
- self.assertEqual(self.repo.lock_client('fooclient'), None)
+ self.repo.unlock_client('fooclient')
+ self.assertFalse(self.repo.got_client_lock('fooclient'))
def test_has_list_of_allowed_client_keys(self):
self.assertEqual(type(self.repo.get_allowed_client_keys()), list)
@@ -1301,6 +1343,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
value = self.repo.get_client_key(
'fooclient', obnamlib.REPO_CLIENT_TEST_KEY)
self.repo.commit_client('fooclient')
+ self.repo.unlock_client('fooclient')
self.assertEqual(value, 'bar')
def test_unlocking_client_undoes_key_changes(self):
@@ -1360,6 +1403,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
self.repo.lock_client('fooclient')
new_id = self.repo.create_generation('fooclient')
self.repo.commit_client('fooclient')
+ self.repo.unlock_client('fooclient')
self.assertEqual(
self.repo.get_client_generation_ids('fooclient'),
[new_id])
@@ -1417,6 +1461,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
if self.generation_test_key_is_allowed():
gen_id = self.create_generation()
self.repo.commit_client('fooclient')
+ self.repo.unlock_client('fooclient')
self.assertRaises(
obnamlib.RepositoryClientNotLocked,
self.repo.set_generation_key,
@@ -1430,6 +1475,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
value = self.repo.get_generation_key(
gen_id, obnamlib.REPO_GENERATION_TEST_KEY)
self.repo.commit_client('fooclient')
+ self.repo.unlock_client('fooclient')
self.assertEqual(value, 'bar')
def test_removes_unfinished_generation(self):
@@ -1440,6 +1486,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
def test_removes_finished_generation(self):
gen_id = self.create_generation()
self.repo.commit_client('fooclient')
+ self.repo.unlock_client('fooclient')
self.repo.lock_client('fooclient')
self.repo.remove_generation(gen_id)
self.assertEqual(self.repo.get_client_generation_ids('fooclient'), [])
@@ -1454,6 +1501,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
def test_removing_generation_without_client_lock_fails(self):
gen_id = self.create_generation()
self.repo.commit_client('fooclient')
+ self.repo.unlock_client('fooclient')
self.assertRaises(
obnamlib.RepositoryClientNotLocked,
self.repo.remove_generation, gen_id)
@@ -1461,6 +1509,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
def test_unlocking_client_forgets_generation_removal(self):
gen_id = self.create_generation()
self.repo.commit_client('fooclient')
+ self.repo.unlock_client('fooclient')
self.repo.lock_client('fooclient')
self.repo.remove_generation(gen_id)
self.repo.unlock_client('fooclient')
@@ -1472,6 +1521,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
gen_id = self.create_generation()
self.repo.remove_generation(gen_id)
self.repo.commit_client('fooclient')
+ self.repo.unlock_client('fooclient')
self.assertEqual(self.repo.get_client_generation_ids('fooclient'), [])
def test_empty_generation_uses_no_chunk_ids(self):
@@ -1502,6 +1552,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
# one.
gen_id = self.create_generation()
self.repo.commit_client('fooclient')
+ self.repo.unlock_client('fooclient')
self.repo.lock_client('fooclient')
gen_id_2 = self.repo.create_generation('fooclient')
genspec = self.repo.make_generation_spec(gen_id)
@@ -1533,6 +1584,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
self.repo.set_file_key(
gen_id, '/foo/bar', obnamlib.REPO_FILE_MODE, stat.S_IFREG)
self.repo.commit_client('fooclient')
+ self.repo.unlock_client('fooclient')
self.assertTrue(self.repo.file_exists(gen_id, '/foo/bar'))
def test_creating_generation_clones_previous_one(self):
@@ -1541,6 +1593,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
self.repo.set_file_key(
gen_id, '/foo/bar', obnamlib.REPO_FILE_MODE, stat.S_IFREG)
self.repo.commit_client('fooclient')
+ self.repo.unlock_client('fooclient')
self.repo.lock_client('fooclient')
gen_id_2 = self.repo.create_generation('fooclient')
@@ -1558,6 +1611,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
self.repo.set_file_key(
gen_id, '/foo/bar', obnamlib.REPO_FILE_MODE, stat.S_IFREG)
self.repo.commit_client('fooclient')
+ self.repo.unlock_client('fooclient')
self.repo.lock_client('fooclient')
gen_id_2 = self.repo.create_generation('fooclient')
@@ -1572,12 +1626,14 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
self.repo.set_file_key(
gen_id, '/foo/bar', obnamlib.REPO_FILE_MODE, stat.S_IFREG)
self.repo.commit_client('fooclient')
+ self.repo.unlock_client('fooclient')
self.repo.lock_client('fooclient')
gen_id_2 = self.repo.create_generation('fooclient')
self.assertTrue(self.repo.file_exists(gen_id_2, '/foo/bar'))
self.repo.remove_file(gen_id_2, '/foo/bar')
self.repo.commit_client('fooclient')
+ self.repo.unlock_client('fooclient')
self.assertTrue(self.repo.file_exists(gen_id, '/foo/bar'))
self.assertFalse(self.repo.file_exists(gen_id_2, '/foo/bar'))
@@ -1758,6 +1814,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
self.repo.set_file_key(
gen_id, '/foo/bar', obnamlib.REPO_FILE_TEST_KEY, 'yoyo')
self.repo.commit_client('fooclient')
+ self.repo.unlock_client('fooclient')
value = self.repo.get_file_key(
gen_id, '/foo/bar', obnamlib.REPO_FILE_TEST_KEY)
self.assertEqual(value, 'yoyo')
@@ -1770,12 +1827,14 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
self.repo.set_file_key(
gen_id, '/foo/bar', obnamlib.REPO_FILE_TEST_KEY, 'first')
self.repo.commit_client('fooclient')
+ self.repo.unlock_client('fooclient')
self.repo.lock_client('fooclient')
gen_id_2 = self.repo.create_generation('fooclient')
self.repo.set_file_key(
gen_id_2, '/foo/bar', obnamlib.REPO_FILE_TEST_KEY, 'second')
self.repo.commit_client('fooclient')
+ self.repo.unlock_client('fooclient')
value = self.repo.get_file_key(
gen_id, '/foo/bar', obnamlib.REPO_FILE_TEST_KEY)
@@ -1866,6 +1925,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
gen_id, '/foo/bar', obnamlib.REPO_FILE_MODE, stat.S_IFREG)
self.repo.append_file_chunk_id(gen_id, '/foo/bar', 1)
self.repo.commit_client('fooclient')
+ self.repo.unlock_client('fooclient')
self.repo.lock_client('fooclient')
gen_id_2 = self.repo.create_generation('fooclient')
@@ -1886,6 +1946,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
gen_id, '/foo/bar', obnamlib.REPO_FILE_MODE, stat.S_IFREG)
self.repo.append_file_chunk_id(gen_id, '/foo/bar', 1)
self.repo.commit_client('fooclient')
+ self.repo.unlock_client('fooclient')
self.repo.lock_client('fooclient')
gen_id_2 = self.repo.create_generation('fooclient')
@@ -1895,6 +1956,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
[1, 2])
self.repo.commit_client('fooclient')
+ self.repo.unlock_client('fooclient')
self.assertEqual(
self.repo.get_file_chunk_ids(gen_id, '/foo/bar'),
[1])
@@ -2043,6 +2105,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
token = self.repo.prepare_chunk_for_indexes('foochunk')
self.repo.put_chunk_into_indexes(chunk_id, token, 'fooclient')
self.repo.commit_chunk_indexes()
+ self.repo.unlock_chunk_indexes()
self.assertRaises(
obnamlib.RepositoryChunkIndexesNotLocked,
self.repo.remove_chunk_from_indexes, chunk_id, 'fooclient')
@@ -2054,6 +2117,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
token = self.repo.prepare_chunk_for_indexes('foochunk')
self.repo.put_chunk_into_indexes(chunk_id, token, 'fooclient')
self.repo.commit_chunk_indexes()
+ self.repo.unlock_chunk_indexes()
self.assertRaises(
obnamlib.RepositoryChunkIndexesNotLocked,
self.repo.remove_chunk_from_indexes_for_all_clients, chunk_id)
@@ -2076,9 +2140,15 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
token = self.repo.prepare_chunk_for_indexes('foochunk')
self.repo.put_chunk_into_indexes(chunk_id, token, 'fooclient')
self.repo.commit_chunk_indexes()
+ self.repo.unlock_chunk_indexes()
self.assertEqual(
self.repo.find_chunk_ids_by_content('foochunk'), [chunk_id])
+ def test_committing_does_NOT_remove_chunk_indexes_lock(self):
+ self.repo.lock_chunk_indexes()
+ self.repo.commit_chunk_indexes()
+ self.assertTrue(self.repo.got_chunk_indexes_lock())
+
def test_locking_chunk_indexes_twice_fails(self):
self.repo.lock_chunk_indexes()
self.assertRaises(
@@ -2102,6 +2172,7 @@ class RepositoryInterfaceTests(unittest.TestCase): # pragma: no cover
token = self.repo.prepare_chunk_for_indexes('foochunk')
self.repo.put_chunk_into_indexes(chunk_id, token, 'fooclient')
self.repo.commit_chunk_indexes()
+ self.repo.unlock_chunk_indexes()
ret = self.repo.validate_chunk_content(chunk_id)
self.assertTrue(ret is True or ret is None)