diff options
author | Sascha Silbe <sascha-pgp@silbe.org> | 2012-04-03 10:10:43 (GMT) |
---|---|---|
committer | Sascha Silbe <sascha-pgp@silbe.org> | 2013-11-16 20:12:12 (GMT) |
commit | 50c35b7a071de620e6e4505d8afb98f0e94a21b7 (patch) | |
tree | 1775a697919f18369bb57dc37719cdbbf319f0e1 | |
parent | b434cf9633b6fa8c80f32d969e1607cef1d72b89 (diff) |
fsemulation: add support for root query
The root query is used to restrict the file system view to a certain subset of
the data store.
-rw-r--r-- | fsemulation.py | 64 |
1 files changed, 44 insertions, 20 deletions
diff --git a/fsemulation.py b/fsemulation.py index a18abdf..26b5cb9 100644 --- a/fsemulation.py +++ b/fsemulation.py @@ -94,7 +94,8 @@ class _LRU(collections.MutableMapping): class DataStore(object): - def __init__(self): + def __init__(self, root_query): + self._root_query = root_query self.supports_versions = False self._lock = threading.RLock() self._data_store_version = 0 @@ -134,7 +135,8 @@ class DataStore(object): Only return the latest version of each entry for data stores with version support. """ - query = query or {} + query = dict(query or {}) + query.update(self._root_query) if self._data_store.dbus_interface == DS_DBUS_INTERFACE2: options = {'metadata': ['tree_id', 'version_id'], 'order_by': ['-timestamp']} @@ -163,7 +165,8 @@ class DataStore(object): Returns a list of tuples containing the object_id and metadata. """ - query = query or {} + query = dict(query or {}) + query.update(self._root_query) properties = list(_USEFUL_PROPS) if self._data_store.dbus_interface == DS_DBUS_INTERFACE2: @@ -192,9 +195,11 @@ class DataStore(object): @synchronised def list_versions(self, tree_id): """Retrieve all version_ids of the given data store entry""" + query = dict(self._root_query) + query['tree_id'] = tree_id options = {'all_versions': True, 'order_by': ['-timestamp']} return [unicode(entry['version_id']) - for entry in self._data_store.find({'tree_id': tree_id}, + for entry in self._data_store.find(query, options, timeout=DBUS_TIMEOUT_MAX, byte_arrays=True)[0]] @synchronised @@ -207,7 +212,8 @@ class DataStore(object): """Return all unique values of the given property""" assert isinstance(name, unicode) - query = query or {} + query = dict(query or {}) + query.update(self._root_query) if self._data_store.dbus_interface == DS_DBUS_INTERFACE2: options = {'metadata': [name], 'all_versions': True} entries = self._data_store.find(query, options, @@ -227,19 +233,21 @@ class DataStore(object): def check_object_id(self, object_id): """Return True if the given object_id identifies a data store entry""" try: - self.get_properties(object_id, [u'uid']) + entry = self.get_properties(object_id, self._root_query.keys()) except dbus.DBusException, exception: if exception.get_dbus_name() == DBUS_PYTHON_VALUE_ERROR: return False raise - return True + return self._matches_root_query(entry) @synchronised def check_tree_id(self, tree_id): """Return True if the given tree_id identifies a data store entry""" assert isinstance(tree_id, unicode) - results = self._data_store.find({'tree_id': tree_id}, {}, + query = dict(self._root_query) + query['tree_id'] = tree_id + results = self._data_store.find(query, {}, timeout=DBUS_TIMEOUT_MAX, byte_arrays=True)[0] return bool(results) @@ -253,13 +261,16 @@ class DataStore(object): assert isinstance(word, unicode) query_string = u'%s:"%s"' % (name, word.replace(u'"', u'')) + query = dict(self._root_query) if self._data_store.dbus_interface == DS_DBUS_INTERFACE2: options = {'limit': 1} - results = self._data_store.text_search({}, query_string, options, + results = self._data_store.text_search(query, query_string, + options, timeout=DBUS_TIMEOUT_MAX, byte_arrays=True)[0] else: - query = {'query': query_string, 'limit': 1} + query['query'] = query_string + query['limit'] = 1 results = self._data_store.find(query, [name], timeout=DBUS_TIMEOUT_MAX, byte_arrays=True)[0] @@ -272,12 +283,14 @@ class DataStore(object): Returns a dictionary with unicode strings as keys and values. """ + query = dict(self._root_query) if self._data_store.dbus_interface == DS_DBUS_INTERFACE2: tree_id, version_id = object_id assert isinstance(tree_id, unicode) assert isinstance(version_id, unicode) - query = {'tree_id': tree_id, 'version_id': version_id} + query['tree_id'] = tree_id + query['version_id'] = version_id options = {} if names: options['metadata'] = names @@ -295,6 +308,9 @@ class DataStore(object): metadata = self._data_store.get_properties(object_id, byte_arrays=True) + if not self._matches_root_query(metadata): + raise ValueError('Object %r does not exist' % (object_id, )) + metadata['uid'] = object_id if names: metadata = dict([(name, metadata[name]) for name in names @@ -369,16 +385,17 @@ class DataStore(object): @synchronised def remove_entry(self, object_id): """Remove a single (version of a) data store entry""" + # Make sure we don't allow deleting entries that don't match + # the root query. + if not self.check_object_id(object_id): + raise ValueError('Object %r does not exist' % (object_id, )) + if self._data_store.dbus_interface == DS_DBUS_INTERFACE2: tree_id, version_id = object_id - assert isinstance(tree_id, unicode) - assert isinstance(version_id, unicode) - self._data_store.delete(tree_id, version_id, timeout=DBUS_TIMEOUT_MAX) else: - assert isinstance(object_id, unicode) self._data_store.delete(object_id, timeout=DBUS_TIMEOUT_MAX) @synchronised @@ -402,15 +419,17 @@ class DataStore(object): @synchronised def get_data(self, object_id): """Return path to data for data store entry identified by object_id.""" + # Make sure we don't allow deleting entries that don't match + # the root query. + if not self.check_object_id(object_id): + raise ValueError('Object %r does not exist' % (object_id, )) + if self._data_store.dbus_interface == DS_DBUS_INTERFACE2: tree_id, version_id = object_id - assert isinstance(tree_id, unicode) - assert isinstance(version_id, unicode) return self._data_store.get_data(tree_id, version_id, byte_arrays=True) else: - assert isinstance(object_id, unicode) return self._data_store.get_filename(object_id, byte_arrays=True) @synchronised @@ -450,6 +469,11 @@ class DataStore(object): timeout=DBUS_TIMEOUT_MAX) return unicode(object_id) + def _matches_root_query(self, metadata): + """Return True if metadata matches the root query""" + return not [True for key, value in self._root_query.items() + if metadata.get(key) != value] + def _convert_metadata(self, metadata): """Convert metadata (as returned by the data store) to a unicode dict @@ -938,8 +962,8 @@ class FSEmulation(object): # public API - def __init__(self): - self.data_store = DataStore() + def __init__(self, root_query=None): + self.data_store = DataStore(root_query or {}) # FIXME: determine good LRU size self._cache = _LRU(500) self._root_dir = RootDirectory(self, 0550) |