diff options
author | Lars Wirzenius <liw@liw.fi> | 2015-05-03 22:55:48 +0300 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2015-05-03 23:10:06 +0300 |
commit | c56a86f1e6a6d93a8e46020658c2af5ba9eacaf7 (patch) | |
tree | 74961d119b66b8d5924c6e6c51d75a6507b51b91 | |
parent | 568e56d0fb8a418c66bf55e67f104f159043a796 (diff) | |
download | obnam-c56a86f1e6a6d93a8e46020658c2af5ba9eacaf7.tar.gz |
Add a delegator class for RepoInterface implementations
-rw-r--r-- | obnamlib/__init__.py | 3 | ||||
-rw-r--r-- | obnamlib/delegator.py | 313 | ||||
-rw-r--r-- | without-tests | 1 |
3 files changed, 317 insertions, 0 deletions
diff --git a/obnamlib/__init__.py b/obnamlib/__init__.py index 9aedf0e8..a0e01c0e 100644 --- a/obnamlib/__init__.py +++ b/obnamlib/__init__.py @@ -158,6 +158,9 @@ from repo_interface import ( REPO_FILE_MD5, REPO_FILE_INTEGER_KEYS) +from .delegator import RepositoryDelegator + + # # Repository format dummy specific modules. # diff --git a/obnamlib/delegator.py b/obnamlib/delegator.py new file mode 100644 index 00000000..25f990fd --- /dev/null +++ b/obnamlib/delegator.py @@ -0,0 +1,313 @@ +# Copyright 2015 Lars Wirzenius +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# =*= License: GPL-3+ =*= + + +import copy +import hashlib +import errno +import os +import random +import StringIO + +import tracing +import yaml + +import obnamlib + + +class RepositoryDelegator(obnamlib.RepositoryInterface): + + '''Implement RepositoryInterface by delegating to other objects.''' + + def __init__(self, **kwargs): + self._fs = None + self._hooks = kwargs['hooks'] + self._lock_timeout = kwargs.get('lock_timeout', 0) + + self._client_finder = ClientFinder() + self._client_finder.set_current_time(kwargs['current_time']) + + def set_client_list_object(self, client_list): + self._client_list = client_list + self._client_finder.set_client_list(self._client_list) + + def set_chunk_store_object(self, chunk_store): + self._chunk_store = chunk_store + + def set_chunk_indexes_object(self, chunk_indexes): + self._chunk_indexes = chunk_indexes + + def set_client_factory(self, client_factory): + self._client_finder.set_client_factory(client_factory) + + def get_fs(self): + return self._fs.fs + + def set_fs(self, fs): + self._fs = obnamlib.RepositoryFS(self, fs, self._hooks) + self._lockmgr = obnamlib.LockManager(self._fs, self._lock_timeout, '') + + self._client_list.set_fs(self._fs) + self._client_list.set_lock_manager(self._lockmgr) + self._client_list.set_hooks(self._hooks) + + self._client_finder.set_fs(self._fs) + self._client_finder.set_lock_manager(self._lockmgr) + + self._chunk_store.set_fs(self._fs) + + self._chunk_indexes.set_fs(self._fs) + self._chunk_indexes.set_lock_manager(self._lockmgr) + + + # + # Client list methods. + # + + def get_client_names(self): + return self._client_list.get_client_names() + + def lock_client_list(self): + self._client_list.lock() + + def unlock_client_list(self): + self._client_list.unlock() + + def commit_client_list(self): + self._client_list.commit() + + def got_client_list_lock(self): + return self._client_list.got_lock + + def force_client_list_lock(self): + return self._client_list.force_lock() + + def add_client(self, client_name): + self._client_list.add_client(client_name) + + def remove_client(self, client_name): + self._client_list.remove_client(client_name) + + def rename_client(self, old_client_name, new_client_name): + self._client_list.rename_client(old_client_name, new_client_name) + + def get_client_encryption_key_id(self, client_name): + return self._client_list.get_client_encryption_key_id(client_name) + + def set_client_encryption_key_id(self, client_name, key_id): + return self._client_list.set_client_encryption_key_id( + client_name, key_id) + + # + # Per-client methods. + # + + def client_is_locked(self, client_name): + return self._lookup_client(client_name).is_locked() + + def _lookup_client(self, client_name): + return self._client_finder.find_client(client_name) + + def lock_client(self, client_name): + self._lookup_client(client_name).lock() + + def unlock_client(self, client_name): + self._lookup_client(client_name).unlock() + + def commit_client(self, client_name): + self._lookup_client(client_name).commit() + + def got_client_lock(self, client_name): + return self._lookup_client(client_name).got_lock + + def force_client_lock(self, client_name): + self._lookup_client(client_name).force_lock() + + def get_client_generation_ids(self, client_name): + return self._lookup_client(client_name).get_client_generation_ids() + + def create_generation(self, client_name): + return self._lookup_client(client_name).create_generation() + + def get_generation_key(self, generation_id, key): + client = self._lookup_client_by_generation(generation_id) + return client.get_generation_key(generation_id.gen_number, key) + + def _lookup_client_by_generation(self, generation_id): + return self._lookup_client(generation_id.client_name) + + def set_generation_key(self, generation_id, key, value): + if key not in self.get_allowed_generation_keys(): + raise obnamlib.RepositoryGenerationKeyNotAllowed( + client_name=generation_id.client_name, + format=self.format, + key_name=obnamlib.repo_key_name(key)) + client = self._lookup_client_by_generation(generation_id) + return client.set_generation_key(generation_id.gen_number, key, value) + + def remove_generation(self, generation_id): + client = self._lookup_client_by_generation(generation_id) + return client.remove_generation(generation_id.gen_number) + + def get_generation_chunk_ids(self, generation_id): + client = self._lookup_client_by_generation(generation_id) + return client.get_generation_chunk_ids(generation_id.gen_number) + + def file_exists(self, generation_id, filename): + client = self._lookup_client_by_generation(generation_id) + return client.file_exists(generation_id.gen_number, filename) + + def add_file(self, generation_id, filename): + client = self._lookup_client_by_generation(generation_id) + return client.add_file(generation_id.gen_number, filename) + + def remove_file(self, generation_id, filename): + client = self._lookup_client_by_generation(generation_id) + return client.remove_file(generation_id.gen_number, filename) + + def get_file_key(self, generation_id, filename, key): + if key not in self.get_allowed_file_keys(): + raise obnamlib.RepositoryFileKeyNotAllowed( + client_name=generation_id.client_name, + format=self.format) + + client = self._lookup_client_by_generation(generation_id) + return client.get_file_key(generation_id.gen_number, filename, key) + + def set_file_key(self, generation_id, filename, key, value): + if key not in self.get_allowed_file_keys(): + raise obnamlib.RepositoryFileKeyNotAllowed( + client_name=generation_id.client_name, + format=self.format) + + client = self._lookup_client_by_generation(generation_id) + return client.set_file_key( + generation_id.gen_number, filename, key, value) + + def get_file_chunk_ids(self, generation_id, filename): + client = self._lookup_client_by_generation(generation_id) + return client.get_file_chunk_ids(generation_id.gen_number, filename) + + def append_file_chunk_id(self, generation_id, filename, chunk_id): + client = self._lookup_client_by_generation(generation_id) + return client.append_file_chunk_id( + generation_id.gen_number, filename, chunk_id) + + def clear_file_chunk_ids(self, generation_id, filename): + client = self._lookup_client_by_generation(generation_id) + return client.clear_file_chunk_ids(generation_id.gen_number, filename) + + def get_file_children(self, generation_id, filename): + client = self._lookup_client_by_generation(generation_id) + return client.get_file_children(generation_id.gen_number, filename) + + # + # Chunk storage methods. + # + + def put_chunk_content(self, content): + return self._chunk_store.put_chunk_content(content) + + def get_chunk_content(self, chunk_id): + return self._chunk_store.get_chunk_content(chunk_id) + + def has_chunk(self, chunk_id): + return self._chunk_store.has_chunk(chunk_id) + + def remove_chunk(self, chunk_id): + return self._chunk_store.remove_chunk(chunk_id) + + def get_chunk_ids(self): + return self._chunk_store.get_chunk_ids() + + # + # Chunk indexes methods. + # + + def lock_chunk_indexes(self): + self._chunk_indexes.lock() + + def unlock_chunk_indexes(self): + self._chunk_indexes.unlock() + + def commit_chunk_indexes(self): + self._chunk_indexes.commit() + + def got_chunk_indexes_lock(self): + return self._chunk_indexes.got_lock + + def force_chunk_indexes_lock(self): + self._chunk_indexes.force_lock() + + def prepare_chunk_for_indexes(self, chunk_content): + return self._chunk_indexes.prepare_chunk_for_indexes(chunk_content) + + def put_chunk_into_indexes(self, chunk_id, token, client_id): + return self._chunk_indexes.put_chunk_into_indexes( + chunk_id, token, client_id) + + def find_chunk_ids_by_content(self, chunk_content): + return self._chunk_indexes.find_chunk_ids_by_content(chunk_content) + + def remove_chunk_from_indexes(self, chunk_id, client_id): + self._chunk_indexes.remove_chunk_from_indexes(chunk_id, client_id) + + def remove_chunk_from_indexes_for_all_clients(self, chunk_id): + self._chunk_indexes.remove_chunk_from_indexes_for_all_clients(chunk_id) + + def validate_chunk_content(self, chunk_id): + return self._chunk_indexes.validate_chunk_content(chunk_id) + + +class ClientFinder(object): + + def __init__(self): + self._client_factory = None + self._fs = None + self._lockmgr = None + self._client_list = None + self._clients = {} + self._current_time = None + + def set_client_factory(self, client_factory): + self._client_factory = client_factory + + def set_fs(self, fs): + self._fs = fs + + def set_lock_manager(self, lockmgr): + self._lockmgr = lockmgr + + def set_client_list(self, client_list): + self._client_list = client_list + + def set_current_time(self, current_time): + self._current_time = current_time + + def find_client(self, client_name): + if client_name not in self._client_list.get_client_names(): + raise obnamlib.RepositoryClientDoesNotExist( + client_name=client_name) + + if client_name not in self._clients: + client = self._client_factory(client_name) + client.set_fs(self._fs) + client.set_lock_manager(self._lockmgr) + client.set_current_time(self._current_time) + self._clients[client_name] = client + + return self._clients[client_name] diff --git a/without-tests b/without-tests index 98c28d66..28ab10de 100644 --- a/without-tests +++ b/without-tests @@ -1,6 +1,7 @@ setup.py obnamlib/__init__.py obnamlib/app.py +obnamlib/delegator.py obnamlib/humanise.py obnamlib/fsck_work_item.py obnamlib/repo_interface.py |