summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/CMakeLists.txt1
-rw-r--r--common/entitystorage.cpp74
-rw-r--r--common/entitystorage.h126
-rw-r--r--common/facade.h3
-rw-r--r--common/resourceaccess.cpp2
5 files changed, 3 insertions, 203 deletions
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index f24ec46..bdb9eac 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -15,7 +15,6 @@ set(command_SRCS
15 definitions.cpp 15 definitions.cpp
16 log.cpp 16 log.cpp
17 entitybuffer.cpp 17 entitybuffer.cpp
18 entitystorage.cpp
19 clientapi.cpp 18 clientapi.cpp
20 facadefactory.cpp 19 facadefactory.cpp
21 commands.cpp 20 commands.cpp
diff --git a/common/entitystorage.cpp b/common/entitystorage.cpp
deleted file mode 100644
index 5d4df9f..0000000
--- a/common/entitystorage.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
1/*
2 * Copyright (C) 2014 Christian Mollekopf <chrigi_1@fastmail.fm>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#include "entitystorage.h"
21
22ResultSet EntityStorageBase::filteredSet(const ResultSet &resultSet, const std::function<bool(const Akonadi2::ApplicationDomain::ApplicationDomainType::Ptr &domainObject)> &filter, const Akonadi2::Storage::Transaction &transaction, bool initialQuery)
23{
24 auto resultSetPtr = QSharedPointer<ResultSet>::create(resultSet);
25
26 //Read through the source values and return whatever matches the filter
27 std::function<bool(std::function<void(const Akonadi2::ApplicationDomain::ApplicationDomainType::Ptr &, Akonadi2::Operation)>)> generator = [this, resultSetPtr, &transaction, filter, initialQuery](std::function<void(const Akonadi2::ApplicationDomain::ApplicationDomainType::Ptr &, Akonadi2::Operation)> callback) -> bool {
28 while (resultSetPtr->next()) {
29 readEntity(transaction, resultSetPtr->id(), [this, filter, callback, initialQuery](const Akonadi2::ApplicationDomain::ApplicationDomainType::Ptr &domainObject, Akonadi2::Operation operation) {
30 //Always remove removals, they probably don't match due to non-available properties
31 if (filter(domainObject) || operation == Akonadi2::Operation_Removal) {
32 if (initialQuery) {
33 //We're not interested in removals during the initial query
34 if (operation != Akonadi2::Operation_Removal) {
35 callback(domainObject, Akonadi2::Operation_Creation);
36 }
37 } else {
38 callback(domainObject, operation);
39 }
40 }
41 });
42 }
43 return false;
44 };
45 return ResultSet(generator);
46}
47
48
49ResultSet EntityStorageBase::getResultSet(const Akonadi2::Query &query, Akonadi2::Storage::Transaction &transaction, qint64 baseRevision)
50{
51 QSet<QByteArray> remainingFilters = query.propertyFilter.keys().toSet();
52 ResultSet resultSet;
53 const bool initialQuery = (baseRevision == 1);
54 if (initialQuery) {
55 Trace() << "Initial result set update";
56 resultSet = loadInitialResultSet(query, transaction, remainingFilters);
57 } else {
58 //TODO fallback in case the old revision is no longer available to clear + redo complete initial scan
59 Trace() << "Incremental result set update" << baseRevision;
60 resultSet = loadIncrementalResultSet(baseRevision, query, transaction, remainingFilters);
61 }
62
63 auto filter = [remainingFilters, query, baseRevision](const Akonadi2::ApplicationDomain::ApplicationDomainType::Ptr &domainObject) -> bool {
64 for (const auto &filterProperty : remainingFilters) {
65 //TODO implement other comparison operators than equality
66 if (domainObject->getProperty(filterProperty) != query.propertyFilter.value(filterProperty)) {
67 return false;
68 }
69 }
70 return true;
71 };
72
73 return filteredSet(resultSet, filter, transaction, initialQuery);
74}
diff --git a/common/entitystorage.h b/common/entitystorage.h
deleted file mode 100644
index 8e73083..0000000
--- a/common/entitystorage.h
+++ /dev/null
@@ -1,126 +0,0 @@
1/*
2 * Copyright (C) 2014 Christian Mollekopf <chrigi_1@fastmail.fm>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19#pragma once
20
21#include <QByteArray>
22
23#include "query.h"
24#include "domainadaptor.h"
25#include "entitybuffer.h"
26#include "log.h"
27#include "storage.h"
28#include "resultset.h"
29#include "resultprovider.h"
30#include "definitions.h"
31
32/**
33 * Wraps storage, entity adaptor factory and indexes into one.
34 *
35 */
36class EntityStorageBase
37{
38public:
39 typedef std::function<ResultSet (const Akonadi2::Query &query, Akonadi2::Storage::Transaction &transaction, QSet<QByteArray> &remainingFilters)> InitialResultLoader;
40 typedef std::function<ResultSet (qint64 baseRevision, const Akonadi2::Query &query, Akonadi2::Storage::Transaction &transaction, QSet<QByteArray> &remainingFilters)> IncrementalResultLoader;
41 typedef std::function<void(const Akonadi2::Storage::Transaction &transaction, const QByteArray &key, const std::function<void(const Akonadi2::ApplicationDomain::ApplicationDomainType::Ptr &, Akonadi2::Operation)> &resultCallback)> EntityReader;
42
43 /**
44 * Returns the initial result set that still needs to be filtered.
45 *
46 * To make this efficient indexes should be chosen that are as selective as possible.
47 */
48 InitialResultLoader loadInitialResultSet;
49 /**
50 * Returns the incremental result set that still needs to be filtered.
51 */
52 IncrementalResultLoader loadIncrementalResultSet;
53
54 /**
55 * Loads a single entity by uid from storage.
56 */
57 EntityReader readEntity;
58
59protected:
60 EntityStorageBase(const QByteArray &instanceIdentifier)
61 : mResourceInstanceIdentifier(instanceIdentifier)
62 {
63
64 }
65
66 virtual Akonadi2::ApplicationDomain::ApplicationDomainType::Ptr copy(const Akonadi2::ApplicationDomain::ApplicationDomainType &) = 0;
67
68 ResultSet getResultSet(const Akonadi2::Query &query, Akonadi2::Storage::Transaction &transaction, qint64 baseRevision);
69
70 QByteArray mResourceInstanceIdentifier;
71
72private:
73 ResultSet filteredSet(const ResultSet &resultSet, const std::function<bool(const Akonadi2::ApplicationDomain::ApplicationDomainType::Ptr &domainObject)> &filter, const Akonadi2::Storage::Transaction &transaction, bool isInitialQuery);
74};
75
76template<typename DomainType>
77class EntityStorage : public EntityStorageBase
78{
79
80public:
81
82 EntityStorage(const QByteArray &instanceIdentifier)
83 : EntityStorageBase(instanceIdentifier)
84 {
85 }
86
87protected:
88 Akonadi2::ApplicationDomain::ApplicationDomainType::Ptr copy(const Akonadi2::ApplicationDomain::ApplicationDomainType &object) Q_DECL_OVERRIDE
89 {
90 return Akonadi2::ApplicationDomain::ApplicationDomainType::getInMemoryRepresentation<DomainType>(object);
91 }
92
93public:
94
95 virtual qint64 read(const Akonadi2::Query &query, qint64 baseRevision, const QSharedPointer<Akonadi2::ResultProvider<typename DomainType::Ptr> > &resultProvider)
96 {
97 Akonadi2::Storage storage(Akonadi2::storageLocation(), mResourceInstanceIdentifier);
98 storage.setDefaultErrorHandler([](const Akonadi2::Storage::Error &error) {
99 Warning() << "Error during query: " << error.store << error.message;
100 });
101
102 auto transaction = storage.createTransaction(Akonadi2::Storage::ReadOnly);
103
104 Log() << "Querying" << baseRevision << Akonadi2::Storage::maxRevision(transaction);
105 auto resultSet = getResultSet(query, transaction, baseRevision);
106 while(resultSet.next([this, resultProvider](const Akonadi2::ApplicationDomain::ApplicationDomainType::Ptr &value, Akonadi2::Operation operation) -> bool {
107 switch (operation) {
108 case Akonadi2::Operation_Creation:
109 Trace() << "Got creation";
110 resultProvider->add(copy(*value).template staticCast<DomainType>());
111 break;
112 case Akonadi2::Operation_Modification:
113 Trace() << "Got modification";
114 resultProvider->modify(copy(*value).template staticCast<DomainType>());
115 break;
116 case Akonadi2::Operation_Removal:
117 Trace() << "Got removal";
118 resultProvider->remove(copy(*value).template staticCast<DomainType>());
119 break;
120 }
121 return true;
122 })){};
123 return Akonadi2::Storage::maxRevision(transaction);
124 }
125
126};
diff --git a/common/facade.h b/common/facade.h
index 5be1c73..6e45e08 100644
--- a/common/facade.h
+++ b/common/facade.h
@@ -29,7 +29,8 @@
29#include "domainadaptor.h" 29#include "domainadaptor.h"
30#include "log.h" 30#include "log.h"
31#include "resultset.h" 31#include "resultset.h"
32#include "entitystorage.h" 32#include "storage.h"
33#include "definitions.h"
33 34
34/** 35/**
35 * A QueryRunner runs a query and updates the corresponding result set. 36 * A QueryRunner runs a query and updates the corresponding result set.
diff --git a/common/resourceaccess.cpp b/common/resourceaccess.cpp
index bd9e2c9..88f785f 100644
--- a/common/resourceaccess.cpp
+++ b/common/resourceaccess.cpp
@@ -340,7 +340,7 @@ KAsync::Job<void> ResourceAccess::sendRevisionReplayedCommand(qint64 revision)
340void ResourceAccess::open() 340void ResourceAccess::open()
341{ 341{
342 if (d->socket && d->socket->isValid()) { 342 if (d->socket && d->socket->isValid()) {
343 log("Socket valid, so not opening again"); 343 Trace() << "Socket valid, so not opening again";
344 return; 344 return;
345 } 345 }
346 if (d->openingSocket) { 346 if (d->openingSocket) {