Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha 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)
commit50c35b7a071de620e6e4505d8afb98f0e94a21b7 (patch)
tree1775a697919f18369bb57dc37719cdbbf319f0e1
parentb434cf9633b6fa8c80f32d969e1607cef1d72b89 (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.py64
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)