summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/entitybuffer.cpp5
-rw-r--r--common/entitybuffer.h1
-rw-r--r--common/metadata.fbs1
-rw-r--r--common/pipeline.cpp44
-rw-r--r--common/pipeline.h37
-rw-r--r--common/resource.cpp5
-rw-r--r--common/resource.h2
-rw-r--r--dummyresource/facade.cpp138
-rw-r--r--dummyresource/facade.h53
-rw-r--r--dummyresource/resourcefactory.cpp56
-rw-r--r--dummyresource/resourcefactory.h1
-rw-r--r--synchronizer/listener.cpp2
12 files changed, 253 insertions, 92 deletions
diff --git a/common/entitybuffer.cpp b/common/entitybuffer.cpp
index b9c9d76..c5d6bce 100644
--- a/common/entitybuffer.cpp
+++ b/common/entitybuffer.cpp
@@ -18,6 +18,11 @@ EntityBuffer::EntityBuffer(void *dataValue, int dataSize)
18 } 18 }
19} 19}
20 20
21const Akonadi2::Entity &EntityBuffer::entity()
22{
23 return *mEntity;
24}
25
21const flatbuffers::Vector<uint8_t>* EntityBuffer::resourceBuffer() 26const flatbuffers::Vector<uint8_t>* EntityBuffer::resourceBuffer()
22{ 27{
23 if (!mEntity) { 28 if (!mEntity) {
diff --git a/common/entitybuffer.h b/common/entitybuffer.h
index c072777..bd9360d 100644
--- a/common/entitybuffer.h
+++ b/common/entitybuffer.h
@@ -12,6 +12,7 @@ public:
12 const flatbuffers::Vector<uint8_t> *resourceBuffer(); 12 const flatbuffers::Vector<uint8_t> *resourceBuffer();
13 const flatbuffers::Vector<uint8_t> *metadataBuffer(); 13 const flatbuffers::Vector<uint8_t> *metadataBuffer();
14 const flatbuffers::Vector<uint8_t> *localBuffer(); 14 const flatbuffers::Vector<uint8_t> *localBuffer();
15 const Entity &entity();
15 16
16 static void extractResourceBuffer(void *dataValue, int dataSize, const std::function<void(const flatbuffers::Vector<uint8_t> *)> &handler); 17 static void extractResourceBuffer(void *dataValue, int dataSize, const std::function<void(const flatbuffers::Vector<uint8_t> *)> &handler);
17 static void assembleEntityBuffer(flatbuffers::FlatBufferBuilder &fbb, void *metadataData, size_t metadataSize, void *resourceData, size_t resourceSize, void *localData, size_t localSize); 18 static void assembleEntityBuffer(flatbuffers::FlatBufferBuilder &fbb, void *metadataData, size_t metadataSize, void *resourceData, size_t resourceSize, void *localData, size_t localSize);
diff --git a/common/metadata.fbs b/common/metadata.fbs
index 71684b6..34a8df2 100644
--- a/common/metadata.fbs
+++ b/common/metadata.fbs
@@ -2,6 +2,7 @@ namespace Akonadi2;
2 2
3table Metadata { 3table Metadata {
4 revision: ulong; 4 revision: ulong;
5 processed: bool = true;
5} 6}
6 7
7root_type Metadata; 8root_type Metadata;
diff --git a/common/pipeline.cpp b/common/pipeline.cpp
index 04954ac..8d00480 100644
--- a/common/pipeline.cpp
+++ b/common/pipeline.cpp
@@ -41,10 +41,10 @@ public:
41 } 41 }
42 42
43 Storage storage; 43 Storage storage;
44 QVector<Preprocessor *> nullPipeline; 44 QHash<QString, QVector<Preprocessor *> > nullPipeline;
45 QVector<Preprocessor *> newPipeline; 45 QHash<QString, QVector<Preprocessor *> > newPipeline;
46 QVector<Preprocessor *> modifiedPipeline; 46 QHash<QString, QVector<Preprocessor *> > modifiedPipeline;
47 QVector<Preprocessor *> deletedPipeline; 47 QHash<QString, QVector<Preprocessor *> > deletedPipeline;
48 QVector<PipelineState> activePipelines; 48 QVector<PipelineState> activePipelines;
49 bool stepScheduled; 49 bool stepScheduled;
50}; 50};
@@ -60,6 +60,23 @@ Pipeline::~Pipeline()
60 delete d; 60 delete d;
61} 61}
62 62
63void Pipeline::setPreprocessors(const QString &entityType, Type pipelineType, const QVector<Preprocessor *> &preprocessors)
64{
65 switch (pipelineType) {
66 case NewPipeline:
67 d->newPipeline[entityType] = preprocessors;
68 break;
69 case ModifiedPipeline:
70 d->modifiedPipeline[entityType] = preprocessors;
71 break;
72 case DeletedPipeline:
73 d->deletedPipeline[entityType] = preprocessors;
74 break;
75 default:
76 break;
77 };
78}
79
63Storage &Pipeline::storage() const 80Storage &Pipeline::storage() const
64{ 81{
65 return d->storage; 82 return d->storage;
@@ -68,12 +85,12 @@ Storage &Pipeline::storage() const
68void Pipeline::null() 85void Pipeline::null()
69{ 86{
70 //TODO: is there really any need for the null pipeline? if so, it should be doing something ;) 87 //TODO: is there really any need for the null pipeline? if so, it should be doing something ;)
71 PipelineState state(this, NullPipeline, QByteArray(), d->nullPipeline); 88 // PipelineState state(this, NullPipeline, QByteArray(), d->nullPipeline);
72 d->activePipelines << state; 89 // d->activePipelines << state;
73 state.step(); 90 // state.step();
74} 91}
75 92
76void Pipeline::newEntity(const QByteArray &key, void *resourceBufferData, size_t size) 93void Pipeline::newEntity(const QString &entityType, const QByteArray &key, void *resourceBufferData, size_t size)
77{ 94{
78 const qint64 newRevision = storage().maxRevision() + 1; 95 const qint64 newRevision = storage().maxRevision() + 1;
79 96
@@ -81,6 +98,7 @@ void Pipeline::newEntity(const QByteArray &key, void *resourceBufferData, size_t
81 flatbuffers::FlatBufferBuilder metadataFbb; 98 flatbuffers::FlatBufferBuilder metadataFbb;
82 auto metadataBuilder = Akonadi2::MetadataBuilder(metadataFbb); 99 auto metadataBuilder = Akonadi2::MetadataBuilder(metadataFbb);
83 metadataBuilder.add_revision(newRevision); 100 metadataBuilder.add_revision(newRevision);
101 metadataBuilder.add_processed(false);
84 auto metadataBuffer = metadataBuilder.Finish(); 102 auto metadataBuffer = metadataBuilder.Finish();
85 Akonadi2::FinishMetadataBuffer(metadataFbb, metadataBuffer); 103 Akonadi2::FinishMetadataBuffer(metadataFbb, metadataBuffer);
86 104
@@ -90,21 +108,21 @@ void Pipeline::newEntity(const QByteArray &key, void *resourceBufferData, size_t
90 storage().write(key.data(), key.size(), fbb.GetBufferPointer(), fbb.GetSize()); 108 storage().write(key.data(), key.size(), fbb.GetBufferPointer(), fbb.GetSize());
91 storage().setMaxRevision(newRevision); 109 storage().setMaxRevision(newRevision);
92 110
93 PipelineState state(this, NewPipeline, key, d->newPipeline); 111 PipelineState state(this, NewPipeline, key, d->newPipeline[entityType]);
94 d->activePipelines << state; 112 d->activePipelines << state;
95 state.step(); 113 state.step();
96} 114}
97 115
98void Pipeline::modifiedEntity(const QByteArray &key, void *data, size_t size) 116void Pipeline::modifiedEntity(const QString &entityType, const QByteArray &key, void *data, size_t size)
99{ 117{
100 PipelineState state(this, ModifiedPipeline, key, d->modifiedPipeline); 118 PipelineState state(this, ModifiedPipeline, key, d->modifiedPipeline[entityType]);
101 d->activePipelines << state; 119 d->activePipelines << state;
102 state.step(); 120 state.step();
103} 121}
104 122
105void Pipeline::deletedEntity(const QByteArray &key) 123void Pipeline::deletedEntity(const QString &entityType, const QByteArray &key)
106{ 124{
107 PipelineState state(this, DeletedPipeline, key, d->deletedPipeline); 125 PipelineState state(this, DeletedPipeline, key, d->deletedPipeline[entityType]);
108 d->activePipelines << state; 126 d->activePipelines << state;
109 state.step(); 127 state.step();
110} 128}
diff --git a/common/pipeline.h b/common/pipeline.h
index 6ef8703..8373899 100644
--- a/common/pipeline.h
+++ b/common/pipeline.h
@@ -27,6 +27,7 @@
27 27
28#include <akonadi2common_export.h> 28#include <akonadi2common_export.h>
29#include <storage.h> 29#include <storage.h>
30#include <clientapi.h> //For domain types
30 31
31namespace Akonadi2 32namespace Akonadi2
32{ 33{
@@ -46,12 +47,34 @@ public:
46 47
47 Storage &storage() const; 48 Storage &storage() const;
48 49
50 // template <typename T>
51 // Storage &storage() const;
52
53 template <typename T>
54 void setPreprocessors(Type type, const QVector<Preprocessor *> &preprocessors)
55 {
56 setPreprocessors(Akonadi2::Domain::getTypeName<T>(), type, preprocessors);
57 }
58
49 void null(); 59 void null();
50 //FIXME We should probably directly provide a DomainTypeAdapter here. The data has already been written and we only need to read it for processing. And we need to read all buffers. 60
51 void newEntity(const QByteArray &key, void *resourceBufferData, size_t size); 61 template <typename T>
52 //TODO Send local buffer data as well? 62 void newEntity(const QByteArray &key, void *resourceBufferData, size_t size)
53 void modifiedEntity(const QByteArray &key, void *data, size_t size); 63 {
54 void deletedEntity(const QByteArray &key); 64 newEntity(Akonadi2::Domain::getTypeName<T>(), key, resourceBufferData, size);
65 }
66
67 template <typename T>
68 void modifiedEntity(const QByteArray &key, void *data, size_t size)
69 {
70 modifiedEntity(Akonadi2::Domain::getTypeName<T>(), key, data, size);
71 }
72
73 template <typename T>
74 void deletedEntity(const QByteArray &key)
75 {
76 deletedEntity(Akonadi2::Domain::getTypeName<T>(), key);
77 }
55 78
56Q_SIGNALS: 79Q_SIGNALS:
57 void revisionUpdated(); 80 void revisionUpdated();
@@ -61,6 +84,10 @@ private Q_SLOTS:
61 void stepPipelines(); 84 void stepPipelines();
62 85
63private: 86private:
87 void setPreprocessors(const QString &entityType, Type pipelineType, const QVector<Preprocessor *> &preprocessors);
88 void newEntity(const QString &entityType, const QByteArray &key, void *resourceBufferData, size_t size);
89 void modifiedEntity(const QString &entityType, const QByteArray &key, void *data, size_t size);
90 void deletedEntity(const QString &entityType, const QByteArray &key);
64 void pipelineStepped(const PipelineState &state); 91 void pipelineStepped(const PipelineState &state);
65 void pipelineCompleted(const PipelineState &state); 92 void pipelineCompleted(const PipelineState &state);
66 void scheduleStep(); 93 void scheduleStep();
diff --git a/common/resource.cpp b/common/resource.cpp
index bba6609..db08c4f 100644
--- a/common/resource.cpp
+++ b/common/resource.cpp
@@ -39,6 +39,11 @@ Resource::~Resource()
39 //delete d; 39 //delete d;
40} 40}
41 41
42void Resource::configurePipeline(Pipeline *pipeline)
43{
44
45}
46
42void Resource::processCommand(int commandId, const QByteArray &data, uint size, Pipeline *pipeline) 47void Resource::processCommand(int commandId, const QByteArray &data, uint size, Pipeline *pipeline)
43{ 48{
44 Q_UNUSED(commandId) 49 Q_UNUSED(commandId)
diff --git a/common/resource.h b/common/resource.h
index fb42c1b..52a28a6 100644
--- a/common/resource.h
+++ b/common/resource.h
@@ -36,6 +36,8 @@ public:
36 virtual void processCommand(int commandId, const QByteArray &data, uint size, Pipeline *pipeline); 36 virtual void processCommand(int commandId, const QByteArray &data, uint size, Pipeline *pipeline);
37 virtual Async::Job<void> synchronizeWithSource(Pipeline *pipeline); 37 virtual Async::Job<void> synchronizeWithSource(Pipeline *pipeline);
38 38
39 virtual void configurePipeline(Pipeline *pipeline);
40
39private: 41private:
40 class Private; 42 class Private;
41 Private * const d; 43 Private * const d;
diff --git a/dummyresource/facade.cpp b/dummyresource/facade.cpp
index d3974e9..c167297 100644
--- a/dummyresource/facade.cpp
+++ b/dummyresource/facade.cpp
@@ -33,44 +33,87 @@
33using namespace DummyCalendar; 33using namespace DummyCalendar;
34using namespace flatbuffers; 34using namespace flatbuffers;
35 35
36/** 36//This will become a generic implementation that simply takes the resource buffer and local buffer pointer
37 * The property mapper holds accessor functions for all properties. 37class DummyEventAdaptor : public Akonadi2::Domain::BufferAdaptor
38 *
39 * It is by default initialized with accessors that access the local-only buffer,
40 * and resource simply have to overwrite those accessors.
41 */
42template<typename BufferType>
43class PropertyMapper
44{ 38{
45public: 39public:
46 void setProperty(const QString &key, const QVariant &value, BufferType *buffer) 40 DummyEventAdaptor()
41 : BufferAdaptor()
47 { 42 {
48 if (mWriteAccessors.contains(key)) { 43
49 auto accessor = mWriteAccessors.value(key); 44 }
50 return accessor(value, buffer); 45
46 void setProperty(const QString &key, const QVariant &value)
47 {
48 if (mResourceMapper->mWriteAccessors.contains(key)) {
49 // mResourceMapper.setProperty(key, value, mResourceBuffer);
50 } else {
51 // mLocalMapper.;
51 } 52 }
52 } 53 }
53 54
54 virtual QVariant getProperty(const QString &key, BufferType const *buffer) const 55 virtual QVariant getProperty(const QString &key) const
55 { 56 {
56 if (mReadAccessors.contains(key)) { 57 if (mResourceBuffer && mResourceMapper->mReadAccessors.contains(key)) {
57 auto accessor = mReadAccessors.value(key); 58 return mResourceMapper->getProperty(key, mResourceBuffer);
58 return accessor(buffer); 59 } else if (mLocalBuffer) {
60 return mLocalMapper->getProperty(key, mLocalBuffer);
59 } 61 }
60 return QVariant(); 62 return QVariant();
61 } 63 }
62 QHash<QString, std::function<QVariant(BufferType const *)> > mReadAccessors; 64
63 QHash<QString, std::function<void(const QVariant &, BufferType*)> > mWriteAccessors; 65 Akonadi2::Domain::Buffer::Event const *mLocalBuffer;
66 DummyEvent const *mResourceBuffer;
67
68 QSharedPointer<PropertyMapper<Akonadi2::Domain::Buffer::Event> > mLocalMapper;
69 QSharedPointer<PropertyMapper<DummyEvent> > mResourceMapper;
64}; 70};
65 71
72template<>
73QSharedPointer<Akonadi2::Domain::BufferAdaptor> DomainTypeAdaptorFactory<typename Akonadi2::Domain::Event, typename Akonadi2::Domain::Buffer::Event, DummyEvent>::createAdaptor(const Akonadi2::Entity &entity)
74{
75 DummyEvent const *resourceBuffer = 0;
76 if (auto resourceData = entity.resource()) {
77 flatbuffers::Verifier verifyer(resourceData->Data(), resourceData->size());
78 if (VerifyDummyEventBuffer(verifyer)) {
79 resourceBuffer = GetDummyEvent(resourceData);
80 }
81 }
82
83 Akonadi2::Metadata const *metadataBuffer = 0;
84 if (auto metadataData = entity.metadata()) {
85 flatbuffers::Verifier verifyer(metadataData->Data(), metadataData->size());
86 if (Akonadi2::VerifyMetadataBuffer(verifyer)) {
87 metadataBuffer = Akonadi2::GetMetadata(metadataData);
88 }
89 }
90
91 Akonadi2::Domain::Buffer::Event const *localBuffer = 0;
92 if (auto localData = entity.local()) {
93 flatbuffers::Verifier verifyer(localData->Data(), localData->size());
94 if (Akonadi2::Domain::Buffer::VerifyEventBuffer(verifyer)) {
95 localBuffer = Akonadi2::Domain::Buffer::GetEvent(localData);
96 }
97 }
98
99 auto adaptor = QSharedPointer<DummyEventAdaptor>::create();
100 adaptor->mLocalBuffer = localBuffer;
101 adaptor->mResourceBuffer = resourceBuffer;
102 adaptor->mResourceMapper = mResourceMapper;
103 adaptor->mLocalMapper = mLocalMapper;
104 return adaptor;
105}
106
66DummyResourceFacade::DummyResourceFacade() 107DummyResourceFacade::DummyResourceFacade()
67 : Akonadi2::StoreFacade<Akonadi2::Domain::Event>(), 108 : Akonadi2::StoreFacade<Akonadi2::Domain::Event>(),
68 mResourceAccess(new Akonadi2::ResourceAccess("org.kde.dummy")) 109 mResourceAccess(new Akonadi2::ResourceAccess("org.kde.dummy")),
110 mFactory(new DomainTypeAdaptorFactory<Akonadi2::Domain::Event, Akonadi2::Domain::Buffer::Event, DummyCalendar::DummyEvent>())
69{ 111{
70 PropertyMapper<DummyEvent> mapper; 112 auto mapper = QSharedPointer<PropertyMapper<DummyEvent> >::create();
71 mapper.mReadAccessors.insert("summary", [](DummyEvent const *buffer) -> QVariant { 113 mapper->mReadAccessors.insert("summary", [](DummyEvent const *buffer) -> QVariant {
72 return QString::fromStdString(buffer->summary()->c_str()); 114 return QString::fromStdString(buffer->summary()->c_str());
73 }); 115 });
116 mFactory->mResourceMapper = mapper;
74} 117}
75 118
76DummyResourceFacade::~DummyResourceFacade() 119DummyResourceFacade::~DummyResourceFacade()
@@ -105,45 +148,6 @@ void DummyResourceFacade::remove(const Akonadi2::Domain::Event &domainObject)
105// 148//
106 149
107 150
108//This will become a generic implementation that simply takes the resource buffer and local buffer pointer
109class DummyEventAdaptor : public Akonadi2::Domain::BufferAdaptor
110{
111public:
112 DummyEventAdaptor()
113 : BufferAdaptor()
114 {
115
116 }
117
118 void setProperty(const QString &key, const QVariant &value)
119 {
120 if (mResourceMapper.mWriteAccessors.contains(key)) {
121 // mResourceMapper.setProperty(key, value, mResourceBuffer);
122 } else {
123 // mLocalMapper.;
124 }
125 }
126
127 virtual QVariant getProperty(const QString &key) const
128 {
129 if (mResourceBuffer && mResourceMapper.mReadAccessors.contains(key)) {
130 return mResourceMapper.getProperty(key, mResourceBuffer);
131 } else if (mLocalBuffer) {
132 return mLocalMapper.getProperty(key, mLocalBuffer);
133 }
134 return QVariant();
135 }
136
137 Akonadi2::Domain::Buffer::Event const *mLocalBuffer;
138 DummyEvent const *mResourceBuffer;
139
140 PropertyMapper<Akonadi2::Domain::Buffer::Event> mLocalMapper;
141 PropertyMapper<DummyEvent> mResourceMapper;
142
143 //Keep query alive so values remain valid
144 QSharedPointer<Akonadi2::Storage> storage;
145};
146
147static std::function<bool(const std::string &key, DummyEvent const *buffer)> prepareQuery(const Akonadi2::Query &query) 151static std::function<bool(const std::string &key, DummyEvent const *buffer)> prepareQuery(const Akonadi2::Query &query)
148{ 152{
149 //Compose some functions to make query matching fast. 153 //Compose some functions to make query matching fast.
@@ -225,26 +229,16 @@ void DummyResourceFacade::load(const Akonadi2::Query &query, const std::function
225 } 229 }
226 } 230 }
227 231
228 Akonadi2::Domain::Buffer::Event const *localBuffer = 0;
229 if (auto localData = buffer.localBuffer()) {
230 flatbuffers::Verifier verifyer(localData->Data(), localData->size());
231 if (Akonadi2::Domain::Buffer::VerifyEventBuffer(verifyer)) {
232 localBuffer = Akonadi2::Domain::Buffer::GetEvent(localData);
233 }
234 }
235
236 if (!resourceBuffer || !metadataBuffer) { 232 if (!resourceBuffer || !metadataBuffer) {
237 qWarning() << "invalid buffer " << QString::fromStdString(std::string(static_cast<char*>(keyValue), keySize)); 233 qWarning() << "invalid buffer " << QString::fromStdString(std::string(static_cast<char*>(keyValue), keySize));
238 return true; 234 return true;
239 } 235 }
240 236
241 //We probably only want to create all buffers after the scan 237 //We probably only want to create all buffers after the scan
238 //TODO use adapter for query and scan?
242 if (preparedQuery && preparedQuery(std::string(static_cast<char*>(keyValue), keySize), resourceBuffer)) { 239 if (preparedQuery && preparedQuery(std::string(static_cast<char*>(keyValue), keySize), resourceBuffer)) {
243 qint64 revision = metadataBuffer ? metadataBuffer->revision() : -1; 240 qint64 revision = metadataBuffer ? metadataBuffer->revision() : -1;
244 auto adaptor = QSharedPointer<DummyEventAdaptor>::create(); 241 auto adaptor = mFactory->createAdaptor(buffer.entity());
245 adaptor->mLocalBuffer = localBuffer;
246 adaptor->mResourceBuffer = resourceBuffer;
247 adaptor->storage = storage;
248 auto event = QSharedPointer<Akonadi2::Domain::Event>::create("org.kde.dummy", QString::fromUtf8(static_cast<char*>(keyValue), keySize), revision, adaptor); 242 auto event = QSharedPointer<Akonadi2::Domain::Event>::create("org.kde.dummy", QString::fromUtf8(static_cast<char*>(keyValue), keySize), revision, adaptor);
249 resultCallback(event); 243 resultCallback(event);
250 } 244 }
diff --git a/dummyresource/facade.h b/dummyresource/facade.h
index c76e62c..46b27ef 100644
--- a/dummyresource/facade.h
+++ b/dummyresource/facade.h
@@ -21,11 +21,63 @@
21 21
22#include "common/clientapi.h" 22#include "common/clientapi.h"
23#include "common/storage.h" 23#include "common/storage.h"
24#include "entity_generated.h"
25#include "event_generated.h"
26#include "dummycalendar_generated.h"
24 27
25namespace Akonadi2 { 28namespace Akonadi2 {
26 class ResourceAccess; 29 class ResourceAccess;
27} 30}
28 31
32/**
33 * The property mapper holds accessor functions for all properties.
34 *
35 * It is by default initialized with accessors that access the local-only buffer,
36 * and resource simply have to overwrite those accessors.
37 */
38template<typename BufferType>
39class PropertyMapper
40{
41public:
42 void setProperty(const QString &key, const QVariant &value, BufferType *buffer)
43 {
44 if (mWriteAccessors.contains(key)) {
45 auto accessor = mWriteAccessors.value(key);
46 return accessor(value, buffer);
47 }
48 }
49
50 virtual QVariant getProperty(const QString &key, BufferType const *buffer) const
51 {
52 if (mReadAccessors.contains(key)) {
53 auto accessor = mReadAccessors.value(key);
54 return accessor(buffer);
55 }
56 return QVariant();
57 }
58 QHash<QString, std::function<QVariant(BufferType const *)> > mReadAccessors;
59 QHash<QString, std::function<void(const QVariant &, BufferType*)> > mWriteAccessors;
60};
61
62//The factory should define how to go from an entitybuffer (local + resource buffer), to a domain type adapter.
63//It defines how values are split accross local and resource buffer.
64//This is required by the facade the read the value, and by the pipeline preprocessors to access the domain values in a generic way.
65template<typename DomainType, typename LocalBuffer, typename ResourceBuffer>
66class DomainTypeAdaptorFactory
67{
68};
69
70template<typename LocalBuffer, typename ResourceBuffer>
71class DomainTypeAdaptorFactory<typename Akonadi2::Domain::Event, LocalBuffer, ResourceBuffer>
72{
73public:
74 QSharedPointer<Akonadi2::Domain::BufferAdaptor> createAdaptor(const Akonadi2::Entity &entity);
75
76// private:
77 QSharedPointer<PropertyMapper<LocalBuffer> > mLocalMapper;
78 QSharedPointer<PropertyMapper<ResourceBuffer> > mResourceMapper;
79};
80
29class DummyResourceFacade : public Akonadi2::StoreFacade<Akonadi2::Domain::Event> 81class DummyResourceFacade : public Akonadi2::StoreFacade<Akonadi2::Domain::Event>
30{ 82{
31public: 83public:
@@ -39,4 +91,5 @@ public:
39private: 91private:
40 void synchronizeResource(const std::function<void()> &continuation); 92 void synchronizeResource(const std::function<void()> &continuation);
41 QSharedPointer<Akonadi2::ResourceAccess> mResourceAccess; 93 QSharedPointer<Akonadi2::ResourceAccess> mResourceAccess;
94 QSharedPointer<DomainTypeAdaptorFactory<Akonadi2::Domain::Event, Akonadi2::Domain::Buffer::Event, DummyCalendar::DummyEvent> > mFactory;
42}; 95};
diff --git a/dummyresource/resourcefactory.cpp b/dummyresource/resourcefactory.cpp
index c9e4d7a..08222c0 100644
--- a/dummyresource/resourcefactory.cpp
+++ b/dummyresource/resourcefactory.cpp
@@ -20,10 +20,48 @@
20#include "resourcefactory.h" 20#include "resourcefactory.h"
21#include "facade.h" 21#include "facade.h"
22#include "entitybuffer.h" 22#include "entitybuffer.h"
23#include "pipeline.h"
23#include "dummycalendar_generated.h" 24#include "dummycalendar_generated.h"
24#include "metadata_generated.h" 25#include "metadata_generated.h"
25#include <QUuid> 26#include <QUuid>
26 27
28/*
29 * Figure out how to implement various classes of processors:
30 * * read-only (index and such) => domain adapter
31 * * filter => provide means to move entity elsewhere, and also reflect change in source (I guess?)
32 * * flag extractors? => like read-only? Or write to local portion of buffer?
33 * ** $ISSPAM should become part of domain object and is written to the local part of the mail.
34 * ** => value could be calculated by the server directly
35 */
36// template <typename DomainType>
37class SimpleProcessor : public Akonadi2::Preprocessor
38{
39public:
40 SimpleProcessor(const std::function<void(const Akonadi2::PipelineState &state)> &f)
41 : Akonadi2::Preprocessor(),
42 mFunction(f)
43 {
44 }
45
46 void process(const Akonadi2::PipelineState &state) {
47 mFunction(state);
48 }
49
50protected:
51 std::function<void(const Akonadi2::PipelineState &state)> mFunction;
52};
53
54// template <typename DomainType>
55// class SimpleReadOnlyProcessor : public SimpleProcessor<DomainType>
56// {
57// public:
58// using SimpleProcessor::SimpleProcessor;
59// void process(Akonadi2::PipelineState state) {
60// mFunction();
61// }
62// };
63
64
27static std::string createEvent() 65static std::string createEvent()
28{ 66{
29 static const size_t attachmentSize = 1024*2; // 2KB 67 static const size_t attachmentSize = 1024*2; // 2KB
@@ -61,6 +99,20 @@ DummyResource::DummyResource()
61{ 99{
62} 100}
63 101
102void DummyResource::configurePipeline(Akonadi2::Pipeline *pipeline)
103{
104 //TODO setup preprocessors for each domain type and pipeline type allowing full customization
105 //Eventually the order should be self configuring, for now it's hardcoded.
106 auto eventIndexer = new SimpleProcessor([](const Akonadi2::PipelineState &state) {
107 //FIXME
108 // auto adaptor = QSharedPointer<DummyEventAdaptor>::create();
109 // adaptor->mLocalBuffer = localBuffer;
110 // adaptor->mResourceBuffer = resourceBuffer;
111 // adaptor->storage = storage;
112 });
113 pipeline->setPreprocessors<Akonadi2::Domain::Event>(Akonadi2::Pipeline::NewPipeline, QVector<Akonadi2::Preprocessor*>() << eventIndexer);
114}
115
64void findByRemoteId(QSharedPointer<Akonadi2::Storage> storage, const QString &rid, std::function<void(void *keyValue, int keySize, void *dataValue, int dataSize)> callback) 116void findByRemoteId(QSharedPointer<Akonadi2::Storage> storage, const QString &rid, std::function<void(void *keyValue, int keySize, void *dataValue, int dataSize)> callback)
65{ 117{
66 //TODO lookup in rid index instead of doing a full scan 118 //TODO lookup in rid index instead of doing a full scan
@@ -119,7 +171,7 @@ Async::Job<void> DummyResource::synchronizeWithSource(Akonadi2::Pipeline *pipeli
119 DummyCalendar::FinishDummyEventBuffer(m_fbb, buffer); 171 DummyCalendar::FinishDummyEventBuffer(m_fbb, buffer);
120 //TODO toRFC4122 would probably be more efficient, but results in non-printable keys. 172 //TODO toRFC4122 would probably be more efficient, but results in non-printable keys.
121 const auto key = QUuid::createUuid().toString().toUtf8(); 173 const auto key = QUuid::createUuid().toString().toUtf8();
122 pipeline->newEntity(key, m_fbb.GetBufferPointer(), m_fbb.GetSize()); 174 pipeline->newEntity<Akonadi2::Domain::Event>(key, m_fbb.GetBufferPointer(), m_fbb.GetSize());
123 } else { //modification 175 } else { //modification
124 //TODO diff and create modification if necessary 176 //TODO diff and create modification if necessary
125 } 177 }
@@ -139,7 +191,7 @@ void DummyResource::processCommand(int commandId, const QByteArray &data, uint s
139 builder .add_summary(m_fbb.CreateString("summary summary!")); 191 builder .add_summary(m_fbb.CreateString("summary summary!"));
140 auto buffer = builder.Finish(); 192 auto buffer = builder.Finish();
141 DummyCalendar::FinishDummyEventBuffer(m_fbb, buffer); 193 DummyCalendar::FinishDummyEventBuffer(m_fbb, buffer);
142 pipeline->newEntity("fakekey", m_fbb.GetBufferPointer(), m_fbb.GetSize()); 194 pipeline->newEntity<Akonadi2::Domain::Event>("fakekey", m_fbb.GetBufferPointer(), m_fbb.GetSize());
143 m_fbb.Clear(); 195 m_fbb.Clear();
144} 196}
145 197
diff --git a/dummyresource/resourcefactory.h b/dummyresource/resourcefactory.h
index dba674f..427fcc6 100644
--- a/dummyresource/resourcefactory.h
+++ b/dummyresource/resourcefactory.h
@@ -33,6 +33,7 @@ public:
33 DummyResource(); 33 DummyResource();
34 Async::Job<void> synchronizeWithSource(Akonadi2::Pipeline *pipeline); 34 Async::Job<void> synchronizeWithSource(Akonadi2::Pipeline *pipeline);
35 void processCommand(int commandId, const QByteArray &data, uint size, Akonadi2::Pipeline *pipeline); 35 void processCommand(int commandId, const QByteArray &data, uint size, Akonadi2::Pipeline *pipeline);
36 void configurePipeline(Akonadi2::Pipeline *pipeline);
36 37
37private: 38private:
38 flatbuffers::FlatBufferBuilder m_fbb; 39 flatbuffers::FlatBufferBuilder m_fbb;
diff --git a/synchronizer/listener.cpp b/synchronizer/listener.cpp
index 51794ed..8b5a19a 100644
--- a/synchronizer/listener.cpp
+++ b/synchronizer/listener.cpp
@@ -37,10 +37,12 @@ Listener::Listener(const QString &resourceName, QObject *parent)
37 m_server(new QLocalServer(this)), 37 m_server(new QLocalServer(this)),
38 m_resourceName(resourceName), 38 m_resourceName(resourceName),
39 m_resource(0), 39 m_resource(0),
40 //TODO move pipeline(s) to resource
40 m_pipeline(new Akonadi2::Pipeline(resourceName, parent)), 41 m_pipeline(new Akonadi2::Pipeline(resourceName, parent)),
41 m_clientBufferProcessesTimer(new QTimer(this)), 42 m_clientBufferProcessesTimer(new QTimer(this)),
42 m_messageId(0) 43 m_messageId(0)
43{ 44{
45 m_resource->configurePipeline(m_pipeline);
44 connect(m_pipeline, &Akonadi2::Pipeline::revisionUpdated, 46 connect(m_pipeline, &Akonadi2::Pipeline::revisionUpdated,
45 this, &Listener::refreshRevision); 47 this, &Listener::refreshRevision);
46 connect(m_server, &QLocalServer::newConnection, 48 connect(m_server, &QLocalServer::newConnection,