summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2013-12-27 12:16:39 +0000
committerLars Wirzenius <liw@liw.fi>2013-12-28 21:51:25 +0000
commit2697b732a03017993870d6ec013ea4b951bc7785 (patch)
treee34d6d43379abf622ee7a59533b7e3e70cdfa59a
parent69f0fd1c2f17664d98630ff3f13ea1a85445ea76 (diff)
downloadobnam-2697b732a03017993870d6ec013ea4b951bc7785.tar.gz
Cache file key settings as well, in repo fmt 6
-rw-r--r--obnamlib/repo_fmt_6.py82
-rw-r--r--test-gpghome/random_seedbin600 -> 600 bytes
2 files changed, 54 insertions, 28 deletions
diff --git a/obnamlib/repo_fmt_6.py b/obnamlib/repo_fmt_6.py
index bd601ab1..67a3f2c5 100644
--- a/obnamlib/repo_fmt_6.py
+++ b/obnamlib/repo_fmt_6.py
@@ -343,6 +343,8 @@ class RepositoryFormat6(obnamlib.RepositoryInterface):
tracing.trace('client_name=%s', client_name)
self._require_client_lock(client_name)
+ self._flush_file_key_cache()
+
open_client = self._open_clients[client_name]
if open_client.removed_generation_numbers:
@@ -726,13 +728,7 @@ class RepositoryFormat6(obnamlib.RepositoryInterface):
}
- # A cache for file key lookups. Without this, we always need to
- # fetch and decode a full, encoded obnamlib.Metadata object.
- # The dict is indexed by (generation_number, pathname) tuples,
- # and is invalidated when any change is made to any file key.
- # FIXME: This only helps with lookups, not with setting keys.
-
- self._file_key_cache = {}
+ self._setup_file_key_cache()
def _require_existing_file(self, generation_id, filename):
client_name, gen_number = generation_id
@@ -764,25 +760,59 @@ class RepositoryFormat6(obnamlib.RepositoryInterface):
def remove_file(self, generation_id, filename):
client_name, gen_number = generation_id
self._require_client_lock(client_name)
+ self._flush_file_key_cache()
client = self._open_client(client_name)
client.remove(filename) # FIXME: Only removes from unfinished gen!
def get_allowed_file_keys(self):
return self._file_keys.keys()
+ def _setup_file_key_cache(self):
+ # A cache for file key lookups and changes. We operate on a
+ # very simple heuristic: the caller will be getting or setting
+ # file keys on one file at a time, so we cache until the
+ # filename (or generation) changes. We also flush the cache
+ # when any other changes to the repository are made, such as
+ # removing generations.
+ #
+ # The dict is indexed by a (generation_id, filename) tuple,
+ # and should contain only one item. The value is a tuple of
+ # (dirty_flag, obnamlib.Metadata object).
+
+ self._file_key_cache = {}
+
+ def _get_file_key_cache_key(self, generation_id, filename):
+ return (generation_id, filename)
+
+ def _flush_file_key_cache(self):
+ for cache_key, value in self._file_key_cache.items():
+ generation_id, filename = cache_key
+ client_name, generation_number = generation_id
+ dirty, metadata = value
+ if dirty:
+ encoded_metadata = obnamlib.encode_metadata(metadata)
+ client = self._open_client(client_name)
+ # FIXME: Only sets in unfinished generation
+ client.set_metadata(filename, encoded_metadata)
+ self._setup_file_key_cache()
+
+ def _cache_file_keys_from_storage(self, generation_id, filename):
+ # FIXME: The genid should be parsed by a dedicated method
+ client_name, gen_number = generation_id
+ client = self._open_client(client_name)
+ encoded_metadata = client.get_metadata(gen_number, filename)
+ metadata = obnamlib.decode_metadata(encoded_metadata)
+ cache_key = self._get_file_key_cache_key(generation_id, filename)
+ self._file_key_cache[cache_key] = (False, metadata)
+
def get_file_key(self, generation_id, filename, key):
self._require_existing_file(generation_id, filename)
- client_name, gen_number = generation_id
-
- cache_key = (gen_number, filename)
- if cache_key in self._file_key_cache:
- metadata = self._file_key_cache[cache_key]
- else:
- client = self._open_client(client_name)
- encoded_metadata = client.get_metadata(gen_number, filename)
- metadata = obnamlib.decode_metadata(encoded_metadata)
- self._file_key_cache[cache_key] = metadata
+ cache_key = self._get_file_key_cache_key(generation_id, filename)
+ if cache_key not in self._file_key_cache:
+ self._flush_file_key_cache()
+ self._cache_file_keys_from_storage(generation_id, filename)
+ dirty, metadata = self._file_key_cache[cache_key]
if key in self._file_keys:
value = getattr(metadata, self._file_keys[key])
@@ -791,6 +821,7 @@ class RepositoryFormat6(obnamlib.RepositoryInterface):
else:
return value or ''
else:
+ client_name, gen_number = generation_id
raise obnamlib.RepositoryFileKeyNotAllowed(
self.format, client_name, key)
@@ -799,24 +830,19 @@ class RepositoryFormat6(obnamlib.RepositoryInterface):
self._require_client_lock(client_name)
self._require_existing_file(generation_id, filename)
- # Invalidate the file key cache.
- self._file_key_cache = {}
-
- client = self._open_client(client_name)
-
- encoded_metadata = client.get_metadata(gen_number, filename)
- metadata = obnamlib.decode_metadata(encoded_metadata)
+ cache_key = self._get_file_key_cache_key(generation_id, filename)
+ if cache_key not in self._file_key_cache:
+ self._flush_file_key_cache()
+ self._cache_file_keys_from_storage(generation_id, filename)
+ dirty, metadata = self._file_key_cache[cache_key]
if key in self._file_keys:
setattr(metadata, self._file_keys[key], value)
+ self._file_key_cache[cache_key] = (True, metadata)
else:
raise obnamlib.RepositoryFileKeyNotAllowed(
self.format, client_name, key)
- encoded_metadata = obnamlib.encode_metadata(metadata)
- # FIXME: Only sets in unfinished generation
- client.set_metadata(filename, encoded_metadata)
-
def get_file_chunk_ids(self, generation_id, filename):
self._require_existing_file(generation_id, filename)
client_name, gen_number = generation_id
diff --git a/test-gpghome/random_seed b/test-gpghome/random_seed
index b8fbeb97..e1fd53c3 100644
--- a/test-gpghome/random_seed
+++ b/test-gpghome/random_seed
Binary files differ