summaryrefslogtreecommitdiffstats
path: root/examples/maildirresource/maildirresource.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/maildirresource/maildirresource.cpp')
-rw-r--r--examples/maildirresource/maildirresource.cpp63
1 files changed, 62 insertions, 1 deletions
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
66void 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
74void 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
66QString MaildirResource::resolveRemoteId(const QByteArray &bufferType, const QString &remoteId, Akonadi2::Storage::Transaction &transaction) 82QString 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
343KAsync::Job<void> MaildirResource::replay(const QByteArray &type, const QByteArray &key, const QByteArray &value) 363KAsync::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