summaryrefslogtreecommitdiffstats
path: root/examples/imapresource/imapresource.cpp
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2016-10-16 14:55:20 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2016-10-21 09:02:21 +0200
commit237b9ae4113e7a9f489632296941becb71afdb45 (patch)
tree01cde58f495944f01cad9d282391d4efd2897141 /examples/imapresource/imapresource.cpp
parent95d11bf0be98a4e3c08502fe23417b800233ce14 (diff)
downloadsink-237b9ae4113e7a9f489632296941becb71afdb45.tar.gz
sink-237b9ae4113e7a9f489632296941becb71afdb45.zip
Refactor how the storage is used.
This is the initial refactoring to improve how we deal with the storage. It does a couple of things: * Rename Sink::Storage to Sink::Storage::DataStore to free up the Sink::Storage namespace * Introduce a Sink::ResourceContext to have a single object that can be passed around containing everything that is necessary to operate on a resource. This is a lot better than the multiple separate parameters that we used to pass around all over the place, while still allowing for dependency injection for tests. * Tie storage access together using the new EntityStore that directly works with ApplicationDomainTypes. This gives us a central place where main storage, indexes and buffer adaptors are tied together, which will also give us a place to implement external indexes, such as a fulltextindex using xapian. * Use ApplicationDomainTypes as the default way to pass around entities. Instead of using various ways to pass around entities (buffers, buffer adaptors, ApplicationDomainTypes), only use a single way. The old approach was confusing, and was only done as: * optimization; really shouldn't be necessary and otherwise I'm sure we can find better ways to optimize ApplicationDomainType itself. * a way to account for entities that have multiple buffers, a concept that I no longer deem relevant. While this commit does the bulk of the work to get there, the following commits will refactor more stuff to get things back to normal.
Diffstat (limited to 'examples/imapresource/imapresource.cpp')
-rw-r--r--examples/imapresource/imapresource.cpp66
1 files changed, 24 insertions, 42 deletions
diff --git a/examples/imapresource/imapresource.cpp b/examples/imapresource/imapresource.cpp
index c72579c..0ea07bf 100644
--- a/examples/imapresource/imapresource.cpp
+++ b/examples/imapresource/imapresource.cpp
@@ -50,8 +50,8 @@
50#include <QtAlgorithms> 50#include <QtAlgorithms>
51 51
52#include "imapserverproxy.h" 52#include "imapserverproxy.h"
53#include "entityreader.h"
54#include "mailpreprocessor.h" 53#include "mailpreprocessor.h"
54#include "adaptorfactoryregistry.h"
55#include "specialpurposepreprocessor.h" 55#include "specialpurposepreprocessor.h"
56 56
57//This is the resources entity type, and not the domain type 57//This is the resources entity type, and not the domain type
@@ -92,8 +92,8 @@ static QByteArray assembleMailRid(const ApplicationDomain::Mail &mail, qint64 im
92 92
93class ImapSynchronizer : public Sink::Synchronizer { 93class ImapSynchronizer : public Sink::Synchronizer {
94public: 94public:
95 ImapSynchronizer(const QByteArray &resourceType, const QByteArray &resourceInstanceIdentifier) 95 ImapSynchronizer(const ResourceContext &resourceContext)
96 : Sink::Synchronizer(resourceType, resourceInstanceIdentifier) 96 : Sink::Synchronizer(resourceContext)
97 { 97 {
98 98
99 } 99 }
@@ -126,17 +126,6 @@ public:
126 SinkTrace() << "Found folders " << folderList.size(); 126 SinkTrace() << "Found folders " << folderList.size();
127 127
128 scanForRemovals(bufferType, 128 scanForRemovals(bufferType,
129 [this, &bufferType](const std::function<void(const QByteArray &)> &callback) {
130 //TODO Instead of iterating over all entries in the database, which can also pick up the same item multiple times,
131 //we should rather iterate over an index that contains every uid exactly once. The remoteId index would be such an index,
132 //but we currently fail to iterate over all entries in an index it seems.
133 // auto remoteIds = synchronizationTransaction.openDatabase("rid.mapping." + bufferType, std::function<void(const Sink::Storage::Error &)>(), true);
134 auto mainDatabase = Sink::Storage::mainDatabase(transaction(), bufferType);
135 mainDatabase.scan("", [&](const QByteArray &key, const QByteArray &) {
136 callback(key);
137 return true;
138 });
139 },
140 [&folderList](const QByteArray &remoteId) -> bool { 129 [&folderList](const QByteArray &remoteId) -> bool {
141 // folderList.contains(remoteId) 130 // folderList.contains(remoteId)
142 for (const auto &folderPath : folderList) { 131 for (const auto &folderPath : folderList) {
@@ -190,18 +179,12 @@ public:
190 const auto folderLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, path.toUtf8()); 179 const auto folderLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, path.toUtf8());
191 180
192 int count = 0; 181 int count = 0;
193 auto property = Sink::ApplicationDomain::Mail::Folder::name; 182
194 scanForRemovals(bufferType, 183 scanForRemovals(bufferType,
195 [&](const std::function<void(const QByteArray &)> &callback) { 184 [&](const std::function<void(const QByteArray &)> &callback) {
196 Index index(bufferType + ".index." + property, transaction()); 185 store().indexLookup<ApplicationDomain::Mail, ApplicationDomain::Mail::Folder>(folderLocalId, callback);
197 index.lookup(folderLocalId, [&](const QByteArray &sinkId) {
198 callback(sinkId);
199 },
200 [&](const Index::Error &error) {
201 SinkWarning() << "Error in index: " << error.message << property;
202 });
203 }, 186 },
204 [messages, path, &count](const QByteArray &remoteId) -> bool { 187 [&](const QByteArray &remoteId) -> bool {
205 if (messages.contains(uidFromMailRid(remoteId))) { 188 if (messages.contains(uidFromMailRid(remoteId))) {
206 return true; 189 return true;
207 } 190 }
@@ -347,7 +330,7 @@ public:
347class ImapWriteback : public Sink::SourceWriteBack 330class ImapWriteback : public Sink::SourceWriteBack
348{ 331{
349public: 332public:
350 ImapWriteback(const QByteArray &resourceType, const QByteArray &resourceInstanceIdentifier) : Sink::SourceWriteBack(resourceType, resourceInstanceIdentifier) 333 ImapWriteback(const ResourceContext &resourceContext) : Sink::SourceWriteBack(resourceContext)
351 { 334 {
352 335
353 } 336 }
@@ -514,10 +497,10 @@ public:
514 QByteArray mResourceInstanceIdentifier; 497 QByteArray mResourceInstanceIdentifier;
515}; 498};
516 499
517ImapResource::ImapResource(const QByteArray &instanceIdentifier, const QSharedPointer<Sink::Pipeline> &pipeline) 500ImapResource::ImapResource(const ResourceContext &resourceContext, const QSharedPointer<Sink::Pipeline> &pipeline)
518 : Sink::GenericResource(PLUGIN_NAME, instanceIdentifier, pipeline) 501 : Sink::GenericResource(resourceContext, pipeline)
519{ 502{
520 auto config = ResourceConfig::getConfiguration(instanceIdentifier); 503 auto config = ResourceConfig::getConfiguration(resourceContext.instanceId());
521 mServer = config.value("server").toString(); 504 mServer = config.value("server").toString();
522 mPort = config.value("port").toInt(); 505 mPort = config.value("port").toInt();
523 mUser = config.value("username").toString(); 506 mUser = config.value("username").toString();
@@ -532,46 +515,45 @@ ImapResource::ImapResource(const QByteArray &instanceIdentifier, const QSharedPo
532 mPort = list.at(1).toInt(); 515 mPort = list.at(1).toInt();
533 } 516 }
534 517
535 auto synchronizer = QSharedPointer<ImapSynchronizer>::create(PLUGIN_NAME, instanceIdentifier); 518 auto synchronizer = QSharedPointer<ImapSynchronizer>::create(resourceContext);
536 synchronizer->mServer = mServer; 519 synchronizer->mServer = mServer;
537 synchronizer->mPort = mPort; 520 synchronizer->mPort = mPort;
538 synchronizer->mUser = mUser; 521 synchronizer->mUser = mUser;
539 synchronizer->mPassword = mPassword; 522 synchronizer->mPassword = mPassword;
540 synchronizer->mResourceInstanceIdentifier = instanceIdentifier;
541 setupSynchronizer(synchronizer); 523 setupSynchronizer(synchronizer);
542 auto changereplay = QSharedPointer<ImapWriteback>::create(PLUGIN_NAME, instanceIdentifier); 524 auto changereplay = QSharedPointer<ImapWriteback>::create(resourceContext);
543 changereplay->mServer = mServer; 525 changereplay->mServer = mServer;
544 changereplay->mPort = mPort; 526 changereplay->mPort = mPort;
545 changereplay->mUser = mUser; 527 changereplay->mUser = mUser;
546 changereplay->mPassword = mPassword; 528 changereplay->mPassword = mPassword;
547 setupChangereplay(changereplay); 529 setupChangereplay(changereplay);
548 530
549 setupPreprocessors(ENTITY_TYPE_MAIL, QVector<Sink::Preprocessor*>() << new SpecialPurposeProcessor(mResourceType, mResourceInstanceIdentifier) << new MimeMessageMover << new MailPropertyExtractor << new DefaultIndexUpdater<Sink::ApplicationDomain::Mail>); 531 setupPreprocessors(ENTITY_TYPE_MAIL, QVector<Sink::Preprocessor*>() << new SpecialPurposeProcessor(resourceContext.resourceType, resourceContext.instanceId()) << new MimeMessageMover << new MailPropertyExtractor << new DefaultIndexUpdater<Sink::ApplicationDomain::Mail>);
550 setupPreprocessors(ENTITY_TYPE_FOLDER, QVector<Sink::Preprocessor*>() << new DefaultIndexUpdater<Sink::ApplicationDomain::Folder>); 532 setupPreprocessors(ENTITY_TYPE_FOLDER, QVector<Sink::Preprocessor*>() << new DefaultIndexUpdater<Sink::ApplicationDomain::Folder>);
551} 533}
552 534
553void ImapResource::removeFromDisk(const QByteArray &instanceIdentifier) 535void ImapResource::removeFromDisk(const QByteArray &instanceIdentifier)
554{ 536{
555 GenericResource::removeFromDisk(instanceIdentifier); 537 GenericResource::removeFromDisk(instanceIdentifier);
556 Sink::Storage(Sink::storageLocation(), instanceIdentifier + ".synchronization", Sink::Storage::ReadWrite).removeFromDisk(); 538 Sink::Storage::DataStore(Sink::storageLocation(), instanceIdentifier + ".synchronization", Sink::Storage::DataStore::ReadWrite).removeFromDisk();
557} 539}
558 540
559KAsync::Job<void> ImapResource::inspect(int inspectionType, const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expectedValue) 541KAsync::Job<void> ImapResource::inspect(int inspectionType, const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expectedValue)
560{ 542{
561 auto synchronizationStore = QSharedPointer<Sink::Storage>::create(Sink::storageLocation(), mResourceInstanceIdentifier + ".synchronization", Sink::Storage::ReadOnly); 543 auto synchronizationStore = QSharedPointer<Sink::Storage::DataStore>::create(Sink::storageLocation(), mResourceContext.instanceId() + ".synchronization", Sink::Storage::DataStore::ReadOnly);
562 auto synchronizationTransaction = synchronizationStore->createTransaction(Sink::Storage::ReadOnly); 544 auto synchronizationTransaction = synchronizationStore->createTransaction(Sink::Storage::DataStore::ReadOnly);
563 545
564 auto mainStore = QSharedPointer<Sink::Storage>::create(Sink::storageLocation(), mResourceInstanceIdentifier, Sink::Storage::ReadOnly); 546 auto mainStore = QSharedPointer<Sink::Storage::DataStore>::create(Sink::storageLocation(), mResourceContext.instanceId(), Sink::Storage::DataStore::ReadOnly);
565 auto transaction = mainStore->createTransaction(Sink::Storage::ReadOnly); 547 auto transaction = mainStore->createTransaction(Sink::Storage::DataStore::ReadOnly);
566 548
567 auto entityStore = QSharedPointer<Sink::EntityStore>::create(mResourceType, mResourceInstanceIdentifier, transaction); 549 Sink::Storage::EntityStore entityStore(mResourceContext);
568 auto syncStore = QSharedPointer<Sink::RemoteIdMap>::create(synchronizationTransaction); 550 auto syncStore = QSharedPointer<Sink::RemoteIdMap>::create(synchronizationTransaction);
569 551
570 SinkTrace() << "Inspecting " << inspectionType << domainType << entityId << property << expectedValue; 552 SinkTrace() << "Inspecting " << inspectionType << domainType << entityId << property << expectedValue;
571 553
572 if (domainType == ENTITY_TYPE_MAIL) { 554 if (domainType == ENTITY_TYPE_MAIL) {
573 const auto mail = entityStore->read<Sink::ApplicationDomain::Mail>(entityId); 555 const auto mail = entityStore.readLatest<Sink::ApplicationDomain::Mail>(entityId);
574 const auto folder = entityStore->read<Sink::ApplicationDomain::Folder>(mail.getFolder()); 556 const auto folder = entityStore.readLatest<Sink::ApplicationDomain::Folder>(mail.getFolder());
575 const auto folderRemoteId = syncStore->resolveLocalId(ENTITY_TYPE_FOLDER, mail.getFolder()); 557 const auto folderRemoteId = syncStore->resolveLocalId(ENTITY_TYPE_FOLDER, mail.getFolder());
576 const auto mailRemoteId = syncStore->resolveLocalId(ENTITY_TYPE_MAIL, mail.identifier()); 558 const auto mailRemoteId = syncStore->resolveLocalId(ENTITY_TYPE_MAIL, mail.identifier());
577 if (mailRemoteId.isEmpty() || folderRemoteId.isEmpty()) { 559 if (mailRemoteId.isEmpty() || folderRemoteId.isEmpty()) {
@@ -635,7 +617,7 @@ KAsync::Job<void> ImapResource::inspect(int inspectionType, const QByteArray &in
635 } 617 }
636 if (domainType == ENTITY_TYPE_FOLDER) { 618 if (domainType == ENTITY_TYPE_FOLDER) {
637 const auto remoteId = syncStore->resolveLocalId(ENTITY_TYPE_FOLDER, entityId); 619 const auto remoteId = syncStore->resolveLocalId(ENTITY_TYPE_FOLDER, entityId);
638 const auto folder = entityStore->read<Sink::ApplicationDomain::Folder>(entityId); 620 const auto folder = entityStore.readLatest<Sink::ApplicationDomain::Folder>(entityId);
639 621
640 if (inspectionType == Sink::ResourceControl::Inspection::CacheIntegrityInspectionType) { 622 if (inspectionType == Sink::ResourceControl::Inspection::CacheIntegrityInspectionType) {
641 SinkLog() << "Inspecting cache integrity" << remoteId; 623 SinkLog() << "Inspecting cache integrity" << remoteId;
@@ -698,9 +680,9 @@ ImapResourceFactory::ImapResourceFactory(QObject *parent)
698 680
699} 681}
700 682
701Sink::Resource *ImapResourceFactory::createResource(const QByteArray &instanceIdentifier) 683Sink::Resource *ImapResourceFactory::createResource(const ResourceContext &context)
702{ 684{
703 return new ImapResource(instanceIdentifier); 685 return new ImapResource(context);
704} 686}
705 687
706void ImapResourceFactory::registerFacades(Sink::FacadeFactory &factory) 688void ImapResourceFactory::registerFacades(Sink::FacadeFactory &factory)