summaryrefslogtreecommitdiffstats
path: root/dummyresource/facade.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dummyresource/facade.cpp')
-rw-r--r--dummyresource/facade.cpp89
1 files changed, 23 insertions, 66 deletions
diff --git a/dummyresource/facade.cpp b/dummyresource/facade.cpp
index 949b4c4..1477fcf 100644
--- a/dummyresource/facade.cpp
+++ b/dummyresource/facade.cpp
@@ -28,7 +28,6 @@
28#include "event_generated.h" 28#include "event_generated.h"
29#include "entity_generated.h" 29#include "entity_generated.h"
30#include "metadata_generated.h" 30#include "metadata_generated.h"
31#include "createentity_generated.h"
32#include "domainadaptor.h" 31#include "domainadaptor.h"
33#include <common/entitybuffer.h> 32#include <common/entitybuffer.h>
34#include <common/index.h> 33#include <common/index.h>
@@ -37,9 +36,9 @@
37using namespace DummyCalendar; 36using namespace DummyCalendar;
38using namespace flatbuffers; 37using namespace flatbuffers;
39 38
39
40DummyResourceFacade::DummyResourceFacade() 40DummyResourceFacade::DummyResourceFacade()
41 : Akonadi2::StoreFacade<Akonadi2::Domain::Event>(), 41 : Akonadi2::GenericFacade<Akonadi2::ApplicationDomain::Event>("org.kde.dummy"),
42 mResourceAccess(new Akonadi2::ResourceAccess("org.kde.dummy")),
43 mFactory(new DummyEventAdaptorFactory) 42 mFactory(new DummyEventAdaptorFactory)
44{ 43{
45} 44}
@@ -48,38 +47,30 @@ DummyResourceFacade::~DummyResourceFacade()
48{ 47{
49} 48}
50 49
51Async::Job<void> DummyResourceFacade::create(const Akonadi2::Domain::Event &domainObject) 50Async::Job<void> DummyResourceFacade::create(const Akonadi2::ApplicationDomain::Event &domainObject)
52{ 51{
53 flatbuffers::FlatBufferBuilder entityFbb; 52 flatbuffers::FlatBufferBuilder entityFbb;
54 mFactory->createBuffer(domainObject, entityFbb); 53 mFactory->createBuffer(domainObject, entityFbb);
55 54 return sendCreateCommand("event", QByteArray::fromRawData(reinterpret_cast<const char*>(entityFbb.GetBufferPointer()), entityFbb.GetSize()));
56 flatbuffers::FlatBufferBuilder fbb;
57 //This is the resource buffer type and not the domain type
58 auto type = fbb.CreateString("event");
59 auto delta = fbb.CreateVector<uint8_t>(entityFbb.GetBufferPointer(), entityFbb.GetSize());
60 auto location = Akonadi2::Commands::CreateCreateEntity(fbb, type, delta);
61 Akonadi2::Commands::FinishCreateEntityBuffer(fbb, location);
62 mResourceAccess->open();
63 return mResourceAccess->sendCommand(Akonadi2::Commands::CreateEntityCommand, fbb);
64} 55}
65 56
66Async::Job<void> DummyResourceFacade::modify(const Akonadi2::Domain::Event &domainObject) 57Async::Job<void> DummyResourceFacade::modify(const Akonadi2::ApplicationDomain::Event &domainObject)
67{ 58{
68 //Create message buffer and send to resource 59 //Create message buffer and send to resource
69 return Async::null<void>(); 60 return Async::null<void>();
70} 61}
71 62
72Async::Job<void> DummyResourceFacade::remove(const Akonadi2::Domain::Event &domainObject) 63Async::Job<void> DummyResourceFacade::remove(const Akonadi2::ApplicationDomain::Event &domainObject)
73{ 64{
74 //Create message buffer and send to resource 65 //Create message buffer and send to resource
75 return Async::null<void>(); 66 return Async::null<void>();
76} 67}
77 68
78static std::function<bool(const std::string &key, DummyEvent const *buffer, Akonadi2::Domain::Buffer::Event const *local)> prepareQuery(const Akonadi2::Query &query) 69static std::function<bool(const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local)> prepareQuery(const Akonadi2::Query &query)
79{ 70{
80 //Compose some functions to make query matching fast. 71 //Compose some functions to make query matching fast.
81 //This way we can process the query once, and convert all values into something that can be compared quickly 72 //This way we can process the query once, and convert all values into something that can be compared quickly
82 std::function<bool(const std::string &key, DummyEvent const *buffer, Akonadi2::Domain::Buffer::Event const *local)> preparedQuery; 73 std::function<bool(const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local)> preparedQuery;
83 if (!query.ids.isEmpty()) { 74 if (!query.ids.isEmpty()) {
84 //Match by id 75 //Match by id
85 //TODO: for id's a direct lookup would be way faster 76 //TODO: for id's a direct lookup would be way faster
@@ -90,7 +81,7 @@ static std::function<bool(const std::string &key, DummyEvent const *buffer, Akon
90 for (const auto &id : query.ids) { 81 for (const auto &id : query.ids) {
91 ids << id.toStdString(); 82 ids << id.toStdString();
92 } 83 }
93 preparedQuery = [ids](const std::string &key, DummyEvent const *buffer, Akonadi2::Domain::Buffer::Event const *local) { 84 preparedQuery = [ids](const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local) {
94 if (ids.contains(key)) { 85 if (ids.contains(key)) {
95 return true; 86 return true;
96 } 87 }
@@ -99,7 +90,7 @@ static std::function<bool(const std::string &key, DummyEvent const *buffer, Akon
99 } else if (!query.propertyFilter.isEmpty()) { 90 } else if (!query.propertyFilter.isEmpty()) {
100 if (query.propertyFilter.contains("uid")) { 91 if (query.propertyFilter.contains("uid")) {
101 const QByteArray uid = query.propertyFilter.value("uid").toByteArray(); 92 const QByteArray uid = query.propertyFilter.value("uid").toByteArray();
102 preparedQuery = [uid](const std::string &key, DummyEvent const *buffer, Akonadi2::Domain::Buffer::Event const *local) { 93 preparedQuery = [uid](const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local) {
103 if (local && local->uid() && (QByteArray::fromRawData(local->uid()->c_str(), local->uid()->size()) == uid)) { 94 if (local && local->uid() && (QByteArray::fromRawData(local->uid()->c_str(), local->uid()->size()) == uid)) {
104 return true; 95 return true;
105 } 96 }
@@ -108,32 +99,14 @@ static std::function<bool(const std::string &key, DummyEvent const *buffer, Akon
108 } 99 }
109 } else { 100 } else {
110 //Match everything 101 //Match everything
111 preparedQuery = [](const std::string &key, DummyEvent const *buffer, Akonadi2::Domain::Buffer::Event const *local) { 102 preparedQuery = [](const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local) {
112 return true; 103 return true;
113 }; 104 };
114 } 105 }
115 return preparedQuery; 106 return preparedQuery;
116} 107}
117 108
118Async::Job<void> DummyResourceFacade::synchronizeResource(bool sync, bool processAll) 109void DummyResourceFacade::readValue(QSharedPointer<Akonadi2::Storage> storage, const QByteArray &key, const std::function<void(const Akonadi2::ApplicationDomain::Event::Ptr &)> &resultCallback, std::function<bool(const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local)> preparedQuery)
119{
120 //TODO check if a sync is necessary
121 //TODO Only sync what was requested
122 //TODO timeout
123
124 if (sync || processAll) {
125 return Async::start<void>([=](Async::Future<void> &future) {
126 mResourceAccess->open();
127 mResourceAccess->synchronizeResource(sync, processAll).then<void>([&future](Async::Future<void> &f) {
128 future.setFinished();
129 f.setFinished();
130 }).exec();
131 });
132 }
133 return Async::null<void>();
134}
135
136void DummyResourceFacade::readValue(QSharedPointer<Akonadi2::Storage> storage, const QByteArray &key, const std::function<void(const Akonadi2::Domain::Event::Ptr &)> &resultCallback, std::function<bool(const std::string &key, DummyEvent const *buffer, Akonadi2::Domain::Buffer::Event const *local)> preparedQuery)
137{ 110{
138 storage->scan(key, [=](void *keyValue, int keySize, void *dataValue, int dataSize) -> bool { 111 storage->scan(key, [=](void *keyValue, int keySize, void *dataValue, int dataSize) -> bool {
139 112
@@ -145,31 +118,11 @@ void DummyResourceFacade::readValue(QSharedPointer<Akonadi2::Storage> storage, c
145 //Extract buffers 118 //Extract buffers
146 Akonadi2::EntityBuffer buffer(dataValue, dataSize); 119 Akonadi2::EntityBuffer buffer(dataValue, dataSize);
147 120
148 DummyEvent const *resourceBuffer = 0; 121 const auto resourceBuffer = Akonadi2::EntityBuffer::readBuffer<DummyEvent>(buffer.entity().resource());
149 if (auto resourceData = buffer.entity().resource()) { 122 const auto localBuffer = Akonadi2::EntityBuffer::readBuffer<Akonadi2::ApplicationDomain::Buffer::Event>(buffer.entity().local());
150 flatbuffers::Verifier verifyer(resourceData->Data(), resourceData->size()); 123 const auto metadataBuffer = Akonadi2::EntityBuffer::readBuffer<Akonadi2::Metadata>(buffer.entity().metadata());
151 if (VerifyDummyEventBuffer(verifyer)) {
152 resourceBuffer = GetDummyEvent(resourceData->Data());
153 }
154 }
155
156 Akonadi2::Domain::Buffer::Event const *localBuffer = 0;
157 if (auto localData = buffer.entity().local()) {
158 flatbuffers::Verifier verifyer(localData->Data(), localData->size());
159 if (Akonadi2::Domain::Buffer::VerifyEventBuffer(verifyer)) {
160 localBuffer = Akonadi2::Domain::Buffer::GetEvent(localData->Data());
161 }
162 }
163
164 Akonadi2::Metadata const *metadataBuffer = 0;
165 if (auto metadataData = buffer.entity().metadata()) {
166 flatbuffers::Verifier verifyer(metadataData->Data(), metadataData->size());
167 if (Akonadi2::VerifyMetadataBuffer(verifyer)) {
168 metadataBuffer = Akonadi2::GetMetadata(metadataData->Data());
169 }
170 }
171 124
172 if (!resourceBuffer || !metadataBuffer) { 125 if ((!resourceBuffer && !localBuffer) || !metadataBuffer) {
173 qWarning() << "invalid buffer " << QByteArray::fromRawData(static_cast<char*>(keyValue), keySize); 126 qWarning() << "invalid buffer " << QByteArray::fromRawData(static_cast<char*>(keyValue), keySize);
174 return true; 127 return true;
175 } 128 }
@@ -182,8 +135,9 @@ void DummyResourceFacade::readValue(QSharedPointer<Akonadi2::Storage> storage, c
182 //Not i.e. for tags that are stored as flags in each entity of an imap store. 135 //Not i.e. for tags that are stored as flags in each entity of an imap store.
183 auto adaptor = mFactory->createAdaptor(buffer.entity()); 136 auto adaptor = mFactory->createAdaptor(buffer.entity());
184 //TODO only copy requested properties 137 //TODO only copy requested properties
185 auto memoryAdaptor = QSharedPointer<Akonadi2::Domain::MemoryBufferAdaptor>::create(*adaptor); 138 auto memoryAdaptor = QSharedPointer<Akonadi2::ApplicationDomain::MemoryBufferAdaptor>::create(*adaptor);
186 auto event = QSharedPointer<Akonadi2::Domain::Event>::create("org.kde.dummy", QString::fromUtf8(static_cast<char*>(keyValue), keySize), revision, memoryAdaptor); 139 // here we could copy additional properties that don't have a 1:1 mapping, such as separately stored tags.
140 auto event = QSharedPointer<Akonadi2::ApplicationDomain::Event>::create("org.kde.dummy", QByteArray::fromRawData(static_cast<char*>(keyValue), keySize), revision, memoryAdaptor);
187 resultCallback(event); 141 resultCallback(event);
188 } 142 }
189 return true; 143 return true;
@@ -193,7 +147,7 @@ void DummyResourceFacade::readValue(QSharedPointer<Akonadi2::Storage> storage, c
193 }); 147 });
194} 148}
195 149
196Async::Job<void> DummyResourceFacade::load(const Akonadi2::Query &query, const std::function<void(const Akonadi2::Domain::Event::Ptr &)> &resultCallback) 150Async::Job<void> DummyResourceFacade::load(const Akonadi2::Query &query, const std::function<void(const Akonadi2::ApplicationDomain::Event::Ptr &)> &resultCallback)
197{ 151{
198 return synchronizeResource(query.syncOnDemand, query.processAll).then<void>([=](Async::Future<void> &future) { 152 return synchronizeResource(query.syncOnDemand, query.processAll).then<void>([=](Async::Future<void> &future) {
199 //Now that the sync is complete we can execute the query 153 //Now that the sync is complete we can execute the query
@@ -201,6 +155,9 @@ Async::Job<void> DummyResourceFacade::load(const Akonadi2::Query &query, const s
201 155
202 auto storage = QSharedPointer<Akonadi2::Storage>::create(Akonadi2::Store::storageLocation(), "org.kde.dummy"); 156 auto storage = QSharedPointer<Akonadi2::Storage>::create(Akonadi2::Store::storageLocation(), "org.kde.dummy");
203 157
158 //TODO use transaction over full query and record store revision. We'll need it to update the query.
159
160 //Index lookups
204 QVector<QByteArray> keys; 161 QVector<QByteArray> keys;
205 if (query.propertyFilter.contains("uid")) { 162 if (query.propertyFilter.contains("uid")) {
206 static Index uidIndex(Akonadi2::Store::storageLocation(), "org.kde.dummy.index.uid", Akonadi2::Storage::ReadOnly); 163 static Index uidIndex(Akonadi2::Store::storageLocation(), "org.kde.dummy.index.uid", Akonadi2::Storage::ReadOnly);