From 810543a625074fb8685c7c59e36123c055e8fda6 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Sun, 7 Jun 2015 19:26:21 +0200 Subject: Use type-specific index implementations. --- common/domain/event.cpp | 3 ++- common/domain/event.h | 5 +++- examples/dummyresource/facade.cpp | 57 +++++---------------------------------- 3 files changed, 12 insertions(+), 53 deletions(-) diff --git a/common/domain/event.cpp b/common/domain/event.cpp index 776fa50..c435c6b 100644 --- a/common/domain/event.cpp +++ b/common/domain/event.cpp @@ -32,7 +32,7 @@ using namespace Akonadi2::ApplicationDomain; -ResultSet TypeImplementation::queryIndexes(const Akonadi2::Query &query, const QByteArray &resourceInstanceIdentifier) +ResultSet TypeImplementation::queryIndexes(const Akonadi2::Query &query, const QByteArray &resourceInstanceIdentifier, QSet &appliedFilters) { QVector keys; if (query.propertyFilter.contains("uid")) { @@ -43,6 +43,7 @@ ResultSet TypeImplementation::queryIndexes(const Akonadi2::Query &query, [](const Index::Error &error) { Warning() << "Error in index: " << error.message; }); + appliedFilters << "uid"; } return ResultSet(keys); } diff --git a/common/domain/event.h b/common/domain/event.h index d40e55d..68c684a 100644 --- a/common/domain/event.h +++ b/common/domain/event.h @@ -39,18 +39,21 @@ namespace ApplicationDomain { /** * Implements all type-specific code such as updating and querying indexes. + * + * These are type specifiy default implementations. Theoretically a resource could implement it's own implementation. */ template<> class TypeImplementation { public: typedef Akonadi2::ApplicationDomain::Buffer::Event Buffer; typedef Akonadi2::ApplicationDomain::Buffer::EventBuilder BufferBuilder; + static QSet indexedProperties(); /** * Returns the potential result set based on the indexes. * * An empty result set indicates that a full scan is required. */ - static ResultSet queryIndexes(const Akonadi2::Query &query, const QByteArray &resourceInstanceIdentifier); + static ResultSet queryIndexes(const Akonadi2::Query &query, const QByteArray &resourceInstanceIdentifier, QSet &appliedFilters); static void index(const Event &type); static QSharedPointer > initializeReadPropertyMapper(); static QSharedPointer > initializeWritePropertyMapper(); diff --git a/examples/dummyresource/facade.cpp b/examples/dummyresource/facade.cpp index e678214..9849a92 100644 --- a/examples/dummyresource/facade.cpp +++ b/examples/dummyresource/facade.cpp @@ -48,46 +48,6 @@ DummyResourceFacade::~DummyResourceFacade() { } -static std::function prepareQuery(const Akonadi2::Query &query) -{ - //Compose some functions to make query matching fast. - //This way we can process the query once, and convert all values into something that can be compared quickly - std::function preparedQuery; - if (!query.ids.isEmpty()) { - //Match by id - //TODO: for id's a direct lookup would be way faster - - //We convert the id's to std::string so we don't have to convert each key during the scan. (This runs only once, and the query will be run for every key) - //Probably a premature optimization, but perhaps a useful technique to be investigated. - QVector ids; - for (const auto &id : query.ids) { - ids << id.toStdString(); - } - preparedQuery = [ids](const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local) { - if (ids.contains(key)) { - return true; - } - return false; - }; - } else if (!query.propertyFilter.isEmpty()) { - if (query.propertyFilter.contains("uid")) { - const QByteArray uid = query.propertyFilter.value("uid").toByteArray(); - preparedQuery = [uid](const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local) { - if (local && local->uid() && (QByteArray::fromRawData(local->uid()->c_str(), local->uid()->size()) == uid)) { - return true; - } - return false; - }; - } - } else { - //Match everything - preparedQuery = [](const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local) { - return true; - }; - } - return preparedQuery; -} - static void scan(const QSharedPointer &storage, const QByteArray &key, std::function callback) { storage->scan(key, [=](void *keyValue, int keySize, void *dataValue, int dataSize) -> bool { @@ -130,22 +90,17 @@ void DummyResourceFacade::readValue(const QSharedPointer &sto static ResultSet getResultSet(const Akonadi2::Query &query, const QSharedPointer &storage) { - auto resultSet = Akonadi2::ApplicationDomain::TypeImplementation::queryIndexes(query, "org.kde.dummy"); + QSet appliedFilters; + ResultSet resultSet = Akonadi2::ApplicationDomain::TypeImplementation::queryIndexes(query, "org.kde.dummy", appliedFilters); + const auto remainingFilters = query.propertyFilter.keys().toSet() - appliedFilters; - //Scan for where we don't have an index - //TODO: we may want a way for queryIndexes to indicate that the resultSet is not final, and that a scan over the remaining set is required - //TODO: the prepared query should be generalized in TypeImplementation on top of domain adaptors if (resultSet.isEmpty()) { QVector keys; - const auto preparedQuery = prepareQuery(query); - scan(storage, QByteArray(), [preparedQuery, &keys](const QByteArray &key, const Akonadi2::Entity &entity, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local, Akonadi2::Metadata const *metadataBuffer) { - //TODO use adapter for query and scan? - if (preparedQuery && preparedQuery(std::string(key.constData(), key.size()), buffer, local)) { - keys << key; - } + scan(storage, QByteArray(), [=, &keys](const QByteArray &key, const Akonadi2::Entity &entity, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local, Akonadi2::Metadata const *metadataBuffer) { + keys << key; return true; }); - return ResultSet(keys); + resultSet = ResultSet(keys); } return resultSet; -- cgit v1.2.3