diff options
Diffstat (limited to 'examples')
-rw-r--r-- | examples/maildirresource/libmaildir/maildir.cpp | 7 | ||||
-rw-r--r-- | examples/maildirresource/libmaildir/maildir.h | 5 | ||||
-rw-r--r-- | examples/maildirresource/maildirresource.cpp | 63 | ||||
-rw-r--r-- | examples/maildirresource/maildirresource.h | 6 |
4 files changed, 80 insertions, 1 deletions
diff --git a/examples/maildirresource/libmaildir/maildir.cpp b/examples/maildirresource/libmaildir/maildir.cpp index 67a2d2d..2b0148c 100644 --- a/examples/maildirresource/libmaildir/maildir.cpp +++ b/examples/maildirresource/libmaildir/maildir.cpp | |||
@@ -332,6 +332,13 @@ bool Maildir::create() | |||
332 | return true; | 332 | return true; |
333 | } | 333 | } |
334 | 334 | ||
335 | bool Maildir::remove() | ||
336 | { | ||
337 | QDir dir(d->path); | ||
338 | dir.removeRecursively(); | ||
339 | return true; | ||
340 | } | ||
341 | |||
335 | QString Maildir::path() const | 342 | QString Maildir::path() const |
336 | { | 343 | { |
337 | return d->path; | 344 | return d->path; |
diff --git a/examples/maildirresource/libmaildir/maildir.h b/examples/maildirresource/libmaildir/maildir.h index 6853033..f80ba5d 100644 --- a/examples/maildirresource/libmaildir/maildir.h +++ b/examples/maildirresource/libmaildir/maildir.h | |||
@@ -71,6 +71,11 @@ public: | |||
71 | bool create(); | 71 | bool create(); |
72 | 72 | ||
73 | /** | 73 | /** |
74 | * Remove the maildir and everything it contains. | ||
75 | */ | ||
76 | bool remove(); | ||
77 | |||
78 | /** | ||
74 | * Returns the path of this maildir. | 79 | * Returns the path of this maildir. |
75 | */ | 80 | */ |
76 | QString path() const; | 81 | QString path() const; |
diff --git a/examples/maildirresource/maildirresource.cpp b/examples/maildirresource/maildirresource.cpp index d0b663b..8333f76 100644 --- a/examples/maildirresource/maildirresource.cpp +++ b/examples/maildirresource/maildirresource.cpp | |||
@@ -63,6 +63,22 @@ MaildirResource::MaildirResource(const QByteArray &instanceIdentifier, const QSh | |||
63 | Trace() << "Started maildir resource for maildir: " << mMaildirPath; | 63 | Trace() << "Started maildir resource for maildir: " << mMaildirPath; |
64 | } | 64 | } |
65 | 65 | ||
66 | void MaildirResource::recordRemoteId(const QByteArray &bufferType, const QByteArray &localId, const QByteArray &remoteId, Akonadi2::Storage::Transaction &transaction) | ||
67 | { | ||
68 | Index index("rid.mapping." + bufferType, transaction); | ||
69 | Index localIndex("localid.mapping." + bufferType, transaction); | ||
70 | index.add(remoteId, localId); | ||
71 | localIndex.add(localId, remoteId); | ||
72 | } | ||
73 | |||
74 | void MaildirResource::removeRemoteId(const QByteArray &bufferType, const QByteArray &localId, const QByteArray &remoteId, Akonadi2::Storage::Transaction &transaction) | ||
75 | { | ||
76 | Index index("rid.mapping." + bufferType, transaction); | ||
77 | Index localIndex("localid.mapping." + bufferType, transaction); | ||
78 | index.remove(remoteId, localId); | ||
79 | localIndex.remove(localId, remoteId); | ||
80 | } | ||
81 | |||
66 | QString MaildirResource::resolveRemoteId(const QByteArray &bufferType, const QString &remoteId, Akonadi2::Storage::Transaction &transaction) | 82 | QString MaildirResource::resolveRemoteId(const QByteArray &bufferType, const QString &remoteId, Akonadi2::Storage::Transaction &transaction) |
67 | { | 83 | { |
68 | //Lookup local id for remote id, or insert a new pair otherwise | 84 | //Lookup local id for remote id, or insert a new pair otherwise |
@@ -332,17 +348,62 @@ KAsync::Job<void> MaildirResource::synchronizeWithSource() | |||
332 | { | 348 | { |
333 | Log() << " Synchronizing"; | 349 | Log() << " Synchronizing"; |
334 | return KAsync::start<void>([this]() { | 350 | return KAsync::start<void>([this]() { |
351 | //Changereplay would deadlock otherwise when trying to open the synchronization store | ||
352 | enableChangeReplay(false); | ||
335 | auto transaction = Akonadi2::Storage(Akonadi2::storageLocation(), mResourceInstanceIdentifier, Akonadi2::Storage::ReadOnly).createTransaction(Akonadi2::Storage::ReadOnly); | 353 | auto transaction = Akonadi2::Storage(Akonadi2::storageLocation(), mResourceInstanceIdentifier, Akonadi2::Storage::ReadOnly).createTransaction(Akonadi2::Storage::ReadOnly); |
336 | synchronizeFolders(transaction); | 354 | synchronizeFolders(transaction); |
337 | for (const auto &folder : listAvailableFolders()) { | 355 | for (const auto &folder : listAvailableFolders()) { |
338 | synchronizeMails(transaction, folder); | 356 | synchronizeMails(transaction, folder); |
339 | } | 357 | } |
358 | Log() << "Done Synchronizing"; | ||
359 | enableChangeReplay(true); | ||
340 | }); | 360 | }); |
341 | } | 361 | } |
342 | 362 | ||
343 | KAsync::Job<void> MaildirResource::replay(const QByteArray &type, const QByteArray &key, const QByteArray &value) | 363 | KAsync::Job<void> MaildirResource::replay(const QByteArray &type, const QByteArray &key, const QByteArray &value) |
344 | { | 364 | { |
345 | Trace() << "Replaying " << key; | 365 | //This results in a deadlock during sync |
366 | Akonadi2::Storage store(Akonadi2::storageLocation(), mResourceInstanceIdentifier + ".synchronization", Akonadi2::Storage::ReadWrite); | ||
367 | auto synchronizationTransaction = store.createTransaction(Akonadi2::Storage::ReadWrite); | ||
368 | const auto uid = Akonadi2::Storage::uidFromKey(key); | ||
369 | const auto remoteId = resolveLocalId(type, uid, synchronizationTransaction); | ||
370 | |||
371 | Trace() << "Replaying " << key << type; | ||
372 | if (type == ENTITY_TYPE_FOLDER) { | ||
373 | Akonadi2::EntityBuffer buffer(value.data(), value.size()); | ||
374 | const Akonadi2::Entity &entity = buffer.entity(); | ||
375 | const auto metadataBuffer = Akonadi2::EntityBuffer::readBuffer<Akonadi2::Metadata>(entity.metadata()); | ||
376 | const qint64 revision = metadataBuffer ? metadataBuffer->revision() : -1; | ||
377 | const auto operation = metadataBuffer ? metadataBuffer->operation() : Akonadi2::Operation_Creation; | ||
378 | if (operation == Akonadi2::Operation_Creation) { | ||
379 | //FIXME: This check only works for new entities | ||
380 | //Figure out wether we have replayed that revision already to the source | ||
381 | if (!remoteId.isEmpty()) { | ||
382 | Trace() << "Change is coming from the source"; | ||
383 | return KAsync::null<void>(); | ||
384 | } | ||
385 | const Akonadi2::ApplicationDomain::Folder folder(mResourceInstanceIdentifier, Akonadi2::Storage::uidFromKey(key), revision, mFolderAdaptorFactory->createAdaptor(entity)); | ||
386 | auto folderName = folder.getProperty("name").toString(); | ||
387 | //TODO handle non toplevel folders | ||
388 | auto path = mMaildirPath + "/" + folderName; | ||
389 | Trace() << "Creating a new folder: " << path; | ||
390 | KPIM::Maildir maildir(path, false); | ||
391 | maildir.create(); | ||
392 | recordRemoteId(ENTITY_TYPE_FOLDER, folder.identifier(), path.toUtf8(), synchronizationTransaction); | ||
393 | } else if (operation == Akonadi2::Operation_Removal) { | ||
394 | const auto uid = Akonadi2::Storage::uidFromKey(key); | ||
395 | const auto remoteId = resolveLocalId(ENTITY_TYPE_FOLDER, uid, synchronizationTransaction); | ||
396 | const auto path = remoteId; | ||
397 | Trace() << "Removing a folder: " << path; | ||
398 | KPIM::Maildir maildir(path, false); | ||
399 | maildir.remove(); | ||
400 | removeRemoteId(ENTITY_TYPE_FOLDER, uid, remoteId.toUtf8(), synchronizationTransaction); | ||
401 | } else if (operation == Akonadi2::Operation_Modification) { | ||
402 | Warning() << "Folder modifications are not implemented"; | ||
403 | } else { | ||
404 | Warning() << "Unkown operation" << operation; | ||
405 | } | ||
406 | } | ||
346 | return KAsync::null<void>(); | 407 | return KAsync::null<void>(); |
347 | } | 408 | } |
348 | 409 | ||
diff --git a/examples/maildirresource/maildirresource.h b/examples/maildirresource/maildirresource.h index eec1e97..e577e18 100644 --- a/examples/maildirresource/maildirresource.h +++ b/examples/maildirresource/maildirresource.h | |||
@@ -41,6 +41,12 @@ private: | |||
41 | KAsync::Job<void> replay(const QByteArray &type, const QByteArray &key, const QByteArray &value) Q_DECL_OVERRIDE; | 41 | KAsync::Job<void> replay(const QByteArray &type, const QByteArray &key, const QByteArray &value) Q_DECL_OVERRIDE; |
42 | 42 | ||
43 | /** | 43 | /** |
44 | * Records a localId to remoteId mapping | ||
45 | */ | ||
46 | void recordRemoteId(const QByteArray &bufferType, const QByteArray &localId, const QByteArray &remoteId, Akonadi2::Storage::Transaction &transaction); | ||
47 | void removeRemoteId(const QByteArray &bufferType, const QByteArray &localId, const QByteArray &remoteId, Akonadi2::Storage::Transaction &transaction); | ||
48 | |||
49 | /** | ||
44 | * Tries to find a local id for the remote id, and creates a new local id otherwise. | 50 | * Tries to find a local id for the remote id, and creates a new local id otherwise. |
45 | * | 51 | * |
46 | * The new local id is recorded in the local to remote id mapping. | 52 | * The new local id is recorded in the local to remote id mapping. |