diff options
author | Sascha Silbe <sascha-pgp@silbe.org> | 2013-06-22 07:19:02 (GMT) |
---|---|---|
committer | Sascha Silbe <sascha-pgp@silbe.org> | 2013-06-22 07:19:02 (GMT) |
commit | 2111710c5f18fa0409fa181e5bebf660fc7823cb (patch) | |
tree | 049f0da7ef90322f9411bc7410ca889e4acb4361 | |
parent | 5a1d619477c14c82be3bcc199a203a594899b234 (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.py | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/fsemulation.py b/fsemulation.py index 5077265..58120fb 100644 --- a/fsemulation.py +++ b/fsemulation.py @@ -120,8 +120,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']} @@ -149,8 +149,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: @@ -187,14 +186,14 @@ class DataStore(object): 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)] 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, @@ -219,7 +218,7 @@ class DataStore(object): return False raise - return self._matches_root_query(entry) + return True def check_tree_id(self, tree_id): """Return True if the given tree_id identifies a data store entry""" @@ -283,11 +282,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 @@ -436,10 +441,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 |