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>2013-06-22 07:19:02 (GMT)
committer Sascha Silbe <sascha-pgp@silbe.org>2013-11-16 20:12:23 (GMT)
commit41afb73b7ecb5e5e3e3d0c0d8916554367170c59 (patch)
tree78adaa45b5f90c5e665bd6b83a6c7e621ebcbe22
parent50c35b7a071de620e6e4505d8afb98f0e94a21b7 (diff)
fsemulation: don't try to duplicate data store / Xapian matching
_matches_root_query() was meant to verify that a requested entity has actually been exported by the user (using root_query). But in order to do that, a lot of the matching functionality in the data store (usually implemented using Xapian) would have to be duplicated for any except the most basic export selections to work. E.g. exporting based on tags needs to work on parts (words) of a single value, rather than an exact match on the full string. Instead, let the data store do the verification by using its searching API even if we already know the object id. There's some performance impact to this, but it's not clear a reasonably functional _matches_root_query() would be much faster.
-rw-r--r--fsemulation.py33
1 files changed, 21 insertions, 12 deletions
diff --git a/fsemulation.py b/fsemulation.py
index 26b5cb9..beade38 100644
--- a/fsemulation.py
+++ b/fsemulation.py
@@ -135,8 +135,8 @@ class DataStore(object):
Only return the latest version of each entry for data stores with
version support.
"""
- query = dict(query or {})
- query.update(self._root_query)
+ query = self._merge_root_query(query)
+
if self._data_store.dbus_interface == DS_DBUS_INTERFACE2:
options = {'metadata': ['tree_id', 'version_id'],
'order_by': ['-timestamp']}
@@ -165,8 +165,7 @@ class DataStore(object):
Returns a list of tuples containing the object_id and metadata.
"""
- query = dict(query or {})
- query.update(self._root_query)
+ query = self._merge_root_query(query)
properties = list(_USEFUL_PROPS)
if self._data_store.dbus_interface == DS_DBUS_INTERFACE2:
@@ -205,15 +204,15 @@ class DataStore(object):
@synchronised
def list_tree_ids(self, query=None):
"""Retrieve the tree_ids of all (matching) data store entries"""
+ query = self._merge_root_query(query)
return [unicode(entry[0]) for entry in self.list_object_ids(query)]
@synchronised
def list_property_values(self, name, query=None):
"""Return all unique values of the given property"""
assert isinstance(name, unicode)
+ query = self._merge_root_query(query)
- 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,
@@ -239,7 +238,7 @@ class DataStore(object):
return False
raise
- return self._matches_root_query(entry)
+ return True
@synchronised
def check_tree_id(self, tree_id):
@@ -306,11 +305,17 @@ class DataStore(object):
else:
assert isinstance(object_id, unicode)
+ query['uid'] = object_id
+ results = self._data_store.find(query, names or [],
+ timeout=DBUS_TIMEOUT_MAX,
+ byte_arrays=True)[0]
+
metadata = self._data_store.get_properties(object_id,
byte_arrays=True)
- if not self._matches_root_query(metadata):
+ if not results:
raise ValueError('Object %r does not exist' % (object_id, ))
+ metadata = results[0]
metadata['uid'] = object_id
if names:
metadata = dict([(name, metadata[name]) for name in names
@@ -469,10 +474,14 @@ 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 _merge_root_query(self, query):
+ query = dict(query or {})
+ xapian_query = query.get('query', '')
+ query.update(self._root_query)
+ if ('query' in self._root_query) and xapian_query:
+ query['query'] = '(%s) AND (%s)' % (self._root_query['query'],
+ xapian_query)
+ return query
def _convert_metadata(self, metadata):
"""Convert metadata (as returned by the data store) to a unicode dict