summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/clientapi.h26
-rw-r--r--common/pipeline.cpp10
-rw-r--r--common/test/clientapitest.cpp14
-rw-r--r--dummyresource/facade.cpp23
-rw-r--r--dummyresource/facade.h4
-rw-r--r--dummyresource/resourcefactory.cpp4
-rw-r--r--tests/dummyresourcetest.cpp53
7 files changed, 84 insertions, 50 deletions
diff --git a/common/clientapi.h b/common/clientapi.h
index 2f1c127..dd11a0d 100644
--- a/common/clientapi.h
+++ b/common/clientapi.h
@@ -165,7 +165,7 @@ namespace Akonadi2 {
165/** 165/**
166 * Standardized Domain Types 166 * Standardized Domain Types
167 * 167 *
168 * The don't adhere to any standard and can be freely extended 168 * They don't adhere to any standard and can be freely extended
169 * Their sole purpose is providing a standardized interface to access data. 169 * Their sole purpose is providing a standardized interface to access data.
170 * 170 *
171 * This is necessary to decouple resource-backends from application domain containers (otherwise each resource would have to provide a faceade for each application domain container). 171 * This is necessary to decouple resource-backends from application domain containers (otherwise each resource would have to provide a faceade for each application domain container).
@@ -297,6 +297,7 @@ using namespace async;
297class Query 297class Query
298{ 298{
299public: 299public:
300 Query() : syncOnDemand(true) {}
300 //Could also be a propertyFilter 301 //Could also be a propertyFilter
301 QStringList resources; 302 QStringList resources;
302 //Could also be a propertyFilter 303 //Could also be a propertyFilter
@@ -305,6 +306,7 @@ public:
305 QHash<QString, QVariant> propertyFilter; 306 QHash<QString, QVariant> propertyFilter;
306 //Properties to retrieve 307 //Properties to retrieve
307 QSet<QString> requestedProperties; 308 QSet<QString> requestedProperties;
309 bool syncOnDemand;
308}; 310};
309 311
310 312
@@ -324,7 +326,7 @@ public:
324 virtual Async::Job<void> create(const DomainType &domainObject) = 0; 326 virtual Async::Job<void> create(const DomainType &domainObject) = 0;
325 virtual Async::Job<void> modify(const DomainType &domainObject) = 0; 327 virtual Async::Job<void> modify(const DomainType &domainObject) = 0;
326 virtual Async::Job<void> remove(const DomainType &domainObject) = 0; 328 virtual Async::Job<void> remove(const DomainType &domainObject) = 0;
327 virtual void load(const Query &query, const std::function<void(const typename DomainType::Ptr &)> &resultCallback, const std::function<void()> &completeCallback) = 0; 329 virtual Async::Job<void> load(const Query &query, const std::function<void(const typename DomainType::Ptr &)> &resultCallback) = 0;
328}; 330};
329 331
330 332
@@ -418,21 +420,25 @@ public:
418 // query tells us in which resources we're interested 420 // query tells us in which resources we're interested
419 // TODO: queries to individual resources could be parallelized 421 // TODO: queries to individual resources could be parallelized
420 auto eventloop = QSharedPointer<QEventLoop>::create(); 422 auto eventloop = QSharedPointer<QEventLoop>::create();
421 int completeCounter = 0; 423 Async::Job<void> job = Async::null<void>();
422 for(const QString &resource : query.resources) { 424 for(const QString &resource : query.resources) {
423 auto facade = FacadeFactory::instance().getFacade<DomainType>(resource); 425 auto facade = FacadeFactory::instance().getFacade<DomainType>(resource);
424 //We have to bind an instance to the function callback. Since we use a shared pointer this keeps the result provider instance (and thus also the emitter) alive. 426 //We have to bind an instance to the function callback. Since we use a shared pointer this keeps the result provider instance (and thus also the emitter) alive.
425 std::function<void(const typename DomainType::Ptr &)> addCallback = std::bind(&ResultProvider<typename DomainType::Ptr>::add, resultSet, std::placeholders::_1); 427 std::function<void(const typename DomainType::Ptr &)> addCallback = std::bind(&ResultProvider<typename DomainType::Ptr>::add, resultSet, std::placeholders::_1);
426 //We copy the facade pointer to keep it alive 428 //We copy the facade pointer to keep it alive
427 facade->load(query, addCallback, [&completeCounter, &query, resultSet, facade, eventloop]() { 429 job = job.then<void>([facade, query, addCallback](Async::Future<void> &future) {
428 //TODO use jobs instead of this counter 430 Async::Job<void> j = facade->load(query, addCallback);
429 completeCounter++; 431 j.then<void>([&future, facade](Async::Future<void> &f) {
430 if (completeCounter == query.resources.size()) { 432 future.setFinished();
431 resultSet->complete(); 433 f.setFinished();
432 eventloop->quit(); 434 }).exec();
433 }
434 }); 435 });
435 } 436 }
437 job.then<void>([eventloop, resultSet](Async::Future<void> &future) {
438 resultSet->complete();
439 eventloop->quit();
440 future.setFinished();
441 }).exec();
436 //The thread contains no eventloop, so execute one here 442 //The thread contains no eventloop, so execute one here
437 eventloop->exec(QEventLoop::ExcludeUserInputEvents); 443 eventloop->exec(QEventLoop::ExcludeUserInputEvents);
438 }); 444 });
diff --git a/common/pipeline.cpp b/common/pipeline.cpp
index 339a39c..dda7671 100644
--- a/common/pipeline.cpp
+++ b/common/pipeline.cpp
@@ -106,15 +106,21 @@ Async::Job<void> Pipeline::newEntity(void const *command, size_t size)
106 { 106 {
107 flatbuffers::Verifier verifyer(reinterpret_cast<const uint8_t *>(command), size); 107 flatbuffers::Verifier verifyer(reinterpret_cast<const uint8_t *>(command), size);
108 if (!Akonadi2::Commands::VerifyCreateEntityBuffer(verifyer)) { 108 if (!Akonadi2::Commands::VerifyCreateEntityBuffer(verifyer)) {
109 qWarning() << "invalid buffer"; 109 qWarning() << "invalid buffer, not a create entity buffer";
110 return Async::null<void>(); 110 return Async::null<void>();
111 } 111 }
112 } 112 }
113
114 auto createEntity = Akonadi2::Commands::GetCreateEntity(command); 113 auto createEntity = Akonadi2::Commands::GetCreateEntity(command);
115 114
116 //TODO rename createEntitiy->domainType to bufferType 115 //TODO rename createEntitiy->domainType to bufferType
117 const QString entityType = QString::fromUtf8(reinterpret_cast<char const*>(createEntity->domainType()->Data()), createEntity->domainType()->size()); 116 const QString entityType = QString::fromUtf8(reinterpret_cast<char const*>(createEntity->domainType()->Data()), createEntity->domainType()->size());
117 {
118 flatbuffers::Verifier verifyer(reinterpret_cast<const uint8_t *>(createEntity->delta()->Data()), createEntity->delta()->size());
119 if (!Akonadi2::VerifyEntityBuffer(verifyer)) {
120 qWarning() << "invalid buffer, not an entity buffer";
121 return Async::null<void>();
122 }
123 }
118 auto entity = Akonadi2::GetEntity(createEntity->delta()->Data()); 124 auto entity = Akonadi2::GetEntity(createEntity->delta()->Data());
119 125
120 //Add metadata buffer 126 //Add metadata buffer
diff --git a/common/test/clientapitest.cpp b/common/test/clientapitest.cpp
index 16616a3..c9e4d6d 100644
--- a/common/test/clientapitest.cpp
+++ b/common/test/clientapitest.cpp
@@ -11,13 +11,15 @@ public:
11 virtual Async::Job<void> create(const Akonadi2::Domain::Event &domainObject){ return Async::null<void>(); }; 11 virtual Async::Job<void> create(const Akonadi2::Domain::Event &domainObject){ return Async::null<void>(); };
12 virtual Async::Job<void> modify(const Akonadi2::Domain::Event &domainObject){ return Async::null<void>(); }; 12 virtual Async::Job<void> modify(const Akonadi2::Domain::Event &domainObject){ return Async::null<void>(); };
13 virtual Async::Job<void> remove(const Akonadi2::Domain::Event &domainObject){ return Async::null<void>(); }; 13 virtual Async::Job<void> remove(const Akonadi2::Domain::Event &domainObject){ return Async::null<void>(); };
14 virtual void load(const Akonadi2::Query &query, const std::function<void(const Akonadi2::Domain::Event::Ptr &)> &resultCallback, const std::function<void()> &completeCallback) 14 virtual Async::Job<void> load(const Akonadi2::Query &query, const std::function<void(const Akonadi2::Domain::Event::Ptr &)> &resultCallback)
15 { 15 {
16 qDebug() << "load called"; 16 return Async::start<void>([this, resultCallback](Async::Future<void> &future) {
17 for(const auto &result : results) { 17 qDebug() << "load called";
18 resultCallback(result); 18 for(const auto &result : results) {
19 } 19 resultCallback(result);
20 completeCallback(); 20 }
21 future.setFinished();
22 });
21 } 23 }
22 24
23 QList<Akonadi2::Domain::Event::Ptr> results; 25 QList<Akonadi2::Domain::Event::Ptr> results;
diff --git a/dummyresource/facade.cpp b/dummyresource/facade.cpp
index 13c174b..b7ba2c2 100644
--- a/dummyresource/facade.cpp
+++ b/dummyresource/facade.cpp
@@ -118,22 +118,29 @@ static std::function<bool(const std::string &key, DummyEvent const *buffer)> pre
118 return preparedQuery; 118 return preparedQuery;
119} 119}
120 120
121void DummyResourceFacade::synchronizeResource(const std::function<void()> &continuation) 121Async::Job<void> DummyResourceFacade::synchronizeResource(bool sync)
122{ 122{
123 //TODO check if a sync is necessary 123 //TODO check if a sync is necessary
124 //TODO Only sync what was requested 124 //TODO Only sync what was requested
125 //TODO timeout 125 //TODO timeout
126 mResourceAccess->synchronizeResource().then<void>([continuation](Async::Future<void> &f){ 126
127 continuation(); 127 if (sync) {
128 f.setFinished(); 128 return Async::start<void>([=](Async::Future<void> &future) {
129 }).exec(); 129 mResourceAccess->open();
130 mResourceAccess->synchronizeResource().then<void>([&future](Async::Future<void> &f) {
131 future.setFinished();
132 f.setFinished();
133 }).exec();
134 });
135 }
136 return Async::null<void>();
130} 137}
131 138
132void DummyResourceFacade::load(const Akonadi2::Query &query, const std::function<void(const Akonadi2::Domain::Event::Ptr &)> &resultCallback, const std::function<void()> &completeCallback) 139Async::Job<void> DummyResourceFacade::load(const Akonadi2::Query &query, const std::function<void(const Akonadi2::Domain::Event::Ptr &)> &resultCallback)
133{ 140{
134 qDebug() << "load called"; 141 qDebug() << "load called";
135 142
136 synchronizeResource([=]() { 143 return synchronizeResource(query.syncOnDemand).then<void>([=](Async::Future<void> &future) {
137 qDebug() << "sync complete"; 144 qDebug() << "sync complete";
138 //Now that the sync is complete we can execute the query 145 //Now that the sync is complete we can execute the query
139 const auto preparedQuery = prepareQuery(query); 146 const auto preparedQuery = prepareQuery(query);
@@ -188,7 +195,7 @@ void DummyResourceFacade::load(const Akonadi2::Query &query, const std::function
188 } 195 }
189 return true; 196 return true;
190 }); 197 });
191 completeCallback(); 198 future.setFinished();
192 }); 199 });
193} 200}
194 201
diff --git a/dummyresource/facade.h b/dummyresource/facade.h
index 9c8827a..da0b1d6 100644
--- a/dummyresource/facade.h
+++ b/dummyresource/facade.h
@@ -40,10 +40,10 @@ public:
40 virtual Async::Job<void> create(const Akonadi2::Domain::Event &domainObject); 40 virtual Async::Job<void> create(const Akonadi2::Domain::Event &domainObject);
41 virtual Async::Job<void> modify(const Akonadi2::Domain::Event &domainObject); 41 virtual Async::Job<void> modify(const Akonadi2::Domain::Event &domainObject);
42 virtual Async::Job<void> remove(const Akonadi2::Domain::Event &domainObject); 42 virtual Async::Job<void> remove(const Akonadi2::Domain::Event &domainObject);
43 virtual void load(const Akonadi2::Query &query, const std::function<void(const Akonadi2::Domain::Event::Ptr &)> &resultCallback, const std::function<void()> &completeCallback); 43 virtual Async::Job<void> load(const Akonadi2::Query &query, const std::function<void(const Akonadi2::Domain::Event::Ptr &)> &resultCallback);
44 44
45private: 45private:
46 void synchronizeResource(const std::function<void()> &continuation); 46 Async::Job<void> synchronizeResource(bool sync);
47 QSharedPointer<Akonadi2::ResourceAccess> mResourceAccess; 47 QSharedPointer<Akonadi2::ResourceAccess> mResourceAccess;
48 QSharedPointer<DomainTypeAdaptorFactory<Akonadi2::Domain::Event, Akonadi2::Domain::Buffer::Event, DummyCalendar::DummyEvent> > mFactory; 48 QSharedPointer<DomainTypeAdaptorFactory<Akonadi2::Domain::Event, Akonadi2::Domain::Buffer::Event, DummyCalendar::DummyEvent> > mFactory;
49}; 49};
diff --git a/dummyresource/resourcefactory.cpp b/dummyresource/resourcefactory.cpp
index f74eb72..dc716ef 100644
--- a/dummyresource/resourcefactory.cpp
+++ b/dummyresource/resourcefactory.cpp
@@ -317,7 +317,9 @@ Async::Job<void> DummyResource::synchronizeWithSource(Akonadi2::Pipeline *pipeli
317 builder.add_attachment(attachment); 317 builder.add_attachment(attachment);
318 auto buffer = builder.Finish(); 318 auto buffer = builder.Finish();
319 DummyCalendar::FinishDummyEventBuffer(m_fbb, buffer); 319 DummyCalendar::FinishDummyEventBuffer(m_fbb, buffer);
320 enqueueCommand(mSynchronizerQueue, Akonadi2::Commands::CreateEntityCommand, QByteArray::fromRawData(reinterpret_cast<char const *>(m_fbb.GetBufferPointer()), m_fbb.GetSize())); 320 flatbuffers::FlatBufferBuilder entityFbb;
321 Akonadi2::EntityBuffer::assembleEntityBuffer(entityFbb, 0, 0, m_fbb.GetBufferPointer(), m_fbb.GetSize(), 0, 0);
322 enqueueCommand(mSynchronizerQueue, Akonadi2::Commands::CreateEntityCommand, QByteArray::fromRawData(reinterpret_cast<char const *>(entityFbb.GetBufferPointer()), entityFbb.GetSize()));
321 } else { //modification 323 } else { //modification
322 //TODO diff and create modification if necessary 324 //TODO diff and create modification if necessary
323 } 325 }
diff --git a/tests/dummyresourcetest.cpp b/tests/dummyresourcetest.cpp
index c469796..a80d22f 100644
--- a/tests/dummyresourcetest.cpp
+++ b/tests/dummyresourcetest.cpp
@@ -82,27 +82,38 @@ private Q_SLOTS:
82 QCOMPARE(revisionSpy.count(), 2); 82 QCOMPARE(revisionSpy.count(), 2);
83 } 83 }
84 84
85 // void testResourceSync() 85 void testWriteToFacade()
86 // { 86 {
87 // Akonadi2::Pipeline pipeline("org.kde.dummy"); 87 Akonadi2::Query query;
88 // DummyResource resource; 88 Akonadi2::Domain::Event event;
89 // auto job = resource.synchronizeWithSource(&pipeline); 89 event.setProperty("summary", "summaryValue");
90 // auto future = job.exec(); 90 Akonadi2::Store::create<Akonadi2::Domain::Event>(event, "org.kde.dummy");
91 // QTRY_VERIFY(future.isFinished()); 91
92 // } 92 QTest::qWait(1000);
93 93 //TODO wait for success response
94 // void testSyncAndFacade() 94 }
95 // { 95
96 // Akonadi2::Query query; 96 void testResourceSync()
97 // query.resources << "org.kde.dummy"; 97 {
98 98 Akonadi2::Pipeline pipeline("org.kde.dummy");
99 // async::SyncListResult<Akonadi2::Domain::Event::Ptr> result(Akonadi2::Store::load<Akonadi2::Domain::Event>(query)); 99 DummyResource resource;
100 // result.exec(); 100 auto job = resource.synchronizeWithSource(&pipeline);
101 // QVERIFY(!result.isEmpty()); 101 auto future = job.exec();
102 // auto value = result.first(); 102 QTRY_VERIFY(future.isFinished());
103 // QVERIFY(!value->getProperty("summary").toString().isEmpty()); 103 }
104 // qDebug() << value->getProperty("summary").toString(); 104
105 // } 105 void testSyncAndFacade()
106 {
107 Akonadi2::Query query;
108 query.resources << "org.kde.dummy";
109
110 async::SyncListResult<Akonadi2::Domain::Event::Ptr> result(Akonadi2::Store::load<Akonadi2::Domain::Event>(query));
111 result.exec();
112 QVERIFY(!result.isEmpty());
113 auto value = result.first();
114 QVERIFY(!value->getProperty("summary").toString().isEmpty());
115 qDebug() << value->getProperty("summary").toString();
116 }
106 117
107}; 118};
108 119