diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/CMakeLists.txt | 1 | ||||
-rw-r--r-- | common/clientapi.cpp | 8 | ||||
-rw-r--r-- | common/clientapi.h | 97 | ||||
-rw-r--r-- | common/domain/event.fbs | 2 | ||||
-rw-r--r-- | common/domainadaptor.cpp | 63 | ||||
-rw-r--r-- | common/domainadaptor.h | 187 | ||||
-rw-r--r-- | common/entitybuffer.cpp | 27 | ||||
-rw-r--r-- | common/entitybuffer.h | 26 | ||||
-rw-r--r-- | common/facade.h | 88 | ||||
-rw-r--r-- | common/resource.h | 7 | ||||
-rw-r--r-- | common/resourceaccess.cpp | 10 | ||||
-rw-r--r-- | common/resourceaccess.h | 4 | ||||
-rw-r--r-- | common/storage.h | 2 | ||||
-rw-r--r-- | common/storage_common.cpp | 2 | ||||
-rw-r--r-- | common/storage_lmdb.cpp | 4 | ||||
-rw-r--r-- | common/test/clientapitest.cpp | 18 |
16 files changed, 438 insertions, 108 deletions
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 650691c..b06718f 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt | |||
@@ -30,6 +30,7 @@ set(command_SRCS | |||
30 | commands.cpp | 30 | commands.cpp |
31 | console.cpp | 31 | console.cpp |
32 | pipeline.cpp | 32 | pipeline.cpp |
33 | domainadaptor.cpp | ||
33 | resource.cpp | 34 | resource.cpp |
34 | resourceaccess.cpp | 35 | resourceaccess.cpp |
35 | storage_common.cpp | 36 | storage_common.cpp |
diff --git a/common/clientapi.cpp b/common/clientapi.cpp index 6f0b421..48de1b0 100644 --- a/common/clientapi.cpp +++ b/common/clientapi.cpp | |||
@@ -14,24 +14,24 @@ namespace async | |||
14 | namespace Akonadi2 | 14 | namespace Akonadi2 |
15 | { | 15 | { |
16 | 16 | ||
17 | namespace Domain | 17 | namespace ApplicationDomain |
18 | { | 18 | { |
19 | 19 | ||
20 | template<> | 20 | template<> |
21 | QString getTypeName<Event>() | 21 | QByteArray getTypeName<Event>() |
22 | { | 22 | { |
23 | return "event"; | 23 | return "event"; |
24 | } | 24 | } |
25 | 25 | ||
26 | template<> | 26 | template<> |
27 | QString getTypeName<Todo>() | 27 | QByteArray getTypeName<Todo>() |
28 | { | 28 | { |
29 | return "todo"; | 29 | return "todo"; |
30 | } | 30 | } |
31 | 31 | ||
32 | } // namespace Domain | 32 | } // namespace Domain |
33 | 33 | ||
34 | void Store::shutdown(const QString &identifier) | 34 | void Store::shutdown(const QByteArray &identifier) |
35 | { | 35 | { |
36 | Akonadi2::ResourceAccess resourceAccess(identifier); | 36 | Akonadi2::ResourceAccess resourceAccess(identifier); |
37 | //FIXME this starts the resource, just to shut it down again if it's not running in the first place. | 37 | //FIXME this starts the resource, just to shut it down again if it's not running in the first place. |
diff --git a/common/clientapi.h b/common/clientapi.h index 63305ab..22448b3 100644 --- a/common/clientapi.h +++ b/common/clientapi.h | |||
@@ -163,7 +163,7 @@ namespace async { | |||
163 | namespace Akonadi2 { | 163 | namespace Akonadi2 { |
164 | 164 | ||
165 | /** | 165 | /** |
166 | * Standardized Domain Types | 166 | * Standardized Application Domain Types |
167 | * | 167 | * |
168 | * They 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. |
@@ -172,7 +172,7 @@ namespace Akonadi2 { | |||
172 | * | 172 | * |
173 | * These types will be frequently modified (for every new feature that should be exposed to the any client) | 173 | * These types will be frequently modified (for every new feature that should be exposed to the any client) |
174 | */ | 174 | */ |
175 | namespace Domain { | 175 | namespace ApplicationDomain { |
176 | 176 | ||
177 | /** | 177 | /** |
178 | * This class has to be implemented by resources and can be used as generic interface to access the buffer properties | 178 | * This class has to be implemented by resources and can be used as generic interface to access the buffer properties |
@@ -180,9 +180,9 @@ namespace Domain { | |||
180 | class BufferAdaptor { | 180 | class BufferAdaptor { |
181 | public: | 181 | public: |
182 | virtual ~BufferAdaptor() {} | 182 | virtual ~BufferAdaptor() {} |
183 | virtual QVariant getProperty(const QString &key) const { return QVariant(); } | 183 | virtual QVariant getProperty(const QByteArray &key) const { return QVariant(); } |
184 | virtual void setProperty(const QString &key, const QVariant &value) {} | 184 | virtual void setProperty(const QByteArray &key, const QVariant &value) {} |
185 | virtual QStringList availableProperties() const { return QStringList(); } | 185 | virtual QList<QByteArray> availableProperties() const { return QList<QByteArray>(); } |
186 | }; | 186 | }; |
187 | 187 | ||
188 | class MemoryBufferAdaptor : public BufferAdaptor { | 188 | class MemoryBufferAdaptor : public BufferAdaptor { |
@@ -202,12 +202,12 @@ public: | |||
202 | 202 | ||
203 | virtual ~MemoryBufferAdaptor() {} | 203 | virtual ~MemoryBufferAdaptor() {} |
204 | 204 | ||
205 | virtual QVariant getProperty(const QString &key) const { return mValues.value(key); } | 205 | virtual QVariant getProperty(const QByteArray &key) const { return mValues.value(key); } |
206 | virtual void setProperty(const QString &key, const QVariant &value) { mValues.insert(key, value); } | 206 | virtual void setProperty(const QByteArray &key, const QVariant &value) { mValues.insert(key, value); } |
207 | virtual QStringList availableProperties() const { return mValues.keys(); } | 207 | virtual QByteArrayList availableProperties() const { return mValues.keys(); } |
208 | 208 | ||
209 | private: | 209 | private: |
210 | QHash<QString, QVariant> mValues; | 210 | QHash<QByteArray, QVariant> mValues; |
211 | }; | 211 | }; |
212 | 212 | ||
213 | /** | 213 | /** |
@@ -215,14 +215,14 @@ private: | |||
215 | * * provide a unified interface to read buffers (for zero-copy reading) | 215 | * * provide a unified interface to read buffers (for zero-copy reading) |
216 | * * record changes to generate changesets for modifications | 216 | * * record changes to generate changesets for modifications |
217 | */ | 217 | */ |
218 | class AkonadiDomainType { | 218 | class ApplicationDomainType { |
219 | public: | 219 | public: |
220 | AkonadiDomainType() | 220 | ApplicationDomainType() |
221 | :mAdaptor(new MemoryBufferAdaptor()) | 221 | :mAdaptor(new MemoryBufferAdaptor()) |
222 | { | 222 | { |
223 | 223 | ||
224 | } | 224 | } |
225 | AkonadiDomainType(const QString &resourceName, const QString &identifier, qint64 revision, const QSharedPointer<BufferAdaptor> &adaptor) | 225 | ApplicationDomainType(const QByteArray &resourceName, const QByteArray &identifier, qint64 revision, const QSharedPointer<BufferAdaptor> &adaptor) |
226 | : mAdaptor(adaptor), | 226 | : mAdaptor(adaptor), |
227 | mResourceName(resourceName), | 227 | mResourceName(resourceName), |
228 | mIdentifier(identifier), | 228 | mIdentifier(identifier), |
@@ -230,41 +230,43 @@ public: | |||
230 | { | 230 | { |
231 | } | 231 | } |
232 | 232 | ||
233 | virtual ~AkonadiDomainType() {} | 233 | virtual ~ApplicationDomainType() {} |
234 | 234 | ||
235 | virtual QVariant getProperty(const QString &key) const { return mAdaptor->getProperty(key); } | 235 | virtual QVariant getProperty(const QByteArray &key) const { return mAdaptor->getProperty(key); } |
236 | virtual void setProperty(const QString &key, const QVariant &value){ mChangeSet.insert(key, value); mAdaptor->setProperty(key, value); } | 236 | virtual void setProperty(const QByteArray &key, const QVariant &value){ mChangeSet.insert(key, value); mAdaptor->setProperty(key, value); } |
237 | virtual QByteArrayList changedProperties() const { return mChangeSet.keys(); } | ||
238 | qint64 revision() const { return mRevision; } | ||
237 | 239 | ||
238 | private: | 240 | private: |
239 | QSharedPointer<BufferAdaptor> mAdaptor; | 241 | QSharedPointer<BufferAdaptor> mAdaptor; |
240 | QHash<QString, QVariant> mChangeSet; | 242 | QHash<QByteArray, QVariant> mChangeSet; |
241 | /* | 243 | /* |
242 | * Each domain object needs to store the resource, identifier, revision triple so we can link back to the storage location. | 244 | * Each domain object needs to store the resource, identifier, revision triple so we can link back to the storage location. |
243 | */ | 245 | */ |
244 | QString mResourceName; | 246 | QString mResourceName; |
245 | QString mIdentifier; | 247 | QByteArray mIdentifier; |
246 | qint64 mRevision; | 248 | qint64 mRevision; |
247 | }; | 249 | }; |
248 | 250 | ||
249 | struct Event : public AkonadiDomainType { | 251 | struct Event : public ApplicationDomainType { |
250 | typedef QSharedPointer<Event> Ptr; | 252 | typedef QSharedPointer<Event> Ptr; |
251 | using AkonadiDomainType::AkonadiDomainType; | 253 | using ApplicationDomainType::ApplicationDomainType; |
252 | }; | 254 | }; |
253 | 255 | ||
254 | struct Todo : public AkonadiDomainType { | 256 | struct Todo : public ApplicationDomainType { |
255 | typedef QSharedPointer<Todo> Ptr; | 257 | typedef QSharedPointer<Todo> Ptr; |
256 | using AkonadiDomainType::AkonadiDomainType; | 258 | using ApplicationDomainType::ApplicationDomainType; |
257 | }; | 259 | }; |
258 | 260 | ||
259 | struct Calendar : public AkonadiDomainType { | 261 | struct Calendar : public ApplicationDomainType { |
260 | typedef QSharedPointer<Calendar> Ptr; | 262 | typedef QSharedPointer<Calendar> Ptr; |
261 | using AkonadiDomainType::AkonadiDomainType; | 263 | using ApplicationDomainType::ApplicationDomainType; |
262 | }; | 264 | }; |
263 | 265 | ||
264 | class Mail : public AkonadiDomainType { | 266 | class Mail : public ApplicationDomainType { |
265 | }; | 267 | }; |
266 | 268 | ||
267 | class Folder : public AkonadiDomainType { | 269 | class Folder : public ApplicationDomainType { |
268 | }; | 270 | }; |
269 | 271 | ||
270 | /** | 272 | /** |
@@ -274,13 +276,13 @@ class Folder : public AkonadiDomainType { | |||
274 | */ | 276 | */ |
275 | 277 | ||
276 | template<class DomainType> | 278 | template<class DomainType> |
277 | QString getTypeName(); | 279 | QByteArray getTypeName(); |
278 | 280 | ||
279 | template<> | 281 | template<> |
280 | QString getTypeName<Event>(); | 282 | QByteArray getTypeName<Event>(); |
281 | 283 | ||
282 | template<> | 284 | template<> |
283 | QString getTypeName<Todo>(); | 285 | QByteArray getTypeName<Todo>(); |
284 | 286 | ||
285 | } | 287 | } |
286 | 288 | ||
@@ -298,19 +300,22 @@ using namespace async; | |||
298 | * * what resources to search | 300 | * * what resources to search |
299 | * * filters on various properties (parent collection, startDate range, ....) | 301 | * * filters on various properties (parent collection, startDate range, ....) |
300 | * * properties we need (for on-demand querying) | 302 | * * properties we need (for on-demand querying) |
303 | * | ||
304 | * syncOnDemand: Execute a source sync before executing the query | ||
305 | * processAll: Ensure all local messages are processed before querying to guarantee an up-to date dataset. | ||
301 | */ | 306 | */ |
302 | class Query | 307 | class Query |
303 | { | 308 | { |
304 | public: | 309 | public: |
305 | Query() : syncOnDemand(true), processAll(false) {} | 310 | Query() : syncOnDemand(true), processAll(false) {} |
306 | //Could also be a propertyFilter | 311 | //Could also be a propertyFilter |
307 | QStringList resources; | 312 | QByteArrayList resources; |
308 | //Could also be a propertyFilter | 313 | //Could also be a propertyFilter |
309 | QStringList ids; | 314 | QByteArrayList ids; |
310 | //Filters to apply | 315 | //Filters to apply |
311 | QHash<QString, QVariant> propertyFilter; | 316 | QHash<QByteArray, QVariant> propertyFilter; |
312 | //Properties to retrieve | 317 | //Properties to retrieve |
313 | QSet<QString> requestedProperties; | 318 | QSet<QByteArray> requestedProperties; |
314 | bool syncOnDemand; | 319 | bool syncOnDemand; |
315 | bool processAll; | 320 | bool processAll; |
316 | }; | 321 | }; |
@@ -328,7 +333,7 @@ template<class DomainType> | |||
328 | class StoreFacade { | 333 | class StoreFacade { |
329 | public: | 334 | public: |
330 | virtual ~StoreFacade(){}; | 335 | virtual ~StoreFacade(){}; |
331 | QString type() const { return Domain::getTypeName<DomainType>(); } | 336 | QByteArray type() const { return ApplicationDomain::getTypeName<DomainType>(); } |
332 | virtual Async::Job<void> create(const DomainType &domainObject) = 0; | 337 | virtual Async::Job<void> create(const DomainType &domainObject) = 0; |
333 | virtual Async::Job<void> modify(const DomainType &domainObject) = 0; | 338 | virtual Async::Job<void> modify(const DomainType &domainObject) = 0; |
334 | virtual Async::Job<void> remove(const DomainType &domainObject) = 0; | 339 | virtual Async::Job<void> remove(const DomainType &domainObject) = 0; |
@@ -351,15 +356,15 @@ public: | |||
351 | return factory; | 356 | return factory; |
352 | } | 357 | } |
353 | 358 | ||
354 | static QString key(const QString &resource, const QString &type) | 359 | static QByteArray key(const QByteArray &resource, const QByteArray &type) |
355 | { | 360 | { |
356 | return resource + type; | 361 | return resource + type; |
357 | } | 362 | } |
358 | 363 | ||
359 | template<class DomainType, class Facade> | 364 | template<class DomainType, class Facade> |
360 | void registerFacade(const QString &resource) | 365 | void registerFacade(const QByteArray &resource) |
361 | { | 366 | { |
362 | const QString typeName = Domain::getTypeName<DomainType>(); | 367 | const QByteArray typeName = ApplicationDomain::getTypeName<DomainType>(); |
363 | mFacadeRegistry.insert(key(resource, typeName), [](){ return new Facade; }); | 368 | mFacadeRegistry.insert(key(resource, typeName), [](){ return new Facade; }); |
364 | } | 369 | } |
365 | 370 | ||
@@ -373,16 +378,16 @@ public: | |||
373 | * FIXME the factory function should really be returning QSharedPointer<void>, which doesn't work (std::shared_pointer<void> would though). That way i.e. a test could keep the object alive until it's done. | 378 | * FIXME the factory function should really be returning QSharedPointer<void>, which doesn't work (std::shared_pointer<void> would though). That way i.e. a test could keep the object alive until it's done. |
374 | */ | 379 | */ |
375 | template<class DomainType, class Facade> | 380 | template<class DomainType, class Facade> |
376 | void registerFacade(const QString &resource, const std::function<void*(void)> &customFactoryFunction) | 381 | void registerFacade(const QByteArray &resource, const std::function<void*(void)> &customFactoryFunction) |
377 | { | 382 | { |
378 | const QString typeName = Domain::getTypeName<DomainType>(); | 383 | const QByteArray typeName = ApplicationDomain::getTypeName<DomainType>(); |
379 | mFacadeRegistry.insert(key(resource, typeName), customFactoryFunction); | 384 | mFacadeRegistry.insert(key(resource, typeName), customFactoryFunction); |
380 | } | 385 | } |
381 | 386 | ||
382 | template<class DomainType> | 387 | template<class DomainType> |
383 | QSharedPointer<StoreFacade<DomainType> > getFacade(const QString &resource) | 388 | QSharedPointer<StoreFacade<DomainType> > getFacade(const QByteArray &resource) |
384 | { | 389 | { |
385 | const QString typeName = Domain::getTypeName<DomainType>(); | 390 | const QByteArray typeName = ApplicationDomain::getTypeName<DomainType>(); |
386 | auto factoryFunction = mFacadeRegistry.value(key(resource, typeName)); | 391 | auto factoryFunction = mFacadeRegistry.value(key(resource, typeName)); |
387 | if (factoryFunction) { | 392 | if (factoryFunction) { |
388 | return QSharedPointer<StoreFacade<DomainType> >(static_cast<StoreFacade<DomainType>* >(factoryFunction())); | 393 | return QSharedPointer<StoreFacade<DomainType> >(static_cast<StoreFacade<DomainType>* >(factoryFunction())); |
@@ -392,7 +397,7 @@ public: | |||
392 | } | 397 | } |
393 | 398 | ||
394 | private: | 399 | private: |
395 | QHash<QString, std::function<void*(void)> > mFacadeRegistry; | 400 | QHash<QByteArray, std::function<void*(void)> > mFacadeRegistry; |
396 | }; | 401 | }; |
397 | 402 | ||
398 | /** | 403 | /** |
@@ -421,7 +426,7 @@ public: | |||
421 | // query tells us in which resources we're interested | 426 | // query tells us in which resources we're interested |
422 | // TODO: queries to individual resources could be parallelized | 427 | // TODO: queries to individual resources could be parallelized |
423 | Async::Job<void> job = Async::null<void>(); | 428 | Async::Job<void> job = Async::null<void>(); |
424 | for(const QString &resource : query.resources) { | 429 | for(const QByteArray &resource : query.resources) { |
425 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resource); | 430 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resource); |
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. | 431 | //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. |
427 | std::function<void(const typename DomainType::Ptr &)> addCallback = std::bind(&ResultProvider<typename DomainType::Ptr>::add, resultSet, std::placeholders::_1); | 432 | std::function<void(const typename DomainType::Ptr &)> addCallback = std::bind(&ResultProvider<typename DomainType::Ptr>::add, resultSet, std::placeholders::_1); |
@@ -460,7 +465,7 @@ public: | |||
460 | */ | 465 | */ |
461 | //TODO return job that tracks progress until resource has stored the message in it's queue? | 466 | //TODO return job that tracks progress until resource has stored the message in it's queue? |
462 | template <class DomainType> | 467 | template <class DomainType> |
463 | static void create(const DomainType &domainObject, const QString &resourceIdentifier) { | 468 | static void create(const DomainType &domainObject, const QByteArray &resourceIdentifier) { |
464 | //Potentially move to separate thread as well | 469 | //Potentially move to separate thread as well |
465 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceIdentifier); | 470 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceIdentifier); |
466 | auto job = facade->create(domainObject); | 471 | auto job = facade->create(domainObject); |
@@ -475,7 +480,7 @@ public: | |||
475 | * This includes moving etc. since these are also simple settings on a property. | 480 | * This includes moving etc. since these are also simple settings on a property. |
476 | */ | 481 | */ |
477 | template <class DomainType> | 482 | template <class DomainType> |
478 | static void modify(const DomainType &domainObject, const QString &resourceIdentifier) { | 483 | static void modify(const DomainType &domainObject, const QByteArray &resourceIdentifier) { |
479 | //Potentially move to separate thread as well | 484 | //Potentially move to separate thread as well |
480 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceIdentifier); | 485 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceIdentifier); |
481 | facade.modify(domainObject); | 486 | facade.modify(domainObject); |
@@ -485,13 +490,13 @@ public: | |||
485 | * Remove an entity. | 490 | * Remove an entity. |
486 | */ | 491 | */ |
487 | template <class DomainType> | 492 | template <class DomainType> |
488 | static void remove(const DomainType &domainObject, const QString &resourceIdentifier) { | 493 | static void remove(const DomainType &domainObject, const QByteArray &resourceIdentifier) { |
489 | //Potentially move to separate thread as well | 494 | //Potentially move to separate thread as well |
490 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceIdentifier); | 495 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceIdentifier); |
491 | facade.remove(domainObject); | 496 | facade.remove(domainObject); |
492 | } | 497 | } |
493 | 498 | ||
494 | static void shutdown(const QString &resourceIdentifier); | 499 | static void shutdown(const QByteArray &resourceIdentifier); |
495 | }; | 500 | }; |
496 | 501 | ||
497 | } | 502 | } |
diff --git a/common/domain/event.fbs b/common/domain/event.fbs index 49ff270..0c6628b 100644 --- a/common/domain/event.fbs +++ b/common/domain/event.fbs | |||
@@ -1,4 +1,4 @@ | |||
1 | namespace Akonadi2.Domain.Buffer; | 1 | namespace Akonadi2.ApplicationDomain.Buffer; |
2 | 2 | ||
3 | table Event { | 3 | table Event { |
4 | uid:string; | 4 | uid:string; |
diff --git a/common/domainadaptor.cpp b/common/domainadaptor.cpp new file mode 100644 index 0000000..aa8c3d9 --- /dev/null +++ b/common/domainadaptor.cpp | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 Christian Mollekopf <chrigi_1@fastmail.fm> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the | ||
16 | * Free Software Foundation, Inc., | ||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | */ | ||
19 | |||
20 | #include "domainadaptor.h" | ||
21 | |||
22 | template <> | ||
23 | flatbuffers::uoffset_t extractProperty<QString>(const QVariant &property, flatbuffers::FlatBufferBuilder &fbb) | ||
24 | { | ||
25 | if (property.isValid()) { | ||
26 | return fbb.CreateString(property.toString().toStdString()).o; | ||
27 | } | ||
28 | return 0; | ||
29 | } | ||
30 | |||
31 | template <> | ||
32 | QSharedPointer<ReadPropertyMapper<Akonadi2::ApplicationDomain::Buffer::Event> > initializeReadPropertyMapper<Akonadi2::ApplicationDomain::Buffer::Event>() | ||
33 | { | ||
34 | auto propertyMapper = QSharedPointer<ReadPropertyMapper<Akonadi2::ApplicationDomain::Buffer::Event> >::create(); | ||
35 | propertyMapper->addMapping("summary", [](Akonadi2::ApplicationDomain::Buffer::Event const *buffer) -> QVariant { | ||
36 | if (buffer->summary()) { | ||
37 | return QString::fromStdString(buffer->summary()->c_str()); | ||
38 | } | ||
39 | return QVariant(); | ||
40 | }); | ||
41 | propertyMapper->addMapping("uid", [](Akonadi2::ApplicationDomain::Buffer::Event const *buffer) -> QVariant { | ||
42 | if (buffer->uid()) { | ||
43 | return QString::fromStdString(buffer->uid()->c_str()); | ||
44 | } | ||
45 | return QVariant(); | ||
46 | }); | ||
47 | return propertyMapper; | ||
48 | } | ||
49 | |||
50 | template <> | ||
51 | QSharedPointer<WritePropertyMapper<Akonadi2::ApplicationDomain::Buffer::EventBuilder> > initializeWritePropertyMapper<Akonadi2::ApplicationDomain::Buffer::EventBuilder>() | ||
52 | { | ||
53 | auto propertyMapper = QSharedPointer<WritePropertyMapper<Akonadi2::ApplicationDomain::Buffer::EventBuilder> >::create(); | ||
54 | propertyMapper->addMapping("summary", [](const QVariant &value, flatbuffers::FlatBufferBuilder &fbb) -> std::function<void(Akonadi2::ApplicationDomain::Buffer::EventBuilder &)> { | ||
55 | auto offset = extractProperty<QString>(value, fbb); | ||
56 | return [offset](Akonadi2::ApplicationDomain::Buffer::EventBuilder &builder) { builder.add_summary(offset); }; | ||
57 | }); | ||
58 | propertyMapper->addMapping("uid", [](const QVariant &value, flatbuffers::FlatBufferBuilder &fbb) -> std::function<void(Akonadi2::ApplicationDomain::Buffer::EventBuilder &)> { | ||
59 | auto offset = extractProperty<QString>(value, fbb); | ||
60 | return [offset](Akonadi2::ApplicationDomain::Buffer::EventBuilder &builder) { builder.add_uid(offset); }; | ||
61 | }); | ||
62 | return propertyMapper; | ||
63 | } | ||
diff --git a/common/domainadaptor.h b/common/domainadaptor.h index e46e893..e356692 100644 --- a/common/domainadaptor.h +++ b/common/domainadaptor.h | |||
@@ -21,59 +21,194 @@ | |||
21 | 21 | ||
22 | #include "entity_generated.h" | 22 | #include "entity_generated.h" |
23 | #include <QVariant> | 23 | #include <QVariant> |
24 | #include <QString> | 24 | #include <QByteArray> |
25 | #include <functional> | 25 | #include <functional> |
26 | #include "clientapi.h" //for domain parts | 26 | #include "clientapi.h" //for domain parts |
27 | 27 | ||
28 | #include "event_generated.h" | ||
29 | #include "entity_generated.h" | ||
30 | #include "metadata_generated.h" | ||
31 | #include "entitybuffer.h" | ||
32 | |||
28 | /** | 33 | /** |
29 | * The property mapper holds accessor functions for all properties. | 34 | * The property mapper is a non-typesafe virtual dispatch. |
30 | * | 35 | * |
31 | * It is by default initialized with accessors that access the local-only buffer, | 36 | * Instead of using an interface and requring each implementation to override |
32 | * and resource simply have to overwrite those accessors. | 37 | * a virtual method per property, the property mapper can be filled with accessors |
38 | * that extract the properties from resource types. | ||
33 | */ | 39 | */ |
34 | template<typename BufferType> | 40 | template<typename BufferType> |
35 | class PropertyMapper | 41 | class ReadPropertyMapper |
42 | { | ||
43 | public: | ||
44 | virtual QVariant getProperty(const QByteArray &key, BufferType const *buffer) const | ||
45 | { | ||
46 | if (mReadAccessors.contains(key)) { | ||
47 | auto accessor = mReadAccessors.value(key); | ||
48 | return accessor(buffer); | ||
49 | } | ||
50 | return QVariant(); | ||
51 | } | ||
52 | bool hasMapping(const QByteArray &key) const { return mReadAccessors.contains(key); } | ||
53 | QList<QByteArray> availableProperties() const { return mReadAccessors.keys(); } | ||
54 | void addMapping(const QByteArray &property, const std::function<QVariant(BufferType const *)> &mapping) { | ||
55 | mReadAccessors.insert(property, mapping); | ||
56 | } | ||
57 | private: | ||
58 | QHash<QByteArray, std::function<QVariant(BufferType const *)> > mReadAccessors; | ||
59 | }; | ||
60 | |||
61 | template<typename BufferBuilder> | ||
62 | class WritePropertyMapper | ||
36 | { | 63 | { |
37 | public: | 64 | public: |
38 | void setProperty(const QString &key, const QVariant &value, BufferType *buffer) | 65 | virtual void setProperty(const QByteArray &key, const QVariant &value, QList<std::function<void(BufferBuilder &)> > &builderCalls, flatbuffers::FlatBufferBuilder &fbb) const |
39 | { | 66 | { |
40 | if (mWriteAccessors.contains(key)) { | 67 | if (mWriteAccessors.contains(key)) { |
41 | auto accessor = mWriteAccessors.value(key); | 68 | auto accessor = mWriteAccessors.value(key); |
42 | return accessor(value, buffer); | 69 | builderCalls << accessor(value, fbb); |
43 | } | 70 | } |
44 | } | 71 | } |
72 | bool hasMapping(const QByteArray &key) const { return mWriteAccessors.contains(key); } | ||
73 | void addMapping(const QByteArray &property, const std::function<std::function<void(BufferBuilder &)>(const QVariant &, flatbuffers::FlatBufferBuilder &)> &mapping) { | ||
74 | mWriteAccessors.insert(property, mapping); | ||
75 | } | ||
76 | private: | ||
77 | QHash<QByteArray, std::function<std::function<void(BufferBuilder &)>(const QVariant &, flatbuffers::FlatBufferBuilder &)> > mWriteAccessors; | ||
78 | }; | ||
79 | |||
80 | /** | ||
81 | * Defines how to convert qt primitives to flatbuffer ones | ||
82 | * TODO: rename to createProperty or so? | ||
83 | */ | ||
84 | template <class T> | ||
85 | flatbuffers::uoffset_t extractProperty(const QVariant &, flatbuffers::FlatBufferBuilder &fbb); | ||
86 | |||
87 | /** | ||
88 | * Create a buffer from a domain object using the provided mappings | ||
89 | */ | ||
90 | template <class Builder, class Buffer> | ||
91 | flatbuffers::Offset<Buffer> createBufferPart(const Akonadi2::ApplicationDomain::ApplicationDomainType &domainObject, flatbuffers::FlatBufferBuilder &fbb, const WritePropertyMapper<Builder> &mapper) | ||
92 | { | ||
93 | //First create a primitives such as strings using the mappings | ||
94 | QList<std::function<void(Builder &)> > propertiesToAddToResource; | ||
95 | for (const auto &property : domainObject.changedProperties()) { | ||
96 | qWarning() << "copying property " << property; | ||
97 | const auto value = domainObject.getProperty(property); | ||
98 | if (mapper.hasMapping(property)) { | ||
99 | mapper.setProperty(property, domainObject.getProperty(property), propertiesToAddToResource, fbb); | ||
100 | } else { | ||
101 | qWarning() << "no mapping for property available " << property; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | //Then create all porperties using the above generated builderCalls | ||
106 | Builder builder(fbb); | ||
107 | for (auto propertyBuilder : propertiesToAddToResource) { | ||
108 | propertyBuilder(builder); | ||
109 | } | ||
110 | return builder.Finish(); | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * A generic adaptor implementation that uses a property mapper to read/write values. | ||
115 | * | ||
116 | * TODO: this is the read-only part. Create a write only equivalent | ||
117 | */ | ||
118 | template <class LocalBuffer, class ResourceBuffer> | ||
119 | class GenericBufferAdaptor : public Akonadi2::ApplicationDomain::BufferAdaptor | ||
120 | { | ||
121 | public: | ||
122 | GenericBufferAdaptor() | ||
123 | : BufferAdaptor() | ||
124 | { | ||
125 | |||
126 | } | ||
45 | 127 | ||
46 | virtual QVariant getProperty(const QString &key, BufferType const *buffer) const | 128 | //TODO remove |
129 | void setProperty(const QByteArray &key, const QVariant &value) | ||
47 | { | 130 | { |
48 | if (mReadAccessors.contains(key)) { | 131 | } |
49 | auto accessor = mReadAccessors.value(key); | 132 | |
50 | return accessor(buffer); | 133 | virtual QVariant getProperty(const QByteArray &key) const |
134 | { | ||
135 | if (mResourceBuffer && mResourceMapper->hasMapping(key)) { | ||
136 | return mResourceMapper->getProperty(key, mResourceBuffer); | ||
137 | } else if (mLocalBuffer && mLocalMapper->hasMapping(key)) { | ||
138 | return mLocalMapper->getProperty(key, mLocalBuffer); | ||
51 | } | 139 | } |
140 | qWarning() << "no mapping available for key " << key; | ||
52 | return QVariant(); | 141 | return QVariant(); |
53 | } | 142 | } |
54 | QHash<QString, std::function<QVariant(BufferType const *)> > mReadAccessors; | 143 | |
55 | QHash<QString, std::function<void(const QVariant &, BufferType*)> > mWriteAccessors; | 144 | virtual QList<QByteArray> availableProperties() const |
145 | { | ||
146 | QList<QByteArray> props; | ||
147 | props << mResourceMapper->availableProperties(); | ||
148 | props << mLocalMapper->availableProperties(); | ||
149 | return props; | ||
150 | } | ||
151 | |||
152 | LocalBuffer const *mLocalBuffer; | ||
153 | ResourceBuffer const *mResourceBuffer; | ||
154 | QSharedPointer<ReadPropertyMapper<LocalBuffer> > mLocalMapper; | ||
155 | QSharedPointer<ReadPropertyMapper<ResourceBuffer> > mResourceMapper; | ||
56 | }; | 156 | }; |
57 | 157 | ||
58 | //The factory should define how to go from an entitybuffer (local + resource buffer), to a domain type adapter. | 158 | /** |
59 | //It defines how values are split accross local and resource buffer. | 159 | * Initializes the local property mapper. |
60 | //This is required by the facade the read the value, and by the pipeline preprocessors to access the domain values in a generic way. | 160 | * |
61 | // template<typename DomainType, typename LocalBuffer, typename ResourceBuffer> | 161 | * Provide an implementation for each application domain type. |
62 | // class DomainTypeAdaptorFactory | 162 | */ |
63 | // { | 163 | template <class T> |
64 | // }; | 164 | QSharedPointer<ReadPropertyMapper<T> > initializeReadPropertyMapper(); |
165 | |||
166 | template <class T> | ||
167 | QSharedPointer<WritePropertyMapper<T> > initializeWritePropertyMapper(); | ||
65 | 168 | ||
66 | template<typename DomainType, typename LocalBuffer, typename ResourceBuffer> | 169 | /** |
67 | class DomainTypeAdaptorFactory/* <typename DomainType, LocalBuffer, ResourceBuffer> */ | 170 | * The factory should define how to go from an entitybuffer (local + resource buffer), to a domain type adapter. |
171 | * It defines how values are split accross local and resource buffer. | ||
172 | * This is required by the facade the read the value, and by the pipeline preprocessors to access the domain values in a generic way. | ||
173 | */ | ||
174 | template<typename DomainType, typename LocalBuffer, typename ResourceBuffer, typename LocalBuilder, typename ResourceBuilder> | ||
175 | class DomainTypeAdaptorFactory | ||
68 | { | 176 | { |
69 | public: | 177 | public: |
178 | DomainTypeAdaptorFactory() : | ||
179 | mLocalMapper(initializeReadPropertyMapper<LocalBuffer>()), | ||
180 | mResourceMapper(QSharedPointer<ReadPropertyMapper<ResourceBuffer> >::create()), | ||
181 | mLocalWriteMapper(initializeWritePropertyMapper<LocalBuilder>()), | ||
182 | mResourceWriteMapper(QSharedPointer<WritePropertyMapper<ResourceBuilder> >::create()) | ||
183 | {}; | ||
70 | virtual ~DomainTypeAdaptorFactory() {}; | 184 | virtual ~DomainTypeAdaptorFactory() {}; |
71 | virtual QSharedPointer<Akonadi2::Domain::BufferAdaptor> createAdaptor(const Akonadi2::Entity &entity) = 0; | 185 | |
72 | virtual void createBuffer(const Akonadi2::Domain::Event &event, flatbuffers::FlatBufferBuilder &fbb) {}; | 186 | /** |
187 | * Creates an adaptor for the given domain and resource types. | ||
188 | * | ||
189 | * This returns by default a GenericBufferAdaptor initialized with the corresponding property mappers. | ||
190 | */ | ||
191 | virtual QSharedPointer<Akonadi2::ApplicationDomain::BufferAdaptor> createAdaptor(const Akonadi2::Entity &entity) | ||
192 | { | ||
193 | const auto resourceBuffer = Akonadi2::EntityBuffer::readBuffer<ResourceBuffer>(entity.resource()); | ||
194 | const auto localBuffer = Akonadi2::EntityBuffer::readBuffer<LocalBuffer>(entity.local()); | ||
195 | // const auto metadataBuffer = Akonadi2::EntityBuffer::readBuffer<Akonadi2::Metadata>(entity.metadata()); | ||
196 | |||
197 | auto adaptor = QSharedPointer<GenericBufferAdaptor<LocalBuffer, ResourceBuffer> >::create(); | ||
198 | adaptor->mLocalBuffer = localBuffer; | ||
199 | adaptor->mLocalMapper = mLocalMapper; | ||
200 | adaptor->mResourceBuffer = resourceBuffer; | ||
201 | adaptor->mResourceMapper = mResourceMapper; | ||
202 | return adaptor; | ||
203 | } | ||
204 | |||
205 | virtual void createBuffer(const Akonadi2::ApplicationDomain::Event &event, flatbuffers::FlatBufferBuilder &fbb) {}; | ||
73 | 206 | ||
74 | protected: | 207 | protected: |
75 | QSharedPointer<PropertyMapper<LocalBuffer> > mLocalMapper; | 208 | QSharedPointer<ReadPropertyMapper<LocalBuffer> > mLocalMapper; |
76 | QSharedPointer<PropertyMapper<ResourceBuffer> > mResourceMapper; | 209 | QSharedPointer<ReadPropertyMapper<ResourceBuffer> > mResourceMapper; |
210 | QSharedPointer<WritePropertyMapper<LocalBuilder> > mLocalWriteMapper; | ||
211 | QSharedPointer<WritePropertyMapper<ResourceBuilder> > mResourceWriteMapper; | ||
77 | }; | 212 | }; |
78 | 213 | ||
79 | 214 | ||
diff --git a/common/entitybuffer.cpp b/common/entitybuffer.cpp index 5ba4afe..b555ac3 100644 --- a/common/entitybuffer.cpp +++ b/common/entitybuffer.cpp | |||
@@ -56,17 +56,24 @@ void EntityBuffer::extractResourceBuffer(void *dataValue, int dataSize, const st | |||
56 | } | 56 | } |
57 | } | 57 | } |
58 | 58 | ||
59 | void EntityBuffer::assembleEntityBuffer(flatbuffers::FlatBufferBuilder &fbb, void const *metadataData, size_t metadataSize, void const *resourceData, size_t resourceSize, void const *localData, size_t localSize) | 59 | flatbuffers::Offset<flatbuffers::Vector<uint8_t> > EntityBuffer::appendAsVector(flatbuffers::FlatBufferBuilder &fbb, void const *data, size_t size) |
60 | { | 60 | { |
61 | auto metadata = fbb.CreateVector<uint8_t>(static_cast<uint8_t const*>(metadataData), metadataSize); | 61 | //Since we do memcpy trickery, this will only work on little endian |
62 | auto resource = fbb.CreateVector<uint8_t>(static_cast<uint8_t const*>(resourceData), resourceSize); | 62 | assert(FLATBUFFERS_LITTLEENDIAN); |
63 | auto local = fbb.CreateVector<uint8_t>(static_cast<uint8_t const*>(localData), localSize); | 63 | auto metadata = fbb.CreateUninitializedVector<uint8_t>(size); |
64 | auto builder = Akonadi2::EntityBuilder(fbb); | 64 | { |
65 | builder.add_metadata(metadata); | 65 | auto ptr = reinterpret_cast<flatbuffers::Vector<uint8_t> *>(fbb.GetBufferPointer())->Data(); |
66 | builder.add_resource(resource); | 66 | std::memcpy((void*)ptr, data, size); |
67 | builder.add_local(local); | 67 | } |
68 | return metadata; | ||
69 | } | ||
68 | 70 | ||
69 | auto buffer = builder.Finish(); | 71 | void EntityBuffer::assembleEntityBuffer(flatbuffers::FlatBufferBuilder &fbb, void const *metadataData, size_t metadataSize, void const *resourceData, size_t resourceSize, void const *localData, size_t localSize) |
70 | Akonadi2::FinishEntityBuffer(fbb, buffer); | 72 | { |
73 | auto metadata = appendAsVector(fbb, metadataData, metadataSize); | ||
74 | auto resource = appendAsVector(fbb, resourceData, resourceSize); | ||
75 | auto local = appendAsVector(fbb, localData, localSize); | ||
76 | auto entity = Akonadi2::CreateEntity(fbb, metadata, resource, local); | ||
77 | Akonadi2::FinishEntityBuffer(fbb, entity); | ||
71 | } | 78 | } |
72 | 79 | ||
diff --git a/common/entitybuffer.h b/common/entitybuffer.h index 097b450..82152c9 100644 --- a/common/entitybuffer.h +++ b/common/entitybuffer.h | |||
@@ -15,7 +15,33 @@ public: | |||
15 | const Entity &entity(); | 15 | const Entity &entity(); |
16 | 16 | ||
17 | static void extractResourceBuffer(void *dataValue, int dataSize, const std::function<void(const uint8_t *, size_t size)> &handler); | 17 | static void extractResourceBuffer(void *dataValue, int dataSize, const std::function<void(const uint8_t *, size_t size)> &handler); |
18 | /* | ||
19 | * TODO: Ideally we would be passing references to vectors in the same bufferbuilder, to avoid needlessly copying data. | ||
20 | * Unfortunately I couldn't find a way to cast a table to a vector<uint8_t> reference. | ||
21 | * We can't use union's either (which would allow to have a field that stores a selection of tables), as we don't want to modify | ||
22 | * the entity schema for each resource's buffers. | ||
23 | */ | ||
18 | static void assembleEntityBuffer(flatbuffers::FlatBufferBuilder &fbb, void const *metadataData, size_t metadataSize, void const *resourceData, size_t resourceSize, void const *localData, size_t localSize); | 24 | static void assembleEntityBuffer(flatbuffers::FlatBufferBuilder &fbb, void const *metadataData, size_t metadataSize, void const *resourceData, size_t resourceSize, void const *localData, size_t localSize); |
25 | static flatbuffers::Offset<flatbuffers::Vector<uint8_t> > appendAsVector(flatbuffers::FlatBufferBuilder &fbb, void const *data, size_t size); | ||
26 | template<typename T> | ||
27 | static const T *readBuffer(const uint8_t *data, int size) | ||
28 | { | ||
29 | flatbuffers::Verifier verifier(data, size); | ||
30 | if (verifier.VerifyBuffer<T>()) { | ||
31 | return flatbuffers::GetRoot<T>(data); | ||
32 | } | ||
33 | return nullptr; | ||
34 | } | ||
35 | |||
36 | template<typename T> | ||
37 | static const T *readBuffer(const flatbuffers::Vector<uint8_t> *data) | ||
38 | { | ||
39 | if (data) { | ||
40 | return readBuffer<T>(data->Data(), data->size()); | ||
41 | } | ||
42 | return nullptr; | ||
43 | } | ||
44 | |||
19 | 45 | ||
20 | private: | 46 | private: |
21 | const Entity *mEntity; | 47 | const Entity *mEntity; |
diff --git a/common/facade.h b/common/facade.h new file mode 100644 index 0000000..98bcb38 --- /dev/null +++ b/common/facade.h | |||
@@ -0,0 +1,88 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Christian Mollekopf <chrigi_1@fastmail.fm> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the | ||
16 | * Free Software Foundation, Inc., | ||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | */ | ||
19 | |||
20 | #pragma once | ||
21 | |||
22 | #include "clientapi.h" | ||
23 | |||
24 | #include <QByteArray> | ||
25 | |||
26 | #include "async/src/async.h" | ||
27 | #include "resourceaccess.h" | ||
28 | #include "commands.h" | ||
29 | #include "createentity_generated.h" | ||
30 | #include "domainadaptor.h" | ||
31 | #include "entitybuffer.h" | ||
32 | |||
33 | namespace Akonadi2 { | ||
34 | class ResourceAccess; | ||
35 | /** | ||
36 | * Default facade implementation for resources that are implemented in a separate process using the ResourceAccess class. | ||
37 | */ | ||
38 | template <typename DomainType> | ||
39 | class GenericFacade: public Akonadi2::StoreFacade<DomainType> | ||
40 | { | ||
41 | public: | ||
42 | GenericFacade(const QByteArray &resourceIdentifier) | ||
43 | : Akonadi2::StoreFacade<DomainType>(), | ||
44 | mResourceAccess(new ResourceAccess(resourceIdentifier)) | ||
45 | { | ||
46 | } | ||
47 | |||
48 | ~GenericFacade() | ||
49 | { | ||
50 | } | ||
51 | |||
52 | protected: | ||
53 | Async::Job<void> sendCreateCommand(const QByteArray &t, const QByteArray &buffer) | ||
54 | { | ||
55 | flatbuffers::FlatBufferBuilder fbb; | ||
56 | //This is the resource buffer type and not the domain type | ||
57 | auto type = fbb.CreateString(t.constData()); | ||
58 | auto delta = Akonadi2::EntityBuffer::appendAsVector(fbb, buffer.constData(), buffer.size()); | ||
59 | auto location = Akonadi2::Commands::CreateCreateEntity(fbb, type, delta); | ||
60 | Akonadi2::Commands::FinishCreateEntityBuffer(fbb, location); | ||
61 | mResourceAccess->open(); | ||
62 | return mResourceAccess->sendCommand(Akonadi2::Commands::CreateEntityCommand, fbb); | ||
63 | } | ||
64 | |||
65 | Async::Job<void> synchronizeResource(bool sync, bool processAll) | ||
66 | { | ||
67 | //TODO check if a sync is necessary | ||
68 | //TODO Only sync what was requested | ||
69 | //TODO timeout | ||
70 | //TODO the synchronization should normally not be necessary: We just return what is already available. | ||
71 | |||
72 | if (sync || processAll) { | ||
73 | return Async::start<void>([=](Async::Future<void> &future) { | ||
74 | mResourceAccess->open(); | ||
75 | mResourceAccess->synchronizeResource(sync, processAll).then<void>([&future]() { | ||
76 | future.setFinished(); | ||
77 | }).exec(); | ||
78 | }); | ||
79 | } | ||
80 | return Async::null<void>(); | ||
81 | } | ||
82 | |||
83 | private: | ||
84 | //TODO use one resource access instance per application => make static | ||
85 | QSharedPointer<Akonadi2::ResourceAccess> mResourceAccess; | ||
86 | }; | ||
87 | |||
88 | } | ||
diff --git a/common/resource.h b/common/resource.h index bcce229..18a6827 100644 --- a/common/resource.h +++ b/common/resource.h | |||
@@ -26,10 +26,12 @@ | |||
26 | namespace Akonadi2 | 26 | namespace Akonadi2 |
27 | { | 27 | { |
28 | 28 | ||
29 | /** | ||
30 | * Resource interface | ||
31 | */ | ||
29 | class AKONADI2COMMON_EXPORT Resource | 32 | class AKONADI2COMMON_EXPORT Resource |
30 | { | 33 | { |
31 | public: | 34 | public: |
32 | //TODO: configuration | ||
33 | Resource(); | 35 | Resource(); |
34 | virtual ~Resource(); | 36 | virtual ~Resource(); |
35 | 37 | ||
@@ -44,6 +46,9 @@ private: | |||
44 | Private * const d; | 46 | Private * const d; |
45 | }; | 47 | }; |
46 | 48 | ||
49 | /** | ||
50 | * Factory interface for resource to implement. | ||
51 | */ | ||
47 | class ResourceFactory : public QObject | 52 | class ResourceFactory : public QObject |
48 | { | 53 | { |
49 | public: | 54 | public: |
diff --git a/common/resourceaccess.cpp b/common/resourceaccess.cpp index 7320e50..7a343f9 100644 --- a/common/resourceaccess.cpp +++ b/common/resourceaccess.cpp | |||
@@ -64,8 +64,8 @@ public: | |||
64 | class ResourceAccess::Private | 64 | class ResourceAccess::Private |
65 | { | 65 | { |
66 | public: | 66 | public: |
67 | Private(const QString &name, ResourceAccess *ra); | 67 | Private(const QByteArray &name, ResourceAccess *ra); |
68 | QString resourceName; | 68 | QByteArray resourceName; |
69 | QLocalSocket *socket; | 69 | QLocalSocket *socket; |
70 | QTimer *tryOpenTimer; | 70 | QTimer *tryOpenTimer; |
71 | bool startingProcess; | 71 | bool startingProcess; |
@@ -77,7 +77,7 @@ public: | |||
77 | uint messageId; | 77 | uint messageId; |
78 | }; | 78 | }; |
79 | 79 | ||
80 | ResourceAccess::Private::Private(const QString &name, ResourceAccess *q) | 80 | ResourceAccess::Private::Private(const QByteArray &name, ResourceAccess *q) |
81 | : resourceName(name), | 81 | : resourceName(name), |
82 | socket(new QLocalSocket(q)), | 82 | socket(new QLocalSocket(q)), |
83 | tryOpenTimer(new QTimer(q)), | 83 | tryOpenTimer(new QTimer(q)), |
@@ -87,7 +87,7 @@ ResourceAccess::Private::Private(const QString &name, ResourceAccess *q) | |||
87 | { | 87 | { |
88 | } | 88 | } |
89 | 89 | ||
90 | ResourceAccess::ResourceAccess(const QString &resourceName, QObject *parent) | 90 | ResourceAccess::ResourceAccess(const QByteArray &resourceName, QObject *parent) |
91 | : QObject(parent), | 91 | : QObject(parent), |
92 | d(new Private(resourceName, this)) | 92 | d(new Private(resourceName, this)) |
93 | { | 93 | { |
@@ -112,7 +112,7 @@ ResourceAccess::~ResourceAccess() | |||
112 | 112 | ||
113 | } | 113 | } |
114 | 114 | ||
115 | QString ResourceAccess::resourceName() const | 115 | QByteArray ResourceAccess::resourceName() const |
116 | { | 116 | { |
117 | return d->resourceName; | 117 | return d->resourceName; |
118 | } | 118 | } |
diff --git a/common/resourceaccess.h b/common/resourceaccess.h index a5a2547..088bf36 100644 --- a/common/resourceaccess.h +++ b/common/resourceaccess.h | |||
@@ -35,10 +35,10 @@ class ResourceAccess : public QObject | |||
35 | Q_OBJECT | 35 | Q_OBJECT |
36 | 36 | ||
37 | public: | 37 | public: |
38 | ResourceAccess(const QString &resourceName, QObject *parent = 0); | 38 | ResourceAccess(const QByteArray &resourceName, QObject *parent = 0); |
39 | ~ResourceAccess(); | 39 | ~ResourceAccess(); |
40 | 40 | ||
41 | QString resourceName() const; | 41 | QByteArray resourceName() const; |
42 | bool isReady() const; | 42 | bool isReady() const; |
43 | 43 | ||
44 | Async::Job<void> sendCommand(int commandId); | 44 | Async::Job<void> sendCommand(int commandId); |
diff --git a/common/storage.h b/common/storage.h index 78faac0..09365b0 100644 --- a/common/storage.h +++ b/common/storage.h | |||
@@ -98,7 +98,7 @@ public: | |||
98 | * Set the default error handler. | 98 | * Set the default error handler. |
99 | */ | 99 | */ |
100 | void setDefaultErrorHandler(const std::function<void(const Storage::Error &error)> &errorHandler); | 100 | void setDefaultErrorHandler(const std::function<void(const Storage::Error &error)> &errorHandler); |
101 | std::function<void(const Storage::Error &error)> defaultErrorHandler(); | 101 | std::function<void(const Storage::Error &error)> defaultErrorHandler() const; |
102 | 102 | ||
103 | /** | 103 | /** |
104 | * A basic error handler that writes to std::cerr. | 104 | * A basic error handler that writes to std::cerr. |
diff --git a/common/storage_common.cpp b/common/storage_common.cpp index 5728096..65f6e57 100644 --- a/common/storage_common.cpp +++ b/common/storage_common.cpp | |||
@@ -46,7 +46,7 @@ void Storage::setDefaultErrorHandler(const std::function<void(const Storage::Err | |||
46 | mErrorHandler = errorHandler; | 46 | mErrorHandler = errorHandler; |
47 | } | 47 | } |
48 | 48 | ||
49 | std::function<void(const Storage::Error &error)> Storage::defaultErrorHandler() | 49 | std::function<void(const Storage::Error &error)> Storage::defaultErrorHandler() const |
50 | { | 50 | { |
51 | if (mErrorHandler) { | 51 | if (mErrorHandler) { |
52 | return mErrorHandler; | 52 | return mErrorHandler; |
diff --git a/common/storage_lmdb.cpp b/common/storage_lmdb.cpp index 4fcb11f..7bbf8b5 100644 --- a/common/storage_lmdb.cpp +++ b/common/storage_lmdb.cpp | |||
@@ -425,11 +425,11 @@ qint64 Storage::diskUsage() const | |||
425 | void Storage::removeFromDisk() const | 425 | void Storage::removeFromDisk() const |
426 | { | 426 | { |
427 | const QString fullPath(d->storageRoot + '/' + d->name); | 427 | const QString fullPath(d->storageRoot + '/' + d->name); |
428 | qDebug() << "removing " << fullPath; | ||
429 | QMutexLocker locker(&d->sMutex); | 428 | QMutexLocker locker(&d->sMutex); |
430 | QDir dir(fullPath); | 429 | QDir dir(fullPath); |
431 | if (!dir.removeRecursively()) { | 430 | if (!dir.removeRecursively()) { |
432 | qWarning() << "Failed to remove directory" << d->storageRoot << d->name; | 431 | Error error(d->name.toLatin1(), ErrorCodes::GenericError, QString("Failed to remove directory %1 %2").arg(d->storageRoot).arg(d->name).toLatin1()); |
432 | defaultErrorHandler()(error); | ||
433 | } | 433 | } |
434 | auto env = d->sEnvironments.take(fullPath); | 434 | auto env = d->sEnvironments.take(fullPath); |
435 | mdb_env_close(env); | 435 | mdb_env_close(env); |
diff --git a/common/test/clientapitest.cpp b/common/test/clientapitest.cpp index c9e4d6d..24b3fb9 100644 --- a/common/test/clientapitest.cpp +++ b/common/test/clientapitest.cpp | |||
@@ -4,14 +4,14 @@ | |||
4 | 4 | ||
5 | #include "../clientapi.h" | 5 | #include "../clientapi.h" |
6 | 6 | ||
7 | class DummyResourceFacade : public Akonadi2::StoreFacade<Akonadi2::Domain::Event> | 7 | class DummyResourceFacade : public Akonadi2::StoreFacade<Akonadi2::ApplicationDomain::Event> |
8 | { | 8 | { |
9 | public: | 9 | public: |
10 | ~DummyResourceFacade(){}; | 10 | ~DummyResourceFacade(){}; |
11 | virtual Async::Job<void> create(const Akonadi2::Domain::Event &domainObject){ return Async::null<void>(); }; | 11 | virtual Async::Job<void> create(const Akonadi2::ApplicationDomain::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::ApplicationDomain::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::ApplicationDomain::Event &domainObject){ return Async::null<void>(); }; |
14 | virtual Async::Job<void> load(const Akonadi2::Query &query, const std::function<void(const Akonadi2::Domain::Event::Ptr &)> &resultCallback) | 14 | virtual Async::Job<void> load(const Akonadi2::Query &query, const std::function<void(const Akonadi2::ApplicationDomain::Event::Ptr &)> &resultCallback) |
15 | { | 15 | { |
16 | return Async::start<void>([this, resultCallback](Async::Future<void> &future) { | 16 | return Async::start<void>([this, resultCallback](Async::Future<void> &future) { |
17 | qDebug() << "load called"; | 17 | qDebug() << "load called"; |
@@ -22,7 +22,7 @@ public: | |||
22 | }); | 22 | }); |
23 | } | 23 | } |
24 | 24 | ||
25 | QList<Akonadi2::Domain::Event::Ptr> results; | 25 | QList<Akonadi2::ApplicationDomain::Event::Ptr> results; |
26 | }; | 26 | }; |
27 | 27 | ||
28 | class ClientAPITest : public QObject | 28 | class ClientAPITest : public QObject |
@@ -33,14 +33,14 @@ private Q_SLOTS: | |||
33 | void testLoad() | 33 | void testLoad() |
34 | { | 34 | { |
35 | DummyResourceFacade facade; | 35 | DummyResourceFacade facade; |
36 | facade.results << QSharedPointer<Akonadi2::Domain::Event>::create("resource", "id", 0, QSharedPointer<Akonadi2::Domain::BufferAdaptor>()); | 36 | facade.results << QSharedPointer<Akonadi2::ApplicationDomain::Event>::create("resource", "id", 0, QSharedPointer<Akonadi2::ApplicationDomain::BufferAdaptor>()); |
37 | 37 | ||
38 | Akonadi2::FacadeFactory::instance().registerFacade<Akonadi2::Domain::Event, DummyResourceFacade>("dummyresource", [facade](){ return new DummyResourceFacade(facade); }); | 38 | Akonadi2::FacadeFactory::instance().registerFacade<Akonadi2::ApplicationDomain::Event, DummyResourceFacade>("dummyresource", [facade](){ return new DummyResourceFacade(facade); }); |
39 | 39 | ||
40 | Akonadi2::Query query; | 40 | Akonadi2::Query query; |
41 | query.resources << "dummyresource"; | 41 | query.resources << "dummyresource"; |
42 | 42 | ||
43 | async::SyncListResult<Akonadi2::Domain::Event::Ptr> result(Akonadi2::Store::load<Akonadi2::Domain::Event>(query)); | 43 | async::SyncListResult<Akonadi2::ApplicationDomain::Event::Ptr> result(Akonadi2::Store::load<Akonadi2::ApplicationDomain::Event>(query)); |
44 | result.exec(); | 44 | result.exec(); |
45 | QCOMPARE(result.size(), 1); | 45 | QCOMPARE(result.size(), 1); |
46 | } | 46 | } |