summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/changereplay.cpp28
-rw-r--r--common/changereplay.h1
-rw-r--r--common/commands/notification.fbs7
-rw-r--r--common/configstore.cpp12
-rw-r--r--common/definitions.cpp14
-rw-r--r--common/definitions.h2
-rw-r--r--common/domain/applicationdomaintype.cpp16
-rw-r--r--common/domain/applicationdomaintype.h62
-rw-r--r--common/domain/folder.cpp4
-rw-r--r--common/domain/mail.cpp4
-rw-r--r--common/domainadaptor.h15
-rw-r--r--common/entityreader.cpp50
-rw-r--r--common/facade.cpp9
-rw-r--r--common/facade.h3
-rw-r--r--common/genericresource.cpp103
-rw-r--r--common/genericresource.h5
-rw-r--r--common/index.cpp9
-rw-r--r--common/index.h2
-rw-r--r--common/listener.cpp112
-rw-r--r--common/listener.h12
-rw-r--r--common/log.cpp104
-rw-r--r--common/log.h28
-rw-r--r--common/mailpreprocessor.cpp20
-rw-r--r--common/messagequeue.cpp6
-rw-r--r--common/modelresult.cpp19
-rw-r--r--common/notification.h13
-rw-r--r--common/pipeline.cpp90
-rw-r--r--common/pipeline.h4
-rw-r--r--common/queryrunner.cpp44
-rw-r--r--common/queryrunner.h4
-rw-r--r--common/remoteidmap.cpp4
-rw-r--r--common/resource.h2
-rw-r--r--common/resourceaccess.cpp144
-rw-r--r--common/resourceaccess.h16
-rw-r--r--common/resourceconfig.cpp4
-rw-r--r--common/resourcecontrol.cpp21
-rw-r--r--common/resourcefacade.cpp278
-rw-r--r--common/resourcefacade.h29
-rw-r--r--common/sourcewriteback.cpp24
-rw-r--r--common/specialpurposepreprocessor.cpp4
-rw-r--r--common/storage.h27
-rw-r--r--common/storage_common.cpp12
-rw-r--r--common/storage_lmdb.cpp61
-rw-r--r--common/store.cpp55
-rw-r--r--common/synchronizer.cpp38
-rw-r--r--common/test.cpp39
-rw-r--r--common/typeindex.cpp21
-rw-r--r--docs/sinksh.md10
-rw-r--r--examples/client/main.cpp2
-rw-r--r--examples/dummyresource/resourcefactory.cpp23
-rw-r--r--examples/dummyresource/resourcefactory.h5
-rw-r--r--examples/imapresource/imapresource.cpp99
-rw-r--r--examples/imapresource/imapresource.h4
-rw-r--r--examples/imapresource/imapserverproxy.cpp40
-rw-r--r--examples/imapresource/tests/imapmailsynctest.cpp8
-rw-r--r--examples/imapresource/tests/imapmailtest.cpp8
-rw-r--r--examples/imapresource/tests/imapserverproxytest.cpp15
-rw-r--r--examples/imapresource/tests/resetmailbox.sh1
-rw-r--r--examples/maildirresource/facade.cpp4
-rw-r--r--examples/maildirresource/maildirresource.cpp57
-rw-r--r--examples/maildirresource/maildirresource.h4
-rw-r--r--examples/mailtransportresource/mailtransportresource.cpp18
-rw-r--r--examples/mailtransportresource/mailtransportresource.h4
-rw-r--r--examples/mailtransportresource/tests/mailtransporttest.cpp1
-rw-r--r--sinksh/CMakeLists.txt1
-rw-r--r--sinksh/sinksh_utils.cpp40
-rw-r--r--sinksh/sinksh_utils.h1
-rw-r--r--sinksh/syntax_modules/sink_clear.cpp2
-rw-r--r--sinksh/syntax_modules/sink_remove.cpp2
-rw-r--r--sinksh/syntax_modules/sink_stat.cpp29
-rw-r--r--sinksh/syntax_modules/sink_sync.cpp2
-rw-r--r--sinksh/syntax_modules/sink_trace.cpp87
-rw-r--r--synchronizer/main.cpp14
-rw-r--r--tests/accountstest.cpp45
-rw-r--r--tests/clientapitest.cpp11
-rw-r--r--tests/dummyresourcebenchmark.cpp32
-rw-r--r--tests/dummyresourcetest.cpp37
-rw-r--r--tests/dummyresourcewritebenchmark.cpp14
-rw-r--r--tests/genericfacadetest.cpp6
-rw-r--r--tests/genericresourcebenchmark.cpp16
-rw-r--r--tests/genericresourcetest.cpp7
-rw-r--r--tests/indextest.cpp6
-rw-r--r--tests/inspectiontest.cpp9
-rw-r--r--tests/maildirsyncbenchmark.cpp13
-rw-r--r--tests/mailquerybenchmark.cpp2
-rw-r--r--tests/mailsynctest.cpp10
-rw-r--r--tests/mailsynctest.h1
-rw-r--r--tests/mailtest.cpp8
-rw-r--r--tests/mailtest.h1
-rw-r--r--tests/messagequeuetest.cpp29
-rw-r--r--tests/modelinteractivitytest.cpp18
-rw-r--r--tests/pipelinebenchmark.cpp2
-rw-r--r--tests/pipelinetest.cpp61
-rw-r--r--tests/querytest.cpp59
-rw-r--r--tests/resourcecommunicationtest.cpp20
-rw-r--r--tests/resourceconfigtest.cpp28
-rw-r--r--tests/testaccounttest.cpp1
97 files changed, 1548 insertions, 950 deletions
diff --git a/common/changereplay.cpp b/common/changereplay.cpp
index 0096bd0..4b7d593 100644
--- a/common/changereplay.cpp
+++ b/common/changereplay.cpp
@@ -26,13 +26,12 @@
26 26
27using namespace Sink; 27using namespace Sink;
28 28
29#undef DEBUG_AREA 29SINK_DEBUG_AREA("changereplay");
30#define DEBUG_AREA "resource.changereplay"
31 30
32ChangeReplay::ChangeReplay(const QByteArray &resourceName) 31ChangeReplay::ChangeReplay(const QByteArray &resourceName)
33 : mStorage(storageLocation(), resourceName, Storage::ReadOnly), mChangeReplayStore(storageLocation(), resourceName + ".changereplay", Storage::ReadWrite), mReplayInProgress(false) 32 : mStorage(storageLocation(), resourceName, Storage::ReadOnly), mChangeReplayStore(storageLocation(), resourceName + ".changereplay", Storage::ReadWrite), mReplayInProgress(false)
34{ 33{
35 Trace() << "Created change replay: " << resourceName; 34 SinkTrace() << "Created change replay: " << resourceName;
36} 35}
37 36
38qint64 ChangeReplay::getLastReplayedRevision() 37qint64 ChangeReplay::getLastReplayedRevision()
@@ -51,10 +50,10 @@ qint64 ChangeReplay::getLastReplayedRevision()
51bool ChangeReplay::allChangesReplayed() 50bool ChangeReplay::allChangesReplayed()
52{ 51{
53 const qint64 topRevision = Storage::maxRevision(mStorage.createTransaction(Storage::ReadOnly, [](const Sink::Storage::Error &error) { 52 const qint64 topRevision = Storage::maxRevision(mStorage.createTransaction(Storage::ReadOnly, [](const Sink::Storage::Error &error) {
54 Warning() << error.message; 53 SinkWarning() << error.message;
55 })); 54 }));
56 const qint64 lastReplayedRevision = getLastReplayedRevision(); 55 const qint64 lastReplayedRevision = getLastReplayedRevision();
57 Trace() << "All changes replayed " << topRevision << lastReplayedRevision; 56 SinkTrace() << "All changes replayed " << topRevision << lastReplayedRevision;
58 return (lastReplayedRevision >= topRevision); 57 return (lastReplayedRevision >= topRevision);
59} 58}
60 59
@@ -62,10 +61,10 @@ KAsync::Job<void> ChangeReplay::replayNextRevision()
62{ 61{
63 mReplayInProgress = true; 62 mReplayInProgress = true;
64 auto mainStoreTransaction = mStorage.createTransaction(Storage::ReadOnly, [](const Sink::Storage::Error &error) { 63 auto mainStoreTransaction = mStorage.createTransaction(Storage::ReadOnly, [](const Sink::Storage::Error &error) {
65 Warning() << error.message; 64 SinkWarning() << error.message;
66 }); 65 });
67 auto replayStoreTransaction = mChangeReplayStore.createTransaction(Storage::ReadOnly, [](const Sink::Storage::Error &error) { 66 auto replayStoreTransaction = mChangeReplayStore.createTransaction(Storage::ReadOnly, [](const Sink::Storage::Error &error) {
68 Warning() << error.message; 67 SinkWarning() << error.message;
69 }); 68 });
70 qint64 lastReplayedRevision = 0; 69 qint64 lastReplayedRevision = 0;
71 replayStoreTransaction.openDatabase().scan("lastReplayedRevision", 70 replayStoreTransaction.openDatabase().scan("lastReplayedRevision",
@@ -78,14 +77,14 @@ KAsync::Job<void> ChangeReplay::replayNextRevision()
78 77
79 auto recordReplayedRevision = [this](qint64 revision) { 78 auto recordReplayedRevision = [this](qint64 revision) {
80 auto replayStoreTransaction = mChangeReplayStore.createTransaction(Storage::ReadWrite, [](const Sink::Storage::Error &error) { 79 auto replayStoreTransaction = mChangeReplayStore.createTransaction(Storage::ReadWrite, [](const Sink::Storage::Error &error) {
81 Warning() << error.message; 80 SinkWarning() << error.message;
82 }); 81 });
83 replayStoreTransaction.openDatabase().write("lastReplayedRevision", QByteArray::number(revision)); 82 replayStoreTransaction.openDatabase().write("lastReplayedRevision", QByteArray::number(revision));
84 replayStoreTransaction.commit(); 83 replayStoreTransaction.commit();
85 }; 84 };
86 85
87 if (lastReplayedRevision < topRevision) { 86 if (lastReplayedRevision < topRevision) {
88 Trace() << "Changereplay from " << lastReplayedRevision << " to " << topRevision; 87 SinkTrace() << "Changereplay from " << lastReplayedRevision << " to " << topRevision;
89 qint64 revision = lastReplayedRevision + 1; 88 qint64 revision = lastReplayedRevision + 1;
90 const auto uid = Storage::getUidFromRevision(mainStoreTransaction, revision); 89 const auto uid = Storage::getUidFromRevision(mainStoreTransaction, revision);
91 const auto type = Storage::getTypeFromRevision(mainStoreTransaction, revision); 90 const auto type = Storage::getTypeFromRevision(mainStoreTransaction, revision);
@@ -94,25 +93,25 @@ KAsync::Job<void> ChangeReplay::replayNextRevision()
94 Storage::mainDatabase(mainStoreTransaction, type) 93 Storage::mainDatabase(mainStoreTransaction, type)
95 .scan(key, 94 .scan(key,
96 [&lastReplayedRevision, type, this, &replayJob](const QByteArray &key, const QByteArray &value) -> bool { 95 [&lastReplayedRevision, type, this, &replayJob](const QByteArray &key, const QByteArray &value) -> bool {
97 Trace() << "Replaying " << key; 96 SinkTrace() << "Replaying " << key;
98 replayJob = replay(type, key, value); 97 replayJob = replay(type, key, value);
99 return false; 98 return false;
100 }, 99 },
101 [key](const Storage::Error &) { ErrorMsg() << "Failed to replay change " << key; }); 100 [key](const Storage::Error &) { SinkError() << "Failed to replay change " << key; });
102 return replayJob.then<void>([this, revision, recordReplayedRevision]() { 101 return replayJob.then<void>([this, revision, recordReplayedRevision]() {
103 Trace() << "Replayed until " << revision; 102 SinkTrace() << "Replayed until " << revision;
104 recordReplayedRevision(revision); 103 recordReplayedRevision(revision);
105 //replay until we're done 104 //replay until we're done
106 replayNextRevision().exec(); 105 replayNextRevision().exec();
107 }, 106 },
108 [this, revision, recordReplayedRevision](int, QString) { 107 [this, revision, recordReplayedRevision](int, QString) {
109 Trace() << "Change replay failed" << revision; 108 SinkTrace() << "Change replay failed" << revision;
110 //We're probably not online or so, so postpone retrying 109 //We're probably not online or so, so postpone retrying
111 mReplayInProgress = false; 110 mReplayInProgress = false;
112 emit changesReplayed(); 111 emit changesReplayed();
113 }); 112 });
114 } else { 113 } else {
115 Trace() << "No changes to replay"; 114 SinkTrace() << "No changes to replay";
116 mReplayInProgress = false; 115 mReplayInProgress = false;
117 emit changesReplayed(); 116 emit changesReplayed();
118 } 117 }
@@ -122,6 +121,7 @@ KAsync::Job<void> ChangeReplay::replayNextRevision()
122void ChangeReplay::revisionChanged() 121void ChangeReplay::revisionChanged()
123{ 122{
124 if (!mReplayInProgress) { 123 if (!mReplayInProgress) {
124 emit replayingChanges();
125 replayNextRevision().exec(); 125 replayNextRevision().exec();
126 } 126 }
127} 127}
diff --git a/common/changereplay.h b/common/changereplay.h
index aba3dd0..6c1c1db 100644
--- a/common/changereplay.h
+++ b/common/changereplay.h
@@ -45,6 +45,7 @@ public:
45 45
46signals: 46signals:
47 void changesReplayed(); 47 void changesReplayed();
48 void replayingChanges();
48 49
49public slots: 50public slots:
50 void revisionChanged(); 51 void revisionChanged();
diff --git a/common/commands/notification.fbs b/common/commands/notification.fbs
index 8750ff5..c82fad3 100644
--- a/common/commands/notification.fbs
+++ b/common/commands/notification.fbs
@@ -1,13 +1,10 @@
1namespace Sink.Commands; 1namespace Sink.Commands;
2 2
3enum NotificationType : byte { Shutdown = 1, Status, Warning, Progress, Inspection, RevisionUpdate }
4enum NotificationCode : byte { Success = 0, Failure = 1, UserCode }
5
6table Notification { 3table Notification {
7 type: NotificationType = Status; 4 type: int = 0; //See notification.h
8 identifier: string; //An identifier that links back to the something related to the notification (e.g. an entity id or a command id) 5 identifier: string; //An identifier that links back to the something related to the notification (e.g. an entity id or a command id)
9 message: string; 6 message: string;
10 code: int = 0; //Of type NotificationCode 7 code: int = 0; //See notification.h
11} 8}
12 9
13root_type Notification; 10root_type Notification;
diff --git a/common/configstore.cpp b/common/configstore.cpp
index a8469ba..9a68662 100644
--- a/common/configstore.cpp
+++ b/common/configstore.cpp
@@ -20,13 +20,15 @@
20 20
21#include <QSettings> 21#include <QSettings>
22#include <QSharedPointer> 22#include <QSharedPointer>
23#include <QStandardPaths>
24#include <QFile> 23#include <QFile>
25#include <log.h> 24#include <log.h>
25#include <definitions.h>
26
27SINK_DEBUG_AREA("configstore")
26 28
27static QSharedPointer<QSettings> getConfig(const QByteArray &identifier) 29static QSharedPointer<QSettings> getConfig(const QByteArray &identifier)
28{ 30{
29 return QSharedPointer<QSettings>::create(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/sink/" + identifier + ".ini", QSettings::IniFormat); 31 return QSharedPointer<QSettings>::create(Sink::configLocation() + "/" + identifier + ".ini", QSettings::IniFormat);
30} 32}
31 33
32ConfigStore::ConfigStore(const QByteArray &identifier) 34ConfigStore::ConfigStore(const QByteArray &identifier)
@@ -50,7 +52,7 @@ QMap<QByteArray, QByteArray> ConfigStore::getEntries()
50 52
51void ConfigStore::add(const QByteArray &identifier, const QByteArray &type) 53void ConfigStore::add(const QByteArray &identifier, const QByteArray &type)
52{ 54{
53 Trace() << "Adding " << identifier; 55 SinkTrace() << "Adding " << identifier;
54 mConfig->beginGroup(QString::fromLatin1(identifier)); 56 mConfig->beginGroup(QString::fromLatin1(identifier));
55 mConfig->setValue("type", type); 57 mConfig->setValue("type", type);
56 mConfig->endGroup(); 58 mConfig->endGroup();
@@ -59,7 +61,7 @@ void ConfigStore::add(const QByteArray &identifier, const QByteArray &type)
59 61
60void ConfigStore::remove(const QByteArray &identifier) 62void ConfigStore::remove(const QByteArray &identifier)
61{ 63{
62 Trace() << "Removing " << identifier; 64 SinkTrace() << "Removing " << identifier;
63 mConfig->beginGroup(QString::fromLatin1(identifier)); 65 mConfig->beginGroup(QString::fromLatin1(identifier));
64 mConfig->remove(""); 66 mConfig->remove("");
65 mConfig->endGroup(); 67 mConfig->endGroup();
@@ -75,7 +77,7 @@ void ConfigStore::clear()
75 77
76void ConfigStore::modify(const QByteArray &identifier, const QMap<QByteArray, QVariant> &configuration) 78void ConfigStore::modify(const QByteArray &identifier, const QMap<QByteArray, QVariant> &configuration)
77{ 79{
78 Trace() << "Modifying " << identifier; 80 SinkTrace() << "Modifying " << identifier;
79 auto config = getConfig(identifier); 81 auto config = getConfig(identifier);
80 config->clear(); 82 config->clear();
81 for (const auto &key : configuration.keys()) { 83 for (const auto &key : configuration.keys()) {
diff --git a/common/definitions.cpp b/common/definitions.cpp
index 362faf7..3fc4700 100644
--- a/common/definitions.cpp
+++ b/common/definitions.cpp
@@ -25,12 +25,22 @@
25 25
26QString Sink::storageLocation() 26QString Sink::storageLocation()
27{ 27{
28 return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/sink/storage"; 28 return dataLocation() + "/storage";
29}
30
31QString Sink::dataLocation()
32{
33 return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/sink";
34}
35
36QString Sink::configLocation()
37{
38 return QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/sink";
29} 39}
30 40
31QString Sink::temporaryFileLocation() 41QString Sink::temporaryFileLocation()
32{ 42{
33 auto path = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/sink/temporaryFiles"; 43 auto path = dataLocation() + "/temporaryFiles";
34 //FIXME create in a singleton on startup? 44 //FIXME create in a singleton on startup?
35 QDir dir; 45 QDir dir;
36 dir.mkpath(path); 46 dir.mkpath(path);
diff --git a/common/definitions.h b/common/definitions.h
index 1008235..e8cd45e 100644
--- a/common/definitions.h
+++ b/common/definitions.h
@@ -26,6 +26,8 @@
26 26
27namespace Sink { 27namespace Sink {
28QString SINK_EXPORT storageLocation(); 28QString SINK_EXPORT storageLocation();
29QString SINK_EXPORT dataLocation();
30QString SINK_EXPORT configLocation();
29QString SINK_EXPORT temporaryFileLocation(); 31QString SINK_EXPORT temporaryFileLocation();
30QString SINK_EXPORT resourceStorageLocation(const QByteArray &resourceInstanceIdentifier); 32QString SINK_EXPORT resourceStorageLocation(const QByteArray &resourceInstanceIdentifier);
31} 33}
diff --git a/common/domain/applicationdomaintype.cpp b/common/domain/applicationdomaintype.cpp
index 44eeb13..ce113c2 100644
--- a/common/domain/applicationdomaintype.cpp
+++ b/common/domain/applicationdomaintype.cpp
@@ -24,6 +24,8 @@
24#include "storage.h" //for generateUid() 24#include "storage.h" //for generateUid()
25#include <QFile> 25#include <QFile>
26 26
27SINK_DEBUG_AREA("applicationdomaintype");
28
27namespace Sink { 29namespace Sink {
28namespace ApplicationDomain { 30namespace ApplicationDomain {
29 31
@@ -82,7 +84,7 @@ QVariant ApplicationDomainType::getProperty(const QByteArray &key) const
82{ 84{
83 Q_ASSERT(mAdaptor); 85 Q_ASSERT(mAdaptor);
84 if (!mAdaptor->availableProperties().contains(key)) { 86 if (!mAdaptor->availableProperties().contains(key)) {
85 Warning() << "No such property available " << key; 87 SinkWarning() << "No such property available " << key;
86 } 88 }
87 return mAdaptor->getProperty(key); 89 return mAdaptor->getProperty(key);
88} 90}
@@ -105,7 +107,7 @@ QByteArray ApplicationDomainType::getBlobProperty(const QByteArray &key) const
105 const auto path = getProperty(key).toByteArray(); 107 const auto path = getProperty(key).toByteArray();
106 QFile file(path); 108 QFile file(path);
107 if (!file.open(QIODevice::ReadOnly)) { 109 if (!file.open(QIODevice::ReadOnly)) {
108 ErrorMsg() << "Failed to open the file: " << file.errorString() << path; 110 SinkError() << "Failed to open the file: " << file.errorString() << path;
109 return QByteArray(); 111 return QByteArray();
110 } 112 }
111 return file.readAll(); 113 return file.readAll();
@@ -116,7 +118,7 @@ void ApplicationDomainType::setBlobProperty(const QByteArray &key, const QByteAr
116 const auto path = Sink::temporaryFileLocation() + "/" + QUuid::createUuid().toString(); 118 const auto path = Sink::temporaryFileLocation() + "/" + QUuid::createUuid().toString();
117 QFile file(path); 119 QFile file(path);
118 if (!file.open(QIODevice::WriteOnly)) { 120 if (!file.open(QIODevice::WriteOnly)) {
119 ErrorMsg() << "Failed to open the file: " << file.errorString() << path; 121 SinkError() << "Failed to open the file: " << file.errorString() << path;
120 return; 122 return;
121 } 123 }
122 file.write(value); 124 file.write(value);
@@ -251,7 +253,7 @@ namespace DummyResource {
251 SinkResource create(const QByteArray &account) 253 SinkResource create(const QByteArray &account)
252 { 254 {
253 auto &&resource = ApplicationDomainType::createEntity<SinkResource>(); 255 auto &&resource = ApplicationDomainType::createEntity<SinkResource>();
254 resource.setProperty("type", "org.kde.dummy"); 256 resource.setProperty("type", "sink.dummy");
255 resource.setProperty("account", account); 257 resource.setProperty("account", account);
256 resource.setProperty("capabilities", QVariant::fromValue(QByteArrayList() << ResourceCapabilities::Mail::storage << "-folder.rename")); 258 resource.setProperty("capabilities", QVariant::fromValue(QByteArrayList() << ResourceCapabilities::Mail::storage << "-folder.rename"));
257 // resource.setProperty("capabilities", QVariant::fromValue(QByteArrayList() << ResourceCapabilities::Mail::storage << ResourceCapabilities::Mail::drafts << "-folder.rename" << ResourceCapabilities::Mail::trash)); 259 // resource.setProperty("capabilities", QVariant::fromValue(QByteArrayList() << ResourceCapabilities::Mail::storage << ResourceCapabilities::Mail::drafts << "-folder.rename" << ResourceCapabilities::Mail::trash));
@@ -263,7 +265,7 @@ namespace MaildirResource {
263 SinkResource create(const QByteArray &account) 265 SinkResource create(const QByteArray &account)
264 { 266 {
265 auto &&resource = ApplicationDomainType::createEntity<SinkResource>(); 267 auto &&resource = ApplicationDomainType::createEntity<SinkResource>();
266 resource.setProperty("type", "org.kde.maildir"); 268 resource.setProperty("type", "sink.maildir");
267 resource.setProperty("account", account); 269 resource.setProperty("account", account);
268 resource.setProperty("capabilities", QVariant::fromValue(QByteArrayList() << ResourceCapabilities::Mail::storage << ResourceCapabilities::Mail::drafts << "-folder.rename" << ResourceCapabilities::Mail::trash)); 270 resource.setProperty("capabilities", QVariant::fromValue(QByteArrayList() << ResourceCapabilities::Mail::storage << ResourceCapabilities::Mail::drafts << "-folder.rename" << ResourceCapabilities::Mail::trash));
269 return resource; 271 return resource;
@@ -274,7 +276,7 @@ namespace MailtransportResource {
274 SinkResource create(const QByteArray &account) 276 SinkResource create(const QByteArray &account)
275 { 277 {
276 auto &&resource = ApplicationDomainType::createEntity<SinkResource>(); 278 auto &&resource = ApplicationDomainType::createEntity<SinkResource>();
277 resource.setProperty("type", "org.kde.mailtransport"); 279 resource.setProperty("type", "sink.mailtransport");
278 resource.setProperty("account", account); 280 resource.setProperty("account", account);
279 resource.setProperty("capabilities", QVariant::fromValue(QByteArrayList() << ResourceCapabilities::Mail::transport)); 281 resource.setProperty("capabilities", QVariant::fromValue(QByteArrayList() << ResourceCapabilities::Mail::transport));
280 return resource; 282 return resource;
@@ -285,7 +287,7 @@ namespace ImapResource {
285 SinkResource create(const QByteArray &account) 287 SinkResource create(const QByteArray &account)
286 { 288 {
287 auto &&resource = ApplicationDomainType::createEntity<SinkResource>(); 289 auto &&resource = ApplicationDomainType::createEntity<SinkResource>();
288 resource.setProperty("type", "org.kde.imap"); 290 resource.setProperty("type", "sink.imap");
289 resource.setProperty("account", account); 291 resource.setProperty("account", account);
290 resource.setProperty("capabilities", QVariant::fromValue(QByteArrayList() << ResourceCapabilities::Mail::storage << ResourceCapabilities::Mail::drafts << ResourceCapabilities::Mail::folderhierarchy << ResourceCapabilities::Mail::trash)); 292 resource.setProperty("capabilities", QVariant::fromValue(QByteArrayList() << ResourceCapabilities::Mail::storage << ResourceCapabilities::Mail::drafts << ResourceCapabilities::Mail::folderhierarchy << ResourceCapabilities::Mail::trash));
291 return resource; 293 return resource;
diff --git a/common/domain/applicationdomaintype.h b/common/domain/applicationdomaintype.h
index 849c3e2..5efb936 100644
--- a/common/domain/applicationdomaintype.h
+++ b/common/domain/applicationdomaintype.h
@@ -52,6 +52,13 @@
52 void setExtracted##NAME(const TYPE &value) { setProperty(NAME::name, QVariant::fromValue(value)); } \ 52 void setExtracted##NAME(const TYPE &value) { setProperty(NAME::name, QVariant::fromValue(value)); } \
53 TYPE get##NAME() const { return getProperty(NAME::name).value<TYPE>(); } \ 53 TYPE get##NAME() const { return getProperty(NAME::name).value<TYPE>(); } \
54 54
55#define SINK_STATUS_PROPERTY(TYPE, NAME, LOWERCASENAME) \
56 struct NAME { \
57 static constexpr const char *name = #LOWERCASENAME; \
58 typedef TYPE Type; \
59 }; \
60 void setStatus##NAME(const TYPE &value) { setProperty(NAME::name, QVariant::fromValue(value)); } \
61 TYPE get##NAME() const { return getProperty(NAME::name).value<TYPE>(); } \
55 62
56#define SINK_BLOB_PROPERTY(NAME, LOWERCASENAME) \ 63#define SINK_BLOB_PROPERTY(NAME, LOWERCASENAME) \
57 struct NAME { \ 64 struct NAME { \
@@ -76,6 +83,14 @@
76namespace Sink { 83namespace Sink {
77namespace ApplicationDomain { 84namespace ApplicationDomain {
78 85
86struct SINK_EXPORT Error {
87
88};
89
90struct SINK_EXPORT Progress {
91
92};
93
79/** 94/**
80 * The domain type interface has two purposes: 95 * The domain type interface has two purposes:
81 * * provide a unified interface to read buffers (for zero-copy reading) 96 * * provide a unified interface to read buffers (for zero-copy reading)
@@ -215,6 +230,38 @@ struct SINK_EXPORT Mail : public Entity {
215}; 230};
216 231
217/** 232/**
233 * The status of an account or resource.
234 *
235 * It is set as follows:
236 * * By default the status is offline.
237 * * If a connection to the server could be established the status is Connected.
238 * * If an error occurred that keeps the resource from operating (so non transient), the resource enters the error state.
239 * * If a long running operation is started the resource goes to the busy state (and return to the previous state after that).
240 */
241enum SINK_EXPORT Status {
242 OfflineStatus,
243 ConnectedStatus,
244 BusyStatus,
245 ErrorStatus
246};
247
248struct SINK_EXPORT SinkAccount : public ApplicationDomainType {
249 typedef QSharedPointer<SinkAccount> Ptr;
250 explicit SinkAccount(const QByteArray &resourceInstanceIdentifier, const QByteArray &identifier, qint64 revision, const QSharedPointer<BufferAdaptor> &adaptor);
251 explicit SinkAccount(const QByteArray &identifier);
252 SinkAccount();
253 virtual ~SinkAccount();
254
255 SINK_PROPERTY(QString, Name, name);
256 SINK_PROPERTY(QString, Icon, icon);
257 SINK_PROPERTY(QString, AccountType, accountType);
258 SINK_STATUS_PROPERTY(int, Status, status);
259 SINK_STATUS_PROPERTY(ApplicationDomain::Error, Error, error);
260 SINK_STATUS_PROPERTY(ApplicationDomain::Progress, Progress, progress);
261};
262
263
264/**
218 * Represents an sink resource. 265 * Represents an sink resource.
219 * 266 *
220 * This type is used for configuration of resources, 267 * This type is used for configuration of resources,
@@ -226,14 +273,13 @@ struct SINK_EXPORT SinkResource : public ApplicationDomainType {
226 explicit SinkResource(const QByteArray &identifier); 273 explicit SinkResource(const QByteArray &identifier);
227 SinkResource(); 274 SinkResource();
228 virtual ~SinkResource(); 275 virtual ~SinkResource();
229};
230 276
231struct SINK_EXPORT SinkAccount : public ApplicationDomainType { 277 SINK_REFERENCE_PROPERTY(SinkAccount, Account, account);
232 typedef QSharedPointer<SinkAccount> Ptr; 278 SINK_PROPERTY(QString, ResourceType, resourceType);
233 explicit SinkAccount(const QByteArray &resourceInstanceIdentifier, const QByteArray &identifier, qint64 revision, const QSharedPointer<BufferAdaptor> &adaptor); 279 SINK_PROPERTY(QByteArrayList, Capabilities, capabilities);
234 explicit SinkAccount(const QByteArray &identifier); 280 SINK_STATUS_PROPERTY(int, Status, status);
235 SinkAccount(); 281 SINK_STATUS_PROPERTY(ApplicationDomain::Error, Error, error);
236 virtual ~SinkAccount(); 282 SINK_STATUS_PROPERTY(ApplicationDomain::Progress, Progress, progress);
237}; 283};
238 284
239struct SINK_EXPORT Identity : public ApplicationDomainType { 285struct SINK_EXPORT Identity : public ApplicationDomainType {
@@ -330,3 +376,5 @@ Q_DECLARE_METATYPE(Sink::ApplicationDomain::SinkAccount)
330Q_DECLARE_METATYPE(Sink::ApplicationDomain::SinkAccount::Ptr) 376Q_DECLARE_METATYPE(Sink::ApplicationDomain::SinkAccount::Ptr)
331Q_DECLARE_METATYPE(Sink::ApplicationDomain::Identity) 377Q_DECLARE_METATYPE(Sink::ApplicationDomain::Identity)
332Q_DECLARE_METATYPE(Sink::ApplicationDomain::Identity::Ptr) 378Q_DECLARE_METATYPE(Sink::ApplicationDomain::Identity::Ptr)
379Q_DECLARE_METATYPE(Sink::ApplicationDomain::Error)
380Q_DECLARE_METATYPE(Sink::ApplicationDomain::Progress)
diff --git a/common/domain/folder.cpp b/common/domain/folder.cpp
index 309ca3f..ddb0c10 100644
--- a/common/domain/folder.cpp
+++ b/common/domain/folder.cpp
@@ -35,6 +35,8 @@
35 35
36#include "folder_generated.h" 36#include "folder_generated.h"
37 37
38SINK_DEBUG_AREA("folder");
39
38static QMutex sMutex; 40static QMutex sMutex;
39 41
40using namespace Sink::ApplicationDomain; 42using namespace Sink::ApplicationDomain;
@@ -58,7 +60,7 @@ ResultSet TypeImplementation<Folder>::queryIndexes(const Sink::Query &query, con
58 60
59void TypeImplementation<Folder>::index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction) 61void TypeImplementation<Folder>::index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction)
60{ 62{
61 Trace() << "Indexing " << identifier; 63 SinkTrace() << "Indexing " << identifier;
62 getIndex().add(identifier, bufferAdaptor, transaction); 64 getIndex().add(identifier, bufferAdaptor, transaction);
63} 65}
64 66
diff --git a/common/domain/mail.cpp b/common/domain/mail.cpp
index 5b35a9a..13e1305 100644
--- a/common/domain/mail.cpp
+++ b/common/domain/mail.cpp
@@ -35,6 +35,8 @@
35 35
36#include "mail_generated.h" 36#include "mail_generated.h"
37 37
38SINK_DEBUG_AREA("mail");
39
38static QMutex sMutex; 40static QMutex sMutex;
39 41
40using namespace Sink::ApplicationDomain; 42using namespace Sink::ApplicationDomain;
@@ -63,7 +65,7 @@ ResultSet TypeImplementation<Mail>::queryIndexes(const Sink::Query &query, const
63 65
64void TypeImplementation<Mail>::index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction) 66void TypeImplementation<Mail>::index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction)
65{ 67{
66 Trace() << "Indexing " << identifier; 68 SinkTrace() << "Indexing " << identifier;
67 getIndex().add(identifier, bufferAdaptor, transaction); 69 getIndex().add(identifier, bufferAdaptor, transaction);
68} 70}
69 71
diff --git a/common/domainadaptor.h b/common/domainadaptor.h
index 8ac8171..25448f3 100644
--- a/common/domainadaptor.h
+++ b/common/domainadaptor.h
@@ -47,12 +47,12 @@ createBufferPart(const Sink::ApplicationDomain::ApplicationDomainType &domainObj
47 // First create a primitives such as strings using the mappings 47 // First create a primitives such as strings using the mappings
48 QList<std::function<void(Builder &)>> propertiesToAddToResource; 48 QList<std::function<void(Builder &)>> propertiesToAddToResource;
49 for (const auto &property : domainObject.changedProperties()) { 49 for (const auto &property : domainObject.changedProperties()) {
50 // Trace() << "copying property " << property; 50 // SinkTrace() << "copying property " << property;
51 const auto value = domainObject.getProperty(property); 51 const auto value = domainObject.getProperty(property);
52 if (mapper.hasMapping(property)) { 52 if (mapper.hasMapping(property)) {
53 mapper.setProperty(property, domainObject.getProperty(property), propertiesToAddToResource, fbb); 53 mapper.setProperty(property, domainObject.getProperty(property), propertiesToAddToResource, fbb);
54 } else { 54 } else {
55 // Trace() << "no mapping for property available " << property; 55 // SinkTrace() << "no mapping for property available " << property;
56 } 56 }
57 } 57 }
58 58
@@ -79,7 +79,7 @@ static void createBufferPartBuffer(const Sink::ApplicationDomain::ApplicationDom
79 fbb.Finish(pos, "AKFB"); 79 fbb.Finish(pos, "AKFB");
80 flatbuffers::Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize()); 80 flatbuffers::Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize());
81 if (!verifier.VerifyBuffer<Buffer>()) { 81 if (!verifier.VerifyBuffer<Buffer>()) {
82 Warning() << "Created invalid uffer"; 82 SinkWarning_(0, "bufferadaptor") << "Created invalid uffer";
83 } 83 }
84} 84}
85 85
@@ -89,6 +89,7 @@ static void createBufferPartBuffer(const Sink::ApplicationDomain::ApplicationDom
89template <class LocalBuffer, class ResourceBuffer> 89template <class LocalBuffer, class ResourceBuffer>
90class GenericBufferAdaptor : public Sink::ApplicationDomain::BufferAdaptor 90class GenericBufferAdaptor : public Sink::ApplicationDomain::BufferAdaptor
91{ 91{
92 SINK_DEBUG_AREA("bufferadaptor")
92public: 93public:
93 GenericBufferAdaptor() : BufferAdaptor() 94 GenericBufferAdaptor() : BufferAdaptor()
94 { 95 {
@@ -96,7 +97,7 @@ public:
96 97
97 virtual void setProperty(const QByteArray &key, const QVariant &value) Q_DECL_OVERRIDE 98 virtual void setProperty(const QByteArray &key, const QVariant &value) Q_DECL_OVERRIDE
98 { 99 {
99 Warning() << "Can't set property " << key; 100 SinkWarning() << "Can't set property " << key;
100 Q_ASSERT(false); 101 Q_ASSERT(false);
101 } 102 }
102 103
@@ -107,7 +108,7 @@ public:
107 } else if (mLocalBuffer && mLocalMapper->hasMapping(key)) { 108 } else if (mLocalBuffer && mLocalMapper->hasMapping(key)) {
108 return mLocalMapper->getProperty(key, mLocalBuffer); 109 return mLocalMapper->getProperty(key, mLocalBuffer);
109 } 110 }
110 Warning() << "No mapping available for key " << key << mLocalBuffer << mResourceBuffer; 111 SinkWarning() << "No mapping available for key " << key << mLocalBuffer << mResourceBuffer;
111 return QVariant(); 112 return QVariant();
112 } 113 }
113 114
@@ -168,13 +169,13 @@ public:
168 { 169 {
169 flatbuffers::FlatBufferBuilder localFbb; 170 flatbuffers::FlatBufferBuilder localFbb;
170 if (mLocalWriteMapper) { 171 if (mLocalWriteMapper) {
171 // Trace() << "Creating local buffer part"; 172 // SinkTrace() << "Creating local buffer part";
172 createBufferPartBuffer<LocalBuffer, LocalBuilder>(domainObject, localFbb, *mLocalWriteMapper); 173 createBufferPartBuffer<LocalBuffer, LocalBuilder>(domainObject, localFbb, *mLocalWriteMapper);
173 } 174 }
174 175
175 flatbuffers::FlatBufferBuilder resFbb; 176 flatbuffers::FlatBufferBuilder resFbb;
176 if (mResourceWriteMapper) { 177 if (mResourceWriteMapper) {
177 // Trace() << "Creating resouce buffer part"; 178 // SinkTrace() << "Creating resouce buffer part";
178 createBufferPartBuffer<ResourceBuffer, ResourceBuilder>(domainObject, resFbb, *mResourceWriteMapper); 179 createBufferPartBuffer<ResourceBuffer, ResourceBuilder>(domainObject, resFbb, *mResourceWriteMapper);
179 } 180 }
180 181
diff --git a/common/entityreader.cpp b/common/entityreader.cpp
index c15f73f..411e7e4 100644
--- a/common/entityreader.cpp
+++ b/common/entityreader.cpp
@@ -23,6 +23,8 @@
23#include "storage.h" 23#include "storage.h"
24#include "query.h" 24#include "query.h"
25 25
26SINK_DEBUG_AREA("entityreader")
27
26using namespace Sink; 28using namespace Sink;
27 29
28QSharedPointer<Sink::ApplicationDomain::BufferAdaptor> EntityReaderUtils::getLatest(const Sink::Storage::NamedDatabase &db, const QByteArray &uid, DomainTypeAdaptorFactoryInterface &adaptorFactory, qint64 &retrievedRevision) 30QSharedPointer<Sink::ApplicationDomain::BufferAdaptor> EntityReaderUtils::getLatest(const Sink::Storage::NamedDatabase &db, const QByteArray &uid, DomainTypeAdaptorFactoryInterface &adaptorFactory, qint64 &retrievedRevision)
@@ -32,15 +34,15 @@ QSharedPointer<Sink::ApplicationDomain::BufferAdaptor> EntityReaderUtils::getLat
32 [&current, &adaptorFactory, &retrievedRevision](const QByteArray &key, const QByteArray &data) -> bool { 34 [&current, &adaptorFactory, &retrievedRevision](const QByteArray &key, const QByteArray &data) -> bool {
33 Sink::EntityBuffer buffer(const_cast<const char *>(data.data()), data.size()); 35 Sink::EntityBuffer buffer(const_cast<const char *>(data.data()), data.size());
34 if (!buffer.isValid()) { 36 if (!buffer.isValid()) {
35 Warning() << "Read invalid buffer from disk"; 37 SinkWarning() << "Read invalid buffer from disk";
36 } else { 38 } else {
37 Trace() << "Found value " << key; 39 SinkTrace() << "Found value " << key;
38 current = adaptorFactory.createAdaptor(buffer.entity()); 40 current = adaptorFactory.createAdaptor(buffer.entity());
39 retrievedRevision = Sink::Storage::revisionFromKey(key); 41 retrievedRevision = Sink::Storage::revisionFromKey(key);
40 } 42 }
41 return false; 43 return false;
42 }, 44 },
43 [](const Sink::Storage::Error &error) { Warning() << "Failed to read current value from storage: " << error.message; }); 45 [](const Sink::Storage::Error &error) { SinkWarning() << "Failed to read current value from storage: " << error.message; });
44 return current; 46 return current;
45} 47}
46 48
@@ -51,14 +53,14 @@ QSharedPointer<Sink::ApplicationDomain::BufferAdaptor> EntityReaderUtils::get(co
51 [&current, &adaptorFactory, &retrievedRevision](const QByteArray &key, const QByteArray &data) -> bool { 53 [&current, &adaptorFactory, &retrievedRevision](const QByteArray &key, const QByteArray &data) -> bool {
52 Sink::EntityBuffer buffer(const_cast<const char *>(data.data()), data.size()); 54 Sink::EntityBuffer buffer(const_cast<const char *>(data.data()), data.size());
53 if (!buffer.isValid()) { 55 if (!buffer.isValid()) {
54 Warning() << "Read invalid buffer from disk"; 56 SinkWarning() << "Read invalid buffer from disk";
55 } else { 57 } else {
56 current = adaptorFactory.createAdaptor(buffer.entity()); 58 current = adaptorFactory.createAdaptor(buffer.entity());
57 retrievedRevision = Sink::Storage::revisionFromKey(key); 59 retrievedRevision = Sink::Storage::revisionFromKey(key);
58 } 60 }
59 return false; 61 return false;
60 }, 62 },
61 [](const Sink::Storage::Error &error) { Warning() << "Failed to read current value from storage: " << error.message; }); 63 [](const Sink::Storage::Error &error) { SinkWarning() << "Failed to read current value from storage: " << error.message; });
62 return current; 64 return current;
63} 65}
64 66
@@ -74,7 +76,7 @@ QSharedPointer<Sink::ApplicationDomain::BufferAdaptor> EntityReaderUtils::getPre
74 } 76 }
75 return true; 77 return true;
76 }, 78 },
77 [](const Sink::Storage::Error &error) { Warning() << "Failed to read current value from storage: " << error.message; }, true); 79 [](const Sink::Storage::Error &error) { SinkWarning() << "Failed to read current value from storage: " << error.message; }, true);
78 return get(db, Sink::Storage::assembleKey(uid, latestRevision), adaptorFactory, retrievedRevision); 80 return get(db, Sink::Storage::assembleKey(uid, latestRevision), adaptorFactory, retrievedRevision);
79} 81}
80 82
@@ -86,7 +88,7 @@ EntityReader<DomainType>::EntityReader(const QByteArray &resourceType, const QBy
86 mDomainTypeAdaptorFactory(*mDomainTypeAdaptorFactoryPtr) 88 mDomainTypeAdaptorFactory(*mDomainTypeAdaptorFactoryPtr)
87{ 89{
88 Q_ASSERT(!resourceType.isEmpty()); 90 Q_ASSERT(!resourceType.isEmpty());
89 Trace() << "resourceType " << resourceType; 91 SinkTrace() << "resourceType " << resourceType;
90 Q_ASSERT(mDomainTypeAdaptorFactoryPtr); 92 Q_ASSERT(mDomainTypeAdaptorFactoryPtr);
91} 93}
92 94
@@ -165,13 +167,13 @@ void EntityReader<DomainType>::readEntity(const Sink::Storage::NamedDatabase &db
165 resultCallback(DomainType::Ptr::create(mResourceInstanceIdentifier, Sink::Storage::uidFromKey(key), revision, adaptor), operation); 167 resultCallback(DomainType::Ptr::create(mResourceInstanceIdentifier, Sink::Storage::uidFromKey(key), revision, adaptor), operation);
166 return false; 168 return false;
167 }, 169 },
168 [&](const Sink::Storage::Error &error) { Warning() << "Error during query: " << error.message << key; }); 170 [&](const Sink::Storage::Error &error) { SinkWarning() << "Error during query: " << error.message << key; });
169} 171}
170 172
171static inline ResultSet fullScan(const Sink::Storage::Transaction &transaction, const QByteArray &bufferType) 173static inline ResultSet fullScan(const Sink::Storage::Transaction &transaction, const QByteArray &bufferType)
172{ 174{
173 // TODO use a result set with an iterator, to read values on demand 175 // TODO use a result set with an iterator, to read values on demand
174 Trace() << "Looking for : " << bufferType; 176 SinkTrace() << "Looking for : " << bufferType;
175 //The scan can return duplicate results if we have multiple revisions, so we use a set to deduplicate. 177 //The scan can return duplicate results if we have multiple revisions, so we use a set to deduplicate.
176 QSet<QByteArray> keys; 178 QSet<QByteArray> keys;
177 Storage::mainDatabase(transaction, bufferType) 179 Storage::mainDatabase(transaction, bufferType)
@@ -179,14 +181,14 @@ static inline ResultSet fullScan(const Sink::Storage::Transaction &transaction,
179 [&](const QByteArray &key, const QByteArray &value) -> bool { 181 [&](const QByteArray &key, const QByteArray &value) -> bool {
180 if (keys.contains(Sink::Storage::uidFromKey(key))) { 182 if (keys.contains(Sink::Storage::uidFromKey(key))) {
181 //Not something that should persist if the replay works, so we keep a message for now. 183 //Not something that should persist if the replay works, so we keep a message for now.
182 Trace() << "Multiple revisions for key: " << key; 184 SinkTrace() << "Multiple revisions for key: " << key;
183 } 185 }
184 keys << Sink::Storage::uidFromKey(key); 186 keys << Sink::Storage::uidFromKey(key);
185 return true; 187 return true;
186 }, 188 },
187 [](const Sink::Storage::Error &error) { Warning() << "Error during query: " << error.message; }); 189 [](const Sink::Storage::Error &error) { SinkWarning() << "Error during query: " << error.message; });
188 190
189 Trace() << "Full scan retrieved " << keys.size() << " results."; 191 SinkTrace() << "Full scan retrieved " << keys.size() << " results.";
190 return ResultSet(keys.toList().toVector()); 192 return ResultSet(keys.toList().toVector());
191} 193}
192 194
@@ -224,7 +226,7 @@ ResultSet EntityReader<DomainType>::loadIncrementalResultSet(qint64 baseRevision
224 while (*revisionCounter <= topRevision) { 226 while (*revisionCounter <= topRevision) {
225 const auto uid = Sink::Storage::getUidFromRevision(mTransaction, *revisionCounter); 227 const auto uid = Sink::Storage::getUidFromRevision(mTransaction, *revisionCounter);
226 const auto type = Sink::Storage::getTypeFromRevision(mTransaction, *revisionCounter); 228 const auto type = Sink::Storage::getTypeFromRevision(mTransaction, *revisionCounter);
227 // Trace() << "Revision" << *revisionCounter << type << uid; 229 // SinkTrace() << "Revision" << *revisionCounter << type << uid;
228 Q_ASSERT(!uid.isEmpty()); 230 Q_ASSERT(!uid.isEmpty());
229 Q_ASSERT(!type.isEmpty()); 231 Q_ASSERT(!type.isEmpty());
230 if (type != bufferType) { 232 if (type != bufferType) {
@@ -236,7 +238,7 @@ ResultSet EntityReader<DomainType>::loadIncrementalResultSet(qint64 baseRevision
236 *revisionCounter += 1; 238 *revisionCounter += 1;
237 return key; 239 return key;
238 } 240 }
239 Trace() << "Finished reading incremental result set:" << *revisionCounter; 241 SinkTrace() << "Finished reading incremental result set:" << *revisionCounter;
240 // We're done 242 // We're done
241 return QByteArray(); 243 return QByteArray();
242 }); 244 });
@@ -248,7 +250,7 @@ ResultSet EntityReader<DomainType>::filterAndSortSet(ResultSet &resultSet, const
248{ 250{
249 const bool sortingRequired = !sortProperty.isEmpty(); 251 const bool sortingRequired = !sortProperty.isEmpty();
250 if (initialQuery && sortingRequired) { 252 if (initialQuery && sortingRequired) {
251 Trace() << "Sorting the resultset in memory according to property: " << sortProperty; 253 SinkTrace() << "Sorting the resultset in memory according to property: " << sortProperty;
252 // Sort the complete set by reading the sort property and filling into a sorted map 254 // Sort the complete set by reading the sort property and filling into a sorted map
253 auto sortedMap = QSharedPointer<QMap<QByteArray, QByteArray>>::create(); 255 auto sortedMap = QSharedPointer<QMap<QByteArray, QByteArray>>::create();
254 while (resultSet.next()) { 256 while (resultSet.next()) {
@@ -271,7 +273,7 @@ ResultSet EntityReader<DomainType>::filterAndSortSet(ResultSet &resultSet, const
271 }); 273 });
272 } 274 }
273 275
274 Trace() << "Sorted " << sortedMap->size() << " values."; 276 SinkTrace() << "Sorted " << sortedMap->size() << " values.";
275 auto iterator = QSharedPointer<QMapIterator<QByteArray, QByteArray>>::create(*sortedMap); 277 auto iterator = QSharedPointer<QMapIterator<QByteArray, QByteArray>>::create(*sortedMap);
276 ResultSet::ValueGenerator generator = [this, iterator, sortedMap, &db, filter, initialQuery]( 278 ResultSet::ValueGenerator generator = [this, iterator, sortedMap, &db, filter, initialQuery](
277 std::function<void(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &, Sink::Operation)> callback) -> bool { 279 std::function<void(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &, Sink::Operation)> callback) -> bool {
@@ -330,11 +332,11 @@ QPair<qint64, qint64> EntityReader<DomainType>::load(const Sink::Query &query, c
330 QSet<QByteArray> remainingFilters; 332 QSet<QByteArray> remainingFilters;
331 QByteArray remainingSorting; 333 QByteArray remainingSorting;
332 auto resultSet = baseSetRetriever(remainingFilters, remainingSorting); 334 auto resultSet = baseSetRetriever(remainingFilters, remainingSorting);
333 Trace() << "Base set retrieved. " << Log::TraceTime(time.elapsed()); 335 SinkTrace() << "Base set retrieved. " << Log::TraceTime(time.elapsed());
334 auto filteredSet = filterAndSortSet(resultSet, getFilter(remainingFilters, query), db, initialQuery, remainingSorting); 336 auto filteredSet = filterAndSortSet(resultSet, getFilter(remainingFilters, query), db, initialQuery, remainingSorting);
335 Trace() << "Filtered set retrieved. " << Log::TraceTime(time.elapsed()); 337 SinkTrace() << "Filtered set retrieved. " << Log::TraceTime(time.elapsed());
336 auto replayedEntities = replaySet(filteredSet, offset, batchSize, callback); 338 auto replayedEntities = replaySet(filteredSet, offset, batchSize, callback);
337 // Trace() << "Filtered set replayed. " << Log::TraceTime(time.elapsed()); 339 // SinkTrace() << "Filtered set replayed. " << Log::TraceTime(time.elapsed());
338 return qMakePair(Sink::Storage::maxRevision(mTransaction), replayedEntities); 340 return qMakePair(Sink::Storage::maxRevision(mTransaction), replayedEntities);
339} 341}
340 342
@@ -346,7 +348,7 @@ QPair<qint64, qint64> EntityReader<DomainType>::executeInitialQuery(const Sink::
346 auto revisionAndReplayedEntities = load(query, [&](QSet<QByteArray> &remainingFilters, QByteArray &remainingSorting) -> ResultSet { 348 auto revisionAndReplayedEntities = load(query, [&](QSet<QByteArray> &remainingFilters, QByteArray &remainingSorting) -> ResultSet {
347 return loadInitialResultSet(query, remainingFilters, remainingSorting); 349 return loadInitialResultSet(query, remainingFilters, remainingSorting);
348 }, true, offset, batchsize, callback); 350 }, true, offset, batchsize, callback);
349 Trace() << "Initial query took: " << Log::TraceTime(time.elapsed()); 351 SinkTrace() << "Initial query took: " << Log::TraceTime(time.elapsed());
350 return revisionAndReplayedEntities; 352 return revisionAndReplayedEntities;
351} 353}
352 354
@@ -359,7 +361,7 @@ QPair<qint64, qint64> EntityReader<DomainType>::executeIncrementalQuery(const Si
359 auto revisionAndReplayedEntities = load(query, [&](QSet<QByteArray> &remainingFilters, QByteArray &remainingSorting) -> ResultSet { 361 auto revisionAndReplayedEntities = load(query, [&](QSet<QByteArray> &remainingFilters, QByteArray &remainingSorting) -> ResultSet {
360 return loadIncrementalResultSet(baseRevision, query, remainingFilters); 362 return loadIncrementalResultSet(baseRevision, query, remainingFilters);
361 }, false, 0, 0, callback); 363 }, false, 0, 0, callback);
362 Trace() << "Initial query took: " << Log::TraceTime(time.elapsed()); 364 SinkTrace() << "Initial query took: " << Log::TraceTime(time.elapsed());
363 return revisionAndReplayedEntities; 365 return revisionAndReplayedEntities;
364} 366}
365 367
@@ -377,7 +379,7 @@ EntityReader<DomainType>::getFilter(const QSet<QByteArray> remainingFilters, con
377 const auto property = domainObject->getProperty(filterProperty); 379 const auto property = domainObject->getProperty(filterProperty);
378 const auto comparator = query.propertyFilter.value(filterProperty); 380 const auto comparator = query.propertyFilter.value(filterProperty);
379 if (!comparator.matches(property)) { 381 if (!comparator.matches(property)) {
380 Trace() << "Filtering entity due to property mismatch on filter: " << filterProperty << property << ":" << comparator.value; 382 SinkTrace() << "Filtering entity due to property mismatch on filter: " << filterProperty << property << ":" << comparator.value;
381 return false; 383 return false;
382 } 384 }
383 } 385 }
@@ -388,7 +390,7 @@ EntityReader<DomainType>::getFilter(const QSet<QByteArray> remainingFilters, con
388template <class DomainType> 390template <class DomainType>
389qint64 EntityReader<DomainType>::replaySet(ResultSet &resultSet, int offset, int batchSize, const std::function<bool(const typename DomainType::Ptr &value, Sink::Operation operation)> &callback) 391qint64 EntityReader<DomainType>::replaySet(ResultSet &resultSet, int offset, int batchSize, const std::function<bool(const typename DomainType::Ptr &value, Sink::Operation operation)> &callback)
390{ 392{
391 Trace() << "Skipping over " << offset << " results"; 393 SinkTrace() << "Skipping over " << offset << " results";
392 resultSet.skip(offset); 394 resultSet.skip(offset);
393 int counter = 0; 395 int counter = 0;
394 while (!batchSize || (counter < batchSize)) { 396 while (!batchSize || (counter < batchSize)) {
@@ -401,7 +403,7 @@ qint64 EntityReader<DomainType>::replaySet(ResultSet &resultSet, int offset, int
401 break; 403 break;
402 } 404 }
403 }; 405 };
404 Trace() << "Replayed " << counter << " results." 406 SinkTrace() << "Replayed " << counter << " results."
405 << "Limit " << batchSize; 407 << "Limit " << batchSize;
406 return counter; 408 return counter;
407} 409}
diff --git a/common/facade.cpp b/common/facade.cpp
index 2660300..72f7414 100644
--- a/common/facade.cpp
+++ b/common/facade.cpp
@@ -30,9 +30,6 @@
30 30
31using namespace Sink; 31using namespace Sink;
32 32
33#undef DEBUG_AREA
34#define DEBUG_AREA "client.facade"
35
36template <class DomainType> 33template <class DomainType>
37GenericFacade<DomainType>::GenericFacade( 34GenericFacade<DomainType>::GenericFacade(
38 const QByteArray &resourceIdentifier, const DomainTypeAdaptorFactoryInterface::Ptr &adaptorFactory, const QSharedPointer<Sink::ResourceAccessInterface> resourceAccess) 35 const QByteArray &resourceIdentifier, const DomainTypeAdaptorFactoryInterface::Ptr &adaptorFactory, const QSharedPointer<Sink::ResourceAccessInterface> resourceAccess)
@@ -59,7 +56,7 @@ template <class DomainType>
59KAsync::Job<void> GenericFacade<DomainType>::create(const DomainType &domainObject) 56KAsync::Job<void> GenericFacade<DomainType>::create(const DomainType &domainObject)
60{ 57{
61 if (!mDomainTypeAdaptorFactory) { 58 if (!mDomainTypeAdaptorFactory) {
62 Warning() << "No domain type adaptor factory available"; 59 SinkWarning() << "No domain type adaptor factory available";
63 return KAsync::error<void>(); 60 return KAsync::error<void>();
64 } 61 }
65 flatbuffers::FlatBufferBuilder entityFbb; 62 flatbuffers::FlatBufferBuilder entityFbb;
@@ -71,10 +68,10 @@ template <class DomainType>
71KAsync::Job<void> GenericFacade<DomainType>::modify(const DomainType &domainObject) 68KAsync::Job<void> GenericFacade<DomainType>::modify(const DomainType &domainObject)
72{ 69{
73 if (!mDomainTypeAdaptorFactory) { 70 if (!mDomainTypeAdaptorFactory) {
74 Warning() << "No domain type adaptor factory available"; 71 SinkWarning() << "No domain type adaptor factory available";
75 return KAsync::error<void>(); 72 return KAsync::error<void>();
76 } 73 }
77 Trace() << "Modifying entity: " << domainObject.identifier() << domainObject.changedProperties(); 74 SinkTrace() << "Modifying entity: " << domainObject.identifier() << domainObject.changedProperties();
78 flatbuffers::FlatBufferBuilder entityFbb; 75 flatbuffers::FlatBufferBuilder entityFbb;
79 mDomainTypeAdaptorFactory->createBuffer(domainObject, entityFbb); 76 mDomainTypeAdaptorFactory->createBuffer(domainObject, entityFbb);
80 return mResourceAccess->sendModifyCommand(domainObject.identifier(), domainObject.revision(), bufferTypeForDomainType(), QByteArrayList(), BufferUtils::extractBuffer(entityFbb), domainObject.changedProperties()); 77 return mResourceAccess->sendModifyCommand(domainObject.identifier(), domainObject.revision(), bufferTypeForDomainType(), QByteArrayList(), BufferUtils::extractBuffer(entityFbb), domainObject.changedProperties());
diff --git a/common/facade.h b/common/facade.h
index 658ccb8..b193580 100644
--- a/common/facade.h
+++ b/common/facade.h
@@ -46,6 +46,9 @@ namespace Sink {
46template <typename DomainType> 46template <typename DomainType>
47class SINK_EXPORT GenericFacade : public Sink::StoreFacade<DomainType> 47class SINK_EXPORT GenericFacade : public Sink::StoreFacade<DomainType>
48{ 48{
49protected:
50 SINK_DEBUG_AREA("facade")
51 SINK_DEBUG_COMPONENT(mResourceInstanceIdentifier)
49public: 52public:
50 /** 53 /**
51 * Create a new GenericFacade 54 * Create a new GenericFacade
diff --git a/common/genericresource.cpp b/common/genericresource.cpp
index c06c22a..7136882 100644
--- a/common/genericresource.cpp
+++ b/common/genericresource.cpp
@@ -46,9 +46,6 @@ static int sCommitInterval = 10;
46 46
47using namespace Sink; 47using namespace Sink;
48 48
49#undef DEBUG_AREA
50#define DEBUG_AREA "resource.commandprocessor"
51
52/** 49/**
53 * Drives the pipeline using the output from all command queues 50 * Drives the pipeline using the output from all command queues
54 */ 51 */
@@ -56,12 +53,13 @@ class CommandProcessor : public QObject
56{ 53{
57 Q_OBJECT 54 Q_OBJECT
58 typedef std::function<KAsync::Job<void>(void const *, size_t)> InspectionFunction; 55 typedef std::function<KAsync::Job<void>(void const *, size_t)> InspectionFunction;
56 SINK_DEBUG_AREA("commandprocessor")
59 57
60public: 58public:
61 CommandProcessor(Sink::Pipeline *pipeline, QList<MessageQueue *> commandQueues) : QObject(), mPipeline(pipeline), mCommandQueues(commandQueues), mProcessingLock(false) 59 CommandProcessor(Sink::Pipeline *pipeline, QList<MessageQueue *> commandQueues) : QObject(), mPipeline(pipeline), mCommandQueues(commandQueues), mProcessingLock(false)
62 { 60 {
63 mLowerBoundRevision = Storage::maxRevision(mPipeline->storage().createTransaction(Storage::ReadOnly, [](const Sink::Storage::Error &error) { 61 mLowerBoundRevision = Storage::maxRevision(mPipeline->storage().createTransaction(Storage::ReadOnly, [](const Sink::Storage::Error &error) {
64 Warning() << error.message; 62 SinkWarning() << error.message;
65 })); 63 }));
66 64
67 for (auto queue : mCommandQueues) { 65 for (auto queue : mCommandQueues) {
@@ -80,7 +78,6 @@ public:
80 mInspect = f; 78 mInspect = f;
81 } 79 }
82 80
83
84signals: 81signals:
85 void error(int errorCode, const QString &errorMessage); 82 void error(int errorCode, const QString &errorMessage);
86 83
@@ -114,7 +111,7 @@ private slots:
114 111
115 KAsync::Job<qint64> processQueuedCommand(const Sink::QueuedCommand *queuedCommand) 112 KAsync::Job<qint64> processQueuedCommand(const Sink::QueuedCommand *queuedCommand)
116 { 113 {
117 Trace() << "Processing command: " << Sink::Commands::name(queuedCommand->commandId()); 114 SinkTrace() << "Processing command: " << Sink::Commands::name(queuedCommand->commandId());
118 // Throw command into appropriate pipeline 115 // Throw command into appropriate pipeline
119 switch (queuedCommand->commandId()) { 116 switch (queuedCommand->commandId()) {
120 case Sink::Commands::DeleteEntityCommand: 117 case Sink::Commands::DeleteEntityCommand:
@@ -138,21 +135,21 @@ private slots:
138 { 135 {
139 flatbuffers::Verifier verifyer(reinterpret_cast<const uint8_t *>(data.constData()), data.size()); 136 flatbuffers::Verifier verifyer(reinterpret_cast<const uint8_t *>(data.constData()), data.size());
140 if (!Sink::VerifyQueuedCommandBuffer(verifyer)) { 137 if (!Sink::VerifyQueuedCommandBuffer(verifyer)) {
141 Warning() << "invalid buffer"; 138 SinkWarning() << "invalid buffer";
142 // return KAsync::error<void, qint64>(1, "Invalid Buffer"); 139 // return KAsync::error<void, qint64>(1, "Invalid Buffer");
143 } 140 }
144 auto queuedCommand = Sink::GetQueuedCommand(data.constData()); 141 auto queuedCommand = Sink::GetQueuedCommand(data.constData());
145 const auto commandId = queuedCommand->commandId(); 142 const auto commandId = queuedCommand->commandId();
146 Trace() << "Dequeued Command: " << Sink::Commands::name(commandId); 143 SinkTrace() << "Dequeued Command: " << Sink::Commands::name(commandId);
147 return processQueuedCommand(queuedCommand) 144 return processQueuedCommand(queuedCommand)
148 .then<qint64, qint64>( 145 .then<qint64, qint64>(
149 [commandId](qint64 createdRevision) -> qint64 { 146 [this, commandId](qint64 createdRevision) -> qint64 {
150 Trace() << "Command pipeline processed: " << Sink::Commands::name(commandId); 147 SinkTrace() << "Command pipeline processed: " << Sink::Commands::name(commandId);
151 return createdRevision; 148 return createdRevision;
152 }, 149 },
153 [](int errorCode, QString errorMessage) { 150 [](int errorCode, QString errorMessage) {
154 // FIXME propagate error, we didn't handle it 151 // FIXME propagate error, we didn't handle it
155 Warning() << "Error while processing queue command: " << errorMessage; 152 SinkWarning() << "Error while processing queue command: " << errorMessage;
156 }); 153 });
157 } 154 }
158 155
@@ -169,7 +166,7 @@ private slots:
169 return KAsync::start<void>([this, data, time](KAsync::Future<void> &future) { 166 return KAsync::start<void>([this, data, time](KAsync::Future<void> &future) {
170 processQueuedCommand(data) 167 processQueuedCommand(data)
171 .then<void, qint64>([&future, this, time](qint64 createdRevision) { 168 .then<void, qint64>([&future, this, time](qint64 createdRevision) {
172 Trace() << "Created revision " << createdRevision << ". Processing took: " << Log::TraceTime(time->elapsed()); 169 SinkTrace() << "Created revision " << createdRevision << ". Processing took: " << Log::TraceTime(time->elapsed());
173 future.setFinished(); 170 future.setFinished();
174 }) 171 })
175 .exec(); 172 .exec();
@@ -178,7 +175,7 @@ private slots:
178 .then<void>([&future, queue]() { future.setFinished(); }, 175 .then<void>([&future, queue]() { future.setFinished(); },
179 [&future](int i, QString error) { 176 [&future](int i, QString error) {
180 if (i != MessageQueue::ErrorCodes::NoMessageFound) { 177 if (i != MessageQueue::ErrorCodes::NoMessageFound) {
181 Warning() << "Error while getting message from messagequeue: " << error; 178 SinkWarning() << "Error while getting message from messagequeue: " << error;
182 } 179 }
183 future.setFinished(); 180 future.setFinished();
184 }) 181 })
@@ -192,12 +189,12 @@ private slots:
192 auto time = QSharedPointer<QTime>::create(); 189 auto time = QSharedPointer<QTime>::create();
193 time->start(); 190 time->start();
194 mPipeline->startTransaction(); 191 mPipeline->startTransaction();
195 Trace() << "Cleaning up from " << mPipeline->cleanedUpRevision() + 1 << " to " << mLowerBoundRevision; 192 SinkTrace() << "Cleaning up from " << mPipeline->cleanedUpRevision() + 1 << " to " << mLowerBoundRevision;
196 for (qint64 revision = mPipeline->cleanedUpRevision() + 1; revision <= mLowerBoundRevision; revision++) { 193 for (qint64 revision = mPipeline->cleanedUpRevision() + 1; revision <= mLowerBoundRevision; revision++) {
197 mPipeline->cleanupRevision(revision); 194 mPipeline->cleanupRevision(revision);
198 } 195 }
199 mPipeline->commit(); 196 mPipeline->commit();
200 Trace() << "Cleanup done." << Log::TraceTime(time->elapsed()); 197 SinkTrace() << "Cleanup done." << Log::TraceTime(time->elapsed());
201 198
202 // Go through all message queues 199 // Go through all message queues
203 auto it = QSharedPointer<QListIterator<MessageQueue *>>::create(mCommandQueues); 200 auto it = QSharedPointer<QListIterator<MessageQueue *>>::create(mCommandQueues);
@@ -208,8 +205,8 @@ private slots:
208 205
209 auto queue = it->next(); 206 auto queue = it->next();
210 processQueue(queue) 207 processQueue(queue)
211 .then<void>([&future, time]() { 208 .then<void>([this, &future, time]() {
212 Trace() << "Queue processed." << Log::TraceTime(time->elapsed()); 209 SinkTrace() << "Queue processed." << Log::TraceTime(time->elapsed());
213 future.setFinished(); 210 future.setFinished();
214 }) 211 })
215 .exec(); 212 .exec();
@@ -226,9 +223,6 @@ private:
226 InspectionFunction mInspect; 223 InspectionFunction mInspect;
227}; 224};
228 225
229#undef DEBUG_AREA
230#define DEBUG_AREA "resource"
231
232GenericResource::GenericResource(const QByteArray &resourceType, const QByteArray &resourceInstanceIdentifier, const QSharedPointer<Pipeline> &pipeline ) 226GenericResource::GenericResource(const QByteArray &resourceType, const QByteArray &resourceInstanceIdentifier, const QSharedPointer<Pipeline> &pipeline )
233 : Sink::Resource(), 227 : Sink::Resource(),
234 mUserQueue(Sink::storageLocation(), resourceInstanceIdentifier + ".userqueue"), 228 mUserQueue(Sink::storageLocation(), resourceInstanceIdentifier + ".userqueue"),
@@ -240,7 +234,7 @@ GenericResource::GenericResource(const QByteArray &resourceType, const QByteArra
240 mClientLowerBoundRevision(std::numeric_limits<qint64>::max()) 234 mClientLowerBoundRevision(std::numeric_limits<qint64>::max())
241{ 235{
242 mPipeline->setResourceType(mResourceType); 236 mPipeline->setResourceType(mResourceType);
243 mProcessor = new CommandProcessor(mPipeline.data(), QList<MessageQueue *>() << &mUserQueue << &mSynchronizerQueue); 237 mProcessor = std::unique_ptr<CommandProcessor>(new CommandProcessor(mPipeline.data(), QList<MessageQueue *>() << &mUserQueue << &mSynchronizerQueue));
244 mProcessor->setInspectionCommand([this](void const *command, size_t size) { 238 mProcessor->setInspectionCommand([this](void const *command, size_t size) {
245 flatbuffers::Verifier verifier((const uint8_t *)command, size); 239 flatbuffers::Verifier verifier((const uint8_t *)command, size);
246 if (Sink::Commands::VerifyInspectionBuffer(verifier)) { 240 if (Sink::Commands::VerifyInspectionBuffer(verifier)) {
@@ -260,18 +254,18 @@ GenericResource::GenericResource(const QByteArray &resourceType, const QByteArra
260 [=]() { 254 [=]() {
261 Log_area("resource.inspection") << "Inspection was successful: " << inspectionType << inspectionId << entityId; 255 Log_area("resource.inspection") << "Inspection was successful: " << inspectionType << inspectionId << entityId;
262 Sink::Notification n; 256 Sink::Notification n;
263 n.type = Sink::Commands::NotificationType_Inspection; 257 n.type = Sink::Notification::Inspection;
264 n.id = inspectionId; 258 n.id = inspectionId;
265 n.code = Sink::Commands::NotificationCode_Success; 259 n.code = Sink::Notification::Success;
266 emit notify(n); 260 emit notify(n);
267 }, 261 },
268 [=](int code, const QString &message) { 262 [=](int code, const QString &message) {
269 Warning_area("resource.inspection") << "Inspection failed: " << inspectionType << inspectionId << entityId << message; 263 Warning_area("resource.inspection") << "Inspection failed: " << inspectionType << inspectionId << entityId << message;
270 Sink::Notification n; 264 Sink::Notification n;
271 n.type = Sink::Commands::NotificationType_Inspection; 265 n.type = Sink::Notification::Inspection;
272 n.message = message; 266 n.message = message;
273 n.id = inspectionId; 267 n.id = inspectionId;
274 n.code = Sink::Commands::NotificationCode_Failure; 268 n.code = Sink::Notification::Failure;
275 emit notify(n); 269 emit notify(n);
276 }) 270 })
277 .exec(); 271 .exec();
@@ -279,8 +273,14 @@ GenericResource::GenericResource(const QByteArray &resourceType, const QByteArra
279 } 273 }
280 return KAsync::error<void>(-1, "Invalid inspection command."); 274 return KAsync::error<void>(-1, "Invalid inspection command.");
281 }); 275 });
282 QObject::connect(mProcessor, &CommandProcessor::error, [this](int errorCode, const QString &msg) { onProcessorError(errorCode, msg); }); 276 {
283 QObject::connect(mPipeline.data(), &Pipeline::revisionUpdated, this, &Resource::revisionUpdated); 277 auto ret =QObject::connect(mProcessor.get(), &CommandProcessor::error, [this](int errorCode, const QString &msg) { onProcessorError(errorCode, msg); });
278 Q_ASSERT(ret);
279 }
280 {
281 auto ret = QObject::connect(mPipeline.data(), &Pipeline::revisionUpdated, this, &Resource::revisionUpdated);
282 Q_ASSERT(ret);
283 }
284 mClientLowerBoundRevision = mPipeline->cleanedUpRevision(); 284 mClientLowerBoundRevision = mPipeline->cleanedUpRevision();
285 285
286 mCommitQueueTimer.setInterval(sCommitInterval); 286 mCommitQueueTimer.setInterval(sCommitInterval);
@@ -290,13 +290,12 @@ GenericResource::GenericResource(const QByteArray &resourceType, const QByteArra
290 290
291GenericResource::~GenericResource() 291GenericResource::~GenericResource()
292{ 292{
293 delete mProcessor;
294} 293}
295 294
296KAsync::Job<void> GenericResource::inspect( 295KAsync::Job<void> GenericResource::inspect(
297 int inspectionType, const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expectedValue) 296 int inspectionType, const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expectedValue)
298{ 297{
299 Warning() << "Inspection not implemented"; 298 SinkWarning() << "Inspection not implemented";
300 return KAsync::null<void>(); 299 return KAsync::null<void>();
301} 300}
302 301
@@ -329,13 +328,36 @@ void GenericResource::setupSynchronizer(const QSharedPointer<Synchronizer> &sync
329void GenericResource::setupChangereplay(const QSharedPointer<ChangeReplay> &changeReplay) 328void GenericResource::setupChangereplay(const QSharedPointer<ChangeReplay> &changeReplay)
330{ 329{
331 mChangeReplay = changeReplay; 330 mChangeReplay = changeReplay;
331 {
332 auto ret = QObject::connect(mChangeReplay.data(), &ChangeReplay::replayingChanges, [this]() {
333 Sink::Notification n;
334 n.id = "changereplay";
335 n.type = Sink::Notification::Status;
336 n.message = "Replaying changes.";
337 n.code = Sink::ApplicationDomain::BusyStatus;
338 emit notify(n);
339 });
340 Q_ASSERT(ret);
341 }
342 {
343 auto ret = QObject::connect(mChangeReplay.data(), &ChangeReplay::changesReplayed, [this]() {
344 Sink::Notification n;
345 n.id = "changereplay";
346 n.type = Sink::Notification::Status;
347 n.message = "All changes have been replayed.";
348 n.code = Sink::ApplicationDomain::ConnectedStatus;
349 emit notify(n);
350 });
351 Q_ASSERT(ret);
352 }
353
332 mProcessor->setOldestUsedRevision(mChangeReplay->getLastReplayedRevision()); 354 mProcessor->setOldestUsedRevision(mChangeReplay->getLastReplayedRevision());
333 enableChangeReplay(true); 355 enableChangeReplay(true);
334} 356}
335 357
336void GenericResource::removeDataFromDisk() 358void GenericResource::removeDataFromDisk()
337{ 359{
338 Log() << "Removing the resource from disk: " << mResourceInstanceIdentifier; 360 SinkLog() << "Removing the resource from disk: " << mResourceInstanceIdentifier;
339 //Ensure we have no transaction or databases open 361 //Ensure we have no transaction or databases open
340 mSynchronizer.clear(); 362 mSynchronizer.clear();
341 mChangeReplay.clear(); 363 mChangeReplay.clear();
@@ -363,7 +385,7 @@ qint64 GenericResource::diskUsage(const QByteArray &instanceIdentifier)
363 385
364void GenericResource::onProcessorError(int errorCode, const QString &errorMessage) 386void GenericResource::onProcessorError(int errorCode, const QString &errorMessage)
365{ 387{
366 Warning() << "Received error from Processor: " << errorCode << errorMessage; 388 SinkWarning() << "Received error from Processor: " << errorCode << errorMessage;
367 mError = errorCode; 389 mError = errorCode;
368} 390}
369 391
@@ -399,12 +421,27 @@ void GenericResource::processCommand(int commandId, const QByteArray &data)
399KAsync::Job<void> GenericResource::synchronizeWithSource() 421KAsync::Job<void> GenericResource::synchronizeWithSource()
400{ 422{
401 return KAsync::start<void>([this](KAsync::Future<void> &future) { 423 return KAsync::start<void>([this](KAsync::Future<void> &future) {
402 Log() << " Synchronizing"; 424
425 Sink::Notification n;
426 n.id = "sync";
427 n.type = Sink::Notification::Status;
428 n.message = "Synchronization has started.";
429 n.code = Sink::ApplicationDomain::BusyStatus;
430 emit notify(n);
431
432 SinkLog() << " Synchronizing";
403 // Changereplay would deadlock otherwise when trying to open the synchronization store 433 // Changereplay would deadlock otherwise when trying to open the synchronization store
404 enableChangeReplay(false); 434 enableChangeReplay(false);
405 mSynchronizer->synchronize() 435 mSynchronizer->synchronize()
406 .then<void>([this, &future]() { 436 .then<void>([this, &future]() {
407 Log() << "Done Synchronizing"; 437 SinkLog() << "Done Synchronizing";
438 Sink::Notification n;
439 n.id = "sync";
440 n.type = Sink::Notification::Status;
441 n.message = "Synchronization has ended.";
442 n.code = Sink::ApplicationDomain::ConnectedStatus;
443 emit notify(n);
444
408 enableChangeReplay(true); 445 enableChangeReplay(true);
409 future.setFinished(); 446 future.setFinished();
410 }, [this, &future](int errorCode, const QString &error) { 447 }, [this, &future](int errorCode, const QString &error) {
diff --git a/common/genericresource.h b/common/genericresource.h
index 0878968..25892ca 100644
--- a/common/genericresource.h
+++ b/common/genericresource.h
@@ -40,6 +40,9 @@ class Synchronizer;
40 */ 40 */
41class SINK_EXPORT GenericResource : public Resource 41class SINK_EXPORT GenericResource : public Resource
42{ 42{
43protected:
44 SINK_DEBUG_AREA("resource")
45 SINK_DEBUG_COMPONENT(mResourceInstanceIdentifier)
43public: 46public:
44 GenericResource(const QByteArray &resourceType, const QByteArray &resourceInstanceIdentifier, const QSharedPointer<Pipeline> &pipeline); 47 GenericResource(const QByteArray &resourceType, const QByteArray &resourceInstanceIdentifier, const QSharedPointer<Pipeline> &pipeline);
45 virtual ~GenericResource(); 48 virtual ~GenericResource();
@@ -77,7 +80,7 @@ protected:
77 QSharedPointer<Pipeline> mPipeline; 80 QSharedPointer<Pipeline> mPipeline;
78 81
79private: 82private:
80 CommandProcessor *mProcessor; 83 std::unique_ptr<CommandProcessor> mProcessor;
81 QSharedPointer<ChangeReplay> mChangeReplay; 84 QSharedPointer<ChangeReplay> mChangeReplay;
82 QSharedPointer<Synchronizer> mSynchronizer; 85 QSharedPointer<Synchronizer> mSynchronizer;
83 int mError; 86 int mError;
diff --git a/common/index.cpp b/common/index.cpp
index 151f7af..beed45c 100644
--- a/common/index.cpp
+++ b/common/index.cpp
@@ -2,8 +2,7 @@
2 2
3#include "log.h" 3#include "log.h"
4 4
5#undef Trace 5SINK_DEBUG_AREA("index")
6#define Trace() Trace_area("index." + mName.toLatin1())
7 6
8Index::Index(const QString &storageRoot, const QString &name, Sink::Storage::AccessMode mode) 7Index::Index(const QString &storageRoot, const QString &name, Sink::Storage::AccessMode mode)
9 : mTransaction(Sink::Storage(storageRoot, name, mode).createTransaction(mode)), 8 : mTransaction(Sink::Storage(storageRoot, name, mode).createTransaction(mode)),
@@ -34,8 +33,8 @@ void Index::lookup(const QByteArray &key, const std::function<void(const QByteAr
34 resultHandler(value); 33 resultHandler(value);
35 return true; 34 return true;
36 }, 35 },
37 [errorHandler](const Sink::Storage::Error &error) { 36 [this, errorHandler](const Sink::Storage::Error &error) {
38 Warning() << "Error while retrieving value" << error.message; 37 SinkWarning() << "Error while retrieving value" << error.message;
39 errorHandler(Error(error.store, error.code, error.message)); 38 errorHandler(Error(error.store, error.code, error.message));
40 }, 39 },
41 matchSubStringKeys); 40 matchSubStringKeys);
@@ -45,6 +44,6 @@ QByteArray Index::lookup(const QByteArray &key)
45{ 44{
46 QByteArray result; 45 QByteArray result;
47 //We have to create a deep copy, otherwise the returned data may become invalid when the transaction ends. 46 //We have to create a deep copy, otherwise the returned data may become invalid when the transaction ends.
48 lookup(key, [&result](const QByteArray &value) { result = QByteArray(value.constData(), value.size()); }, [this](const Index::Error &error) { Trace() << "Error while retrieving value" << error.message; }); 47 lookup(key, [&result](const QByteArray &value) { result = QByteArray(value.constData(), value.size()); }, [this](const Index::Error &error) { SinkTrace() << "Error while retrieving value" << error.message; });
49 return result; 48 return result;
50} 49}
diff --git a/common/index.h b/common/index.h
index 0345f56..bfedf9a 100644
--- a/common/index.h
+++ b/common/index.h
@@ -5,6 +5,7 @@
5#include <functional> 5#include <functional>
6#include <QString> 6#include <QString>
7#include "storage.h" 7#include "storage.h"
8#include "log.h"
8 9
9/** 10/**
10 * An index for value pairs. 11 * An index for value pairs.
@@ -43,4 +44,5 @@ private:
43 Sink::Storage::Transaction mTransaction; 44 Sink::Storage::Transaction mTransaction;
44 Sink::Storage::NamedDatabase mDb; 45 Sink::Storage::NamedDatabase mDb;
45 QString mName; 46 QString mName;
47 SINK_DEBUG_COMPONENT(mName.toLatin1())
46}; 48};
diff --git a/common/listener.cpp b/common/listener.cpp
index 84afe16..2c5c1df 100644
--- a/common/listener.cpp
+++ b/common/listener.cpp
@@ -39,39 +39,35 @@
39#include <QTime> 39#include <QTime>
40#include <QDataStream> 40#include <QDataStream>
41 41
42#undef DEBUG_AREA
43#define DEBUG_AREA "resource.communication"
44
45Listener::Listener(const QByteArray &resourceInstanceIdentifier, const QByteArray &resourceType, QObject *parent) 42Listener::Listener(const QByteArray &resourceInstanceIdentifier, const QByteArray &resourceType, QObject *parent)
46 : QObject(parent), 43 : QObject(parent),
47 m_server(new QLocalServer(this)), 44 m_server(new QLocalServer(this)),
48 m_resourceName(resourceType), 45 m_resourceName(resourceType),
49 m_resourceInstanceIdentifier(resourceInstanceIdentifier), 46 m_resourceInstanceIdentifier(resourceInstanceIdentifier),
50 m_resource(0),
51 m_clientBufferProcessesTimer(new QTimer(this)), 47 m_clientBufferProcessesTimer(new QTimer(this)),
52 m_messageId(0) 48 m_messageId(0)
53{ 49{
54 connect(m_server, &QLocalServer::newConnection, this, &Listener::acceptConnection); 50 connect(m_server.get(), &QLocalServer::newConnection, this, &Listener::acceptConnection);
55 Trace() << "Trying to open " << m_resourceInstanceIdentifier; 51 SinkTrace() << "Trying to open " << m_resourceInstanceIdentifier;
56 52
57 if (!m_server->listen(QString::fromLatin1(m_resourceInstanceIdentifier))) { 53 if (!m_server->listen(QString::fromLatin1(m_resourceInstanceIdentifier))) {
58 m_server->removeServer(m_resourceInstanceIdentifier); 54 m_server->removeServer(m_resourceInstanceIdentifier);
59 if (!m_server->listen(QString::fromLatin1(m_resourceInstanceIdentifier))) { 55 if (!m_server->listen(QString::fromLatin1(m_resourceInstanceIdentifier))) {
60 Warning() << "Utter failure to start server"; 56 SinkWarning() << "Utter failure to start server";
61 exit(-1); 57 exit(-1);
62 } 58 }
63 } 59 }
64 60
65 if (m_server->isListening()) { 61 if (m_server->isListening()) {
66 Log() << QString("Listening on %1").arg(m_server->serverName()); 62 SinkLog() << QString("Listening on %1").arg(m_server->serverName());
67 } 63 }
68 64
69 m_checkConnectionsTimer = new QTimer; 65 m_checkConnectionsTimer = std::unique_ptr<QTimer>(new QTimer);
70 m_checkConnectionsTimer->setSingleShot(true); 66 m_checkConnectionsTimer->setSingleShot(true);
71 m_checkConnectionsTimer->setInterval(1000); 67 m_checkConnectionsTimer->setInterval(1000);
72 connect(m_checkConnectionsTimer, &QTimer::timeout, [this]() { 68 connect(m_checkConnectionsTimer.get(), &QTimer::timeout, [this]() {
73 if (m_connections.isEmpty()) { 69 if (m_connections.isEmpty()) {
74 Log() << QString("No connections, shutting down."); 70 SinkLog() << QString("No connections, shutting down.");
75 quit(); 71 quit();
76 } 72 }
77 }); 73 });
@@ -80,18 +76,19 @@ Listener::Listener(const QByteArray &resourceInstanceIdentifier, const QByteArra
80 // or even just drop down to invoking the method queued? => invoke queued unless we need throttling 76 // or even just drop down to invoking the method queued? => invoke queued unless we need throttling
81 m_clientBufferProcessesTimer->setInterval(0); 77 m_clientBufferProcessesTimer->setInterval(0);
82 m_clientBufferProcessesTimer->setSingleShot(true); 78 m_clientBufferProcessesTimer->setSingleShot(true);
83 connect(m_clientBufferProcessesTimer, &QTimer::timeout, this, &Listener::processClientBuffers); 79 connect(m_clientBufferProcessesTimer.get(), &QTimer::timeout, this, &Listener::processClientBuffers);
84} 80}
85 81
86Listener::~Listener() 82Listener::~Listener()
87{ 83{
84 closeAllConnections();
88} 85}
89 86
90void Listener::emergencyAbortAllConnections() 87void Listener::emergencyAbortAllConnections()
91{ 88{
92 for (Client &client : m_connections) { 89 for (Client &client : m_connections) {
93 if (client.socket) { 90 if (client.socket) {
94 Warning() << "Sending panic"; 91 SinkWarning() << "Sending panic";
95 client.socket->write("PANIC"); 92 client.socket->write("PANIC");
96 client.socket->waitForBytesWritten(); 93 client.socket->waitForBytesWritten();
97 disconnect(client.socket, 0, this, 0); 94 disconnect(client.socket, 0, this, 0);
@@ -120,11 +117,11 @@ void Listener::closeAllConnections()
120 117
121void Listener::acceptConnection() 118void Listener::acceptConnection()
122{ 119{
123 Trace() << "Accepting connection"; 120 SinkTrace() << "Accepting connection";
124 QLocalSocket *socket = m_server->nextPendingConnection(); 121 QLocalSocket *socket = m_server->nextPendingConnection();
125 122
126 if (!socket) { 123 if (!socket) {
127 Warning() << "Accepted connection but didn't get a socket for it"; 124 SinkWarning() << "Accepted connection but didn't get a socket for it";
128 return; 125 return;
129 } 126 }
130 127
@@ -135,7 +132,7 @@ void Listener::acceptConnection()
135 132
136 // If this is the first client, set the lower limit for revision cleanup 133 // If this is the first client, set the lower limit for revision cleanup
137 if (m_connections.size() == 1) { 134 if (m_connections.size() == 1) {
138 loadResource()->setLowerBoundRevision(0); 135 loadResource().setLowerBoundRevision(0);
139 } 136 }
140 137
141 if (socket->bytesAvailable()) { 138 if (socket->bytesAvailable()) {
@@ -156,13 +153,13 @@ void Listener::clientDropped()
156 const Client &client = it.next(); 153 const Client &client = it.next();
157 if (client.socket == socket) { 154 if (client.socket == socket) {
158 dropped = true; 155 dropped = true;
159 Log() << QString("Dropped connection: %1").arg(client.name) << socket; 156 SinkLog() << QString("Dropped connection: %1").arg(client.name) << socket;
160 it.remove(); 157 it.remove();
161 break; 158 break;
162 } 159 }
163 } 160 }
164 if (!dropped) { 161 if (!dropped) {
165 Warning() << "Failed to find connection for disconnected socket: " << socket; 162 SinkWarning() << "Failed to find connection for disconnected socket: " << socket;
166 } 163 }
167 164
168 checkConnections(); 165 checkConnections();
@@ -172,7 +169,7 @@ void Listener::checkConnections()
172{ 169{
173 // If this was the last client, disengage the lower limit for revision cleanup 170 // If this was the last client, disengage the lower limit for revision cleanup
174 if (m_connections.isEmpty()) { 171 if (m_connections.isEmpty()) {
175 loadResource()->setLowerBoundRevision(std::numeric_limits<qint64>::max()); 172 loadResource().setLowerBoundRevision(std::numeric_limits<qint64>::max());
176 } 173 }
177 m_checkConnectionsTimer->start(); 174 m_checkConnectionsTimer->start();
178} 175}
@@ -188,7 +185,7 @@ void Listener::onDataAvailable()
188 185
189void Listener::readFromSocket(QLocalSocket *socket) 186void Listener::readFromSocket(QLocalSocket *socket)
190{ 187{
191 Trace() << "Reading from socket..."; 188 SinkTrace() << "Reading from socket...";
192 for (Client &client : m_connections) { 189 for (Client &client : m_connections) {
193 if (client.socket == socket) { 190 if (client.socket == socket) {
194 client.commandBuffer += socket->readAll(); 191 client.commandBuffer += socket->readAll();
@@ -231,7 +228,7 @@ void Listener::processCommand(int commandId, uint messageId, const QByteArray &c
231 auto buffer = Sink::Commands::GetHandshake(commandBuffer.constData()); 228 auto buffer = Sink::Commands::GetHandshake(commandBuffer.constData());
232 client.name = buffer->name()->c_str(); 229 client.name = buffer->name()->c_str();
233 } else { 230 } else {
234 Warning() << "received invalid command"; 231 SinkWarning() << "received invalid command";
235 } 232 }
236 break; 233 break;
237 } 234 }
@@ -239,27 +236,27 @@ void Listener::processCommand(int commandId, uint messageId, const QByteArray &c
239 flatbuffers::Verifier verifier((const uint8_t *)commandBuffer.constData(), commandBuffer.size()); 236 flatbuffers::Verifier verifier((const uint8_t *)commandBuffer.constData(), commandBuffer.size());
240 if (Sink::Commands::VerifySynchronizeBuffer(verifier)) { 237 if (Sink::Commands::VerifySynchronizeBuffer(verifier)) {
241 auto buffer = Sink::Commands::GetSynchronize(commandBuffer.constData()); 238 auto buffer = Sink::Commands::GetSynchronize(commandBuffer.constData());
242 Trace() << QString("Synchronize request (id %1) from %2").arg(messageId).arg(client.name); 239 SinkTrace() << QString("Synchronize request (id %1) from %2").arg(messageId).arg(client.name);
243 auto timer = QSharedPointer<QTime>::create(); 240 auto timer = QSharedPointer<QTime>::create();
244 timer->start(); 241 timer->start();
245 auto job = KAsync::null<void>(); 242 auto job = KAsync::null<void>();
246 if (buffer->sourceSync()) { 243 if (buffer->sourceSync()) {
247 job = loadResource()->synchronizeWithSource(); 244 job = loadResource().synchronizeWithSource();
248 } 245 }
249 if (buffer->localSync()) { 246 if (buffer->localSync()) {
250 job = job.then<void>(loadResource()->processAllMessages()); 247 job = job.then<void>(loadResource().processAllMessages());
251 } 248 }
252 job.then<void>([callback, timer]() { 249 job.then<void>([callback, timer]() {
253 Trace() << "Sync took " << Sink::Log::TraceTime(timer->elapsed()); 250 SinkTrace() << "Sync took " << Sink::Log::TraceTime(timer->elapsed());
254 callback(true); 251 callback(true);
255 }, [callback](int errorCode, const QString &msg) { 252 }, [callback](int errorCode, const QString &msg) {
256 Warning() << "Sync failed: " << msg; 253 SinkWarning() << "Sync failed: " << msg;
257 callback(false); 254 callback(false);
258 }) 255 })
259 .exec(); 256 .exec();
260 return; 257 return;
261 } else { 258 } else {
262 Warning() << "received invalid command"; 259 SinkWarning() << "received invalid command";
263 } 260 }
264 break; 261 break;
265 } 262 }
@@ -268,44 +265,43 @@ void Listener::processCommand(int commandId, uint messageId, const QByteArray &c
268 case Sink::Commands::DeleteEntityCommand: 265 case Sink::Commands::DeleteEntityCommand:
269 case Sink::Commands::ModifyEntityCommand: 266 case Sink::Commands::ModifyEntityCommand:
270 case Sink::Commands::CreateEntityCommand: 267 case Sink::Commands::CreateEntityCommand:
271 Trace() << "Command id " << messageId << " of type \"" << Sink::Commands::name(commandId) << "\" from " << client.name; 268 SinkTrace() << "Command id " << messageId << " of type \"" << Sink::Commands::name(commandId) << "\" from " << client.name;
272 loadResource()->processCommand(commandId, commandBuffer); 269 loadResource().processCommand(commandId, commandBuffer);
273 break; 270 break;
274 case Sink::Commands::ShutdownCommand: 271 case Sink::Commands::ShutdownCommand:
275 Log() << QString("Received shutdown command from %1").arg(client.name); 272 SinkLog() << QString("Received shutdown command from %1").arg(client.name);
276 // Immediately reject new connections 273 // Immediately reject new connections
277 m_server->close(); 274 m_server->close();
278 QTimer::singleShot(0, this, &Listener::quit); 275 QTimer::singleShot(0, this, &Listener::quit);
279 break; 276 break;
280 case Sink::Commands::PingCommand: 277 case Sink::Commands::PingCommand:
281 Trace() << QString("Received ping command from %1").arg(client.name); 278 SinkTrace() << QString("Received ping command from %1").arg(client.name);
282 break; 279 break;
283 case Sink::Commands::RevisionReplayedCommand: { 280 case Sink::Commands::RevisionReplayedCommand: {
284 Trace() << QString("Received revision replayed command from %1").arg(client.name); 281 SinkTrace() << QString("Received revision replayed command from %1").arg(client.name);
285 flatbuffers::Verifier verifier((const uint8_t *)commandBuffer.constData(), commandBuffer.size()); 282 flatbuffers::Verifier verifier((const uint8_t *)commandBuffer.constData(), commandBuffer.size());
286 if (Sink::Commands::VerifyRevisionReplayedBuffer(verifier)) { 283 if (Sink::Commands::VerifyRevisionReplayedBuffer(verifier)) {
287 auto buffer = Sink::Commands::GetRevisionReplayed(commandBuffer.constData()); 284 auto buffer = Sink::Commands::GetRevisionReplayed(commandBuffer.constData());
288 client.currentRevision = buffer->revision(); 285 client.currentRevision = buffer->revision();
289 } else { 286 } else {
290 Warning() << "received invalid command"; 287 SinkWarning() << "received invalid command";
291 } 288 }
292 loadResource()->setLowerBoundRevision(lowerBoundRevision()); 289 loadResource().setLowerBoundRevision(lowerBoundRevision());
293 } break; 290 } break;
294 case Sink::Commands::RemoveFromDiskCommand: { 291 case Sink::Commands::RemoveFromDiskCommand: {
295 Log() << QString("Received a remove from disk command from %1").arg(client.name); 292 SinkLog() << QString("Received a remove from disk command from %1").arg(client.name);
296 delete m_resource; 293 m_resource.reset(nullptr);
297 m_resource = nullptr; 294 loadResource().removeDataFromDisk();
298 loadResource()->removeDataFromDisk();
299 m_server->close(); 295 m_server->close();
300 QTimer::singleShot(0, this, &Listener::quit); 296 QTimer::singleShot(0, this, &Listener::quit);
301 } break; 297 } break;
302 default: 298 default:
303 if (commandId > Sink::Commands::CustomCommand) { 299 if (commandId > Sink::Commands::CustomCommand) {
304 Log() << QString("Received custom command from %1: ").arg(client.name) << commandId; 300 SinkLog() << QString("Received custom command from %1: ").arg(client.name) << commandId;
305 loadResource()->processCommand(commandId, commandBuffer); 301 loadResource().processCommand(commandId, commandBuffer);
306 } else { 302 } else {
307 success = false; 303 success = false;
308 ErrorMsg() << QString("\tReceived invalid command from %1: ").arg(client.name) << commandId; 304 SinkError() << QString("\tReceived invalid command from %1: ").arg(client.name) << commandId;
309 } 305 }
310 break; 306 break;
311 } 307 }
@@ -330,7 +326,7 @@ qint64 Listener::lowerBoundRevision()
330void Listener::quit() 326void Listener::quit()
331{ 327{
332 // Broadcast shutdown notifications to open clients, so they don't try to restart the resource 328 // Broadcast shutdown notifications to open clients, so they don't try to restart the resource
333 auto command = Sink::Commands::CreateNotification(m_fbb, Sink::Commands::NotificationType::NotificationType_Shutdown); 329 auto command = Sink::Commands::CreateNotification(m_fbb, Sink::Notification::Shutdown);
334 Sink::Commands::FinishNotificationBuffer(m_fbb, command); 330 Sink::Commands::FinishNotificationBuffer(m_fbb, command);
335 for (Client &client : m_connections) { 331 for (Client &client : m_connections) {
336 if (client.socket && client.socket->isOpen()) { 332 if (client.socket && client.socket->isOpen()) {
@@ -353,7 +349,7 @@ bool Listener::processClientBuffer(Client &client)
353 const uint messageId = *(uint *)client.commandBuffer.constData(); 349 const uint messageId = *(uint *)client.commandBuffer.constData();
354 const int commandId = *(int *)(client.commandBuffer.constData() + sizeof(uint)); 350 const int commandId = *(int *)(client.commandBuffer.constData() + sizeof(uint));
355 const uint size = *(uint *)(client.commandBuffer.constData() + sizeof(int) + sizeof(uint)); 351 const uint size = *(uint *)(client.commandBuffer.constData() + sizeof(int) + sizeof(uint));
356 Trace() << "Received message. Id:" << messageId << " CommandId: " << commandId << " Size: " << size; 352 SinkTrace() << "Received message. Id:" << messageId << " CommandId: " << commandId << " Size: " << size;
357 353
358 // TODO: reject messages above a certain size? 354 // TODO: reject messages above a certain size?
359 355
@@ -366,11 +362,11 @@ bool Listener::processClientBuffer(Client &client)
366 const QByteArray commandBuffer = client.commandBuffer.left(size); 362 const QByteArray commandBuffer = client.commandBuffer.left(size);
367 client.commandBuffer.remove(0, size); 363 client.commandBuffer.remove(0, size);
368 processCommand(commandId, messageId, commandBuffer, client, [this, messageId, commandId, socket, clientName](bool success) { 364 processCommand(commandId, messageId, commandBuffer, client, [this, messageId, commandId, socket, clientName](bool success) {
369 Trace() << QString("Completed command messageid %1 of type \"%2\" from %3").arg(messageId).arg(QString(Sink::Commands::name(commandId))).arg(clientName); 365 SinkTrace() << QString("Completed command messageid %1 of type \"%2\" from %3").arg(messageId).arg(QString(Sink::Commands::name(commandId))).arg(clientName);
370 if (socket) { 366 if (socket) {
371 sendCommandCompleted(socket.data(), messageId, success); 367 sendCommandCompleted(socket.data(), messageId, success);
372 } else { 368 } else {
373 Log() << QString("Socket became invalid before we could send a response. client: %1").arg(clientName); 369 SinkLog() << QString("Socket became invalid before we could send a response. client: %1").arg(clientName);
374 } 370 }
375 }); 371 });
376 372
@@ -407,7 +403,7 @@ void Listener::updateClientsWithRevision(qint64 revision)
407 continue; 403 continue;
408 } 404 }
409 405
410 Trace() << "Sending revision update for " << client.name << revision; 406 SinkTrace() << "Sending revision update for " << client.name << revision;
411 Sink::Commands::write(client.socket, ++m_messageId, Sink::Commands::RevisionUpdateCommand, m_fbb); 407 Sink::Commands::write(client.socket, ++m_messageId, Sink::Commands::RevisionUpdateCommand, m_fbb);
412 } 408 }
413 m_fbb.Clear(); 409 m_fbb.Clear();
@@ -418,7 +414,7 @@ void Listener::notify(const Sink::Notification &notification)
418 auto messageString = m_fbb.CreateString(notification.message.toUtf8().constData(), notification.message.toUtf8().size()); 414 auto messageString = m_fbb.CreateString(notification.message.toUtf8().constData(), notification.message.toUtf8().size());
419 auto idString = m_fbb.CreateString(notification.id.constData(), notification.id.size()); 415 auto idString = m_fbb.CreateString(notification.id.constData(), notification.id.size());
420 Sink::Commands::NotificationBuilder builder(m_fbb); 416 Sink::Commands::NotificationBuilder builder(m_fbb);
421 builder.add_type(static_cast<Sink::Commands::NotificationType>(notification.type)); 417 builder.add_type(notification.type);
422 builder.add_code(notification.code); 418 builder.add_code(notification.code);
423 builder.add_identifier(idString); 419 builder.add_identifier(idString);
424 builder.add_message(messageString); 420 builder.add_message(messageString);
@@ -432,25 +428,25 @@ void Listener::notify(const Sink::Notification &notification)
432 m_fbb.Clear(); 428 m_fbb.Clear();
433} 429}
434 430
435Sink::Resource *Listener::loadResource() 431Sink::Resource &Listener::loadResource()
436{ 432{
437 if (!m_resource) { 433 if (!m_resource) {
438 if (Sink::ResourceFactory *resourceFactory = Sink::ResourceFactory::load(m_resourceName)) { 434 if (Sink::ResourceFactory *resourceFactory = Sink::ResourceFactory::load(m_resourceName)) {
439 m_resource = resourceFactory->createResource(m_resourceInstanceIdentifier); 435 m_resource = std::unique_ptr<Sink::Resource>(resourceFactory->createResource(m_resourceInstanceIdentifier));
440 if (!m_resource) { 436 if (!m_resource) {
441 ErrorMsg() << "Failed to instantiate the resource " << m_resourceName; 437 SinkError() << "Failed to instantiate the resource " << m_resourceName;
442 m_resource = new Sink::Resource; 438 m_resource = std::unique_ptr<Sink::Resource>(new Sink::Resource);
443 } 439 }
444 Trace() << QString("Resource factory: %1").arg((qlonglong)resourceFactory); 440 SinkTrace() << QString("Resource factory: %1").arg((qlonglong)resourceFactory);
445 Trace() << QString("\tResource: %1").arg((qlonglong)m_resource); 441 SinkTrace() << QString("\tResource: %1").arg((qlonglong)m_resource.get());
446 connect(m_resource, &Sink::Resource::revisionUpdated, this, &Listener::refreshRevision); 442 connect(m_resource.get(), &Sink::Resource::revisionUpdated, this, &Listener::refreshRevision);
447 connect(m_resource, &Sink::Resource::notify, this, &Listener::notify); 443 connect(m_resource.get(), &Sink::Resource::notify, this, &Listener::notify);
448 } else { 444 } else {
449 ErrorMsg() << "Failed to load resource " << m_resourceName; 445 SinkError() << "Failed to load resource " << m_resourceName;
450 m_resource = new Sink::Resource; 446 m_resource = std::unique_ptr<Sink::Resource>(new Sink::Resource);
451 } 447 }
452 } 448 }
453 return m_resource; 449 return *m_resource;
454} 450}
455 451
456#pragma clang diagnostic push 452#pragma clang diagnostic push
diff --git a/common/listener.h b/common/listener.h
index 5e376c7..d6c537a 100644
--- a/common/listener.h
+++ b/common/listener.h
@@ -25,6 +25,7 @@
25#include <QPointer> 25#include <QPointer>
26#include <QLocalSocket> 26#include <QLocalSocket>
27#include <flatbuffers/flatbuffers.h> 27#include <flatbuffers/flatbuffers.h>
28#include <log.h>
28 29
29namespace Sink { 30namespace Sink {
30class Resource; 31class Resource;
@@ -54,6 +55,7 @@ public:
54class SINK_EXPORT Listener : public QObject 55class SINK_EXPORT Listener : public QObject
55{ 56{
56 Q_OBJECT 57 Q_OBJECT
58 SINK_DEBUG_AREA("communication")
57 59
58public: 60public:
59 Listener(const QByteArray &resourceName, const QByteArray &resourceType, QObject *parent = 0); 61 Listener(const QByteArray &resourceName, const QByteArray &resourceType, QObject *parent = 0);
@@ -81,17 +83,17 @@ private:
81 bool processClientBuffer(Client &client); 83 bool processClientBuffer(Client &client);
82 void sendCommandCompleted(QLocalSocket *socket, uint messageId, bool success); 84 void sendCommandCompleted(QLocalSocket *socket, uint messageId, bool success);
83 void updateClientsWithRevision(qint64); 85 void updateClientsWithRevision(qint64);
84 Sink::Resource *loadResource(); 86 Sink::Resource &loadResource();
85 void readFromSocket(QLocalSocket *socket); 87 void readFromSocket(QLocalSocket *socket);
86 qint64 lowerBoundRevision(); 88 qint64 lowerBoundRevision();
87 89
88 QLocalServer *m_server; 90 std::unique_ptr<QLocalServer> m_server;
89 QVector<Client> m_connections; 91 QVector<Client> m_connections;
90 flatbuffers::FlatBufferBuilder m_fbb; 92 flatbuffers::FlatBufferBuilder m_fbb;
91 const QByteArray m_resourceName; 93 const QByteArray m_resourceName;
92 const QByteArray m_resourceInstanceIdentifier; 94 const QByteArray m_resourceInstanceIdentifier;
93 Sink::Resource *m_resource; 95 std::unique_ptr<Sink::Resource> m_resource;
94 QTimer *m_clientBufferProcessesTimer; 96 std::unique_ptr<QTimer> m_clientBufferProcessesTimer;
95 QTimer *m_checkConnectionsTimer; 97 std::unique_ptr<QTimer> m_checkConnectionsTimer;
96 int m_messageId; 98 int m_messageId;
97}; 99};
diff --git a/common/log.cpp b/common/log.cpp
index b0f6237..099c043 100644
--- a/common/log.cpp
+++ b/common/log.cpp
@@ -4,16 +4,25 @@
4#include <QIODevice> 4#include <QIODevice>
5#include <QCoreApplication> 5#include <QCoreApplication>
6#include <QSettings> 6#include <QSettings>
7#include <QStandardPaths>
8#include <QSharedPointer> 7#include <QSharedPointer>
8#include <QMutex>
9#include <QMutexLocker>
9#include <iostream> 10#include <iostream>
10#include <unistd.h> 11#include <unistd.h>
12#include <memory>
13#include <definitions.h>
11 14
12using namespace Sink::Log; 15using namespace Sink::Log;
13 16
14static QSharedPointer<QSettings> config() 17static QSharedPointer<QSettings> config()
15{ 18{
16 return QSharedPointer<QSettings>::create(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/sink/log.ini", QSettings::IniFormat); 19 return QSharedPointer<QSettings>::create(Sink::configLocation() + "/log.ini", QSettings::IniFormat);
20}
21
22static QByteArray sPrimaryComponent;
23void Sink::Log::setPrimaryComponent(const QString &component)
24{
25 sPrimaryComponent = component.toUtf8();
17} 26}
18 27
19class DebugStream : public QIODevice 28class DebugStream : public QIODevice
@@ -212,9 +221,63 @@ static QByteArray getProgramName()
212 } 221 }
213} 222}
214 223
224static QSharedPointer<QSettings> debugAreasConfig()
225{
226 return QSharedPointer<QSettings>::create(Sink::dataLocation() + "/debugAreas.ini", QSettings::IniFormat);
227}
228
229class DebugAreaCollector {
230public:
231 DebugAreaCollector()
232 {
233 QMutexLocker locker(&mutex);
234 mDebugAreas = debugAreasConfig()->value("areas").value<QString>().split(';').toSet();
235 }
236
237 ~DebugAreaCollector()
238 {
239 QMutexLocker locker(&mutex);
240 mDebugAreas += debugAreasConfig()->value("areas").value<QString>().split(';').toSet();
241 debugAreasConfig()->setValue("areas", QVariant::fromValue(mDebugAreas.toList().join(';')));
242 }
243
244 void add(const QString &area)
245 {
246 QMutexLocker locker(&mutex);
247 mDebugAreas << area;
248 }
249
250 QSet<QString> debugAreas()
251 {
252 QMutexLocker locker(&mutex);
253 return mDebugAreas;
254 }
255
256 QMutex mutex;
257 QSet<QString> mDebugAreas;
258};
259
260static auto sDebugAreaCollector = std::unique_ptr<DebugAreaCollector>(new DebugAreaCollector);
261
262QSet<QString> Sink::Log::debugAreas()
263{
264 return sDebugAreaCollector->debugAreas();
265}
266
267static void collectDebugArea(const QString &debugArea)
268{
269 sDebugAreaCollector->add(debugArea);
270}
271
215static bool containsItemStartingWith(const QByteArray &pattern, const QByteArrayList &list) 272static bool containsItemStartingWith(const QByteArray &pattern, const QByteArrayList &list)
216{ 273{
217 for (const auto &item : list) { 274 for (const auto &item : list) {
275 if (item.startsWith('*')) {
276 auto stripped = item.mid(1);
277 if (pattern.contains(stripped)) {
278 return true;
279 }
280 }
218 if (pattern.startsWith(item)) { 281 if (pattern.startsWith(item)) {
219 return true; 282 return true;
220 } 283 }
@@ -232,24 +295,23 @@ static bool caseInsensitiveContains(const QByteArray &pattern, const QByteArrayL
232 return false; 295 return false;
233} 296}
234 297
235QDebug Sink::Log::debugStream(DebugLevel debugLevel, int line, const char *file, const char *function, const char *debugArea) 298QDebug Sink::Log::debugStream(DebugLevel debugLevel, int line, const char *file, const char *function, const char *debugArea, const char *debugComponent)
236{ 299{
237 static NullStream nullstream; 300 static NullStream nullstream;
238 if (debugLevel < debugOutputLevel()) { 301 if (debugLevel < debugOutputLevel()) {
239 return QDebug(&nullstream); 302 return QDebug(&nullstream);
240 } 303 }
241 304
242 auto areas = debugOutputFilter(Sink::Log::Area); 305 if (sPrimaryComponent.isEmpty()) {
243 if (debugArea && !areas.isEmpty()) { 306 sPrimaryComponent = getProgramName();
244 if (!containsItemStartingWith(debugArea, areas)) {
245 return QDebug(&nullstream);
246 }
247 } 307 }
248 static QByteArray programName = getProgramName(); 308 QString fullDebugArea = sPrimaryComponent + "." + (debugComponent ? (QString::fromLatin1(debugComponent) + ".") : "") + (debugArea ? QString::fromLatin1(debugArea) : "");
309
310 collectDebugArea(fullDebugArea);
249 311
250 auto filter = debugOutputFilter(Sink::Log::ApplicationName); 312 auto areas = debugOutputFilter(Sink::Log::Area);
251 if (!filter.isEmpty() && !filter.contains(programName)) { 313 if (!areas.isEmpty()) {
252 if (!containsItemStartingWith(programName, filter)) { 314 if (!containsItemStartingWith(fullDebugArea.toUtf8(), areas)) {
253 return QDebug(&nullstream); 315 return QDebug(&nullstream);
254 } 316 }
255 } 317 }
@@ -293,19 +355,17 @@ QDebug Sink::Log::debugStream(DebugLevel debugLevel, int line, const char *file,
293 } 355 }
294 if (showProgram) { 356 if (showProgram) {
295 int width = 10; 357 int width = 10;
296 output += QString(" %1(%2)").arg(QString::fromLatin1(programName).leftJustified(width, ' ', true)).arg(unsigned(getpid())).rightJustified(width + 8, ' '); 358 output += QString(" %1(%2)").arg(QString::fromLatin1(getProgramName()).leftJustified(width, ' ', true)).arg(unsigned(getpid())).rightJustified(width + 8, ' ');
297 } 359 }
298 if (debugArea) { 360 if (useColor) {
299 if (useColor) { 361 output += colorCommand(QList<int>() << ANSI_Colors::Bold << prefixColorCode);
300 output += colorCommand(QList<int>() << ANSI_Colors::Bold << prefixColorCode); 362 }
301 } 363 output += QString(" %1 ").arg(fullDebugArea.leftJustified(25, ' ', true));
302 output += QString(" %1 ").arg(QString::fromLatin1(debugArea).leftJustified(25, ' ', true)); 364 if (useColor) {
303 if (useColor) { 365 output += resetColor;
304 output += resetColor;
305 }
306 } 366 }
307 if (showFunction) { 367 if (showFunction) {
308 output += QString(" %3").arg(QString::fromLatin1(function).leftJustified(25, ' ', true)); 368 output += QString(" %3").arg(fullDebugArea.leftJustified(25, ' ', true));
309 } 369 }
310 if (showLocation) { 370 if (showLocation) {
311 const auto filename = QString::fromLatin1(file).split('/').last(); 371 const auto filename = QString::fromLatin1(file).split('/').last();
diff --git a/common/log.h b/common/log.h
index 0e92ea9..f47a3ae 100644
--- a/common/log.h
+++ b/common/log.h
@@ -14,6 +14,9 @@ enum DebugLevel
14 Error 14 Error
15}; 15};
16 16
17void SINK_EXPORT setPrimaryComponent(const QString &component);
18QSet<QString> SINK_EXPORT debugAreas();
19
17QByteArray SINK_EXPORT debugLevelName(DebugLevel debugLevel); 20QByteArray SINK_EXPORT debugLevelName(DebugLevel debugLevel);
18DebugLevel SINK_EXPORT debugLevelFromName(const QByteArray &name); 21DebugLevel SINK_EXPORT debugLevelFromName(const QByteArray &name);
19 22
@@ -55,7 +58,7 @@ QByteArrayList SINK_EXPORT debugOutputFilter(FilterType type);
55void SINK_EXPORT setDebugOutputFields(const QByteArrayList &filter); 58void SINK_EXPORT setDebugOutputFields(const QByteArrayList &filter);
56QByteArrayList SINK_EXPORT debugOutputFields(); 59QByteArrayList SINK_EXPORT debugOutputFields();
57 60
58QDebug SINK_EXPORT debugStream(DebugLevel debugLevel, int line, const char *file, const char *function, const char *debugArea = 0); 61QDebug SINK_EXPORT debugStream(DebugLevel debugLevel, int line, const char *file, const char *function, const char *debugArea = 0, const char *debugComponent = 0);
59 62
60struct SINK_EXPORT TraceTime 63struct SINK_EXPORT TraceTime
61{ 64{
@@ -71,18 +74,23 @@ inline QDebug SINK_EXPORT operator<<(QDebug d, const TraceTime &time)
71} 74}
72} 75}
73 76
74#define DEBUG_AREA nullptr 77static const char *getComponentName() { return nullptr; }
75
76#define Trace_() Sink::Log::debugStream(Sink::Log::DebugLevel::Trace, __LINE__, __FILE__, Q_FUNC_INFO)
77#define Log_() Sink::Log::debugStream(Sink::Log::DebugLevel::Log, __LINE__, __FILE__, Q_FUNC_INFO)
78 78
79#define Trace_area(AREA) Sink::Log::debugStream(Sink::Log::DebugLevel::Trace, __LINE__, __FILE__, Q_FUNC_INFO, AREA) 79#define Trace_area(AREA) Sink::Log::debugStream(Sink::Log::DebugLevel::Trace, __LINE__, __FILE__, Q_FUNC_INFO, AREA)
80#define Log_area(AREA) Sink::Log::debugStream(Sink::Log::DebugLevel::Log, __LINE__, __FILE__, Q_FUNC_INFO, AREA) 80#define Log_area(AREA) Sink::Log::debugStream(Sink::Log::DebugLevel::Log, __LINE__, __FILE__, Q_FUNC_INFO, AREA)
81#define Warning_area(AREA) Sink::Log::debugStream(Sink::Log::DebugLevel::Warning, __LINE__, __FILE__, Q_FUNC_INFO, AREA) 81#define Warning_area(AREA) Sink::Log::debugStream(Sink::Log::DebugLevel::Warning, __LINE__, __FILE__, Q_FUNC_INFO, AREA)
82#define Error_area(AREA) Sink::Log::debugStream(Sink::Log::DebugLevel::Error, __LINE__, __FILE__, Q_FUNC_INFO, AREA) 82#define Error_area(AREA) Sink::Log::debugStream(Sink::Log::DebugLevel::Error, __LINE__, __FILE__, Q_FUNC_INFO, AREA)
83 83
84#define Trace() Sink::Log::debugStream(Sink::Log::DebugLevel::Trace, __LINE__, __FILE__, Q_FUNC_INFO, DEBUG_AREA) 84#define SinkTrace_(COMPONENT, AREA) Sink::Log::debugStream(Sink::Log::DebugLevel::Trace, __LINE__, __FILE__, Q_FUNC_INFO, AREA, COMPONENT)
85#define Log() Sink::Log::debugStream(Sink::Log::DebugLevel::Log, __LINE__, __FILE__, Q_FUNC_INFO, DEBUG_AREA) 85#define SinkLog_(COMPONENT, AREA) Sink::Log::debugStream(Sink::Log::DebugLevel::Log, __LINE__, __FILE__, Q_FUNC_INFO, AREA, COMPONENT)
86#define Warning() Sink::Log::debugStream(Sink::Log::DebugLevel::Warning, __LINE__, __FILE__, Q_FUNC_INFO, DEBUG_AREA) 86#define SinkWarning_(COMPONENT, AREA) Sink::Log::debugStream(Sink::Log::DebugLevel::Warning, __LINE__, __FILE__, Q_FUNC_INFO, AREA, COMPONENT)
87// FIXME Error clashes with Storage::Error and MessageQueue::Error 87#define SinkError_(COMPONENT, AREA) Sink::Log::debugStream(Sink::Log::DebugLevel::Error, __LINE__, __FILE__, Q_FUNC_INFO, AREA, COMPONENT)
88#define ErrorMsg() Sink::Log::debugStream(Sink::Log::DebugLevel::Error, __LINE__, __FILE__, Q_FUNC_INFO, DEBUG_AREA) 88
89#define SinkTrace() Sink::Log::debugStream(Sink::Log::DebugLevel::Trace, __LINE__, __FILE__, Q_FUNC_INFO, s_sinkDebugArea, getComponentName())
90#define SinkLog() Sink::Log::debugStream(Sink::Log::DebugLevel::Log, __LINE__, __FILE__, Q_FUNC_INFO, s_sinkDebugArea, getComponentName())
91#define SinkWarning() Sink::Log::debugStream(Sink::Log::DebugLevel::Warning, __LINE__, __FILE__, Q_FUNC_INFO, s_sinkDebugArea, getComponentName())
92#define SinkError() Sink::Log::debugStream(Sink::Log::DebugLevel::Error, __LINE__, __FILE__, Q_FUNC_INFO, s_sinkDebugArea, getComponentName())
93
94#define SINK_DEBUG_AREA(AREA) static constexpr const char* s_sinkDebugArea{AREA};
95#define SINK_DEBUG_COMPONENT(COMPONENT) const char* getComponentName() const { return COMPONENT; };
96#define SINK_DEBUG_COMPONENT_STATIC(COMPONENT) static const char* getComponentName() { return COMPONENT; };
diff --git a/common/mailpreprocessor.cpp b/common/mailpreprocessor.cpp
index 005a93e..2863ad4 100644
--- a/common/mailpreprocessor.cpp
+++ b/common/mailpreprocessor.cpp
@@ -29,6 +29,8 @@
29 29
30using namespace Sink; 30using namespace Sink;
31 31
32SINK_DEBUG_AREA("mailpreprocessor")
33
32QString MailPropertyExtractor::getFilePathFromMimeMessagePath(const QString &s) const 34QString MailPropertyExtractor::getFilePathFromMimeMessagePath(const QString &s) const
33{ 35{
34 return s; 36 return s;
@@ -37,20 +39,24 @@ QString MailPropertyExtractor::getFilePathFromMimeMessagePath(const QString &s)
37void MailPropertyExtractor::updatedIndexedProperties(Sink::ApplicationDomain::Mail &mail) 39void MailPropertyExtractor::updatedIndexedProperties(Sink::ApplicationDomain::Mail &mail)
38{ 40{
39 const auto mimeMessagePath = getFilePathFromMimeMessagePath(mail.getMimeMessagePath()); 41 const auto mimeMessagePath = getFilePathFromMimeMessagePath(mail.getMimeMessagePath());
40 Trace() << "Updating indexed properties " << mimeMessagePath; 42 if (mimeMessagePath.isNull()) {
43 SinkTrace() << "No mime message";
44 return;
45 }
46 SinkTrace() << "Updating indexed properties " << mimeMessagePath;
41 QFile f(mimeMessagePath); 47 QFile f(mimeMessagePath);
42 if (!f.open(QIODevice::ReadOnly)) { 48 if (!f.open(QIODevice::ReadOnly)) {
43 Warning() << "Failed to open the file: " << mimeMessagePath; 49 SinkWarning() << "Failed to open the file: " << mimeMessagePath;
44 return; 50 return;
45 } 51 }
46 if (!f.size()) { 52 if (!f.size()) {
47 Warning() << "The file is empty."; 53 SinkWarning() << "The file is empty.";
48 return; 54 return;
49 } 55 }
50 const auto mappedSize = qMin((qint64)8000, f.size()); 56 const auto mappedSize = qMin((qint64)8000, f.size());
51 auto mapped = f.map(0, mappedSize); 57 auto mapped = f.map(0, mappedSize);
52 if (!mapped) { 58 if (!mapped) {
53 Warning() << "Failed to map the file: " << f.errorString(); 59 SinkWarning() << "Failed to map the file: " << f.errorString();
54 return; 60 return;
55 } 61 }
56 62
@@ -85,15 +91,15 @@ QString MimeMessageMover::moveMessage(const QString &oldPath, const Sink::Applic
85 const auto filePath = directory + "/" + mail.identifier(); 91 const auto filePath = directory + "/" + mail.identifier();
86 if (oldPath != filePath) { 92 if (oldPath != filePath) {
87 if (!QDir().mkpath(directory)) { 93 if (!QDir().mkpath(directory)) {
88 Warning() << "Failed to create the directory: " << directory; 94 SinkWarning() << "Failed to create the directory: " << directory;
89 } 95 }
90 QFile::remove(filePath); 96 QFile::remove(filePath);
91 QFile origFile(oldPath); 97 QFile origFile(oldPath);
92 if (!origFile.open(QIODevice::ReadWrite)) { 98 if (!origFile.open(QIODevice::ReadWrite)) {
93 Warning() << "Failed to open the original file with write rights: " << origFile.errorString(); 99 SinkWarning() << "Failed to open the original file with write rights: " << origFile.errorString();
94 } 100 }
95 if (!origFile.rename(filePath)) { 101 if (!origFile.rename(filePath)) {
96 Warning() << "Failed to move the file from: " << oldPath << " to " << filePath << ". " << origFile.errorString(); 102 SinkWarning() << "Failed to move the file from: " << oldPath << " to " << filePath << ". " << origFile.errorString();
97 } 103 }
98 origFile.close(); 104 origFile.close();
99 return filePath; 105 return filePath;
diff --git a/common/messagequeue.cpp b/common/messagequeue.cpp
index b9f11f8..a6e44e3 100644
--- a/common/messagequeue.cpp
+++ b/common/messagequeue.cpp
@@ -3,6 +3,8 @@
3#include <QDebug> 3#include <QDebug>
4#include <log.h> 4#include <log.h>
5 5
6SINK_DEBUG_AREA("messagequeue")
7
6static KAsync::Job<void> waitForCompletion(QList<KAsync::Future<void>> &futures) 8static KAsync::Job<void> waitForCompletion(QList<KAsync::Future<void>> &futures)
7{ 9{
8 auto context = new QObject; 10 auto context = new QObject;
@@ -128,7 +130,7 @@ KAsync::Job<void> MessageQueue::dequeueBatch(int maxBatchSize, const std::functi
128 return false; 130 return false;
129 }, 131 },
130 [](const Sink::Storage::Error &error) { 132 [](const Sink::Storage::Error &error) {
131 ErrorMsg() << "Error while retrieving value" << error.message; 133 SinkError() << "Error while retrieving value" << error.message;
132 // errorHandler(Error(error.store, error.code, error.message)); 134 // errorHandler(Error(error.store, error.code, error.message));
133 }); 135 });
134 136
@@ -164,7 +166,7 @@ bool MessageQueue::isEmpty()
164 } 166 }
165 return true; 167 return true;
166 }, 168 },
167 [](const Sink::Storage::Error &error) { ErrorMsg() << "Error while checking if empty" << error.message; }); 169 [](const Sink::Storage::Error &error) { SinkError() << "Error while checking if empty" << error.message; });
168 } 170 }
169 return count == 0; 171 return count == 0;
170} 172}
diff --git a/common/modelresult.cpp b/common/modelresult.cpp
index 3778d4d..56a39ee 100644
--- a/common/modelresult.cpp
+++ b/common/modelresult.cpp
@@ -25,8 +25,7 @@
25#include "domain/folder.h" 25#include "domain/folder.h"
26#include "log.h" 26#include "log.h"
27 27
28#undef DEBUG_AREA 28SINK_DEBUG_AREA("modelresult")
29#define DEBUG_AREA "client.modelresult"
30 29
31static uint qHash(const Sink::ApplicationDomain::ApplicationDomainType &type) 30static uint qHash(const Sink::ApplicationDomain::ApplicationDomainType &type)
32{ 31{
@@ -123,7 +122,7 @@ QModelIndex ModelResult<T, Ptr>::index(int row, int column, const QModelIndex &p
123 const auto childId = list.at(row); 122 const auto childId = list.at(row);
124 return createIndex(row, column, childId); 123 return createIndex(row, column, childId);
125 } 124 }
126 Warning() << "Index not available " << row << column << parent; 125 SinkWarning() << "Index not available " << row << column << parent;
127 Q_ASSERT(false); 126 Q_ASSERT(false);
128 return QModelIndex(); 127 return QModelIndex();
129} 128}
@@ -174,7 +173,7 @@ bool ModelResult<T, Ptr>::canFetchMore(const QModelIndex &parent) const
174template <class T, class Ptr> 173template <class T, class Ptr>
175void ModelResult<T, Ptr>::fetchMore(const QModelIndex &parent) 174void ModelResult<T, Ptr>::fetchMore(const QModelIndex &parent)
176{ 175{
177 Trace() << "Fetching more: " << parent; 176 SinkTrace() << "Fetching more: " << parent;
178 fetchEntities(parent); 177 fetchEntities(parent);
179} 178}
180 179
@@ -185,7 +184,7 @@ void ModelResult<T, Ptr>::add(const Ptr &value)
185 const auto id = parentId(value); 184 const auto id = parentId(value);
186 // Ignore updates we get before the initial fetch is done 185 // Ignore updates we get before the initial fetch is done
187 if (!mEntityChildrenFetched.contains(id)) { 186 if (!mEntityChildrenFetched.contains(id)) {
188 Trace() << "Too early" << id; 187 SinkTrace() << "Too early" << id;
189 return; 188 return;
190 } 189 }
191 auto parent = createIndexFromId(id); 190 auto parent = createIndexFromId(id);
@@ -198,7 +197,7 @@ void ModelResult<T, Ptr>::add(const Ptr &value)
198 } 197 }
199 } 198 }
200 if (mEntities.contains(childId)) { 199 if (mEntities.contains(childId)) {
201 Warning() << "Entity already in model " << value->identifier(); 200 SinkWarning() << "Entity already in model " << value->identifier();
202 return; 201 return;
203 } 202 }
204 // qDebug() << "Inserting rows " << index << parent; 203 // qDebug() << "Inserting rows " << index << parent;
@@ -234,18 +233,18 @@ void ModelResult<T, Ptr>::fetchEntities(const QModelIndex &parent)
234 const auto id = getIdentifier(parent); 233 const auto id = getIdentifier(parent);
235 mEntityChildrenFetchComplete.remove(id); 234 mEntityChildrenFetchComplete.remove(id);
236 mEntityChildrenFetched.insert(id); 235 mEntityChildrenFetched.insert(id);
237 Trace() << "Loading child entities of parent " << id; 236 SinkTrace() << "Loading child entities of parent " << id;
238 if (loadEntities) { 237 if (loadEntities) {
239 loadEntities(parent.data(DomainObjectRole).template value<Ptr>()); 238 loadEntities(parent.data(DomainObjectRole).template value<Ptr>());
240 } else { 239 } else {
241 Warning() << "No way to fetch entities"; 240 SinkWarning() << "No way to fetch entities";
242 } 241 }
243} 242}
244 243
245template <class T, class Ptr> 244template <class T, class Ptr>
246void ModelResult<T, Ptr>::setFetcher(const std::function<void(const Ptr &parent)> &fetcher) 245void ModelResult<T, Ptr>::setFetcher(const std::function<void(const Ptr &parent)> &fetcher)
247{ 246{
248 Trace() << "Setting fetcher"; 247 SinkTrace() << "Setting fetcher";
249 loadEntities = fetcher; 248 loadEntities = fetcher;
250} 249}
251 250
@@ -270,7 +269,7 @@ void ModelResult<T, Ptr>::setEmitter(const typename Sink::ResultEmitter<Ptr>::Pt
270 }); 269 });
271 }); 270 });
272 emitter->onInitialResultSetComplete([this](const Ptr &parent) { 271 emitter->onInitialResultSetComplete([this](const Ptr &parent) {
273 Trace() << "Initial result set complete"; 272 SinkTrace() << "Initial result set complete";
274 const qint64 parentId = parent ? qHash(*parent) : 0; 273 const qint64 parentId = parent ? qHash(*parent) : 0;
275 const auto parentIndex = createIndexFromId(parentId); 274 const auto parentIndex = createIndexFromId(parentId);
276 mEntityChildrenFetchComplete.insert(parentId); 275 mEntityChildrenFetchComplete.insert(parentId);
diff --git a/common/notification.h b/common/notification.h
index 0eb796d..0a267e6 100644
--- a/common/notification.h
+++ b/common/notification.h
@@ -30,6 +30,19 @@ namespace Sink {
30class SINK_EXPORT Notification 30class SINK_EXPORT Notification
31{ 31{
32public: 32public:
33 enum NoticationType {
34 Shutdown,
35 Status,
36 Warning,
37 Progress,
38 Inspection,
39 RevisionUpdate
40 };
41 enum InspectionCode {
42 Success,
43 Failure
44 };
45
33 QByteArray id; 46 QByteArray id;
34 int type; 47 int type;
35 QString message; 48 QString message;
diff --git a/common/pipeline.cpp b/common/pipeline.cpp
index c6d5297..f1a4a32 100644
--- a/common/pipeline.cpp
+++ b/common/pipeline.cpp
@@ -38,8 +38,7 @@
38#include "definitions.h" 38#include "definitions.h"
39#include "bufferutils.h" 39#include "bufferutils.h"
40 40
41#undef DEBUG_AREA 41SINK_DEBUG_AREA("pipeline")
42#define DEBUG_AREA "resource.pipeline"
43 42
44namespace Sink { 43namespace Sink {
45 44
@@ -52,7 +51,7 @@ public:
52 51
53 Storage storage; 52 Storage storage;
54 Storage::Transaction transaction; 53 Storage::Transaction transaction;
55 QHash<QString, QVector<Preprocessor *>> processors; 54 QHash<QString, QVector<QSharedPointer<Preprocessor>>> processors;
56 bool revisionChanged; 55 bool revisionChanged;
57 void storeNewRevision(qint64 newRevision, const flatbuffers::FlatBufferBuilder &fbb, const QByteArray &bufferType, const QByteArray &uid); 56 void storeNewRevision(qint64 newRevision, const flatbuffers::FlatBufferBuilder &fbb, const QByteArray &bufferType, const QByteArray &uid);
58 QTime transactionTime; 57 QTime transactionTime;
@@ -63,10 +62,10 @@ public:
63 62
64void Pipeline::Private::storeNewRevision(qint64 newRevision, const flatbuffers::FlatBufferBuilder &fbb, const QByteArray &bufferType, const QByteArray &uid) 63void Pipeline::Private::storeNewRevision(qint64 newRevision, const flatbuffers::FlatBufferBuilder &fbb, const QByteArray &bufferType, const QByteArray &uid)
65{ 64{
66 Trace() << "Committing new revision: " << uid << newRevision; 65 SinkTrace() << "Committing new revision: " << uid << newRevision;
67 Storage::mainDatabase(transaction, bufferType) 66 Storage::mainDatabase(transaction, bufferType)
68 .write(Storage::assembleKey(uid, newRevision), BufferUtils::extractBuffer(fbb), 67 .write(Storage::assembleKey(uid, newRevision), BufferUtils::extractBuffer(fbb),
69 [uid, newRevision](const Storage::Error &error) { Warning() << "Failed to write entity" << uid << newRevision; }); 68 [uid, newRevision](const Storage::Error &error) { SinkWarning() << "Failed to write entity" << uid << newRevision; });
70 revisionChanged = true; 69 revisionChanged = true;
71 Storage::setMaxRevision(transaction, newRevision); 70 Storage::setMaxRevision(transaction, newRevision);
72 Storage::recordRevision(transaction, newRevision, uid, bufferType); 71 Storage::recordRevision(transaction, newRevision, uid, bufferType);
@@ -79,15 +78,17 @@ Pipeline::Pipeline(const QString &resourceName, QObject *parent) : QObject(paren
79 78
80Pipeline::~Pipeline() 79Pipeline::~Pipeline()
81{ 80{
82 delete d; 81 d->transaction = Storage::Transaction();
83} 82}
84 83
85void Pipeline::setPreprocessors(const QString &entityType, const QVector<Preprocessor *> &processors) 84void Pipeline::setPreprocessors(const QString &entityType, const QVector<Preprocessor *> &processors)
86{ 85{
86 auto &list = d->processors[entityType];
87 list.clear();
87 for (auto p : processors) { 88 for (auto p : processors) {
88 p->setup(d->resourceType, d->resourceInstanceIdentifier, this); 89 p->setup(d->resourceType, d->resourceInstanceIdentifier, this);
90 list.append(QSharedPointer<Preprocessor>(p));
89 } 91 }
90 d->processors[entityType] = processors;
91} 92}
92 93
93void Pipeline::setResourceType(const QByteArray &resourceType) 94void Pipeline::setResourceType(const QByteArray &resourceType)
@@ -105,21 +106,21 @@ void Pipeline::startTransaction()
105 if (d->transaction) { 106 if (d->transaction) {
106 return; 107 return;
107 } 108 }
108 Trace() << "Starting transaction."; 109 SinkTrace() << "Starting transaction.";
109 d->transactionTime.start(); 110 d->transactionTime.start();
110 d->transactionItemCount = 0; 111 d->transactionItemCount = 0;
111 d->transaction = std::move(storage().createTransaction(Storage::ReadWrite, [](const Sink::Storage::Error &error) { 112 d->transaction = storage().createTransaction(Storage::ReadWrite, [](const Sink::Storage::Error &error) {
112 Warning() << error.message; 113 SinkWarning() << error.message;
113 })); 114 });
114 115
115 //FIXME this is a temporary measure to recover from a failure to open the named databases correctly. 116 //FIXME this is a temporary measure to recover from a failure to open the named databases correctly.
116 //Once the actual problem is fixed it will be enough to simply crash if we open the wrong database (which we check in openDatabase already). 117 //Once the actual problem is fixed it will be enough to simply crash if we open the wrong database (which we check in openDatabase already).
117 //It seems like the validateNamedDatabase calls actually stops the mdb_put failures during sync... 118 //It seems like the validateNamedDatabase calls actually stops the mdb_put failures during sync...
118 if (d->storage.exists()) { 119 if (d->storage.exists()) {
119 while (!d->transaction.validateNamedDatabases()) { 120 while (!d->transaction.validateNamedDatabases()) {
120 Warning() << "Opened an invalid transaction!!!!!!"; 121 SinkWarning() << "Opened an invalid transaction!!!!!!";
121 d->transaction = std::move(storage().createTransaction(Storage::ReadWrite, [](const Sink::Storage::Error &error) { 122 d->transaction = std::move(storage().createTransaction(Storage::ReadWrite, [](const Sink::Storage::Error &error) {
122 Warning() << error.message; 123 SinkWarning() << error.message;
123 })); 124 }));
124 } 125 }
125 } 126 }
@@ -139,7 +140,7 @@ void Pipeline::commit()
139 } 140 }
140 const auto revision = Storage::maxRevision(d->transaction); 141 const auto revision = Storage::maxRevision(d->transaction);
141 const auto elapsed = d->transactionTime.elapsed(); 142 const auto elapsed = d->transactionTime.elapsed();
142 Log() << "Committing revision: " << revision << ":" << d->transactionItemCount << " items in: " << Log::TraceTime(elapsed) << " " 143 SinkLog() << "Committing revision: " << revision << ":" << d->transactionItemCount << " items in: " << Log::TraceTime(elapsed) << " "
143 << (double)elapsed / (double)qMax(d->transactionItemCount, 1) << "[ms/item]"; 144 << (double)elapsed / (double)qMax(d->transactionItemCount, 1) << "[ms/item]";
144 if (d->transaction) { 145 if (d->transaction) {
145 d->transaction.commit(); 146 d->transaction.commit();
@@ -168,7 +169,7 @@ KAsync::Job<qint64> Pipeline::newEntity(void const *command, size_t size)
168 { 169 {
169 flatbuffers::Verifier verifyer(reinterpret_cast<const uint8_t *>(command), size); 170 flatbuffers::Verifier verifyer(reinterpret_cast<const uint8_t *>(command), size);
170 if (!Commands::VerifyCreateEntityBuffer(verifyer)) { 171 if (!Commands::VerifyCreateEntityBuffer(verifyer)) {
171 Warning() << "invalid buffer, not a create entity buffer"; 172 SinkWarning() << "invalid buffer, not a create entity buffer";
172 return KAsync::error<qint64>(0); 173 return KAsync::error<qint64>(0);
173 } 174 }
174 } 175 }
@@ -180,7 +181,7 @@ KAsync::Job<qint64> Pipeline::newEntity(void const *command, size_t size)
180 if (createEntity->entityId()) { 181 if (createEntity->entityId()) {
181 key = QByteArray(reinterpret_cast<char const *>(createEntity->entityId()->Data()), createEntity->entityId()->size()); 182 key = QByteArray(reinterpret_cast<char const *>(createEntity->entityId()->Data()), createEntity->entityId()->size());
182 if (Storage::mainDatabase(d->transaction, bufferType).contains(key)) { 183 if (Storage::mainDatabase(d->transaction, bufferType).contains(key)) {
183 ErrorMsg() << "An entity with this id already exists: " << key; 184 SinkError() << "An entity with this id already exists: " << key;
184 return KAsync::error<qint64>(0); 185 return KAsync::error<qint64>(0);
185 } 186 }
186 } 187 }
@@ -188,31 +189,31 @@ KAsync::Job<qint64> Pipeline::newEntity(void const *command, size_t size)
188 if (key.isEmpty()) { 189 if (key.isEmpty()) {
189 key = Sink::Storage::generateUid(); 190 key = Sink::Storage::generateUid();
190 } 191 }
191 Log() << "New Entity. Type: " << bufferType << "uid: "<< key << " replayToSource: " << replayToSource; 192 SinkLog() << "New Entity. Type: " << bufferType << "uid: "<< key << " replayToSource: " << replayToSource;
192 Q_ASSERT(!key.isEmpty()); 193 Q_ASSERT(!key.isEmpty());
193 194
194 { 195 {
195 flatbuffers::Verifier verifyer(reinterpret_cast<const uint8_t *>(createEntity->delta()->Data()), createEntity->delta()->size()); 196 flatbuffers::Verifier verifyer(reinterpret_cast<const uint8_t *>(createEntity->delta()->Data()), createEntity->delta()->size());
196 if (!VerifyEntityBuffer(verifyer)) { 197 if (!VerifyEntityBuffer(verifyer)) {
197 Warning() << "invalid buffer, not an entity buffer"; 198 SinkWarning() << "invalid buffer, not an entity buffer";
198 return KAsync::error<qint64>(0); 199 return KAsync::error<qint64>(0);
199 } 200 }
200 } 201 }
201 auto entity = GetEntity(createEntity->delta()->Data()); 202 auto entity = GetEntity(createEntity->delta()->Data());
202 if (!entity->resource()->size() && !entity->local()->size()) { 203 if (!entity->resource()->size() && !entity->local()->size()) {
203 Warning() << "No local and no resource buffer while trying to create entity."; 204 SinkWarning() << "No local and no resource buffer while trying to create entity.";
204 return KAsync::error<qint64>(0); 205 return KAsync::error<qint64>(0);
205 } 206 }
206 207
207 auto adaptorFactory = Sink::AdaptorFactoryRegistry::instance().getFactory(d->resourceType, bufferType); 208 auto adaptorFactory = Sink::AdaptorFactoryRegistry::instance().getFactory(d->resourceType, bufferType);
208 if (!adaptorFactory) { 209 if (!adaptorFactory) {
209 Warning() << "no adaptor factory for type " << bufferType; 210 SinkWarning() << "no adaptor factory for type " << bufferType;
210 return KAsync::error<qint64>(0); 211 return KAsync::error<qint64>(0);
211 } 212 }
212 213
213 auto adaptor = adaptorFactory->createAdaptor(*entity); 214 auto adaptor = adaptorFactory->createAdaptor(*entity);
214 auto memoryAdaptor = QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create(*(adaptor), adaptor->availableProperties()); 215 auto memoryAdaptor = QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create(*(adaptor), adaptor->availableProperties());
215 for (auto processor : d->processors[bufferType]) { 216 foreach (const auto &processor, d->processors[bufferType]) {
216 processor->newEntity(key, Storage::maxRevision(d->transaction) + 1, *memoryAdaptor, d->transaction); 217 processor->newEntity(key, Storage::maxRevision(d->transaction) + 1, *memoryAdaptor, d->transaction);
217 } 218 }
218 //The maxRevision may have changed meanwhile if the entity created sub-entities 219 //The maxRevision may have changed meanwhile if the entity created sub-entities
@@ -242,7 +243,7 @@ KAsync::Job<qint64> Pipeline::modifiedEntity(void const *command, size_t size)
242 { 243 {
243 flatbuffers::Verifier verifyer(reinterpret_cast<const uint8_t *>(command), size); 244 flatbuffers::Verifier verifyer(reinterpret_cast<const uint8_t *>(command), size);
244 if (!Commands::VerifyModifyEntityBuffer(verifyer)) { 245 if (!Commands::VerifyModifyEntityBuffer(verifyer)) {
245 Warning() << "invalid buffer, not a modify entity buffer"; 246 SinkWarning() << "invalid buffer, not a modify entity buffer";
246 return KAsync::error<qint64>(0); 247 return KAsync::error<qint64>(0);
247 } 248 }
248 } 249 }
@@ -252,21 +253,21 @@ KAsync::Job<qint64> Pipeline::modifiedEntity(void const *command, size_t size)
252 if (modifyEntity->modifiedProperties()) { 253 if (modifyEntity->modifiedProperties()) {
253 changeset = BufferUtils::fromVector(*modifyEntity->modifiedProperties()); 254 changeset = BufferUtils::fromVector(*modifyEntity->modifiedProperties());
254 } else { 255 } else {
255 Warning() << "No changeset available"; 256 SinkWarning() << "No changeset available";
256 } 257 }
257 const qint64 baseRevision = modifyEntity->revision(); 258 const qint64 baseRevision = modifyEntity->revision();
258 const bool replayToSource = modifyEntity->replayToSource(); 259 const bool replayToSource = modifyEntity->replayToSource();
259 const QByteArray bufferType = QByteArray(reinterpret_cast<char const *>(modifyEntity->domainType()->Data()), modifyEntity->domainType()->size()); 260 const QByteArray bufferType = QByteArray(reinterpret_cast<char const *>(modifyEntity->domainType()->Data()), modifyEntity->domainType()->size());
260 const QByteArray key = QByteArray(reinterpret_cast<char const *>(modifyEntity->entityId()->Data()), modifyEntity->entityId()->size()); 261 const QByteArray key = QByteArray(reinterpret_cast<char const *>(modifyEntity->entityId()->Data()), modifyEntity->entityId()->size());
261 Log() << "Modified Entity. Type: " << bufferType << "uid: "<< key << " replayToSource: " << replayToSource; 262 SinkLog() << "Modified Entity. Type: " << bufferType << "uid: "<< key << " replayToSource: " << replayToSource;
262 if (bufferType.isEmpty() || key.isEmpty()) { 263 if (bufferType.isEmpty() || key.isEmpty()) {
263 Warning() << "entity type or key " << bufferType << key; 264 SinkWarning() << "entity type or key " << bufferType << key;
264 return KAsync::error<qint64>(0); 265 return KAsync::error<qint64>(0);
265 } 266 }
266 { 267 {
267 flatbuffers::Verifier verifyer(reinterpret_cast<const uint8_t *>(modifyEntity->delta()->Data()), modifyEntity->delta()->size()); 268 flatbuffers::Verifier verifyer(reinterpret_cast<const uint8_t *>(modifyEntity->delta()->Data()), modifyEntity->delta()->size());
268 if (!VerifyEntityBuffer(verifyer)) { 269 if (!VerifyEntityBuffer(verifyer)) {
269 Warning() << "invalid buffer, not an entity buffer"; 270 SinkWarning() << "invalid buffer, not an entity buffer";
270 return KAsync::error<qint64>(0); 271 return KAsync::error<qint64>(0);
271 } 272 }
272 } 273 }
@@ -274,7 +275,7 @@ KAsync::Job<qint64> Pipeline::modifiedEntity(void const *command, size_t size)
274 // TODO use only readPropertyMapper and writePropertyMapper 275 // TODO use only readPropertyMapper and writePropertyMapper
275 auto adaptorFactory = Sink::AdaptorFactoryRegistry::instance().getFactory(d->resourceType, bufferType); 276 auto adaptorFactory = Sink::AdaptorFactoryRegistry::instance().getFactory(d->resourceType, bufferType);
276 if (!adaptorFactory) { 277 if (!adaptorFactory) {
277 Warning() << "no adaptor factory for type " << bufferType; 278 SinkWarning() << "no adaptor factory for type " << bufferType;
278 return KAsync::error<qint64>(0); 279 return KAsync::error<qint64>(0);
279 } 280 }
280 281
@@ -288,16 +289,16 @@ KAsync::Job<qint64> Pipeline::modifiedEntity(void const *command, size_t size)
288 [&current, adaptorFactory](const QByteArray &key, const QByteArray &data) -> bool { 289 [&current, adaptorFactory](const QByteArray &key, const QByteArray &data) -> bool {
289 EntityBuffer buffer(const_cast<const char *>(data.data()), data.size()); 290 EntityBuffer buffer(const_cast<const char *>(data.data()), data.size());
290 if (!buffer.isValid()) { 291 if (!buffer.isValid()) {
291 Warning() << "Read invalid buffer from disk"; 292 SinkWarning() << "Read invalid buffer from disk";
292 } else { 293 } else {
293 current = adaptorFactory->createAdaptor(buffer.entity()); 294 current = adaptorFactory->createAdaptor(buffer.entity());
294 } 295 }
295 return false; 296 return false;
296 }, 297 },
297 [baseRevision](const Storage::Error &error) { Warning() << "Failed to read old revision from storage: " << error.message << "Revision: " << baseRevision; }); 298 [baseRevision](const Storage::Error &error) { SinkWarning() << "Failed to read old revision from storage: " << error.message << "Revision: " << baseRevision; });
298 299
299 if (!current) { 300 if (!current) {
300 Warning() << "Failed to read local value " << key; 301 SinkWarning() << "Failed to read local value " << key;
301 return KAsync::error<qint64>(0); 302 return KAsync::error<qint64>(0);
302 } 303 }
303 304
@@ -305,7 +306,7 @@ KAsync::Job<qint64> Pipeline::modifiedEntity(void const *command, size_t size)
305 306
306 // Apply diff 307 // Apply diff
307 // FIXME only apply the properties that are available in the buffer 308 // FIXME only apply the properties that are available in the buffer
308 Trace() << "Applying changed properties: " << changeset; 309 SinkTrace() << "Applying changed properties: " << changeset;
309 for (const auto &property : changeset) { 310 for (const auto &property : changeset) {
310 const auto value = diff->getProperty(property); 311 const auto value = diff->getProperty(property);
311 if (value.isValid()) { 312 if (value.isValid()) {
@@ -321,7 +322,7 @@ KAsync::Job<qint64> Pipeline::modifiedEntity(void const *command, size_t size)
321 } 322 }
322 323
323 newAdaptor->resetChangedProperties(); 324 newAdaptor->resetChangedProperties();
324 for (auto processor : d->processors[bufferType]) { 325 foreach (const auto &processor, d->processors[bufferType]) {
325 processor->modifiedEntity(key, Storage::maxRevision(d->transaction) + 1, *current, *newAdaptor, d->transaction); 326 processor->modifiedEntity(key, Storage::maxRevision(d->transaction) + 1, *current, *newAdaptor, d->transaction);
326 } 327 }
327 //The maxRevision may have changed meanwhile if the entity created sub-entities 328 //The maxRevision may have changed meanwhile if the entity created sub-entities
@@ -355,7 +356,7 @@ KAsync::Job<qint64> Pipeline::deletedEntity(void const *command, size_t size)
355 { 356 {
356 flatbuffers::Verifier verifyer(reinterpret_cast<const uint8_t *>(command), size); 357 flatbuffers::Verifier verifyer(reinterpret_cast<const uint8_t *>(command), size);
357 if (!Commands::VerifyDeleteEntityBuffer(verifyer)) { 358 if (!Commands::VerifyDeleteEntityBuffer(verifyer)) {
358 Warning() << "invalid buffer, not a delete entity buffer"; 359 SinkWarning() << "invalid buffer, not a delete entity buffer";
359 return KAsync::error<qint64>(0); 360 return KAsync::error<qint64>(0);
360 } 361 }
361 } 362 }
@@ -364,7 +365,7 @@ KAsync::Job<qint64> Pipeline::deletedEntity(void const *command, size_t size)
364 const bool replayToSource = deleteEntity->replayToSource(); 365 const bool replayToSource = deleteEntity->replayToSource();
365 const QByteArray bufferType = QByteArray(reinterpret_cast<char const *>(deleteEntity->domainType()->Data()), deleteEntity->domainType()->size()); 366 const QByteArray bufferType = QByteArray(reinterpret_cast<char const *>(deleteEntity->domainType()->Data()), deleteEntity->domainType()->size());
366 const QByteArray key = QByteArray(reinterpret_cast<char const *>(deleteEntity->entityId()->Data()), deleteEntity->entityId()->size()); 367 const QByteArray key = QByteArray(reinterpret_cast<char const *>(deleteEntity->entityId()->Data()), deleteEntity->entityId()->size());
367 Log() << "Deleted Entity. Type: " << bufferType << "uid: "<< key << " replayToSource: " << replayToSource; 368 SinkLog() << "Deleted Entity. Type: " << bufferType << "uid: "<< key << " replayToSource: " << replayToSource;
368 369
369 bool found = false; 370 bool found = false;
370 bool alreadyRemoved = false; 371 bool alreadyRemoved = false;
@@ -381,14 +382,14 @@ KAsync::Job<qint64> Pipeline::deletedEntity(void const *command, size_t size)
381 } 382 }
382 return false; 383 return false;
383 }, 384 },
384 [](const Storage::Error &error) { Warning() << "Failed to read old revision from storage: " << error.message; }); 385 [](const Storage::Error &error) { SinkWarning() << "Failed to read old revision from storage: " << error.message; });
385 386
386 if (!found) { 387 if (!found) {
387 Warning() << "Failed to find entity " << key; 388 SinkWarning() << "Failed to find entity " << key;
388 return KAsync::error<qint64>(0); 389 return KAsync::error<qint64>(0);
389 } 390 }
390 if (alreadyRemoved) { 391 if (alreadyRemoved) {
391 Warning() << "Entity is already removed " << key; 392 SinkWarning() << "Entity is already removed " << key;
392 return KAsync::error<qint64>(0); 393 return KAsync::error<qint64>(0);
393 } 394 }
394 395
@@ -408,7 +409,7 @@ KAsync::Job<qint64> Pipeline::deletedEntity(void const *command, size_t size)
408 409
409 auto adaptorFactory = Sink::AdaptorFactoryRegistry::instance().getFactory(d->resourceType, bufferType); 410 auto adaptorFactory = Sink::AdaptorFactoryRegistry::instance().getFactory(d->resourceType, bufferType);
410 if (!adaptorFactory) { 411 if (!adaptorFactory) {
411 Warning() << "no adaptor factory for type " << bufferType; 412 SinkWarning() << "no adaptor factory for type " << bufferType;
412 return KAsync::error<qint64>(0); 413 return KAsync::error<qint64>(0);
413 } 414 }
414 415
@@ -418,17 +419,17 @@ KAsync::Job<qint64> Pipeline::deletedEntity(void const *command, size_t size)
418 [this, bufferType, newRevision, adaptorFactory, key, &current](const QByteArray &, const QByteArray &data) -> bool { 419 [this, bufferType, newRevision, adaptorFactory, key, &current](const QByteArray &, const QByteArray &data) -> bool {
419 EntityBuffer buffer(const_cast<const char *>(data.data()), data.size()); 420 EntityBuffer buffer(const_cast<const char *>(data.data()), data.size());
420 if (!buffer.isValid()) { 421 if (!buffer.isValid()) {
421 Warning() << "Read invalid buffer from disk"; 422 SinkWarning() << "Read invalid buffer from disk";
422 } else { 423 } else {
423 current = adaptorFactory->createAdaptor(buffer.entity()); 424 current = adaptorFactory->createAdaptor(buffer.entity());
424 } 425 }
425 return false; 426 return false;
426 }, 427 },
427 [this](const Storage::Error &error) { ErrorMsg() << "Failed to find value in pipeline: " << error.message; }); 428 [this](const Storage::Error &error) { SinkError() << "Failed to find value in pipeline: " << error.message; });
428 429
429 d->storeNewRevision(newRevision, fbb, bufferType, key); 430 d->storeNewRevision(newRevision, fbb, bufferType, key);
430 431
431 for (auto processor : d->processors[bufferType]) { 432 foreach (const auto &processor, d->processors[bufferType]) {
432 processor->deletedEntity(key, newRevision, *current, d->transaction); 433 processor->deletedEntity(key, newRevision, *current, d->transaction);
433 } 434 }
434 435
@@ -440,13 +441,13 @@ void Pipeline::cleanupRevision(qint64 revision)
440 d->revisionChanged = true; 441 d->revisionChanged = true;
441 const auto uid = Storage::getUidFromRevision(d->transaction, revision); 442 const auto uid = Storage::getUidFromRevision(d->transaction, revision);
442 const auto bufferType = Storage::getTypeFromRevision(d->transaction, revision); 443 const auto bufferType = Storage::getTypeFromRevision(d->transaction, revision);
443 Trace() << "Cleaning up revision " << revision << uid << bufferType; 444 SinkTrace() << "Cleaning up revision " << revision << uid << bufferType;
444 Storage::mainDatabase(d->transaction, bufferType) 445 Storage::mainDatabase(d->transaction, bufferType)
445 .scan(uid, 446 .scan(uid,
446 [&](const QByteArray &key, const QByteArray &data) -> bool { 447 [&](const QByteArray &key, const QByteArray &data) -> bool {
447 EntityBuffer buffer(const_cast<const char *>(data.data()), data.size()); 448 EntityBuffer buffer(const_cast<const char *>(data.data()), data.size());
448 if (!buffer.isValid()) { 449 if (!buffer.isValid()) {
449 Warning() << "Read invalid buffer from disk"; 450 SinkWarning() << "Read invalid buffer from disk";
450 } else { 451 } else {
451 const auto metadata = flatbuffers::GetRoot<Metadata>(buffer.metadataBuffer()); 452 const auto metadata = flatbuffers::GetRoot<Metadata>(buffer.metadataBuffer());
452 const qint64 rev = metadata->revision(); 453 const qint64 rev = metadata->revision();
@@ -459,7 +460,7 @@ void Pipeline::cleanupRevision(qint64 revision)
459 460
460 return true; 461 return true;
461 }, 462 },
462 [](const Storage::Error &error) { Warning() << "Error while reading: " << error.message; }, true); 463 [](const Storage::Error &error) { SinkWarning() << "Error while reading: " << error.message; }, true);
463 Storage::setCleanedUpRevision(d->transaction, revision); 464 Storage::setCleanedUpRevision(d->transaction, revision);
464} 465}
465 466
@@ -481,7 +482,6 @@ Preprocessor::Preprocessor() : d(new Preprocessor::Private)
481 482
482Preprocessor::~Preprocessor() 483Preprocessor::~Preprocessor()
483{ 484{
484 delete d;
485} 485}
486 486
487void Preprocessor::setup(const QByteArray &resourceType, const QByteArray &resourceInstanceIdentifier, Pipeline *pipeline) 487void Preprocessor::setup(const QByteArray &resourceType, const QByteArray &resourceInstanceIdentifier, Pipeline *pipeline)
diff --git a/common/pipeline.h b/common/pipeline.h
index d04d795..ef89cf0 100644
--- a/common/pipeline.h
+++ b/common/pipeline.h
@@ -72,7 +72,7 @@ signals:
72 72
73private: 73private:
74 class Private; 74 class Private;
75 Private *const d; 75 const std::unique_ptr<Private> d;
76}; 76};
77 77
78class SINK_EXPORT Preprocessor 78class SINK_EXPORT Preprocessor
@@ -103,7 +103,7 @@ protected:
103private: 103private:
104 friend class Pipeline; 104 friend class Pipeline;
105 class Private; 105 class Private;
106 Private *const d; 106 const std::unique_ptr<Private> d;
107}; 107};
108 108
109template<typename DomainType> 109template<typename DomainType>
diff --git a/common/queryrunner.cpp b/common/queryrunner.cpp
index 78a4b94..2e2e96d 100644
--- a/common/queryrunner.cpp
+++ b/common/queryrunner.cpp
@@ -29,8 +29,7 @@
29#include "asyncutils.h" 29#include "asyncutils.h"
30#include "entityreader.h" 30#include "entityreader.h"
31 31
32#undef DEBUG_AREA 32SINK_DEBUG_AREA("queryrunner")
33#define DEBUG_AREA "client.queryrunner"
34 33
35using namespace Sink; 34using namespace Sink;
36 35
@@ -43,6 +42,8 @@ using namespace Sink;
43template <typename DomainType> 42template <typename DomainType>
44class QueryWorker : public QObject 43class QueryWorker : public QObject
45{ 44{
45 // SINK_DEBUG_COMPONENT(mResourceInstanceIdentifier, mId)
46 SINK_DEBUG_COMPONENT(mResourceInstanceIdentifier)
46public: 47public:
47 QueryWorker(const Sink::Query &query, const QByteArray &instanceIdentifier, const DomainTypeAdaptorFactoryInterface::Ptr &, const QByteArray &bufferType, 48 QueryWorker(const Sink::Query &query, const QByteArray &instanceIdentifier, const DomainTypeAdaptorFactoryInterface::Ptr &, const QByteArray &bufferType,
48 const QueryRunnerBase::ResultTransformation &transformation); 49 const QueryRunnerBase::ResultTransformation &transformation);
@@ -61,22 +62,19 @@ private:
61 QByteArray mId; //Used for identification in debug output 62 QByteArray mId; //Used for identification in debug output
62}; 63};
63 64
64#undef Trace
65#define Trace() Trace_area(DEBUG_AREA)
66
67template <class DomainType> 65template <class DomainType>
68QueryRunner<DomainType>::QueryRunner(const Sink::Query &query, const Sink::ResourceAccessInterface::Ptr &resourceAccess, const QByteArray &instanceIdentifier, 66QueryRunner<DomainType>::QueryRunner(const Sink::Query &query, const Sink::ResourceAccessInterface::Ptr &resourceAccess, const QByteArray &instanceIdentifier,
69 const DomainTypeAdaptorFactoryInterface::Ptr &factory, const QByteArray &bufferType) 67 const DomainTypeAdaptorFactoryInterface::Ptr &factory, const QByteArray &bufferType)
70 : QueryRunnerBase(), mResourceAccess(resourceAccess), mResultProvider(new ResultProvider<typename DomainType::Ptr>), mBatchSize(query.limit) 68 : QueryRunnerBase(), mResourceAccess(resourceAccess), mResultProvider(new ResultProvider<typename DomainType::Ptr>), mBatchSize(query.limit)
71{ 69{
72 Trace() << "Starting query"; 70 SinkTrace() << "Starting query";
73 if (query.limit && query.sortProperty.isEmpty()) { 71 if (query.limit && query.sortProperty.isEmpty()) {
74 Warning() << "A limited query without sorting is typically a bad idea."; 72 SinkWarning() << "A limited query without sorting is typically a bad idea.";
75 } 73 }
76 // We delegate loading of initial data to the result provider, so it can decide for itself what it needs to load. 74 // We delegate loading of initial data to the result provider, so it can decide for itself what it needs to load.
77 mResultProvider->setFetcher([=](const typename DomainType::Ptr &parent) { 75 mResultProvider->setFetcher([=](const typename DomainType::Ptr &parent) {
78 const QByteArray parentId = parent ? parent->identifier() : QByteArray(); 76 const QByteArray parentId = parent ? parent->identifier() : QByteArray();
79 Trace() << "Running fetcher. Offset: " << mOffset[parentId] << " Batchsize: " << mBatchSize; 77 SinkTrace() << "Running fetcher. Offset: " << mOffset[parentId] << " Batchsize: " << mBatchSize;
80 auto resultProvider = mResultProvider; 78 auto resultProvider = mResultProvider;
81 if (query.synchronousQuery) { 79 if (query.synchronousQuery) {
82 QueryWorker<DomainType> worker(query, instanceIdentifier, factory, bufferType, mResultTransformation); 80 QueryWorker<DomainType> worker(query, instanceIdentifier, factory, bufferType, mResultTransformation);
@@ -123,12 +121,15 @@ QueryRunner<DomainType>::QueryRunner(const Sink::Query &query, const Sink::Resou
123 mResourceAccess->open(); 121 mResourceAccess->open();
124 QObject::connect(mResourceAccess.data(), &Sink::ResourceAccess::revisionChanged, this, &QueryRunner::revisionChanged); 122 QObject::connect(mResourceAccess.data(), &Sink::ResourceAccess::revisionChanged, this, &QueryRunner::revisionChanged);
125 } 123 }
124 mResultProvider->onDone([this]() {
125 delete this;
126 });
126} 127}
127 128
128template <class DomainType> 129template <class DomainType>
129QueryRunner<DomainType>::~QueryRunner() 130QueryRunner<DomainType>::~QueryRunner()
130{ 131{
131 Trace() << "Stopped query"; 132 SinkTrace() << "Stopped query";
132} 133}
133 134
134template <class DomainType> 135template <class DomainType>
@@ -144,21 +145,18 @@ typename Sink::ResultEmitter<typename DomainType::Ptr>::Ptr QueryRunner<DomainTy
144} 145}
145 146
146 147
147#undef Trace
148#define Trace() Trace_area("client.queryrunner." + mId)
149
150template <class DomainType> 148template <class DomainType>
151QueryWorker<DomainType>::QueryWorker(const Sink::Query &query, const QByteArray &instanceIdentifier, const DomainTypeAdaptorFactoryInterface::Ptr &factory, 149QueryWorker<DomainType>::QueryWorker(const Sink::Query &query, const QByteArray &instanceIdentifier, const DomainTypeAdaptorFactoryInterface::Ptr &factory,
152 const QByteArray &bufferType, const QueryRunnerBase::ResultTransformation &transformation) 150 const QByteArray &bufferType, const QueryRunnerBase::ResultTransformation &transformation)
153 : QObject(), mResultTransformation(transformation), mDomainTypeAdaptorFactory(factory), mResourceInstanceIdentifier(instanceIdentifier), mId(QUuid::createUuid().toByteArray()) 151 : QObject(), mResultTransformation(transformation), mDomainTypeAdaptorFactory(factory), mResourceInstanceIdentifier(instanceIdentifier), mId(QUuid::createUuid().toByteArray())
154{ 152{
155 Trace() << "Starting query worker"; 153 SinkTrace() << "Starting query worker";
156} 154}
157 155
158template <class DomainType> 156template <class DomainType>
159QueryWorker<DomainType>::~QueryWorker() 157QueryWorker<DomainType>::~QueryWorker()
160{ 158{
161 Trace() << "Stopped query worker"; 159 SinkTrace() << "Stopped query worker";
162} 160}
163 161
164template <class DomainType> 162template <class DomainType>
@@ -171,15 +169,15 @@ std::function<bool(const typename DomainType::Ptr &, Sink::Operation)> QueryWork
171 } 169 }
172 switch (operation) { 170 switch (operation) {
173 case Sink::Operation_Creation: 171 case Sink::Operation_Creation:
174 // Trace() << "Got creation"; 172 // SinkTrace() << "Got creation";
175 resultProvider.add(valueCopy); 173 resultProvider.add(valueCopy);
176 break; 174 break;
177 case Sink::Operation_Modification: 175 case Sink::Operation_Modification:
178 // Trace() << "Got modification"; 176 // SinkTrace() << "Got modification";
179 resultProvider.modify(valueCopy); 177 resultProvider.modify(valueCopy);
180 break; 178 break;
181 case Sink::Operation_Removal: 179 case Sink::Operation_Removal:
182 // Trace() << "Got removal"; 180 // SinkTrace() << "Got removal";
183 resultProvider.remove(valueCopy); 181 resultProvider.remove(valueCopy);
184 break; 182 break;
185 } 183 }
@@ -197,7 +195,7 @@ QPair<qint64, qint64> QueryWorker<DomainType>::executeIncrementalQuery(const Sin
197 195
198 Sink::EntityReader<DomainType> reader(*mDomainTypeAdaptorFactory, mResourceInstanceIdentifier, transaction); 196 Sink::EntityReader<DomainType> reader(*mDomainTypeAdaptorFactory, mResourceInstanceIdentifier, transaction);
199 auto revisionAndReplayedEntities = reader.executeIncrementalQuery(query, resultProvider.revision(), resultProviderCallback(query, resultProvider)); 197 auto revisionAndReplayedEntities = reader.executeIncrementalQuery(query, resultProvider.revision(), resultProviderCallback(query, resultProvider));
200 Trace() << "Incremental query took: " << Log::TraceTime(time.elapsed()); 198 SinkTrace() << "Incremental query took: " << Log::TraceTime(time.elapsed());
201 return revisionAndReplayedEntities; 199 return revisionAndReplayedEntities;
202} 200}
203 201
@@ -209,10 +207,10 @@ Storage::Transaction QueryWorker<DomainType>::getTransaction()
209 Sink::Storage storage(Sink::storageLocation(), mResourceInstanceIdentifier); 207 Sink::Storage storage(Sink::storageLocation(), mResourceInstanceIdentifier);
210 if (!storage.exists()) { 208 if (!storage.exists()) {
211 //This is not an error if the resource wasn't started before 209 //This is not an error if the resource wasn't started before
212 Log() << "Store doesn't exist: " << mResourceInstanceIdentifier; 210 SinkLog() << "Store doesn't exist: " << mResourceInstanceIdentifier;
213 return Sink::Storage::Transaction(); 211 return Sink::Storage::Transaction();
214 } 212 }
215 storage.setDefaultErrorHandler([](const Sink::Storage::Error &error) { Warning() << "Error during query: " << error.store << error.message; }); 213 storage.setDefaultErrorHandler([this](const Sink::Storage::Error &error) { SinkWarning() << "Error during query: " << error.store << error.message; });
216 transaction = storage.createTransaction(Sink::Storage::ReadOnly); 214 transaction = storage.createTransaction(Sink::Storage::ReadOnly);
217 } 215 }
218 216
@@ -235,10 +233,10 @@ QPair<qint64, qint64> QueryWorker<DomainType>::executeInitialQuery(
235 auto modifiedQuery = query; 233 auto modifiedQuery = query;
236 if (!query.parentProperty.isEmpty()) { 234 if (!query.parentProperty.isEmpty()) {
237 if (parent) { 235 if (parent) {
238 Trace() << "Running initial query for parent:" << parent->identifier(); 236 SinkTrace() << "Running initial query for parent:" << parent->identifier();
239 modifiedQuery.propertyFilter.insert(query.parentProperty, Query::Comparator(parent->identifier())); 237 modifiedQuery.propertyFilter.insert(query.parentProperty, Query::Comparator(parent->identifier()));
240 } else { 238 } else {
241 Trace() << "Running initial query for toplevel"; 239 SinkTrace() << "Running initial query for toplevel";
242 modifiedQuery.propertyFilter.insert(query.parentProperty, Query::Comparator(QVariant())); 240 modifiedQuery.propertyFilter.insert(query.parentProperty, Query::Comparator(QVariant()));
243 } 241 }
244 } 242 }
@@ -247,7 +245,7 @@ QPair<qint64, qint64> QueryWorker<DomainType>::executeInitialQuery(
247 245
248 Sink::EntityReader<DomainType> reader(*mDomainTypeAdaptorFactory, mResourceInstanceIdentifier, transaction); 246 Sink::EntityReader<DomainType> reader(*mDomainTypeAdaptorFactory, mResourceInstanceIdentifier, transaction);
249 auto revisionAndReplayedEntities = reader.executeInitialQuery(modifiedQuery, offset, batchsize, resultProviderCallback(query, resultProvider)); 247 auto revisionAndReplayedEntities = reader.executeInitialQuery(modifiedQuery, offset, batchsize, resultProviderCallback(query, resultProvider));
250 Trace() << "Initial query took: " << Log::TraceTime(time.elapsed()); 248 SinkTrace() << "Initial query took: " << Log::TraceTime(time.elapsed());
251 return revisionAndReplayedEntities; 249 return revisionAndReplayedEntities;
252} 250}
253 251
diff --git a/common/queryrunner.h b/common/queryrunner.h
index e6d5a54..155528e 100644
--- a/common/queryrunner.h
+++ b/common/queryrunner.h
@@ -32,6 +32,8 @@
32class QueryRunnerBase : public QObject 32class QueryRunnerBase : public QObject
33{ 33{
34 Q_OBJECT 34 Q_OBJECT
35protected:
36 SINK_DEBUG_AREA("queryrunner")
35public: 37public:
36 typedef std::function<void(Sink::ApplicationDomain::ApplicationDomainType &domainObject)> ResultTransformation; 38 typedef std::function<void(Sink::ApplicationDomain::ApplicationDomainType &domainObject)> ResultTransformation;
37 39
@@ -52,7 +54,7 @@ protected slots:
52 */ 54 */
53 void revisionChanged(qint64 newRevision) 55 void revisionChanged(qint64 newRevision)
54 { 56 {
55 Trace() << "New revision: " << newRevision; 57 SinkTrace() << "New revision: " << newRevision;
56 run().exec(); 58 run().exec();
57 } 59 }
58 60
diff --git a/common/remoteidmap.cpp b/common/remoteidmap.cpp
index bbcd641..20a054d 100644
--- a/common/remoteidmap.cpp
+++ b/common/remoteidmap.cpp
@@ -25,6 +25,8 @@
25 25
26using namespace Sink; 26using namespace Sink;
27 27
28SINK_DEBUG_AREA("remoteidmap")
29
28RemoteIdMap::RemoteIdMap(Sink::Storage::Transaction &transaction) 30RemoteIdMap::RemoteIdMap(Sink::Storage::Transaction &transaction)
29 : mTransaction(transaction) 31 : mTransaction(transaction)
30{ 32{
@@ -67,7 +69,7 @@ QByteArray RemoteIdMap::resolveLocalId(const QByteArray &bufferType, const QByte
67{ 69{
68 QByteArray remoteId = Index("localid.mapping." + bufferType, mTransaction).lookup(localId); 70 QByteArray remoteId = Index("localid.mapping." + bufferType, mTransaction).lookup(localId);
69 if (remoteId.isEmpty()) { 71 if (remoteId.isEmpty()) {
70 Warning() << "Couldn't find the remote id for " << localId; 72 SinkWarning() << "Couldn't find the remote id for " << localId;
71 return QByteArray(); 73 return QByteArray();
72 } 74 }
73 return remoteId; 75 return remoteId;
diff --git a/common/resource.h b/common/resource.h
index d6c3c5f..1c35838 100644
--- a/common/resource.h
+++ b/common/resource.h
@@ -91,4 +91,4 @@ private:
91 91
92} // namespace Sink 92} // namespace Sink
93 93
94Q_DECLARE_INTERFACE(Sink::ResourceFactory, "org.kde.sink.resourcefactory") 94Q_DECLARE_INTERFACE(Sink::ResourceFactory, "sink.sink.resourcefactory")
diff --git a/common/resourceaccess.cpp b/common/resourceaccess.cpp
index d3bd85f..c878143 100644
--- a/common/resourceaccess.cpp
+++ b/common/resourceaccess.cpp
@@ -44,12 +44,6 @@
44#include <QBuffer> 44#include <QBuffer>
45#include <QTime> 45#include <QTime>
46 46
47#undef Trace
48#define TracePrivate() Trace_area("client.communication." + resourceInstanceIdentifier)
49#define Trace() Trace_area("client.communication." + d->resourceInstanceIdentifier)
50#undef Log
51#define Log() Log_area("client.communication." + d->resourceInstanceIdentifier)
52
53static void queuedInvoke(const std::function<void()> &f, QObject *context = 0) 47static void queuedInvoke(const std::function<void()> &f, QObject *context = 0)
54{ 48{
55 auto timer = QSharedPointer<QTimer>::create(); 49 auto timer = QSharedPointer<QTimer>::create();
@@ -100,8 +94,10 @@ public:
100 QHash<uint, bool> completeCommands; 94 QHash<uint, bool> completeCommands;
101 uint messageId; 95 uint messageId;
102 bool openingSocket; 96 bool openingSocket;
97 SINK_DEBUG_COMPONENT(resourceInstanceIdentifier)
103}; 98};
104 99
100
105ResourceAccess::Private::Private(const QByteArray &name, const QByteArray &instanceIdentifier, ResourceAccess *q) 101ResourceAccess::Private::Private(const QByteArray &name, const QByteArray &instanceIdentifier, ResourceAccess *q)
106 : resourceName(name), resourceInstanceIdentifier(instanceIdentifier), messageId(0), openingSocket(false) 102 : resourceName(name), resourceInstanceIdentifier(instanceIdentifier), messageId(0), openingSocket(false)
107{ 103{
@@ -111,7 +107,7 @@ void ResourceAccess::Private::abortPendingOperations()
111{ 107{
112 callCallbacks(); 108 callCallbacks();
113 if (!resultHandler.isEmpty()) { 109 if (!resultHandler.isEmpty()) {
114 Warning() << "Aborting pending operations " << resultHandler.keys(); 110 SinkWarning() << "Aborting pending operations " << resultHandler.keys();
115 } 111 }
116 auto handlers = resultHandler.values(); 112 auto handlers = resultHandler.values();
117 resultHandler.clear(); 113 resultHandler.clear();
@@ -165,7 +161,7 @@ KAsync::Job<void> ResourceAccess::Private::tryToConnect()
165 auto counter = QSharedPointer<int>::create(0); 161 auto counter = QSharedPointer<int>::create(0);
166 return KAsync::dowhile([this]() -> bool { return !socket; }, 162 return KAsync::dowhile([this]() -> bool { return !socket; },
167 [this, counter](KAsync::Future<void> &future) { 163 [this, counter](KAsync::Future<void> &future) {
168 TracePrivate() << "Loop"; 164 SinkTrace() << "Loop";
169 connectToServer(resourceInstanceIdentifier) 165 connectToServer(resourceInstanceIdentifier)
170 .then<void, QSharedPointer<QLocalSocket>>( 166 .then<void, QSharedPointer<QLocalSocket>>(
171 [this, &future](const QSharedPointer<QLocalSocket> &s) { 167 [this, &future](const QSharedPointer<QLocalSocket> &s) {
@@ -178,7 +174,7 @@ KAsync::Job<void> ResourceAccess::Private::tryToConnect()
178 static int timeout = 500; 174 static int timeout = 500;
179 static int maxRetries = timeout / waitTime; 175 static int maxRetries = timeout / waitTime;
180 if (*counter > maxRetries) { 176 if (*counter > maxRetries) {
181 TracePrivate() << "Giving up"; 177 SinkTrace() << "Giving up";
182 future.setError(-1, "Failed to connect to socket"); 178 future.setError(-1, "Failed to connect to socket");
183 } else { 179 } else {
184 KAsync::wait(waitTime).then<void>([&future]() { future.setFinished(); }).exec(); 180 KAsync::wait(waitTime).then<void>([&future]() { future.setFinished(); }).exec();
@@ -192,17 +188,17 @@ KAsync::Job<void> ResourceAccess::Private::tryToConnect()
192KAsync::Job<void> ResourceAccess::Private::initializeSocket() 188KAsync::Job<void> ResourceAccess::Private::initializeSocket()
193{ 189{
194 return KAsync::start<void>([this](KAsync::Future<void> &future) { 190 return KAsync::start<void>([this](KAsync::Future<void> &future) {
195 TracePrivate() << "Trying to connect"; 191 SinkTrace() << "Trying to connect";
196 connectToServer(resourceInstanceIdentifier) 192 connectToServer(resourceInstanceIdentifier)
197 .then<void, QSharedPointer<QLocalSocket>>( 193 .then<void, QSharedPointer<QLocalSocket>>(
198 [this, &future](const QSharedPointer<QLocalSocket> &s) { 194 [this, &future](const QSharedPointer<QLocalSocket> &s) {
199 TracePrivate() << "Connected to resource, without having to start it."; 195 SinkTrace() << "Connected to resource, without having to start it.";
200 Q_ASSERT(s); 196 Q_ASSERT(s);
201 socket = s; 197 socket = s;
202 future.setFinished(); 198 future.setFinished();
203 }, 199 },
204 [this, &future](int errorCode, const QString &errorString) { 200 [this, &future](int errorCode, const QString &errorString) {
205 TracePrivate() << "Failed to connect, starting resource"; 201 SinkTrace() << "Failed to connect, starting resource";
206 // We failed to connect, so let's start the resource 202 // We failed to connect, so let's start the resource
207 QStringList args; 203 QStringList args;
208 if (Sink::Test::testModeEnabled()) { 204 if (Sink::Test::testModeEnabled()) {
@@ -211,16 +207,16 @@ KAsync::Job<void> ResourceAccess::Private::initializeSocket()
211 args << resourceInstanceIdentifier << resourceName; 207 args << resourceInstanceIdentifier << resourceName;
212 qint64 pid = 0; 208 qint64 pid = 0;
213 if (QProcess::startDetached("sink_synchronizer", args, QDir::homePath(), &pid)) { 209 if (QProcess::startDetached("sink_synchronizer", args, QDir::homePath(), &pid)) {
214 TracePrivate() << "Started resource " << pid; 210 SinkTrace() << "Started resource " << pid;
215 tryToConnect() 211 tryToConnect()
216 .then<void>([&future]() { future.setFinished(); }, 212 .then<void>([&future]() { future.setFinished(); },
217 [this, &future](int errorCode, const QString &errorString) { 213 [this, &future](int errorCode, const QString &errorString) {
218 Warning() << "Failed to connect to started resource"; 214 SinkWarning() << "Failed to connect to started resource";
219 future.setError(errorCode, errorString); 215 future.setError(errorCode, errorString);
220 }) 216 })
221 .exec(); 217 .exec();
222 } else { 218 } else {
223 Warning() << "Failed to start resource"; 219 SinkWarning() << "Failed to start resource";
224 } 220 }
225 }) 221 })
226 .exec(); 222 .exec();
@@ -230,14 +226,15 @@ KAsync::Job<void> ResourceAccess::Private::initializeSocket()
230ResourceAccess::ResourceAccess(const QByteArray &resourceInstanceIdentifier, const QByteArray &resourceType) 226ResourceAccess::ResourceAccess(const QByteArray &resourceInstanceIdentifier, const QByteArray &resourceType)
231 : ResourceAccessInterface(), d(new Private(resourceType, resourceInstanceIdentifier, this)) 227 : ResourceAccessInterface(), d(new Private(resourceType, resourceInstanceIdentifier, this))
232{ 228{
233 Trace() << "Starting access"; 229 mResourceStatus = Sink::ApplicationDomain::OfflineStatus;
230 SinkTrace() << "Starting access";
234} 231}
235 232
236ResourceAccess::~ResourceAccess() 233ResourceAccess::~ResourceAccess()
237{ 234{
238 Log() << "Closing access"; 235 SinkLog() << "Closing access";
239 if (!d->resultHandler.isEmpty()) { 236 if (!d->resultHandler.isEmpty()) {
240 Warning() << "Left jobs running while shutting down ResourceAccess: " << d->resultHandler.keys(); 237 SinkWarning() << "Left jobs running while shutting down ResourceAccess: " << d->resultHandler.keys();
241 } 238 }
242} 239}
243 240
@@ -294,7 +291,7 @@ KAsync::Job<void> ResourceAccess::sendCommand(int commandId, flatbuffers::FlatBu
294 291
295KAsync::Job<void> ResourceAccess::synchronizeResource(bool sourceSync, bool localSync) 292KAsync::Job<void> ResourceAccess::synchronizeResource(bool sourceSync, bool localSync)
296{ 293{
297 Trace() << "Sending synchronize command: " << sourceSync << localSync; 294 SinkTrace() << "Sending synchronize command: " << sourceSync << localSync;
298 flatbuffers::FlatBufferBuilder fbb; 295 flatbuffers::FlatBufferBuilder fbb;
299 auto command = Sink::Commands::CreateSynchronize(fbb, sourceSync, localSync); 296 auto command = Sink::Commands::CreateSynchronize(fbb, sourceSync, localSync);
300 Sink::Commands::FinishSynchronizeBuffer(fbb, command); 297 Sink::Commands::FinishSynchronizeBuffer(fbb, command);
@@ -375,7 +372,7 @@ ResourceAccess::sendInspectionCommand(int inspectionType, const QByteArray &insp
375void ResourceAccess::open() 372void ResourceAccess::open()
376{ 373{
377 if (d->socket && d->socket->isValid()) { 374 if (d->socket && d->socket->isValid()) {
378 // Trace() << "Socket valid, so not opening again"; 375 // SinkTrace() << "Socket valid, so not opening again";
379 return; 376 return;
380 } 377 }
381 if (d->openingSocket) { 378 if (d->openingSocket) {
@@ -387,7 +384,7 @@ void ResourceAccess::open()
387 d->initializeSocket() 384 d->initializeSocket()
388 .then<void>( 385 .then<void>(
389 [this, time]() { 386 [this, time]() {
390 Trace() << "Socket is initialized." << Log::TraceTime(time->elapsed()); 387 SinkTrace() << "Socket is initialized." << Log::TraceTime(time->elapsed());
391 d->openingSocket = false; 388 d->openingSocket = false;
392 QObject::connect(d->socket.data(), &QLocalSocket::disconnected, this, &ResourceAccess::disconnected); 389 QObject::connect(d->socket.data(), &QLocalSocket::disconnected, this, &ResourceAccess::disconnected);
393 QObject::connect(d->socket.data(), SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(connectionError(QLocalSocket::LocalSocketError))); 390 QObject::connect(d->socket.data(), SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(connectionError(QLocalSocket::LocalSocketError)));
@@ -396,16 +393,16 @@ void ResourceAccess::open()
396 }, 393 },
397 [this](int error, const QString &errorString) { 394 [this](int error, const QString &errorString) {
398 d->openingSocket = false; 395 d->openingSocket = false;
399 Warning() << "Failed to initialize socket " << errorString; 396 SinkWarning() << "Failed to initialize socket " << errorString;
400 }) 397 })
401 .exec(); 398 .exec();
402} 399}
403 400
404void ResourceAccess::close() 401void ResourceAccess::close()
405{ 402{
406 Log() << QString("Closing %1").arg(d->socket->fullServerName()); 403 SinkLog() << QString("Closing %1").arg(d->socket->fullServerName());
407 Trace() << "Pending commands: " << d->pendingCommands.size(); 404 SinkTrace() << "Pending commands: " << d->pendingCommands.size();
408 Trace() << "Queued commands: " << d->commandQueue.size(); 405 SinkTrace() << "Queued commands: " << d->commandQueue.size();
409 d->socket->close(); 406 d->socket->close();
410} 407}
411 408
@@ -415,10 +412,10 @@ void ResourceAccess::sendCommand(const QSharedPointer<QueuedCommand> &command)
415 // TODO: we should have a timeout for commands 412 // TODO: we should have a timeout for commands
416 d->messageId++; 413 d->messageId++;
417 const auto messageId = d->messageId; 414 const auto messageId = d->messageId;
418 Trace() << QString("Sending command \"%1\" with messageId %2").arg(QString(Sink::Commands::name(command->commandId))).arg(d->messageId); 415 SinkTrace() << QString("Sending command \"%1\" with messageId %2").arg(QString(Sink::Commands::name(command->commandId))).arg(d->messageId);
419 Q_ASSERT(command->callback); 416 Q_ASSERT(command->callback);
420 registerCallback(d->messageId, [this, messageId, command](int errorCode, QString errorMessage) { 417 registerCallback(d->messageId, [this, messageId, command](int errorCode, QString errorMessage) {
421 Trace() << "Command complete " << messageId; 418 SinkTrace() << "Command complete " << messageId;
422 d->pendingCommands.remove(messageId); 419 d->pendingCommands.remove(messageId);
423 command->callback(errorCode, errorMessage); 420 command->callback(errorCode, errorMessage);
424 }); 421 });
@@ -430,8 +427,8 @@ void ResourceAccess::sendCommand(const QSharedPointer<QueuedCommand> &command)
430void ResourceAccess::processCommandQueue() 427void ResourceAccess::processCommandQueue()
431{ 428{
432 // TODO: serialize instead of blast them all through the socket? 429 // TODO: serialize instead of blast them all through the socket?
433 Trace() << "We have " << d->commandQueue.size() << " queued commands"; 430 SinkTrace() << "We have " << d->commandQueue.size() << " queued commands";
434 Trace() << "Pending commands: " << d->pendingCommands.size(); 431 SinkTrace() << "Pending commands: " << d->pendingCommands.size();
435 for (auto command : d->commandQueue) { 432 for (auto command : d->commandQueue) {
436 sendCommand(command); 433 sendCommand(command);
437 } 434 }
@@ -440,9 +437,9 @@ void ResourceAccess::processCommandQueue()
440 437
441void ResourceAccess::processPendingCommandQueue() 438void ResourceAccess::processPendingCommandQueue()
442{ 439{
443 Trace() << "We have " << d->pendingCommands.size() << " pending commands"; 440 SinkTrace() << "We have " << d->pendingCommands.size() << " pending commands";
444 for (auto command : d->pendingCommands) { 441 for (auto command : d->pendingCommands) {
445 Trace() << "Reenquing command " << command->commandId; 442 SinkTrace() << "Reenquing command " << command->commandId;
446 d->commandQueue << command; 443 d->commandQueue << command;
447 } 444 }
448 d->pendingCommands.clear(); 445 d->pendingCommands.clear();
@@ -452,11 +449,11 @@ void ResourceAccess::processPendingCommandQueue()
452void ResourceAccess::connected() 449void ResourceAccess::connected()
453{ 450{
454 if (!isReady()) { 451 if (!isReady()) {
455 Trace() << "Connected but not ready?"; 452 SinkTrace() << "Connected but not ready?";
456 return; 453 return;
457 } 454 }
458 455
459 Trace() << QString("Connected: %1").arg(d->socket->fullServerName()); 456 SinkTrace() << QString("Connected: %1").arg(d->socket->fullServerName());
460 457
461 { 458 {
462 flatbuffers::FlatBufferBuilder fbb; 459 flatbuffers::FlatBufferBuilder fbb;
@@ -476,7 +473,7 @@ void ResourceAccess::connected()
476 473
477void ResourceAccess::disconnected() 474void ResourceAccess::disconnected()
478{ 475{
479 Log() << QString("Disconnected from %1").arg(d->socket->fullServerName()); 476 SinkLog() << QString("Disconnected from %1").arg(d->socket->fullServerName());
480 d->socket->close(); 477 d->socket->close();
481 emit ready(false); 478 emit ready(false);
482} 479}
@@ -485,15 +482,15 @@ void ResourceAccess::connectionError(QLocalSocket::LocalSocketError error)
485{ 482{
486 const bool resourceCrashed = d->partialMessageBuffer.contains("PANIC"); 483 const bool resourceCrashed = d->partialMessageBuffer.contains("PANIC");
487 if (resourceCrashed) { 484 if (resourceCrashed) {
488 ErrorMsg() << "The resource crashed!"; 485 SinkError() << "The resource crashed!";
489 d->abortPendingOperations(); 486 d->abortPendingOperations();
490 } else if (error == QLocalSocket::PeerClosedError) { 487 } else if (error == QLocalSocket::PeerClosedError) {
491 Log() << "The resource closed the connection."; 488 SinkLog() << "The resource closed the connection.";
492 d->abortPendingOperations(); 489 d->abortPendingOperations();
493 } else { 490 } else {
494 Warning() << QString("Connection error: %1 : %2").arg(error).arg(d->socket->errorString()); 491 SinkWarning() << QString("Connection error: %1 : %2").arg(error).arg(d->socket->errorString());
495 if (d->pendingCommands.size()) { 492 if (d->pendingCommands.size()) {
496 Trace() << "Reconnecting due to pending operations: " << d->pendingCommands.size(); 493 SinkTrace() << "Reconnecting due to pending operations: " << d->pendingCommands.size();
497 open(); 494 open();
498 } 495 }
499 } 496 }
@@ -502,7 +499,7 @@ void ResourceAccess::connectionError(QLocalSocket::LocalSocketError error)
502void ResourceAccess::readResourceMessage() 499void ResourceAccess::readResourceMessage()
503{ 500{
504 if (!d->socket || !d->socket->isValid()) { 501 if (!d->socket || !d->socket->isValid()) {
505 Warning() << "No socket available"; 502 SinkWarning() << "No socket available";
506 return; 503 return;
507 } 504 }
508 505
@@ -513,11 +510,27 @@ void ResourceAccess::readResourceMessage()
513 } 510 }
514} 511}
515 512
513static Sink::Notification getNotification(const Sink::Commands::Notification *buffer)
514{
515 Sink::Notification n;
516 if (buffer->identifier()) {
517 // Don't use fromRawData, the buffer is gone once we invoke emit notification
518 n.id = BufferUtils::extractBufferCopy(buffer->identifier());
519 }
520 if (buffer->message()) {
521 // Don't use fromRawData, the buffer is gone once we invoke emit notification
522 n.message = BufferUtils::extractBufferCopy(buffer->message());
523 }
524 n.type = buffer->type();
525 n.code = buffer->code();
526 return n;
527}
528
516bool ResourceAccess::processMessageBuffer() 529bool ResourceAccess::processMessageBuffer()
517{ 530{
518 static const int headerSize = Commands::headerSize(); 531 static const int headerSize = Commands::headerSize();
519 if (d->partialMessageBuffer.size() < headerSize) { 532 if (d->partialMessageBuffer.size() < headerSize) {
520 Warning() << "command too small"; 533 SinkWarning() << "command too small";
521 return false; 534 return false;
522 } 535 }
523 536
@@ -526,16 +539,16 @@ bool ResourceAccess::processMessageBuffer()
526 const uint size = *(int *)(d->partialMessageBuffer.constData() + sizeof(int) + sizeof(uint)); 539 const uint size = *(int *)(d->partialMessageBuffer.constData() + sizeof(int) + sizeof(uint));
527 540
528 if (size > (uint)(d->partialMessageBuffer.size() - headerSize)) { 541 if (size > (uint)(d->partialMessageBuffer.size() - headerSize)) {
529 Warning() << "command too small"; 542 SinkWarning() << "command too small";
530 return false; 543 return false;
531 } 544 }
532 545
533 switch (commandId) { 546 switch (commandId) {
534 case Commands::RevisionUpdateCommand: { 547 case Commands::RevisionUpdateCommand: {
535 auto buffer = Commands::GetRevisionUpdate(d->partialMessageBuffer.constData() + headerSize); 548 auto buffer = Commands::GetRevisionUpdate(d->partialMessageBuffer.constData() + headerSize);
536 Trace() << QString("Revision updated to: %1").arg(buffer->revision()); 549 SinkTrace() << QString("Revision updated to: %1").arg(buffer->revision());
537 Notification n; 550 Notification n;
538 n.type = Sink::Commands::NotificationType::NotificationType_RevisionUpdate; 551 n.type = Sink::Notification::RevisionUpdate;
539 emit notification(n); 552 emit notification(n);
540 emit revisionChanged(buffer->revision()); 553 emit revisionChanged(buffer->revision());
541 554
@@ -543,7 +556,7 @@ bool ResourceAccess::processMessageBuffer()
543 } 556 }
544 case Commands::CommandCompletionCommand: { 557 case Commands::CommandCompletionCommand: {
545 auto buffer = Commands::GetCommandCompletion(d->partialMessageBuffer.constData() + headerSize); 558 auto buffer = Commands::GetCommandCompletion(d->partialMessageBuffer.constData() + headerSize);
546 Trace() << QString("Command with messageId %1 completed %2").arg(buffer->id()).arg(buffer->success() ? "sucessfully" : "unsuccessfully"); 559 SinkTrace() << QString("Command with messageId %1 completed %2").arg(buffer->id()).arg(buffer->success() ? "sucessfully" : "unsuccessfully");
547 560
548 d->completeCommands.insert(buffer->id(), buffer->success()); 561 d->completeCommands.insert(buffer->id(), buffer->success());
549 // The callbacks can result in this object getting destroyed directly, so we need to ensure we finish our work first 562 // The callbacks can result in this object getting destroyed directly, so we need to ensure we finish our work first
@@ -553,32 +566,34 @@ bool ResourceAccess::processMessageBuffer()
553 case Commands::NotificationCommand: { 566 case Commands::NotificationCommand: {
554 auto buffer = Commands::GetNotification(d->partialMessageBuffer.constData() + headerSize); 567 auto buffer = Commands::GetNotification(d->partialMessageBuffer.constData() + headerSize);
555 switch (buffer->type()) { 568 switch (buffer->type()) {
556 case Sink::Commands::NotificationType::NotificationType_Shutdown: 569 case Sink::Notification::Shutdown:
557 Log() << "Received shutdown notification."; 570 SinkLog() << "Received shutdown notification.";
558 close(); 571 close();
559 break; 572 break;
560 case Sink::Commands::NotificationType::NotificationType_Inspection: { 573 case Sink::Notification::Inspection: {
561 Trace() << "Received inspection notification."; 574 SinkTrace() << "Received inspection notification.";
562 Notification n; 575 auto n = getNotification(buffer);
563 if (buffer->identifier()) {
564 // Don't use fromRawData, the buffer is gone once we invoke emit notification
565 n.id = BufferUtils::extractBufferCopy(buffer->identifier());
566 }
567 if (buffer->message()) {
568 // Don't use fromRawData, the buffer is gone once we invoke emit notification
569 n.message = BufferUtils::extractBufferCopy(buffer->message());
570 }
571 n.type = buffer->type();
572 n.code = buffer->code();
573 // The callbacks can result in this object getting destroyed directly, so we need to ensure we finish our work first 576 // The callbacks can result in this object getting destroyed directly, so we need to ensure we finish our work first
574 queuedInvoke([=]() { emit notification(n); }, this); 577 queuedInvoke([=]() { emit notification(n); }, this);
575 } break; 578 } break;
576 case Sink::Commands::NotificationType::NotificationType_Status: 579 case Sink::Notification::Status:
577 case Sink::Commands::NotificationType::NotificationType_Warning: 580 if (mResourceStatus == buffer->code()) {
578 case Sink::Commands::NotificationType::NotificationType_Progress: 581 SinkTrace() << "Got an unnecessary status notification";
579 case Sink::Commands::NotificationType::NotificationType_RevisionUpdate: 582 break;
583 }
584 mResourceStatus = buffer->code();
585 SinkTrace() << "Updated status: " << mResourceStatus;
586 [[clang::fallthrough]];
587 case Sink::Notification::Warning:
588 [[clang::fallthrough]];
589 case Sink::Notification::Progress: {
590 auto n = getNotification(buffer);
591 SinkTrace() << "Received notification: " << n.type;
592 emit notification(n);
593 } break;
594 case Sink::Notification::RevisionUpdate:
580 default: 595 default:
581 Warning() << "Received unknown notification: " << buffer->type(); 596 SinkWarning() << "Received unknown notification: " << buffer->type();
582 break; 597 break;
583 } 598 }
584 break; 599 break;
@@ -624,6 +639,7 @@ Sink::ResourceAccess::Ptr ResourceAccessFactory::getAccess(const QByteArray &ins
624 } 639 }
625 if (!mTimer.contains(instanceIdentifier)) { 640 if (!mTimer.contains(instanceIdentifier)) {
626 auto timer = new QTimer; 641 auto timer = new QTimer;
642 timer->setSingleShot(true);
627 // Drop connection after 3 seconds (which is a random value) 643 // Drop connection after 3 seconds (which is a random value)
628 QObject::connect(timer, &QTimer::timeout, timer, [this, instanceIdentifier]() { mCache.remove(instanceIdentifier); }); 644 QObject::connect(timer, &QTimer::timeout, timer, [this, instanceIdentifier]() { mCache.remove(instanceIdentifier); });
629 timer->setInterval(3000); 645 timer->setInterval(3000);
diff --git a/common/resourceaccess.h b/common/resourceaccess.h
index 69d52b4..5d66246 100644
--- a/common/resourceaccess.h
+++ b/common/resourceaccess.h
@@ -29,6 +29,7 @@
29 29
30#include <flatbuffers/flatbuffers.h> 30#include <flatbuffers/flatbuffers.h>
31#include "notification.h" 31#include "notification.h"
32#include "log.h"
32 33
33namespace Sink { 34namespace Sink {
34 35
@@ -72,19 +73,28 @@ public:
72 return KAsync::null<void>(); 73 return KAsync::null<void>();
73 }; 74 };
74 75
76 int getResourceStatus() const
77 {
78 return mResourceStatus;
79 }
80
75signals: 81signals:
76 void ready(bool isReady); 82 void ready(bool isReady);
77 void revisionChanged(qint64 revision); 83 void revisionChanged(qint64 revision);
78 void notification(Notification revision); 84 void notification(Notification notification);
79 85
80public slots: 86public slots:
81 virtual void open() = 0; 87 virtual void open() = 0;
82 virtual void close() = 0; 88 virtual void close() = 0;
89
90protected:
91 int mResourceStatus;
83}; 92};
84 93
85class SINK_EXPORT ResourceAccess : public ResourceAccessInterface 94class SINK_EXPORT ResourceAccess : public ResourceAccessInterface
86{ 95{
87 Q_OBJECT 96 Q_OBJECT
97 SINK_DEBUG_AREA("communication")
88public: 98public:
89 typedef QSharedPointer<ResourceAccess> Ptr; 99 typedef QSharedPointer<ResourceAccess> Ptr;
90 100
@@ -130,6 +140,7 @@ private:
130 140
131 class Private; 141 class Private;
132 Private *const d; 142 Private *const d;
143 // SINK_DEBUG_COMPONENT(d->resourceInstanceIdentifier)
133}; 144};
134 145
135/** 146/**
@@ -137,8 +148,9 @@ private:
137 * 148 *
138 * This avoids constantly recreating connections, and should allow a single process to have one connection per resource. 149 * This avoids constantly recreating connections, and should allow a single process to have one connection per resource.
139 */ 150 */
140class ResourceAccessFactory 151class SINK_EXPORT ResourceAccessFactory
141{ 152{
153 SINK_DEBUG_AREA("ResourceAccessFactory")
142public: 154public:
143 static ResourceAccessFactory &instance(); 155 static ResourceAccessFactory &instance();
144 Sink::ResourceAccess::Ptr getAccess(const QByteArray &instanceIdentifier, const QByteArray resourceType); 156 Sink::ResourceAccess::Ptr getAccess(const QByteArray &instanceIdentifier, const QByteArray resourceType);
diff --git a/common/resourceconfig.cpp b/common/resourceconfig.cpp
index a4e5fc5..39f9ddb 100644
--- a/common/resourceconfig.cpp
+++ b/common/resourceconfig.cpp
@@ -20,13 +20,13 @@
20 20
21#include <QSettings> 21#include <QSettings>
22#include <QSharedPointer> 22#include <QSharedPointer>
23#include <QStandardPaths>
24#include <QFile> 23#include <QFile>
25#include <log.h> 24#include <log.h>
25#include <definitions.h>
26 26
27static QSharedPointer<QSettings> getConfig(const QByteArray &identifier) 27static QSharedPointer<QSettings> getConfig(const QByteArray &identifier)
28{ 28{
29 return QSharedPointer<QSettings>::create(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/sink/" + identifier + ".ini", QSettings::IniFormat); 29 return QSharedPointer<QSettings>::create(Sink::configLocation() +"/" + identifier + ".ini", QSettings::IniFormat);
30} 30}
31 31
32QByteArray ResourceConfig::newIdentifier(const QByteArray &type) 32QByteArray ResourceConfig::newIdentifier(const QByteArray &type)
diff --git a/common/resourcecontrol.cpp b/common/resourcecontrol.cpp
index 5c2cd06..7d092a4 100644
--- a/common/resourcecontrol.cpp
+++ b/common/resourcecontrol.cpp
@@ -30,14 +30,13 @@
30#include "log.h" 30#include "log.h"
31#include "notifier.h" 31#include "notifier.h"
32 32
33#undef DEBUG_AREA 33SINK_DEBUG_AREA("resourcecontrol")
34#define DEBUG_AREA "client.resourcecontrol"
35 34
36namespace Sink { 35namespace Sink {
37 36
38KAsync::Job<void> ResourceControl::shutdown(const QByteArray &identifier) 37KAsync::Job<void> ResourceControl::shutdown(const QByteArray &identifier)
39{ 38{
40 Trace() << "shutdown " << identifier; 39 SinkTrace() << "shutdown " << identifier;
41 auto time = QSharedPointer<QTime>::create(); 40 auto time = QSharedPointer<QTime>::create();
42 time->start(); 41 time->start();
43 return ResourceAccess::connectToServer(identifier) 42 return ResourceAccess::connectToServer(identifier)
@@ -50,33 +49,33 @@ KAsync::Job<void> ResourceControl::shutdown(const QByteArray &identifier)
50 resourceAccess->sendCommand(Sink::Commands::ShutdownCommand) 49 resourceAccess->sendCommand(Sink::Commands::ShutdownCommand)
51 .then<void>([&future, resourceAccess, time]() { 50 .then<void>([&future, resourceAccess, time]() {
52 resourceAccess->close(); 51 resourceAccess->close();
53 Trace() << "Shutdown complete." << Log::TraceTime(time->elapsed()); 52 SinkTrace() << "Shutdown complete." << Log::TraceTime(time->elapsed());
54 future.setFinished(); 53 future.setFinished();
55 }) 54 })
56 .exec(); 55 .exec();
57 }, 56 },
58 [](int, const QString &) { 57 [](int, const QString &) {
59 Trace() << "Resource is already closed."; 58 SinkTrace() << "Resource is already closed.";
60 // Resource isn't started, nothing to shutdown 59 // Resource isn't started, nothing to shutdown
61 }); 60 });
62} 61}
63 62
64KAsync::Job<void> ResourceControl::start(const QByteArray &identifier) 63KAsync::Job<void> ResourceControl::start(const QByteArray &identifier)
65{ 64{
66 Trace() << "start " << identifier; 65 SinkTrace() << "start " << identifier;
67 auto time = QSharedPointer<QTime>::create(); 66 auto time = QSharedPointer<QTime>::create();
68 time->start(); 67 time->start();
69 auto resourceAccess = ResourceAccessFactory::instance().getAccess(identifier, ResourceConfig::getResourceType(identifier)); 68 auto resourceAccess = ResourceAccessFactory::instance().getAccess(identifier, ResourceConfig::getResourceType(identifier));
70 resourceAccess->open(); 69 resourceAccess->open();
71 return resourceAccess->sendCommand(Sink::Commands::PingCommand).then<void>([resourceAccess, time]() { Trace() << "Start complete." << Log::TraceTime(time->elapsed()); }); 70 return resourceAccess->sendCommand(Sink::Commands::PingCommand).then<void>([resourceAccess, time]() { SinkTrace() << "Start complete." << Log::TraceTime(time->elapsed()); });
72} 71}
73 72
74KAsync::Job<void> ResourceControl::flushMessageQueue(const QByteArrayList &resourceIdentifier) 73KAsync::Job<void> ResourceControl::flushMessageQueue(const QByteArrayList &resourceIdentifier)
75{ 74{
76 Trace() << "flushMessageQueue" << resourceIdentifier; 75 SinkTrace() << "flushMessageQueue" << resourceIdentifier;
77 return KAsync::iterate(resourceIdentifier) 76 return KAsync::iterate(resourceIdentifier)
78 .template each<void, QByteArray>([](const QByteArray &resource, KAsync::Future<void> &future) { 77 .template each<void, QByteArray>([](const QByteArray &resource, KAsync::Future<void> &future) {
79 Trace() << "Flushing message queue " << resource; 78 SinkTrace() << "Flushing message queue " << resource;
80 auto resourceAccess = ResourceAccessFactory::instance().getAccess(resource, ResourceConfig::getResourceType(resource)); 79 auto resourceAccess = ResourceAccessFactory::instance().getAccess(resource, ResourceConfig::getResourceType(resource));
81 resourceAccess->open(); 80 resourceAccess->open();
82 resourceAccess->synchronizeResource(false, true).then<void>([&future, resourceAccess]() { future.setFinished(); }).exec(); 81 resourceAccess->synchronizeResource(false, true).then<void>([&future, resourceAccess]() { future.setFinished(); }).exec();
@@ -95,7 +94,7 @@ KAsync::Job<void> ResourceControl::inspect(const Inspection &inspectionCommand)
95 94
96 auto time = QSharedPointer<QTime>::create(); 95 auto time = QSharedPointer<QTime>::create();
97 time->start(); 96 time->start();
98 Trace() << "Sending inspection " << resource; 97 SinkTrace() << "Sending inspection " << resource;
99 auto resourceAccess = ResourceAccessFactory::instance().getAccess(resource, ResourceConfig::getResourceType(resource)); 98 auto resourceAccess = ResourceAccessFactory::instance().getAccess(resource, ResourceConfig::getResourceType(resource));
100 resourceAccess->open(); 99 resourceAccess->open();
101 auto notifier = QSharedPointer<Sink::Notifier>::create(resourceAccess); 100 auto notifier = QSharedPointer<Sink::Notifier>::create(resourceAccess);
@@ -104,7 +103,7 @@ KAsync::Job<void> ResourceControl::inspect(const Inspection &inspectionCommand)
104 .template then<void>([resourceAccess, notifier, id, time](KAsync::Future<void> &future) { 103 .template then<void>([resourceAccess, notifier, id, time](KAsync::Future<void> &future) {
105 notifier->registerHandler([&future, id, time](const Notification &notification) { 104 notifier->registerHandler([&future, id, time](const Notification &notification) {
106 if (notification.id == id) { 105 if (notification.id == id) {
107 Trace() << "Inspection complete." << Log::TraceTime(time->elapsed()); 106 SinkTrace() << "Inspection complete." << Log::TraceTime(time->elapsed());
108 if (notification.code) { 107 if (notification.code) {
109 future.setError(-1, "Inspection returned an error: " + notification.message); 108 future.setError(-1, "Inspection returned an error: " + notification.message);
110 } else { 109 } else {
diff --git a/common/resourcefacade.cpp b/common/resourcefacade.cpp
index 3901f43..583d6ec 100644
--- a/common/resourcefacade.cpp
+++ b/common/resourcefacade.cpp
@@ -22,23 +22,19 @@
22#include "query.h" 22#include "query.h"
23#include "definitions.h" 23#include "definitions.h"
24#include "storage.h" 24#include "storage.h"
25#include "store.h"
26#include "resourceaccess.h"
25#include <QDir> 27#include <QDir>
26 28
27template <typename DomainType> 29using namespace Sink;
28ConfigNotifier LocalStorageFacade<DomainType>::sConfigNotifier;
29 30
30template <typename DomainType> 31SINK_DEBUG_AREA("ResourceFacade")
31LocalStorageFacade<DomainType>::LocalStorageFacade(const QByteArray &identifier) : Sink::StoreFacade<DomainType>(), mConfigStore(identifier), mResourceInstanceIdentifier(identifier)
32{
33}
34 32
35template <typename DomainType> 33template<typename DomainType>
36LocalStorageFacade<DomainType>::~LocalStorageFacade() 34ConfigNotifier LocalStorageFacade<DomainType>::sConfigNotifier;
37{
38}
39 35
40template <typename DomainType> 36template <typename DomainType>
41typename DomainType::Ptr LocalStorageFacade<DomainType>::readFromConfig(ConfigStore &configStore, const QByteArray &id, const QByteArray &type) 37static typename DomainType::Ptr readFromConfig(ConfigStore &configStore, const QByteArray &id, const QByteArray &type)
42{ 38{
43 auto object = DomainType::Ptr::create(id); 39 auto object = DomainType::Ptr::create(id);
44 object->setProperty("type", type); 40 object->setProperty("type", type);
@@ -49,10 +45,127 @@ typename DomainType::Ptr LocalStorageFacade<DomainType>::readFromConfig(ConfigSt
49 return object; 45 return object;
50} 46}
51 47
48static bool matchesFilter(const QHash<QByteArray, Query::Comparator> &filter, const QMap<QByteArray, QVariant> &properties)
49{
50 for (const auto &filterProperty : filter.keys()) {
51 if (filterProperty == "type") {
52 continue;
53 }
54 if (!filter.value(filterProperty).matches(properties.value(filterProperty))) {
55 return false;
56 }
57 }
58 return true;
59}
60
61template<typename DomainType>
62LocalStorageQueryRunner<DomainType>::LocalStorageQueryRunner(const Query &query, const QByteArray &identifier, ConfigNotifier &configNotifier)
63 : mResultProvider(new ResultProvider<typename DomainType::Ptr>), mConfigStore(identifier), mGuard(new QObject)
64{
65 QObject *guard = new QObject;
66 mResultProvider->setFetcher([this, query, guard, &configNotifier](const QSharedPointer<DomainType> &) {
67 const auto entries = mConfigStore.getEntries();
68 for (const auto &res : entries.keys()) {
69 const auto type = entries.value(res);
70
71 if (query.propertyFilter.contains("type") && query.propertyFilter.value("type").value.toByteArray() != type) {
72 SinkTrace() << "Skipping due to type.";
73 continue;
74 }
75 if (!query.ids.isEmpty() && !query.ids.contains(res)) {
76 continue;
77 }
78 const auto configurationValues = mConfigStore.get(res);
79 if (!matchesFilter(query.propertyFilter, configurationValues)){
80 SinkTrace() << "Skipping due to filter.";
81 continue;
82 }
83 SinkTrace() << "Found match " << res;
84 auto entity = readFromConfig<DomainType>(mConfigStore, res, type);
85 updateStatus(*entity);
86 mResultProvider->add(entity);
87 }
88 if (query.liveQuery) {
89 {
90 auto ret = QObject::connect(&configNotifier, &ConfigNotifier::added, guard, [this](const ApplicationDomain::ApplicationDomainType::Ptr &entry) {
91 auto entity = entry.staticCast<DomainType>();
92 updateStatus(*entity);
93 mResultProvider->add(entity);
94 });
95 Q_ASSERT(ret);
96 }
97 {
98 auto ret = QObject::connect(&configNotifier, &ConfigNotifier::modified, guard, [this](const ApplicationDomain::ApplicationDomainType::Ptr &entry) {
99 auto entity = entry.staticCast<DomainType>();
100 updateStatus(*entity);
101 mResultProvider->modify(entity);
102 });
103 Q_ASSERT(ret);
104 }
105 {
106 auto ret = QObject::connect(&configNotifier, &ConfigNotifier::removed, guard, [this](const ApplicationDomain::ApplicationDomainType::Ptr &entry) {
107 mResultProvider->remove(entry.staticCast<DomainType>());
108 });
109 Q_ASSERT(ret);
110 }
111 }
112 // TODO initialResultSetComplete should be implicit
113 mResultProvider->initialResultSetComplete(typename DomainType::Ptr());
114 mResultProvider->complete();
115 });
116 mResultProvider->onDone([=]() { delete guard; delete this; });
117}
118
119template<typename DomainType>
120QObject *LocalStorageQueryRunner<DomainType>::guard() const
121{
122 return mGuard.get();
123}
124
125template<typename DomainType>
126void LocalStorageQueryRunner<DomainType>::updateStatus(DomainType &entity)
127{
128 if (mStatusUpdater) {
129 mStatusUpdater(entity);
130 }
131}
132
133template<typename DomainType>
134void LocalStorageQueryRunner<DomainType>::setStatusUpdater(const std::function<void(DomainType &)> &updater)
135{
136 mStatusUpdater = updater;
137}
138
139template<typename DomainType>
140void LocalStorageQueryRunner<DomainType>::statusChanged(const QByteArray &identifier)
141{
142 SinkTrace() << "Status changed " << identifier;
143 auto entity = readFromConfig<DomainType>(mConfigStore, identifier, ApplicationDomain::getTypeName<DomainType>());
144 updateStatus(*entity);
145 mResultProvider->modify(entity);
146}
147
148template<typename DomainType>
149typename Sink::ResultEmitter<typename DomainType::Ptr>::Ptr LocalStorageQueryRunner<DomainType>::emitter()
150{
151 return mResultProvider->emitter();
152}
153
154
155template <typename DomainType>
156LocalStorageFacade<DomainType>::LocalStorageFacade(const QByteArray &identifier) : StoreFacade<DomainType>(), mIdentifier(identifier), mConfigStore(identifier)
157{
158}
159
160template <typename DomainType>
161LocalStorageFacade<DomainType>::~LocalStorageFacade()
162{
163}
164
52template <typename DomainType> 165template <typename DomainType>
53typename DomainType::Ptr LocalStorageFacade<DomainType>::readFromConfig(const QByteArray &id, const QByteArray &type) 166typename DomainType::Ptr LocalStorageFacade<DomainType>::readFromConfig(const QByteArray &id, const QByteArray &type)
54{ 167{
55 return readFromConfig(mConfigStore, id, type); 168 return ::readFromConfig<DomainType>(mConfigStore, id, type);
56} 169}
57 170
58template <typename DomainType> 171template <typename DomainType>
@@ -84,7 +197,7 @@ KAsync::Job<void> LocalStorageFacade<DomainType>::modify(const DomainType &domai
84 return KAsync::start<void>([domainObject, this]() { 197 return KAsync::start<void>([domainObject, this]() {
85 const QByteArray identifier = domainObject.identifier(); 198 const QByteArray identifier = domainObject.identifier();
86 if (identifier.isEmpty()) { 199 if (identifier.isEmpty()) {
87 Warning() << "We need an \"identifier\" property to identify the entity to configure."; 200 SinkWarning() << "We need an \"identifier\" property to identify the entity to configure.";
88 return; 201 return;
89 } 202 }
90 auto changedProperties = domainObject.changedProperties(); 203 auto changedProperties = domainObject.changedProperties();
@@ -110,77 +223,22 @@ KAsync::Job<void> LocalStorageFacade<DomainType>::remove(const DomainType &domai
110 return KAsync::start<void>([domainObject, this]() { 223 return KAsync::start<void>([domainObject, this]() {
111 const QByteArray identifier = domainObject.identifier(); 224 const QByteArray identifier = domainObject.identifier();
112 if (identifier.isEmpty()) { 225 if (identifier.isEmpty()) {
113 Warning() << "We need an \"identifier\" property to identify the entity to configure"; 226 SinkWarning() << "We need an \"identifier\" property to identify the entity to configure";
114 return; 227 return;
115 } 228 }
116 Trace() << "Removing: " << identifier; 229 SinkTrace() << "Removing: " << identifier;
117 mConfigStore.remove(identifier); 230 mConfigStore.remove(identifier);
118 sConfigNotifier.remove(QSharedPointer<DomainType>::create(domainObject)); 231 sConfigNotifier.remove(QSharedPointer<DomainType>::create(domainObject));
119 }); 232 });
120} 233}
121 234
122static bool matchesFilter(const QHash<QByteArray, Sink::Query::Comparator> &filter, const QMap<QByteArray, QVariant> &properties)
123{
124 for (const auto &filterProperty : filter.keys()) {
125 if (filterProperty == "type") {
126 continue;
127 }
128 if (!filter.value(filterProperty).matches(properties.value(filterProperty))) {
129 return false;
130 }
131 }
132 return true;
133}
134
135template <typename DomainType> 235template <typename DomainType>
136QPair<KAsync::Job<void>, typename Sink::ResultEmitter<typename DomainType::Ptr>::Ptr> LocalStorageFacade<DomainType>::load(const Sink::Query &query) 236QPair<KAsync::Job<void>, typename ResultEmitter<typename DomainType::Ptr>::Ptr> LocalStorageFacade<DomainType>::load(const Query &query)
137{ 237{
138 QObject *guard = new QObject; 238 auto runner = new LocalStorageQueryRunner<DomainType>(query, mIdentifier, sConfigNotifier);
139 auto resultProvider = new Sink::ResultProvider<typename DomainType::Ptr>(); 239 return qMakePair(KAsync::null<void>(), runner->emitter());
140 auto emitter = resultProvider->emitter();
141 auto identifier = mResourceInstanceIdentifier;
142 resultProvider->setFetcher([identifier, query, guard, resultProvider](const QSharedPointer<DomainType> &) {
143 ConfigStore mConfigStore(identifier);
144 const auto entries = mConfigStore.getEntries();
145 for (const auto &res : entries.keys()) {
146 const auto type = entries.value(res);
147
148 if (query.propertyFilter.contains("type") && query.propertyFilter.value("type").value.toByteArray() != type) {
149 Trace() << "Skipping due to type.";
150 continue;
151 }
152 if (!query.ids.isEmpty() && !query.ids.contains(res)) {
153 continue;
154 }
155 const auto configurationValues = mConfigStore.get(res);
156 if (!matchesFilter(query.propertyFilter, configurationValues)){
157 Trace() << "Skipping due to filter.";
158 continue;
159 }
160 Trace() << "Found match " << res;
161 resultProvider->add(readFromConfig(mConfigStore, res, type));
162 }
163 if (query.liveQuery) {
164 QObject::connect(&sConfigNotifier, &ConfigNotifier::modified, guard, [resultProvider](const Sink::ApplicationDomain::ApplicationDomainType::Ptr &entry) {
165 resultProvider->modify(entry.staticCast<DomainType>());
166 });
167 QObject::connect(&sConfigNotifier, &ConfigNotifier::added, guard, [resultProvider](const Sink::ApplicationDomain::ApplicationDomainType::Ptr &entry) {
168 resultProvider->add(entry.staticCast<DomainType>());
169 });
170 QObject::connect(&sConfigNotifier, &ConfigNotifier::removed, guard,[resultProvider](const Sink::ApplicationDomain::ApplicationDomainType::Ptr &entry) {
171 resultProvider->remove(entry.staticCast<DomainType>());
172 });
173 }
174 // TODO initialResultSetComplete should be implicit
175 resultProvider->initialResultSetComplete(typename DomainType::Ptr());
176 resultProvider->complete();
177 });
178 resultProvider->onDone([=]() { delete resultProvider; delete guard; });
179
180 return qMakePair(KAsync::null<void>(), emitter);
181} 240}
182 241
183
184ResourceFacade::ResourceFacade() : LocalStorageFacade<Sink::ApplicationDomain::SinkResource>("resources") 242ResourceFacade::ResourceFacade() : LocalStorageFacade<Sink::ApplicationDomain::SinkResource>("resources")
185{ 243{
186} 244}
@@ -192,13 +250,28 @@ ResourceFacade::~ResourceFacade()
192KAsync::Job<void> ResourceFacade::remove(const Sink::ApplicationDomain::SinkResource &resource) 250KAsync::Job<void> ResourceFacade::remove(const Sink::ApplicationDomain::SinkResource &resource)
193{ 251{
194 const auto identifier = resource.identifier(); 252 const auto identifier = resource.identifier();
195 return LocalStorageFacade<Sink::ApplicationDomain::SinkResource>::remove(resource).then<void>([identifier]() { 253 return Sink::Store::removeDataFromDisk(identifier).then(LocalStorageFacade<Sink::ApplicationDomain::SinkResource>::remove(resource));
196 // TODO shutdown resource, or use the resource process with a --remove option to cleanup (so we can take advantage of the file locking) 254}
197 QDir dir(Sink::storageLocation()); 255
198 for (const auto &folder : dir.entryList(QStringList() << identifier + "*")) { 256QPair<KAsync::Job<void>, typename Sink::ResultEmitter<typename ApplicationDomain::SinkResource::Ptr>::Ptr> ResourceFacade::load(const Sink::Query &query)
199 Sink::Storage(Sink::storageLocation(), folder, Sink::Storage::ReadWrite).removeFromDisk(); 257{
258 auto runner = new LocalStorageQueryRunner<ApplicationDomain::SinkResource>(query, mIdentifier, sConfigNotifier);
259 auto monitoredResources = QSharedPointer<QSet<QByteArray>>::create();
260 runner->setStatusUpdater([runner, monitoredResources](ApplicationDomain::SinkResource &resource) {
261 auto resourceAccess = ResourceAccessFactory::instance().getAccess(resource.identifier(), ResourceConfig::getResourceType(resource.identifier()));
262 if (!monitoredResources->contains(resource.identifier())) {
263 auto ret = QObject::connect(resourceAccess.data(), &ResourceAccess::notification, runner->guard(), [resource, runner, resourceAccess](const Notification &notification) {
264 SinkTrace() << "Received notification in facade: " << notification.type;
265 if (notification.type == Notification::Status) {
266 runner->statusChanged(resource.identifier());
267 }
268 });
269 Q_ASSERT(ret);
270 monitoredResources->insert(resource.identifier());
200 } 271 }
272 resource.setStatusStatus(resourceAccess->getResourceStatus());
201 }); 273 });
274 return qMakePair(KAsync::null<void>(), runner->emitter());
202} 275}
203 276
204 277
@@ -210,6 +283,55 @@ AccountFacade::~AccountFacade()
210{ 283{
211} 284}
212 285
286QPair<KAsync::Job<void>, typename Sink::ResultEmitter<typename ApplicationDomain::SinkAccount::Ptr>::Ptr> AccountFacade::load(const Sink::Query &query)
287{
288 auto runner = new LocalStorageQueryRunner<ApplicationDomain::SinkAccount>(query, mIdentifier, sConfigNotifier);
289 auto monitoredResources = QSharedPointer<QSet<QByteArray>>::create();
290 runner->setStatusUpdater([runner, monitoredResources](ApplicationDomain::SinkAccount &account) {
291 Query query;
292 query.filter<ApplicationDomain::SinkResource::Account>(account.identifier());
293 const auto resources = Store::read<ApplicationDomain::SinkResource>(query);
294 SinkTrace() << "Found resource belonging to the account " << account.identifier() << " : " << resources;
295 auto accountIdentifier = account.identifier();
296 ApplicationDomain::Status status = ApplicationDomain::ConnectedStatus;
297 for (const auto &resource : resources) {
298 auto resourceAccess = ResourceAccessFactory::instance().getAccess(resource.identifier(), ResourceConfig::getResourceType(resource.identifier()));
299 if (!monitoredResources->contains(resource.identifier())) {
300 auto ret = QObject::connect(resourceAccess.data(), &ResourceAccess::notification, runner->guard(), [resource, runner, resourceAccess, accountIdentifier](const Notification &notification) {
301 SinkTrace() << "Received notification in facade: " << notification.type;
302 if (notification.type == Notification::Status) {
303 runner->statusChanged(accountIdentifier);
304 }
305 });
306 Q_ASSERT(ret);
307 monitoredResources->insert(resource.identifier());
308 }
309
310 //Figure out overall status
311 auto s = resourceAccess->getResourceStatus();
312 switch (s) {
313 case ApplicationDomain::ErrorStatus:
314 status = ApplicationDomain::ErrorStatus;
315 break;
316 case ApplicationDomain::OfflineStatus:
317 if (status == ApplicationDomain::ConnectedStatus) {
318 status = ApplicationDomain::OfflineStatus;
319 }
320 break;
321 case ApplicationDomain::ConnectedStatus:
322 break;
323 case ApplicationDomain::BusyStatus:
324 if (status != ApplicationDomain::ErrorStatus) {
325 status = ApplicationDomain::BusyStatus;
326 }
327 break;
328 }
329 }
330 account.setStatusStatus(status);
331 });
332 return qMakePair(KAsync::null<void>(), runner->emitter());
333}
334
213IdentityFacade::IdentityFacade() : LocalStorageFacade<Sink::ApplicationDomain::Identity>("identities") 335IdentityFacade::IdentityFacade() : LocalStorageFacade<Sink::ApplicationDomain::Identity>("identities")
214{ 336{
215} 337}
diff --git a/common/resourcefacade.h b/common/resourcefacade.h
index 989375d..23c453a 100644
--- a/common/resourcefacade.h
+++ b/common/resourcefacade.h
@@ -56,6 +56,24 @@ signals:
56}; 56};
57 57
58template <typename DomainType> 58template <typename DomainType>
59class LocalStorageQueryRunner
60{
61public:
62 LocalStorageQueryRunner(const Sink::Query &query, const QByteArray &identifier, ConfigNotifier &configNotifier);
63 typename Sink::ResultEmitter<typename DomainType::Ptr>::Ptr emitter();
64 void setStatusUpdater(const std::function<void(DomainType &)> &);
65 void statusChanged(const QByteArray &identifier);
66 QObject *guard() const;
67
68private:
69 void updateStatus(DomainType &entity);
70 std::function<void(DomainType &)> mStatusUpdater;
71 QSharedPointer<Sink::ResultProvider<typename DomainType::Ptr>> mResultProvider;
72 ConfigStore mConfigStore;
73 std::unique_ptr<QObject> mGuard;
74};
75
76template <typename DomainType>
59class LocalStorageFacade : public Sink::StoreFacade<DomainType> 77class LocalStorageFacade : public Sink::StoreFacade<DomainType>
60{ 78{
61public: 79public:
@@ -65,13 +83,14 @@ public:
65 virtual KAsync::Job<void> modify(const DomainType &resource) Q_DECL_OVERRIDE; 83 virtual KAsync::Job<void> modify(const DomainType &resource) Q_DECL_OVERRIDE;
66 virtual KAsync::Job<void> remove(const DomainType &resource) Q_DECL_OVERRIDE; 84 virtual KAsync::Job<void> remove(const DomainType &resource) Q_DECL_OVERRIDE;
67 virtual QPair<KAsync::Job<void>, typename Sink::ResultEmitter<typename DomainType::Ptr>::Ptr> load(const Sink::Query &query) Q_DECL_OVERRIDE; 85 virtual QPair<KAsync::Job<void>, typename Sink::ResultEmitter<typename DomainType::Ptr>::Ptr> load(const Sink::Query &query) Q_DECL_OVERRIDE;
86
87protected:
88 QByteArray mIdentifier;
89 static ConfigNotifier sConfigNotifier;
90
68private: 91private:
69 typename DomainType::Ptr readFromConfig(const QByteArray &id, const QByteArray &type); 92 typename DomainType::Ptr readFromConfig(const QByteArray &id, const QByteArray &type);
70 static typename DomainType::Ptr readFromConfig(ConfigStore &store, const QByteArray &id, const QByteArray &type);
71
72 ConfigStore mConfigStore; 93 ConfigStore mConfigStore;
73 static ConfigNotifier sConfigNotifier;
74 QByteArray mResourceInstanceIdentifier;
75}; 94};
76 95
77class ResourceFacade : public LocalStorageFacade<Sink::ApplicationDomain::SinkResource> 96class ResourceFacade : public LocalStorageFacade<Sink::ApplicationDomain::SinkResource>
@@ -80,6 +99,7 @@ public:
80 ResourceFacade(); 99 ResourceFacade();
81 virtual ~ResourceFacade(); 100 virtual ~ResourceFacade();
82 virtual KAsync::Job<void> remove(const Sink::ApplicationDomain::SinkResource &resource) Q_DECL_OVERRIDE; 101 virtual KAsync::Job<void> remove(const Sink::ApplicationDomain::SinkResource &resource) Q_DECL_OVERRIDE;
102 virtual QPair<KAsync::Job<void>, typename Sink::ResultEmitter<typename Sink::ApplicationDomain::SinkResource::Ptr>::Ptr> load(const Sink::Query &query) Q_DECL_OVERRIDE;
83}; 103};
84 104
85class AccountFacade : public LocalStorageFacade<Sink::ApplicationDomain::SinkAccount> 105class AccountFacade : public LocalStorageFacade<Sink::ApplicationDomain::SinkAccount>
@@ -87,6 +107,7 @@ class AccountFacade : public LocalStorageFacade<Sink::ApplicationDomain::SinkAcc
87public: 107public:
88 AccountFacade(); 108 AccountFacade();
89 virtual ~AccountFacade(); 109 virtual ~AccountFacade();
110 virtual QPair<KAsync::Job<void>, typename Sink::ResultEmitter<typename Sink::ApplicationDomain::SinkAccount::Ptr>::Ptr> load(const Sink::Query &query) Q_DECL_OVERRIDE;
90}; 111};
91 112
92class IdentityFacade : public LocalStorageFacade<Sink::ApplicationDomain::Identity> 113class IdentityFacade : public LocalStorageFacade<Sink::ApplicationDomain::Identity>
diff --git a/common/sourcewriteback.cpp b/common/sourcewriteback.cpp
index a277606..7d21ea6 100644
--- a/common/sourcewriteback.cpp
+++ b/common/sourcewriteback.cpp
@@ -26,6 +26,8 @@
26#define ENTITY_TYPE_MAIL "mail" 26#define ENTITY_TYPE_MAIL "mail"
27#define ENTITY_TYPE_FOLDER "folder" 27#define ENTITY_TYPE_FOLDER "folder"
28 28
29SINK_DEBUG_AREA("sourcewriteback")
30
29using namespace Sink; 31using namespace Sink;
30 32
31SourceWriteBack::SourceWriteBack(const QByteArray &resourceType, const QByteArray &resourceInstanceIdentifier) 33SourceWriteBack::SourceWriteBack(const QByteArray &resourceType, const QByteArray &resourceInstanceIdentifier)
@@ -55,14 +57,14 @@ RemoteIdMap &SourceWriteBack::syncStore()
55 57
56KAsync::Job<void> SourceWriteBack::replay(const QByteArray &type, const QByteArray &key, const QByteArray &value) 58KAsync::Job<void> SourceWriteBack::replay(const QByteArray &type, const QByteArray &key, const QByteArray &value)
57{ 59{
58 Trace() << "Replaying" << type << key; 60 SinkTrace() << "Replaying" << type << key;
59 61
60 Sink::EntityBuffer buffer(value); 62 Sink::EntityBuffer buffer(value);
61 const Sink::Entity &entity = buffer.entity(); 63 const Sink::Entity &entity = buffer.entity();
62 const auto metadataBuffer = Sink::EntityBuffer::readBuffer<Sink::Metadata>(entity.metadata()); 64 const auto metadataBuffer = Sink::EntityBuffer::readBuffer<Sink::Metadata>(entity.metadata());
63 Q_ASSERT(metadataBuffer); 65 Q_ASSERT(metadataBuffer);
64 if (!metadataBuffer->replayToSource()) { 66 if (!metadataBuffer->replayToSource()) {
65 Trace() << "Change is coming from the source"; 67 SinkTrace() << "Change is coming from the source";
66 return KAsync::null<void>(); 68 return KAsync::null<void>();
67 } 69 }
68 Q_ASSERT(!mSyncStore); 70 Q_ASSERT(!mSyncStore);
@@ -81,11 +83,11 @@ KAsync::Job<void> SourceWriteBack::replay(const QByteArray &type, const QByteArr
81 if (operation != Sink::Operation_Creation) { 83 if (operation != Sink::Operation_Creation) {
82 oldRemoteId = syncStore().resolveLocalId(type, uid); 84 oldRemoteId = syncStore().resolveLocalId(type, uid);
83 if (oldRemoteId.isEmpty()) { 85 if (oldRemoteId.isEmpty()) {
84 Warning() << "Couldn't find the remote id for: " << type << uid; 86 SinkWarning() << "Couldn't find the remote id for: " << type << uid;
85 return KAsync::error<void>(1, "Couldn't find the remote id."); 87 return KAsync::error<void>(1, "Couldn't find the remote id.");
86 } 88 }
87 } 89 }
88 Trace() << "Replaying " << key << type << uid << oldRemoteId; 90 SinkTrace() << "Replaying " << key << type << uid << oldRemoteId;
89 91
90 KAsync::Job<QByteArray> job = KAsync::null<QByteArray>(); 92 KAsync::Job<QByteArray> job = KAsync::null<QByteArray>();
91 if (type == ENTITY_TYPE_FOLDER) { 93 if (type == ENTITY_TYPE_FOLDER) {
@@ -98,24 +100,24 @@ KAsync::Job<void> SourceWriteBack::replay(const QByteArray &type, const QByteArr
98 100
99 return job.then<void, QByteArray>([this, operation, type, uid, oldRemoteId](const QByteArray &remoteId) { 101 return job.then<void, QByteArray>([this, operation, type, uid, oldRemoteId](const QByteArray &remoteId) {
100 if (operation == Sink::Operation_Creation) { 102 if (operation == Sink::Operation_Creation) {
101 Trace() << "Replayed creation with remote id: " << remoteId; 103 SinkTrace() << "Replayed creation with remote id: " << remoteId;
102 if (remoteId.isEmpty()) { 104 if (remoteId.isEmpty()) {
103 Warning() << "Returned an empty remoteId from the creation"; 105 SinkWarning() << "Returned an empty remoteId from the creation";
104 } else { 106 } else {
105 syncStore().recordRemoteId(type, uid, remoteId); 107 syncStore().recordRemoteId(type, uid, remoteId);
106 } 108 }
107 } else if (operation == Sink::Operation_Modification) { 109 } else if (operation == Sink::Operation_Modification) {
108 Trace() << "Replayed modification with remote id: " << remoteId; 110 SinkTrace() << "Replayed modification with remote id: " << remoteId;
109 if (remoteId.isEmpty()) { 111 if (remoteId.isEmpty()) {
110 Warning() << "Returned an empty remoteId from the creation"; 112 SinkWarning() << "Returned an empty remoteId from the creation";
111 } else { 113 } else {
112 syncStore().updateRemoteId(type, uid, remoteId); 114 syncStore().updateRemoteId(type, uid, remoteId);
113 } 115 }
114 } else if (operation == Sink::Operation_Removal) { 116 } else if (operation == Sink::Operation_Removal) {
115 Trace() << "Replayed removal with remote id: " << oldRemoteId; 117 SinkTrace() << "Replayed removal with remote id: " << oldRemoteId;
116 syncStore().removeRemoteId(type, uid, oldRemoteId); 118 syncStore().removeRemoteId(type, uid, oldRemoteId);
117 } else { 119 } else {
118 ErrorMsg() << "Unkown operation" << operation; 120 SinkError() << "Unkown operation" << operation;
119 } 121 }
120 122
121 mSyncStore.clear(); 123 mSyncStore.clear();
@@ -123,7 +125,7 @@ KAsync::Job<void> SourceWriteBack::replay(const QByteArray &type, const QByteArr
123 mTransaction.abort(); 125 mTransaction.abort();
124 mSyncTransaction.commit(); 126 mSyncTransaction.commit();
125 }, [this](int errorCode, const QString &errorMessage) { 127 }, [this](int errorCode, const QString &errorMessage) {
126 Warning() << "Failed to replay change: " << errorMessage; 128 SinkWarning() << "Failed to replay change: " << errorMessage;
127 mSyncStore.clear(); 129 mSyncStore.clear();
128 mEntityStore.clear(); 130 mEntityStore.clear();
129 mTransaction.abort(); 131 mTransaction.abort();
diff --git a/common/specialpurposepreprocessor.cpp b/common/specialpurposepreprocessor.cpp
index 2892105..0985880 100644
--- a/common/specialpurposepreprocessor.cpp
+++ b/common/specialpurposepreprocessor.cpp
@@ -5,6 +5,8 @@
5 5
6using namespace Sink; 6using namespace Sink;
7 7
8SINK_DEBUG_AREA("SpecialPurposeProcessor")
9
8static QHash<QByteArray, QString> specialPurposeFolders() 10static QHash<QByteArray, QString> specialPurposeFolders()
9{ 11{
10 QHash<QByteArray, QString> hash; 12 QHash<QByteArray, QString> hash;
@@ -53,7 +55,7 @@ QByteArray SpecialPurposeProcessor::ensureFolder(Sink::Storage::Transaction &tra
53 return false; 55 return false;
54 }); 56 });
55 if (!mSpecialPurposeFolders.contains(specialPurpose)) { 57 if (!mSpecialPurposeFolders.contains(specialPurpose)) {
56 Trace() << "Failed to find a drafts folder, creating a new one"; 58 SinkTrace() << "Failed to find a drafts folder, creating a new one";
57 auto folder = ApplicationDomain::Folder::create(mResourceInstanceIdentifier); 59 auto folder = ApplicationDomain::Folder::create(mResourceInstanceIdentifier);
58 folder.setSpecialPurpose(QByteArrayList() << specialPurpose); 60 folder.setSpecialPurpose(QByteArrayList() << specialPurpose);
59 folder.setName(sSpecialPurposeFolders.value(specialPurpose)); 61 folder.setName(sSpecialPurposeFolders.value(specialPurpose));
diff --git a/common/storage.h b/common/storage.h
index e7b4a3e..4ef20d5 100644
--- a/common/storage.h
+++ b/common/storage.h
@@ -103,18 +103,8 @@ public:
103 */ 103 */
104 bool contains(const QByteArray &uid); 104 bool contains(const QByteArray &uid);
105 105
106 NamedDatabase(NamedDatabase &&other) : d(other.d) 106 NamedDatabase(NamedDatabase &&other);
107 { 107 NamedDatabase &operator=(NamedDatabase &&other);
108 d = other.d;
109 other.d = nullptr;
110 }
111
112 NamedDatabase &operator=(NamedDatabase &&other)
113 {
114 d = other.d;
115 other.d = nullptr;
116 return *this;
117 }
118 108
119 operator bool() const 109 operator bool() const
120 { 110 {
@@ -146,17 +136,8 @@ public:
146 NamedDatabase openDatabase(const QByteArray &name = QByteArray("default"), 136 NamedDatabase openDatabase(const QByteArray &name = QByteArray("default"),
147 const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>(), bool allowDuplicates = false) const; 137 const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>(), bool allowDuplicates = false) const;
148 138
149 Transaction(Transaction &&other) : d(other.d) 139 Transaction(Transaction &&other);
150 { 140 Transaction &operator=(Transaction &&other);
151 d = other.d;
152 other.d = nullptr;
153 }
154 Transaction &operator=(Transaction &&other)
155 {
156 d = other.d;
157 other.d = nullptr;
158 return *this;
159 }
160 141
161 operator bool() const; 142 operator bool() const;
162 143
diff --git a/common/storage_common.cpp b/common/storage_common.cpp
index 6982a4c..1f2594e 100644
--- a/common/storage_common.cpp
+++ b/common/storage_common.cpp
@@ -24,6 +24,8 @@
24#include "log.h" 24#include "log.h"
25#include <QUuid> 25#include <QUuid>
26 26
27SINK_DEBUG_AREA("storage")
28
27namespace Sink { 29namespace Sink {
28 30
29static const char *s_internalPrefix = "__internal"; 31static const char *s_internalPrefix = "__internal";
@@ -31,7 +33,7 @@ static const int s_internalPrefixSize = strlen(s_internalPrefix);
31 33
32void errorHandler(const Storage::Error &error) 34void errorHandler(const Storage::Error &error)
33{ 35{
34 Warning() << "Database error in " << error.store << ", code " << error.code << ", message: " << error.message; 36 SinkWarning() << "Database error in " << error.store << ", code " << error.code << ", message: " << error.message;
35} 37}
36 38
37std::function<void(const Storage::Error &error)> Storage::basicErrorHandler() 39std::function<void(const Storage::Error &error)> Storage::basicErrorHandler()
@@ -67,7 +69,7 @@ qint64 Storage::maxRevision(const Sink::Storage::Transaction &transaction)
67 }, 69 },
68 [](const Error &error) { 70 [](const Error &error) {
69 if (error.code != Sink::Storage::NotFound) { 71 if (error.code != Sink::Storage::NotFound) {
70 Warning() << "Coultn'd find the maximum revision."; 72 SinkWarning() << "Coultn'd find the maximum revision.";
71 } 73 }
72 }); 74 });
73 return r; 75 return r;
@@ -88,7 +90,7 @@ qint64 Storage::cleanedUpRevision(const Sink::Storage::Transaction &transaction)
88 }, 90 },
89 [](const Error &error) { 91 [](const Error &error) {
90 if (error.code != Sink::Storage::NotFound) { 92 if (error.code != Sink::Storage::NotFound) {
91 Warning() << "Coultn'd find the maximum revision."; 93 SinkWarning() << "Coultn'd find the maximum revision.";
92 } 94 }
93 }); 95 });
94 return r; 96 return r;
@@ -103,7 +105,7 @@ QByteArray Storage::getUidFromRevision(const Sink::Storage::Transaction &transac
103 uid = value; 105 uid = value;
104 return false; 106 return false;
105 }, 107 },
106 [revision](const Error &error) { Warning() << "Coultn'd find uid for revision: " << revision << error.message; }); 108 [revision](const Error &error) { SinkWarning() << "Coultn'd find uid for revision: " << revision << error.message; });
107 return uid; 109 return uid;
108} 110}
109 111
@@ -116,7 +118,7 @@ QByteArray Storage::getTypeFromRevision(const Sink::Storage::Transaction &transa
116 type = value; 118 type = value;
117 return false; 119 return false;
118 }, 120 },
119 [revision](const Error &error) { Warning() << "Coultn'd find type for revision " << revision; }); 121 [revision](const Error &error) { SinkWarning() << "Coultn'd find type for revision " << revision; });
120 return type; 122 return type;
121} 123}
122 124
diff --git a/common/storage_lmdb.cpp b/common/storage_lmdb.cpp
index 3687594..79f4465 100644
--- a/common/storage_lmdb.cpp
+++ b/common/storage_lmdb.cpp
@@ -34,10 +34,8 @@
34#include <lmdb.h> 34#include <lmdb.h>
35#include "log.h" 35#include "log.h"
36 36
37#undef Trace 37SINK_DEBUG_AREA("storage")
38#define Trace() Trace_area("storage." + d->storageRoot.toLatin1() + '/' + d->name.toLatin1()) 38// SINK_DEBUG_COMPONENT(d->storageRoot.toLatin1() + '/' + d->name.toLatin1())
39#undef Warning
40#define Warning() Warning_area("storage")
41 39
42namespace Sink { 40namespace Sink {
43 41
@@ -103,6 +101,21 @@ Storage::NamedDatabase::NamedDatabase(NamedDatabase::Private *prv) : d(prv)
103{ 101{
104} 102}
105 103
104Storage::NamedDatabase::NamedDatabase(NamedDatabase &&other) : d(nullptr)
105{
106 *this = std::move(other);
107}
108
109Storage::NamedDatabase &Storage::NamedDatabase::operator=(Storage::NamedDatabase &&other)
110{
111 if (&other != this) {
112 delete d;
113 d = other.d;
114 other.d = nullptr;
115 }
116 return *this;
117}
118
106Storage::NamedDatabase::~NamedDatabase() 119Storage::NamedDatabase::~NamedDatabase()
107{ 120{
108 delete d; 121 delete d;
@@ -339,7 +352,7 @@ qint64 Storage::NamedDatabase::getSize()
339 MDB_stat stat; 352 MDB_stat stat;
340 rc = mdb_stat(d->transaction, d->dbi, &stat); 353 rc = mdb_stat(d->transaction, d->dbi, &stat);
341 if (rc) { 354 if (rc) {
342 Warning() << "Something went wrong " << QByteArray(mdb_strerror(rc)); 355 SinkWarning() << "Something went wrong " << QByteArray(mdb_strerror(rc));
343 } 356 }
344 // std::cout << "overflow_pages: " << stat.ms_overflow_pages << std::endl; 357 // std::cout << "overflow_pages: " << stat.ms_overflow_pages << std::endl;
345 // std::cout << "page size: " << stat.ms_psize << std::endl; 358 // std::cout << "page size: " << stat.ms_psize << std::endl;
@@ -398,6 +411,21 @@ Storage::Transaction::Transaction(Transaction::Private *prv) : d(prv)
398 d->startTransaction(); 411 d->startTransaction();
399} 412}
400 413
414Storage::Transaction::Transaction(Transaction &&other) : d(nullptr)
415{
416 *this = std::move(other);
417}
418
419Storage::Transaction &Storage::Transaction::operator=(Storage::Transaction &&other)
420{
421 if (&other != this) {
422 delete d;
423 d = other.d;
424 other.d = nullptr;
425 }
426 return *this;
427}
428
401Storage::Transaction::~Transaction() 429Storage::Transaction::~Transaction()
402{ 430{
403 if (d && d->transaction) { 431 if (d && d->transaction) {
@@ -452,7 +480,7 @@ static bool ensureCorrectDb(Storage::NamedDatabase &database, const QByteArray &
452 bool openedTheWrongDatabase = false; 480 bool openedTheWrongDatabase = false;
453 auto count = database.scan("__internal_dbname", [db, &openedTheWrongDatabase](const QByteArray &key, const QByteArray &value) ->bool { 481 auto count = database.scan("__internal_dbname", [db, &openedTheWrongDatabase](const QByteArray &key, const QByteArray &value) ->bool {
454 if (value != db) { 482 if (value != db) {
455 Warning() << "Opened the wrong database, got " << value << " instead of " << db; 483 SinkWarning() << "Opened the wrong database, got " << value << " instead of " << db;
456 openedTheWrongDatabase = true; 484 openedTheWrongDatabase = true;
457 } 485 }
458 return false; 486 return false;
@@ -475,7 +503,7 @@ bool Storage::Transaction::validateNamedDatabases()
475 for (const auto &dbName : databases) { 503 for (const auto &dbName : databases) {
476 auto db = openDatabase(dbName); 504 auto db = openDatabase(dbName);
477 if (!db) { 505 if (!db) {
478 Warning() << "Failed to open the database: " << dbName; 506 SinkWarning() << "Failed to open the database: " << dbName;
479 return false; 507 return false;
480 } 508 }
481 } 509 }
@@ -497,7 +525,7 @@ Storage::NamedDatabase Storage::Transaction::openDatabase(const QByteArray &db,
497 } 525 }
498 auto database = Storage::NamedDatabase(p); 526 auto database = Storage::NamedDatabase(p);
499 if (!ensureCorrectDb(database, db, d->requestedRead)) { 527 if (!ensureCorrectDb(database, db, d->requestedRead)) {
500 Warning() << "Failed to open the database" << db; 528 SinkWarning() << "Failed to open the database" << db;
501 return Storage::NamedDatabase(); 529 return Storage::NamedDatabase();
502 } 530 }
503 return database; 531 return database;
@@ -506,7 +534,7 @@ Storage::NamedDatabase Storage::Transaction::openDatabase(const QByteArray &db,
506QList<QByteArray> Storage::Transaction::getDatabaseNames() const 534QList<QByteArray> Storage::Transaction::getDatabaseNames() const
507{ 535{
508 if (!d) { 536 if (!d) {
509 Warning() << "Invalid transaction"; 537 SinkWarning() << "Invalid transaction";
510 return QList<QByteArray>(); 538 return QList<QByteArray>();
511 } 539 }
512 540
@@ -529,11 +557,12 @@ QList<QByteArray> Storage::Transaction::getDatabaseNames() const
529 rc = 0; 557 rc = 0;
530 } 558 }
531 if (rc) { 559 if (rc) {
532 Warning() << "Failed to get a value" << rc; 560 SinkWarning() << "Failed to get a value" << rc;
533 } 561 }
534 } 562 }
563 mdb_cursor_close(cursor);
535 } else { 564 } else {
536 Warning() << "Failed to open db" << rc << QByteArray(mdb_strerror(rc)); 565 SinkWarning() << "Failed to open db" << rc << QByteArray(mdb_strerror(rc));
537 } 566 }
538 return list; 567 return list;
539} 568}
@@ -580,7 +609,7 @@ Storage::Private::Private(const QString &s, const QString &n, AccessMode m) : st
580 int rc = 0; 609 int rc = 0;
581 if ((rc = mdb_env_create(&env))) { 610 if ((rc = mdb_env_create(&env))) {
582 // TODO: handle error 611 // TODO: handle error
583 Warning() << "mdb_env_create: " << rc << " " << mdb_strerror(rc); 612 SinkWarning() << "mdb_env_create: " << rc << " " << mdb_strerror(rc);
584 } else { 613 } else {
585 mdb_env_set_maxdbs(env, 50); 614 mdb_env_set_maxdbs(env, 50);
586 unsigned int flags = MDB_NOTLS; 615 unsigned int flags = MDB_NOTLS;
@@ -588,11 +617,13 @@ Storage::Private::Private(const QString &s, const QString &n, AccessMode m) : st
588 flags |= MDB_RDONLY; 617 flags |= MDB_RDONLY;
589 } 618 }
590 if ((rc = mdb_env_open(env, fullPath.toStdString().data(), flags, 0664))) { 619 if ((rc = mdb_env_open(env, fullPath.toStdString().data(), flags, 0664))) {
591 Warning() << "mdb_env_open: " << rc << " " << mdb_strerror(rc); 620 SinkWarning() << "mdb_env_open: " << rc << " " << mdb_strerror(rc);
592 mdb_env_close(env); 621 mdb_env_close(env);
593 env = 0; 622 env = 0;
594 } else { 623 } else {
595 // FIXME: dynamic resize 624 // FIXME: dynamic resize
625 // In order to run valgrind this size must be smaller than half your available RAM
626 // https://github.com/BVLC/caffe/issues/2404
596 const size_t dbSize = (size_t)10485760 * (size_t)8000; // 1MB * 8000 627 const size_t dbSize = (size_t)10485760 * (size_t)8000; // 1MB * 8000
597 mdb_env_set_mapsize(env, dbSize); 628 mdb_env_set_mapsize(env, dbSize);
598 sEnvironments.insert(fullPath, env); 629 sEnvironments.insert(fullPath, env);
@@ -648,7 +679,7 @@ qint64 Storage::diskUsage() const
648{ 679{
649 QFileInfo info(d->storageRoot + '/' + d->name + "/data.mdb"); 680 QFileInfo info(d->storageRoot + '/' + d->name + "/data.mdb");
650 if (!info.exists()) { 681 if (!info.exists()) {
651 Warning() << "Tried to get filesize for non-existant file: " << info.path(); 682 SinkWarning() << "Tried to get filesize for non-existant file: " << info.path();
652 } 683 }
653 return info.size(); 684 return info.size();
654} 685}
@@ -658,7 +689,7 @@ void Storage::removeFromDisk() const
658 const QString fullPath(d->storageRoot + '/' + d->name); 689 const QString fullPath(d->storageRoot + '/' + d->name);
659 QMutexLocker locker(&d->sMutex); 690 QMutexLocker locker(&d->sMutex);
660 QDir dir(fullPath); 691 QDir dir(fullPath);
661 Trace() << "Removing database from disk: " << fullPath; 692 SinkTrace() << "Removing database from disk: " << fullPath;
662 if (!dir.removeRecursively()) { 693 if (!dir.removeRecursively()) {
663 Error error(d->name.toLatin1(), ErrorCodes::GenericError, QString("Failed to remove directory %1 %2").arg(d->storageRoot).arg(d->name).toLatin1()); 694 Error error(d->name.toLatin1(), ErrorCodes::GenericError, QString("Failed to remove directory %1 %2").arg(d->storageRoot).arg(d->name).toLatin1());
664 defaultErrorHandler()(error); 695 defaultErrorHandler()(error);
diff --git a/common/store.cpp b/common/store.cpp
index 1162a18..a58287b 100644
--- a/common/store.cpp
+++ b/common/store.cpp
@@ -36,8 +36,7 @@
36#include "storage.h" 36#include "storage.h"
37#include "log.h" 37#include "log.h"
38 38
39#undef DEBUG_AREA 39SINK_DEBUG_AREA("store")
40#define DEBUG_AREA "client.store"
41 40
42namespace Sink { 41namespace Sink {
43 42
@@ -88,24 +87,24 @@ static QMap<QByteArray, QByteArray> getResources(const QList<QByteArray> &resour
88 } 87 }
89 resources.insert(res, configuredResources.value(res)); 88 resources.insert(res, configuredResources.value(res));
90 } else { 89 } else {
91 Warning() << "Resource is not existing: " << res; 90 SinkWarning() << "Resource is not existing: " << res;
92 } 91 }
93 } 92 }
94 } 93 }
95 Trace() << "Found resources: " << resources; 94 SinkTrace() << "Found resources: " << resources;
96 return resources; 95 return resources;
97} 96}
98 97
99template <class DomainType> 98template <class DomainType>
100QSharedPointer<QAbstractItemModel> Store::loadModel(Query query) 99QSharedPointer<QAbstractItemModel> Store::loadModel(Query query)
101{ 100{
102 Trace() << "Query: " << ApplicationDomain::getTypeName<DomainType>(); 101 SinkTrace() << "Query: " << ApplicationDomain::getTypeName<DomainType>();
103 Trace() << " Requested: " << query.requestedProperties; 102 SinkTrace() << " Requested: " << query.requestedProperties;
104 Trace() << " Filter: " << query.propertyFilter; 103 SinkTrace() << " Filter: " << query.propertyFilter;
105 Trace() << " Parent: " << query.parentProperty; 104 SinkTrace() << " Parent: " << query.parentProperty;
106 Trace() << " Ids: " << query.ids; 105 SinkTrace() << " Ids: " << query.ids;
107 Trace() << " IsLive: " << query.liveQuery; 106 SinkTrace() << " IsLive: " << query.liveQuery;
108 Trace() << " Sorting: " << query.sortProperty; 107 SinkTrace() << " Sorting: " << query.sortProperty;
109 auto model = QSharedPointer<ModelResult<DomainType, typename DomainType::Ptr>>::create(query, query.requestedProperties); 108 auto model = QSharedPointer<ModelResult<DomainType, typename DomainType::Ptr>>::create(query, query.requestedProperties);
110 109
111 //* Client defines lifetime of model 110 //* Client defines lifetime of model
@@ -123,16 +122,16 @@ QSharedPointer<QAbstractItemModel> Store::loadModel(Query query)
123 const auto resourceType = resources.value(resourceInstanceIdentifier); 122 const auto resourceType = resources.value(resourceInstanceIdentifier);
124 auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceType, resourceInstanceIdentifier); 123 auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceType, resourceInstanceIdentifier);
125 if (facade) { 124 if (facade) {
126 Trace() << "Trying to fetch from resource " << resourceInstanceIdentifier; 125 SinkTrace() << "Trying to fetch from resource " << resourceInstanceIdentifier;
127 auto result = facade->load(query); 126 auto result = facade->load(query);
128 if (result.second) { 127 if (result.second) {
129 aggregatingEmitter->addEmitter(result.second); 128 aggregatingEmitter->addEmitter(result.second);
130 } else { 129 } else {
131 Warning() << "Null emitter for resource " << resourceInstanceIdentifier; 130 SinkWarning() << "Null emitter for resource " << resourceInstanceIdentifier;
132 } 131 }
133 result.first.template then<void>([&future]() { future.setFinished(); }).exec(); 132 result.first.template then<void>([&future]() { future.setFinished(); }).exec();
134 } else { 133 } else {
135 Trace() << "Couldn' find a facade for " << resourceInstanceIdentifier; 134 SinkTrace() << "Couldn' find a facade for " << resourceInstanceIdentifier;
136 // Ignore the error and carry on 135 // Ignore the error and carry on
137 future.setFinished(); 136 future.setFinished();
138 } 137 }
@@ -164,7 +163,7 @@ KAsync::Job<void> Store::create(const DomainType &domainObject)
164{ 163{
165 // Potentially move to separate thread as well 164 // Potentially move to separate thread as well
166 auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier()); 165 auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier());
167 return facade->create(domainObject).template then<void>([facade]() {}, [](int errorCode, const QString &error) { Warning() << "Failed to create"; }); 166 return facade->create(domainObject).template then<void>([facade]() {}, [](int errorCode, const QString &error) { SinkWarning() << "Failed to create"; });
168} 167}
169 168
170template <class DomainType> 169template <class DomainType>
@@ -172,7 +171,7 @@ KAsync::Job<void> Store::modify(const DomainType &domainObject)
172{ 171{
173 // Potentially move to separate thread as well 172 // Potentially move to separate thread as well
174 auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier()); 173 auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier());
175 return facade->modify(domainObject).template then<void>([facade]() {}, [](int errorCode, const QString &error) { Warning() << "Failed to modify"; }); 174 return facade->modify(domainObject).template then<void>([facade]() {}, [](int errorCode, const QString &error) { SinkWarning() << "Failed to modify"; });
176} 175}
177 176
178template <class DomainType> 177template <class DomainType>
@@ -180,7 +179,7 @@ KAsync::Job<void> Store::remove(const DomainType &domainObject)
180{ 179{
181 // Potentially move to separate thread as well 180 // Potentially move to separate thread as well
182 auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier()); 181 auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier());
183 return facade->remove(domainObject).template then<void>([facade]() {}, [](int errorCode, const QString &error) { Warning() << "Failed to remove"; }); 182 return facade->remove(domainObject).template then<void>([facade]() {}, [](int errorCode, const QString &error) { SinkWarning() << "Failed to remove"; });
184} 183}
185 184
186KAsync::Job<void> Store::removeDataFromDisk(const QByteArray &identifier) 185KAsync::Job<void> Store::removeDataFromDisk(const QByteArray &identifier)
@@ -188,28 +187,28 @@ KAsync::Job<void> Store::removeDataFromDisk(const QByteArray &identifier)
188 // All databases are going to become invalid, nuke the environments 187 // All databases are going to become invalid, nuke the environments
189 // TODO: all clients should react to a notification the resource 188 // TODO: all clients should react to a notification the resource
190 Sink::Storage::clearEnv(); 189 Sink::Storage::clearEnv();
191 Trace() << "Remove data from disk " << identifier; 190 SinkTrace() << "Remove data from disk " << identifier;
192 auto time = QSharedPointer<QTime>::create(); 191 auto time = QSharedPointer<QTime>::create();
193 time->start(); 192 time->start();
194 auto resourceAccess = ResourceAccessFactory::instance().getAccess(identifier, ResourceConfig::getResourceType(identifier)); 193 auto resourceAccess = ResourceAccessFactory::instance().getAccess(identifier, ResourceConfig::getResourceType(identifier));
195 resourceAccess->open(); 194 resourceAccess->open();
196 return resourceAccess->sendCommand(Sink::Commands::RemoveFromDiskCommand) 195 return resourceAccess->sendCommand(Sink::Commands::RemoveFromDiskCommand)
197 .then<void>([resourceAccess, time]() { Trace() << "Remove from disk complete." << Log::TraceTime(time->elapsed()); }); 196 .then<void>([resourceAccess, time]() { SinkTrace() << "Remove from disk complete." << Log::TraceTime(time->elapsed()); });
198} 197}
199 198
200KAsync::Job<void> Store::synchronize(const Sink::Query &query) 199KAsync::Job<void> Store::synchronize(const Sink::Query &query)
201{ 200{
202 Trace() << "synchronize" << query.resources; 201 SinkTrace() << "synchronize" << query.resources;
203 auto resources = getResources(query.resources, query.accounts).keys(); 202 auto resources = getResources(query.resources, query.accounts).keys();
204 //FIXME only necessary because each doesn't propagate errors 203 //FIXME only necessary because each doesn't propagate errors
205 auto error = new bool; 204 auto error = new bool;
206 return KAsync::iterate(resources) 205 return KAsync::iterate(resources)
207 .template each<void, QByteArray>([query, error](const QByteArray &resource, KAsync::Future<void> &future) { 206 .template each<void, QByteArray>([query, error](const QByteArray &resource, KAsync::Future<void> &future) {
208 Trace() << "Synchronizing " << resource; 207 SinkTrace() << "Synchronizing " << resource;
209 auto resourceAccess = ResourceAccessFactory::instance().getAccess(resource, ResourceConfig::getResourceType(resource)); 208 auto resourceAccess = ResourceAccessFactory::instance().getAccess(resource, ResourceConfig::getResourceType(resource));
210 resourceAccess->open(); 209 resourceAccess->open();
211 resourceAccess->synchronizeResource(true, false).then<void>([resourceAccess, &future]() {Trace() << "synced."; future.setFinished(); }, 210 resourceAccess->synchronizeResource(true, false).then<void>([resourceAccess, &future]() {SinkTrace() << "synced."; future.setFinished(); },
212 [&future, error](int errorCode, QString msg) { *error = true; Warning() << "Error during sync."; future.setError(errorCode, msg); }).exec(); 211 [&future, error](int errorCode, QString msg) { *error = true; SinkWarning() << "Error during sync."; future.setError(errorCode, msg); }).exec();
213 }).then<void>([error](KAsync::Future<void> &future) { 212 }).then<void>([error](KAsync::Future<void> &future) {
214 if (*error) { 213 if (*error) {
215 future.setError(1, "Error during sync."); 214 future.setError(1, "Error during sync.");
@@ -306,25 +305,25 @@ QList<DomainType> Store::read(const Sink::Query &q)
306 auto resources = getResources(query.resources, query.accounts, ApplicationDomain::getTypeName<DomainType>()); 305 auto resources = getResources(query.resources, query.accounts, ApplicationDomain::getTypeName<DomainType>());
307 auto aggregatingEmitter = AggregatingResultEmitter<typename DomainType::Ptr>::Ptr::create(); 306 auto aggregatingEmitter = AggregatingResultEmitter<typename DomainType::Ptr>::Ptr::create();
308 aggregatingEmitter->onAdded([&list](const typename DomainType::Ptr &value){ 307 aggregatingEmitter->onAdded([&list](const typename DomainType::Ptr &value){
309 Trace() << "Found value: " << value->identifier(); 308 SinkTrace() << "Found value: " << value->identifier();
310 list << *value; 309 list << *value;
311 }); 310 });
312 for (const auto resourceInstanceIdentifier : resources.keys()) { 311 for (const auto resourceInstanceIdentifier : resources.keys()) {
313 const auto resourceType = resources.value(resourceInstanceIdentifier); 312 const auto resourceType = resources.value(resourceInstanceIdentifier);
314 Trace() << "Looking for " << resourceType << resourceInstanceIdentifier; 313 SinkTrace() << "Looking for " << resourceType << resourceInstanceIdentifier;
315 auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceType, resourceInstanceIdentifier); 314 auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceType, resourceInstanceIdentifier);
316 if (facade) { 315 if (facade) {
317 Trace() << "Trying to fetch from resource " << resourceInstanceIdentifier; 316 SinkTrace() << "Trying to fetch from resource " << resourceInstanceIdentifier;
318 auto result = facade->load(query); 317 auto result = facade->load(query);
319 if (result.second) { 318 if (result.second) {
320 aggregatingEmitter->addEmitter(result.second); 319 aggregatingEmitter->addEmitter(result.second);
321 } else { 320 } else {
322 Warning() << "Null emitter for resource " << resourceInstanceIdentifier; 321 SinkWarning() << "Null emitter for resource " << resourceInstanceIdentifier;
323 } 322 }
324 result.first.exec(); 323 result.first.exec();
325 aggregatingEmitter->fetch(typename DomainType::Ptr()); 324 aggregatingEmitter->fetch(typename DomainType::Ptr());
326 } else { 325 } else {
327 Trace() << "Couldn't find a facade for " << resourceInstanceIdentifier; 326 SinkTrace() << "Couldn't find a facade for " << resourceInstanceIdentifier;
328 // Ignore the error and carry on 327 // Ignore the error and carry on
329 } 328 }
330 } 329 }
diff --git a/common/synchronizer.cpp b/common/synchronizer.cpp
index 1374d00..2d4fb8d 100644
--- a/common/synchronizer.cpp
+++ b/common/synchronizer.cpp
@@ -29,6 +29,8 @@
29#include "modifyentity_generated.h" 29#include "modifyentity_generated.h"
30#include "deleteentity_generated.h" 30#include "deleteentity_generated.h"
31 31
32SINK_DEBUG_AREA("synchronizer")
33
32using namespace Sink; 34using namespace Sink;
33 35
34Synchronizer::Synchronizer(const QByteArray &resourceType, const QByteArray &resourceInstanceIdentifier) 36Synchronizer::Synchronizer(const QByteArray &resourceType, const QByteArray &resourceInstanceIdentifier)
@@ -37,7 +39,7 @@ Synchronizer::Synchronizer(const QByteArray &resourceType, const QByteArray &res
37 mResourceType(resourceType), 39 mResourceType(resourceType),
38 mResourceInstanceIdentifier(resourceInstanceIdentifier) 40 mResourceInstanceIdentifier(resourceInstanceIdentifier)
39{ 41{
40 Trace() << "Starting synchronizer: " << resourceType << resourceInstanceIdentifier; 42 SinkTrace() << "Starting synchronizer: " << resourceType << resourceInstanceIdentifier;
41} 43}
42 44
43Synchronizer::~Synchronizer() 45Synchronizer::~Synchronizer()
@@ -129,11 +131,11 @@ void Synchronizer::scanForRemovals(const QByteArray &bufferType, const std::func
129 entryGenerator([this, bufferType, &exists](const QByteArray &key) { 131 entryGenerator([this, bufferType, &exists](const QByteArray &key) {
130 auto sinkId = Sink::Storage::uidFromKey(key); 132 auto sinkId = Sink::Storage::uidFromKey(key);
131 const auto remoteId = syncStore().resolveLocalId(bufferType, sinkId); 133 const auto remoteId = syncStore().resolveLocalId(bufferType, sinkId);
132 Trace() << "Checking for removal " << key << remoteId; 134 SinkTrace() << "Checking for removal " << key << remoteId;
133 // If we have no remoteId, the entity hasn't been replayed to the source yet 135 // If we have no remoteId, the entity hasn't been replayed to the source yet
134 if (!remoteId.isEmpty()) { 136 if (!remoteId.isEmpty()) {
135 if (!exists(remoteId)) { 137 if (!exists(remoteId)) {
136 Trace() << "Found a removed entity: " << sinkId; 138 SinkTrace() << "Found a removed entity: " << sinkId;
137 deleteEntity(sinkId, Sink::Storage::maxRevision(transaction()), bufferType, 139 deleteEntity(sinkId, Sink::Storage::maxRevision(transaction()), bufferType,
138 [this](const QByteArray &buffer) { enqueueCommand(Sink::Commands::DeleteEntityCommand, buffer); }); 140 [this](const QByteArray &buffer) { enqueueCommand(Sink::Commands::DeleteEntityCommand, buffer); });
139 } 141 }
@@ -143,14 +145,14 @@ void Synchronizer::scanForRemovals(const QByteArray &bufferType, const std::func
143 145
144void Synchronizer::createOrModify(const QByteArray &bufferType, const QByteArray &remoteId, const Sink::ApplicationDomain::ApplicationDomainType &entity) 146void Synchronizer::createOrModify(const QByteArray &bufferType, const QByteArray &remoteId, const Sink::ApplicationDomain::ApplicationDomainType &entity)
145{ 147{
146 Trace() << "Create or modify" << bufferType << remoteId; 148 SinkTrace() << "Create or modify" << bufferType << remoteId;
147 auto mainDatabase = Storage::mainDatabase(transaction(), bufferType); 149 auto mainDatabase = Storage::mainDatabase(transaction(), bufferType);
148 const auto sinkId = syncStore().resolveRemoteId(bufferType, remoteId); 150 const auto sinkId = syncStore().resolveRemoteId(bufferType, remoteId);
149 const auto found = mainDatabase.contains(sinkId); 151 const auto found = mainDatabase.contains(sinkId);
150 auto adaptorFactory = Sink::AdaptorFactoryRegistry::instance().getFactory(mResourceType, bufferType); 152 auto adaptorFactory = Sink::AdaptorFactoryRegistry::instance().getFactory(mResourceType, bufferType);
151 Q_ASSERT(adaptorFactory); 153 Q_ASSERT(adaptorFactory);
152 if (!found) { 154 if (!found) {
153 Trace() << "Found a new entity: " << remoteId; 155 SinkTrace() << "Found a new entity: " << remoteId;
154 createEntity( 156 createEntity(
155 sinkId, bufferType, entity, *adaptorFactory, [this](const QByteArray &buffer) { enqueueCommand(Sink::Commands::CreateEntityCommand, buffer); }); 157 sinkId, bufferType, entity, *adaptorFactory, [this](const QByteArray &buffer) { enqueueCommand(Sink::Commands::CreateEntityCommand, buffer); });
156 } else { // modification 158 } else { // modification
@@ -159,17 +161,17 @@ void Synchronizer::createOrModify(const QByteArray &bufferType, const QByteArray
159 bool changed = false; 161 bool changed = false;
160 for (const auto &property : entity.changedProperties()) { 162 for (const auto &property : entity.changedProperties()) {
161 if (entity.getProperty(property) != current->getProperty(property)) { 163 if (entity.getProperty(property) != current->getProperty(property)) {
162 Trace() << "Property changed " << sinkId << property; 164 SinkTrace() << "Property changed " << sinkId << property;
163 changed = true; 165 changed = true;
164 } 166 }
165 } 167 }
166 if (changed) { 168 if (changed) {
167 Trace() << "Found a modified entity: " << remoteId; 169 SinkTrace() << "Found a modified entity: " << remoteId;
168 modifyEntity(sinkId, Sink::Storage::maxRevision(transaction()), bufferType, entity, *adaptorFactory, 170 modifyEntity(sinkId, Sink::Storage::maxRevision(transaction()), bufferType, entity, *adaptorFactory,
169 [this](const QByteArray &buffer) { enqueueCommand(Sink::Commands::ModifyEntityCommand, buffer); }); 171 [this](const QByteArray &buffer) { enqueueCommand(Sink::Commands::ModifyEntityCommand, buffer); });
170 } 172 }
171 } else { 173 } else {
172 Warning() << "Failed to get current entity"; 174 SinkWarning() << "Failed to get current entity";
173 } 175 }
174 } 176 }
175} 177}
@@ -178,7 +180,7 @@ template<typename DomainType>
178void Synchronizer::createOrModify(const QByteArray &bufferType, const QByteArray &remoteId, const DomainType &entity, const QHash<QByteArray, Sink::Query::Comparator> &mergeCriteria) 180void Synchronizer::createOrModify(const QByteArray &bufferType, const QByteArray &remoteId, const DomainType &entity, const QHash<QByteArray, Sink::Query::Comparator> &mergeCriteria)
179{ 181{
180 182
181 Trace() << "Create or modify" << bufferType << remoteId; 183 SinkTrace() << "Create or modify" << bufferType << remoteId;
182 auto mainDatabase = Storage::mainDatabase(transaction(), bufferType); 184 auto mainDatabase = Storage::mainDatabase(transaction(), bufferType);
183 const auto sinkId = syncStore().resolveRemoteId(bufferType, remoteId); 185 const auto sinkId = syncStore().resolveRemoteId(bufferType, remoteId);
184 const auto found = mainDatabase.contains(sinkId); 186 const auto found = mainDatabase.contains(sinkId);
@@ -192,17 +194,17 @@ void Synchronizer::createOrModify(const QByteArray &bufferType, const QByteArray
192 reader.query(query, 194 reader.query(query,
193 [this, bufferType, remoteId, &merge](const DomainType &o) -> bool{ 195 [this, bufferType, remoteId, &merge](const DomainType &o) -> bool{
194 merge = true; 196 merge = true;
195 Trace() << "Merging local entity with remote entity: " << o.identifier() << remoteId; 197 SinkTrace() << "Merging local entity with remote entity: " << o.identifier() << remoteId;
196 syncStore().recordRemoteId(bufferType, o.identifier(), remoteId); 198 syncStore().recordRemoteId(bufferType, o.identifier(), remoteId);
197 return false; 199 return false;
198 }); 200 });
199 if (!merge) { 201 if (!merge) {
200 Trace() << "Found a new entity: " << remoteId; 202 SinkTrace() << "Found a new entity: " << remoteId;
201 createEntity( 203 createEntity(
202 sinkId, bufferType, entity, *adaptorFactory, [this](const QByteArray &buffer) { enqueueCommand(Sink::Commands::CreateEntityCommand, buffer); }); 204 sinkId, bufferType, entity, *adaptorFactory, [this](const QByteArray &buffer) { enqueueCommand(Sink::Commands::CreateEntityCommand, buffer); });
203 } 205 }
204 } else { 206 } else {
205 Trace() << "Found a new entity: " << remoteId; 207 SinkTrace() << "Found a new entity: " << remoteId;
206 createEntity( 208 createEntity(
207 sinkId, bufferType, entity, *adaptorFactory, [this](const QByteArray &buffer) { enqueueCommand(Sink::Commands::CreateEntityCommand, buffer); }); 209 sinkId, bufferType, entity, *adaptorFactory, [this](const QByteArray &buffer) { enqueueCommand(Sink::Commands::CreateEntityCommand, buffer); });
208 } 210 }
@@ -212,17 +214,17 @@ void Synchronizer::createOrModify(const QByteArray &bufferType, const QByteArray
212 bool changed = false; 214 bool changed = false;
213 for (const auto &property : entity.changedProperties()) { 215 for (const auto &property : entity.changedProperties()) {
214 if (entity.getProperty(property) != current->getProperty(property)) { 216 if (entity.getProperty(property) != current->getProperty(property)) {
215 Trace() << "Property changed " << sinkId << property; 217 SinkTrace() << "Property changed " << sinkId << property;
216 changed = true; 218 changed = true;
217 } 219 }
218 } 220 }
219 if (changed) { 221 if (changed) {
220 Trace() << "Found a modified entity: " << remoteId; 222 SinkTrace() << "Found a modified entity: " << remoteId;
221 modifyEntity(sinkId, Sink::Storage::maxRevision(transaction()), bufferType, entity, *adaptorFactory, 223 modifyEntity(sinkId, Sink::Storage::maxRevision(transaction()), bufferType, entity, *adaptorFactory,
222 [this](const QByteArray &buffer) { enqueueCommand(Sink::Commands::ModifyEntityCommand, buffer); }); 224 [this](const QByteArray &buffer) { enqueueCommand(Sink::Commands::ModifyEntityCommand, buffer); });
223 } 225 }
224 } else { 226 } else {
225 Warning() << "Failed to get current entity"; 227 SinkWarning() << "Failed to get current entity";
226 } 228 }
227 } 229 }
228} 230}
@@ -239,7 +241,7 @@ void Synchronizer::modify(const DomainType &entity)
239 241
240KAsync::Job<void> Synchronizer::synchronize() 242KAsync::Job<void> Synchronizer::synchronize()
241{ 243{
242 Trace() << "Synchronizing"; 244 SinkTrace() << "Synchronizing";
243 mSyncInProgress = true; 245 mSyncInProgress = true;
244 mMessageQueue->startTransaction(); 246 mMessageQueue->startTransaction();
245 return synchronizeWithSource().then<void>([this]() { 247 return synchronizeWithSource().then<void>([this]() {
@@ -265,7 +267,7 @@ void Synchronizer::commit()
265Sink::Storage::Transaction &Synchronizer::transaction() 267Sink::Storage::Transaction &Synchronizer::transaction()
266{ 268{
267 if (!mTransaction) { 269 if (!mTransaction) {
268 Trace() << "Starting transaction"; 270 SinkTrace() << "Starting transaction";
269 mTransaction = mStorage.createTransaction(Sink::Storage::ReadOnly); 271 mTransaction = mStorage.createTransaction(Sink::Storage::ReadOnly);
270 } 272 }
271 return mTransaction; 273 return mTransaction;
@@ -274,7 +276,7 @@ Sink::Storage::Transaction &Synchronizer::transaction()
274Sink::Storage::Transaction &Synchronizer::syncTransaction() 276Sink::Storage::Transaction &Synchronizer::syncTransaction()
275{ 277{
276 if (!mSyncTransaction) { 278 if (!mSyncTransaction) {
277 Trace() << "Starting transaction"; 279 SinkTrace() << "Starting transaction";
278 mSyncTransaction = mSyncStorage.createTransaction(Sink::Storage::ReadWrite); 280 mSyncTransaction = mSyncStorage.createTransaction(Sink::Storage::ReadWrite);
279 } 281 }
280 return mSyncTransaction; 282 return mSyncTransaction;
diff --git a/common/test.cpp b/common/test.cpp
index 59ad9ec..5b4c899 100644
--- a/common/test.cpp
+++ b/common/test.cpp
@@ -27,11 +27,17 @@
27#include "facadefactory.h" 27#include "facadefactory.h"
28#include "query.h" 28#include "query.h"
29#include "resourceconfig.h" 29#include "resourceconfig.h"
30#include "definitions.h"
31
32SINK_DEBUG_AREA("test")
30 33
31using namespace Sink; 34using namespace Sink;
32 35
33void Sink::Test::initTest() 36void Sink::Test::initTest()
34{ 37{
38 auto logIniFile = Sink::configLocation() + "/log.ini";
39 auto areaAutocompletionFile = Sink::dataLocation() + "/debugAreas.ini";
40
35 setTestModeEnabled(true); 41 setTestModeEnabled(true);
36 // qDebug() << "Removing " << QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); 42 // qDebug() << "Removing " << QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
37 QDir(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)).removeRecursively(); 43 QDir(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)).removeRecursively();
@@ -45,6 +51,31 @@ void Sink::Test::initTest()
45 QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)).removeRecursively(); 51 QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)).removeRecursively();
46 // qDebug() << "Removing " << QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation); 52 // qDebug() << "Removing " << QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation);
47 QDir(QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation)).removeRecursively(); 53 QDir(QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation)).removeRecursively();
54 Log::setPrimaryComponent("test");
55
56 //We copy those files so we can control debug output from outside the test with sinksh
57 {
58 QFile file(logIniFile);
59 if (!file.open(QIODevice::ReadOnly)) {
60 qWarning() << "Failed to open the file: " << logIniFile;
61 }
62 QDir dir;
63 dir.mkpath(Sink::configLocation());
64 if (!file.copy(Sink::configLocation() + "/log.ini")) {
65 qWarning() << "Failed to move the file: " << Sink::configLocation() + "/log.ini";
66 }
67 }
68 {
69 QFile file(areaAutocompletionFile);
70 if (!file.open(QIODevice::ReadOnly)) {
71 qWarning() << "Failed to open the file: " << logIniFile;
72 }
73 QDir dir;
74 dir.mkpath(Sink::dataLocation());
75 if (!file.copy(Sink::dataLocation() + "/debugAreas.ini")) {
76 qWarning() << "Failed to move the file: " << Sink::configLocation() + "/log.ini";
77 }
78 }
48} 79}
49 80
50void Sink::Test::setTestModeEnabled(bool enabled) 81void Sink::Test::setTestModeEnabled(bool enabled)
@@ -102,7 +133,7 @@ public:
102 { 133 {
103 auto resultProvider = new Sink::ResultProvider<typename T::Ptr>(); 134 auto resultProvider = new Sink::ResultProvider<typename T::Ptr>();
104 resultProvider->onDone([resultProvider]() { 135 resultProvider->onDone([resultProvider]() {
105 Trace() << "Result provider is done"; 136 SinkTrace() << "Result provider is done";
106 delete resultProvider; 137 delete resultProvider;
107 }); 138 });
108 // We have to do it this way, otherwise we're not setting the fetcher right 139 // We have to do it this way, otherwise we're not setting the fetcher right
@@ -110,11 +141,11 @@ public:
110 141
111 resultProvider->setFetcher([query, resultProvider, this](const typename T::Ptr &parent) { 142 resultProvider->setFetcher([query, resultProvider, this](const typename T::Ptr &parent) {
112 if (parent) { 143 if (parent) {
113 Trace() << "Running the fetcher " << parent->identifier(); 144 SinkTrace() << "Running the fetcher " << parent->identifier();
114 } else { 145 } else {
115 Trace() << "Running the fetcher."; 146 SinkTrace() << "Running the fetcher.";
116 } 147 }
117 Trace() << "-------------------------."; 148 SinkTrace() << "-------------------------.";
118 for (const auto &res : mTestAccount->entities<T>()) { 149 for (const auto &res : mTestAccount->entities<T>()) {
119 qDebug() << "Parent filter " << query.propertyFilter.value("parent").value.toByteArray() << res->identifier() << res->getProperty("parent").toByteArray(); 150 qDebug() << "Parent filter " << query.propertyFilter.value("parent").value.toByteArray() << res->identifier() << res->getProperty("parent").toByteArray();
120 auto parentProperty = res->getProperty("parent").toByteArray(); 151 auto parentProperty = res->getProperty("parent").toByteArray();
diff --git a/common/typeindex.cpp b/common/typeindex.cpp
index 05bbf5c..78195d3 100644
--- a/common/typeindex.cpp
+++ b/common/typeindex.cpp
@@ -22,8 +22,7 @@
22#include "index.h" 22#include "index.h"
23#include <QDateTime> 23#include <QDateTime>
24 24
25#undef DEBUG_AREA 25SINK_DEBUG_AREA("typeindex")
26#define DEBUG_AREA "common.typeindex"
27 26
28static QByteArray getByteArray(const QVariant &value) 27static QByteArray getByteArray(const QVariant &value)
29{ 28{
@@ -63,7 +62,7 @@ template <>
63void TypeIndex::addProperty<QByteArray>(const QByteArray &property) 62void TypeIndex::addProperty<QByteArray>(const QByteArray &property)
64{ 63{
65 auto indexer = [this, property](const QByteArray &identifier, const QVariant &value, Sink::Storage::Transaction &transaction) { 64 auto indexer = [this, property](const QByteArray &identifier, const QVariant &value, Sink::Storage::Transaction &transaction) {
66 // Trace() << "Indexing " << mType + ".index." + property << value.toByteArray(); 65 // SinkTrace() << "Indexing " << mType + ".index." + property << value.toByteArray();
67 Index(indexName(property), transaction).add(getByteArray(value), identifier); 66 Index(indexName(property), transaction).add(getByteArray(value), identifier);
68 }; 67 };
69 mIndexer.insert(property, indexer); 68 mIndexer.insert(property, indexer);
@@ -74,7 +73,7 @@ template <>
74void TypeIndex::addProperty<QString>(const QByteArray &property) 73void TypeIndex::addProperty<QString>(const QByteArray &property)
75{ 74{
76 auto indexer = [this, property](const QByteArray &identifier, const QVariant &value, Sink::Storage::Transaction &transaction) { 75 auto indexer = [this, property](const QByteArray &identifier, const QVariant &value, Sink::Storage::Transaction &transaction) {
77 // Trace() << "Indexing " << mType + ".index." + property << value.toByteArray(); 76 // SinkTrace() << "Indexing " << mType + ".index." + property << value.toByteArray();
78 Index(indexName(property), transaction).add(getByteArray(value), identifier); 77 Index(indexName(property), transaction).add(getByteArray(value), identifier);
79 }; 78 };
80 mIndexer.insert(property, indexer); 79 mIndexer.insert(property, indexer);
@@ -85,7 +84,7 @@ template <>
85void TypeIndex::addProperty<QDateTime>(const QByteArray &property) 84void TypeIndex::addProperty<QDateTime>(const QByteArray &property)
86{ 85{
87 auto indexer = [this, property](const QByteArray &identifier, const QVariant &value, Sink::Storage::Transaction &transaction) { 86 auto indexer = [this, property](const QByteArray &identifier, const QVariant &value, Sink::Storage::Transaction &transaction) {
88 // Trace() << "Indexing " << mType + ".index." + property << date.toString(); 87 // SinkTrace() << "Indexing " << mType + ".index." + property << date.toString();
89 Index(indexName(property), transaction).add(getByteArray(value), identifier); 88 Index(indexName(property), transaction).add(getByteArray(value), identifier);
90 }; 89 };
91 mIndexer.insert(property, indexer); 90 mIndexer.insert(property, indexer);
@@ -143,12 +142,12 @@ ResultSet TypeIndex::query(const Sink::Query &query, QSet<QByteArray> &appliedFi
143 if (query.propertyFilter.contains(it.key()) && query.sortProperty == it.value()) { 142 if (query.propertyFilter.contains(it.key()) && query.sortProperty == it.value()) {
144 Index index(indexName(it.key(), it.value()), transaction); 143 Index index(indexName(it.key(), it.value()), transaction);
145 const auto lookupKey = getByteArray(query.propertyFilter.value(it.key()).value); 144 const auto lookupKey = getByteArray(query.propertyFilter.value(it.key()).value);
146 Trace() << "looking for " << lookupKey; 145 SinkTrace() << "looking for " << lookupKey;
147 index.lookup(lookupKey, [&](const QByteArray &value) { keys << value; }, 146 index.lookup(lookupKey, [&](const QByteArray &value) { keys << value; },
148 [it](const Index::Error &error) { Warning() << "Error in index: " << error.message << it.key() << it.value(); }, true); 147 [it](const Index::Error &error) { SinkWarning() << "Error in index: " << error.message << it.key() << it.value(); }, true);
149 appliedFilters << it.key(); 148 appliedFilters << it.key();
150 appliedSorting = it.value(); 149 appliedSorting = it.value();
151 Trace() << "Index lookup on " << it.key() << it.value() << " found " << keys.size() << " keys."; 150 SinkTrace() << "Index lookup on " << it.key() << it.value() << " found " << keys.size() << " keys.";
152 return ResultSet(keys); 151 return ResultSet(keys);
153 } 152 }
154 } 153 }
@@ -157,12 +156,12 @@ ResultSet TypeIndex::query(const Sink::Query &query, QSet<QByteArray> &appliedFi
157 Index index(indexName(property), transaction); 156 Index index(indexName(property), transaction);
158 const auto lookupKey = getByteArray(query.propertyFilter.value(property).value); 157 const auto lookupKey = getByteArray(query.propertyFilter.value(property).value);
159 index.lookup( 158 index.lookup(
160 lookupKey, [&](const QByteArray &value) { keys << value; }, [property](const Index::Error &error) { Warning() << "Error in index: " << error.message << property; }); 159 lookupKey, [&](const QByteArray &value) { keys << value; }, [property](const Index::Error &error) { SinkWarning() << "Error in index: " << error.message << property; });
161 appliedFilters << property; 160 appliedFilters << property;
162 Trace() << "Index lookup on " << property << " found " << keys.size() << " keys."; 161 SinkTrace() << "Index lookup on " << property << " found " << keys.size() << " keys.";
163 return ResultSet(keys); 162 return ResultSet(keys);
164 } 163 }
165 } 164 }
166 Trace() << "No matching index"; 165 SinkTrace() << "No matching index";
167 return ResultSet(keys); 166 return ResultSet(keys);
168} 167}
diff --git a/docs/sinksh.md b/docs/sinksh.md
index 9884169..b04eb0c 100644
--- a/docs/sinksh.md
+++ b/docs/sinksh.md
@@ -33,22 +33,22 @@ Provides the same contents as "list" but in a graphical tree view. This was real
33# Setting up a new resource instance 33# Setting up a new resource instance
34sink_cmd is already the primary way how you create resource instances: 34sink_cmd is already the primary way how you create resource instances:
35 35
36 `sinksh create resource org.kde.maildir path /home/developer/maildir1` 36 `sinksh create resource sink.maildir path /home/developer/maildir1`
37 37
38This creates a resource of type "org.kde.maildir" and a configuration of "path" with the value "home/developer/maildir1". Resources are stored in configuration files, so all this does is write to some config files. 38This creates a resource of type "sink.maildir" and a configuration of "path" with the value "home/developer/maildir1". Resources are stored in configuration files, so all this does is write to some config files.
39 39
40 `sinksh list resource` 40 `sinksh list resource`
41 41
42By listing all available resources we can find the identifier of the resource that was automatically assigned. 42By listing all available resources we can find the identifier of the resource that was automatically assigned.
43 43
44 `sinksh synchronize org.kde.maildir.instance1` 44 `sinksh synchronize sink.maildir.instance1`
45 45
46This triggers the actual synchronization in the resource, and from there on the data is available. 46This triggers the actual synchronization in the resource, and from there on the data is available.
47 47
48 `sinksh list folder org.kde.maildir.instance1` 48 `sinksh list folder sink.maildir.instance1`
49 49
50This will get you all folders that are in the resource. 50This will get you all folders that are in the resource.
51 51
52 `sinksh remove resource org.kde.maildir.instance1` 52 `sinksh remove resource sink.maildir.instance1`
53 53
54And this will finally remove all traces of the resource instance. 54And this will finally remove all traces of the resource instance.
diff --git a/examples/client/main.cpp b/examples/client/main.cpp
index 07e780e..f4b472f 100644
--- a/examples/client/main.cpp
+++ b/examples/client/main.cpp
@@ -120,7 +120,7 @@ public:
120 syncButton->setText("Synchronize!"); 120 syncButton->setText("Synchronize!");
121 QObject::connect(syncButton, &QPushButton::pressed, []() { 121 QObject::connect(syncButton, &QPushButton::pressed, []() {
122 Sink::Query query; 122 Sink::Query query;
123 query.resources << "org.kde.dummy.instance1"; 123 query.resources << "sink.dummy.instance1";
124 Sink::Store::synchronize(query).exec(); 124 Sink::Store::synchronize(query).exec();
125 }); 125 });
126 126
diff --git a/examples/dummyresource/resourcefactory.cpp b/examples/dummyresource/resourcefactory.cpp
index 2bd52cc..0f7463f 100644
--- a/examples/dummyresource/resourcefactory.cpp
+++ b/examples/dummyresource/resourcefactory.cpp
@@ -23,6 +23,7 @@
23#include "entitybuffer.h" 23#include "entitybuffer.h"
24#include "pipeline.h" 24#include "pipeline.h"
25#include "dummycalendar_generated.h" 25#include "dummycalendar_generated.h"
26#include "notification_generated.h"
26#include "mail_generated.h" 27#include "mail_generated.h"
27#include "createentity_generated.h" 28#include "createentity_generated.h"
28#include "domainadaptor.h" 29#include "domainadaptor.h"
@@ -47,6 +48,8 @@
47#define ENTITY_TYPE_MAIL "mail" 48#define ENTITY_TYPE_MAIL "mail"
48#define ENTITY_TYPE_FOLDER "folder" 49#define ENTITY_TYPE_FOLDER "folder"
49 50
51SINK_DEBUG_AREA("dummyresource")
52
50class DummySynchronizer : public Sink::Synchronizer { 53class DummySynchronizer : public Sink::Synchronizer {
51 public: 54 public:
52 55
@@ -104,12 +107,12 @@ class DummySynchronizer : public Sink::Synchronizer {
104 auto entity = createEntity(remoteId, it.value()); 107 auto entity = createEntity(remoteId, it.value());
105 createOrModify(bufferType, remoteId, *entity); 108 createOrModify(bufferType, remoteId, *entity);
106 } 109 }
107 Trace() << "Sync of " << count << " entities of type " << bufferType << " done." << Sink::Log::TraceTime(time->elapsed()); 110 SinkTrace() << "Sync of " << count << " entities of type " << bufferType << " done." << Sink::Log::TraceTime(time->elapsed());
108 } 111 }
109 112
110 KAsync::Job<void> synchronizeWithSource() Q_DECL_OVERRIDE 113 KAsync::Job<void> synchronizeWithSource() Q_DECL_OVERRIDE
111 { 114 {
112 Log() << " Synchronizing with the source"; 115 SinkLog() << " Synchronizing with the source";
113 return KAsync::start<void>([this]() { 116 return KAsync::start<void>([this]() {
114 synchronize(ENTITY_TYPE_EVENT, DummyStore::instance().events(), [this](const QByteArray &ridBuffer, const QMap<QString, QVariant> &data) { 117 synchronize(ENTITY_TYPE_EVENT, DummyStore::instance().events(), [this](const QByteArray &ridBuffer, const QMap<QString, QVariant> &data) {
115 return createEvent(ridBuffer, data); 118 return createEvent(ridBuffer, data);
@@ -120,7 +123,7 @@ class DummySynchronizer : public Sink::Synchronizer {
120 synchronize(ENTITY_TYPE_FOLDER, DummyStore::instance().folders(), [this](const QByteArray &ridBuffer, const QMap<QString, QVariant> &data) { 123 synchronize(ENTITY_TYPE_FOLDER, DummyStore::instance().folders(), [this](const QByteArray &ridBuffer, const QMap<QString, QVariant> &data) {
121 return createFolder(ridBuffer, data); 124 return createFolder(ridBuffer, data);
122 }); 125 });
123 Log() << "Done Synchronizing"; 126 SinkLog() << "Done Synchronizing";
124 }); 127 });
125 } 128 }
126 129
@@ -144,10 +147,22 @@ DummyResource::~DummyResource()
144 147
145} 148}
146 149
150KAsync::Job<void> DummyResource::synchronizeWithSource()
151{
152 SinkTrace() << "Synchronize with source and sending a notification about it";
153 Sink::Notification n;
154 n.id = "connected";
155 n.type = Sink::Notification::Status;
156 n.message = "We're connected";
157 n.code = Sink::ApplicationDomain::ConnectedStatus;
158 emit notify(n);
159 return GenericResource::synchronizeWithSource();
160}
161
147KAsync::Job<void> DummyResource::inspect(int inspectionType, const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expectedValue) 162KAsync::Job<void> DummyResource::inspect(int inspectionType, const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expectedValue)
148{ 163{
149 164
150 Trace() << "Inspecting " << inspectionType << domainType << entityId << property << expectedValue; 165 SinkTrace() << "Inspecting " << inspectionType << domainType << entityId << property << expectedValue;
151 if (property == "testInspection") { 166 if (property == "testInspection") {
152 if (expectedValue.toBool()) { 167 if (expectedValue.toBool()) {
153 //Success 168 //Success
diff --git a/examples/dummyresource/resourcefactory.h b/examples/dummyresource/resourcefactory.h
index 1c51b00..9192c68 100644
--- a/examples/dummyresource/resourcefactory.h
+++ b/examples/dummyresource/resourcefactory.h
@@ -27,7 +27,7 @@
27#include <flatbuffers/flatbuffers.h> 27#include <flatbuffers/flatbuffers.h>
28 28
29//TODO: a little ugly to have this in two places, once here and once in Q_PLUGIN_METADATA 29//TODO: a little ugly to have this in two places, once here and once in Q_PLUGIN_METADATA
30#define PLUGIN_NAME "org.kde.dummy" 30#define PLUGIN_NAME "sink.dummy"
31 31
32class DummyResource : public Sink::GenericResource 32class DummyResource : public Sink::GenericResource
33{ 33{
@@ -35,13 +35,14 @@ public:
35 DummyResource(const QByteArray &instanceIdentifier, const QSharedPointer<Sink::Pipeline> &pipeline = QSharedPointer<Sink::Pipeline>()); 35 DummyResource(const QByteArray &instanceIdentifier, const QSharedPointer<Sink::Pipeline> &pipeline = QSharedPointer<Sink::Pipeline>());
36 virtual ~DummyResource(); 36 virtual ~DummyResource();
37 37
38 KAsync::Job<void> synchronizeWithSource() Q_DECL_OVERRIDE;
38 KAsync::Job<void> inspect(int inspectionType, const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expectedValue) Q_DECL_OVERRIDE; 39 KAsync::Job<void> inspect(int inspectionType, const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expectedValue) Q_DECL_OVERRIDE;
39}; 40};
40 41
41class DummyResourceFactory : public Sink::ResourceFactory 42class DummyResourceFactory : public Sink::ResourceFactory
42{ 43{
43 Q_OBJECT 44 Q_OBJECT
44 Q_PLUGIN_METADATA(IID "org.kde.dummy") 45 Q_PLUGIN_METADATA(IID "sink.dummy")
45 Q_INTERFACES(Sink::ResourceFactory) 46 Q_INTERFACES(Sink::ResourceFactory)
46 47
47public: 48public:
diff --git a/examples/imapresource/imapresource.cpp b/examples/imapresource/imapresource.cpp
index e23add8..92f64bf 100644
--- a/examples/imapresource/imapresource.cpp
+++ b/examples/imapresource/imapresource.cpp
@@ -54,8 +54,7 @@
54#define ENTITY_TYPE_MAIL "mail" 54#define ENTITY_TYPE_MAIL "mail"
55#define ENTITY_TYPE_FOLDER "folder" 55#define ENTITY_TYPE_FOLDER "folder"
56 56
57#undef DEBUG_AREA 57SINK_DEBUG_AREA("imapresource")
58#define DEBUG_AREA "resource.imap"
59 58
60using namespace Imap; 59using namespace Imap;
61using namespace Sink; 60using namespace Sink;
@@ -95,7 +94,7 @@ public:
95 94
96 QByteArray createFolder(const QString &folderName, const QString &folderPath, const QString &parentFolderRid, const QByteArray &icon) 95 QByteArray createFolder(const QString &folderName, const QString &folderPath, const QString &parentFolderRid, const QByteArray &icon)
97 { 96 {
98 Trace() << "Creating folder: " << folderName << parentFolderRid; 97 SinkTrace() << "Creating folder: " << folderName << parentFolderRid;
99 const auto remoteId = folderPath.toUtf8(); 98 const auto remoteId = folderPath.toUtf8();
100 const auto bufferType = ENTITY_TYPE_FOLDER; 99 const auto bufferType = ENTITY_TYPE_FOLDER;
101 Sink::ApplicationDomain::Folder folder; 100 Sink::ApplicationDomain::Folder folder;
@@ -118,7 +117,7 @@ public:
118 void synchronizeFolders(const QVector<Folder> &folderList) 117 void synchronizeFolders(const QVector<Folder> &folderList)
119 { 118 {
120 const QByteArray bufferType = ENTITY_TYPE_FOLDER; 119 const QByteArray bufferType = ENTITY_TYPE_FOLDER;
121 Trace() << "Found folders " << folderList.size(); 120 SinkTrace() << "Found folders " << folderList.size();
122 121
123 scanForRemovals(bufferType, 122 scanForRemovals(bufferType,
124 [this, &bufferType](const std::function<void(const QByteArray &)> &callback) { 123 [this, &bufferType](const std::function<void(const QByteArray &)> &callback) {
@@ -154,7 +153,7 @@ public:
154 time->start(); 153 time->start();
155 const QByteArray bufferType = ENTITY_TYPE_MAIL; 154 const QByteArray bufferType = ENTITY_TYPE_MAIL;
156 155
157 Trace() << "Importing new mail." << path; 156 SinkTrace() << "Importing new mail." << path;
158 157
159 const auto folderLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, path.toUtf8()); 158 const auto folderLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, path.toUtf8());
160 159
@@ -163,7 +162,7 @@ public:
163 count++; 162 count++;
164 const auto remoteId = assembleMailRid(folderLocalId, message.uid); 163 const auto remoteId = assembleMailRid(folderLocalId, message.uid);
165 164
166 Trace() << "Found a mail " << remoteId << message.msg->subject(true)->asUnicodeString() << message.flags; 165 SinkTrace() << "Found a mail " << remoteId << message.msg->subject(true)->asUnicodeString() << message.flags;
167 166
168 auto mail = Sink::ApplicationDomain::Mail::create(mResourceInstanceIdentifier); 167 auto mail = Sink::ApplicationDomain::Mail::create(mResourceInstanceIdentifier);
169 mail.setFolder(folderLocalId); 168 mail.setFolder(folderLocalId);
@@ -174,7 +173,7 @@ public:
174 createOrModify(bufferType, remoteId, mail); 173 createOrModify(bufferType, remoteId, mail);
175 } 174 }
176 const auto elapsed = time->elapsed(); 175 const auto elapsed = time->elapsed();
177 Log() << "Synchronized " << count << " mails in " << path << Sink::Log::TraceTime(elapsed) << " " << elapsed/qMax(count, 1) << " [ms/mail]"; 176 SinkLog() << "Synchronized " << count << " mails in " << path << Sink::Log::TraceTime(elapsed) << " " << elapsed/qMax(count, 1) << " [ms/mail]";
178 } 177 }
179 178
180 void synchronizeRemovals(const QString &path, const QSet<qint64> &messages) 179 void synchronizeRemovals(const QString &path, const QSet<qint64> &messages)
@@ -183,7 +182,7 @@ public:
183 time->start(); 182 time->start();
184 const QByteArray bufferType = ENTITY_TYPE_MAIL; 183 const QByteArray bufferType = ENTITY_TYPE_MAIL;
185 184
186 Trace() << "Finding removed mail."; 185 SinkTrace() << "Finding removed mail.";
187 186
188 const auto folderLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, path.toUtf8()); 187 const auto folderLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, path.toUtf8());
189 188
@@ -196,7 +195,7 @@ public:
196 callback(sinkId); 195 callback(sinkId);
197 }, 196 },
198 [&](const Index::Error &error) { 197 [&](const Index::Error &error) {
199 Warning() << "Error in index: " << error.message << property; 198 SinkWarning() << "Error in index: " << error.message << property;
200 }); 199 });
201 }, 200 },
202 [messages, path, &count](const QByteArray &remoteId) -> bool { 201 [messages, path, &count](const QByteArray &remoteId) -> bool {
@@ -209,24 +208,24 @@ public:
209 ); 208 );
210 209
211 const auto elapsed = time->elapsed(); 210 const auto elapsed = time->elapsed();
212 Log() << "Removed " << count << " mails in " << path << Sink::Log::TraceTime(elapsed) << " " << elapsed/qMax(count, 1) << " [ms/mail]"; 211 SinkLog() << "Removed " << count << " mails in " << path << Sink::Log::TraceTime(elapsed) << " " << elapsed/qMax(count, 1) << " [ms/mail]";
213 } 212 }
214 213
215 KAsync::Job<void> synchronizeWithSource() Q_DECL_OVERRIDE 214 KAsync::Job<void> synchronizeWithSource() Q_DECL_OVERRIDE
216 { 215 {
217 Log() << " Synchronizing"; 216 SinkLog() << " Synchronizing";
218 return KAsync::start<void>([this](KAsync::Future<void> future) { 217 return KAsync::start<void>([this](KAsync::Future<void> future) {
219 Trace() << "Connecting to:" << mServer << mPort; 218 SinkTrace() << "Connecting to:" << mServer << mPort;
220 Trace() << "as:" << mUser; 219 SinkTrace() << "as:" << mUser;
221 ImapServerProxy imap(mServer, mPort); 220 ImapServerProxy imap(mServer, mPort);
222 auto loginFuture = imap.login(mUser, mPassword).exec(); 221 auto loginFuture = imap.login(mUser, mPassword).exec();
223 loginFuture.waitForFinished(); 222 loginFuture.waitForFinished();
224 if (loginFuture.errorCode()) { 223 if (loginFuture.errorCode()) {
225 Warning() << "Login failed."; 224 SinkWarning() << "Login failed.";
226 future.setError(1, "Login failed"); 225 future.setError(1, "Login failed");
227 return; 226 return;
228 } else { 227 } else {
229 Trace() << "Login was successful"; 228 SinkTrace() << "Login was successful";
230 } 229 }
231 230
232 QVector<Folder> folderList; 231 QVector<Folder> folderList;
@@ -238,11 +237,11 @@ public:
238 }).exec(); 237 }).exec();
239 folderFuture.waitForFinished(); 238 folderFuture.waitForFinished();
240 if (folderFuture.errorCode()) { 239 if (folderFuture.errorCode()) {
241 Warning() << "Folder sync failed."; 240 SinkWarning() << "Folder sync failed.";
242 future.setError(1, "Folder list sync failed"); 241 future.setError(1, "Folder list sync failed");
243 return; 242 return;
244 } else { 243 } else {
245 Trace() << "Folder sync was successful"; 244 SinkTrace() << "Folder sync was successful";
246 } 245 }
247 246
248 for (const auto &folder : folderList) { 247 for (const auto &folder : folderList) {
@@ -251,7 +250,7 @@ public:
251 } 250 }
252 QSet<qint64> uids; 251 QSet<qint64> uids;
253 auto messagesFuture = imap.fetchMessages(folder, [this, folder, &uids](const QVector<Message> &messages) { 252 auto messagesFuture = imap.fetchMessages(folder, [this, folder, &uids](const QVector<Message> &messages) {
254 Trace() << "Synchronizing mails" << folder.normalizedPath(); 253 SinkTrace() << "Synchronizing mails" << folder.normalizedPath();
255 for (const auto &msg : messages) { 254 for (const auto &msg : messages) {
256 uids << msg.uid; 255 uids << msg.uid;
257 } 256 }
@@ -260,16 +259,16 @@ public:
260 messagesFuture.waitForFinished(); 259 messagesFuture.waitForFinished();
261 commit(); 260 commit();
262 if (messagesFuture.errorCode()) { 261 if (messagesFuture.errorCode()) {
263 Warning() << "Folder sync failed: " << folder.normalizedPath(); 262 SinkWarning() << "Folder sync failed: " << folder.normalizedPath();
264 continue; 263 continue;
265 } 264 }
266 //Remove what there is to remove 265 //Remove what there is to remove
267 synchronizeRemovals(folder.normalizedPath(), uids); 266 synchronizeRemovals(folder.normalizedPath(), uids);
268 commit(); 267 commit();
269 Trace() << "Folder synchronized: " << folder.normalizedPath(); 268 SinkTrace() << "Folder synchronized: " << folder.normalizedPath();
270 } 269 }
271 270
272 Log() << "Done Synchronizing"; 271 SinkLog() << "Done Synchronizing";
273 future.setFinished(); 272 future.setFinished();
274 }); 273 });
275 } 274 }
@@ -310,7 +309,7 @@ public:
310 .then<void, qint64>([imap, mailbox, rid, mail](qint64 uid) { 309 .then<void, qint64>([imap, mailbox, rid, mail](qint64 uid) {
311 const auto remoteId = assembleMailRid(mail, uid); 310 const auto remoteId = assembleMailRid(mail, uid);
312 //FIXME this get's called after the final error handler? WTF? 311 //FIXME this get's called after the final error handler? WTF?
313 Trace() << "Finished creating a new mail: " << remoteId; 312 SinkTrace() << "Finished creating a new mail: " << remoteId;
314 *rid = remoteId; 313 *rid = remoteId;
315 }).then<QByteArray>([rid, imap]() { //FIXME fix KJob so we don't need this extra clause 314 }).then<QByteArray>([rid, imap]() { //FIXME fix KJob so we don't need this extra clause
316 return *rid; 315 return *rid;
@@ -319,19 +318,19 @@ public:
319 const auto folderId = folderIdFromMailRid(oldRemoteId); 318 const auto folderId = folderIdFromMailRid(oldRemoteId);
320 const QString mailbox = syncStore().resolveLocalId(ENTITY_TYPE_FOLDER, folderId); 319 const QString mailbox = syncStore().resolveLocalId(ENTITY_TYPE_FOLDER, folderId);
321 const auto uid = uidFromMailRid(oldRemoteId); 320 const auto uid = uidFromMailRid(oldRemoteId);
322 Trace() << "Removing a mail: " << oldRemoteId << "in the mailbox: " << mailbox; 321 SinkTrace() << "Removing a mail: " << oldRemoteId << "in the mailbox: " << mailbox;
323 KIMAP::ImapSet set; 322 KIMAP::ImapSet set;
324 set.add(uid); 323 set.add(uid);
325 return login.then(imap->remove(mailbox, set)) 324 return login.then(imap->remove(mailbox, set))
326 .then<QByteArray>([imap, oldRemoteId]() { 325 .then<QByteArray>([imap, oldRemoteId]() {
327 Trace() << "Finished removing a mail: " << oldRemoteId; 326 SinkTrace() << "Finished removing a mail: " << oldRemoteId;
328 return QByteArray(); 327 return QByteArray();
329 }); 328 });
330 } else if (operation == Sink::Operation_Modification) { 329 } else if (operation == Sink::Operation_Modification) {
331 const QString mailbox = syncStore().resolveLocalId(ENTITY_TYPE_FOLDER, mail.getFolder()); 330 const QString mailbox = syncStore().resolveLocalId(ENTITY_TYPE_FOLDER, mail.getFolder());
332 const auto uid = uidFromMailRid(oldRemoteId); 331 const auto uid = uidFromMailRid(oldRemoteId);
333 332
334 Trace() << "Modifying a mail: " << oldRemoteId << " in the mailbox: " << mailbox << changedProperties; 333 SinkTrace() << "Modifying a mail: " << oldRemoteId << " in the mailbox: " << mailbox << changedProperties;
335 334
336 QByteArrayList flags; 335 QByteArrayList flags;
337 if (!mail.getUnread()) { 336 if (!mail.getUnread()) {
@@ -344,7 +343,7 @@ public:
344 const bool messageMoved = changedProperties.contains(ApplicationDomain::Mail::Folder::name); 343 const bool messageMoved = changedProperties.contains(ApplicationDomain::Mail::Folder::name);
345 const bool messageChanged = changedProperties.contains(ApplicationDomain::Mail::MimeMessage::name); 344 const bool messageChanged = changedProperties.contains(ApplicationDomain::Mail::MimeMessage::name);
346 if (messageChanged || messageMoved) { 345 if (messageChanged || messageMoved) {
347 Trace() << "Replacing message."; 346 SinkTrace() << "Replacing message.";
348 const auto folderId = folderIdFromMailRid(oldRemoteId); 347 const auto folderId = folderIdFromMailRid(oldRemoteId);
349 const QString oldMailbox = syncStore().resolveLocalId(ENTITY_TYPE_FOLDER, folderId); 348 const QString oldMailbox = syncStore().resolveLocalId(ENTITY_TYPE_FOLDER, folderId);
350 QByteArray content = KMime::LFtoCRLF(mail.getMimeMessage()); 349 QByteArray content = KMime::LFtoCRLF(mail.getMimeMessage());
@@ -355,7 +354,7 @@ public:
355 return login.then(imap->append(mailbox, content, flags, internalDate)) 354 return login.then(imap->append(mailbox, content, flags, internalDate))
356 .then<void, qint64>([imap, mailbox, rid, mail](qint64 uid) { 355 .then<void, qint64>([imap, mailbox, rid, mail](qint64 uid) {
357 const auto remoteId = assembleMailRid(mail, uid); 356 const auto remoteId = assembleMailRid(mail, uid);
358 Trace() << "Finished creating a modified mail: " << remoteId; 357 SinkTrace() << "Finished creating a modified mail: " << remoteId;
359 *rid = remoteId; 358 *rid = remoteId;
360 }) 359 })
361 .then(imap->remove(oldMailbox, set)) 360 .then(imap->remove(oldMailbox, set))
@@ -363,13 +362,13 @@ public:
363 return *rid; 362 return *rid;
364 }); 363 });
365 } else { 364 } else {
366 Trace() << "Updating flags only."; 365 SinkTrace() << "Updating flags only.";
367 KIMAP::ImapSet set; 366 KIMAP::ImapSet set;
368 set.add(uid); 367 set.add(uid);
369 return login.then(imap->select(mailbox)) 368 return login.then(imap->select(mailbox))
370 .then(imap->storeFlags(set, flags)) 369 .then(imap->storeFlags(set, flags))
371 .then<void>([imap, mailbox]() { 370 .then<void>([imap, mailbox]() {
372 Trace() << "Finished modifying mail"; 371 SinkTrace() << "Finished modifying mail";
373 }) 372 })
374 .then<QByteArray>([oldRemoteId, imap]() { 373 .then<QByteArray>([oldRemoteId, imap]() {
375 return oldRemoteId; 374 return oldRemoteId;
@@ -388,11 +387,11 @@ public:
388 if (!folder.getParent().isEmpty()) { 387 if (!folder.getParent().isEmpty()) {
389 parentFolder = syncStore().resolveLocalId(ENTITY_TYPE_FOLDER, folder.getParent()); 388 parentFolder = syncStore().resolveLocalId(ENTITY_TYPE_FOLDER, folder.getParent());
390 } 389 }
391 Trace() << "Creating a new folder: " << parentFolder << folder.getName(); 390 SinkTrace() << "Creating a new folder: " << parentFolder << folder.getName();
392 auto rid = QSharedPointer<QByteArray>::create(); 391 auto rid = QSharedPointer<QByteArray>::create();
393 auto createFolder = login.then<QString>(imap->createSubfolder(parentFolder, folder.getName())) 392 auto createFolder = login.then<QString>(imap->createSubfolder(parentFolder, folder.getName()))
394 .then<void, QString>([imap, rid](const QString &createdFolder) { 393 .then<void, QString>([imap, rid](const QString &createdFolder) {
395 Trace() << "Finished creating a new folder: " << createdFolder; 394 SinkTrace() << "Finished creating a new folder: " << createdFolder;
396 *rid = createdFolder.toUtf8(); 395 *rid = createdFolder.toUtf8();
397 }); 396 });
398 if (folder.getSpecialPurpose().isEmpty()) { 397 if (folder.getSpecialPurpose().isEmpty()) {
@@ -414,15 +413,15 @@ public:
414 for (const auto &purpose : folder.getSpecialPurpose()) { 413 for (const auto &purpose : folder.getSpecialPurpose()) {
415 if (specialPurposeFolders->contains(purpose)) { 414 if (specialPurposeFolders->contains(purpose)) {
416 auto f = specialPurposeFolders->value(purpose); 415 auto f = specialPurposeFolders->value(purpose);
417 Trace() << "Merging specialpurpose folder with: " << f << " with purpose: " << purpose; 416 SinkTrace() << "Merging specialpurpose folder with: " << f << " with purpose: " << purpose;
418 *rid = f.toUtf8(); 417 *rid = f.toUtf8();
419 return KAsync::null<void>(); 418 return KAsync::null<void>();
420 } 419 }
421 } 420 }
422 Trace() << "No match found for merging, creating a new folder"; 421 SinkTrace() << "No match found for merging, creating a new folder";
423 return imap->createSubfolder(parentFolder, folder.getName()) 422 return imap->createSubfolder(parentFolder, folder.getName())
424 .then<void, QString>([imap, rid](const QString &createdFolder) { 423 .then<void, QString>([imap, rid](const QString &createdFolder) {
425 Trace() << "Finished creating a new folder: " << createdFolder; 424 SinkTrace() << "Finished creating a new folder: " << createdFolder;
426 *rid = createdFolder.toUtf8(); 425 *rid = createdFolder.toUtf8();
427 }); 426 });
428 427
@@ -433,18 +432,18 @@ public:
433 return mergeJob; 432 return mergeJob;
434 } 433 }
435 } else if (operation == Sink::Operation_Removal) { 434 } else if (operation == Sink::Operation_Removal) {
436 Trace() << "Removing a folder: " << oldRemoteId; 435 SinkTrace() << "Removing a folder: " << oldRemoteId;
437 return login.then<void>(imap->remove(oldRemoteId)) 436 return login.then<void>(imap->remove(oldRemoteId))
438 .then<QByteArray>([oldRemoteId, imap]() { 437 .then<QByteArray>([oldRemoteId, imap]() {
439 Trace() << "Finished removing a folder: " << oldRemoteId; 438 SinkTrace() << "Finished removing a folder: " << oldRemoteId;
440 return QByteArray(); 439 return QByteArray();
441 }); 440 });
442 } else if (operation == Sink::Operation_Modification) { 441 } else if (operation == Sink::Operation_Modification) {
443 Trace() << "Renaming a folder: " << oldRemoteId << folder.getName(); 442 SinkTrace() << "Renaming a folder: " << oldRemoteId << folder.getName();
444 auto rid = QSharedPointer<QByteArray>::create(); 443 auto rid = QSharedPointer<QByteArray>::create();
445 return login.then<QString>(imap->renameSubfolder(oldRemoteId, folder.getName())) 444 return login.then<QString>(imap->renameSubfolder(oldRemoteId, folder.getName()))
446 .then<void, QString>([imap, rid](const QString &createdFolder) { 445 .then<void, QString>([imap, rid](const QString &createdFolder) {
447 Trace() << "Finished renaming a folder: " << createdFolder; 446 SinkTrace() << "Finished renaming a folder: " << createdFolder;
448 *rid = createdFolder.toUtf8(); 447 *rid = createdFolder.toUtf8();
449 }) 448 })
450 .then<QByteArray>([rid](){ 449 .then<QByteArray>([rid](){
@@ -515,7 +514,7 @@ KAsync::Job<void> ImapResource::inspect(int inspectionType, const QByteArray &in
515 auto entityStore = QSharedPointer<Sink::EntityStore>::create(mResourceType, mResourceInstanceIdentifier, transaction); 514 auto entityStore = QSharedPointer<Sink::EntityStore>::create(mResourceType, mResourceInstanceIdentifier, transaction);
516 auto syncStore = QSharedPointer<Sink::RemoteIdMap>::create(synchronizationTransaction); 515 auto syncStore = QSharedPointer<Sink::RemoteIdMap>::create(synchronizationTransaction);
517 516
518 Trace() << "Inspecting " << inspectionType << domainType << entityId << property << expectedValue; 517 SinkTrace() << "Inspecting " << inspectionType << domainType << entityId << property << expectedValue;
519 518
520 if (domainType == ENTITY_TYPE_MAIL) { 519 if (domainType == ENTITY_TYPE_MAIL) {
521 const auto mail = entityStore->read<Sink::ApplicationDomain::Mail>(entityId); 520 const auto mail = entityStore->read<Sink::ApplicationDomain::Mail>(entityId);
@@ -523,11 +522,11 @@ KAsync::Job<void> ImapResource::inspect(int inspectionType, const QByteArray &in
523 const auto folderRemoteId = syncStore->resolveLocalId(ENTITY_TYPE_FOLDER, mail.getFolder()); 522 const auto folderRemoteId = syncStore->resolveLocalId(ENTITY_TYPE_FOLDER, mail.getFolder());
524 const auto mailRemoteId = syncStore->resolveLocalId(ENTITY_TYPE_MAIL, mail.identifier()); 523 const auto mailRemoteId = syncStore->resolveLocalId(ENTITY_TYPE_MAIL, mail.identifier());
525 if (mailRemoteId.isEmpty() || folderRemoteId.isEmpty()) { 524 if (mailRemoteId.isEmpty() || folderRemoteId.isEmpty()) {
526 Warning() << "Missing remote id for folder or mail. " << mailRemoteId << folderRemoteId; 525 SinkWarning() << "Missing remote id for folder or mail. " << mailRemoteId << folderRemoteId;
527 return KAsync::error<void>(); 526 return KAsync::error<void>();
528 } 527 }
529 const auto uid = uidFromMailRid(mailRemoteId); 528 const auto uid = uidFromMailRid(mailRemoteId);
530 Trace() << "Mail remote id: " << folderRemoteId << mailRemoteId << mail.identifier() << folder.identifier(); 529 SinkTrace() << "Mail remote id: " << folderRemoteId << mailRemoteId << mail.identifier() << folder.identifier();
531 530
532 KIMAP::ImapSet set; 531 KIMAP::ImapSet set;
533 set.add(uid); 532 set.add(uid);
@@ -538,8 +537,8 @@ KAsync::Job<void> ImapResource::inspect(int inspectionType, const QByteArray &in
538 scope.mode = KIMAP::FetchJob::FetchScope::Full; 537 scope.mode = KIMAP::FetchJob::FetchScope::Full;
539 auto imap = QSharedPointer<ImapServerProxy>::create(mServer, mPort); 538 auto imap = QSharedPointer<ImapServerProxy>::create(mServer, mPort);
540 auto messageByUid = QSharedPointer<QHash<qint64, Imap::Message>>::create(); 539 auto messageByUid = QSharedPointer<QHash<qint64, Imap::Message>>::create();
541 Trace() << "Connecting to:" << mServer << mPort; 540 SinkTrace() << "Connecting to:" << mServer << mPort;
542 Trace() << "as:" << mUser; 541 SinkTrace() << "as:" << mUser;
543 auto inspectionJob = imap->login(mUser, mPassword) 542 auto inspectionJob = imap->login(mUser, mPassword)
544 .then<void>(imap->select(folderRemoteId)) 543 .then<void>(imap->select(folderRemoteId))
545 .then<void>(imap->fetch(set, scope, [imap, messageByUid](const QVector<Imap::Message> &messages) { 544 .then<void>(imap->fetch(set, scope, [imap, messageByUid](const QVector<Imap::Message> &messages) {
@@ -574,8 +573,8 @@ KAsync::Job<void> ImapResource::inspect(int inspectionType, const QByteArray &in
574 if (inspectionType == Sink::ResourceControl::Inspection::ExistenceInspectionType) { 573 if (inspectionType == Sink::ResourceControl::Inspection::ExistenceInspectionType) {
575 return inspectionJob.then<void, KAsync::Job<void>>([=]() { 574 return inspectionJob.then<void, KAsync::Job<void>>([=]() {
576 if (!messageByUid->contains(uid)) { 575 if (!messageByUid->contains(uid)) {
577 Warning() << "Existing messages are: " << messageByUid->keys(); 576 SinkWarning() << "Existing messages are: " << messageByUid->keys();
578 Warning() << "We're looking for: " << uid; 577 SinkWarning() << "We're looking for: " << uid;
579 return KAsync::error<void>(1, "Couldn't find message: " + mailRemoteId); 578 return KAsync::error<void>(1, "Couldn't find message: " + mailRemoteId);
580 } 579 }
581 return KAsync::null<void>(); 580 return KAsync::null<void>();
@@ -587,7 +586,7 @@ KAsync::Job<void> ImapResource::inspect(int inspectionType, const QByteArray &in
587 const auto folder = entityStore->read<Sink::ApplicationDomain::Folder>(entityId); 586 const auto folder = entityStore->read<Sink::ApplicationDomain::Folder>(entityId);
588 587
589 if (inspectionType == Sink::ResourceControl::Inspection::CacheIntegrityInspectionType) { 588 if (inspectionType == Sink::ResourceControl::Inspection::CacheIntegrityInspectionType) {
590 Log() << "Inspecting cache integrity" << remoteId; 589 SinkLog() << "Inspecting cache integrity" << remoteId;
591 590
592 int expectedCount = 0; 591 int expectedCount = 0;
593 Index index("mail.index.folder", transaction); 592 Index index("mail.index.folder", transaction);
@@ -595,7 +594,7 @@ KAsync::Job<void> ImapResource::inspect(int inspectionType, const QByteArray &in
595 expectedCount++; 594 expectedCount++;
596 }, 595 },
597 [&](const Index::Error &error) { 596 [&](const Index::Error &error) {
598 Warning() << "Error in index: " << error.message << property; 597 SinkWarning() << "Error in index: " << error.message << property;
599 }); 598 });
600 599
601 auto set = KIMAP::ImapSet::fromImapSequenceSet("1:*"); 600 auto set = KIMAP::ImapSet::fromImapSequenceSet("1:*");
@@ -630,10 +629,10 @@ KAsync::Job<void> ImapResource::inspect(int inspectionType, const QByteArray &in
630 *folderByName << f.pathParts.last(); 629 *folderByName << f.pathParts.last();
631 } 630 }
632 })) 631 }))
633 .then<void, KAsync::Job<void>>([folderByName, folderByPath, folder, remoteId, imap]() { 632 .then<void, KAsync::Job<void>>([this, folderByName, folderByPath, folder, remoteId, imap]() {
634 if (!folderByName->contains(folder.getName())) { 633 if (!folderByName->contains(folder.getName())) {
635 Warning() << "Existing folders are: " << *folderByPath; 634 SinkWarning() << "Existing folders are: " << *folderByPath;
636 Warning() << "We're looking for: " << folder.getName(); 635 SinkWarning() << "We're looking for: " << folder.getName();
637 return KAsync::error<void>(1, "Wrong folder name: " + remoteId); 636 return KAsync::error<void>(1, "Wrong folder name: " + remoteId);
638 } 637 }
639 return KAsync::null<void>(); 638 return KAsync::null<void>();
diff --git a/examples/imapresource/imapresource.h b/examples/imapresource/imapresource.h
index 0c3b541..534a04e 100644
--- a/examples/imapresource/imapresource.h
+++ b/examples/imapresource/imapresource.h
@@ -26,7 +26,7 @@
26#include <flatbuffers/flatbuffers.h> 26#include <flatbuffers/flatbuffers.h>
27 27
28//TODO: a little ugly to have this in two places, once here and once in Q_PLUGIN_METADATA 28//TODO: a little ugly to have this in two places, once here and once in Q_PLUGIN_METADATA
29#define PLUGIN_NAME "org.kde.imap" 29#define PLUGIN_NAME "sink.imap"
30 30
31class ImapMailAdaptorFactory; 31class ImapMailAdaptorFactory;
32class ImapFolderAdaptorFactory; 32class ImapFolderAdaptorFactory;
@@ -56,7 +56,7 @@ private:
56class ImapResourceFactory : public Sink::ResourceFactory 56class ImapResourceFactory : public Sink::ResourceFactory
57{ 57{
58 Q_OBJECT 58 Q_OBJECT
59 Q_PLUGIN_METADATA(IID "org.kde.imap") 59 Q_PLUGIN_METADATA(IID "sink.imap")
60 Q_INTERFACES(Sink::ResourceFactory) 60 Q_INTERFACES(Sink::ResourceFactory)
61 61
62public: 62public:
diff --git a/examples/imapresource/imapserverproxy.cpp b/examples/imapresource/imapserverproxy.cpp
index 1b0a2ec..73ec654 100644
--- a/examples/imapresource/imapserverproxy.cpp
+++ b/examples/imapresource/imapserverproxy.cpp
@@ -37,6 +37,8 @@
37 37
38#include "log.h" 38#include "log.h"
39 39
40SINK_DEBUG_AREA("imapserverproxy")
41
40using namespace Imap; 42using namespace Imap;
41 43
42const char* Imap::Flags::Seen = "\\Seen"; 44const char* Imap::Flags::Seen = "\\Seen";
@@ -54,16 +56,16 @@ static KAsync::Job<T> runJob(KJob *job, const std::function<T(KJob*)> &f)
54{ 56{
55 return KAsync::start<T>([job, f](KAsync::Future<T> &future) { 57 return KAsync::start<T>([job, f](KAsync::Future<T> &future) {
56 QObject::connect(job, &KJob::result, [&future, f](KJob *job) { 58 QObject::connect(job, &KJob::result, [&future, f](KJob *job) {
57 Trace() << "Job done: " << job->metaObject()->className(); 59 SinkTrace() << "Job done: " << job->metaObject()->className();
58 if (job->error()) { 60 if (job->error()) {
59 Warning() << "Job failed: " << job->errorString(); 61 SinkWarning() << "Job failed: " << job->errorString();
60 future.setError(job->error(), job->errorString()); 62 future.setError(job->error(), job->errorString());
61 } else { 63 } else {
62 future.setValue(f(job)); 64 future.setValue(f(job));
63 future.setFinished(); 65 future.setFinished();
64 } 66 }
65 }); 67 });
66 Trace() << "Starting job: " << job->metaObject()->className(); 68 SinkTrace() << "Starting job: " << job->metaObject()->className();
67 job->start(); 69 job->start();
68 }); 70 });
69} 71}
@@ -72,15 +74,15 @@ static KAsync::Job<void> runJob(KJob *job)
72{ 74{
73 return KAsync::start<void>([job](KAsync::Future<void> &future) { 75 return KAsync::start<void>([job](KAsync::Future<void> &future) {
74 QObject::connect(job, &KJob::result, [&future](KJob *job) { 76 QObject::connect(job, &KJob::result, [&future](KJob *job) {
75 Trace() << "Job done: " << job->metaObject()->className(); 77 SinkTrace() << "Job done: " << job->metaObject()->className();
76 if (job->error()) { 78 if (job->error()) {
77 Warning() << "Job failed: " << job->errorString(); 79 SinkWarning() << "Job failed: " << job->errorString();
78 future.setError(job->error(), job->errorString()); 80 future.setError(job->error(), job->errorString());
79 } else { 81 } else {
80 future.setFinished(); 82 future.setFinished();
81 } 83 }
82 }); 84 });
83 Trace() << "Starting job: " << job->metaObject()->className(); 85 SinkTrace() << "Starting job: " << job->metaObject()->className();
84 job->start(); 86 job->start();
85 }); 87 });
86} 88}
@@ -117,11 +119,11 @@ KAsync::Job<void> ImapServerProxy::login(const QString &username, const QString
117 auto namespaceJob = new KIMAP::NamespaceJob(mSession); 119 auto namespaceJob = new KIMAP::NamespaceJob(mSession);
118 120
119 return runJob(loginJob).then(runJob(capabilitiesJob)).then<void>([this](){ 121 return runJob(loginJob).then(runJob(capabilitiesJob)).then<void>([this](){
120 Trace() << "Supported capabilities: " << mCapabilities; 122 SinkTrace() << "Supported capabilities: " << mCapabilities;
121 QStringList requiredExtensions = QStringList() << "UIDPLUS" << "NAMESPACE"; 123 QStringList requiredExtensions = QStringList() << "UIDPLUS" << "NAMESPACE";
122 for (const auto &requiredExtension : requiredExtensions) { 124 for (const auto &requiredExtension : requiredExtensions) {
123 if (!mCapabilities.contains(requiredExtension)) { 125 if (!mCapabilities.contains(requiredExtension)) {
124 Warning() << "Server doesn't support required capability: " << requiredExtension; 126 SinkWarning() << "Server doesn't support required capability: " << requiredExtension;
125 //TODO fail the job 127 //TODO fail the job
126 } 128 }
127 } 129 }
@@ -138,9 +140,9 @@ KAsync::Job<void> ImapServerProxy::login(const QString &username, const QString
138 mUserNamespaces << ns.name; 140 mUserNamespaces << ns.name;
139 mUserNamespaceSeparator = ns.separator; 141 mUserNamespaceSeparator = ns.separator;
140 } 142 }
141 Trace() << "Found personal namespaces: " << mPersonalNamespaces << mPersonalNamespaceSeparator; 143 SinkTrace() << "Found personal namespaces: " << mPersonalNamespaces << mPersonalNamespaceSeparator;
142 Trace() << "Found shared namespaces: " << mSharedNamespaces << mSharedNamespaceSeparator; 144 SinkTrace() << "Found shared namespaces: " << mSharedNamespaces << mSharedNamespaceSeparator;
143 Trace() << "Found user namespaces: " << mUserNamespaces << mUserNamespaceSeparator; 145 SinkTrace() << "Found user namespaces: " << mUserNamespaces << mUserNamespaceSeparator;
144 }); 146 });
145} 147}
146 148
@@ -291,8 +293,8 @@ KAsync::Job<QList<qint64>> ImapServerProxy::fetchHeaders(const QString &mailbox)
291 const QMap<qint64,KIMAP::MessageAttribute> &attrs, 293 const QMap<qint64,KIMAP::MessageAttribute> &attrs,
292 const QMap<qint64,KIMAP::MessageFlags> &flags, 294 const QMap<qint64,KIMAP::MessageFlags> &flags,
293 const QMap<qint64,KIMAP::MessagePtr> &messages) { 295 const QMap<qint64,KIMAP::MessagePtr> &messages) {
294 Trace() << "Received " << uids.size() << " headers from " << mailbox; 296 SinkTrace() << "Received " << uids.size() << " headers from " << mailbox;
295 Trace() << uids.size() << sizes.size() << attrs.size() << flags.size() << messages.size(); 297 SinkTrace() << uids.size() << sizes.size() << attrs.size() << flags.size() << messages.size();
296 298
297 //TODO based on the data available here, figure out which messages to actually fetch 299 //TODO based on the data available here, figure out which messages to actually fetch
298 //(we only fetched headers and structure so far) 300 //(we only fetched headers and structure so far)
@@ -344,7 +346,7 @@ KAsync::Job<QString> ImapServerProxy::createSubfolder(const QString &parentMailb
344 } else { 346 } else {
345 *folder = parentMailbox + mPersonalNamespaceSeparator + folderName; 347 *folder = parentMailbox + mPersonalNamespaceSeparator + folderName;
346 } 348 }
347 Trace() << "Creating subfolder: " << *folder; 349 SinkTrace() << "Creating subfolder: " << *folder;
348 return create(*folder); 350 return create(*folder);
349 }) 351 })
350 .then<QString>([=]() { 352 .then<QString>([=]() {
@@ -360,7 +362,7 @@ KAsync::Job<QString> ImapServerProxy::renameSubfolder(const QString &oldMailbox,
360 auto parts = oldMailbox.split(mPersonalNamespaceSeparator); 362 auto parts = oldMailbox.split(mPersonalNamespaceSeparator);
361 parts.removeLast(); 363 parts.removeLast();
362 *folder = parts.join(mPersonalNamespaceSeparator) + mPersonalNamespaceSeparator + newName; 364 *folder = parts.join(mPersonalNamespaceSeparator) + mPersonalNamespaceSeparator + newName;
363 Trace() << "Renaming subfolder: " << oldMailbox << *folder; 365 SinkTrace() << "Renaming subfolder: " << oldMailbox << *folder;
364 return rename(oldMailbox, *folder); 366 return rename(oldMailbox, *folder);
365 }) 367 })
366 .then<QString>([=]() { 368 .then<QString>([=]() {
@@ -370,14 +372,14 @@ KAsync::Job<QString> ImapServerProxy::renameSubfolder(const QString &oldMailbox,
370 372
371KAsync::Job<void> ImapServerProxy::fetchFolders(std::function<void(const QVector<Folder> &)> callback) 373KAsync::Job<void> ImapServerProxy::fetchFolders(std::function<void(const QVector<Folder> &)> callback)
372{ 374{
373 Trace() << "Fetching folders"; 375 SinkTrace() << "Fetching folders";
374 return list(KIMAP::ListJob::IncludeUnsubscribed, [callback](const QList<KIMAP::MailBoxDescriptor> &mailboxes, const QList<QList<QByteArray> > &flags){ 376 return list(KIMAP::ListJob::IncludeUnsubscribed, [callback](const QList<KIMAP::MailBoxDescriptor> &mailboxes, const QList<QList<QByteArray> > &flags){
375 QVector<Folder> list; 377 QVector<Folder> list;
376 for (int i = 0; i < mailboxes.size(); i++) { 378 for (int i = 0; i < mailboxes.size(); i++) {
377 const auto mailbox = mailboxes[i]; 379 const auto mailbox = mailboxes[i];
378 const auto mailboxFlags = flags[i]; 380 const auto mailboxFlags = flags[i];
379 bool noselect = mailboxFlags.contains(QByteArray(FolderFlags::Noselect).toLower()) || mailboxFlags.contains(QByteArray(FolderFlags::Noselect)); 381 bool noselect = mailboxFlags.contains(QByteArray(FolderFlags::Noselect).toLower()) || mailboxFlags.contains(QByteArray(FolderFlags::Noselect));
380 Log() << "Found mailbox: " << mailbox.name << mailboxFlags << FolderFlags::Noselect << noselect; 382 SinkLog() << "Found mailbox: " << mailbox.name << mailboxFlags << FolderFlags::Noselect << noselect;
381 list << Folder{mailbox.name.split(mailbox.separator), mailbox.name, mailbox.separator, noselect}; 383 list << Folder{mailbox.name.split(mailbox.separator), mailbox.name, mailbox.separator, noselect};
382 } 384 }
383 callback(list); 385 callback(list);
@@ -395,9 +397,9 @@ KAsync::Job<void> ImapServerProxy::fetchMessages(const Folder &folder, std::func
395 Q_ASSERT(!mPersonalNamespaceSeparator.isNull()); 397 Q_ASSERT(!mPersonalNamespaceSeparator.isNull());
396 return select(mailboxFromFolder(folder)).then<void, KAsync::Job<void>>([this, callback, folder]() -> KAsync::Job<void> { 398 return select(mailboxFromFolder(folder)).then<void, KAsync::Job<void>>([this, callback, folder]() -> KAsync::Job<void> {
397 return fetchHeaders(mailboxFromFolder(folder)).then<void, KAsync::Job<void>, QList<qint64>>([this, callback](const QList<qint64> &uidsToFetch){ 399 return fetchHeaders(mailboxFromFolder(folder)).then<void, KAsync::Job<void>, QList<qint64>>([this, callback](const QList<qint64> &uidsToFetch){
398 Trace() << "Uids to fetch: " << uidsToFetch; 400 SinkTrace() << "Uids to fetch: " << uidsToFetch;
399 if (uidsToFetch.isEmpty()) { 401 if (uidsToFetch.isEmpty()) {
400 Trace() << "Nothing to fetch"; 402 SinkTrace() << "Nothing to fetch";
401 callback(QVector<Message>()); 403 callback(QVector<Message>());
402 return KAsync::null<void>(); 404 return KAsync::null<void>();
403 } 405 }
diff --git a/examples/imapresource/tests/imapmailsynctest.cpp b/examples/imapresource/tests/imapmailsynctest.cpp
index 968cde5..fcc659d 100644
--- a/examples/imapresource/tests/imapmailsynctest.cpp
+++ b/examples/imapresource/tests/imapmailsynctest.cpp
@@ -17,6 +17,7 @@
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */ 18 */
19#include <QtTest> 19#include <QtTest>
20#include <QTcpSocket>
20 21
21#include <tests/mailsynctest.h> 22#include <tests/mailsynctest.h>
22#include "../imapresource.h" 23#include "../imapresource.h"
@@ -38,6 +39,13 @@ class ImapMailSyncTest : public Sink::MailSyncTest
38 Q_OBJECT 39 Q_OBJECT
39 40
40protected: 41protected:
42 bool isBackendAvailable() Q_DECL_OVERRIDE
43 {
44 QTcpSocket socket;
45 socket.connectToHost("localhost", 993);
46 return socket.waitForConnected(200);
47 }
48
41 void resetTestEnvironment() Q_DECL_OVERRIDE 49 void resetTestEnvironment() Q_DECL_OVERRIDE
42 { 50 {
43 system("resetmailbox.sh"); 51 system("resetmailbox.sh");
diff --git a/examples/imapresource/tests/imapmailtest.cpp b/examples/imapresource/tests/imapmailtest.cpp
index c94a731..e6f41f4 100644
--- a/examples/imapresource/tests/imapmailtest.cpp
+++ b/examples/imapresource/tests/imapmailtest.cpp
@@ -1,4 +1,5 @@
1#include <QtTest> 1#include <QtTest>
2#include <QTcpSocket>
2 3
3#include <tests/mailtest.h> 4#include <tests/mailtest.h>
4 5
@@ -18,6 +19,13 @@ class ImapMailTest : public Sink::MailTest
18 Q_OBJECT 19 Q_OBJECT
19 20
20protected: 21protected:
22 bool isBackendAvailable() Q_DECL_OVERRIDE
23 {
24 QTcpSocket socket;
25 socket.connectToHost("localhost", 993);
26 return socket.waitForConnected(200);
27 }
28
21 void resetTestEnvironment() Q_DECL_OVERRIDE 29 void resetTestEnvironment() Q_DECL_OVERRIDE
22 { 30 {
23 system("resetmailbox.sh"); 31 system("resetmailbox.sh");
diff --git a/examples/imapresource/tests/imapserverproxytest.cpp b/examples/imapresource/tests/imapserverproxytest.cpp
index e32298c..ef695b3 100644
--- a/examples/imapresource/tests/imapserverproxytest.cpp
+++ b/examples/imapresource/tests/imapserverproxytest.cpp
@@ -2,6 +2,7 @@
2 2
3#include <QString> 3#include <QString>
4#include <KMime/Message> 4#include <KMime/Message>
5#include <QTcpSocket>
5 6
6#include "../imapserverproxy.h" 7#include "../imapserverproxy.h"
7 8
@@ -11,6 +12,8 @@
11 12
12using namespace Imap; 13using namespace Imap;
13 14
15SINK_DEBUG_AREA("imapserverproxytest")
16
14/** 17/**
15 */ 18 */
16class ImapServerProxyTest : public QObject 19class ImapServerProxyTest : public QObject
@@ -22,7 +25,9 @@ class ImapServerProxyTest : public QObject
22private slots: 25private slots:
23 void initTestCase() 26 void initTestCase()
24 { 27 {
25 Sink::Log::setDebugOutputLevel(Sink::Log::Trace); 28 QTcpSocket socket;
29 socket.connectToHost("localhost", 993);
30 QVERIFY(socket.waitForConnected(200));
26 system("resetmailbox.sh"); 31 system("resetmailbox.sh");
27 } 32 }
28 33
@@ -77,8 +82,8 @@ private slots:
77 const QMap<qint64,KIMAP::MessageAttribute> &attrs, 82 const QMap<qint64,KIMAP::MessageAttribute> &attrs,
78 const QMap<qint64,KIMAP::MessageFlags> &flags, 83 const QMap<qint64,KIMAP::MessageFlags> &flags,
79 const QMap<qint64,KIMAP::MessagePtr> &messages) { 84 const QMap<qint64,KIMAP::MessagePtr> &messages) {
80 Trace() << "Received " << uids.size() << " messages from " << mailbox; 85 SinkTrace() << "Received " << uids.size() << " messages from " << mailbox;
81 Trace() << uids.size() << sizes.size() << attrs.size() << flags.size() << messages.size(); 86 SinkTrace() << uids.size() << sizes.size() << attrs.size() << flags.size() << messages.size();
82 count += uids.size(); 87 count += uids.size();
83 })); 88 }));
84 89
@@ -102,8 +107,8 @@ private slots:
102 const QMap<qint64,KIMAP::MessageAttribute> &attrs, 107 const QMap<qint64,KIMAP::MessageAttribute> &attrs,
103 const QMap<qint64,KIMAP::MessageFlags> &flags, 108 const QMap<qint64,KIMAP::MessageFlags> &flags,
104 const QMap<qint64,KIMAP::MessagePtr> &messages) { 109 const QMap<qint64,KIMAP::MessagePtr> &messages) {
105 Trace() << "Received " << uids.size() << " messages from " << mailbox; 110 SinkTrace() << "Received " << uids.size() << " messages from " << mailbox;
106 Trace() << uids.size() << sizes.size() << attrs.size() << flags.size() << messages.size(); 111 SinkTrace() << uids.size() << sizes.size() << attrs.size() << flags.size() << messages.size();
107 count += uids.size(); 112 count += uids.size();
108 })); 113 }));
109 114
diff --git a/examples/imapresource/tests/resetmailbox.sh b/examples/imapresource/tests/resetmailbox.sh
index 8834b51..6ed198e 100644
--- a/examples/imapresource/tests/resetmailbox.sh
+++ b/examples/imapresource/tests/resetmailbox.sh
@@ -4,6 +4,7 @@ sudo echo "sam user.doe.* cyrus c" | cyradm --auth PLAIN -u cyrus -w admin local
4sudo echo "dm user.doe.*" | cyradm --auth PLAIN -u cyrus -w admin localhost 4sudo echo "dm user.doe.*" | cyradm --auth PLAIN -u cyrus -w admin localhost
5sudo echo "cm user.doe.test" | cyradm --auth PLAIN -u cyrus -w admin localhost 5sudo echo "cm user.doe.test" | cyradm --auth PLAIN -u cyrus -w admin localhost
6sudo echo "cm user.doe.Drafts" | cyradm --auth PLAIN -u cyrus -w admin localhost 6sudo echo "cm user.doe.Drafts" | cyradm --auth PLAIN -u cyrus -w admin localhost
7sudo echo "cm user.doe.Trash" | cyradm --auth PLAIN -u cyrus -w admin localhost
7sudo echo "sam user.doe cyrus c" | cyradm --auth PLAIN -u cyrus -w admin localhost 8sudo echo "sam user.doe cyrus c" | cyradm --auth PLAIN -u cyrus -w admin localhost
8sudo cp /work/source/Sink/examples/imapresource/tests/data/1365777830.R28.localhost.localdomain\:2\,S /var/spool/imap/d/user/doe/test/1. 9sudo cp /work/source/Sink/examples/imapresource/tests/data/1365777830.R28.localhost.localdomain\:2\,S /var/spool/imap/d/user/doe/test/1.
9sudo chown cyrus:mail /var/spool/imap/d/user/doe/test/1. 10sudo chown cyrus:mail /var/spool/imap/d/user/doe/test/1.
diff --git a/examples/maildirresource/facade.cpp b/examples/maildirresource/facade.cpp
index d8fc02d..256b255 100644
--- a/examples/maildirresource/facade.cpp
+++ b/examples/maildirresource/facade.cpp
@@ -38,11 +38,11 @@ MaildirResourceMailFacade::MaildirResourceMailFacade(const QByteArray &instanceI
38 const auto folderPath = parts.join('/'); 38 const auto folderPath = parts.join('/');
39 const auto path = folderPath + "/cur/"; 39 const auto path = folderPath + "/cur/";
40 40
41 Trace() << "Looking for mail in: " << path << key; 41 SinkTrace_("", "maildirfacade") << "Looking for mail in: " << path << key;
42 QDir dir(path); 42 QDir dir(path);
43 const QFileInfoList list = dir.entryInfoList(QStringList() << (key+"*"), QDir::Files); 43 const QFileInfoList list = dir.entryInfoList(QStringList() << (key+"*"), QDir::Files);
44 if (list.size() != 1) { 44 if (list.size() != 1) {
45 Warning() << "Failed to find message " << path << key << list.size(); 45 SinkWarning_("", "maildirfacade") << "Failed to find message " << path << key << list.size();
46 value.setProperty("mimeMessage", QVariant()); 46 value.setProperty("mimeMessage", QVariant());
47 } else { 47 } else {
48 value.setProperty("mimeMessage", list.at(0).filePath()); 48 value.setProperty("mimeMessage", list.at(0).filePath());
diff --git a/examples/maildirresource/maildirresource.cpp b/examples/maildirresource/maildirresource.cpp
index e1fcfdf..d7a6fff 100644
--- a/examples/maildirresource/maildirresource.cpp
+++ b/examples/maildirresource/maildirresource.cpp
@@ -51,8 +51,7 @@
51#define ENTITY_TYPE_MAIL "mail" 51#define ENTITY_TYPE_MAIL "mail"
52#define ENTITY_TYPE_FOLDER "folder" 52#define ENTITY_TYPE_FOLDER "folder"
53 53
54#undef DEBUG_AREA 54SINK_DEBUG_AREA("maildirresource")
55#define DEBUG_AREA "resource.maildir"
56 55
57using namespace Sink; 56using namespace Sink;
58 57
@@ -65,8 +64,8 @@ static QString getFilePathFromMimeMessagePath(const QString &mimeMessagePath)
65 QDir dir(path); 64 QDir dir(path);
66 const QFileInfoList list = dir.entryInfoList(QStringList() << (key+"*"), QDir::Files); 65 const QFileInfoList list = dir.entryInfoList(QStringList() << (key+"*"), QDir::Files);
67 if (list.size() != 1) { 66 if (list.size() != 1) {
68 Warning() << "Failed to find message " << mimeMessagePath; 67 SinkWarning() << "Failed to find message " << mimeMessagePath;
69 Warning() << "Failed to find message " << path; 68 SinkWarning() << "Failed to find message " << path;
70 return QString(); 69 return QString();
71 } 70 }
72 return list.first().filePath(); 71 return list.first().filePath();
@@ -115,7 +114,7 @@ public:
115 const auto path = getPath(folder, transaction); 114 const auto path = getPath(folder, transaction);
116 KPIM::Maildir maildir(path, false); 115 KPIM::Maildir maildir(path, false);
117 if (!maildir.isValid(true)) { 116 if (!maildir.isValid(true)) {
118 Warning() << "Maildir is not existing: " << path; 117 SinkWarning() << "Maildir is not existing: " << path;
119 } 118 }
120 auto identifier = maildir.addEntryFromPath(oldPath); 119 auto identifier = maildir.addEntryFromPath(oldPath);
121 return path + "/" + identifier; 120 return path + "/" + identifier;
@@ -124,7 +123,7 @@ public:
124 const auto path = getPath(folder, transaction); 123 const auto path = getPath(folder, transaction);
125 KPIM::Maildir maildir(path, false); 124 KPIM::Maildir maildir(path, false);
126 if (!maildir.isValid(true)) { 125 if (!maildir.isValid(true)) {
127 Warning() << "Maildir is not existing: " << path; 126 SinkWarning() << "Maildir is not existing: " << path;
128 } 127 }
129 auto oldIdentifier = KPIM::Maildir::getKeyFromFile(oldPath); 128 auto oldIdentifier = KPIM::Maildir::getKeyFromFile(oldPath);
130 auto pathParts = oldPath.split('/'); 129 auto pathParts = oldPath.split('/');
@@ -135,7 +134,7 @@ public:
135 } 134 }
136 KPIM::Maildir oldMaildir(oldDirectory, false); 135 KPIM::Maildir oldMaildir(oldDirectory, false);
137 if (!oldMaildir.isValid(false)) { 136 if (!oldMaildir.isValid(false)) {
138 Warning() << "Maildir is not existing: " << path; 137 SinkWarning() << "Maildir is not existing: " << path;
139 } 138 }
140 auto identifier = oldMaildir.moveEntryTo(oldIdentifier, maildir); 139 auto identifier = oldMaildir.moveEntryTo(oldIdentifier, maildir);
141 return path + "/" + identifier; 140 return path + "/" + identifier;
@@ -158,7 +157,7 @@ public:
158 const bool mimeMessageChanged = mimeMessage.isValid() && mimeMessage.toString() != oldEntity.getProperty("mimeMessage").toString(); 157 const bool mimeMessageChanged = mimeMessage.isValid() && mimeMessage.toString() != oldEntity.getProperty("mimeMessage").toString();
159 const bool folderChanged = newFolder.isValid() && newFolder.toString() != oldEntity.getProperty("mimeMessage").toString(); 158 const bool folderChanged = newFolder.isValid() && newFolder.toString() != oldEntity.getProperty("mimeMessage").toString();
160 if (mimeMessageChanged || folderChanged) { 159 if (mimeMessageChanged || folderChanged) {
161 Trace() << "Moving mime message: " << mimeMessageChanged << folderChanged; 160 SinkTrace() << "Moving mime message: " << mimeMessageChanged << folderChanged;
162 auto newPath = moveMessage(mimeMessage.toString(), newEntity.getProperty("folder").toByteArray(), transaction); 161 auto newPath = moveMessage(mimeMessage.toString(), newEntity.getProperty("folder").toByteArray(), transaction);
163 if (newPath != oldEntity.getProperty("mimeMessage").toString()) { 162 if (newPath != oldEntity.getProperty("mimeMessage").toString()) {
164 const auto oldPath = getFilePathFromMimeMessagePath(oldEntity.getProperty("mimeMessage").toString()); 163 const auto oldPath = getFilePathFromMimeMessagePath(oldEntity.getProperty("mimeMessage").toString());
@@ -278,7 +277,7 @@ public:
278 { 277 {
279 const QByteArray bufferType = ENTITY_TYPE_FOLDER; 278 const QByteArray bufferType = ENTITY_TYPE_FOLDER;
280 QStringList folderList = listAvailableFolders(); 279 QStringList folderList = listAvailableFolders();
281 Trace() << "Found folders " << folderList; 280 SinkTrace() << "Found folders " << folderList;
282 281
283 scanForRemovals(bufferType, 282 scanForRemovals(bufferType,
284 [this, &bufferType](const std::function<void(const QByteArray &)> &callback) { 283 [this, &bufferType](const std::function<void(const QByteArray &)> &callback) {
@@ -304,23 +303,23 @@ public:
304 303
305 void synchronizeMails(const QString &path) 304 void synchronizeMails(const QString &path)
306 { 305 {
307 Trace() << "Synchronizing mails" << path; 306 SinkTrace() << "Synchronizing mails" << path;
308 auto time = QSharedPointer<QTime>::create(); 307 auto time = QSharedPointer<QTime>::create();
309 time->start(); 308 time->start();
310 const QByteArray bufferType = ENTITY_TYPE_MAIL; 309 const QByteArray bufferType = ENTITY_TYPE_MAIL;
311 310
312 KPIM::Maildir maildir(path, true); 311 KPIM::Maildir maildir(path, true);
313 if (!maildir.isValid()) { 312 if (!maildir.isValid()) {
314 Warning() << "Failed to sync folder."; 313 SinkWarning() << "Failed to sync folder.";
315 return; 314 return;
316 } 315 }
317 316
318 Trace() << "Importing new mail."; 317 SinkTrace() << "Importing new mail.";
319 maildir.importNewMails(); 318 maildir.importNewMails();
320 319
321 auto listingPath = maildir.pathToCurrent(); 320 auto listingPath = maildir.pathToCurrent();
322 auto entryIterator = QSharedPointer<QDirIterator>::create(listingPath, QDir::Files); 321 auto entryIterator = QSharedPointer<QDirIterator>::create(listingPath, QDir::Files);
323 Trace() << "Looking into " << listingPath; 322 SinkTrace() << "Looking into " << listingPath;
324 323
325 const auto folderLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, path.toUtf8()); 324 const auto folderLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, path.toUtf8());
326 325
@@ -332,7 +331,7 @@ public:
332 callback(sinkId); 331 callback(sinkId);
333 }, 332 },
334 [&](const Index::Error &error) { 333 [&](const Index::Error &error) {
335 Warning() << "Error in index: " << error.message << property; 334 SinkWarning() << "Error in index: " << error.message << property;
336 }); 335 });
337 }, 336 },
338 [](const QByteArray &remoteId) -> bool { 337 [](const QByteArray &remoteId) -> bool {
@@ -350,7 +349,7 @@ public:
350 const auto flags = maildir.readEntryFlags(fileName); 349 const auto flags = maildir.readEntryFlags(fileName);
351 const auto maildirKey = maildir.getKeyFromFile(fileName); 350 const auto maildirKey = maildir.getKeyFromFile(fileName);
352 351
353 Trace() << "Found a mail " << filePath << " : " << fileName; 352 SinkTrace() << "Found a mail " << filePath << " : " << fileName;
354 353
355 Sink::ApplicationDomain::Mail mail; 354 Sink::ApplicationDomain::Mail mail;
356 mail.setProperty("folder", folderLocalId); 355 mail.setProperty("folder", folderLocalId);
@@ -362,12 +361,12 @@ public:
362 createOrModify(bufferType, remoteId, mail); 361 createOrModify(bufferType, remoteId, mail);
363 } 362 }
364 const auto elapsed = time->elapsed(); 363 const auto elapsed = time->elapsed();
365 Log() << "Synchronized " << count << " mails in " << listingPath << Sink::Log::TraceTime(elapsed) << " " << elapsed/qMax(count, 1) << " [ms/mail]"; 364 SinkLog() << "Synchronized " << count << " mails in " << listingPath << Sink::Log::TraceTime(elapsed) << " " << elapsed/qMax(count, 1) << " [ms/mail]";
366 } 365 }
367 366
368 KAsync::Job<void> synchronizeWithSource() Q_DECL_OVERRIDE 367 KAsync::Job<void> synchronizeWithSource() Q_DECL_OVERRIDE
369 { 368 {
370 Log() << " Synchronizing"; 369 SinkLog() << " Synchronizing";
371 return KAsync::start<void, KAsync::Job<void> >([this]() { 370 return KAsync::start<void, KAsync::Job<void> >([this]() {
372 KPIM::Maildir maildir(mMaildirPath, true); 371 KPIM::Maildir maildir(mMaildirPath, true);
373 if (!maildir.isValid(false)) { 372 if (!maildir.isValid(false)) {
@@ -381,7 +380,7 @@ public:
381 //Don't let the transaction grow too much 380 //Don't let the transaction grow too much
382 commit(); 381 commit();
383 } 382 }
384 Log() << "Done Synchronizing"; 383 SinkLog() << "Done Synchronizing";
385 return KAsync::null<void>(); 384 return KAsync::null<void>();
386 }); 385 });
387 } 386 }
@@ -402,15 +401,15 @@ public:
402 { 401 {
403 if (operation == Sink::Operation_Creation) { 402 if (operation == Sink::Operation_Creation) {
404 const auto remoteId = getFilePathFromMimeMessagePath(mail.getMimeMessagePath()); 403 const auto remoteId = getFilePathFromMimeMessagePath(mail.getMimeMessagePath());
405 Trace() << "Mail created: " << remoteId; 404 SinkTrace() << "Mail created: " << remoteId;
406 return KAsync::start<QByteArray>([=]() -> QByteArray { 405 return KAsync::start<QByteArray>([=]() -> QByteArray {
407 return remoteId.toUtf8(); 406 return remoteId.toUtf8();
408 }); 407 });
409 } else if (operation == Sink::Operation_Removal) { 408 } else if (operation == Sink::Operation_Removal) {
410 Trace() << "Removing a mail: " << oldRemoteId; 409 SinkTrace() << "Removing a mail: " << oldRemoteId;
411 return KAsync::null<QByteArray>(); 410 return KAsync::null<QByteArray>();
412 } else if (operation == Sink::Operation_Modification) { 411 } else if (operation == Sink::Operation_Modification) {
413 Trace() << "Modifying a mail: " << oldRemoteId; 412 SinkTrace() << "Modifying a mail: " << oldRemoteId;
414 const auto remoteId = getFilePathFromMimeMessagePath(mail.getMimeMessagePath()); 413 const auto remoteId = getFilePathFromMimeMessagePath(mail.getMimeMessagePath());
415 return KAsync::start<QByteArray>([=]() -> QByteArray { 414 return KAsync::start<QByteArray>([=]() -> QByteArray {
416 return remoteId.toUtf8(); 415 return remoteId.toUtf8();
@@ -425,7 +424,7 @@ public:
425 auto folderName = folder.getName(); 424 auto folderName = folder.getName();
426 //FIXME handle non toplevel folders 425 //FIXME handle non toplevel folders
427 auto path = mMaildirPath + "/" + folderName; 426 auto path = mMaildirPath + "/" + folderName;
428 Trace() << "Creating a new folder: " << path; 427 SinkTrace() << "Creating a new folder: " << path;
429 KPIM::Maildir maildir(path, false); 428 KPIM::Maildir maildir(path, false);
430 maildir.create(); 429 maildir.create();
431 return KAsync::start<QByteArray>([=]() -> QByteArray { 430 return KAsync::start<QByteArray>([=]() -> QByteArray {
@@ -433,12 +432,12 @@ public:
433 }); 432 });
434 } else if (operation == Sink::Operation_Removal) { 433 } else if (operation == Sink::Operation_Removal) {
435 const auto path = oldRemoteId; 434 const auto path = oldRemoteId;
436 Trace() << "Removing a folder: " << path; 435 SinkTrace() << "Removing a folder: " << path;
437 KPIM::Maildir maildir(path, false); 436 KPIM::Maildir maildir(path, false);
438 maildir.remove(); 437 maildir.remove();
439 return KAsync::null<QByteArray>(); 438 return KAsync::null<QByteArray>();
440 } else if (operation == Sink::Operation_Modification) { 439 } else if (operation == Sink::Operation_Modification) {
441 Warning() << "Folder modifications are not implemented"; 440 SinkWarning() << "Folder modifications are not implemented";
442 return KAsync::start<QByteArray>([=]() -> QByteArray { 441 return KAsync::start<QByteArray>([=]() -> QByteArray {
443 return oldRemoteId; 442 return oldRemoteId;
444 }); 443 });
@@ -472,7 +471,7 @@ MaildirResource::MaildirResource(const QByteArray &instanceIdentifier, const QSh
472 setupPreprocessors(ENTITY_TYPE_FOLDER, QVector<Sink::Preprocessor*>() << new FolderPreprocessor(mMaildirPath) << new DefaultIndexUpdater<Sink::ApplicationDomain::Folder>); 471 setupPreprocessors(ENTITY_TYPE_FOLDER, QVector<Sink::Preprocessor*>() << new FolderPreprocessor(mMaildirPath) << new DefaultIndexUpdater<Sink::ApplicationDomain::Folder>);
473 472
474 KPIM::Maildir dir(mMaildirPath, true); 473 KPIM::Maildir dir(mMaildirPath, true);
475 Trace() << "Started maildir resource for maildir: " << mMaildirPath; 474 SinkTrace() << "Started maildir resource for maildir: " << mMaildirPath;
476 { 475 {
477 auto draftsFolder = dir.addSubFolder("Drafts"); 476 auto draftsFolder = dir.addSubFolder("Drafts");
478 auto remoteId = synchronizer->createFolder(draftsFolder, "folder", QByteArrayList() << "drafts"); 477 auto remoteId = synchronizer->createFolder(draftsFolder, "folder", QByteArrayList() << "drafts");
@@ -503,7 +502,7 @@ KAsync::Job<void> MaildirResource::inspect(int inspectionType, const QByteArray
503 auto entityStore = QSharedPointer<EntityStore>::create(mResourceType, mResourceInstanceIdentifier, transaction); 502 auto entityStore = QSharedPointer<EntityStore>::create(mResourceType, mResourceInstanceIdentifier, transaction);
504 auto syncStore = QSharedPointer<RemoteIdMap>::create(synchronizationTransaction); 503 auto syncStore = QSharedPointer<RemoteIdMap>::create(synchronizationTransaction);
505 504
506 Trace() << "Inspecting " << inspectionType << domainType << entityId << property << expectedValue; 505 SinkTrace() << "Inspecting " << inspectionType << domainType << entityId << property << expectedValue;
507 506
508 if (domainType == ENTITY_TYPE_MAIL) { 507 if (domainType == ENTITY_TYPE_MAIL) {
509 auto mail = entityStore->read<Sink::ApplicationDomain::Mail>(entityId); 508 auto mail = entityStore->read<Sink::ApplicationDomain::Mail>(entityId);
@@ -542,7 +541,7 @@ KAsync::Job<void> MaildirResource::inspect(int inspectionType, const QByteArray
542 auto folder = entityStore->read<Sink::ApplicationDomain::Folder>(entityId); 541 auto folder = entityStore->read<Sink::ApplicationDomain::Folder>(entityId);
543 542
544 if (inspectionType == Sink::ResourceControl::Inspection::CacheIntegrityInspectionType) { 543 if (inspectionType == Sink::ResourceControl::Inspection::CacheIntegrityInspectionType) {
545 Trace() << "Inspecting cache integrity" << remoteId; 544 SinkTrace() << "Inspecting cache integrity" << remoteId;
546 if (!QDir(remoteId).exists()) { 545 if (!QDir(remoteId).exists()) {
547 return KAsync::error<void>(1, "The directory is not existing: " + remoteId); 546 return KAsync::error<void>(1, "The directory is not existing: " + remoteId);
548 } 547 }
@@ -553,14 +552,14 @@ KAsync::Job<void> MaildirResource::inspect(int inspectionType, const QByteArray
553 expectedCount++; 552 expectedCount++;
554 }, 553 },
555 [&](const Index::Error &error) { 554 [&](const Index::Error &error) {
556 Warning() << "Error in index: " << error.message << property; 555 SinkWarning() << "Error in index: " << error.message << property;
557 }); 556 });
558 557
559 QDir dir(remoteId + "/cur"); 558 QDir dir(remoteId + "/cur");
560 const QFileInfoList list = dir.entryInfoList(QDir::Files); 559 const QFileInfoList list = dir.entryInfoList(QDir::Files);
561 if (list.size() != expectedCount) { 560 if (list.size() != expectedCount) {
562 for (const auto &fileInfo : list) { 561 for (const auto &fileInfo : list) {
563 Warning() << "Found in cache: " << fileInfo.fileName(); 562 SinkWarning() << "Found in cache: " << fileInfo.fileName();
564 } 563 }
565 return KAsync::error<void>(1, QString("Wrong number of files; found %1 instead of %2.").arg(list.size()).arg(expectedCount)); 564 return KAsync::error<void>(1, QString("Wrong number of files; found %1 instead of %2.").arg(list.size()).arg(expectedCount));
566 } 565 }
diff --git a/examples/maildirresource/maildirresource.h b/examples/maildirresource/maildirresource.h
index d481b22..76aef77 100644
--- a/examples/maildirresource/maildirresource.h
+++ b/examples/maildirresource/maildirresource.h
@@ -26,7 +26,7 @@
26#include <flatbuffers/flatbuffers.h> 26#include <flatbuffers/flatbuffers.h>
27 27
28//TODO: a little ugly to have this in two places, once here and once in Q_PLUGIN_METADATA 28//TODO: a little ugly to have this in two places, once here and once in Q_PLUGIN_METADATA
29#define PLUGIN_NAME "org.kde.maildir" 29#define PLUGIN_NAME "sink.maildir"
30 30
31class MaildirMailAdaptorFactory; 31class MaildirMailAdaptorFactory;
32class MaildirFolderAdaptorFactory; 32class MaildirFolderAdaptorFactory;
@@ -58,7 +58,7 @@ private:
58class MaildirResourceFactory : public Sink::ResourceFactory 58class MaildirResourceFactory : public Sink::ResourceFactory
59{ 59{
60 Q_OBJECT 60 Q_OBJECT
61 Q_PLUGIN_METADATA(IID "org.kde.maildir") 61 Q_PLUGIN_METADATA(IID "sink.maildir")
62 Q_INTERFACES(Sink::ResourceFactory) 62 Q_INTERFACES(Sink::ResourceFactory)
63 63
64public: 64public:
diff --git a/examples/mailtransportresource/mailtransportresource.cpp b/examples/mailtransportresource/mailtransportresource.cpp
index 1e93bdf..a729d4d 100644
--- a/examples/mailtransportresource/mailtransportresource.cpp
+++ b/examples/mailtransportresource/mailtransportresource.cpp
@@ -44,6 +44,8 @@
44 44
45#define ENTITY_TYPE_MAIL "mail" 45#define ENTITY_TYPE_MAIL "mail"
46 46
47SINK_DEBUG_AREA("mailtransportresource")
48
47using namespace Sink; 49using namespace Sink;
48 50
49//TODO fold into synchronizer 51//TODO fold into synchronizer
@@ -58,7 +60,7 @@ public:
58 KAsync::Job<QByteArray> replay(const ApplicationDomain::Mail &mail, Sink::Operation operation, const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties) Q_DECL_OVERRIDE 60 KAsync::Job<QByteArray> replay(const ApplicationDomain::Mail &mail, Sink::Operation operation, const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties) Q_DECL_OVERRIDE
59 { 61 {
60 if (operation == Sink::Operation_Creation) { 62 if (operation == Sink::Operation_Creation) {
61 Trace() << "Dispatching message."; 63 SinkTrace() << "Dispatching message.";
62 // return send(mail, mSettings); 64 // return send(mail, mSettings);
63 } else if (operation == Sink::Operation_Removal) { 65 } else if (operation == Sink::Operation_Removal) {
64 } else if (operation == Sink::Operation_Modification) { 66 } else if (operation == Sink::Operation_Modification) {
@@ -86,9 +88,9 @@ public:
86 msg->setHead(KMime::CRLFtoLF(data)); 88 msg->setHead(KMime::CRLFtoLF(data));
87 msg->parse(); 89 msg->parse();
88 if (settings.testMode) { 90 if (settings.testMode) {
89 Log() << "I would totally send that mail, but I'm in test mode." << mail.identifier(); 91 SinkLog() << "I would totally send that mail, but I'm in test mode." << mail.identifier();
90 auto path = resourceStorageLocation(mResourceInstanceIdentifier) + "/test/"; 92 auto path = resourceStorageLocation(mResourceInstanceIdentifier) + "/test/";
91 Trace() << path; 93 SinkTrace() << path;
92 QDir dir; 94 QDir dir;
93 dir.mkpath(path); 95 dir.mkpath(path);
94 QFile f(path+ mail.identifier()); 96 QFile f(path+ mail.identifier());
@@ -97,9 +99,9 @@ public:
97 f.close(); 99 f.close();
98 } else { 100 } else {
99 if (MailTransport::sendMessage(msg, settings.server.toUtf8(), settings.username.toUtf8(), settings.password.toUtf8(), settings.cacert.toUtf8())) { 101 if (MailTransport::sendMessage(msg, settings.server.toUtf8(), settings.username.toUtf8(), settings.password.toUtf8(), settings.cacert.toUtf8())) {
100 Log() << "Sent message successfully"; 102 SinkLog() << "Sent message successfully";
101 } else { 103 } else {
102 Log() << "Failed to send message"; 104 SinkLog() << "Failed to send message";
103 return KAsync::error<void>(1, "Failed to send the message."); 105 return KAsync::error<void>(1, "Failed to send the message.");
104 } 106 }
105 } 107 }
@@ -108,13 +110,13 @@ public:
108 110
109 KAsync::Job<void> synchronizeWithSource() Q_DECL_OVERRIDE 111 KAsync::Job<void> synchronizeWithSource() Q_DECL_OVERRIDE
110 { 112 {
111 Log() << " Synchronizing"; 113 SinkLog() << " Synchronizing";
112 return KAsync::start<void>([this](KAsync::Future<void> future) { 114 return KAsync::start<void>([this](KAsync::Future<void> future) {
113 Sink::Query query; 115 Sink::Query query;
114 QList<ApplicationDomain::Mail> toSend; 116 QList<ApplicationDomain::Mail> toSend;
115 Log() << " Looking for mail"; 117 SinkLog() << " Looking for mail";
116 store().reader<ApplicationDomain::Mail>().query(query, [&](const ApplicationDomain::Mail &mail) -> bool { 118 store().reader<ApplicationDomain::Mail>().query(query, [&](const ApplicationDomain::Mail &mail) -> bool {
117 Trace() << "Found mail: " << mail.identifier(); 119 SinkTrace() << "Found mail: " << mail.identifier();
118 if (!mail.getSent()) { 120 if (!mail.getSent()) {
119 toSend << mail; 121 toSend << mail;
120 } 122 }
diff --git a/examples/mailtransportresource/mailtransportresource.h b/examples/mailtransportresource/mailtransportresource.h
index 6622ea6..cf6abf2 100644
--- a/examples/mailtransportresource/mailtransportresource.h
+++ b/examples/mailtransportresource/mailtransportresource.h
@@ -23,7 +23,7 @@
23#include "common/genericresource.h" 23#include "common/genericresource.h"
24 24
25//TODO: a little ugly to have this in two places, once here and once in Q_PLUGIN_METADATA 25//TODO: a little ugly to have this in two places, once here and once in Q_PLUGIN_METADATA
26#define PLUGIN_NAME "org.kde.mailtransport" 26#define PLUGIN_NAME "sink.mailtransport"
27 27
28class MailtransportResource : public Sink::GenericResource 28class MailtransportResource : public Sink::GenericResource
29{ 29{
@@ -46,7 +46,7 @@ private:
46class MailtransportResourceFactory : public Sink::ResourceFactory 46class MailtransportResourceFactory : public Sink::ResourceFactory
47{ 47{
48 Q_OBJECT 48 Q_OBJECT
49 Q_PLUGIN_METADATA(IID "org.kde.mailtransport") 49 Q_PLUGIN_METADATA(IID "sink.mailtransport")
50 Q_INTERFACES(Sink::ResourceFactory) 50 Q_INTERFACES(Sink::ResourceFactory)
51 51
52public: 52public:
diff --git a/examples/mailtransportresource/tests/mailtransporttest.cpp b/examples/mailtransportresource/tests/mailtransporttest.cpp
index 3ce5f82..fdd591b 100644
--- a/examples/mailtransportresource/tests/mailtransporttest.cpp
+++ b/examples/mailtransportresource/tests/mailtransporttest.cpp
@@ -33,7 +33,6 @@ private slots:
33 void initTestCase() 33 void initTestCase()
34 { 34 {
35 Test::initTest(); 35 Test::initTest();
36 Log::setDebugOutputLevel(Sink::Log::Trace);
37 auto resource = createResource(); 36 auto resource = createResource();
38 QVERIFY(!resource.identifier().isEmpty()); 37 QVERIFY(!resource.identifier().isEmpty());
39 VERIFYEXEC(Store::create(resource)); 38 VERIFYEXEC(Store::create(resource));
diff --git a/sinksh/CMakeLists.txt b/sinksh/CMakeLists.txt
index e7d3b6e..f0e2f6c 100644
--- a/sinksh/CMakeLists.txt
+++ b/sinksh/CMakeLists.txt
@@ -15,6 +15,7 @@ set(sink_cli_SRCS
15 syntax_modules/sink_stat.cpp 15 syntax_modules/sink_stat.cpp
16 syntax_modules/sink_sync.cpp 16 syntax_modules/sink_sync.cpp
17 syntax_modules/sink_show.cpp 17 syntax_modules/sink_show.cpp
18 syntax_modules/sink_trace.cpp
18 sinksh_utils.cpp 19 sinksh_utils.cpp
19 repl/repl.cpp 20 repl/repl.cpp
20 repl/replStates.cpp 21 repl/replStates.cpp
diff --git a/sinksh/sinksh_utils.cpp b/sinksh/sinksh_utils.cpp
index 091eb38..0e26c5a 100644
--- a/sinksh/sinksh_utils.cpp
+++ b/sinksh/sinksh_utils.cpp
@@ -21,6 +21,7 @@
21#include "sinksh_utils.h" 21#include "sinksh_utils.h"
22 22
23#include "common/store.h" 23#include "common/store.h"
24#include "common/log.h"
24 25
25#include "utils.h" 26#include "utils.h"
26 27
@@ -88,48 +89,35 @@ QSharedPointer<QAbstractItemModel> loadModel(const QString &type, Sink::Query qu
88 return model; 89 return model;
89} 90}
90 91
91QStringList resourceIds(State &state) 92QStringList resourceIds()
92{ 93{
93 QStringList resources;
94 Sink::Query query; 94 Sink::Query query;
95 query.liveQuery = false; 95 query.liveQuery = false;
96 auto model = SinkshUtils::loadModel("resource", query); 96 QStringList resources;
97 97 for (const auto &r : getStore("resource").read(query)) {
98 QObject::connect(model.data(), &QAbstractItemModel::rowsInserted, [model, &resources](const QModelIndex &index, int start, int end) mutable { 98 resources << r.identifier();
99 for (int i = start; i <= end; i++) { 99 }
100 auto object = model->data(model->index(i, 0, index), Sink::Store::DomainObjectBaseRole).value<Sink::ApplicationDomain::ApplicationDomainType::Ptr>();
101 resources << object->identifier();
102 }
103 });
104
105 QObject::connect(model.data(), &QAbstractItemModel::dataChanged, [model, state](const QModelIndex &, const QModelIndex &, const QVector<int> &roles) {
106 if (roles.contains(Sink::Store::ChildrenFetchedRole)) {
107 state.commandFinished();
108 }
109 });
110
111 state.commandStarted();
112
113 return resources; 100 return resources;
114} 101}
115 102
103QStringList debugareaCompleter(const QStringList &, const QString &fragment, State &state)
104{
105 return Utils::filteredCompletions(Sink::Log::debugAreas().toList(), fragment);
106}
107
116QStringList resourceCompleter(const QStringList &, const QString &fragment, State &state) 108QStringList resourceCompleter(const QStringList &, const QString &fragment, State &state)
117{ 109{
118 return Utils::filteredCompletions(resourceIds(state), fragment); 110 return Utils::filteredCompletions(resourceIds(), fragment);
119} 111}
120 112
121QStringList resourceOrTypeCompleter(const QStringList &commands, const QString &fragment, State &state) 113QStringList resourceOrTypeCompleter(const QStringList &commands, const QString &fragment, State &state)
122{ 114{
123 static QStringList types = QStringList() << "resource" 115 static QStringList types = s_types;
124 << "folder"
125 << "mail"
126 << "event"
127 << "account";
128 if (commands.count() == 1) { 116 if (commands.count() == 1) {
129 return Utils::filteredCompletions(s_types, fragment); 117 return Utils::filteredCompletions(s_types, fragment);
130 } 118 }
131 119
132 return Utils::filteredCompletions(resourceIds(state), fragment); 120 return Utils::filteredCompletions(resourceIds(), fragment);
133} 121}
134 122
135QStringList typeCompleter(const QStringList &commands, const QString &fragment, State &state) 123QStringList typeCompleter(const QStringList &commands, const QString &fragment, State &state)
diff --git a/sinksh/sinksh_utils.h b/sinksh/sinksh_utils.h
index b5b6f3c..0a47661 100644
--- a/sinksh/sinksh_utils.h
+++ b/sinksh/sinksh_utils.h
@@ -40,6 +40,7 @@ QStringList resourceIds();
40QStringList resourceCompleter(const QStringList &, const QString &fragment, State &state); 40QStringList resourceCompleter(const QStringList &, const QString &fragment, State &state);
41QStringList resourceOrTypeCompleter(const QStringList &commands, const QString &fragment, State &state); 41QStringList resourceOrTypeCompleter(const QStringList &commands, const QString &fragment, State &state);
42QStringList typeCompleter(const QStringList &commands, const QString &fragment, State &state); 42QStringList typeCompleter(const QStringList &commands, const QString &fragment, State &state);
43QStringList debugareaCompleter(const QStringList &, const QString &fragment, State &state);
43QMap<QString, QString> keyValueMapFromArgs(const QStringList &args); 44QMap<QString, QString> keyValueMapFromArgs(const QStringList &args);
44 45
45/** 46/**
diff --git a/sinksh/syntax_modules/sink_clear.cpp b/sinksh/syntax_modules/sink_clear.cpp
index 72d9a14..1537ecd 100644
--- a/sinksh/syntax_modules/sink_clear.cpp
+++ b/sinksh/syntax_modules/sink_clear.cpp
@@ -50,7 +50,7 @@ bool clear(const QStringList &args, State &state)
50 50
51Syntax::List syntax() 51Syntax::List syntax()
52{ 52{
53 Syntax clear("clear", QObject::tr("Clears the local cache of one or more resources (be careful!)"), &SinkClear::clear); 53 Syntax clear("clear", QObject::tr("Clears the local cache of one or more resources (be careful!)"), &SinkClear::clear, Syntax::NotInteractive);
54 clear.completer = &SinkshUtils::resourceCompleter; 54 clear.completer = &SinkshUtils::resourceCompleter;
55 55
56 return Syntax::List() << clear; 56 return Syntax::List() << clear;
diff --git a/sinksh/syntax_modules/sink_remove.cpp b/sinksh/syntax_modules/sink_remove.cpp
index b374824..d474518 100644
--- a/sinksh/syntax_modules/sink_remove.cpp
+++ b/sinksh/syntax_modules/sink_remove.cpp
@@ -98,7 +98,7 @@ bool resource(const QStringList &args, State &state)
98Syntax::List syntax() 98Syntax::List syntax()
99{ 99{
100 Syntax remove("remove", QObject::tr("Remove items in a resource"), &SinkRemove::remove); 100 Syntax remove("remove", QObject::tr("Remove items in a resource"), &SinkRemove::remove);
101 Syntax resource("resource", QObject::tr("Removes a resource"), &SinkRemove::resource);//, Syntax::EventDriven); 101 Syntax resource("resource", QObject::tr("Removes a resource"), &SinkRemove::resource, Syntax::NotInteractive);
102 resource.completer = &SinkshUtils::resourceCompleter; 102 resource.completer = &SinkshUtils::resourceCompleter;
103 remove.children << resource; 103 remove.children << resource;
104 104
diff --git a/sinksh/syntax_modules/sink_stat.cpp b/sinksh/syntax_modules/sink_stat.cpp
index 06586d9..9f0fe44 100644
--- a/sinksh/syntax_modules/sink_stat.cpp
+++ b/sinksh/syntax_modules/sink_stat.cpp
@@ -70,30 +70,11 @@ bool statAllResources(State &state)
70{ 70{
71 Sink::Query query; 71 Sink::Query query;
72 query.liveQuery = false; 72 query.liveQuery = false;
73 auto model = SinkshUtils::loadModel("resource", query); 73 QStringList resources;
74 74 for (const auto &r : SinkshUtils::getStore("resource").read(query)) {
75 //SUUUPER ugly, but can't think of a better way with 2 glasses of wine in me on Christmas day 75 resources << r.identifier();
76 static QStringList resources;
77 resources.clear();
78
79 QObject::connect(model.data(), &QAbstractItemModel::rowsInserted, [model](const QModelIndex &index, int start, int end) mutable {
80 for (int i = start; i <= end; i++) {
81 auto object = model->data(model->index(i, 0, index), Sink::Store::DomainObjectBaseRole).value<Sink::ApplicationDomain::ApplicationDomainType::Ptr>();
82 resources << object->identifier();
83 }
84 });
85
86 QObject::connect(model.data(), &QAbstractItemModel::dataChanged, [model, state](const QModelIndex &, const QModelIndex &, const QVector<int> &roles) {
87 if (roles.contains(Sink::Store::ChildrenFetchedRole)) {
88 statResources(resources, state);
89 state.commandFinished();
90 }
91 });
92
93 if (!model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()) {
94 return true;
95 } 76 }
96 77 statResources(resources, state);
97 return false; 78 return false;
98} 79}
99 80
@@ -109,7 +90,7 @@ bool stat(const QStringList &args, State &state)
109 90
110Syntax::List syntax() 91Syntax::List syntax()
111{ 92{
112 Syntax state("stat", QObject::tr("Shows database usage for the resources requested"), &SinkStat::stat, Syntax::EventDriven); 93 Syntax state("stat", QObject::tr("Shows database usage for the resources requested"), &SinkStat::stat, Syntax::NotInteractive);
113 state.completer = &SinkshUtils::resourceCompleter; 94 state.completer = &SinkshUtils::resourceCompleter;
114 95
115 return Syntax::List() << state; 96 return Syntax::List() << state;
diff --git a/sinksh/syntax_modules/sink_sync.cpp b/sinksh/syntax_modules/sink_sync.cpp
index 3006202..208b869 100644
--- a/sinksh/syntax_modules/sink_sync.cpp
+++ b/sinksh/syntax_modules/sink_sync.cpp
@@ -56,7 +56,7 @@ bool sync(const QStringList &args, State &state)
56 56
57Syntax::List syntax() 57Syntax::List syntax()
58{ 58{
59 Syntax sync("sync", QObject::tr("Syncronizes all resources that are listed; and empty list triggers a syncronizaton on all resources"), &SinkSync::sync, Syntax::EventDriven ); 59 Syntax sync("sync", QObject::tr("Syncronizes all resources that are listed; and empty list triggers a syncronizaton on all resources"), &SinkSync::sync, Syntax::EventDriven);
60 sync.completer = &SinkshUtils::resourceCompleter; 60 sync.completer = &SinkshUtils::resourceCompleter;
61 61
62 return Syntax::List() << sync; 62 return Syntax::List() << sync;
diff --git a/sinksh/syntax_modules/sink_trace.cpp b/sinksh/syntax_modules/sink_trace.cpp
new file mode 100644
index 0000000..8bd52a0
--- /dev/null
+++ b/sinksh/syntax_modules/sink_trace.cpp
@@ -0,0 +1,87 @@
1/*
2 * Copyright (C) 2016 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 <QDebug>
21#include <QObject> // tr()
22#include <QTimer>
23
24#include "common/resource.h"
25#include "common/storage.h"
26#include "common/resourceconfig.h"
27#include "common/log.h"
28#include "common/storage.h"
29#include "common/definitions.h"
30
31#include "sinksh_utils.h"
32#include "state.h"
33#include "syntaxtree.h"
34#include "iostream"
35
36namespace SinkTrace
37{
38
39bool traceOff(const QStringList &args, State &state)
40{
41 Sink::Log::setDebugOutputLevel(Sink::Log::Log);
42 std::cout << "Turned trace off." << std::endl;
43 return true;
44}
45
46bool traceOn(const QStringList &args, State &state)
47{
48 Sink::Log::setDebugOutputLevel(Sink::Log::Trace);
49 if (args.isEmpty() || (args.size() == 1 && args.first() == "*")) {
50 Sink::Log::setDebugOutputFilter(Sink::Log::Area, QByteArrayList());
51 std::cout << "Set trace filter to: *" << std::endl;
52 } else {
53 QByteArrayList filter;
54 for (const auto &arg : args) {
55 filter << arg.toLatin1();
56 }
57 Sink::Log::setDebugOutputFilter(Sink::Log::Area, filter);
58 std::cout << "Set trace filter to: " << filter.join(", ").toStdString() << std::endl;
59 }
60 return true;
61}
62
63bool trace(const QStringList &args, State &state)
64{
65 return traceOn(args, state);
66}
67
68
69Syntax::List syntax()
70{
71 Syntax trace("trace", QObject::tr("Control trace debug output."), &SinkTrace::trace, Syntax::NotInteractive);
72 trace.completer = &SinkshUtils::debugareaCompleter;
73
74 Syntax traceOff("off", QObject::tr("Turns off trace output."), &SinkTrace::traceOff, Syntax::NotInteractive);
75 traceOff.completer = &SinkshUtils::debugareaCompleter;
76 trace.children << traceOff;
77
78 Syntax traceOn("on", QObject::tr("Turns on trace output."), &SinkTrace::traceOn, Syntax::NotInteractive);
79 traceOn.completer = &SinkshUtils::debugareaCompleter;
80 trace.children << traceOn;
81
82 return Syntax::List() << trace;
83}
84
85REGISTER_SYNTAX(SinkTrace)
86
87}
diff --git a/synchronizer/main.cpp b/synchronizer/main.cpp
index 3168bfc..e9dd6cb 100644
--- a/synchronizer/main.cpp
+++ b/synchronizer/main.cpp
@@ -34,8 +34,7 @@
34#include "log.h" 34#include "log.h"
35#include "test.h" 35#include "test.h"
36 36
37#undef DEBUG_AREA 37SINK_DEBUG_AREA("main")
38#define DEBUG_AREA "resource"
39 38
40static Listener *listener = nullptr; 39static Listener *listener = nullptr;
41 40
@@ -149,25 +148,26 @@ int main(int argc, char *argv[])
149 arguments << argv[i]; 148 arguments << argv[i];
150 } 149 }
151 if (arguments.contains("--test")) { 150 if (arguments.contains("--test")) {
152 Log() << "Running in test-mode"; 151 SinkLog() << "Running in test-mode";
153 arguments.removeAll("--test"); 152 arguments.removeAll("--test");
154 Sink::Test::setTestModeEnabled(true); 153 Sink::Test::setTestModeEnabled(true);
155 } 154 }
156 155
157 if (arguments.count() < 3) { 156 if (arguments.count() < 3) {
158 Warning() << "Not enough args passed, no resource loaded."; 157 SinkWarning() << "Not enough args passed, no resource loaded.";
159 return app.exec(); 158 return app.exec();
160 } 159 }
161 160
162 const QByteArray instanceIdentifier = arguments.at(1); 161 const QByteArray instanceIdentifier = arguments.at(1);
163 const QByteArray resourceType = arguments.at(2); 162 const QByteArray resourceType = arguments.at(2);
164 app.setApplicationName(instanceIdentifier); 163 app.setApplicationName(instanceIdentifier);
165 Log() << "Starting: " << instanceIdentifier; 164 Sink::Log::setPrimaryComponent(instanceIdentifier);
165 SinkLog() << "Starting: " << instanceIdentifier;
166 166
167 QLockFile lockfile(instanceIdentifier + ".lock"); 167 QLockFile lockfile(instanceIdentifier + ".lock");
168 lockfile.setStaleLockTime(500); 168 lockfile.setStaleLockTime(500);
169 if (!lockfile.tryLock(0)) { 169 if (!lockfile.tryLock(0)) {
170 Warning() << "Failed to acquire exclusive lock on socket."; 170 SinkWarning() << "Failed to acquire exclusive lock on socket.";
171 return -1; 171 return -1;
172 } 172 }
173 173
@@ -177,6 +177,6 @@ int main(int argc, char *argv[])
177 QObject::connect(listener, &Listener::noClients, &app, &QCoreApplication::quit); 177 QObject::connect(listener, &Listener::noClients, &app, &QCoreApplication::quit);
178 178
179 auto ret = app.exec(); 179 auto ret = app.exec();
180 Log() << "Exiting: " << instanceIdentifier; 180 SinkLog() << "Exiting: " << instanceIdentifier;
181 return ret; 181 return ret;
182} 182}
diff --git a/tests/accountstest.cpp b/tests/accountstest.cpp
index be5e1a0..4be8bd6 100644
--- a/tests/accountstest.cpp
+++ b/tests/accountstest.cpp
@@ -8,6 +8,7 @@
8#include <store.h> 8#include <store.h>
9#include <log.h> 9#include <log.h>
10#include <configstore.h> 10#include <configstore.h>
11#include "testutils.h"
11 12
12class AccountsTest : public QObject 13class AccountsTest : public QObject
13{ 14{
@@ -17,7 +18,6 @@ private slots:
17 void initTestCase() 18 void initTestCase()
18 { 19 {
19 Sink::Test::initTest(); 20 Sink::Test::initTest();
20 Sink::Log::setDebugOutputLevel(Sink::Log::Trace);
21 } 21 }
22 22
23 void init() 23 void init()
@@ -52,7 +52,7 @@ private slots:
52 QString smtpUsername("smtpUsername"); 52 QString smtpUsername("smtpUsername");
53 QString smtpPassword("smtpPassword"); 53 QString smtpPassword("smtpPassword");
54 auto resource = ApplicationDomainType::createEntity<SinkResource>(); 54 auto resource = ApplicationDomainType::createEntity<SinkResource>();
55 resource.setProperty("type", "org.kde.mailtransport"); 55 resource.setProperty("type", "sink.mailtransport");
56 resource.setProperty("account", account.identifier()); 56 resource.setProperty("account", account.identifier());
57 resource.setProperty("server", smtpServer); 57 resource.setProperty("server", smtpServer);
58 resource.setProperty("username", smtpUsername); 58 resource.setProperty("username", smtpUsername);
@@ -63,7 +63,7 @@ private slots:
63 Store::fetchAll<SinkResource>(Query()).then<void, QList<SinkResource::Ptr>>([&](const QList<SinkResource::Ptr> &resources) { 63 Store::fetchAll<SinkResource>(Query()).then<void, QList<SinkResource::Ptr>>([&](const QList<SinkResource::Ptr> &resources) {
64 QCOMPARE(resources.size(), 1); 64 QCOMPARE(resources.size(), 1);
65 auto resource = resources.first(); 65 auto resource = resources.first();
66 QCOMPARE(resource->getProperty("type").toString(), QString("org.kde.mailtransport")); 66 QCOMPARE(resource->getProperty("type").toString(), QString("sink.mailtransport"));
67 QCOMPARE(resource->getProperty("server").toString(), smtpServer); 67 QCOMPARE(resource->getProperty("server").toString(), smtpServer);
68 }) 68 })
69 .exec().waitForFinished(); 69 .exec().waitForFinished();
@@ -94,8 +94,8 @@ private slots:
94 using namespace Sink::ApplicationDomain; 94 using namespace Sink::ApplicationDomain;
95 95
96 auto account = ApplicationDomainType::createEntity<SinkAccount>(); 96 auto account = ApplicationDomainType::createEntity<SinkAccount>();
97 account.setProperty("type", "maildir"); 97 account.setAccountType("maildir");
98 account.setProperty("name", "name"); 98 account.setName("name");
99 Store::create(account).exec().waitForFinished(); 99 Store::create(account).exec().waitForFinished();
100 100
101 Query query; 101 Query query;
@@ -104,18 +104,47 @@ private slots:
104 QTRY_COMPARE(model->rowCount(QModelIndex()), 1); 104 QTRY_COMPARE(model->rowCount(QModelIndex()), 1);
105 105
106 auto account2 = ApplicationDomainType::createEntity<SinkAccount>(); 106 auto account2 = ApplicationDomainType::createEntity<SinkAccount>();
107 account2.setProperty("type", "maildir"); 107 account2.setAccountType("maildir");
108 account2.setProperty("name", "name"); 108 account2.setName("name");
109 Store::create(account2).exec().waitForFinished(); 109 Store::create(account2).exec().waitForFinished();
110 QTRY_COMPARE(model->rowCount(QModelIndex()), 2); 110 QTRY_COMPARE(model->rowCount(QModelIndex()), 2);
111 111
112 //Ensure the notifier only affects one type 112 //Ensure the notifier only affects one type
113 auto resource = ApplicationDomainType::createEntity<SinkResource>(); 113 auto resource = ApplicationDomainType::createEntity<SinkResource>();
114 resource.setProperty("type", "org.kde.mailtransport"); 114 resource.setResourceType("sink.mailtransport");
115 Store::create(resource).exec().waitForFinished(); 115 Store::create(resource).exec().waitForFinished();
116 QTRY_COMPARE(model->rowCount(QModelIndex()), 2); 116 QTRY_COMPARE(model->rowCount(QModelIndex()), 2);
117 } 117 }
118 118
119 void testLoadAccountStatus()
120 {
121 using namespace Sink;
122 using namespace Sink::ApplicationDomain;
123
124 auto account = ApplicationDomainType::createEntity<SinkAccount>();
125 account.setAccountType("dummy");
126 account.setName("name");
127 VERIFYEXEC(Store::create(account));
128
129 auto res = Sink::ApplicationDomain::DummyResource::create(account.identifier());
130 VERIFYEXEC(Sink::Store::create(res));
131 {
132 Sink::Query query;
133 query.liveQuery = true;
134 query.request<Sink::ApplicationDomain::SinkAccount::Status>();
135
136 auto model = Sink::Store::loadModel<Sink::ApplicationDomain::SinkAccount>(query);
137 QTRY_COMPARE(model->rowCount(QModelIndex()), 1);
138 auto account = model->data(model->index(0, 0, QModelIndex()), Sink::Store::DomainObjectRole).value<Sink::ApplicationDomain::SinkAccount::Ptr>();
139 QCOMPARE(account->getStatus(), static_cast<int>(Sink::ApplicationDomain::OfflineStatus));
140
141 //Synchronize to connect
142 VERIFYEXEC(Sink::Store::synchronize(Query::ResourceFilter(res)));
143
144 QTRY_COMPARE_WITH_TIMEOUT(model->data(model->index(0, 0, QModelIndex()), Sink::Store::DomainObjectRole).value<Sink::ApplicationDomain::SinkAccount::Ptr>()->getStatus(), static_cast<int>(Sink::ApplicationDomain::ConnectedStatus), 1000);
145 }
146 }
147
119}; 148};
120 149
121QTEST_GUILESS_MAIN(AccountsTest) 150QTEST_GUILESS_MAIN(AccountsTest)
diff --git a/tests/clientapitest.cpp b/tests/clientapitest.cpp
index 8c5866d..ed5a9b5 100644
--- a/tests/clientapitest.cpp
+++ b/tests/clientapitest.cpp
@@ -9,6 +9,8 @@
9#include "resultprovider.h" 9#include "resultprovider.h"
10#include "facadefactory.h" 10#include "facadefactory.h"
11 11
12SINK_DEBUG_AREA("clientapitest")
13
12template <typename T> 14template <typename T>
13class TestDummyResourceFacade : public Sink::StoreFacade<T> 15class TestDummyResourceFacade : public Sink::StoreFacade<T>
14{ 16{
@@ -44,7 +46,7 @@ public:
44 { 46 {
45 auto resultProvider = new Sink::ResultProvider<typename T::Ptr>(); 47 auto resultProvider = new Sink::ResultProvider<typename T::Ptr>();
46 resultProvider->onDone([resultProvider]() { 48 resultProvider->onDone([resultProvider]() {
47 Trace() << "Result provider is done"; 49 SinkTrace() << "Result provider is done";
48 delete resultProvider; 50 delete resultProvider;
49 }); 51 });
50 // We have to do it this way, otherwise we're not setting the fetcher right 52 // We have to do it this way, otherwise we're not setting the fetcher right
@@ -52,11 +54,11 @@ public:
52 54
53 resultProvider->setFetcher([query, resultProvider, this](const typename T::Ptr &parent) { 55 resultProvider->setFetcher([query, resultProvider, this](const typename T::Ptr &parent) {
54 if (parent) { 56 if (parent) {
55 Trace() << "Running the fetcher " << parent->identifier(); 57 SinkTrace() << "Running the fetcher " << parent->identifier();
56 } else { 58 } else {
57 Trace() << "Running the fetcher."; 59 SinkTrace() << "Running the fetcher.";
58 } 60 }
59 Trace() << "-------------------------."; 61 SinkTrace() << "-------------------------.";
60 for (const auto &res : results) { 62 for (const auto &res : results) {
61 qDebug() << "Parent filter " << query.propertyFilter.value("parent").value.toByteArray() << res->identifier() << res->getProperty("parent").toByteArray(); 63 qDebug() << "Parent filter " << query.propertyFilter.value("parent").value.toByteArray() << res->identifier() << res->getProperty("parent").toByteArray();
62 auto parentProperty = res->getProperty("parent").toByteArray(); 64 auto parentProperty = res->getProperty("parent").toByteArray();
@@ -91,7 +93,6 @@ private slots:
91 { 93 {
92 Sink::FacadeFactory::instance().resetFactory(); 94 Sink::FacadeFactory::instance().resetFactory();
93 ResourceConfig::clear(); 95 ResourceConfig::clear();
94 Sink::Log::setDebugOutputLevel(Sink::Log::Trace);
95 } 96 }
96 97
97 void testLoad() 98 void testLoad()
diff --git a/tests/dummyresourcebenchmark.cpp b/tests/dummyresourcebenchmark.cpp
index d5f98c3..72562c3 100644
--- a/tests/dummyresourcebenchmark.cpp
+++ b/tests/dummyresourcebenchmark.cpp
@@ -34,9 +34,9 @@ private slots:
34 void initTestCase() 34 void initTestCase()
35 { 35 {
36 Sink::Log::setDebugOutputLevel(Sink::Log::Warning); 36 Sink::Log::setDebugOutputLevel(Sink::Log::Warning);
37 auto factory = Sink::ResourceFactory::load("org.kde.dummy"); 37 auto factory = Sink::ResourceFactory::load("sink.dummy");
38 QVERIFY(factory); 38 QVERIFY(factory);
39 ResourceConfig::addResource("org.kde.dummy.instance1", "org.kde.dummy"); 39 ResourceConfig::addResource("sink.dummy.instance1", "sink.dummy");
40 num = 5000; 40 num = 5000;
41 } 41 }
42 42
@@ -76,21 +76,21 @@ private slots:
76 void testCommandResponsiveness() 76 void testCommandResponsiveness()
77 { 77 {
78 // Test responsiveness including starting the process. 78 // Test responsiveness including starting the process.
79 Sink::Store::removeDataFromDisk("org.kde.dummy.instance1").exec().waitForFinished(); 79 Sink::Store::removeDataFromDisk("sink.dummy.instance1").exec().waitForFinished();
80 80
81 QTime time; 81 QTime time;
82 time.start(); 82 time.start();
83 83
84 Sink::ApplicationDomain::Event event("org.kde.dummy.instance1"); 84 Sink::ApplicationDomain::Event event("sink.dummy.instance1");
85 event.setProperty("uid", "testuid"); 85 event.setProperty("uid", "testuid");
86 QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid")); 86 QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid"));
87 event.setProperty("summary", "summaryValue"); 87 event.setProperty("summary", "summaryValue");
88 88
89 auto notifier = QSharedPointer<Sink::Notifier>::create("org.kde.dummy.instance1", "org.kde.dummy"); 89 auto notifier = QSharedPointer<Sink::Notifier>::create("sink.dummy.instance1", "sink.dummy");
90 bool gotNotification = false; 90 bool gotNotification = false;
91 int duration = 0; 91 int duration = 0;
92 notifier->registerHandler([&gotNotification, &duration, &time](const Sink::Notification &notification) { 92 notifier->registerHandler([&gotNotification, &duration, &time](const Sink::Notification &notification) {
93 if (notification.type == Sink::Commands::NotificationType::NotificationType_RevisionUpdate) { 93 if (notification.type == Sink::Notification::RevisionUpdate) {
94 gotNotification = true; 94 gotNotification = true;
95 duration = time.elapsed(); 95 duration = time.elapsed();
96 } 96 }
@@ -102,19 +102,19 @@ private slots:
102 QTRY_VERIFY(gotNotification); 102 QTRY_VERIFY(gotNotification);
103 103
104 QVERIFY2(duration < 100, QString::fromLatin1("Processing a create command took more than 100ms: %1").arg(duration).toLatin1()); 104 QVERIFY2(duration < 100, QString::fromLatin1("Processing a create command took more than 100ms: %1").arg(duration).toLatin1());
105 Sink::ResourceControl::shutdown("org.kde.dummy.instance1").exec().waitForFinished(); 105 Sink::ResourceControl::shutdown("sink.dummy.instance1").exec().waitForFinished();
106 qDebug() << "Single command took [ms]: " << duration; 106 qDebug() << "Single command took [ms]: " << duration;
107 } 107 }
108 108
109 void testWriteToFacade() 109 void testWriteToFacade()
110 { 110 {
111 Sink::Store::removeDataFromDisk("org.kde.dummy.instance1").exec().waitForFinished(); 111 Sink::Store::removeDataFromDisk("sink.dummy.instance1").exec().waitForFinished();
112 112
113 QTime time; 113 QTime time;
114 time.start(); 114 time.start();
115 QList<KAsync::Future<void>> waitCondition; 115 QList<KAsync::Future<void>> waitCondition;
116 for (int i = 0; i < num; i++) { 116 for (int i = 0; i < num; i++) {
117 Sink::ApplicationDomain::Event event("org.kde.dummy.instance1"); 117 Sink::ApplicationDomain::Event event("sink.dummy.instance1");
118 event.setProperty("uid", "testuid"); 118 event.setProperty("uid", "testuid");
119 QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid")); 119 QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid"));
120 event.setProperty("summary", "summaryValue"); 120 event.setProperty("summary", "summaryValue");
@@ -126,7 +126,7 @@ private slots:
126 // Ensure everything is processed 126 // Ensure everything is processed
127 { 127 {
128 Sink::Query query; 128 Sink::Query query;
129 query.resources << "org.kde.dummy.instance1"; 129 query.resources << "sink.dummy.instance1";
130 Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); 130 Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished();
131 } 131 }
132 auto allProcessedTime = time.elapsed(); 132 auto allProcessedTime = time.elapsed();
@@ -140,7 +140,7 @@ private slots:
140 dataset.insertRow(row); 140 dataset.insertRow(row);
141 HAWD::Formatter::print(dataset); 141 HAWD::Formatter::print(dataset);
142 142
143 auto diskUsage = DummyResource::diskUsage("org.kde.dummy.instance1"); 143 auto diskUsage = DummyResource::diskUsage("sink.dummy.instance1");
144 qDebug() << "Database size [kb]: " << diskUsage / 1024; 144 qDebug() << "Database size [kb]: " << diskUsage / 1024;
145 145
146 // Print memory layout, RSS is what is in memory 146 // Print memory layout, RSS is what is in memory
@@ -155,7 +155,7 @@ private slots:
155 { 155 {
156 time.start(); 156 time.start();
157 Sink::Query query; 157 Sink::Query query;
158 query.resources << "org.kde.dummy.instance1"; 158 query.resources << "sink.dummy.instance1";
159 159
160 query.propertyFilter.insert("uid", Sink::Query::Comparator("testuid")); 160 query.propertyFilter.insert("uid", Sink::Query::Comparator("testuid"));
161 auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Event>(query); 161 auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Event>(query);
@@ -173,12 +173,12 @@ private slots:
173 173
174 void testWriteInProcess() 174 void testWriteInProcess()
175 { 175 {
176 Sink::Store::removeDataFromDisk("org.kde.dummy.instance1").exec().waitForFinished(); 176 Sink::Store::removeDataFromDisk("sink.dummy.instance1").exec().waitForFinished();
177 QTime time; 177 QTime time;
178 time.start(); 178 time.start();
179 179
180 auto pipeline = QSharedPointer<Sink::Pipeline>::create("org.kde.dummy.instance1"); 180 auto pipeline = QSharedPointer<Sink::Pipeline>::create("sink.dummy.instance1");
181 DummyResource resource("org.kde.dummy.instance1", pipeline); 181 DummyResource resource("sink.dummy.instance1", pipeline);
182 182
183 flatbuffers::FlatBufferBuilder eventFbb; 183 flatbuffers::FlatBufferBuilder eventFbb;
184 eventFbb.Clear(); 184 eventFbb.Clear();
@@ -261,7 +261,7 @@ private slots:
261 // This allows to run individual parts without doing a cleanup, but still cleaning up normally 261 // This allows to run individual parts without doing a cleanup, but still cleaning up normally
262 void testCleanupForCompleteTest() 262 void testCleanupForCompleteTest()
263 { 263 {
264 Sink::Store::removeDataFromDisk("org.kde.dummy.instance1").exec().waitForFinished(); 264 Sink::Store::removeDataFromDisk("sink.dummy.instance1").exec().waitForFinished();
265 } 265 }
266 266
267private: 267private:
diff --git a/tests/dummyresourcetest.cpp b/tests/dummyresourcetest.cpp
index d41f235..687a33b 100644
--- a/tests/dummyresourcetest.cpp
+++ b/tests/dummyresourcetest.cpp
@@ -30,11 +30,10 @@ private slots:
30 void initTestCase() 30 void initTestCase()
31 { 31 {
32 Sink::Test::initTest(); 32 Sink::Test::initTest();
33 Sink::Log::setDebugOutputLevel(Sink::Log::Trace); 33 auto factory = Sink::ResourceFactory::load("sink.dummy");
34 auto factory = Sink::ResourceFactory::load("org.kde.dummy");
35 QVERIFY(factory); 34 QVERIFY(factory);
36 DummyResource::removeFromDisk("org.kde.dummy.instance1"); 35 DummyResource::removeFromDisk("sink.dummy.instance1");
37 ResourceConfig::addResource("org.kde.dummy.instance1", "org.kde.dummy"); 36 ResourceConfig::addResource("sink.dummy.instance1", "sink.dummy");
38 } 37 }
39 38
40 void init() 39 void init()
@@ -48,7 +47,7 @@ private slots:
48 void cleanup() 47 void cleanup()
49 { 48 {
50 qDebug() << "Test took " << time.elapsed(); 49 qDebug() << "Test took " << time.elapsed();
51 Sink::Store::removeDataFromDisk(QByteArray("org.kde.dummy.instance1")).exec().waitForFinished(); 50 Sink::Store::removeDataFromDisk(QByteArray("sink.dummy.instance1")).exec().waitForFinished();
52 } 51 }
53 52
54 void testProperty() 53 void testProperty()
@@ -60,13 +59,13 @@ private slots:
60 59
61 void testWriteToFacadeAndQueryByUid() 60 void testWriteToFacadeAndQueryByUid()
62 { 61 {
63 Sink::ApplicationDomain::Event event("org.kde.dummy.instance1"); 62 Sink::ApplicationDomain::Event event("sink.dummy.instance1");
64 event.setProperty("uid", "testuid"); 63 event.setProperty("uid", "testuid");
65 QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid")); 64 QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid"));
66 event.setProperty("summary", "summaryValue"); 65 event.setProperty("summary", "summaryValue");
67 Sink::Store::create<Sink::ApplicationDomain::Event>(event).exec().waitForFinished(); 66 Sink::Store::create<Sink::ApplicationDomain::Event>(event).exec().waitForFinished();
68 67
69 const auto query = Query::ResourceFilter("org.kde.dummy.instance1") ; 68 const auto query = Query::ResourceFilter("sink.dummy.instance1") ;
70 69
71 // Ensure all local data is processed 70 // Ensure all local data is processed
72 Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); 71 Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished();
@@ -79,7 +78,7 @@ private slots:
79 78
80 void testWriteToFacadeAndQueryByUid2() 79 void testWriteToFacadeAndQueryByUid2()
81 { 80 {
82 Sink::ApplicationDomain::Event event("org.kde.dummy.instance1"); 81 Sink::ApplicationDomain::Event event("sink.dummy.instance1");
83 event.setProperty("summary", "summaryValue"); 82 event.setProperty("summary", "summaryValue");
84 83
85 event.setProperty("uid", "testuid"); 84 event.setProperty("uid", "testuid");
@@ -88,7 +87,7 @@ private slots:
88 event.setProperty("uid", "testuid2"); 87 event.setProperty("uid", "testuid2");
89 Sink::Store::create<Sink::ApplicationDomain::Event>(event).exec().waitForFinished(); 88 Sink::Store::create<Sink::ApplicationDomain::Event>(event).exec().waitForFinished();
90 89
91 const auto query = Query::ResourceFilter("org.kde.dummy.instance1") ; 90 const auto query = Query::ResourceFilter("sink.dummy.instance1") ;
92 91
93 // Ensure all local data is processed 92 // Ensure all local data is processed
94 Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); 93 Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished();
@@ -103,7 +102,7 @@ private slots:
103 102
104 void testWriteToFacadeAndQueryBySummary() 103 void testWriteToFacadeAndQueryBySummary()
105 { 104 {
106 Sink::ApplicationDomain::Event event("org.kde.dummy.instance1"); 105 Sink::ApplicationDomain::Event event("sink.dummy.instance1");
107 106
108 event.setProperty("uid", "testuid"); 107 event.setProperty("uid", "testuid");
109 event.setProperty("summary", "summaryValue1"); 108 event.setProperty("summary", "summaryValue1");
@@ -113,7 +112,7 @@ private slots:
113 event.setProperty("summary", "summaryValue2"); 112 event.setProperty("summary", "summaryValue2");
114 Sink::Store::create<Sink::ApplicationDomain::Event>(event).exec().waitForFinished(); 113 Sink::Store::create<Sink::ApplicationDomain::Event>(event).exec().waitForFinished();
115 114
116 const auto query = Query::ResourceFilter("org.kde.dummy.instance1") ; 115 const auto query = Query::ResourceFilter("sink.dummy.instance1") ;
117 116
118 // Ensure all local data is processed 117 // Ensure all local data is processed
119 Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); 118 Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished();
@@ -128,8 +127,8 @@ private slots:
128 127
129 void testResourceSync() 128 void testResourceSync()
130 { 129 {
131 auto pipeline = QSharedPointer<Sink::Pipeline>::create("org.kde.dummy.instance1"); 130 auto pipeline = QSharedPointer<Sink::Pipeline>::create("sink.dummy.instance1");
132 DummyResource resource("org.kde.dummy.instance1", pipeline); 131 DummyResource resource("sink.dummy.instance1", pipeline);
133 auto job = resource.synchronizeWithSource(); 132 auto job = resource.synchronizeWithSource();
134 // TODO pass in optional timeout? 133 // TODO pass in optional timeout?
135 auto future = job.exec(); 134 auto future = job.exec();
@@ -143,7 +142,7 @@ private slots:
143 142
144 void testSyncAndFacade() 143 void testSyncAndFacade()
145 { 144 {
146 const auto query = Query::ResourceFilter("org.kde.dummy.instance1"); 145 const auto query = Query::ResourceFilter("sink.dummy.instance1");
147 146
148 // Ensure all local data is processed 147 // Ensure all local data is processed
149 Sink::Store::synchronize(query).exec().waitForFinished(); 148 Sink::Store::synchronize(query).exec().waitForFinished();
@@ -159,7 +158,7 @@ private slots:
159 158
160 void testSyncAndFacadeMail() 159 void testSyncAndFacadeMail()
161 { 160 {
162 const auto query = Query::ResourceFilter("org.kde.dummy.instance1"); 161 const auto query = Query::ResourceFilter("sink.dummy.instance1");
163 162
164 // Ensure all local data is processed 163 // Ensure all local data is processed
165 Sink::Store::synchronize(query).exec().waitForFinished(); 164 Sink::Store::synchronize(query).exec().waitForFinished();
@@ -175,13 +174,13 @@ private slots:
175 174
176 void testWriteModifyDelete() 175 void testWriteModifyDelete()
177 { 176 {
178 Sink::ApplicationDomain::Event event("org.kde.dummy.instance1"); 177 Sink::ApplicationDomain::Event event("sink.dummy.instance1");
179 event.setProperty("uid", "testuid"); 178 event.setProperty("uid", "testuid");
180 QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid")); 179 QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid"));
181 event.setProperty("summary", "summaryValue"); 180 event.setProperty("summary", "summaryValue");
182 Sink::Store::create<Sink::ApplicationDomain::Event>(event).exec().waitForFinished(); 181 Sink::Store::create<Sink::ApplicationDomain::Event>(event).exec().waitForFinished();
183 182
184 const auto query = Query::ResourceFilter("org.kde.dummy.instance1") + Query::PropertyFilter("uid", "testuid"); 183 const auto query = Query::ResourceFilter("sink.dummy.instance1") + Query::PropertyFilter("uid", "testuid");
185 184
186 // Ensure all local data is processed 185 // Ensure all local data is processed
187 Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); 186 Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished();
@@ -230,14 +229,14 @@ private slots:
230 229
231 void testWriteModifyDeleteLive() 230 void testWriteModifyDeleteLive()
232 { 231 {
233 auto query = Query::ResourceFilter("org.kde.dummy.instance1"); 232 auto query = Query::ResourceFilter("sink.dummy.instance1");
234 query.liveQuery = true; 233 query.liveQuery = true;
235 query += Query::PropertyFilter("uid", "testuid"); 234 query += Query::PropertyFilter("uid", "testuid");
236 235
237 auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Event>(query); 236 auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Event>(query);
238 QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); 237 QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool());
239 238
240 Sink::ApplicationDomain::Event event("org.kde.dummy.instance1"); 239 Sink::ApplicationDomain::Event event("sink.dummy.instance1");
241 event.setProperty("uid", "testuid"); 240 event.setProperty("uid", "testuid");
242 QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid")); 241 QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid"));
243 event.setProperty("summary", "summaryValue"); 242 event.setProperty("summary", "summaryValue");
diff --git a/tests/dummyresourcewritebenchmark.cpp b/tests/dummyresourcewritebenchmark.cpp
index b4ab438..5cd7007 100644
--- a/tests/dummyresourcewritebenchmark.cpp
+++ b/tests/dummyresourcewritebenchmark.cpp
@@ -103,14 +103,14 @@ class DummyResourceWriteBenchmark : public QObject
103 103
104 void writeInProcess(int num) 104 void writeInProcess(int num)
105 { 105 {
106 DummyResource::removeFromDisk("org.kde.dummy.instance1"); 106 DummyResource::removeFromDisk("sink.dummy.instance1");
107 107
108 108
109 QTime time; 109 QTime time;
110 time.start(); 110 time.start();
111 111
112 auto pipeline = QSharedPointer<Sink::Pipeline>::create("org.kde.dummy.instance1"); 112 auto pipeline = QSharedPointer<Sink::Pipeline>::create("sink.dummy.instance1");
113 DummyResource resource("org.kde.dummy.instance1", pipeline); 113 DummyResource resource("sink.dummy.instance1", pipeline);
114 114
115 int bufferSize = 0; 115 int bufferSize = 0;
116 auto command = createEntityBuffer(bufferSize); 116 auto command = createEntityBuffer(bufferSize);
@@ -131,7 +131,7 @@ class DummyResourceWriteBenchmark : public QObject
131 const auto finalRss = getCurrentRSS(); 131 const auto finalRss = getCurrentRSS();
132 const auto rssGrowth = finalRss - startingRss; 132 const auto rssGrowth = finalRss - startingRss;
133 // Since the database is memory mapped it is attributted to the resident set size. 133 // Since the database is memory mapped it is attributted to the resident set size.
134 const auto rssWithoutDb = finalRss - DummyResource::diskUsage("org.kde.dummy.instance1"); 134 const auto rssWithoutDb = finalRss - DummyResource::diskUsage("sink.dummy.instance1");
135 const auto peakRss = getPeakRSS(); 135 const auto peakRss = getPeakRSS();
136 // How much peak deviates from final rss in percent 136 // How much peak deviates from final rss in percent
137 const auto percentageRssError = static_cast<double>(peakRss - finalRss) * 100.0 / static_cast<double>(finalRss); 137 const auto percentageRssError = static_cast<double>(peakRss - finalRss) * 100.0 / static_cast<double>(finalRss);
@@ -143,7 +143,7 @@ class DummyResourceWriteBenchmark : public QObject
143 std::cout << "Rss without db [kb]: " << rssWithoutDb / 1024 << std::endl; 143 std::cout << "Rss without db [kb]: " << rssWithoutDb / 1024 << std::endl;
144 std::cout << "Percentage peak rss error: " << percentageRssError << std::endl; 144 std::cout << "Percentage peak rss error: " << percentageRssError << std::endl;
145 145
146 auto onDisk = DummyResource::diskUsage("org.kde.dummy.instance1"); 146 auto onDisk = DummyResource::diskUsage("sink.dummy.instance1");
147 auto writeAmplification = static_cast<double>(onDisk) / static_cast<double>(bufferSizeTotal); 147 auto writeAmplification = static_cast<double>(onDisk) / static_cast<double>(bufferSizeTotal);
148 std::cout << "On disk [kb]: " << onDisk / 1024 << std::endl; 148 std::cout << "On disk [kb]: " << onDisk / 1024 << std::endl;
149 std::cout << "Buffer size total [kb]: " << bufferSizeTotal / 1024 << std::endl; 149 std::cout << "Buffer size total [kb]: " << bufferSizeTotal / 1024 << std::endl;
@@ -216,13 +216,13 @@ private slots:
216 216
217 void getFreePages() 217 void getFreePages()
218 { 218 {
219 std::system(QString("mdb_stat %1/%2 -ff").arg(Sink::storageLocation()).arg("org.kde.dummy.instance1").toLatin1().constData()); 219 std::system(QString("mdb_stat %1/%2 -ff").arg(Sink::storageLocation()).arg("sink.dummy.instance1").toLatin1().constData());
220 } 220 }
221 221
222 // This allows to run individual parts without doing a cleanup, but still cleaning up normally 222 // This allows to run individual parts without doing a cleanup, but still cleaning up normally
223 void testCleanupForCompleteTest() 223 void testCleanupForCompleteTest()
224 { 224 {
225 DummyResource::removeFromDisk("org.kde.dummy.instance1"); 225 DummyResource::removeFromDisk("sink.dummy.instance1");
226 } 226 }
227 227
228private: 228private:
diff --git a/tests/genericfacadetest.cpp b/tests/genericfacadetest.cpp
index 8336875..0267dac 100644
--- a/tests/genericfacadetest.cpp
+++ b/tests/genericfacadetest.cpp
@@ -8,6 +8,7 @@
8#include <common/domainadaptor.h> 8#include <common/domainadaptor.h>
9#include <common/resultprovider.h> 9#include <common/resultprovider.h>
10#include <common/synclistresult.h> 10#include <common/synclistresult.h>
11#include <common/test.h>
11 12
12// Replace with something different 13// Replace with something different
13#include "event_generated.h" 14#include "event_generated.h"
@@ -23,10 +24,9 @@ class GenericFacadeTest : public QObject
23{ 24{
24 Q_OBJECT 25 Q_OBJECT
25private slots: 26private slots:
26 27 void initTestCase()
27 void init()
28 { 28 {
29 Sink::Log::setDebugOutputLevel(Sink::Log::Trace); 29 Sink::Test::initTest();
30 } 30 }
31 31
32 void testLoad() 32 void testLoad()
diff --git a/tests/genericresourcebenchmark.cpp b/tests/genericresourcebenchmark.cpp
index a0a368c..2315d0b 100644
--- a/tests/genericresourcebenchmark.cpp
+++ b/tests/genericresourcebenchmark.cpp
@@ -96,9 +96,9 @@ private slots:
96 96
97 void initTestCase() 97 void initTestCase()
98 { 98 {
99 removeFromDisk("org.kde.test.instance1"); 99 removeFromDisk("sink.test.instance1");
100 removeFromDisk("org.kde.test.instance1.userqueue"); 100 removeFromDisk("sink.test.instance1.userqueue");
101 removeFromDisk("org.kde.test.instance1.synchronizerqueue"); 101 removeFromDisk("sink.test.instance1.synchronizerqueue");
102 } 102 }
103 103
104 104
@@ -106,8 +106,8 @@ private slots:
106 { 106 {
107 int num = 10000; 107 int num = 10000;
108 108
109 auto pipeline = QSharedPointer<Sink::Pipeline>::create("org.kde.test.instance1"); 109 auto pipeline = QSharedPointer<Sink::Pipeline>::create("sink.test.instance1");
110 TestResource resource("org.kde.test.instance1", pipeline); 110 TestResource resource("sink.test.instance1", pipeline);
111 111
112 auto command = createEntityBuffer(); 112 auto command = createEntityBuffer();
113 113
@@ -141,16 +141,16 @@ private slots:
141 { 141 {
142 int num = 50000; 142 int num = 50000;
143 143
144 auto pipeline = QSharedPointer<Sink::Pipeline>::create("org.kde.test.instance1"); 144 auto pipeline = QSharedPointer<Sink::Pipeline>::create("sink.test.instance1");
145 145
146 auto eventFactory = QSharedPointer<TestEventAdaptorFactory>::create(); 146 auto eventFactory = QSharedPointer<TestEventAdaptorFactory>::create();
147 const QByteArray resourceIdentifier = "org.kde.test.instance1"; 147 const QByteArray resourceIdentifier = "sink.test.instance1";
148 auto indexer = QSharedPointer<IndexUpdater>::create(); 148 auto indexer = QSharedPointer<IndexUpdater>::create();
149 149
150 pipeline->setPreprocessors("event", QVector<Sink::Preprocessor *>() << indexer.data()); 150 pipeline->setPreprocessors("event", QVector<Sink::Preprocessor *>() << indexer.data());
151 pipeline->setAdaptorFactory("event", eventFactory); 151 pipeline->setAdaptorFactory("event", eventFactory);
152 152
153 TestResource resource("org.kde.test.instance1", pipeline); 153 TestResource resource("sink.test.instance1", pipeline);
154 154
155 auto command = createEntityBuffer(); 155 auto command = createEntityBuffer();
156 156
diff --git a/tests/genericresourcetest.cpp b/tests/genericresourcetest.cpp
index 7474cbf..77a901d 100644
--- a/tests/genericresourcetest.cpp
+++ b/tests/genericresourcetest.cpp
@@ -26,8 +26,7 @@ private slots:
26 26
27 void init() 27 void init()
28 { 28 {
29 Sink::GenericResource::removeFromDisk("org.kde.test.instance1"); 29 Sink::GenericResource::removeFromDisk("sink.test.instance1");
30 Sink::Log::setDebugOutputLevel(Sink::Log::Trace);
31 } 30 }
32 31
33 /// Ensure the resource can process messages 32 /// Ensure the resource can process messages
@@ -71,10 +70,10 @@ private slots:
71 } 70 }
72 71
73 // Actual test 72 // Actual test
74 auto pipeline = QSharedPointer<Sink::Pipeline>::create("org.kde.test.instance1"); 73 auto pipeline = QSharedPointer<Sink::Pipeline>::create("sink.test.instance1");
75 QSignalSpy revisionSpy(pipeline.data(), SIGNAL(revisionUpdated(qint64))); 74 QSignalSpy revisionSpy(pipeline.data(), SIGNAL(revisionUpdated(qint64)));
76 QVERIFY(revisionSpy.isValid()); 75 QVERIFY(revisionSpy.isValid());
77 TestResource resource("org.kde.test.instance1", pipeline); 76 TestResource resource("sink.test.instance1", pipeline);
78 resource.processCommand(Sink::Commands::CreateEntityCommand, command); 77 resource.processCommand(Sink::Commands::CreateEntityCommand, command);
79 resource.processCommand(Sink::Commands::CreateEntityCommand, command); 78 resource.processCommand(Sink::Commands::CreateEntityCommand, command);
80 resource.processAllMessages().exec().waitForFinished(); 79 resource.processAllMessages().exec().waitForFinished();
diff --git a/tests/indextest.cpp b/tests/indextest.cpp
index fa3ace4..8566803 100644
--- a/tests/indextest.cpp
+++ b/tests/indextest.cpp
@@ -16,19 +16,19 @@ class IndexTest : public QObject
16private slots: 16private slots:
17 void initTestCase() 17 void initTestCase()
18 { 18 {
19 Sink::Storage store("./testindex", "org.kde.dummy.testindex", Sink::Storage::ReadWrite); 19 Sink::Storage store("./testindex", "sink.dummy.testindex", Sink::Storage::ReadWrite);
20 store.removeFromDisk(); 20 store.removeFromDisk();
21 } 21 }
22 22
23 void cleanup() 23 void cleanup()
24 { 24 {
25 Sink::Storage store("./testindex", "org.kde.dummy.testindex", Sink::Storage::ReadWrite); 25 Sink::Storage store("./testindex", "sink.dummy.testindex", Sink::Storage::ReadWrite);
26 store.removeFromDisk(); 26 store.removeFromDisk();
27 } 27 }
28 28
29 void testIndex() 29 void testIndex()
30 { 30 {
31 Index index("./testindex", "org.kde.dummy.testindex", Sink::Storage::ReadWrite); 31 Index index("./testindex", "sink.dummy.testindex", Sink::Storage::ReadWrite);
32 // The first key is specifically a substring of the second key 32 // The first key is specifically a substring of the second key
33 index.add("key", "value1"); 33 index.add("key", "value1");
34 index.add("keyFoo", "value2"); 34 index.add("keyFoo", "value2");
diff --git a/tests/inspectiontest.cpp b/tests/inspectiontest.cpp
index 38bf23d..3e8a103 100644
--- a/tests/inspectiontest.cpp
+++ b/tests/inspectiontest.cpp
@@ -19,11 +19,10 @@ class InspectionTest : public QObject
19private slots: 19private slots:
20 void initTestCase() 20 void initTestCase()
21 { 21 {
22 Sink::Log::setDebugOutputLevel(Sink::Log::Trace); 22 auto factory = Sink::ResourceFactory::load("sink.dummy");
23 auto factory = Sink::ResourceFactory::load("org.kde.dummy");
24 QVERIFY(factory); 23 QVERIFY(factory);
25 ResourceConfig::addResource("org.kde.dummy.instance1", "org.kde.dummy"); 24 ResourceConfig::addResource("sink.dummy.instance1", "sink.dummy");
26 Sink::Store::removeDataFromDisk(QByteArray("org.kde.dummy.instance1")).exec().waitForFinished(); 25 Sink::Store::removeDataFromDisk(QByteArray("sink.dummy.instance1")).exec().waitForFinished();
27 } 26 }
28 27
29 void testInspection_data() 28 void testInspection_data()
@@ -39,7 +38,7 @@ private slots:
39 using namespace Sink; 38 using namespace Sink;
40 using namespace Sink::ApplicationDomain; 39 using namespace Sink::ApplicationDomain;
41 40
42 Mail mail(QByteArray("org.kde.dummy.instance1"), QByteArray("identifier"), 0, QSharedPointer<MemoryBufferAdaptor::MemoryBufferAdaptor>::create()); 41 Mail mail(QByteArray("sink.dummy.instance1"), QByteArray("identifier"), 0, QSharedPointer<MemoryBufferAdaptor::MemoryBufferAdaptor>::create());
43 42
44 // testInspection is a magic property that the dummyresource supports 43 // testInspection is a magic property that the dummyresource supports
45 auto inspectionCommand = ResourceControl::Inspection::PropertyInspection(mail, "testInspection", success); 44 auto inspectionCommand = ResourceControl::Inspection::PropertyInspection(mail, "testInspection", success);
diff --git a/tests/maildirsyncbenchmark.cpp b/tests/maildirsyncbenchmark.cpp
index 06c5ab1..d84c758 100644
--- a/tests/maildirsyncbenchmark.cpp
+++ b/tests/maildirsyncbenchmark.cpp
@@ -61,18 +61,17 @@ private slots:
61 { 61 {
62 targetPath = tempDir.path() + "/maildir1"; 62 targetPath = tempDir.path() + "/maildir1";
63 63
64 Sink::Log::setDebugOutputLevel(Sink::Log::Log); 64 MaildirResource::removeFromDisk("sink.maildir.test1");
65 MaildirResource::removeFromDisk("org.kde.maildir.test1");
66 Sink::ApplicationDomain::SinkResource resource; 65 Sink::ApplicationDomain::SinkResource resource;
67 resource.setProperty("identifier", "org.kde.maildir.test1"); 66 resource.setProperty("identifier", "sink.maildir.test1");
68 resource.setProperty("type", "org.kde.maildir"); 67 resource.setProperty("type", "sink.maildir");
69 resource.setProperty("path", targetPath); 68 resource.setProperty("path", targetPath);
70 Sink::Store::create(resource).exec().waitForFinished(); 69 Sink::Store::create(resource).exec().waitForFinished();
71 } 70 }
72 71
73 void cleanup() 72 void cleanup()
74 { 73 {
75 MaildirResource::removeFromDisk("org.kde.maildir.test1"); 74 MaildirResource::removeFromDisk("sink.maildir.test1");
76 QDir dir(targetPath); 75 QDir dir(targetPath);
77 dir.removeRecursively(); 76 dir.removeRecursively();
78 } 77 }
@@ -84,8 +83,8 @@ private slots:
84 83
85 void testbench() 84 void testbench()
86 { 85 {
87 auto pipeline = QSharedPointer<Sink::Pipeline>::create("org.kde.maildir.test1"); 86 auto pipeline = QSharedPointer<Sink::Pipeline>::create("sink.maildir.test1");
88 MaildirResource resource("org.kde.maildir.test1", pipeline); 87 MaildirResource resource("sink.maildir.test1", pipeline);
89 QTime time; 88 QTime time;
90 time.start(); 89 time.start();
91 resource.Sink::GenericResource::synchronizeWithSource().exec().waitForFinished(); 90 resource.Sink::GenericResource::synchronizeWithSource().exec().waitForFinished();
diff --git a/tests/mailquerybenchmark.cpp b/tests/mailquerybenchmark.cpp
index 4e58899..450955f 100644
--- a/tests/mailquerybenchmark.cpp
+++ b/tests/mailquerybenchmark.cpp
@@ -148,7 +148,7 @@ private slots:
148 148
149 void init() 149 void init()
150 { 150 {
151 resourceIdentifier = "org.kde.test.instance1"; 151 resourceIdentifier = "sink.test.instance1";
152 Sink::AdaptorFactoryRegistry::instance().registerFactory<Sink::ApplicationDomain::Mail, TestMailAdaptorFactory>("test"); 152 Sink::AdaptorFactoryRegistry::instance().registerFactory<Sink::ApplicationDomain::Mail, TestMailAdaptorFactory>("test");
153 } 153 }
154 154
diff --git a/tests/mailsynctest.cpp b/tests/mailsynctest.cpp
index e70e34e..4b797c8 100644
--- a/tests/mailsynctest.cpp
+++ b/tests/mailsynctest.cpp
@@ -31,10 +31,12 @@
31using namespace Sink; 31using namespace Sink;
32using namespace Sink::ApplicationDomain; 32using namespace Sink::ApplicationDomain;
33 33
34SINK_DEBUG_AREA("mailsynctest")
35
34void MailSyncTest::initTestCase() 36void MailSyncTest::initTestCase()
35{ 37{
36 Test::initTest(); 38 Test::initTest();
37 Log::setDebugOutputLevel(Sink::Log::Trace); 39 QVERIFY(isBackendAvailable());
38 resetTestEnvironment(); 40 resetTestEnvironment();
39 auto resource = createResource(); 41 auto resource = createResource();
40 QVERIFY(!resource.identifier().isEmpty()); 42 QVERIFY(!resource.identifier().isEmpty());
@@ -72,7 +74,7 @@ void MailSyncTest::testListFolders()
72 for (const auto &folder : folders) { 74 for (const auto &folder : folders) {
73 names << folder->getName(); 75 names << folder->getName();
74 } 76 }
75 Trace() << "base folder: " << names; 77 SinkTrace() << "base folder: " << names;
76 baseCount = folders.size(); 78 baseCount = folders.size();
77 }); 79 });
78 VERIFYEXEC(job); 80 VERIFYEXEC(job);
@@ -196,6 +198,10 @@ void MailSyncTest::testListFolderHierarchy()
196 QVERIFY(names.contains("Drafts")); 198 QVERIFY(names.contains("Drafts"));
197 names.removeAll("Drafts"); 199 names.removeAll("Drafts");
198 } 200 }
201 if (mCapabilities.contains(ResourceCapabilities::Mail::trash)) {
202 QVERIFY(names.contains("Trash"));
203 names.removeAll("Trash");
204 }
199 QCOMPARE(names.size(), 3); 205 QCOMPARE(names.size(), 3);
200 QCOMPARE(map.value("sub")->getParent(), map.value("test")->identifier()); 206 QCOMPARE(map.value("sub")->getParent(), map.value("test")->identifier());
201 }); 207 });
diff --git a/tests/mailsynctest.h b/tests/mailsynctest.h
index a21335b..31d3f03 100644
--- a/tests/mailsynctest.h
+++ b/tests/mailsynctest.h
@@ -41,6 +41,7 @@ protected:
41 QByteArray mResourceInstanceIdentifier; 41 QByteArray mResourceInstanceIdentifier;
42 QByteArrayList mCapabilities; 42 QByteArrayList mCapabilities;
43 43
44 virtual bool isBackendAvailable() { return true; }
44 virtual void resetTestEnvironment() = 0; 45 virtual void resetTestEnvironment() = 0;
45 virtual Sink::ApplicationDomain::SinkResource createResource() = 0; 46 virtual Sink::ApplicationDomain::SinkResource createResource() = 0;
46 virtual Sink::ApplicationDomain::SinkResource createFaultyResource() = 0; 47 virtual Sink::ApplicationDomain::SinkResource createFaultyResource() = 0;
diff --git a/tests/mailtest.cpp b/tests/mailtest.cpp
index b9d496d..2547536 100644
--- a/tests/mailtest.cpp
+++ b/tests/mailtest.cpp
@@ -31,10 +31,12 @@
31using namespace Sink; 31using namespace Sink;
32using namespace Sink::ApplicationDomain; 32using namespace Sink::ApplicationDomain;
33 33
34SINK_DEBUG_AREA("mailtest")
35
34void MailTest::initTestCase() 36void MailTest::initTestCase()
35{ 37{
36 Test::initTest(); 38 Test::initTest();
37 Log::setDebugOutputLevel(Sink::Log::Trace); 39 QVERIFY(isBackendAvailable());
38 resetTestEnvironment(); 40 resetTestEnvironment();
39 auto resource = createResource(); 41 auto resource = createResource();
40 QVERIFY(!resource.identifier().isEmpty()); 42 QVERIFY(!resource.identifier().isEmpty());
@@ -250,7 +252,7 @@ void MailTest::testMoveMail()
250 auto mail = *mails.first(); 252 auto mail = *mails.first();
251 modifiedMail = mail; 253 modifiedMail = mail;
252 QCOMPARE(mail.getFolder(), folder.identifier()); 254 QCOMPARE(mail.getFolder(), folder.identifier());
253 Warning() << "path: " << mail.getMimeMessagePath(); 255 SinkWarning() << "path: " << mail.getMimeMessagePath();
254 QVERIFY(QFile(mail.getMimeMessagePath()).exists()); 256 QVERIFY(QFile(mail.getMimeMessagePath()).exists());
255 }); 257 });
256 VERIFYEXEC(job); 258 VERIFYEXEC(job);
@@ -269,7 +271,7 @@ void MailTest::testMoveMail()
269 auto mail = *mails.first(); 271 auto mail = *mails.first();
270 QCOMPARE(mail.getFolder(), folder1.identifier()); 272 QCOMPARE(mail.getFolder(), folder1.identifier());
271 QVERIFY(QFile(mail.getMimeMessagePath()).exists()); 273 QVERIFY(QFile(mail.getMimeMessagePath()).exists());
272 Trace() << "Mime message path: " << mail.getMimeMessagePath(); 274 SinkTrace() << "Mime message path: " << mail.getMimeMessagePath();
273 }); 275 });
274 VERIFYEXEC(job); 276 VERIFYEXEC(job);
275 } 277 }
diff --git a/tests/mailtest.h b/tests/mailtest.h
index 2144bf1..cba623d 100644
--- a/tests/mailtest.h
+++ b/tests/mailtest.h
@@ -34,6 +34,7 @@ protected:
34 QByteArray mResourceInstanceIdentifier; 34 QByteArray mResourceInstanceIdentifier;
35 QByteArrayList mCapabilities; 35 QByteArrayList mCapabilities;
36 36
37 virtual bool isBackendAvailable() { return true; }
37 virtual void resetTestEnvironment() = 0; 38 virtual void resetTestEnvironment() = 0;
38 virtual Sink::ApplicationDomain::SinkResource createResource() = 0; 39 virtual Sink::ApplicationDomain::SinkResource createResource() = 0;
39 40
diff --git a/tests/messagequeuetest.cpp b/tests/messagequeuetest.cpp
index 484ff86..e79bba2 100644
--- a/tests/messagequeuetest.cpp
+++ b/tests/messagequeuetest.cpp
@@ -7,6 +7,9 @@
7#include "storage.h" 7#include "storage.h"
8#include "messagequeue.h" 8#include "messagequeue.h"
9#include "log.h" 9#include "log.h"
10#include "test.h"
11
12SINK_DEBUG_AREA("messagequeuetest")
10 13
11/** 14/**
12 * Test of the messagequeue implementation. 15 * Test of the messagequeue implementation.
@@ -17,8 +20,8 @@ class MessageQueueTest : public QObject
17private slots: 20private slots:
18 void initTestCase() 21 void initTestCase()
19 { 22 {
20 Sink::Log::setDebugOutputLevel(Sink::Log::Trace); 23 Sink::Test::initTest();
21 Sink::Storage store(Sink::Store::storageLocation(), "org.kde.dummy.testqueue", Sink::Storage::ReadWrite); 24 Sink::Storage store(Sink::Store::storageLocation(), "sink.dummy.testqueue", Sink::Storage::ReadWrite);
22 store.removeFromDisk(); 25 store.removeFromDisk();
23 } 26 }
24 27
@@ -28,13 +31,13 @@ private slots:
28 31
29 void cleanup() 32 void cleanup()
30 { 33 {
31 Sink::Storage store(Sink::Store::storageLocation(), "org.kde.dummy.testqueue", Sink::Storage::ReadWrite); 34 Sink::Storage store(Sink::Store::storageLocation(), "sink.dummy.testqueue", Sink::Storage::ReadWrite);
32 store.removeFromDisk(); 35 store.removeFromDisk();
33 } 36 }
34 37
35 void testEmpty() 38 void testEmpty()
36 { 39 {
37 MessageQueue queue(Sink::Store::storageLocation(), "org.kde.dummy.testqueue"); 40 MessageQueue queue(Sink::Store::storageLocation(), "sink.dummy.testqueue");
38 QVERIFY(queue.isEmpty()); 41 QVERIFY(queue.isEmpty());
39 queue.enqueue("value"); 42 queue.enqueue("value");
40 QVERIFY(!queue.isEmpty()); 43 QVERIFY(!queue.isEmpty());
@@ -42,7 +45,7 @@ private slots:
42 45
43 void testDequeueEmpty() 46 void testDequeueEmpty()
44 { 47 {
45 MessageQueue queue(Sink::Store::storageLocation(), "org.kde.dummy.testqueue"); 48 MessageQueue queue(Sink::Store::storageLocation(), "sink.dummy.testqueue");
46 bool gotValue = false; 49 bool gotValue = false;
47 bool gotError = false; 50 bool gotError = false;
48 queue.dequeue([&](void *ptr, int size, std::function<void(bool success)> callback) { gotValue = true; }, [&](const MessageQueue::Error &error) { gotError = true; }); 51 queue.dequeue([&](void *ptr, int size, std::function<void(bool success)> callback) { gotValue = true; }, [&](const MessageQueue::Error &error) { gotError = true; });
@@ -52,7 +55,7 @@ private slots:
52 55
53 void testEnqueue() 56 void testEnqueue()
54 { 57 {
55 MessageQueue queue(Sink::Store::storageLocation(), "org.kde.dummy.testqueue"); 58 MessageQueue queue(Sink::Store::storageLocation(), "sink.dummy.testqueue");
56 QSignalSpy spy(&queue, SIGNAL(messageReady())); 59 QSignalSpy spy(&queue, SIGNAL(messageReady()));
57 queue.enqueue("value1"); 60 queue.enqueue("value1");
58 QCOMPARE(spy.size(), 1); 61 QCOMPARE(spy.size(), 1);
@@ -60,7 +63,7 @@ private slots:
60 63
61 void testDrained() 64 void testDrained()
62 { 65 {
63 MessageQueue queue(Sink::Store::storageLocation(), "org.kde.dummy.testqueue"); 66 MessageQueue queue(Sink::Store::storageLocation(), "sink.dummy.testqueue");
64 QSignalSpy spy(&queue, SIGNAL(drained())); 67 QSignalSpy spy(&queue, SIGNAL(drained()));
65 queue.enqueue("value1"); 68 queue.enqueue("value1");
66 69
@@ -74,13 +77,13 @@ private slots:
74 values << "value1"; 77 values << "value1";
75 values << "value2"; 78 values << "value2";
76 79
77 MessageQueue queue(Sink::Store::storageLocation(), "org.kde.dummy.testqueue"); 80 MessageQueue queue(Sink::Store::storageLocation(), "sink.dummy.testqueue");
78 for (const QByteArray &value : values) { 81 for (const QByteArray &value : values) {
79 queue.enqueue(value); 82 queue.enqueue(value);
80 } 83 }
81 84
82 while (!queue.isEmpty()) { 85 while (!queue.isEmpty()) {
83 Log() << "start"; 86 SinkLog() << "start";
84 const auto expected = values.dequeue(); 87 const auto expected = values.dequeue();
85 bool gotValue = false; 88 bool gotValue = false;
86 bool gotError = false; 89 bool gotError = false;
@@ -104,7 +107,7 @@ private slots:
104 values << "value1"; 107 values << "value1";
105 values << "value2"; 108 values << "value2";
106 109
107 MessageQueue queue(Sink::Store::storageLocation(), "org.kde.dummy.testqueue"); 110 MessageQueue queue(Sink::Store::storageLocation(), "sink.dummy.testqueue");
108 for (const QByteArray &value : values) { 111 for (const QByteArray &value : values) {
109 queue.enqueue(value); 112 queue.enqueue(value);
110 } 113 }
@@ -142,7 +145,7 @@ private slots:
142 */ 145 */
143 void testNestedEnqueue() 146 void testNestedEnqueue()
144 { 147 {
145 MessageQueue queue(Sink::Store::storageLocation(), "org.kde.dummy.testqueue"); 148 MessageQueue queue(Sink::Store::storageLocation(), "sink.dummy.testqueue");
146 queue.enqueue("value1"); 149 queue.enqueue("value1");
147 150
148 bool gotError = false; 151 bool gotError = false;
@@ -157,7 +160,7 @@ private slots:
157 160
158 void testBatchDequeue() 161 void testBatchDequeue()
159 { 162 {
160 MessageQueue queue(Sink::Store::storageLocation(), "org.kde.dummy.testqueue"); 163 MessageQueue queue(Sink::Store::storageLocation(), "sink.dummy.testqueue");
161 queue.enqueue("value1"); 164 queue.enqueue("value1");
162 queue.enqueue("value2"); 165 queue.enqueue("value2");
163 queue.enqueue("value3"); 166 queue.enqueue("value3");
@@ -178,7 +181,7 @@ private slots:
178 181
179 void testBatchEnqueue() 182 void testBatchEnqueue()
180 { 183 {
181 MessageQueue queue(Sink::Store::storageLocation(), "org.kde.dummy.testqueue"); 184 MessageQueue queue(Sink::Store::storageLocation(), "sink.dummy.testqueue");
182 QSignalSpy spy(&queue, SIGNAL(messageReady())); 185 QSignalSpy spy(&queue, SIGNAL(messageReady()));
183 queue.startTransaction(); 186 queue.startTransaction();
184 queue.enqueue("value1"); 187 queue.enqueue("value1");
diff --git a/tests/modelinteractivitytest.cpp b/tests/modelinteractivitytest.cpp
index d0a0920..1ac0e2d 100644
--- a/tests/modelinteractivitytest.cpp
+++ b/tests/modelinteractivitytest.cpp
@@ -10,6 +10,7 @@
10#include "resourceconfig.h" 10#include "resourceconfig.h"
11#include "log.h" 11#include "log.h"
12#include "modelresult.h" 12#include "modelresult.h"
13#include "test.h"
13 14
14static int blockingTime; 15static int blockingTime;
15 16
@@ -29,10 +30,11 @@ public:
29 { 30 {
30 t.start(); 31 t.start();
31 const bool ret = QCoreApplication::notify(receiver, event); 32 const bool ret = QCoreApplication::notify(receiver, event);
32 if (t.elapsed() > 1) 33 if (t.elapsed() > 1) {
33 std::cout 34 std::cout
34 << QString("processing event type %1 for object %2 took %3ms").arg((int)event->type()).arg("" /* receiver->objectName().toLocal8Bit().data()*/).arg((int)t.elapsed()).toStdString() 35 << QString("processing event type %1 for object %2 took %3ms").arg((int)event->type()).arg(receiver->metaObject()->className()).arg((int)t.elapsed()).toStdString()
35 << std::endl; 36 << std::endl;
37 }
36 blockingTime += t.elapsed(); 38 blockingTime += t.elapsed();
37 return ret; 39 return ret;
38 } 40 }
@@ -49,14 +51,14 @@ class ModelinteractivityTest : public QObject
49private slots: 51private slots:
50 void initTestCase() 52 void initTestCase()
51 { 53 {
52 Sink::Log::setDebugOutputLevel(Sink::Log::Warning); 54 Sink::Test::initTest();
53 ResourceConfig::addResource("org.kde.dummy.instance1", "org.kde.dummy"); 55 ResourceConfig::addResource("sink.dummy.instance1", "sink.dummy");
54 Sink::Store::removeDataFromDisk(QByteArray("org.kde.dummy.instance1")).exec().waitForFinished(); 56 Sink::Store::removeDataFromDisk(QByteArray("sink.dummy.instance1")).exec().waitForFinished();
55 } 57 }
56 58
57 void cleanup() 59 void cleanup()
58 { 60 {
59 Sink::Store::removeDataFromDisk(QByteArray("org.kde.dummy.instance1")).exec().waitForFinished(); 61 Sink::Store::removeDataFromDisk(QByteArray("sink.dummy.instance1")).exec().waitForFinished();
60 } 62 }
61 63
62 void init() 64 void init()
@@ -67,14 +69,14 @@ private slots:
67 { 69 {
68 // Setup 70 // Setup
69 { 71 {
70 Sink::ApplicationDomain::Mail mail("org.kde.dummy.instance1"); 72 Sink::ApplicationDomain::Mail mail("sink.dummy.instance1");
71 for (int i = 0; i < 1000; i++) { 73 for (int i = 0; i < 1000; i++) {
72 Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished(); 74 Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished();
73 } 75 }
74 } 76 }
75 77
76 Sink::Query query; 78 Sink::Query query;
77 query.resources << "org.kde.dummy.instance1"; 79 query.resources << "sink.dummy.instance1";
78 query.liveQuery = true; 80 query.liveQuery = true;
79 81
80 Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); 82 Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished();
diff --git a/tests/pipelinebenchmark.cpp b/tests/pipelinebenchmark.cpp
index 51481fd..0c0b9e6 100644
--- a/tests/pipelinebenchmark.cpp
+++ b/tests/pipelinebenchmark.cpp
@@ -131,7 +131,7 @@ private slots:
131 { 131 {
132 Sink::Log::setDebugOutputLevel(Sink::Log::Warning); 132 Sink::Log::setDebugOutputLevel(Sink::Log::Warning);
133 Sink::AdaptorFactoryRegistry::instance().registerFactory<Sink::ApplicationDomain::Mail, TestMailAdaptorFactory>("test"); 133 Sink::AdaptorFactoryRegistry::instance().registerFactory<Sink::ApplicationDomain::Mail, TestMailAdaptorFactory>("test");
134 resourceIdentifier = "org.kde.test.instance1"; 134 resourceIdentifier = "sink.test.instance1";
135 } 135 }
136 136
137 void testWithoutIndex() 137 void testWithoutIndex()
diff --git a/tests/pipelinetest.cpp b/tests/pipelinetest.cpp
index c6ee9ab..7216f62 100644
--- a/tests/pipelinetest.cpp
+++ b/tests/pipelinetest.cpp
@@ -190,13 +190,12 @@ class PipelineTest : public QObject
190private slots: 190private slots:
191 void initTestCase() 191 void initTestCase()
192 { 192 {
193 Sink::Log::setDebugOutputLevel(Sink::Log::Trace);
194 Sink::AdaptorFactoryRegistry::instance().registerFactory<Sink::ApplicationDomain::Event, TestEventAdaptorFactory>("test"); 193 Sink::AdaptorFactoryRegistry::instance().registerFactory<Sink::ApplicationDomain::Event, TestEventAdaptorFactory>("test");
195 } 194 }
196 195
197 void init() 196 void init()
198 { 197 {
199 removeFromDisk("org.kde.pipelinetest.instance1"); 198 removeFromDisk("sink.pipelinetest.instance1");
200 } 199 }
201 200
202 void testCreate() 201 void testCreate()
@@ -204,14 +203,14 @@ private slots:
204 flatbuffers::FlatBufferBuilder entityFbb; 203 flatbuffers::FlatBufferBuilder entityFbb;
205 auto command = createEntityCommand(createEvent(entityFbb)); 204 auto command = createEntityCommand(createEvent(entityFbb));
206 205
207 Sink::Pipeline pipeline("org.kde.pipelinetest.instance1"); 206 Sink::Pipeline pipeline("sink.pipelinetest.instance1");
208 pipeline.setResourceType("test"); 207 pipeline.setResourceType("test");
209 208
210 pipeline.startTransaction(); 209 pipeline.startTransaction();
211 pipeline.newEntity(command.constData(), command.size()); 210 pipeline.newEntity(command.constData(), command.size());
212 pipeline.commit(); 211 pipeline.commit();
213 212
214 auto result = getKeys("org.kde.pipelinetest.instance1", "event.main"); 213 auto result = getKeys("sink.pipelinetest.instance1", "event.main");
215 qDebug() << result; 214 qDebug() << result;
216 QCOMPARE(result.size(), 1); 215 QCOMPARE(result.size(), 1);
217 } 216 }
@@ -221,7 +220,7 @@ private slots:
221 flatbuffers::FlatBufferBuilder entityFbb; 220 flatbuffers::FlatBufferBuilder entityFbb;
222 auto command = createEntityCommand(createEvent(entityFbb, "summary", "description")); 221 auto command = createEntityCommand(createEvent(entityFbb, "summary", "description"));
223 222
224 Sink::Pipeline pipeline("org.kde.pipelinetest.instance1"); 223 Sink::Pipeline pipeline("sink.pipelinetest.instance1");
225 pipeline.setResourceType("test"); 224 pipeline.setResourceType("test");
226 225
227 auto adaptorFactory = QSharedPointer<TestEventAdaptorFactory>::create(); 226 auto adaptorFactory = QSharedPointer<TestEventAdaptorFactory>::create();
@@ -232,7 +231,7 @@ private slots:
232 pipeline.commit(); 231 pipeline.commit();
233 232
234 // Get uid of written entity 233 // Get uid of written entity
235 auto keys = getKeys("org.kde.pipelinetest.instance1", "event.main"); 234 auto keys = getKeys("sink.pipelinetest.instance1", "event.main");
236 QCOMPARE(keys.size(), 1); 235 QCOMPARE(keys.size(), 1);
237 const auto key = keys.first(); 236 const auto key = keys.first();
238 const auto uid = Sink::Storage::uidFromKey(key); 237 const auto uid = Sink::Storage::uidFromKey(key);
@@ -245,7 +244,7 @@ private slots:
245 pipeline.commit(); 244 pipeline.commit();
246 245
247 // Ensure we've got the new revision with the modification 246 // Ensure we've got the new revision with the modification
248 auto buffer = getEntity("org.kde.pipelinetest.instance1", "event.main", Sink::Storage::assembleKey(uid, 2)); 247 auto buffer = getEntity("sink.pipelinetest.instance1", "event.main", Sink::Storage::assembleKey(uid, 2));
249 QVERIFY(!buffer.isEmpty()); 248 QVERIFY(!buffer.isEmpty());
250 Sink::EntityBuffer entityBuffer(buffer.data(), buffer.size()); 249 Sink::EntityBuffer entityBuffer(buffer.data(), buffer.size());
251 auto adaptor = adaptorFactory->createAdaptor(entityBuffer.entity()); 250 auto adaptor = adaptorFactory->createAdaptor(entityBuffer.entity());
@@ -254,7 +253,7 @@ private slots:
254 QVERIFY2(adaptor->getProperty("description").toString() == QString("description"), "The modification has sideeffects."); 253 QVERIFY2(adaptor->getProperty("description").toString() == QString("description"), "The modification has sideeffects.");
255 254
256 // Both revisions are in the store at this point 255 // Both revisions are in the store at this point
257 QCOMPARE(getKeys("org.kde.pipelinetest.instance1", "event.main").size(), 2); 256 QCOMPARE(getKeys("sink.pipelinetest.instance1", "event.main").size(), 2);
258 257
259 // Cleanup old revisions 258 // Cleanup old revisions
260 pipeline.startTransaction(); 259 pipeline.startTransaction();
@@ -262,7 +261,7 @@ private slots:
262 pipeline.commit(); 261 pipeline.commit();
263 262
264 // And now only the latest revision is left 263 // And now only the latest revision is left
265 QCOMPARE(getKeys("org.kde.pipelinetest.instance1", "event.main").size(), 1); 264 QCOMPARE(getKeys("sink.pipelinetest.instance1", "event.main").size(), 1);
266 } 265 }
267 266
268 void testModifyWithUnrelatedOperationInbetween() 267 void testModifyWithUnrelatedOperationInbetween()
@@ -270,7 +269,7 @@ private slots:
270 flatbuffers::FlatBufferBuilder entityFbb; 269 flatbuffers::FlatBufferBuilder entityFbb;
271 auto command = createEntityCommand(createEvent(entityFbb)); 270 auto command = createEntityCommand(createEvent(entityFbb));
272 271
273 Sink::Pipeline pipeline("org.kde.pipelinetest.instance1"); 272 Sink::Pipeline pipeline("sink.pipelinetest.instance1");
274 pipeline.setResourceType("test"); 273 pipeline.setResourceType("test");
275 274
276 auto adaptorFactory = QSharedPointer<TestEventAdaptorFactory>::create(); 275 auto adaptorFactory = QSharedPointer<TestEventAdaptorFactory>::create();
@@ -281,7 +280,7 @@ private slots:
281 pipeline.commit(); 280 pipeline.commit();
282 281
283 // Get uid of written entity 282 // Get uid of written entity
284 auto keys = getKeys("org.kde.pipelinetest.instance1", "event.main"); 283 auto keys = getKeys("sink.pipelinetest.instance1", "event.main");
285 QCOMPARE(keys.size(), 1); 284 QCOMPARE(keys.size(), 1);
286 const auto uid = Sink::Storage::uidFromKey(keys.first()); 285 const auto uid = Sink::Storage::uidFromKey(keys.first());
287 286
@@ -303,7 +302,7 @@ private slots:
303 pipeline.commit(); 302 pipeline.commit();
304 303
305 // Ensure we've got the new revision with the modification 304 // Ensure we've got the new revision with the modification
306 auto buffer = getEntity("org.kde.pipelinetest.instance1", "event.main", Sink::Storage::assembleKey(uid, 3)); 305 auto buffer = getEntity("sink.pipelinetest.instance1", "event.main", Sink::Storage::assembleKey(uid, 3));
307 QVERIFY(!buffer.isEmpty()); 306 QVERIFY(!buffer.isEmpty());
308 Sink::EntityBuffer entityBuffer(buffer.data(), buffer.size()); 307 Sink::EntityBuffer entityBuffer(buffer.data(), buffer.size());
309 auto adaptor = adaptorFactory->createAdaptor(entityBuffer.entity()); 308 auto adaptor = adaptorFactory->createAdaptor(entityBuffer.entity());
@@ -314,7 +313,7 @@ private slots:
314 { 313 {
315 flatbuffers::FlatBufferBuilder entityFbb; 314 flatbuffers::FlatBufferBuilder entityFbb;
316 auto command = createEntityCommand(createEvent(entityFbb)); 315 auto command = createEntityCommand(createEvent(entityFbb));
317 Sink::Pipeline pipeline("org.kde.pipelinetest.instance1"); 316 Sink::Pipeline pipeline("sink.pipelinetest.instance1");
318 pipeline.setResourceType("test"); 317 pipeline.setResourceType("test");
319 318
320 // Create the initial revision 319 // Create the initial revision
@@ -322,7 +321,7 @@ private slots:
322 pipeline.newEntity(command.constData(), command.size()); 321 pipeline.newEntity(command.constData(), command.size());
323 pipeline.commit(); 322 pipeline.commit();
324 323
325 auto result = getKeys("org.kde.pipelinetest.instance1", "event.main"); 324 auto result = getKeys("sink.pipelinetest.instance1", "event.main");
326 QCOMPARE(result.size(), 1); 325 QCOMPARE(result.size(), 1);
327 326
328 const auto uid = Sink::Storage::uidFromKey(result.first()); 327 const auto uid = Sink::Storage::uidFromKey(result.first());
@@ -334,7 +333,7 @@ private slots:
334 pipeline.commit(); 333 pipeline.commit();
335 334
336 // We have a new revision that indicates the deletion 335 // We have a new revision that indicates the deletion
337 QCOMPARE(getKeys("org.kde.pipelinetest.instance1", "event.main").size(), 2); 336 QCOMPARE(getKeys("sink.pipelinetest.instance1", "event.main").size(), 2);
338 337
339 // Cleanup old revisions 338 // Cleanup old revisions
340 pipeline.startTransaction(); 339 pipeline.startTransaction();
@@ -342,18 +341,18 @@ private slots:
342 pipeline.commit(); 341 pipeline.commit();
343 342
344 // And all revisions are gone 343 // And all revisions are gone
345 QCOMPARE(getKeys("org.kde.pipelinetest.instance1", "event.main").size(), 0); 344 QCOMPARE(getKeys("sink.pipelinetest.instance1", "event.main").size(), 0);
346 } 345 }
347 346
348 void testPreprocessor() 347 void testPreprocessor()
349 { 348 {
350 flatbuffers::FlatBufferBuilder entityFbb; 349 flatbuffers::FlatBufferBuilder entityFbb;
351 350
352 TestProcessor testProcessor; 351 auto testProcessor = new TestProcessor;
353 352
354 Sink::Pipeline pipeline("org.kde.pipelinetest.instance1"); 353 Sink::Pipeline pipeline("sink.pipelinetest.instance1");
355 pipeline.setResourceType("test"); 354 pipeline.setResourceType("test");
356 pipeline.setPreprocessors("event", QVector<Sink::Preprocessor *>() << &testProcessor); 355 pipeline.setPreprocessors("event", QVector<Sink::Preprocessor *>() << testProcessor);
357 pipeline.startTransaction(); 356 pipeline.startTransaction();
358 // pipeline.setAdaptorFactory("event", QSharedPointer<TestEventAdaptorFactory>::create()); 357 // pipeline.setAdaptorFactory("event", QSharedPointer<TestEventAdaptorFactory>::create());
359 358
@@ -361,24 +360,24 @@ private slots:
361 { 360 {
362 auto command = createEntityCommand(createEvent(entityFbb)); 361 auto command = createEntityCommand(createEvent(entityFbb));
363 pipeline.newEntity(command.constData(), command.size()); 362 pipeline.newEntity(command.constData(), command.size());
364 QCOMPARE(testProcessor.newUids.size(), 1); 363 QCOMPARE(testProcessor->newUids.size(), 1);
365 QCOMPARE(testProcessor.newRevisions.size(), 1); 364 QCOMPARE(testProcessor->newRevisions.size(), 1);
366 // Key doesn't contain revision and is just the uid 365 // Key doesn't contain revision and is just the uid
367 QCOMPARE(testProcessor.newUids.at(0), Sink::Storage::uidFromKey(testProcessor.newUids.at(0))); 366 QCOMPARE(testProcessor->newUids.at(0), Sink::Storage::uidFromKey(testProcessor->newUids.at(0)));
368 } 367 }
369 pipeline.commit(); 368 pipeline.commit();
370 entityFbb.Clear(); 369 entityFbb.Clear();
371 pipeline.startTransaction(); 370 pipeline.startTransaction();
372 auto keys = getKeys("org.kde.pipelinetest.instance1", "event.main"); 371 auto keys = getKeys("sink.pipelinetest.instance1", "event.main");
373 QCOMPARE(keys.size(), 1); 372 QCOMPARE(keys.size(), 1);
374 const auto uid = Sink::Storage::uidFromKey(keys.first()); 373 const auto uid = Sink::Storage::uidFromKey(keys.first());
375 { 374 {
376 auto modifyCommand = modifyEntityCommand(createEvent(entityFbb, "summary2"), uid, 1); 375 auto modifyCommand = modifyEntityCommand(createEvent(entityFbb, "summary2"), uid, 1);
377 pipeline.modifiedEntity(modifyCommand.constData(), modifyCommand.size()); 376 pipeline.modifiedEntity(modifyCommand.constData(), modifyCommand.size());
378 QCOMPARE(testProcessor.modifiedUids.size(), 1); 377 QCOMPARE(testProcessor->modifiedUids.size(), 1);
379 QCOMPARE(testProcessor.modifiedRevisions.size(), 1); 378 QCOMPARE(testProcessor->modifiedRevisions.size(), 1);
380 // Key doesn't contain revision and is just the uid 379 // Key doesn't contain revision and is just the uid
381 QCOMPARE(testProcessor.modifiedUids.at(0), Sink::Storage::uidFromKey(testProcessor.modifiedUids.at(0))); 380 QCOMPARE(testProcessor->modifiedUids.at(0), Sink::Storage::uidFromKey(testProcessor->modifiedUids.at(0)));
382 } 381 }
383 pipeline.commit(); 382 pipeline.commit();
384 entityFbb.Clear(); 383 entityFbb.Clear();
@@ -386,12 +385,12 @@ private slots:
386 { 385 {
387 auto deleteCommand = deleteEntityCommand(uid, 1); 386 auto deleteCommand = deleteEntityCommand(uid, 1);
388 pipeline.deletedEntity(deleteCommand.constData(), deleteCommand.size()); 387 pipeline.deletedEntity(deleteCommand.constData(), deleteCommand.size());
389 QCOMPARE(testProcessor.deletedUids.size(), 1); 388 QCOMPARE(testProcessor->deletedUids.size(), 1);
390 QCOMPARE(testProcessor.deletedUids.size(), 1); 389 QCOMPARE(testProcessor->deletedUids.size(), 1);
391 QCOMPARE(testProcessor.deletedSummaries.size(), 1); 390 QCOMPARE(testProcessor->deletedSummaries.size(), 1);
392 // Key doesn't contain revision and is just the uid 391 // Key doesn't contain revision and is just the uid
393 QCOMPARE(testProcessor.deletedUids.at(0), Sink::Storage::uidFromKey(testProcessor.deletedUids.at(0))); 392 QCOMPARE(testProcessor->deletedUids.at(0), Sink::Storage::uidFromKey(testProcessor->deletedUids.at(0)));
394 QCOMPARE(testProcessor.deletedSummaries.at(0), QByteArray("summary2")); 393 QCOMPARE(testProcessor->deletedSummaries.at(0), QByteArray("summary2"));
395 } 394 }
396 } 395 }
397}; 396};
diff --git a/tests/querytest.cpp b/tests/querytest.cpp
index 6d7746e..d3a97f6 100644
--- a/tests/querytest.cpp
+++ b/tests/querytest.cpp
@@ -23,16 +23,15 @@ private slots:
23 void initTestCase() 23 void initTestCase()
24 { 24 {
25 Sink::Test::initTest(); 25 Sink::Test::initTest();
26 Sink::Log::setDebugOutputLevel(Sink::Log::Trace); 26 auto factory = Sink::ResourceFactory::load("sink.dummy");
27 auto factory = Sink::ResourceFactory::load("org.kde.dummy");
28 QVERIFY(factory); 27 QVERIFY(factory);
29 ResourceConfig::addResource("org.kde.dummy.instance1", "org.kde.dummy"); 28 ResourceConfig::addResource("sink.dummy.instance1", "sink.dummy");
30 Sink::Store::removeDataFromDisk(QByteArray("org.kde.dummy.instance1")).exec().waitForFinished(); 29 Sink::Store::removeDataFromDisk(QByteArray("sink.dummy.instance1")).exec().waitForFinished();
31 } 30 }
32 31
33 void cleanup() 32 void cleanup()
34 { 33 {
35 Sink::Store::removeDataFromDisk(QByteArray("org.kde.dummy.instance1")).exec().waitForFinished(); 34 Sink::Store::removeDataFromDisk(QByteArray("sink.dummy.instance1")).exec().waitForFinished();
36 } 35 }
37 36
38 void init() 37 void init()
@@ -60,13 +59,13 @@ private slots:
60 { 59 {
61 // Setup 60 // Setup
62 { 61 {
63 Sink::ApplicationDomain::Mail mail("org.kde.dummy.instance1"); 62 Sink::ApplicationDomain::Mail mail("sink.dummy.instance1");
64 Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished(); 63 Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished();
65 } 64 }
66 65
67 // Test 66 // Test
68 Sink::Query query; 67 Sink::Query query;
69 query.resources << "org.kde.dummy.instance1"; 68 query.resources << "sink.dummy.instance1";
70 query.liveQuery = true; 69 query.liveQuery = true;
71 70
72 // We fetch before the data is available and rely on the live query mechanism to deliver the actual data 71 // We fetch before the data is available and rely on the live query mechanism to deliver the actual data
@@ -78,13 +77,13 @@ private slots:
78 { 77 {
79 // Setup 78 // Setup
80 { 79 {
81 Sink::ApplicationDomain::Mail mail("org.kde.dummy.instance1"); 80 Sink::ApplicationDomain::Mail mail("sink.dummy.instance1");
82 Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished(); 81 Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished();
83 } 82 }
84 83
85 // Test 84 // Test
86 Sink::Query query; 85 Sink::Query query;
87 query.resources << "org.kde.dummy.instance1"; 86 query.resources << "sink.dummy.instance1";
88 query.liveQuery = false; 87 query.liveQuery = false;
89 88
90 // Ensure all local data is processed 89 // Ensure all local data is processed
@@ -102,12 +101,12 @@ private slots:
102 QByteArray id; 101 QByteArray id;
103 // Setup 102 // Setup
104 { 103 {
105 Sink::ApplicationDomain::Mail mail("org.kde.dummy.instance1"); 104 Sink::ApplicationDomain::Mail mail("sink.dummy.instance1");
106 Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished(); 105 Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished();
107 Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished(); 106 Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished();
108 107
109 Sink::Query query; 108 Sink::Query query;
110 query.resources << "org.kde.dummy.instance1"; 109 query.resources << "sink.dummy.instance1";
111 110
112 // Ensure all local data is processed 111 // Ensure all local data is processed
113 Sink::Store::synchronize(query).exec().waitForFinished(); 112 Sink::Store::synchronize(query).exec().waitForFinished();
@@ -121,7 +120,7 @@ private slots:
121 120
122 // Test 121 // Test
123 Sink::Query query; 122 Sink::Query query;
124 query.resources << "org.kde.dummy.instance1"; 123 query.resources << "sink.dummy.instance1";
125 query.ids << id; 124 query.ids << id;
126 auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query); 125 auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query);
127 QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); 126 QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool());
@@ -132,13 +131,13 @@ private slots:
132 { 131 {
133 // Setup 132 // Setup
134 { 133 {
135 Sink::ApplicationDomain::Folder folder("org.kde.dummy.instance1"); 134 Sink::ApplicationDomain::Folder folder("sink.dummy.instance1");
136 Sink::Store::create<Sink::ApplicationDomain::Folder>(folder).exec().waitForFinished(); 135 Sink::Store::create<Sink::ApplicationDomain::Folder>(folder).exec().waitForFinished();
137 } 136 }
138 137
139 // Test 138 // Test
140 Sink::Query query; 139 Sink::Query query;
141 query.resources << "org.kde.dummy.instance1"; 140 query.resources << "sink.dummy.instance1";
142 query.liveQuery = true; 141 query.liveQuery = true;
143 142
144 // We fetch before the data is available and rely on the live query mechanism to deliver the actual data 143 // We fetch before the data is available and rely on the live query mechanism to deliver the actual data
@@ -152,11 +151,11 @@ private slots:
152 { 151 {
153 // Setup 152 // Setup
154 { 153 {
155 Sink::ApplicationDomain::Folder folder("org.kde.dummy.instance1"); 154 Sink::ApplicationDomain::Folder folder("sink.dummy.instance1");
156 Sink::Store::create<Sink::ApplicationDomain::Folder>(folder).exec().waitForFinished(); 155 Sink::Store::create<Sink::ApplicationDomain::Folder>(folder).exec().waitForFinished();
157 156
158 Sink::Query query; 157 Sink::Query query;
159 query.resources << "org.kde.dummy.instance1"; 158 query.resources << "sink.dummy.instance1";
160 159
161 // Ensure all local data is processed 160 // Ensure all local data is processed
162 Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); 161 Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished();
@@ -168,14 +167,14 @@ private slots:
168 auto folderEntity = model->index(0, 0).data(Sink::Store::DomainObjectRole).value<Sink::ApplicationDomain::Folder::Ptr>(); 167 auto folderEntity = model->index(0, 0).data(Sink::Store::DomainObjectRole).value<Sink::ApplicationDomain::Folder::Ptr>();
169 QVERIFY(!folderEntity->identifier().isEmpty()); 168 QVERIFY(!folderEntity->identifier().isEmpty());
170 169
171 Sink::ApplicationDomain::Folder subfolder("org.kde.dummy.instance1"); 170 Sink::ApplicationDomain::Folder subfolder("sink.dummy.instance1");
172 subfolder.setProperty("parent", folderEntity->identifier()); 171 subfolder.setProperty("parent", folderEntity->identifier());
173 Sink::Store::create<Sink::ApplicationDomain::Folder>(subfolder).exec().waitForFinished(); 172 Sink::Store::create<Sink::ApplicationDomain::Folder>(subfolder).exec().waitForFinished();
174 } 173 }
175 174
176 // Test 175 // Test
177 Sink::Query query; 176 Sink::Query query;
178 query.resources << "org.kde.dummy.instance1"; 177 query.resources << "sink.dummy.instance1";
179 query.parentProperty = "parent"; 178 query.parentProperty = "parent";
180 179
181 // Ensure all local data is processed 180 // Ensure all local data is processed
@@ -194,7 +193,7 @@ private slots:
194 { 193 {
195 // Setup 194 // Setup
196 { 195 {
197 Sink::ApplicationDomain::Mail mail("org.kde.dummy.instance1"); 196 Sink::ApplicationDomain::Mail mail("sink.dummy.instance1");
198 mail.setProperty("uid", "test1"); 197 mail.setProperty("uid", "test1");
199 mail.setProperty("sender", "doe@example.org"); 198 mail.setProperty("sender", "doe@example.org");
200 Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished(); 199 Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished();
@@ -202,7 +201,7 @@ private slots:
202 201
203 // Test 202 // Test
204 Sink::Query query; 203 Sink::Query query;
205 query.resources << "org.kde.dummy.instance1"; 204 query.resources << "sink.dummy.instance1";
206 query.liveQuery = false; 205 query.liveQuery = false;
207 query += Sink::Query::PropertyFilter("uid", "test1"); 206 query += Sink::Query::PropertyFilter("uid", "test1");
208 207
@@ -220,11 +219,11 @@ private slots:
220 // Setup 219 // Setup
221 Sink::ApplicationDomain::Folder::Ptr folderEntity; 220 Sink::ApplicationDomain::Folder::Ptr folderEntity;
222 { 221 {
223 Sink::ApplicationDomain::Folder folder("org.kde.dummy.instance1"); 222 Sink::ApplicationDomain::Folder folder("sink.dummy.instance1");
224 Sink::Store::create<Sink::ApplicationDomain::Folder>(folder).exec().waitForFinished(); 223 Sink::Store::create<Sink::ApplicationDomain::Folder>(folder).exec().waitForFinished();
225 224
226 Sink::Query query; 225 Sink::Query query;
227 query.resources << "org.kde.dummy.instance1"; 226 query.resources << "sink.dummy.instance1";
228 227
229 // Ensure all local data is processed 228 // Ensure all local data is processed
230 Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); 229 Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished();
@@ -236,7 +235,7 @@ private slots:
236 folderEntity = model->index(0, 0).data(Sink::Store::DomainObjectRole).value<Sink::ApplicationDomain::Folder::Ptr>(); 235 folderEntity = model->index(0, 0).data(Sink::Store::DomainObjectRole).value<Sink::ApplicationDomain::Folder::Ptr>();
237 QVERIFY(!folderEntity->identifier().isEmpty()); 236 QVERIFY(!folderEntity->identifier().isEmpty());
238 237
239 Sink::ApplicationDomain::Mail mail("org.kde.dummy.instance1"); 238 Sink::ApplicationDomain::Mail mail("sink.dummy.instance1");
240 mail.setProperty("uid", "test1"); 239 mail.setProperty("uid", "test1");
241 mail.setProperty("folder", folderEntity->identifier()); 240 mail.setProperty("folder", folderEntity->identifier());
242 Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished(); 241 Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished();
@@ -244,7 +243,7 @@ private slots:
244 243
245 // Test 244 // Test
246 Sink::Query query; 245 Sink::Query query;
247 query.resources << "org.kde.dummy.instance1"; 246 query.resources << "sink.dummy.instance1";
248 query += Sink::Query::PropertyFilter("folder", *folderEntity); 247 query += Sink::Query::PropertyFilter("folder", *folderEntity);
249 248
250 // Ensure all local data is processed 249 // Ensure all local data is processed
@@ -261,11 +260,11 @@ private slots:
261 // Setup 260 // Setup
262 Sink::ApplicationDomain::Folder::Ptr folderEntity; 261 Sink::ApplicationDomain::Folder::Ptr folderEntity;
263 { 262 {
264 Sink::ApplicationDomain::Folder folder("org.kde.dummy.instance1"); 263 Sink::ApplicationDomain::Folder folder("sink.dummy.instance1");
265 Sink::Store::create<Sink::ApplicationDomain::Folder>(folder).exec().waitForFinished(); 264 Sink::Store::create<Sink::ApplicationDomain::Folder>(folder).exec().waitForFinished();
266 265
267 Sink::Query query; 266 Sink::Query query;
268 query.resources << "org.kde.dummy.instance1"; 267 query.resources << "sink.dummy.instance1";
269 268
270 // Ensure all local data is processed 269 // Ensure all local data is processed
271 Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); 270 Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished();
@@ -279,21 +278,21 @@ private slots:
279 278
280 const auto date = QDateTime(QDate(2015, 7, 7), QTime(12, 0)); 279 const auto date = QDateTime(QDate(2015, 7, 7), QTime(12, 0));
281 { 280 {
282 Sink::ApplicationDomain::Mail mail("org.kde.dummy.instance1"); 281 Sink::ApplicationDomain::Mail mail("sink.dummy.instance1");
283 mail.setProperty("uid", "testSecond"); 282 mail.setProperty("uid", "testSecond");
284 mail.setProperty("folder", folderEntity->identifier()); 283 mail.setProperty("folder", folderEntity->identifier());
285 mail.setProperty("date", date.addDays(-1)); 284 mail.setProperty("date", date.addDays(-1));
286 Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished(); 285 Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished();
287 } 286 }
288 { 287 {
289 Sink::ApplicationDomain::Mail mail("org.kde.dummy.instance1"); 288 Sink::ApplicationDomain::Mail mail("sink.dummy.instance1");
290 mail.setProperty("uid", "testLatest"); 289 mail.setProperty("uid", "testLatest");
291 mail.setProperty("folder", folderEntity->identifier()); 290 mail.setProperty("folder", folderEntity->identifier());
292 mail.setProperty("date", date); 291 mail.setProperty("date", date);
293 Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished(); 292 Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished();
294 } 293 }
295 { 294 {
296 Sink::ApplicationDomain::Mail mail("org.kde.dummy.instance1"); 295 Sink::ApplicationDomain::Mail mail("sink.dummy.instance1");
297 mail.setProperty("uid", "testLast"); 296 mail.setProperty("uid", "testLast");
298 mail.setProperty("folder", folderEntity->identifier()); 297 mail.setProperty("folder", folderEntity->identifier());
299 mail.setProperty("date", date.addDays(-2)); 298 mail.setProperty("date", date.addDays(-2));
@@ -303,7 +302,7 @@ private slots:
303 302
304 // Test 303 // Test
305 Sink::Query query; 304 Sink::Query query;
306 query.resources << "org.kde.dummy.instance1"; 305 query.resources << "sink.dummy.instance1";
307 query += Sink::Query::PropertyFilter("folder", *folderEntity); 306 query += Sink::Query::PropertyFilter("folder", *folderEntity);
308 query.sortProperty = "date"; 307 query.sortProperty = "date";
309 query.limit = 1; 308 query.limit = 1;
diff --git a/tests/resourcecommunicationtest.cpp b/tests/resourcecommunicationtest.cpp
index 2874457..1530f63 100644
--- a/tests/resourcecommunicationtest.cpp
+++ b/tests/resourcecommunicationtest.cpp
@@ -92,6 +92,26 @@ private slots:
92 QTRY_COMPARE(complete, count); 92 QTRY_COMPARE(complete, count);
93 QVERIFY(!errors); 93 QVERIFY(!errors);
94 } 94 }
95
96 void testAccessFactory()
97 {
98 const QByteArray resourceIdentifier("test");
99 Listener listener(resourceIdentifier, "");
100 QWeakPointer<Sink::ResourceAccess> weakRef;
101 QTime time;
102 time.start();
103 {
104 auto resourceAccess = Sink::ResourceAccessFactory::instance().getAccess(resourceIdentifier, "");
105 weakRef = resourceAccess.toWeakRef();
106 resourceAccess->open();
107 resourceAccess->sendCommand(Sink::Commands::PingCommand).then<void>([resourceAccess]() { qDebug() << "Pind complete"; }).exec();
108 }
109 QVERIFY(weakRef.toStrongRef());
110 QTRY_VERIFY(!weakRef.toStrongRef());
111 qDebug() << "time.elapsed " << time.elapsed();
112 QVERIFY(time.elapsed() < 3500);
113 QVERIFY(time.elapsed() > 2500);
114 }
95}; 115};
96 116
97QTEST_MAIN(ResourceCommunicationTest) 117QTEST_MAIN(ResourceCommunicationTest)
diff --git a/tests/resourceconfigtest.cpp b/tests/resourceconfigtest.cpp
index bebff50..021d042 100644
--- a/tests/resourceconfigtest.cpp
+++ b/tests/resourceconfigtest.cpp
@@ -8,6 +8,8 @@
8#include "modelresult.h" 8#include "modelresult.h"
9#include "resultprovider.h" 9#include "resultprovider.h"
10#include "facadefactory.h" 10#include "facadefactory.h"
11#include "test.h"
12#include "testutils.h"
11 13
12/** 14/**
13 * Test of the resource configuration. 15 * Test of the resource configuration.
@@ -19,9 +21,9 @@ private slots:
19 21
20 void initTestCase() 22 void initTestCase()
21 { 23 {
24 Sink::Test::initTest();
22 Sink::FacadeFactory::instance().resetFactory(); 25 Sink::FacadeFactory::instance().resetFactory();
23 ResourceConfig::clear(); 26 ResourceConfig::clear();
24 Sink::Log::setDebugOutputLevel(Sink::Log::Trace);
25 } 27 }
26 28
27 void resourceManagement() 29 void resourceManagement()
@@ -72,6 +74,30 @@ private slots:
72 Sink::Store::remove(res).exec().waitForFinished(); 74 Sink::Store::remove(res).exec().waitForFinished();
73 } 75 }
74 76
77 void testLoadResourceStatus()
78 {
79 ResourceConfig::clear();
80 Sink::FacadeFactory::instance().registerStaticFacades();
81
82 auto res = Sink::ApplicationDomain::DummyResource::create("");
83 VERIFYEXEC(Sink::Store::create(res));
84 {
85 Sink::Query query;
86 query.liveQuery = true;
87 query.request<Sink::ApplicationDomain::SinkResource::Status>();
88 auto model = Sink::Store::loadModel<Sink::ApplicationDomain::SinkResource>(query);
89 QTRY_COMPARE(model->rowCount(QModelIndex()), 1);
90 auto resource = model->data(model->index(0, 0, QModelIndex()), Sink::Store::DomainObjectRole).value<Sink::ApplicationDomain::SinkResource::Ptr>();
91 QCOMPARE(resource->getStatus(), static_cast<int>(Sink::ApplicationDomain::OfflineStatus));
92
93 //Synchronize to connect
94 VERIFYEXEC(Sink::Store::synchronize(query));
95 QTRY_COMPARE(model->data(model->index(0, 0, QModelIndex()), Sink::Store::DomainObjectRole).value<Sink::ApplicationDomain::SinkResource::Ptr>()->getStatus(), static_cast<int>(Sink::ApplicationDomain::ConnectedStatus));
96 }
97
98 VERIFYEXEC(Sink::Store::remove(res));
99 }
100
75}; 101};
76 102
77QTEST_MAIN(ResourceConfigTest) 103QTEST_MAIN(ResourceConfigTest)
diff --git a/tests/testaccounttest.cpp b/tests/testaccounttest.cpp
index c630846..078e7a0 100644
--- a/tests/testaccounttest.cpp
+++ b/tests/testaccounttest.cpp
@@ -20,7 +20,6 @@ private slots:
20 { 20 {
21 // Sink::FacadeFactory::instance().resetFactory(); 21 // Sink::FacadeFactory::instance().resetFactory();
22 // ResourceConfig::clear(); 22 // ResourceConfig::clear();
23 Log::setDebugOutputLevel(Sink::Log::Trace);
24 Test::initTest(); 23 Test::initTest();
25 } 24 }
26 25