summaryrefslogtreecommitdiffstats
path: root/dummyresource
diff options
context:
space:
mode:
Diffstat (limited to 'dummyresource')
-rw-r--r--dummyresource/domainadaptor.cpp135
-rw-r--r--dummyresource/domainadaptor.h6
-rw-r--r--dummyresource/facade.cpp89
-rw-r--r--dummyresource/facade.h23
-rw-r--r--dummyresource/resourcefactory.cpp48
5 files changed, 78 insertions, 223 deletions
diff --git a/dummyresource/domainadaptor.cpp b/dummyresource/domainadaptor.cpp
index 2182f9a..fa00bbc 100644
--- a/dummyresource/domainadaptor.cpp
+++ b/dummyresource/domainadaptor.cpp
@@ -9,142 +9,55 @@
9#include "entity_generated.h" 9#include "entity_generated.h"
10#include "metadata_generated.h" 10#include "metadata_generated.h"
11#include "domainadaptor.h" 11#include "domainadaptor.h"
12#include "log.h"
12#include <common/entitybuffer.h> 13#include <common/entitybuffer.h>
13 14
14using namespace DummyCalendar; 15using namespace DummyCalendar;
15using namespace flatbuffers; 16using namespace flatbuffers;
16 17
17using namespace DummyCalendar;
18using namespace flatbuffers;
19
20//This will become a generic implementation that simply takes the resource buffer and local buffer pointer
21class DummyEventAdaptor : public Akonadi2::Domain::BufferAdaptor
22{
23public:
24 DummyEventAdaptor()
25 : BufferAdaptor()
26 {
27
28 }
29
30 void setProperty(const QString &key, const QVariant &value)
31 {
32 if (mResourceMapper && mResourceMapper->mWriteAccessors.contains(key)) {
33 // mResourceMapper->setProperty(key, value, mResourceBuffer);
34 } else {
35 // mLocalMapper.;
36 }
37 }
38 18
39 virtual QVariant getProperty(const QString &key) const
40 {
41 if (mResourceBuffer && mResourceMapper->mReadAccessors.contains(key)) {
42 return mResourceMapper->getProperty(key, mResourceBuffer);
43 } else if (mLocalBuffer && mLocalMapper->mReadAccessors.contains(key)) {
44 return mLocalMapper->getProperty(key, mLocalBuffer);
45 }
46 qWarning() << "no mapping available for key " << key;
47 return QVariant();
48 }
49
50 virtual QStringList availableProperties() const
51 {
52 QStringList props;
53 props << mResourceMapper->mReadAccessors.keys();
54 props << mLocalMapper->mReadAccessors.keys();
55 return props;
56 }
57
58 Akonadi2::Domain::Buffer::Event const *mLocalBuffer;
59 DummyEvent const *mResourceBuffer;
60
61 QSharedPointer<PropertyMapper<Akonadi2::Domain::Buffer::Event> > mLocalMapper;
62 QSharedPointer<PropertyMapper<DummyEvent> > mResourceMapper;
63};
64 19
65 20
66DummyEventAdaptorFactory::DummyEventAdaptorFactory() 21DummyEventAdaptorFactory::DummyEventAdaptorFactory()
67 : DomainTypeAdaptorFactory() 22 : DomainTypeAdaptorFactory()
68{ 23{
69 mResourceMapper = QSharedPointer<PropertyMapper<DummyEvent> >::create(); 24 //TODO turn this into initializeReadPropertyMapper as well?
70 mResourceMapper->mReadAccessors.insert("summary", [](DummyEvent const *buffer) -> QVariant { 25 mResourceMapper->addMapping("summary", [](DummyEvent const *buffer) -> QVariant {
71 if (buffer->summary()) {
72 return QString::fromStdString(buffer->summary()->c_str());
73 }
74 return QVariant();
75 });
76 mLocalMapper = QSharedPointer<PropertyMapper<Akonadi2::Domain::Buffer::Event> >::create();
77 mLocalMapper->mReadAccessors.insert("summary", [](Akonadi2::Domain::Buffer::Event const *buffer) -> QVariant {
78 if (buffer->summary()) { 26 if (buffer->summary()) {
79 return QString::fromStdString(buffer->summary()->c_str()); 27 return QString::fromStdString(buffer->summary()->c_str());
80 } 28 }
81 return QVariant(); 29 return QVariant();
82 }); 30 });
83 mLocalMapper->mReadAccessors.insert("uid", [](Akonadi2::Domain::Buffer::Event const *buffer) -> QVariant {
84 if (buffer->uid()) {
85 return QString::fromStdString(buffer->uid()->c_str());
86 }
87 return QVariant();
88 });
89 31
32 mResourceWriteMapper->addMapping("summary", [](const QVariant &value, flatbuffers::FlatBufferBuilder &fbb) -> std::function<void(DummyEventBuilder &)> {
33 auto offset = extractProperty<QString>(value, fbb);
34 return [offset](DummyEventBuilder &builder) { builder.add_summary(offset); };
35 });
90} 36}
91 37
92//TODO pass EntityBuffer instead? 38
93QSharedPointer<Akonadi2::Domain::BufferAdaptor> DummyEventAdaptorFactory::createAdaptor(const Akonadi2::Entity &entity) 39void DummyEventAdaptorFactory::createBuffer(const Akonadi2::ApplicationDomain::Event &event, flatbuffers::FlatBufferBuilder &fbb)
94{ 40{
95 DummyEvent const *resourceBuffer = 0; 41 flatbuffers::FlatBufferBuilder localFbb;
96 if (auto resourceData = entity.resource()) { 42 if (mLocalWriteMapper) {
97 flatbuffers::Verifier verifyer(resourceData->Data(), resourceData->size()); 43 auto pos = createBufferPart<Akonadi2::ApplicationDomain::Buffer::EventBuilder, Akonadi2::ApplicationDomain::Buffer::Event>(event, localFbb, *mLocalWriteMapper);
98 if (VerifyDummyEventBuffer(verifyer)) { 44 Akonadi2::ApplicationDomain::Buffer::FinishEventBuffer(localFbb, pos);
99 resourceBuffer = GetDummyEvent(resourceData->Data()); 45 flatbuffers::Verifier verifier(localFbb.GetBufferPointer(), localFbb.GetSize());
46 if (!verifier.VerifyBuffer<Akonadi2::ApplicationDomain::Buffer::Event>()) {
47 Warning() << "Created invalid local buffer";
100 } 48 }
101 } 49 }
102 50
103 // Akonadi2::Metadata const *metadataBuffer = 0; 51 flatbuffers::FlatBufferBuilder resFbb;
104 // if (auto metadataData = entity.metadata()) { 52 if (mResourceWriteMapper) {
105 // flatbuffers::Verifier verifyer(metadataData->Data(), metadataData->size()); 53 auto pos = createBufferPart<DummyEventBuilder, DummyEvent>(event, resFbb, *mResourceWriteMapper);
106 // if (Akonadi2::VerifyMetadataBuffer(verifyer)) { 54 DummyCalendar::FinishDummyEventBuffer(resFbb, pos);
107 // metadataBuffer = Akonadi2::GetMetadata(metadataData->Data()); 55 flatbuffers::Verifier verifier(resFbb.GetBufferPointer(), resFbb.GetSize());
108 // } 56 if (!verifier.VerifyBuffer<DummyEvent>()) {
109 // } 57 Warning() << "Created invalid resource buffer";
110
111 Akonadi2::Domain::Buffer::Event const *localBuffer = 0;
112 if (auto localData = entity.local()) {
113 flatbuffers::Verifier verifyer(localData->Data(), localData->size());
114 if (Akonadi2::Domain::Buffer::VerifyEventBuffer(verifyer)) {
115 localBuffer = Akonadi2::Domain::Buffer::GetEvent(localData->Data());
116 } 58 }
117 } 59 }
118 60
119 auto adaptor = QSharedPointer<DummyEventAdaptor>::create(); 61 Akonadi2::EntityBuffer::assembleEntityBuffer(fbb, 0, 0, resFbb.GetBufferPointer(), resFbb.GetSize(), localFbb.GetBufferPointer(), localFbb.GetSize());
120 adaptor->mLocalBuffer = localBuffer;
121 adaptor->mLocalMapper = mLocalMapper;
122 adaptor->mResourceBuffer = resourceBuffer;
123 adaptor->mResourceMapper = mResourceMapper;
124 return adaptor;
125}
126
127void DummyEventAdaptorFactory::createBuffer(const Akonadi2::Domain::Event &event, flatbuffers::FlatBufferBuilder &fbb)
128{
129 flatbuffers::FlatBufferBuilder eventFbb;
130 eventFbb.Clear();
131 {
132 auto summary = eventFbb.CreateString(event.getProperty("summary").toString().toStdString());
133 DummyCalendar::DummyEventBuilder eventBuilder(eventFbb);
134 eventBuilder.add_summary(summary);
135 auto eventLocation = eventBuilder.Finish();
136 DummyCalendar::FinishDummyEventBuffer(eventFbb, eventLocation);
137 }
138
139 flatbuffers::FlatBufferBuilder localFbb;
140 {
141 auto uid = localFbb.CreateString(event.getProperty("uid").toString().toStdString());
142 auto localBuilder = Akonadi2::Domain::Buffer::EventBuilder(localFbb);
143 localBuilder.add_uid(uid);
144 auto location = localBuilder.Finish();
145 Akonadi2::Domain::Buffer::FinishEventBuffer(localFbb, location);
146 }
147
148 Akonadi2::EntityBuffer::assembleEntityBuffer(fbb, 0, 0, eventFbb.GetBufferPointer(), eventFbb.GetSize(), localFbb.GetBufferPointer(), localFbb.GetSize());
149} 62}
150 63
diff --git a/dummyresource/domainadaptor.h b/dummyresource/domainadaptor.h
index 9474176..9d351e7 100644
--- a/dummyresource/domainadaptor.h
+++ b/dummyresource/domainadaptor.h
@@ -1,4 +1,3 @@
1
2#pragma once 1#pragma once
3 2
4#include "common/domainadaptor.h" 3#include "common/domainadaptor.h"
@@ -6,11 +5,10 @@
6#include "dummycalendar_generated.h" 5#include "dummycalendar_generated.h"
7#include "entity_generated.h" 6#include "entity_generated.h"
8 7
9class DummyEventAdaptorFactory : public DomainTypeAdaptorFactory<Akonadi2::Domain::Event, Akonadi2::Domain::Buffer::Event, DummyCalendar::DummyEvent> 8class DummyEventAdaptorFactory : public DomainTypeAdaptorFactory<Akonadi2::ApplicationDomain::Event, Akonadi2::ApplicationDomain::Buffer::Event, DummyCalendar::DummyEvent, Akonadi2::ApplicationDomain::Buffer::EventBuilder, DummyCalendar::DummyEventBuilder>
10{ 9{
11public: 10public:
12 DummyEventAdaptorFactory(); 11 DummyEventAdaptorFactory();
13 virtual ~DummyEventAdaptorFactory() {}; 12 virtual ~DummyEventAdaptorFactory() {};
14 virtual QSharedPointer<Akonadi2::Domain::BufferAdaptor> createAdaptor(const Akonadi2::Entity &entity); 13 virtual void createBuffer(const Akonadi2::ApplicationDomain::Event &event, flatbuffers::FlatBufferBuilder &fbb);
15 virtual void createBuffer(const Akonadi2::Domain::Event &event, flatbuffers::FlatBufferBuilder &fbb);
16}; 14};
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);
diff --git a/dummyresource/facade.h b/dummyresource/facade.h
index 1f69161..37ed81d 100644
--- a/dummyresource/facade.h
+++ b/dummyresource/facade.h
@@ -19,6 +19,8 @@
19 19
20#pragma once 20#pragma once
21 21
22#include "common/facade.h"
23
22#include "common/clientapi.h" 24#include "common/clientapi.h"
23#include "common/storage.h" 25#include "common/storage.h"
24#include "resourcefactory.h" 26#include "resourcefactory.h"
@@ -27,24 +29,17 @@
27#include "dummycalendar_generated.h" 29#include "dummycalendar_generated.h"
28#include "common/domainadaptor.h" 30#include "common/domainadaptor.h"
29 31
30namespace Akonadi2 { 32class DummyResourceFacade : public Akonadi2::GenericFacade<Akonadi2::ApplicationDomain::Event>
31 class ResourceAccess;
32}
33
34
35class DummyResourceFacade : public Akonadi2::StoreFacade<Akonadi2::Domain::Event>
36{ 33{
37public: 34public:
38 DummyResourceFacade(); 35 DummyResourceFacade();
39 virtual ~DummyResourceFacade(); 36 virtual ~DummyResourceFacade();
40 virtual Async::Job<void> create(const Akonadi2::Domain::Event &domainObject); 37 virtual Async::Job<void> create(const Akonadi2::ApplicationDomain::Event &domainObject);
41 virtual Async::Job<void> modify(const Akonadi2::Domain::Event &domainObject); 38 virtual Async::Job<void> modify(const Akonadi2::ApplicationDomain::Event &domainObject);
42 virtual Async::Job<void> remove(const Akonadi2::Domain::Event &domainObject); 39 virtual Async::Job<void> remove(const Akonadi2::ApplicationDomain::Event &domainObject);
43 virtual Async::Job<void> load(const Akonadi2::Query &query, const std::function<void(const Akonadi2::Domain::Event::Ptr &)> &resultCallback); 40 virtual Async::Job<void> load(const Akonadi2::Query &query, const std::function<void(const Akonadi2::ApplicationDomain::Event::Ptr &)> &resultCallback);
44 41
45private: 42private:
46 void 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, DummyCalendar::DummyEvent const *buffer, Akonadi2::Domain::Buffer::Event const *local)>); 43 void 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, DummyCalendar::DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local)>);
47 Async::Job<void> synchronizeResource(bool sync, bool processAll); 44 QSharedPointer<DomainTypeAdaptorFactory<Akonadi2::ApplicationDomain::Event, Akonadi2::ApplicationDomain::Buffer::Event, DummyCalendar::DummyEvent, Akonadi2::ApplicationDomain::Buffer::EventBuilder, DummyCalendar::DummyEventBuilder> > mFactory;
48 QSharedPointer<Akonadi2::ResourceAccess> mResourceAccess;
49 QSharedPointer<DomainTypeAdaptorFactory<Akonadi2::Domain::Event, Akonadi2::Domain::Buffer::Event, DummyCalendar::DummyEvent> > mFactory;
50}; 45};
diff --git a/dummyresource/resourcefactory.cpp b/dummyresource/resourcefactory.cpp
index dda34ef..8f0a2bd 100644
--- a/dummyresource/resourcefactory.cpp
+++ b/dummyresource/resourcefactory.cpp
@@ -191,7 +191,7 @@ private slots:
191 return; 191 return;
192 } 192 }
193 auto queuedCommand = Akonadi2::GetQueuedCommand(ptr); 193 auto queuedCommand = Akonadi2::GetQueuedCommand(ptr);
194 qDebug() << "Dequeued: " << queuedCommand->commandId(); 194 Trace() << "Dequeued: " << queuedCommand->commandId();
195 //TODO JOBAPI: job lifetime management 195 //TODO JOBAPI: job lifetime management
196 //Right now we're just leaking jobs. In this case we'd like jobs that are heap allocated and delete 196 //Right now we're just leaking jobs. In this case we'd like jobs that are heap allocated and delete
197 //themselves once done. In other cases we'd like jobs that only live as long as their handle though. 197 //themselves once done. In other cases we'd like jobs that only live as long as their handle though.
@@ -256,29 +256,18 @@ void DummyResource::configurePipeline(Akonadi2::Pipeline *pipeline)
256 //Eventually the order should be self configuring, for now it's hardcoded. 256 //Eventually the order should be self configuring, for now it's hardcoded.
257 auto eventIndexer = new SimpleProcessor("summaryprocessor", [eventFactory](const Akonadi2::PipelineState &state, const Akonadi2::Entity &entity) { 257 auto eventIndexer = new SimpleProcessor("summaryprocessor", [eventFactory](const Akonadi2::PipelineState &state, const Akonadi2::Entity &entity) {
258 auto adaptor = eventFactory->createAdaptor(entity); 258 auto adaptor = eventFactory->createAdaptor(entity);
259 // qDebug() << "Summary preprocessor: " << adaptor->getProperty("summary").toString(); 259 // Log() << "Summary preprocessor: " << adaptor->getProperty("summary").toString();
260 }); 260 });
261 261
262 auto uidIndexer = new SimpleProcessor("uidIndexer", [eventFactory](const Akonadi2::PipelineState &state, const Akonadi2::Entity &entity) { 262 auto uidIndexer = new SimpleProcessor("uidIndexer", [eventFactory](const Akonadi2::PipelineState &state, const Akonadi2::Entity &entity) {
263 static Index uidIndex(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/akonadi2/storage", "org.kde.dummy.index.uid", Akonadi2::Storage::ReadWrite); 263 static Index uidIndex(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/akonadi2/storage", "org.kde.dummy.index.uid", Akonadi2::Storage::ReadWrite);
264 264
265 //TODO: Benchmark if this is performance wise acceptable, or if we have to access the buffer directly
265 auto adaptor = eventFactory->createAdaptor(entity); 266 auto adaptor = eventFactory->createAdaptor(entity);
266 const auto uid = adaptor->getProperty("uid"); 267 const auto uid = adaptor->getProperty("uid");
267 if (uid.isValid()) { 268 if (uid.isValid()) {
268 uidIndex.add(uid.toByteArray(), state.key()); 269 uidIndex.add(uid.toByteArray(), state.key());
269 } 270 }
270
271 //TODO would this be worthwhile for performance reasons?
272 // flatbuffers::Verifier verifyer(entity.local()->Data(), entity.local()->size());
273 // if (!Akonadi2::Domain::Buffer::VerifyEventBuffer(verifyer)) {
274 // qWarning() << "invalid local buffer";
275 // return;
276 // }
277 // auto localEvent = Akonadi2::Domain::Buffer::GetEvent(entity.local()->Data());
278 // if (localEvent && localEvent->uid()) {
279 // qDebug() << "got uid: " << QByteArray::fromRawData(reinterpret_cast<const char *>(localEvent->uid()->Data()), localEvent->uid()->size());
280 // uidIndex.add(QByteArray::fromRawData(reinterpret_cast<const char *>(localEvent->uid()->Data()), localEvent->uid()->size()), state.key());
281 // }
282 }); 271 });
283 272
284 //event is the entitytype and not the domain type 273 //event is the entitytype and not the domain type
@@ -289,7 +278,7 @@ void DummyResource::configurePipeline(Akonadi2::Pipeline *pipeline)
289 278
290void DummyResource::onProcessorError(int errorCode, const QString &errorMessage) 279void DummyResource::onProcessorError(int errorCode, const QString &errorMessage)
291{ 280{
292 qWarning() << "Received error from Processor: " << errorCode << errorMessage; 281 Warning() << "Received error from Processor: " << errorCode << errorMessage;
293 mError = errorCode; 282 mError = errorCode;
294} 283}
295 284
@@ -325,11 +314,8 @@ void findByRemoteId(QSharedPointer<Akonadi2::Storage> storage, const QString &ri
325void DummyResource::enqueueCommand(MessageQueue &mq, int commandId, const QByteArray &data) 314void DummyResource::enqueueCommand(MessageQueue &mq, int commandId, const QByteArray &data)
326{ 315{
327 m_fbb.Clear(); 316 m_fbb.Clear();
328 auto commandData = m_fbb.CreateVector(reinterpret_cast<uint8_t const *>(data.data()), data.size()); 317 auto commandData = Akonadi2::EntityBuffer::appendAsVector(m_fbb, data.constData(), data.size());
329 auto builder = Akonadi2::QueuedCommandBuilder(m_fbb); 318 auto buffer = Akonadi2::CreateQueuedCommand(m_fbb, commandId, commandData);
330 builder.add_commandId(commandId);
331 builder.add_command(commandData);
332 auto buffer = builder.Finish();
333 Akonadi2::FinishQueuedCommandBuffer(m_fbb, buffer); 319 Akonadi2::FinishQueuedCommandBuffer(m_fbb, buffer);
334 mq.enqueue(m_fbb.GetBufferPointer(), m_fbb.GetSize()); 320 mq.enqueue(m_fbb.GetBufferPointer(), m_fbb.GetSize());
335} 321}
@@ -357,7 +343,7 @@ Async::Job<void> DummyResource::synchronizeWithSource(Akonadi2::Pipeline *pipeli
357 auto rid = m_fbb.CreateString(it.key().toStdString().c_str()); 343 auto rid = m_fbb.CreateString(it.key().toStdString().c_str());
358 auto description = m_fbb.CreateString(it.key().toStdString().c_str()); 344 auto description = m_fbb.CreateString(it.key().toStdString().c_str());
359 static uint8_t rawData[100]; 345 static uint8_t rawData[100];
360 auto attachment = m_fbb.CreateVector(rawData, 100); 346 auto attachment = Akonadi2::EntityBuffer::appendAsVector(m_fbb, rawData, 100);
361 347
362 auto builder = DummyCalendar::DummyEventBuilder(m_fbb); 348 auto builder = DummyCalendar::DummyEventBuilder(m_fbb);
363 builder.add_summary(summary); 349 builder.add_summary(summary);
@@ -372,7 +358,7 @@ Async::Job<void> DummyResource::synchronizeWithSource(Akonadi2::Pipeline *pipeli
372 flatbuffers::FlatBufferBuilder fbb; 358 flatbuffers::FlatBufferBuilder fbb;
373 //This is the resource type and not the domain type 359 //This is the resource type and not the domain type
374 auto type = fbb.CreateString("event"); 360 auto type = fbb.CreateString("event");
375 auto delta = fbb.CreateVector<uint8_t>(entityFbb.GetBufferPointer(), entityFbb.GetSize()); 361 auto delta = Akonadi2::EntityBuffer::appendAsVector(fbb, entityFbb.GetBufferPointer(), entityFbb.GetSize());
376 auto location = Akonadi2::Commands::CreateCreateEntity(fbb, type, delta); 362 auto location = Akonadi2::Commands::CreateCreateEntity(fbb, type, delta);
377 Akonadi2::Commands::FinishCreateEntityBuffer(fbb, location); 363 Akonadi2::Commands::FinishCreateEntityBuffer(fbb, location);
378 364
@@ -388,16 +374,22 @@ Async::Job<void> DummyResource::synchronizeWithSource(Akonadi2::Pipeline *pipeli
388 374
389Async::Job<void> DummyResource::processAllMessages() 375Async::Job<void> DummyResource::processAllMessages()
390{ 376{
377 //We have to wait for all items to be processed to ensure the synced items are available when a query gets executed.
378 //TODO: report errors while processing sync?
379 //TODO JOBAPI: A helper that waits for n events and then continues?
391 return Async::start<void>([this](Async::Future<void> &f) { 380 return Async::start<void>([this](Async::Future<void> &f) {
392 //We have to wait for all items to be processed to ensure the synced items are available when a query gets executed.
393 //TODO: report errors while processing sync?
394 //TODO: also check user-queue?
395 if (mSynchronizerQueue.isEmpty()) { 381 if (mSynchronizerQueue.isEmpty()) {
396 qDebug() << "synchronizer queue is empty";
397 f.setFinished(); 382 f.setFinished();
398 } else { 383 } else {
399 QObject::connect(&mSynchronizerQueue, &MessageQueue::drained, [&f]() { 384 QObject::connect(&mSynchronizerQueue, &MessageQueue::drained, [&f]() {
400 qDebug() << "synchronizer queue drained"; 385 f.setFinished();
386 });
387 }
388 }).then<void>([this](Async::Future<void> &f) {
389 if (mUserQueue.isEmpty()) {
390 f.setFinished();
391 } else {
392 QObject::connect(&mUserQueue, &MessageQueue::drained, [&f]() {
401 f.setFinished(); 393 f.setFinished();
402 }); 394 });
403 } 395 }
@@ -425,7 +417,7 @@ Akonadi2::Resource *DummyResourceFactory::createResource()
425 417
426void DummyResourceFactory::registerFacades(Akonadi2::FacadeFactory &factory) 418void DummyResourceFactory::registerFacades(Akonadi2::FacadeFactory &factory)
427{ 419{
428 factory.registerFacade<Akonadi2::Domain::Event, DummyResourceFacade>(PLUGIN_NAME); 420 factory.registerFacade<Akonadi2::ApplicationDomain::Event, DummyResourceFacade>(PLUGIN_NAME);
429} 421}
430 422
431#include "resourcefactory.moc" 423#include "resourcefactory.moc"