summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2015-06-07 19:26:21 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2015-06-07 19:26:21 +0200
commit810543a625074fb8685c7c59e36123c055e8fda6 (patch)
tree3ea4d74e26d74d022398447a9ede000c3023b181
parent235a85211c769e190754d2fdb172069d68a889b9 (diff)
downloadsink-810543a625074fb8685c7c59e36123c055e8fda6.tar.gz
sink-810543a625074fb8685c7c59e36123c055e8fda6.zip
Use type-specific index implementations.
-rw-r--r--common/domain/event.cpp3
-rw-r--r--common/domain/event.h5
-rw-r--r--examples/dummyresource/facade.cpp57
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 @@
32 32
33using namespace Akonadi2::ApplicationDomain; 33using namespace Akonadi2::ApplicationDomain;
34 34
35ResultSet TypeImplementation<Event>::queryIndexes(const Akonadi2::Query &query, const QByteArray &resourceInstanceIdentifier) 35ResultSet TypeImplementation<Event>::queryIndexes(const Akonadi2::Query &query, const QByteArray &resourceInstanceIdentifier, QSet<QByteArray> &appliedFilters)
36{ 36{
37 QVector<QByteArray> keys; 37 QVector<QByteArray> keys;
38 if (query.propertyFilter.contains("uid")) { 38 if (query.propertyFilter.contains("uid")) {
@@ -43,6 +43,7 @@ ResultSet TypeImplementation<Event>::queryIndexes(const Akonadi2::Query &query,
43 [](const Index::Error &error) { 43 [](const Index::Error &error) {
44 Warning() << "Error in index: " << error.message; 44 Warning() << "Error in index: " << error.message;
45 }); 45 });
46 appliedFilters << "uid";
46 } 47 }
47 return ResultSet(keys); 48 return ResultSet(keys);
48} 49}
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 {
39 39
40/** 40/**
41 * Implements all type-specific code such as updating and querying indexes. 41 * Implements all type-specific code such as updating and querying indexes.
42 *
43 * These are type specifiy default implementations. Theoretically a resource could implement it's own implementation.
42 */ 44 */
43template<> 45template<>
44class TypeImplementation<Akonadi2::ApplicationDomain::Event> { 46class TypeImplementation<Akonadi2::ApplicationDomain::Event> {
45public: 47public:
46 typedef Akonadi2::ApplicationDomain::Buffer::Event Buffer; 48 typedef Akonadi2::ApplicationDomain::Buffer::Event Buffer;
47 typedef Akonadi2::ApplicationDomain::Buffer::EventBuilder BufferBuilder; 49 typedef Akonadi2::ApplicationDomain::Buffer::EventBuilder BufferBuilder;
50 static QSet<QByteArray> indexedProperties();
48 /** 51 /**
49 * Returns the potential result set based on the indexes. 52 * Returns the potential result set based on the indexes.
50 * 53 *
51 * An empty result set indicates that a full scan is required. 54 * An empty result set indicates that a full scan is required.
52 */ 55 */
53 static ResultSet queryIndexes(const Akonadi2::Query &query, const QByteArray &resourceInstanceIdentifier); 56 static ResultSet queryIndexes(const Akonadi2::Query &query, const QByteArray &resourceInstanceIdentifier, QSet<QByteArray> &appliedFilters);
54 static void index(const Event &type); 57 static void index(const Event &type);
55 static QSharedPointer<ReadPropertyMapper<Buffer> > initializeReadPropertyMapper(); 58 static QSharedPointer<ReadPropertyMapper<Buffer> > initializeReadPropertyMapper();
56 static QSharedPointer<WritePropertyMapper<BufferBuilder> > initializeWritePropertyMapper(); 59 static QSharedPointer<WritePropertyMapper<BufferBuilder> > 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()
48{ 48{
49} 49}
50 50
51static std::function<bool(const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local)> prepareQuery(const Akonadi2::Query &query)
52{
53 //Compose some functions to make query matching fast.
54 //This way we can process the query once, and convert all values into something that can be compared quickly
55 std::function<bool(const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local)> preparedQuery;
56 if (!query.ids.isEmpty()) {
57 //Match by id
58 //TODO: for id's a direct lookup would be way faster
59
60 //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)
61 //Probably a premature optimization, but perhaps a useful technique to be investigated.
62 QVector<std::string> ids;
63 for (const auto &id : query.ids) {
64 ids << id.toStdString();
65 }
66 preparedQuery = [ids](const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local) {
67 if (ids.contains(key)) {
68 return true;
69 }
70 return false;
71 };
72 } else if (!query.propertyFilter.isEmpty()) {
73 if (query.propertyFilter.contains("uid")) {
74 const QByteArray uid = query.propertyFilter.value("uid").toByteArray();
75 preparedQuery = [uid](const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local) {
76 if (local && local->uid() && (QByteArray::fromRawData(local->uid()->c_str(), local->uid()->size()) == uid)) {
77 return true;
78 }
79 return false;
80 };
81 }
82 } else {
83 //Match everything
84 preparedQuery = [](const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local) {
85 return true;
86 };
87 }
88 return preparedQuery;
89}
90
91static void scan(const QSharedPointer<Akonadi2::Storage> &storage, const QByteArray &key, std::function<bool(const QByteArray &key, const Akonadi2::Entity &entity, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local, Akonadi2::Metadata const *metadata)> callback) 51static void scan(const QSharedPointer<Akonadi2::Storage> &storage, const QByteArray &key, std::function<bool(const QByteArray &key, const Akonadi2::Entity &entity, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local, Akonadi2::Metadata const *metadata)> callback)
92{ 52{
93 storage->scan(key, [=](void *keyValue, int keySize, void *dataValue, int dataSize) -> bool { 53 storage->scan(key, [=](void *keyValue, int keySize, void *dataValue, int dataSize) -> bool {
@@ -130,22 +90,17 @@ void DummyResourceFacade::readValue(const QSharedPointer<Akonadi2::Storage> &sto
130 90
131static ResultSet getResultSet(const Akonadi2::Query &query, const QSharedPointer<Akonadi2::Storage> &storage) 91static ResultSet getResultSet(const Akonadi2::Query &query, const QSharedPointer<Akonadi2::Storage> &storage)
132{ 92{
133 auto resultSet = Akonadi2::ApplicationDomain::TypeImplementation<Akonadi2::ApplicationDomain::Event>::queryIndexes(query, "org.kde.dummy"); 93 QSet<QByteArray> appliedFilters;
94 ResultSet resultSet = Akonadi2::ApplicationDomain::TypeImplementation<Akonadi2::ApplicationDomain::Event>::queryIndexes(query, "org.kde.dummy", appliedFilters);
95 const auto remainingFilters = query.propertyFilter.keys().toSet() - appliedFilters;
134 96
135 //Scan for where we don't have an index
136 //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
137 //TODO: the prepared query should be generalized in TypeImplementation on top of domain adaptors
138 if (resultSet.isEmpty()) { 97 if (resultSet.isEmpty()) {
139 QVector<QByteArray> keys; 98 QVector<QByteArray> keys;
140 const auto preparedQuery = prepareQuery(query); 99 scan(storage, QByteArray(), [=, &keys](const QByteArray &key, const Akonadi2::Entity &entity, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local, Akonadi2::Metadata const *metadataBuffer) {
141 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) { 100 keys << key;
142 //TODO use adapter for query and scan?
143 if (preparedQuery && preparedQuery(std::string(key.constData(), key.size()), buffer, local)) {
144 keys << key;
145 }
146 return true; 101 return true;
147 }); 102 });
148 return ResultSet(keys); 103 resultSet = ResultSet(keys);
149 } 104 }
150 105
151 return resultSet; 106 return resultSet;