diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2016-03-03 09:01:05 +0100 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2016-03-03 09:01:05 +0100 |
commit | 4d9746c828558c9f872e0aed52442863affb25d5 (patch) | |
tree | 507d7c2ba67f47d3cbbcf01a722236ff1b48426b | |
parent | 9cea920b7dd51867a0be0fed2f461b6be73c103e (diff) | |
download | sink-4d9746c828558c9f872e0aed52442863affb25d5.tar.gz sink-4d9746c828558c9f872e0aed52442863affb25d5.zip |
Fromatted the whole codebase with clang-format.
clang-format -i */**{.cpp,.h}
97 files changed, 2259 insertions, 2411 deletions
diff --git a/common/asyncutils.h b/common/asyncutils.h index ddcc37c..2cf010e 100644 --- a/common/asyncutils.h +++ b/common/asyncutils.h | |||
@@ -24,19 +24,18 @@ | |||
24 | #include <QFutureWatcher> | 24 | #include <QFutureWatcher> |
25 | 25 | ||
26 | namespace async { | 26 | namespace async { |
27 | template<typename T> | 27 | template <typename T> |
28 | KAsync::Job<T> run(const std::function<T()> &f) | 28 | KAsync::Job<T> run(const std::function<T()> &f) |
29 | { | 29 | { |
30 | return KAsync::start<T>([f](KAsync::Future<T> &future) { | 30 | return KAsync::start<T>([f](KAsync::Future<T> &future) { |
31 | auto result = QtConcurrent::run(f); | 31 | auto result = QtConcurrent::run(f); |
32 | auto watcher = new QFutureWatcher<T>; | 32 | auto watcher = new QFutureWatcher<T>; |
33 | watcher->setFuture(result); | 33 | watcher->setFuture(result); |
34 | QObject::connect(watcher, &QFutureWatcher<T>::finished, watcher, [&future, watcher]() { | 34 | QObject::connect(watcher, &QFutureWatcher<T>::finished, watcher, [&future, watcher]() { |
35 | future.setValue(watcher->future().result()); | 35 | future.setValue(watcher->future().result()); |
36 | delete watcher; | 36 | delete watcher; |
37 | future.setFinished(); | 37 | future.setFinished(); |
38 | }); | ||
39 | }); | 38 | }); |
40 | } | 39 | }); |
41 | 40 | } | |
42 | } | 41 | } |
diff --git a/common/bufferadaptor.h b/common/bufferadaptor.h index 892635f..0087643 100644 --- a/common/bufferadaptor.h +++ b/common/bufferadaptor.h | |||
@@ -30,44 +30,64 @@ namespace ApplicationDomain { | |||
30 | /** | 30 | /** |
31 | * This class has to be implemented by resources and can be used as generic interface to access the buffer properties | 31 | * This class has to be implemented by resources and can be used as generic interface to access the buffer properties |
32 | */ | 32 | */ |
33 | class BufferAdaptor { | 33 | class BufferAdaptor |
34 | { | ||
34 | public: | 35 | public: |
35 | virtual ~BufferAdaptor() {} | 36 | virtual ~BufferAdaptor() |
36 | virtual QVariant getProperty(const QByteArray &key) const { return QVariant(); } | 37 | { |
37 | virtual void setProperty(const QByteArray &key, const QVariant &value) {} | 38 | } |
38 | virtual QList<QByteArray> availableProperties() const { return QList<QByteArray>(); } | 39 | virtual QVariant getProperty(const QByteArray &key) const |
40 | { | ||
41 | return QVariant(); | ||
42 | } | ||
43 | virtual void setProperty(const QByteArray &key, const QVariant &value) | ||
44 | { | ||
45 | } | ||
46 | virtual QList<QByteArray> availableProperties() const | ||
47 | { | ||
48 | return QList<QByteArray>(); | ||
49 | } | ||
39 | }; | 50 | }; |
40 | 51 | ||
41 | class MemoryBufferAdaptor : public BufferAdaptor { | 52 | class MemoryBufferAdaptor : public BufferAdaptor |
53 | { | ||
42 | public: | 54 | public: |
43 | MemoryBufferAdaptor() | 55 | MemoryBufferAdaptor() : BufferAdaptor() |
44 | : BufferAdaptor() | ||
45 | { | 56 | { |
46 | } | 57 | } |
47 | 58 | ||
48 | MemoryBufferAdaptor(const BufferAdaptor &buffer, const QList<QByteArray> &properties) | 59 | MemoryBufferAdaptor(const BufferAdaptor &buffer, const QList<QByteArray> &properties) : BufferAdaptor() |
49 | : BufferAdaptor() | ||
50 | { | 60 | { |
51 | if (properties.isEmpty()) { | 61 | if (properties.isEmpty()) { |
52 | for(const auto &property : buffer.availableProperties()) { | 62 | for (const auto &property : buffer.availableProperties()) { |
53 | mValues.insert(property, buffer.getProperty(property)); | 63 | mValues.insert(property, buffer.getProperty(property)); |
54 | } | 64 | } |
55 | } else { | 65 | } else { |
56 | for(const auto &property : properties) { | 66 | for (const auto &property : properties) { |
57 | mValues.insert(property, buffer.getProperty(property)); | 67 | mValues.insert(property, buffer.getProperty(property)); |
58 | } | 68 | } |
59 | } | 69 | } |
60 | } | 70 | } |
61 | 71 | ||
62 | virtual ~MemoryBufferAdaptor() {} | 72 | virtual ~MemoryBufferAdaptor() |
73 | { | ||
74 | } | ||
63 | 75 | ||
64 | virtual QVariant getProperty(const QByteArray &key) const { return mValues.value(key); } | 76 | virtual QVariant getProperty(const QByteArray &key) const |
65 | virtual void setProperty(const QByteArray &key, const QVariant &value) { mValues.insert(key, value); } | 77 | { |
66 | virtual QByteArrayList availableProperties() const { return mValues.keys(); } | 78 | return mValues.value(key); |
79 | } | ||
80 | virtual void setProperty(const QByteArray &key, const QVariant &value) | ||
81 | { | ||
82 | mValues.insert(key, value); | ||
83 | } | ||
84 | virtual QByteArrayList availableProperties() const | ||
85 | { | ||
86 | return mValues.keys(); | ||
87 | } | ||
67 | 88 | ||
68 | private: | 89 | private: |
69 | QHash<QByteArray, QVariant> mValues; | 90 | QHash<QByteArray, QVariant> mValues; |
70 | }; | 91 | }; |
71 | |||
72 | } | 92 | } |
73 | } | 93 | } |
diff --git a/common/bufferutils.h b/common/bufferutils.h index b08b7f8..1eb5d15 100644 --- a/common/bufferutils.h +++ b/common/bufferutils.h | |||
@@ -5,22 +5,21 @@ | |||
5 | 5 | ||
6 | namespace Sink { | 6 | namespace Sink { |
7 | namespace BufferUtils { | 7 | namespace BufferUtils { |
8 | template<typename T> | 8 | template <typename T> |
9 | static QByteArray extractBuffer(const T *data) | 9 | static QByteArray extractBuffer(const T *data) |
10 | { | 10 | { |
11 | return QByteArray::fromRawData(reinterpret_cast<char const *>(data->Data()), data->size()); | 11 | return QByteArray::fromRawData(reinterpret_cast<char const *>(data->Data()), data->size()); |
12 | } | 12 | } |
13 | 13 | ||
14 | template<typename T> | 14 | template <typename T> |
15 | static QByteArray extractBufferCopy(const T *data) | 15 | static QByteArray extractBufferCopy(const T *data) |
16 | { | 16 | { |
17 | return QByteArray(reinterpret_cast<char const *>(data->Data()), data->size()); | 17 | return QByteArray(reinterpret_cast<char const *>(data->Data()), data->size()); |
18 | } | 18 | } |
19 | 19 | ||
20 | static QByteArray extractBuffer(const flatbuffers::FlatBufferBuilder &fbb) | 20 | static QByteArray extractBuffer(const flatbuffers::FlatBufferBuilder &fbb) |
21 | { | 21 | { |
22 | return QByteArray::fromRawData(reinterpret_cast<char const *>(fbb.GetBufferPointer()), fbb.GetSize()); | 22 | return QByteArray::fromRawData(reinterpret_cast<char const *>(fbb.GetBufferPointer()), fbb.GetSize()); |
23 | } | 23 | } |
24 | } | 24 | } |
25 | } | 25 | } |
26 | |||
diff --git a/common/commands.cpp b/common/commands.cpp index 5d38afa..91657b8 100644 --- a/common/commands.cpp +++ b/common/commands.cpp | |||
@@ -22,15 +22,13 @@ | |||
22 | 22 | ||
23 | #include <QIODevice> | 23 | #include <QIODevice> |
24 | 24 | ||
25 | namespace Sink | 25 | namespace Sink { |
26 | { | ||
27 | 26 | ||
28 | namespace Commands | 27 | namespace Commands { |
29 | { | ||
30 | 28 | ||
31 | QByteArray name(int commandId) | 29 | QByteArray name(int commandId) |
32 | { | 30 | { |
33 | switch(commandId) { | 31 | switch (commandId) { |
34 | case UnknownCommand: | 32 | case UnknownCommand: |
35 | return "Unknown"; | 33 | return "Unknown"; |
36 | case CommandCompletionCommand: | 34 | case CommandCompletionCommand: |
@@ -85,9 +83,9 @@ void write(QIODevice *device, int messageId, int commandId, const char *buffer, | |||
85 | size = 0; | 83 | size = 0; |
86 | } | 84 | } |
87 | 85 | ||
88 | device->write((const char*)&messageId, sizeof(int)); | 86 | device->write((const char *)&messageId, sizeof(int)); |
89 | device->write((const char*)&commandId, sizeof(int)); | 87 | device->write((const char *)&commandId, sizeof(int)); |
90 | device->write((const char*)&size, sizeof(uint)); | 88 | device->write((const char *)&size, sizeof(uint)); |
91 | if (buffer) { | 89 | if (buffer) { |
92 | device->write(buffer, size); | 90 | device->write(buffer, size); |
93 | } | 91 | } |
@@ -96,10 +94,10 @@ void write(QIODevice *device, int messageId, int commandId, const char *buffer, | |||
96 | void write(QIODevice *device, int messageId, int commandId, flatbuffers::FlatBufferBuilder &fbb) | 94 | void write(QIODevice *device, int messageId, int commandId, flatbuffers::FlatBufferBuilder &fbb) |
97 | { | 95 | { |
98 | const int dataSize = fbb.GetSize(); | 96 | const int dataSize = fbb.GetSize(); |
99 | device->write((const char*)&messageId, sizeof(int)); | 97 | device->write((const char *)&messageId, sizeof(int)); |
100 | device->write((const char*)&commandId, sizeof(int)); | 98 | device->write((const char *)&commandId, sizeof(int)); |
101 | device->write((const char*)&dataSize, sizeof(int)); | 99 | device->write((const char *)&dataSize, sizeof(int)); |
102 | device->write((const char*)fbb.GetBufferPointer(), dataSize); | 100 | device->write((const char *)fbb.GetBufferPointer(), dataSize); |
103 | } | 101 | } |
104 | 102 | ||
105 | } // namespace Commands | 103 | } // namespace Commands |
diff --git a/common/commands.h b/common/commands.h index 64abd76..b97bbc6 100644 --- a/common/commands.h +++ b/common/commands.h | |||
@@ -26,13 +26,12 @@ | |||
26 | 26 | ||
27 | class QIODevice; | 27 | class QIODevice; |
28 | 28 | ||
29 | namespace Sink | 29 | namespace Sink { |
30 | { | ||
31 | 30 | ||
32 | namespace Commands | 31 | namespace Commands { |
33 | { | ||
34 | 32 | ||
35 | enum CommandIds { | 33 | enum CommandIds |
34 | { | ||
36 | UnknownCommand = 0, | 35 | UnknownCommand = 0, |
37 | CommandCompletionCommand, | 36 | CommandCompletionCommand, |
38 | HandshakeCommand, | 37 | HandshakeCommand, |
@@ -59,7 +58,6 @@ int SINK_EXPORT headerSize(); | |||
59 | void SINK_EXPORT write(QIODevice *device, int messageId, int commandId); | 58 | void SINK_EXPORT write(QIODevice *device, int messageId, int commandId); |
60 | void SINK_EXPORT write(QIODevice *device, int messageId, int commandId, const char *buffer, uint size); | 59 | void SINK_EXPORT write(QIODevice *device, int messageId, int commandId, const char *buffer, uint size); |
61 | void SINK_EXPORT write(QIODevice *device, int messageId, int commandId, flatbuffers::FlatBufferBuilder &fbb); | 60 | void SINK_EXPORT write(QIODevice *device, int messageId, int commandId, flatbuffers::FlatBufferBuilder &fbb); |
62 | |||
63 | } | 61 | } |
64 | 62 | ||
65 | } // namespace Sink | 63 | } // namespace Sink |
diff --git a/common/definitions.h b/common/definitions.h index 029d3f8..96ec27e 100644 --- a/common/definitions.h +++ b/common/definitions.h | |||
@@ -25,6 +25,6 @@ | |||
25 | #include <QByteArray> | 25 | #include <QByteArray> |
26 | 26 | ||
27 | namespace Sink { | 27 | namespace Sink { |
28 | QString SINK_EXPORT storageLocation(); | 28 | QString SINK_EXPORT storageLocation(); |
29 | QByteArray SINK_EXPORT resourceName(const QByteArray &instanceIdentifier); | 29 | QByteArray SINK_EXPORT resourceName(const QByteArray &instanceIdentifier); |
30 | } | 30 | } |
diff --git a/common/domainadaptor.cpp b/common/domainadaptor.cpp index 2955cab..dcacc94 100644 --- a/common/domainadaptor.cpp +++ b/common/domainadaptor.cpp | |||
@@ -18,4 +18,3 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include "domainadaptor.h" | 20 | #include "domainadaptor.h" |
21 | |||
diff --git a/common/domainadaptor.h b/common/domainadaptor.h index 9ce5a8a..0159c6c 100644 --- a/common/domainadaptor.h +++ b/common/domainadaptor.h | |||
@@ -40,10 +40,11 @@ | |||
40 | * Create a buffer from a domain object using the provided mappings | 40 | * Create a buffer from a domain object using the provided mappings |
41 | */ | 41 | */ |
42 | template <class Builder, class Buffer> | 42 | template <class Builder, class Buffer> |
43 | flatbuffers::Offset<Buffer> createBufferPart(const Sink::ApplicationDomain::ApplicationDomainType &domainObject, flatbuffers::FlatBufferBuilder &fbb, const WritePropertyMapper<Builder> &mapper) | 43 | flatbuffers::Offset<Buffer> |
44 | createBufferPart(const Sink::ApplicationDomain::ApplicationDomainType &domainObject, flatbuffers::FlatBufferBuilder &fbb, const WritePropertyMapper<Builder> &mapper) | ||
44 | { | 45 | { |
45 | //First create a primitives such as strings using the mappings | 46 | // First create a primitives such as strings using the mappings |
46 | QList<std::function<void(Builder &)> > propertiesToAddToResource; | 47 | QList<std::function<void(Builder &)>> propertiesToAddToResource; |
47 | for (const auto &property : domainObject.changedProperties()) { | 48 | for (const auto &property : domainObject.changedProperties()) { |
48 | // Trace() << "copying property " << property; | 49 | // Trace() << "copying property " << property; |
49 | const auto value = domainObject.getProperty(property); | 50 | const auto value = domainObject.getProperty(property); |
@@ -54,7 +55,7 @@ flatbuffers::Offset<Buffer> createBufferPart(const Sink::ApplicationDomain::Appl | |||
54 | } | 55 | } |
55 | } | 56 | } |
56 | 57 | ||
57 | //Then create all porperties using the above generated builderCalls | 58 | // Then create all porperties using the above generated builderCalls |
58 | Builder builder(fbb); | 59 | Builder builder(fbb); |
59 | for (auto propertyBuilder : propertiesToAddToResource) { | 60 | for (auto propertyBuilder : propertiesToAddToResource) { |
60 | propertyBuilder(builder); | 61 | propertyBuilder(builder); |
@@ -64,7 +65,7 @@ flatbuffers::Offset<Buffer> createBufferPart(const Sink::ApplicationDomain::Appl | |||
64 | 65 | ||
65 | /** | 66 | /** |
66 | * Create the buffer and finish the FlatBufferBuilder. | 67 | * Create the buffer and finish the FlatBufferBuilder. |
67 | * | 68 | * |
68 | * After this the buffer can be extracted from the FlatBufferBuilder object. | 69 | * After this the buffer can be extracted from the FlatBufferBuilder object. |
69 | */ | 70 | */ |
70 | template <typename Buffer, typename BufferBuilder> | 71 | template <typename Buffer, typename BufferBuilder> |
@@ -88,10 +89,8 @@ template <class LocalBuffer, class ResourceBuffer> | |||
88 | class GenericBufferAdaptor : public Sink::ApplicationDomain::BufferAdaptor | 89 | class GenericBufferAdaptor : public Sink::ApplicationDomain::BufferAdaptor |
89 | { | 90 | { |
90 | public: | 91 | public: |
91 | GenericBufferAdaptor() | 92 | GenericBufferAdaptor() : BufferAdaptor() |
92 | : BufferAdaptor() | ||
93 | { | 93 | { |
94 | |||
95 | } | 94 | } |
96 | 95 | ||
97 | virtual QVariant getProperty(const QByteArray &key) const | 96 | virtual QVariant getProperty(const QByteArray &key) const |
@@ -112,8 +111,8 @@ public: | |||
112 | 111 | ||
113 | LocalBuffer const *mLocalBuffer; | 112 | LocalBuffer const *mLocalBuffer; |
114 | ResourceBuffer const *mResourceBuffer; | 113 | ResourceBuffer const *mResourceBuffer; |
115 | QSharedPointer<ReadPropertyMapper<LocalBuffer> > mLocalMapper; | 114 | QSharedPointer<ReadPropertyMapper<LocalBuffer>> mLocalMapper; |
116 | QSharedPointer<ReadPropertyMapper<ResourceBuffer> > mResourceMapper; | 115 | QSharedPointer<ReadPropertyMapper<ResourceBuffer>> mResourceMapper; |
117 | }; | 116 | }; |
118 | 117 | ||
119 | /** | 118 | /** |
@@ -121,23 +120,23 @@ public: | |||
121 | * It defines how values are split accross local and resource buffer. | 120 | * It defines how values are split accross local and resource buffer. |
122 | * This is required by the facade the read the value, and by the pipeline preprocessors to access the domain values in a generic way. | 121 | * This is required by the facade the read the value, and by the pipeline preprocessors to access the domain values in a generic way. |
123 | */ | 122 | */ |
124 | template<typename DomainType, typename ResourceBuffer, typename ResourceBuilder> | 123 | template <typename DomainType, typename ResourceBuffer, typename ResourceBuilder> |
125 | class SINK_EXPORT DomainTypeAdaptorFactory : public DomainTypeAdaptorFactoryInterface | 124 | class SINK_EXPORT DomainTypeAdaptorFactory : public DomainTypeAdaptorFactoryInterface |
126 | { | 125 | { |
127 | typedef typename Sink::ApplicationDomain::TypeImplementation<DomainType>::Buffer LocalBuffer; | 126 | typedef typename Sink::ApplicationDomain::TypeImplementation<DomainType>::Buffer LocalBuffer; |
128 | typedef typename Sink::ApplicationDomain::TypeImplementation<DomainType>::BufferBuilder LocalBuilder; | 127 | typedef typename Sink::ApplicationDomain::TypeImplementation<DomainType>::BufferBuilder LocalBuilder; |
128 | |||
129 | public: | 129 | public: |
130 | DomainTypeAdaptorFactory() : | 130 | DomainTypeAdaptorFactory() |
131 | mLocalMapper(Sink::ApplicationDomain::TypeImplementation<DomainType>::initializeReadPropertyMapper()), | 131 | : mLocalMapper(Sink::ApplicationDomain::TypeImplementation<DomainType>::initializeReadPropertyMapper()), |
132 | mResourceMapper(QSharedPointer<ReadPropertyMapper<ResourceBuffer> >::create()), | 132 | mResourceMapper(QSharedPointer<ReadPropertyMapper<ResourceBuffer>>::create()), |
133 | mLocalWriteMapper(Sink::ApplicationDomain::TypeImplementation<DomainType>::initializeWritePropertyMapper()), | 133 | mLocalWriteMapper(Sink::ApplicationDomain::TypeImplementation<DomainType>::initializeWritePropertyMapper()), |
134 | mResourceWriteMapper(QSharedPointer<WritePropertyMapper<ResourceBuilder> >::create()) | 134 | mResourceWriteMapper(QSharedPointer<WritePropertyMapper<ResourceBuilder>>::create()){}; |
135 | {}; | 135 | virtual ~DomainTypeAdaptorFactory(){}; |
136 | virtual ~DomainTypeAdaptorFactory() {}; | ||
137 | 136 | ||
138 | /** | 137 | /** |
139 | * Creates an adaptor for the given domain and resource types. | 138 | * Creates an adaptor for the given domain and resource types. |
140 | * | 139 | * |
141 | * This returns by default a GenericBufferAdaptor initialized with the corresponding property mappers. | 140 | * This returns by default a GenericBufferAdaptor initialized with the corresponding property mappers. |
142 | */ | 141 | */ |
143 | virtual QSharedPointer<Sink::ApplicationDomain::BufferAdaptor> createAdaptor(const Sink::Entity &entity) Q_DECL_OVERRIDE | 142 | virtual QSharedPointer<Sink::ApplicationDomain::BufferAdaptor> createAdaptor(const Sink::Entity &entity) Q_DECL_OVERRIDE |
@@ -146,7 +145,7 @@ public: | |||
146 | const auto localBuffer = Sink::EntityBuffer::readBuffer<LocalBuffer>(entity.local()); | 145 | const auto localBuffer = Sink::EntityBuffer::readBuffer<LocalBuffer>(entity.local()); |
147 | // const auto metadataBuffer = Sink::EntityBuffer::readBuffer<Sink::Metadata>(entity.metadata()); | 146 | // const auto metadataBuffer = Sink::EntityBuffer::readBuffer<Sink::Metadata>(entity.metadata()); |
148 | 147 | ||
149 | auto adaptor = QSharedPointer<GenericBufferAdaptor<LocalBuffer, ResourceBuffer> >::create(); | 148 | auto adaptor = QSharedPointer<GenericBufferAdaptor<LocalBuffer, ResourceBuffer>>::create(); |
150 | adaptor->mLocalBuffer = localBuffer; | 149 | adaptor->mLocalBuffer = localBuffer; |
151 | adaptor->mLocalMapper = mLocalMapper; | 150 | adaptor->mLocalMapper = mLocalMapper; |
152 | adaptor->mResourceBuffer = resourceBuffer; | 151 | adaptor->mResourceBuffer = resourceBuffer; |
@@ -154,7 +153,8 @@ public: | |||
154 | return adaptor; | 153 | return adaptor; |
155 | } | 154 | } |
156 | 155 | ||
157 | virtual void createBuffer(const Sink::ApplicationDomain::ApplicationDomainType &domainObject, flatbuffers::FlatBufferBuilder &fbb, void const *metadataData = 0, size_t metadataSize = 0) Q_DECL_OVERRIDE | 156 | virtual void |
157 | createBuffer(const Sink::ApplicationDomain::ApplicationDomainType &domainObject, flatbuffers::FlatBufferBuilder &fbb, void const *metadataData = 0, size_t metadataSize = 0) Q_DECL_OVERRIDE | ||
158 | { | 158 | { |
159 | flatbuffers::FlatBufferBuilder localFbb; | 159 | flatbuffers::FlatBufferBuilder localFbb; |
160 | if (mLocalWriteMapper) { | 160 | if (mLocalWriteMapper) { |
@@ -173,10 +173,8 @@ public: | |||
173 | 173 | ||
174 | 174 | ||
175 | protected: | 175 | protected: |
176 | QSharedPointer<ReadPropertyMapper<LocalBuffer> > mLocalMapper; | 176 | QSharedPointer<ReadPropertyMapper<LocalBuffer>> mLocalMapper; |
177 | QSharedPointer<ReadPropertyMapper<ResourceBuffer> > mResourceMapper; | 177 | QSharedPointer<ReadPropertyMapper<ResourceBuffer>> mResourceMapper; |
178 | QSharedPointer<WritePropertyMapper<LocalBuilder> > mLocalWriteMapper; | 178 | QSharedPointer<WritePropertyMapper<LocalBuilder>> mLocalWriteMapper; |
179 | QSharedPointer<WritePropertyMapper<ResourceBuilder> > mResourceWriteMapper; | 179 | QSharedPointer<WritePropertyMapper<ResourceBuilder>> mResourceWriteMapper; |
180 | }; | 180 | }; |
181 | |||
182 | |||
diff --git a/common/domaintypeadaptorfactoryinterface.h b/common/domaintypeadaptorfactoryinterface.h index 4d0ce04..72aa9b9 100644 --- a/common/domaintypeadaptorfactoryinterface.h +++ b/common/domaintypeadaptorfactoryinterface.h | |||
@@ -21,22 +21,22 @@ | |||
21 | #include <QSharedPointer> | 21 | #include <QSharedPointer> |
22 | 22 | ||
23 | namespace Sink { | 23 | namespace Sink { |
24 | namespace ApplicationDomain { | 24 | namespace ApplicationDomain { |
25 | class BufferAdaptor; | 25 | class BufferAdaptor; |
26 | class ApplicationDomainType; | 26 | class ApplicationDomainType; |
27 | } | 27 | } |
28 | struct Entity; | 28 | struct Entity; |
29 | } | 29 | } |
30 | 30 | ||
31 | namespace flatbuffers { | 31 | namespace flatbuffers { |
32 | class FlatBufferBuilder; | 32 | class FlatBufferBuilder; |
33 | } | 33 | } |
34 | 34 | ||
35 | class DomainTypeAdaptorFactoryInterface | 35 | class DomainTypeAdaptorFactoryInterface |
36 | { | 36 | { |
37 | public: | 37 | public: |
38 | typedef QSharedPointer<DomainTypeAdaptorFactoryInterface> Ptr; | 38 | typedef QSharedPointer<DomainTypeAdaptorFactoryInterface> Ptr; |
39 | virtual ~DomainTypeAdaptorFactoryInterface() {}; | 39 | virtual ~DomainTypeAdaptorFactoryInterface(){}; |
40 | virtual QSharedPointer<Sink::ApplicationDomain::BufferAdaptor> createAdaptor(const Sink::Entity &entity) = 0; | 40 | virtual QSharedPointer<Sink::ApplicationDomain::BufferAdaptor> createAdaptor(const Sink::Entity &entity) = 0; |
41 | 41 | ||
42 | /* | 42 | /* |
@@ -44,5 +44,6 @@ public: | |||
44 | * | 44 | * |
45 | * Note that this only serialized parameters that are part of ApplicationDomainType::changedProperties() | 45 | * Note that this only serialized parameters that are part of ApplicationDomainType::changedProperties() |
46 | */ | 46 | */ |
47 | virtual void createBuffer(const Sink::ApplicationDomain::ApplicationDomainType &domainType, flatbuffers::FlatBufferBuilder &fbb, void const *metadataData = 0, size_t metadataSize = 0) = 0; | 47 | virtual void |
48 | createBuffer(const Sink::ApplicationDomain::ApplicationDomainType &domainType, flatbuffers::FlatBufferBuilder &fbb, void const *metadataData = 0, size_t metadataSize = 0) = 0; | ||
48 | }; | 49 | }; |
diff --git a/common/entitybuffer.cpp b/common/entitybuffer.cpp index b4a5cb2..950bc46 100644 --- a/common/entitybuffer.cpp +++ b/common/entitybuffer.cpp | |||
@@ -6,8 +6,7 @@ | |||
6 | 6 | ||
7 | using namespace Sink; | 7 | using namespace Sink; |
8 | 8 | ||
9 | EntityBuffer::EntityBuffer(const void *dataValue, int dataSize) | 9 | EntityBuffer::EntityBuffer(const void *dataValue, int dataSize) : mEntity(nullptr) |
10 | : mEntity(nullptr) | ||
11 | { | 10 | { |
12 | flatbuffers::Verifier verifyer(reinterpret_cast<const uint8_t *>(dataValue), dataSize); | 11 | flatbuffers::Verifier verifyer(reinterpret_cast<const uint8_t *>(dataValue), dataSize); |
13 | // Q_ASSERT(Sink::VerifyEntity(verifyer)); | 12 | // Q_ASSERT(Sink::VerifyEntity(verifyer)); |
@@ -18,10 +17,8 @@ EntityBuffer::EntityBuffer(const void *dataValue, int dataSize) | |||
18 | } | 17 | } |
19 | } | 18 | } |
20 | 19 | ||
21 | EntityBuffer::EntityBuffer(const QByteArray &data) | 20 | EntityBuffer::EntityBuffer(const QByteArray &data) : EntityBuffer(data.constData(), data.size()) |
22 | : EntityBuffer(data.constData(), data.size()) | ||
23 | { | 21 | { |
24 | |||
25 | } | 22 | } |
26 | 23 | ||
27 | bool EntityBuffer::isValid() const | 24 | bool EntityBuffer::isValid() const |
@@ -35,7 +32,7 @@ const Sink::Entity &EntityBuffer::entity() | |||
35 | return *mEntity; | 32 | return *mEntity; |
36 | } | 33 | } |
37 | 34 | ||
38 | const uint8_t* EntityBuffer::resourceBuffer() | 35 | const uint8_t *EntityBuffer::resourceBuffer() |
39 | { | 36 | { |
40 | if (!mEntity) { | 37 | if (!mEntity) { |
41 | qDebug() << "no buffer"; | 38 | qDebug() << "no buffer"; |
@@ -44,7 +41,7 @@ const uint8_t* EntityBuffer::resourceBuffer() | |||
44 | return mEntity->resource()->Data(); | 41 | return mEntity->resource()->Data(); |
45 | } | 42 | } |
46 | 43 | ||
47 | const uint8_t* EntityBuffer::metadataBuffer() | 44 | const uint8_t *EntityBuffer::metadataBuffer() |
48 | { | 45 | { |
49 | if (!mEntity) { | 46 | if (!mEntity) { |
50 | return nullptr; | 47 | return nullptr; |
@@ -52,7 +49,7 @@ const uint8_t* EntityBuffer::metadataBuffer() | |||
52 | return mEntity->metadata()->Data(); | 49 | return mEntity->metadata()->Data(); |
53 | } | 50 | } |
54 | 51 | ||
55 | const uint8_t* EntityBuffer::localBuffer() | 52 | const uint8_t *EntityBuffer::localBuffer() |
56 | { | 53 | { |
57 | if (!mEntity) { | 54 | if (!mEntity) { |
58 | return nullptr; | 55 | return nullptr; |
@@ -68,17 +65,18 @@ void EntityBuffer::extractResourceBuffer(void *dataValue, int dataSize, const st | |||
68 | } | 65 | } |
69 | } | 66 | } |
70 | 67 | ||
71 | flatbuffers::Offset<flatbuffers::Vector<uint8_t> > EntityBuffer::appendAsVector(flatbuffers::FlatBufferBuilder &fbb, void const *data, size_t size) | 68 | flatbuffers::Offset<flatbuffers::Vector<uint8_t>> EntityBuffer::appendAsVector(flatbuffers::FlatBufferBuilder &fbb, void const *data, size_t size) |
72 | { | 69 | { |
73 | //Since we do memcpy trickery, this will only work on little endian | 70 | // Since we do memcpy trickery, this will only work on little endian |
74 | assert(FLATBUFFERS_LITTLEENDIAN); | 71 | assert(FLATBUFFERS_LITTLEENDIAN); |
75 | uint8_t *rawDataPtr = Q_NULLPTR; | 72 | uint8_t *rawDataPtr = Q_NULLPTR; |
76 | const auto pos = fbb.CreateUninitializedVector<uint8_t>(size, &rawDataPtr); | 73 | const auto pos = fbb.CreateUninitializedVector<uint8_t>(size, &rawDataPtr); |
77 | std::memcpy((void*)rawDataPtr, data, size); | 74 | std::memcpy((void *)rawDataPtr, data, size); |
78 | return pos; | 75 | return pos; |
79 | } | 76 | } |
80 | 77 | ||
81 | void EntityBuffer::assembleEntityBuffer(flatbuffers::FlatBufferBuilder &fbb, void const *metadataData, size_t metadataSize, void const *resourceData, size_t resourceSize, void const *localData, size_t localSize) | 78 | void EntityBuffer::assembleEntityBuffer( |
79 | flatbuffers::FlatBufferBuilder &fbb, void const *metadataData, size_t metadataSize, void const *resourceData, size_t resourceSize, void const *localData, size_t localSize) | ||
82 | { | 80 | { |
83 | auto metadata = appendAsVector(fbb, metadataData, metadataSize); | 81 | auto metadata = appendAsVector(fbb, metadataData, metadataSize); |
84 | auto resource = appendAsVector(fbb, resourceData, resourceSize); | 82 | auto resource = appendAsVector(fbb, resourceData, resourceSize); |
@@ -86,4 +84,3 @@ void EntityBuffer::assembleEntityBuffer(flatbuffers::FlatBufferBuilder &fbb, voi | |||
86 | auto entity = Sink::CreateEntity(fbb, metadata, resource, local); | 84 | auto entity = Sink::CreateEntity(fbb, metadata, resource, local); |
87 | Sink::FinishEntityBuffer(fbb, entity); | 85 | Sink::FinishEntityBuffer(fbb, entity); |
88 | } | 86 | } |
89 | |||
diff --git a/common/entitybuffer.h b/common/entitybuffer.h index 474a619..24f0b6b 100644 --- a/common/entitybuffer.h +++ b/common/entitybuffer.h | |||
@@ -8,7 +8,8 @@ | |||
8 | namespace Sink { | 8 | namespace Sink { |
9 | struct Entity; | 9 | struct Entity; |
10 | 10 | ||
11 | class SINK_EXPORT EntityBuffer { | 11 | class SINK_EXPORT EntityBuffer |
12 | { | ||
12 | public: | 13 | public: |
13 | EntityBuffer(const void *dataValue, int size); | 14 | EntityBuffer(const void *dataValue, int size); |
14 | EntityBuffer(const QByteArray &data); | 15 | EntityBuffer(const QByteArray &data); |
@@ -25,9 +26,10 @@ public: | |||
25 | * We can't use union's either (which would allow to have a field that stores a selection of tables), as we don't want to modify | 26 | * We can't use union's either (which would allow to have a field that stores a selection of tables), as we don't want to modify |
26 | * the entity schema for each resource's buffers. | 27 | * the entity schema for each resource's buffers. |
27 | */ | 28 | */ |
28 | static void assembleEntityBuffer(flatbuffers::FlatBufferBuilder &fbb, void const *metadataData, size_t metadataSize, void const *resourceData, size_t resourceSize, void const *localData, size_t localSize); | 29 | static void assembleEntityBuffer( |
29 | static flatbuffers::Offset<flatbuffers::Vector<uint8_t> > appendAsVector(flatbuffers::FlatBufferBuilder &fbb, void const *data, size_t size); | 30 | flatbuffers::FlatBufferBuilder &fbb, void const *metadataData, size_t metadataSize, void const *resourceData, size_t resourceSize, void const *localData, size_t localSize); |
30 | template<typename T> | 31 | static flatbuffers::Offset<flatbuffers::Vector<uint8_t>> appendAsVector(flatbuffers::FlatBufferBuilder &fbb, void const *data, size_t size); |
32 | template <typename T> | ||
31 | static const T *readBuffer(const uint8_t *data, int size) | 33 | static const T *readBuffer(const uint8_t *data, int size) |
32 | { | 34 | { |
33 | flatbuffers::Verifier verifier(data, size); | 35 | flatbuffers::Verifier verifier(data, size); |
@@ -37,7 +39,7 @@ public: | |||
37 | return nullptr; | 39 | return nullptr; |
38 | } | 40 | } |
39 | 41 | ||
40 | template<typename T> | 42 | template <typename T> |
41 | static const T *readBuffer(const flatbuffers::Vector<uint8_t> *data) | 43 | static const T *readBuffer(const flatbuffers::Vector<uint8_t> *data) |
42 | { | 44 | { |
43 | if (data) { | 45 | if (data) { |
@@ -50,6 +52,4 @@ public: | |||
50 | private: | 52 | private: |
51 | const Entity *mEntity; | 53 | const Entity *mEntity; |
52 | }; | 54 | }; |
53 | |||
54 | } | 55 | } |
55 | |||
diff --git a/common/facade.cpp b/common/facade.cpp index 1219887..803f85c 100644 --- a/common/facade.cpp +++ b/common/facade.cpp | |||
@@ -32,31 +32,29 @@ using namespace Sink; | |||
32 | #undef DEBUG_AREA | 32 | #undef DEBUG_AREA |
33 | #define DEBUG_AREA "client.facade" | 33 | #define DEBUG_AREA "client.facade" |
34 | 34 | ||
35 | template<class DomainType> | 35 | template <class DomainType> |
36 | GenericFacade<DomainType>::GenericFacade(const QByteArray &resourceIdentifier, const DomainTypeAdaptorFactoryInterface::Ptr &adaptorFactory , const QSharedPointer<Sink::ResourceAccessInterface> resourceAccess) | 36 | GenericFacade<DomainType>::GenericFacade( |
37 | : Sink::StoreFacade<DomainType>(), | 37 | const QByteArray &resourceIdentifier, const DomainTypeAdaptorFactoryInterface::Ptr &adaptorFactory, const QSharedPointer<Sink::ResourceAccessInterface> resourceAccess) |
38 | mResourceAccess(resourceAccess), | 38 | : Sink::StoreFacade<DomainType>(), mResourceAccess(resourceAccess), mDomainTypeAdaptorFactory(adaptorFactory), mResourceInstanceIdentifier(resourceIdentifier) |
39 | mDomainTypeAdaptorFactory(adaptorFactory), | ||
40 | mResourceInstanceIdentifier(resourceIdentifier) | ||
41 | { | 39 | { |
42 | if (!mResourceAccess) { | 40 | if (!mResourceAccess) { |
43 | mResourceAccess = ResourceAccessFactory::instance().getAccess(resourceIdentifier); | 41 | mResourceAccess = ResourceAccessFactory::instance().getAccess(resourceIdentifier); |
44 | } | 42 | } |
45 | } | 43 | } |
46 | 44 | ||
47 | template<class DomainType> | 45 | template <class DomainType> |
48 | GenericFacade<DomainType>::~GenericFacade() | 46 | GenericFacade<DomainType>::~GenericFacade() |
49 | { | 47 | { |
50 | } | 48 | } |
51 | 49 | ||
52 | template<class DomainType> | 50 | template <class DomainType> |
53 | QByteArray GenericFacade<DomainType>::bufferTypeForDomainType() | 51 | QByteArray GenericFacade<DomainType>::bufferTypeForDomainType() |
54 | { | 52 | { |
55 | //We happen to have a one to one mapping | 53 | // We happen to have a one to one mapping |
56 | return Sink::ApplicationDomain::getTypeName<DomainType>(); | 54 | return Sink::ApplicationDomain::getTypeName<DomainType>(); |
57 | } | 55 | } |
58 | 56 | ||
59 | template<class DomainType> | 57 | template <class DomainType> |
60 | KAsync::Job<void> GenericFacade<DomainType>::create(const DomainType &domainObject) | 58 | KAsync::Job<void> GenericFacade<DomainType>::create(const DomainType &domainObject) |
61 | { | 59 | { |
62 | if (!mDomainTypeAdaptorFactory) { | 60 | if (!mDomainTypeAdaptorFactory) { |
@@ -68,7 +66,7 @@ KAsync::Job<void> GenericFacade<DomainType>::create(const DomainType &domainObje | |||
68 | return mResourceAccess->sendCreateCommand(bufferTypeForDomainType(), BufferUtils::extractBuffer(entityFbb)); | 66 | return mResourceAccess->sendCreateCommand(bufferTypeForDomainType(), BufferUtils::extractBuffer(entityFbb)); |
69 | } | 67 | } |
70 | 68 | ||
71 | template<class DomainType> | 69 | template <class DomainType> |
72 | KAsync::Job<void> GenericFacade<DomainType>::modify(const DomainType &domainObject) | 70 | KAsync::Job<void> GenericFacade<DomainType>::modify(const DomainType &domainObject) |
73 | { | 71 | { |
74 | if (!mDomainTypeAdaptorFactory) { | 72 | if (!mDomainTypeAdaptorFactory) { |
@@ -80,16 +78,16 @@ KAsync::Job<void> GenericFacade<DomainType>::modify(const DomainType &domainObje | |||
80 | return mResourceAccess->sendModifyCommand(domainObject.identifier(), domainObject.revision(), bufferTypeForDomainType(), QByteArrayList(), BufferUtils::extractBuffer(entityFbb)); | 78 | return mResourceAccess->sendModifyCommand(domainObject.identifier(), domainObject.revision(), bufferTypeForDomainType(), QByteArrayList(), BufferUtils::extractBuffer(entityFbb)); |
81 | } | 79 | } |
82 | 80 | ||
83 | template<class DomainType> | 81 | template <class DomainType> |
84 | KAsync::Job<void> GenericFacade<DomainType>::remove(const DomainType &domainObject) | 82 | KAsync::Job<void> GenericFacade<DomainType>::remove(const DomainType &domainObject) |
85 | { | 83 | { |
86 | return mResourceAccess->sendDeleteCommand(domainObject.identifier(), domainObject.revision(), bufferTypeForDomainType()); | 84 | return mResourceAccess->sendDeleteCommand(domainObject.identifier(), domainObject.revision(), bufferTypeForDomainType()); |
87 | } | 85 | } |
88 | 86 | ||
89 | template<class DomainType> | 87 | template <class DomainType> |
90 | QPair<KAsync::Job<void>, typename ResultEmitter<typename DomainType::Ptr>::Ptr> GenericFacade<DomainType>::load(const Sink::Query &query) | 88 | QPair<KAsync::Job<void>, typename ResultEmitter<typename DomainType::Ptr>::Ptr> GenericFacade<DomainType>::load(const Sink::Query &query) |
91 | { | 89 | { |
92 | //The runner lives for the lifetime of the query | 90 | // The runner lives for the lifetime of the query |
93 | auto runner = new QueryRunner<DomainType>(query, mResourceAccess, mResourceInstanceIdentifier, mDomainTypeAdaptorFactory, bufferTypeForDomainType()); | 91 | auto runner = new QueryRunner<DomainType>(query, mResourceAccess, mResourceInstanceIdentifier, mDomainTypeAdaptorFactory, bufferTypeForDomainType()); |
94 | runner->setResultTransformation(mResultTransformation); | 92 | runner->setResultTransformation(mResultTransformation); |
95 | return qMakePair(KAsync::null<void>(), runner->emitter()); | 93 | return qMakePair(KAsync::null<void>(), runner->emitter()); |
diff --git a/common/facade.h b/common/facade.h index 99fbcdc..a24ac7a 100644 --- a/common/facade.h +++ b/common/facade.h | |||
@@ -33,8 +33,9 @@ namespace Sink { | |||
33 | 33 | ||
34 | /** | 34 | /** |
35 | * Default facade implementation for resources that are implemented in a separate process using the ResourceAccess class. | 35 | * Default facade implementation for resources that are implemented in a separate process using the ResourceAccess class. |
36 | * | 36 | * |
37 | * Ideally a basic resource has no implementation effort for the facades and can simply instanciate default implementations (meaning it only has to implement the factory with all supported types). | 37 | * Ideally a basic resource has no implementation effort for the facades and can simply instanciate default implementations (meaning it only has to implement the factory with all |
38 | * supported types). | ||
38 | * A resource has to implement: | 39 | * A resource has to implement: |
39 | * * A facade factory registering all available facades | 40 | * * A facade factory registering all available facades |
40 | * * An adaptor factory if it uses special resource buffers (default implementation can be used otherwise) | 41 | * * An adaptor factory if it uses special resource buffers (default implementation can be used otherwise) |
@@ -43,16 +44,17 @@ namespace Sink { | |||
43 | * Additionally a resource only has to provide a synchronizer plugin to execute the synchronization | 44 | * Additionally a resource only has to provide a synchronizer plugin to execute the synchronization |
44 | */ | 45 | */ |
45 | template <typename DomainType> | 46 | template <typename DomainType> |
46 | class SINK_EXPORT GenericFacade: public Sink::StoreFacade<DomainType> | 47 | class SINK_EXPORT GenericFacade : public Sink::StoreFacade<DomainType> |
47 | { | 48 | { |
48 | public: | 49 | public: |
49 | /** | 50 | /** |
50 | * Create a new GenericFacade | 51 | * Create a new GenericFacade |
51 | * | 52 | * |
52 | * @param resourceIdentifier is the identifier of the resource instance | 53 | * @param resourceIdentifier is the identifier of the resource instance |
53 | * @param adaptorFactory is the adaptor factory used to generate the mappings from domain to resource types and vice versa | 54 | * @param adaptorFactory is the adaptor factory used to generate the mappings from domain to resource types and vice versa |
54 | */ | 55 | */ |
55 | GenericFacade(const QByteArray &resourceIdentifier, const DomainTypeAdaptorFactoryInterface::Ptr &adaptorFactory = DomainTypeAdaptorFactoryInterface::Ptr(), const QSharedPointer<Sink::ResourceAccessInterface> resourceAccess = QSharedPointer<Sink::ResourceAccessInterface>()); | 56 | GenericFacade(const QByteArray &resourceIdentifier, const DomainTypeAdaptorFactoryInterface::Ptr &adaptorFactory = DomainTypeAdaptorFactoryInterface::Ptr(), |
57 | const QSharedPointer<Sink::ResourceAccessInterface> resourceAccess = QSharedPointer<Sink::ResourceAccessInterface>()); | ||
56 | ~GenericFacade(); | 58 | ~GenericFacade(); |
57 | 59 | ||
58 | static QByteArray bufferTypeForDomainType(); | 60 | static QByteArray bufferTypeForDomainType(); |
@@ -63,10 +65,9 @@ public: | |||
63 | 65 | ||
64 | protected: | 66 | protected: |
65 | std::function<void(Sink::ApplicationDomain::ApplicationDomainType &domainObject)> mResultTransformation; | 67 | std::function<void(Sink::ApplicationDomain::ApplicationDomainType &domainObject)> mResultTransformation; |
66 | //TODO use one resource access instance per application & per resource | 68 | // TODO use one resource access instance per application & per resource |
67 | QSharedPointer<Sink::ResourceAccessInterface> mResourceAccess; | 69 | QSharedPointer<Sink::ResourceAccessInterface> mResourceAccess; |
68 | DomainTypeAdaptorFactoryInterface::Ptr mDomainTypeAdaptorFactory; | 70 | DomainTypeAdaptorFactoryInterface::Ptr mDomainTypeAdaptorFactory; |
69 | QByteArray mResourceInstanceIdentifier; | 71 | QByteArray mResourceInstanceIdentifier; |
70 | }; | 72 | }; |
71 | |||
72 | } | 73 | } |
diff --git a/common/facadefactory.cpp b/common/facadefactory.cpp index d9ee5f7..ab52681 100644 --- a/common/facadefactory.cpp +++ b/common/facadefactory.cpp | |||
@@ -64,7 +64,7 @@ std::shared_ptr<void> FacadeFactory::getFacade(const QByteArray &resource, const | |||
64 | const QByteArray k = key(resource, typeName); | 64 | const QByteArray k = key(resource, typeName); |
65 | if (!mFacadeRegistry.contains(k)) { | 65 | if (!mFacadeRegistry.contains(k)) { |
66 | locker.unlock(); | 66 | locker.unlock(); |
67 | //This will call FacadeFactory::instace() internally | 67 | // This will call FacadeFactory::instace() internally |
68 | Sink::ResourceFactory::load(QString::fromLatin1(resource)); | 68 | Sink::ResourceFactory::load(QString::fromLatin1(resource)); |
69 | locker.relock(); | 69 | locker.relock(); |
70 | } | 70 | } |
diff --git a/common/facadefactory.h b/common/facadefactory.h index ef2a3f9..83b8898 100644 --- a/common/facadefactory.h +++ b/common/facadefactory.h | |||
@@ -38,7 +38,8 @@ namespace Sink { | |||
38 | * | 38 | * |
39 | * If we were to provide default implementations for certain capabilities. Here would be the place to do so. | 39 | * If we were to provide default implementations for certain capabilities. Here would be the place to do so. |
40 | */ | 40 | */ |
41 | class SINK_EXPORT FacadeFactory { | 41 | class SINK_EXPORT FacadeFactory |
42 | { | ||
42 | public: | 43 | public: |
43 | typedef std::function<std::shared_ptr<void>(const QByteArray &)> FactoryFunction; | 44 | typedef std::function<std::shared_ptr<void>(const QByteArray &)> FactoryFunction; |
44 | 45 | ||
@@ -48,10 +49,10 @@ public: | |||
48 | 49 | ||
49 | static QByteArray key(const QByteArray &resource, const QByteArray &type); | 50 | static QByteArray key(const QByteArray &resource, const QByteArray &type); |
50 | 51 | ||
51 | template<class DomainType, class Facade> | 52 | template <class DomainType, class Facade> |
52 | void registerFacade(const QByteArray &resource) | 53 | void registerFacade(const QByteArray &resource) |
53 | { | 54 | { |
54 | registerFacade(resource, [](const QByteArray &instanceIdentifier){ return std::make_shared<Facade>(instanceIdentifier); }, ApplicationDomain::getTypeName<DomainType>()); | 55 | registerFacade(resource, [](const QByteArray &instanceIdentifier) { return std::make_shared<Facade>(instanceIdentifier); }, ApplicationDomain::getTypeName<DomainType>()); |
55 | } | 56 | } |
56 | 57 | ||
57 | /* | 58 | /* |
@@ -59,7 +60,7 @@ public: | |||
59 | * | 60 | * |
60 | * Primarily for testing. | 61 | * Primarily for testing. |
61 | */ | 62 | */ |
62 | template<class DomainType, class Facade> | 63 | template <class DomainType, class Facade> |
63 | void registerFacade(const QByteArray &resource, const FactoryFunction &customFactoryFunction) | 64 | void registerFacade(const QByteArray &resource, const FactoryFunction &customFactoryFunction) |
64 | { | 65 | { |
65 | registerFacade(resource, customFactoryFunction, ApplicationDomain::getTypeName<DomainType>()); | 66 | registerFacade(resource, customFactoryFunction, ApplicationDomain::getTypeName<DomainType>()); |
@@ -72,11 +73,11 @@ public: | |||
72 | */ | 73 | */ |
73 | void resetFactory(); | 74 | void resetFactory(); |
74 | 75 | ||
75 | template<class DomainType> | 76 | template <class DomainType> |
76 | std::shared_ptr<StoreFacade<DomainType> > getFacade(const QByteArray &resource, const QByteArray &instanceIdentifier) | 77 | std::shared_ptr<StoreFacade<DomainType>> getFacade(const QByteArray &resource, const QByteArray &instanceIdentifier) |
77 | { | 78 | { |
78 | const QByteArray typeName = ApplicationDomain::getTypeName<DomainType>(); | 79 | const QByteArray typeName = ApplicationDomain::getTypeName<DomainType>(); |
79 | return std::static_pointer_cast<StoreFacade<DomainType> >(getFacade(resource, instanceIdentifier, typeName)); | 80 | return std::static_pointer_cast<StoreFacade<DomainType>>(getFacade(resource, instanceIdentifier, typeName)); |
80 | } | 81 | } |
81 | 82 | ||
82 | private: | 83 | private: |
@@ -87,6 +88,4 @@ private: | |||
87 | QHash<QByteArray, FactoryFunction> mFacadeRegistry; | 88 | QHash<QByteArray, FactoryFunction> mFacadeRegistry; |
88 | static QMutex sMutex; | 89 | static QMutex sMutex; |
89 | }; | 90 | }; |
90 | |||
91 | } | 91 | } |
92 | |||
diff --git a/common/facadeinterface.h b/common/facadeinterface.h index 17cba5e..7d5dd7d 100644 --- a/common/facadeinterface.h +++ b/common/facadeinterface.h | |||
@@ -32,17 +32,21 @@ class Query; | |||
32 | 32 | ||
33 | /** | 33 | /** |
34 | * Interface for the store facade. | 34 | * Interface for the store facade. |
35 | * | 35 | * |
36 | * All methods are synchronous. | 36 | * All methods are synchronous. |
37 | * Facades are stateful (they hold connections to resources and database). | 37 | * Facades are stateful (they hold connections to resources and database). |
38 | * | 38 | * |
39 | * TODO: would it make sense to split the write, read and notification parts? (we could potentially save some connections) | 39 | * TODO: would it make sense to split the write, read and notification parts? (we could potentially save some connections) |
40 | */ | 40 | */ |
41 | template<class DomainType> | 41 | template <class DomainType> |
42 | class StoreFacade { | 42 | class StoreFacade |
43 | { | ||
43 | public: | 44 | public: |
44 | virtual ~StoreFacade(){}; | 45 | virtual ~StoreFacade(){}; |
45 | QByteArray type() const { return ApplicationDomain::getTypeName<DomainType>(); } | 46 | QByteArray type() const |
47 | { | ||
48 | return ApplicationDomain::getTypeName<DomainType>(); | ||
49 | } | ||
46 | 50 | ||
47 | /** | 51 | /** |
48 | * Create an entity in the store. | 52 | * Create an entity in the store. |
@@ -68,11 +72,12 @@ public: | |||
68 | /** | 72 | /** |
69 | * Load entities from the store. | 73 | * Load entities from the store. |
70 | */ | 74 | */ |
71 | virtual QPair<KAsync::Job<void>, typename Sink::ResultEmitter<typename DomainType::Ptr>::Ptr > load(const Query &query) = 0; | 75 | virtual QPair<KAsync::Job<void>, typename Sink::ResultEmitter<typename DomainType::Ptr>::Ptr> load(const Query &query) = 0; |
72 | }; | 76 | }; |
73 | 77 | ||
74 | template<class DomainType> | 78 | template <class DomainType> |
75 | class NullFacade : public StoreFacade<DomainType> { | 79 | class NullFacade : public StoreFacade<DomainType> |
80 | { | ||
76 | public: | 81 | public: |
77 | virtual ~NullFacade(){}; | 82 | virtual ~NullFacade(){}; |
78 | KAsync::Job<void> create(const DomainType &domainObject) | 83 | KAsync::Job<void> create(const DomainType &domainObject) |
@@ -90,10 +95,9 @@ public: | |||
90 | return KAsync::error<void>(-1, "Failed to create a facade"); | 95 | return KAsync::error<void>(-1, "Failed to create a facade"); |
91 | } | 96 | } |
92 | 97 | ||
93 | QPair<KAsync::Job<void>, typename Sink::ResultEmitter<typename DomainType::Ptr>::Ptr > load(const Query &query) | 98 | QPair<KAsync::Job<void>, typename Sink::ResultEmitter<typename DomainType::Ptr>::Ptr> load(const Query &query) |
94 | { | 99 | { |
95 | return qMakePair(KAsync::null<void>(), typename Sink::ResultEmitter<typename DomainType::Ptr>::Ptr()); | 100 | return qMakePair(KAsync::null<void>(), typename Sink::ResultEmitter<typename DomainType::Ptr>::Ptr()); |
96 | } | 101 | } |
97 | }; | 102 | }; |
98 | |||
99 | } | 103 | } |
diff --git a/common/genericresource.cpp b/common/genericresource.cpp index 74a8cfb..9c9a12f 100644 --- a/common/genericresource.cpp +++ b/common/genericresource.cpp | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <QTime> | 20 | #include <QTime> |
21 | 21 | ||
22 | static int sBatchSize = 100; | 22 | static int sBatchSize = 100; |
23 | //This interval directly affects the roundtrip time of single commands | 23 | // This interval directly affects the roundtrip time of single commands |
24 | static int sCommitInterval = 10; | 24 | static int sCommitInterval = 10; |
25 | 25 | ||
26 | using namespace Sink; | 26 | using namespace Sink; |
@@ -39,26 +39,23 @@ class ChangeReplay : public QObject | |||
39 | { | 39 | { |
40 | Q_OBJECT | 40 | Q_OBJECT |
41 | public: | 41 | public: |
42 | |||
43 | typedef std::function<KAsync::Job<void>(const QByteArray &type, const QByteArray &key, const QByteArray &value)> ReplayFunction; | 42 | typedef std::function<KAsync::Job<void>(const QByteArray &type, const QByteArray &key, const QByteArray &value)> ReplayFunction; |
44 | 43 | ||
45 | ChangeReplay(const QString &resourceName, const ReplayFunction &replayFunction) | 44 | ChangeReplay(const QString &resourceName, const ReplayFunction &replayFunction) |
46 | : mStorage(storageLocation(), resourceName, Storage::ReadOnly), | 45 | : mStorage(storageLocation(), resourceName, Storage::ReadOnly), mChangeReplayStore(storageLocation(), resourceName + ".changereplay", Storage::ReadWrite), mReplayFunction(replayFunction) |
47 | mChangeReplayStore(storageLocation(), resourceName + ".changereplay", Storage::ReadWrite), | ||
48 | mReplayFunction(replayFunction) | ||
49 | { | 46 | { |
50 | |||
51 | } | 47 | } |
52 | 48 | ||
53 | qint64 getLastReplayedRevision() | 49 | qint64 getLastReplayedRevision() |
54 | { | 50 | { |
55 | qint64 lastReplayedRevision = 0; | 51 | qint64 lastReplayedRevision = 0; |
56 | auto replayStoreTransaction = mChangeReplayStore.createTransaction(Storage::ReadOnly); | 52 | auto replayStoreTransaction = mChangeReplayStore.createTransaction(Storage::ReadOnly); |
57 | replayStoreTransaction.openDatabase().scan("lastReplayedRevision", [&lastReplayedRevision](const QByteArray &key, const QByteArray &value) -> bool { | 53 | replayStoreTransaction.openDatabase().scan("lastReplayedRevision", |
58 | lastReplayedRevision = value.toLongLong(); | 54 | [&lastReplayedRevision](const QByteArray &key, const QByteArray &value) -> bool { |
59 | return false; | 55 | lastReplayedRevision = value.toLongLong(); |
60 | }, [](const Storage::Error &) { | 56 | return false; |
61 | }); | 57 | }, |
58 | [](const Storage::Error &) {}); | ||
62 | return lastReplayedRevision; | 59 | return lastReplayedRevision; |
63 | } | 60 | } |
64 | 61 | ||
@@ -79,28 +76,30 @@ public slots: | |||
79 | auto mainStoreTransaction = mStorage.createTransaction(Storage::ReadOnly); | 76 | auto mainStoreTransaction = mStorage.createTransaction(Storage::ReadOnly); |
80 | auto replayStoreTransaction = mChangeReplayStore.createTransaction(Storage::ReadWrite); | 77 | auto replayStoreTransaction = mChangeReplayStore.createTransaction(Storage::ReadWrite); |
81 | qint64 lastReplayedRevision = 1; | 78 | qint64 lastReplayedRevision = 1; |
82 | replayStoreTransaction.openDatabase().scan("lastReplayedRevision", [&lastReplayedRevision](const QByteArray &key, const QByteArray &value) -> bool { | 79 | replayStoreTransaction.openDatabase().scan("lastReplayedRevision", |
83 | lastReplayedRevision = value.toLongLong(); | 80 | [&lastReplayedRevision](const QByteArray &key, const QByteArray &value) -> bool { |
84 | return false; | 81 | lastReplayedRevision = value.toLongLong(); |
85 | }, [](const Storage::Error &) { | 82 | return false; |
86 | }); | 83 | }, |
84 | [](const Storage::Error &) {}); | ||
87 | const qint64 topRevision = Storage::maxRevision(mainStoreTransaction); | 85 | const qint64 topRevision = Storage::maxRevision(mainStoreTransaction); |
88 | 86 | ||
89 | Trace() << "Changereplay from " << lastReplayedRevision << " to " << topRevision; | 87 | Trace() << "Changereplay from " << lastReplayedRevision << " to " << topRevision; |
90 | if (lastReplayedRevision <= topRevision) { | 88 | if (lastReplayedRevision <= topRevision) { |
91 | qint64 revision = lastReplayedRevision; | 89 | qint64 revision = lastReplayedRevision; |
92 | for (;revision <= topRevision; revision++) { | 90 | for (; revision <= topRevision; revision++) { |
93 | const auto uid = Storage::getUidFromRevision(mainStoreTransaction, revision); | 91 | const auto uid = Storage::getUidFromRevision(mainStoreTransaction, revision); |
94 | const auto type = Storage::getTypeFromRevision(mainStoreTransaction, revision); | 92 | const auto type = Storage::getTypeFromRevision(mainStoreTransaction, revision); |
95 | const auto key = Storage::assembleKey(uid, revision); | 93 | const auto key = Storage::assembleKey(uid, revision); |
96 | Storage::mainDatabase(mainStoreTransaction, type).scan(key, [&lastReplayedRevision, type, this](const QByteArray &key, const QByteArray &value) -> bool { | 94 | Storage::mainDatabase(mainStoreTransaction, type) |
97 | mReplayFunction(type, key, value).exec(); | 95 | .scan(key, |
98 | //TODO make for loop async, and pass to async replay function together with type | 96 | [&lastReplayedRevision, type, this](const QByteArray &key, const QByteArray &value) -> bool { |
99 | Trace() << "Replaying " << key; | 97 | mReplayFunction(type, key, value).exec(); |
100 | return false; | 98 | // TODO make for loop async, and pass to async replay function together with type |
101 | }, [key](const Storage::Error &) { | 99 | Trace() << "Replaying " << key; |
102 | ErrorMsg() << "Failed to replay change " << key; | 100 | return false; |
103 | }); | 101 | }, |
102 | [key](const Storage::Error &) { ErrorMsg() << "Failed to replay change " << key; }); | ||
104 | } | 103 | } |
105 | revision--; | 104 | revision--; |
106 | replayStoreTransaction.openDatabase().write("lastReplayedRevision", QByteArray::number(revision)); | 105 | replayStoreTransaction.openDatabase().write("lastReplayedRevision", QByteArray::number(revision)); |
@@ -126,15 +125,12 @@ class CommandProcessor : public QObject | |||
126 | { | 125 | { |
127 | Q_OBJECT | 126 | Q_OBJECT |
128 | typedef std::function<KAsync::Job<void>(void const *, size_t)> InspectionFunction; | 127 | typedef std::function<KAsync::Job<void>(void const *, size_t)> InspectionFunction; |
128 | |||
129 | public: | 129 | public: |
130 | CommandProcessor(Sink::Pipeline *pipeline, QList<MessageQueue*> commandQueues) | 130 | CommandProcessor(Sink::Pipeline *pipeline, QList<MessageQueue *> commandQueues) : QObject(), mPipeline(pipeline), mCommandQueues(commandQueues), mProcessingLock(false) |
131 | : QObject(), | ||
132 | mPipeline(pipeline), | ||
133 | mCommandQueues(commandQueues), | ||
134 | mProcessingLock(false) | ||
135 | { | 131 | { |
136 | mPipeline->startTransaction(); | 132 | mPipeline->startTransaction(); |
137 | //FIXME Should be initialized to the current value of the change replay queue | 133 | // FIXME Should be initialized to the current value of the change replay queue |
138 | mLowerBoundRevision = Storage::maxRevision(mPipeline->transaction()); | 134 | mLowerBoundRevision = Storage::maxRevision(mPipeline->transaction()); |
139 | mPipeline->commit(); | 135 | mPipeline->commit(); |
140 | 136 | ||
@@ -176,18 +172,20 @@ private slots: | |||
176 | return; | 172 | return; |
177 | } | 173 | } |
178 | mProcessingLock = true; | 174 | mProcessingLock = true; |
179 | auto job = processPipeline().then<void>([this]() { | 175 | auto job = processPipeline() |
180 | mProcessingLock = false; | 176 | .then<void>([this]() { |
181 | if (messagesToProcessAvailable()) { | 177 | mProcessingLock = false; |
182 | process(); | 178 | if (messagesToProcessAvailable()) { |
183 | } | 179 | process(); |
184 | }).exec(); | 180 | } |
181 | }) | ||
182 | .exec(); | ||
185 | } | 183 | } |
186 | 184 | ||
187 | KAsync::Job<qint64> processQueuedCommand(const Sink::QueuedCommand *queuedCommand) | 185 | KAsync::Job<qint64> processQueuedCommand(const Sink::QueuedCommand *queuedCommand) |
188 | { | 186 | { |
189 | Log() << "Processing command: " << Sink::Commands::name(queuedCommand->commandId()); | 187 | Log() << "Processing command: " << Sink::Commands::name(queuedCommand->commandId()); |
190 | //Throw command into appropriate pipeline | 188 | // Throw command into appropriate pipeline |
191 | switch (queuedCommand->commandId()) { | 189 | switch (queuedCommand->commandId()) { |
192 | case Sink::Commands::DeleteEntityCommand: | 190 | case Sink::Commands::DeleteEntityCommand: |
193 | return mPipeline->deletedEntity(queuedCommand->command()->Data(), queuedCommand->command()->size()); | 191 | return mPipeline->deletedEntity(queuedCommand->command()->Data(), queuedCommand->command()->size()); |
@@ -197,9 +195,7 @@ private slots: | |||
197 | return mPipeline->newEntity(queuedCommand->command()->Data(), queuedCommand->command()->size()); | 195 | return mPipeline->newEntity(queuedCommand->command()->Data(), queuedCommand->command()->size()); |
198 | case Sink::Commands::InspectionCommand: | 196 | case Sink::Commands::InspectionCommand: |
199 | if (mInspect) { | 197 | if (mInspect) { |
200 | return mInspect(queuedCommand->command()->Data(), queuedCommand->command()->size()).then<qint64>([]() { | 198 | return mInspect(queuedCommand->command()->Data(), queuedCommand->command()->size()).then<qint64>([]() { return -1; }); |
201 | return -1; | ||
202 | }); | ||
203 | } else { | 199 | } else { |
204 | return KAsync::error<qint64>(-1, "Missing inspection command."); | 200 | return KAsync::error<qint64>(-1, "Missing inspection command."); |
205 | } | 201 | } |
@@ -218,50 +214,47 @@ private slots: | |||
218 | auto queuedCommand = Sink::GetQueuedCommand(data.constData()); | 214 | auto queuedCommand = Sink::GetQueuedCommand(data.constData()); |
219 | const auto commandId = queuedCommand->commandId(); | 215 | const auto commandId = queuedCommand->commandId(); |
220 | Trace() << "Dequeued Command: " << Sink::Commands::name(commandId); | 216 | Trace() << "Dequeued Command: " << Sink::Commands::name(commandId); |
221 | return processQueuedCommand(queuedCommand).then<qint64, qint64>( | 217 | return processQueuedCommand(queuedCommand) |
222 | [commandId](qint64 createdRevision) -> qint64 { | 218 | .then<qint64, qint64>( |
223 | Trace() << "Command pipeline processed: " << Sink::Commands::name(commandId); | 219 | [commandId](qint64 createdRevision) -> qint64 { |
224 | return createdRevision; | 220 | Trace() << "Command pipeline processed: " << Sink::Commands::name(commandId); |
225 | } | 221 | return createdRevision; |
226 | , | 222 | }, |
227 | [](int errorCode, QString errorMessage) { | 223 | [](int errorCode, QString errorMessage) { |
228 | //FIXME propagate error, we didn't handle it | 224 | // FIXME propagate error, we didn't handle it |
229 | Warning() << "Error while processing queue command: " << errorMessage; | 225 | Warning() << "Error while processing queue command: " << errorMessage; |
230 | } | 226 | }); |
231 | ); | ||
232 | } | 227 | } |
233 | 228 | ||
234 | //Process all messages of this queue | 229 | // Process all messages of this queue |
235 | KAsync::Job<void> processQueue(MessageQueue *queue) | 230 | KAsync::Job<void> processQueue(MessageQueue *queue) |
236 | { | 231 | { |
237 | auto time = QSharedPointer<QTime>::create(); | 232 | auto time = QSharedPointer<QTime>::create(); |
238 | return KAsync::start<void>([this](){ | 233 | return KAsync::start<void>([this]() { mPipeline->startTransaction(); }) |
239 | mPipeline->startTransaction(); | 234 | .then(KAsync::dowhile([queue]() { return !queue->isEmpty(); }, |
240 | }).then(KAsync::dowhile( | 235 | [this, queue, time](KAsync::Future<void> &future) { |
241 | [queue]() { return !queue->isEmpty(); }, | 236 | queue->dequeueBatch(sBatchSize, |
242 | [this, queue, time](KAsync::Future<void> &future) { | 237 | [this, time](const QByteArray &data) { |
243 | queue->dequeueBatch(sBatchSize, [this, time](const QByteArray &data) { | 238 | time->start(); |
244 | time->start(); | 239 | return KAsync::start<void>([this, data, time](KAsync::Future<void> &future) { |
245 | return KAsync::start<void>([this, data, time](KAsync::Future<void> &future) { | 240 | processQueuedCommand(data) |
246 | processQueuedCommand(data).then<void, qint64>([&future, this, time](qint64 createdRevision) { | 241 | .then<void, qint64>([&future, this, time](qint64 createdRevision) { |
247 | Trace() << "Created revision " << createdRevision << ". Processing took: " << Log::TraceTime(time->elapsed()); | 242 | Trace() << "Created revision " << createdRevision << ". Processing took: " << Log::TraceTime(time->elapsed()); |
243 | future.setFinished(); | ||
244 | }) | ||
245 | .exec(); | ||
246 | }); | ||
247 | }) | ||
248 | .then<void>([&future, queue]() { future.setFinished(); }, | ||
249 | [&future](int i, QString error) { | ||
250 | if (i != MessageQueue::ErrorCodes::NoMessageFound) { | ||
251 | Warning() << "Error while getting message from messagequeue: " << error; | ||
252 | } | ||
248 | future.setFinished(); | 253 | future.setFinished(); |
249 | }).exec(); | 254 | }) |
250 | }); | 255 | .exec(); |
251 | } | 256 | })) |
252 | ).then<void>([&future, queue](){ | 257 | .then<void>([this]() { mPipeline->commit(); }); |
253 | future.setFinished(); | ||
254 | }, | ||
255 | [&future](int i, QString error) { | ||
256 | if (i != MessageQueue::ErrorCodes::NoMessageFound) { | ||
257 | Warning() << "Error while getting message from messagequeue: " << error; | ||
258 | } | ||
259 | future.setFinished(); | ||
260 | }).exec(); | ||
261 | } | ||
262 | )).then<void>([this]() { | ||
263 | mPipeline->commit(); | ||
264 | }); | ||
265 | } | 258 | } |
266 | 259 | ||
267 | KAsync::Job<void> processPipeline() | 260 | KAsync::Job<void> processPipeline() |
@@ -276,29 +269,29 @@ private slots: | |||
276 | mPipeline->commit(); | 269 | mPipeline->commit(); |
277 | Trace() << "Cleanup done." << Log::TraceTime(time->elapsed()); | 270 | Trace() << "Cleanup done." << Log::TraceTime(time->elapsed()); |
278 | 271 | ||
279 | //Go through all message queues | 272 | // Go through all message queues |
280 | auto it = QSharedPointer<QListIterator<MessageQueue*> >::create(mCommandQueues); | 273 | auto it = QSharedPointer<QListIterator<MessageQueue *>>::create(mCommandQueues); |
281 | return KAsync::dowhile( | 274 | return KAsync::dowhile([it]() { return it->hasNext(); }, |
282 | [it]() { return it->hasNext(); }, | ||
283 | [it, this](KAsync::Future<void> &future) { | 275 | [it, this](KAsync::Future<void> &future) { |
284 | auto time = QSharedPointer<QTime>::create(); | 276 | auto time = QSharedPointer<QTime>::create(); |
285 | time->start(); | 277 | time->start(); |
286 | 278 | ||
287 | auto queue = it->next(); | 279 | auto queue = it->next(); |
288 | processQueue(queue).then<void>([&future, time]() { | 280 | processQueue(queue) |
289 | Trace() << "Queue processed." << Log::TraceTime(time->elapsed()); | 281 | .then<void>([&future, time]() { |
290 | future.setFinished(); | 282 | Trace() << "Queue processed." << Log::TraceTime(time->elapsed()); |
291 | }).exec(); | 283 | future.setFinished(); |
292 | } | 284 | }) |
293 | ); | 285 | .exec(); |
286 | }); | ||
294 | } | 287 | } |
295 | 288 | ||
296 | private: | 289 | private: |
297 | Sink::Pipeline *mPipeline; | 290 | Sink::Pipeline *mPipeline; |
298 | //Ordered by priority | 291 | // Ordered by priority |
299 | QList<MessageQueue*> mCommandQueues; | 292 | QList<MessageQueue *> mCommandQueues; |
300 | bool mProcessingLock; | 293 | bool mProcessingLock; |
301 | //The lowest revision we no longer need | 294 | // The lowest revision we no longer need |
302 | qint64 mLowerBoundRevision; | 295 | qint64 mLowerBoundRevision; |
303 | InspectionFunction mInspect; | 296 | InspectionFunction mInspect; |
304 | }; | 297 | }; |
@@ -308,14 +301,14 @@ private: | |||
308 | 301 | ||
309 | GenericResource::GenericResource(const QByteArray &resourceInstanceIdentifier, const QSharedPointer<Pipeline> &pipeline) | 302 | GenericResource::GenericResource(const QByteArray &resourceInstanceIdentifier, const QSharedPointer<Pipeline> &pipeline) |
310 | : Sink::Resource(), | 303 | : Sink::Resource(), |
311 | mUserQueue(Sink::storageLocation(), resourceInstanceIdentifier + ".userqueue"), | 304 | mUserQueue(Sink::storageLocation(), resourceInstanceIdentifier + ".userqueue"), |
312 | mSynchronizerQueue(Sink::storageLocation(), resourceInstanceIdentifier + ".synchronizerqueue"), | 305 | mSynchronizerQueue(Sink::storageLocation(), resourceInstanceIdentifier + ".synchronizerqueue"), |
313 | mResourceInstanceIdentifier(resourceInstanceIdentifier), | 306 | mResourceInstanceIdentifier(resourceInstanceIdentifier), |
314 | mPipeline(pipeline ? pipeline : QSharedPointer<Sink::Pipeline>::create(resourceInstanceIdentifier)), | 307 | mPipeline(pipeline ? pipeline : QSharedPointer<Sink::Pipeline>::create(resourceInstanceIdentifier)), |
315 | mError(0), | 308 | mError(0), |
316 | mClientLowerBoundRevision(std::numeric_limits<qint64>::max()) | 309 | mClientLowerBoundRevision(std::numeric_limits<qint64>::max()) |
317 | { | 310 | { |
318 | mProcessor = new CommandProcessor(mPipeline.data(), QList<MessageQueue*>() << &mUserQueue << &mSynchronizerQueue); | 311 | mProcessor = new CommandProcessor(mPipeline.data(), QList<MessageQueue *>() << &mUserQueue << &mSynchronizerQueue); |
319 | mProcessor->setInspectionCommand([this](void const *command, size_t size) { | 312 | mProcessor->setInspectionCommand([this](void const *command, size_t size) { |
320 | flatbuffers::Verifier verifier((const uint8_t *)command, size); | 313 | flatbuffers::Verifier verifier((const uint8_t *)command, size); |
321 | if (Sink::Commands::VerifyInspectionBuffer(verifier)) { | 314 | if (Sink::Commands::VerifyInspectionBuffer(verifier)) { |
@@ -330,22 +323,26 @@ GenericResource::GenericResource(const QByteArray &resourceInstanceIdentifier, c | |||
330 | QDataStream s(expectedValueString); | 323 | QDataStream s(expectedValueString); |
331 | QVariant expectedValue; | 324 | QVariant expectedValue; |
332 | s >> expectedValue; | 325 | s >> expectedValue; |
333 | inspect(inspectionType, inspectionId, domainType, entityId, property, expectedValue).then<void>([=]() { | 326 | inspect(inspectionType, inspectionId, domainType, entityId, property, expectedValue) |
334 | Log_area("resource.inspection") << "Inspection was successful: " << inspectionType << inspectionId << entityId; | 327 | .then<void>( |
335 | Sink::Notification n; | 328 | [=]() { |
336 | n.type = Sink::Commands::NotificationType_Inspection; | 329 | Log_area("resource.inspection") << "Inspection was successful: " << inspectionType << inspectionId << entityId; |
337 | n.id = inspectionId; | 330 | Sink::Notification n; |
338 | n.code = Sink::Commands::NotificationCode_Success; | 331 | n.type = Sink::Commands::NotificationType_Inspection; |
339 | emit notify(n); | 332 | n.id = inspectionId; |
340 | }, [=](int code, const QString &message) { | 333 | n.code = Sink::Commands::NotificationCode_Success; |
341 | Log() << "Inspection failed: "<< inspectionType << inspectionId << entityId << message; | 334 | emit notify(n); |
342 | Sink::Notification n; | 335 | }, |
343 | n.type = Sink::Commands::NotificationType_Inspection; | 336 | [=](int code, const QString &message) { |
344 | n.message = message; | 337 | Log() << "Inspection failed: " << inspectionType << inspectionId << entityId << message; |
345 | n.id = inspectionId; | 338 | Sink::Notification n; |
346 | n.code = Sink::Commands::NotificationCode_Failure; | 339 | n.type = Sink::Commands::NotificationType_Inspection; |
347 | emit notify(n); | 340 | n.message = message; |
348 | }).exec(); | 341 | n.id = inspectionId; |
342 | n.code = Sink::Commands::NotificationCode_Failure; | ||
343 | emit notify(n); | ||
344 | }) | ||
345 | .exec(); | ||
349 | return KAsync::null<void>(); | 346 | return KAsync::null<void>(); |
350 | } | 347 | } |
351 | return KAsync::error<void>(-1, "Invalid inspection command."); | 348 | return KAsync::error<void>(-1, "Invalid inspection command."); |
@@ -353,9 +350,9 @@ GenericResource::GenericResource(const QByteArray &resourceInstanceIdentifier, c | |||
353 | QObject::connect(mProcessor, &CommandProcessor::error, [this](int errorCode, const QString &msg) { onProcessorError(errorCode, msg); }); | 350 | QObject::connect(mProcessor, &CommandProcessor::error, [this](int errorCode, const QString &msg) { onProcessorError(errorCode, msg); }); |
354 | QObject::connect(mPipeline.data(), &Pipeline::revisionUpdated, this, &Resource::revisionUpdated); | 351 | QObject::connect(mPipeline.data(), &Pipeline::revisionUpdated, this, &Resource::revisionUpdated); |
355 | mSourceChangeReplay = new ChangeReplay(resourceInstanceIdentifier, [this](const QByteArray &type, const QByteArray &key, const QByteArray &value) { | 352 | mSourceChangeReplay = new ChangeReplay(resourceInstanceIdentifier, [this](const QByteArray &type, const QByteArray &key, const QByteArray &value) { |
356 | //This results in a deadlock when a sync is in progress and we try to create a second writing transaction (which is why we turn changereplay off during the sync) | 353 | // This results in a deadlock when a sync is in progress and we try to create a second writing transaction (which is why we turn changereplay off during the sync) |
357 | auto synchronizationStore = QSharedPointer<Sink::Storage>::create(Sink::storageLocation(), mResourceInstanceIdentifier + ".synchronization", Sink::Storage::ReadWrite); | 354 | auto synchronizationStore = QSharedPointer<Sink::Storage>::create(Sink::storageLocation(), mResourceInstanceIdentifier + ".synchronization", Sink::Storage::ReadWrite); |
358 | return this->replay(*synchronizationStore, type, key, value).then<void>([synchronizationStore](){}); | 355 | return this->replay(*synchronizationStore, type, key, value).then<void>([synchronizationStore]() {}); |
359 | }); | 356 | }); |
360 | enableChangeReplay(true); | 357 | enableChangeReplay(true); |
361 | mClientLowerBoundRevision = mPipeline->cleanedUpRevision(); | 358 | mClientLowerBoundRevision = mPipeline->cleanedUpRevision(); |
@@ -372,7 +369,8 @@ GenericResource::~GenericResource() | |||
372 | delete mSourceChangeReplay; | 369 | delete mSourceChangeReplay; |
373 | } | 370 | } |
374 | 371 | ||
375 | KAsync::Job<void> GenericResource::inspect(int inspectionType, const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expectedValue) | 372 | KAsync::Job<void> GenericResource::inspect( |
373 | int inspectionType, const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expectedValue) | ||
376 | { | 374 | { |
377 | Warning() << "Inspection not implemented"; | 375 | Warning() << "Inspection not implemented"; |
378 | return KAsync::null<void>(); | 376 | return KAsync::null<void>(); |
@@ -390,7 +388,7 @@ void GenericResource::enableChangeReplay(bool enable) | |||
390 | } | 388 | } |
391 | } | 389 | } |
392 | 390 | ||
393 | void GenericResource::addType(const QByteArray &type, DomainTypeAdaptorFactoryInterface::Ptr factory, const QVector<Sink::Preprocessor*> &preprocessors) | 391 | void GenericResource::addType(const QByteArray &type, DomainTypeAdaptorFactoryInterface::Ptr factory, const QVector<Sink::Preprocessor *> &preprocessors) |
394 | { | 392 | { |
395 | mPipeline->setPreprocessors(type, preprocessors); | 393 | mPipeline->setPreprocessors(type, preprocessors); |
396 | mPipeline->setAdaptorFactory(type, factory); | 394 | mPipeline->setAdaptorFactory(type, factory); |
@@ -463,14 +461,16 @@ KAsync::Job<void> GenericResource::synchronizeWithSource() | |||
463 | { | 461 | { |
464 | return KAsync::start<void>([this]() { | 462 | return KAsync::start<void>([this]() { |
465 | Log() << " Synchronizing"; | 463 | Log() << " Synchronizing"; |
466 | //Changereplay would deadlock otherwise when trying to open the synchronization store | 464 | // Changereplay would deadlock otherwise when trying to open the synchronization store |
467 | enableChangeReplay(false); | 465 | enableChangeReplay(false); |
468 | auto mainStore = QSharedPointer<Sink::Storage>::create(Sink::storageLocation(), mResourceInstanceIdentifier, Sink::Storage::ReadOnly); | 466 | auto mainStore = QSharedPointer<Sink::Storage>::create(Sink::storageLocation(), mResourceInstanceIdentifier, Sink::Storage::ReadOnly); |
469 | auto syncStore = QSharedPointer<Sink::Storage>::create(Sink::storageLocation(), mResourceInstanceIdentifier + ".synchronization", Sink::Storage::ReadWrite); | 467 | auto syncStore = QSharedPointer<Sink::Storage>::create(Sink::storageLocation(), mResourceInstanceIdentifier + ".synchronization", Sink::Storage::ReadWrite); |
470 | synchronizeWithSource(*mainStore, *syncStore).then<void>([this, mainStore, syncStore]() { | 468 | synchronizeWithSource(*mainStore, *syncStore) |
471 | Log() << "Done Synchronizing"; | 469 | .then<void>([this, mainStore, syncStore]() { |
472 | enableChangeReplay(true); | 470 | Log() << "Done Synchronizing"; |
473 | }).exec(); | 471 | enableChangeReplay(true); |
472 | }) | ||
473 | .exec(); | ||
474 | }); | 474 | }); |
475 | } | 475 | } |
476 | 476 | ||
@@ -484,42 +484,39 @@ static void waitForDrained(KAsync::Future<void> &f, MessageQueue &queue) | |||
484 | if (queue.isEmpty()) { | 484 | if (queue.isEmpty()) { |
485 | f.setFinished(); | 485 | f.setFinished(); |
486 | } else { | 486 | } else { |
487 | QObject::connect(&queue, &MessageQueue::drained, [&f]() { | 487 | QObject::connect(&queue, &MessageQueue::drained, [&f]() { f.setFinished(); }); |
488 | f.setFinished(); | ||
489 | }); | ||
490 | } | 488 | } |
491 | }; | 489 | }; |
492 | 490 | ||
493 | KAsync::Job<void> GenericResource::processAllMessages() | 491 | KAsync::Job<void> GenericResource::processAllMessages() |
494 | { | 492 | { |
495 | //We have to wait for all items to be processed to ensure the synced items are available when a query gets executed. | 493 | // We have to wait for all items to be processed to ensure the synced items are available when a query gets executed. |
496 | //TODO: report errors while processing sync? | 494 | // TODO: report errors while processing sync? |
497 | //TODO JOBAPI: A helper that waits for n events and then continues? | 495 | // TODO JOBAPI: A helper that waits for n events and then continues? |
498 | return KAsync::start<void>([this](KAsync::Future<void> &f) { | 496 | return KAsync::start<void>([this](KAsync::Future<void> &f) { |
499 | if (mCommitQueueTimer.isActive()) { | 497 | if (mCommitQueueTimer.isActive()) { |
500 | auto context = new QObject; | 498 | auto context = new QObject; |
501 | QObject::connect(&mCommitQueueTimer, &QTimer::timeout, context, [&f, context]() { | 499 | QObject::connect(&mCommitQueueTimer, &QTimer::timeout, context, [&f, context]() { |
502 | delete context; | 500 | delete context; |
501 | f.setFinished(); | ||
502 | }); | ||
503 | } else { | ||
504 | f.setFinished(); | ||
505 | } | ||
506 | }) | ||
507 | .then<void>([this](KAsync::Future<void> &f) { waitForDrained(f, mSynchronizerQueue); }) | ||
508 | .then<void>([this](KAsync::Future<void> &f) { waitForDrained(f, mUserQueue); }) | ||
509 | .then<void>([this](KAsync::Future<void> &f) { | ||
510 | if (mSourceChangeReplay->allChangesReplayed()) { | ||
503 | f.setFinished(); | 511 | f.setFinished(); |
504 | }); | 512 | } else { |
505 | } else { | 513 | auto context = new QObject; |
506 | f.setFinished(); | 514 | QObject::connect(mSourceChangeReplay, &ChangeReplay::changesReplayed, context, [&f, context]() { |
507 | } | 515 | delete context; |
508 | }).then<void>([this](KAsync::Future<void> &f) { | 516 | f.setFinished(); |
509 | waitForDrained(f, mSynchronizerQueue); | 517 | }); |
510 | }).then<void>([this](KAsync::Future<void> &f) { | 518 | } |
511 | waitForDrained(f, mUserQueue); | 519 | }); |
512 | }).then<void>([this](KAsync::Future<void> &f) { | ||
513 | if (mSourceChangeReplay->allChangesReplayed()) { | ||
514 | f.setFinished(); | ||
515 | } else { | ||
516 | auto context = new QObject; | ||
517 | QObject::connect(mSourceChangeReplay, &ChangeReplay::changesReplayed, context, [&f, context]() { | ||
518 | delete context; | ||
519 | f.setFinished(); | ||
520 | }); | ||
521 | } | ||
522 | }); | ||
523 | } | 520 | } |
524 | 521 | ||
525 | void GenericResource::updateLowerBoundRevision() | 522 | void GenericResource::updateLowerBoundRevision() |
@@ -533,14 +530,15 @@ void GenericResource::setLowerBoundRevision(qint64 revision) | |||
533 | updateLowerBoundRevision(); | 530 | updateLowerBoundRevision(); |
534 | } | 531 | } |
535 | 532 | ||
536 | void GenericResource::createEntity(const QByteArray &sinkId, const QByteArray &bufferType, const Sink::ApplicationDomain::ApplicationDomainType &domainObject, DomainTypeAdaptorFactoryInterface &adaptorFactory, std::function<void(const QByteArray &)> callback) | 533 | void GenericResource::createEntity(const QByteArray &sinkId, const QByteArray &bufferType, const Sink::ApplicationDomain::ApplicationDomainType &domainObject, |
534 | DomainTypeAdaptorFactoryInterface &adaptorFactory, std::function<void(const QByteArray &)> callback) | ||
537 | { | 535 | { |
538 | //These changes are coming from the source | 536 | // These changes are coming from the source |
539 | const auto replayToSource = false; | 537 | const auto replayToSource = false; |
540 | flatbuffers::FlatBufferBuilder entityFbb; | 538 | flatbuffers::FlatBufferBuilder entityFbb; |
541 | adaptorFactory.createBuffer(domainObject, entityFbb); | 539 | adaptorFactory.createBuffer(domainObject, entityFbb); |
542 | flatbuffers::FlatBufferBuilder fbb; | 540 | flatbuffers::FlatBufferBuilder fbb; |
543 | //This is the resource type and not the domain type | 541 | // This is the resource type and not the domain type |
544 | auto entityId = fbb.CreateString(sinkId.toStdString()); | 542 | auto entityId = fbb.CreateString(sinkId.toStdString()); |
545 | auto type = fbb.CreateString(bufferType.toStdString()); | 543 | auto type = fbb.CreateString(bufferType.toStdString()); |
546 | auto delta = Sink::EntityBuffer::appendAsVector(fbb, entityFbb.GetBufferPointer(), entityFbb.GetSize()); | 544 | auto delta = Sink::EntityBuffer::appendAsVector(fbb, entityFbb.GetBufferPointer(), entityFbb.GetSize()); |
@@ -549,18 +547,19 @@ void GenericResource::createEntity(const QByteArray &sinkId, const QByteArray &b | |||
549 | callback(BufferUtils::extractBuffer(fbb)); | 547 | callback(BufferUtils::extractBuffer(fbb)); |
550 | } | 548 | } |
551 | 549 | ||
552 | void GenericResource::modifyEntity(const QByteArray &sinkId, qint64 revision, const QByteArray &bufferType, const Sink::ApplicationDomain::ApplicationDomainType &domainObject, DomainTypeAdaptorFactoryInterface &adaptorFactory, std::function<void(const QByteArray &)> callback) | 550 | void GenericResource::modifyEntity(const QByteArray &sinkId, qint64 revision, const QByteArray &bufferType, const Sink::ApplicationDomain::ApplicationDomainType &domainObject, |
551 | DomainTypeAdaptorFactoryInterface &adaptorFactory, std::function<void(const QByteArray &)> callback) | ||
553 | { | 552 | { |
554 | //These changes are coming from the source | 553 | // These changes are coming from the source |
555 | const auto replayToSource = false; | 554 | const auto replayToSource = false; |
556 | flatbuffers::FlatBufferBuilder entityFbb; | 555 | flatbuffers::FlatBufferBuilder entityFbb; |
557 | adaptorFactory.createBuffer(domainObject, entityFbb); | 556 | adaptorFactory.createBuffer(domainObject, entityFbb); |
558 | flatbuffers::FlatBufferBuilder fbb; | 557 | flatbuffers::FlatBufferBuilder fbb; |
559 | auto entityId = fbb.CreateString(sinkId.toStdString()); | 558 | auto entityId = fbb.CreateString(sinkId.toStdString()); |
560 | //This is the resource type and not the domain type | 559 | // This is the resource type and not the domain type |
561 | auto type = fbb.CreateString(bufferType.toStdString()); | 560 | auto type = fbb.CreateString(bufferType.toStdString()); |
562 | auto delta = Sink::EntityBuffer::appendAsVector(fbb, entityFbb.GetBufferPointer(), entityFbb.GetSize()); | 561 | auto delta = Sink::EntityBuffer::appendAsVector(fbb, entityFbb.GetBufferPointer(), entityFbb.GetSize()); |
563 | //TODO removals | 562 | // TODO removals |
564 | auto location = Sink::Commands::CreateModifyEntity(fbb, revision, entityId, 0, type, delta, replayToSource); | 563 | auto location = Sink::Commands::CreateModifyEntity(fbb, revision, entityId, 0, type, delta, replayToSource); |
565 | Sink::Commands::FinishModifyEntityBuffer(fbb, location); | 564 | Sink::Commands::FinishModifyEntityBuffer(fbb, location); |
566 | callback(BufferUtils::extractBuffer(fbb)); | 565 | callback(BufferUtils::extractBuffer(fbb)); |
@@ -568,11 +567,11 @@ void GenericResource::modifyEntity(const QByteArray &sinkId, qint64 revision, co | |||
568 | 567 | ||
569 | void GenericResource::deleteEntity(const QByteArray &sinkId, qint64 revision, const QByteArray &bufferType, std::function<void(const QByteArray &)> callback) | 568 | void GenericResource::deleteEntity(const QByteArray &sinkId, qint64 revision, const QByteArray &bufferType, std::function<void(const QByteArray &)> callback) |
570 | { | 569 | { |
571 | //These changes are coming from the source | 570 | // These changes are coming from the source |
572 | const auto replayToSource = false; | 571 | const auto replayToSource = false; |
573 | flatbuffers::FlatBufferBuilder fbb; | 572 | flatbuffers::FlatBufferBuilder fbb; |
574 | auto entityId = fbb.CreateString(sinkId.toStdString()); | 573 | auto entityId = fbb.CreateString(sinkId.toStdString()); |
575 | //This is the resource type and not the domain type | 574 | // This is the resource type and not the domain type |
576 | auto type = fbb.CreateString(bufferType.toStdString()); | 575 | auto type = fbb.CreateString(bufferType.toStdString()); |
577 | auto location = Sink::Commands::CreateDeleteEntity(fbb, revision, entityId, type, replayToSource); | 576 | auto location = Sink::Commands::CreateDeleteEntity(fbb, revision, entityId, type, replayToSource); |
578 | Sink::Commands::FinishDeleteEntityBuffer(fbb, location); | 577 | Sink::Commands::FinishDeleteEntityBuffer(fbb, location); |
@@ -581,7 +580,8 @@ void GenericResource::deleteEntity(const QByteArray &sinkId, qint64 revision, co | |||
581 | 580 | ||
582 | void GenericResource::recordRemoteId(const QByteArray &bufferType, const QByteArray &localId, const QByteArray &remoteId, Sink::Storage::Transaction &transaction) | 581 | void GenericResource::recordRemoteId(const QByteArray &bufferType, const QByteArray &localId, const QByteArray &remoteId, Sink::Storage::Transaction &transaction) |
583 | { | 582 | { |
584 | Index("rid.mapping." + bufferType, transaction).add(remoteId, localId);; | 583 | Index("rid.mapping." + bufferType, transaction).add(remoteId, localId); |
584 | ; | ||
585 | Index("localid.mapping." + bufferType, transaction).add(localId, remoteId); | 585 | Index("localid.mapping." + bufferType, transaction).add(localId, remoteId); |
586 | } | 586 | } |
587 | 587 | ||
@@ -600,7 +600,7 @@ void GenericResource::updateRemoteId(const QByteArray &bufferType, const QByteAr | |||
600 | 600 | ||
601 | QByteArray GenericResource::resolveRemoteId(const QByteArray &bufferType, const QByteArray &remoteId, Sink::Storage::Transaction &transaction) | 601 | QByteArray GenericResource::resolveRemoteId(const QByteArray &bufferType, const QByteArray &remoteId, Sink::Storage::Transaction &transaction) |
602 | { | 602 | { |
603 | //Lookup local id for remote id, or insert a new pair otherwise | 603 | // Lookup local id for remote id, or insert a new pair otherwise |
604 | Index index("rid.mapping." + bufferType, transaction); | 604 | Index index("rid.mapping." + bufferType, transaction); |
605 | QByteArray sinkId = index.lookup(remoteId); | 605 | QByteArray sinkId = index.lookup(remoteId); |
606 | if (sinkId.isEmpty()) { | 606 | if (sinkId.isEmpty()) { |
@@ -621,19 +621,19 @@ QByteArray GenericResource::resolveLocalId(const QByteArray &bufferType, const Q | |||
621 | return remoteId; | 621 | return remoteId; |
622 | } | 622 | } |
623 | 623 | ||
624 | void GenericResource::scanForRemovals(Sink::Storage::Transaction &transaction, Sink::Storage::Transaction &synchronizationTransaction, const QByteArray &bufferType, const std::function<void(const std::function<void(const QByteArray &key)> &callback)> &entryGenerator, std::function<bool(const QByteArray &remoteId)> exists) | 624 | void GenericResource::scanForRemovals(Sink::Storage::Transaction &transaction, Sink::Storage::Transaction &synchronizationTransaction, const QByteArray &bufferType, |
625 | const std::function<void(const std::function<void(const QByteArray &key)> &callback)> &entryGenerator, std::function<bool(const QByteArray &remoteId)> exists) | ||
625 | { | 626 | { |
626 | entryGenerator([this, &transaction, bufferType, &synchronizationTransaction, &exists](const QByteArray &key) { | 627 | entryGenerator([this, &transaction, bufferType, &synchronizationTransaction, &exists](const QByteArray &key) { |
627 | auto sinkId = Sink::Storage::uidFromKey(key); | 628 | auto sinkId = Sink::Storage::uidFromKey(key); |
628 | Trace() << "Checking for removal " << key; | 629 | Trace() << "Checking for removal " << key; |
629 | const auto remoteId = resolveLocalId(bufferType, sinkId, synchronizationTransaction); | 630 | const auto remoteId = resolveLocalId(bufferType, sinkId, synchronizationTransaction); |
630 | //If we have no remoteId, the entity hasn't been replayed to the source yet | 631 | // If we have no remoteId, the entity hasn't been replayed to the source yet |
631 | if (!remoteId.isEmpty()) { | 632 | if (!remoteId.isEmpty()) { |
632 | if (!exists(remoteId)) { | 633 | if (!exists(remoteId)) { |
633 | Trace() << "Found a removed entity: " << sinkId; | 634 | Trace() << "Found a removed entity: " << sinkId; |
634 | deleteEntity(sinkId, Sink::Storage::maxRevision(transaction), bufferType, [this](const QByteArray &buffer) { | 635 | deleteEntity(sinkId, Sink::Storage::maxRevision(transaction), bufferType, |
635 | enqueueCommand(mSynchronizerQueue, Sink::Commands::DeleteEntityCommand, buffer); | 636 | [this](const QByteArray &buffer) { enqueueCommand(mSynchronizerQueue, Sink::Commands::DeleteEntityCommand, buffer); }); |
636 | }); | ||
637 | } | 637 | } |
638 | } | 638 | } |
639 | }); | 639 | }); |
@@ -642,32 +642,31 @@ void GenericResource::scanForRemovals(Sink::Storage::Transaction &transaction, S | |||
642 | static QSharedPointer<Sink::ApplicationDomain::BufferAdaptor> getLatest(const Sink::Storage::NamedDatabase &db, const QByteArray &uid, DomainTypeAdaptorFactoryInterface &adaptorFactory) | 642 | static QSharedPointer<Sink::ApplicationDomain::BufferAdaptor> getLatest(const Sink::Storage::NamedDatabase &db, const QByteArray &uid, DomainTypeAdaptorFactoryInterface &adaptorFactory) |
643 | { | 643 | { |
644 | QSharedPointer<Sink::ApplicationDomain::BufferAdaptor> current; | 644 | QSharedPointer<Sink::ApplicationDomain::BufferAdaptor> current; |
645 | db.findLatest(uid, [¤t, &adaptorFactory](const QByteArray &key, const QByteArray &data) -> bool { | 645 | db.findLatest(uid, |
646 | Sink::EntityBuffer buffer(const_cast<const char *>(data.data()), data.size()); | 646 | [¤t, &adaptorFactory](const QByteArray &key, const QByteArray &data) -> bool { |
647 | if (!buffer.isValid()) { | 647 | Sink::EntityBuffer buffer(const_cast<const char *>(data.data()), data.size()); |
648 | Warning() << "Read invalid buffer from disk"; | 648 | if (!buffer.isValid()) { |
649 | } else { | 649 | Warning() << "Read invalid buffer from disk"; |
650 | current = adaptorFactory.createAdaptor(buffer.entity()); | 650 | } else { |
651 | } | 651 | current = adaptorFactory.createAdaptor(buffer.entity()); |
652 | return false; | 652 | } |
653 | }, | 653 | return false; |
654 | [](const Sink::Storage::Error &error) { | 654 | }, |
655 | Warning() << "Failed to read current value from storage: " << error.message; | 655 | [](const Sink::Storage::Error &error) { Warning() << "Failed to read current value from storage: " << error.message; }); |
656 | }); | ||
657 | return current; | 656 | return current; |
658 | } | 657 | } |
659 | 658 | ||
660 | void GenericResource::createOrModify(Sink::Storage::Transaction &transaction, Sink::Storage::Transaction &synchronizationTransaction, DomainTypeAdaptorFactoryInterface &adaptorFactory, const QByteArray &bufferType, const QByteArray &remoteId, const Sink::ApplicationDomain::ApplicationDomainType &entity) | 659 | void GenericResource::createOrModify(Sink::Storage::Transaction &transaction, Sink::Storage::Transaction &synchronizationTransaction, |
660 | DomainTypeAdaptorFactoryInterface &adaptorFactory, const QByteArray &bufferType, const QByteArray &remoteId, const Sink::ApplicationDomain::ApplicationDomainType &entity) | ||
661 | { | 661 | { |
662 | auto mainDatabase = Storage::mainDatabase(transaction, bufferType); | 662 | auto mainDatabase = Storage::mainDatabase(transaction, bufferType); |
663 | const auto sinkId = resolveRemoteId(bufferType, remoteId, synchronizationTransaction); | 663 | const auto sinkId = resolveRemoteId(bufferType, remoteId, synchronizationTransaction); |
664 | const auto found = mainDatabase.contains(sinkId); | 664 | const auto found = mainDatabase.contains(sinkId); |
665 | if (!found) { | 665 | if (!found) { |
666 | Trace() << "Found a new entity: " << remoteId; | 666 | Trace() << "Found a new entity: " << remoteId; |
667 | createEntity(sinkId, bufferType, entity, adaptorFactory, [this](const QByteArray &buffer) { | 667 | createEntity( |
668 | enqueueCommand(mSynchronizerQueue, Sink::Commands::CreateEntityCommand, buffer); | 668 | sinkId, bufferType, entity, adaptorFactory, [this](const QByteArray &buffer) { enqueueCommand(mSynchronizerQueue, Sink::Commands::CreateEntityCommand, buffer); }); |
669 | }); | 669 | } else { // modification |
670 | } else { //modification | ||
671 | if (auto current = getLatest(mainDatabase, sinkId, adaptorFactory)) { | 670 | if (auto current = getLatest(mainDatabase, sinkId, adaptorFactory)) { |
672 | bool changed = false; | 671 | bool changed = false; |
673 | for (const auto &property : entity.changedProperties()) { | 672 | for (const auto &property : entity.changedProperties()) { |
@@ -678,9 +677,8 @@ void GenericResource::createOrModify(Sink::Storage::Transaction &transaction, Si | |||
678 | } | 677 | } |
679 | if (changed) { | 678 | if (changed) { |
680 | Trace() << "Found a modified entity: " << remoteId; | 679 | Trace() << "Found a modified entity: " << remoteId; |
681 | modifyEntity(sinkId, Sink::Storage::maxRevision(transaction), bufferType, entity, adaptorFactory, [this](const QByteArray &buffer) { | 680 | modifyEntity(sinkId, Sink::Storage::maxRevision(transaction), bufferType, entity, adaptorFactory, |
682 | enqueueCommand(mSynchronizerQueue, Sink::Commands::ModifyEntityCommand, buffer); | 681 | [this](const QByteArray &buffer) { enqueueCommand(mSynchronizerQueue, Sink::Commands::ModifyEntityCommand, buffer); }); |
683 | }); | ||
684 | } | 682 | } |
685 | } else { | 683 | } else { |
686 | Warning() << "Failed to get current entity"; | 684 | Warning() << "Failed to get current entity"; |
diff --git a/common/genericresource.h b/common/genericresource.h index b9bb994..9665d6b 100644 --- a/common/genericresource.h +++ b/common/genericresource.h | |||
@@ -29,8 +29,7 @@ | |||
29 | class CommandProcessor; | 29 | class CommandProcessor; |
30 | class ChangeReplay; | 30 | class ChangeReplay; |
31 | 31 | ||
32 | namespace Sink | 32 | namespace Sink { |
33 | { | ||
34 | class Pipeline; | 33 | class Pipeline; |
35 | class Preprocessor; | 34 | class Preprocessor; |
36 | 35 | ||
@@ -48,7 +47,8 @@ public: | |||
48 | virtual KAsync::Job<void> synchronizeWithSource(Sink::Storage &mainStore, Sink::Storage &synchronizationStore); | 47 | virtual KAsync::Job<void> synchronizeWithSource(Sink::Storage &mainStore, Sink::Storage &synchronizationStore); |
49 | virtual KAsync::Job<void> processAllMessages() Q_DECL_OVERRIDE; | 48 | virtual KAsync::Job<void> processAllMessages() Q_DECL_OVERRIDE; |
50 | virtual void setLowerBoundRevision(qint64 revision) Q_DECL_OVERRIDE; | 49 | virtual void setLowerBoundRevision(qint64 revision) Q_DECL_OVERRIDE; |
51 | virtual KAsync::Job<void> inspect(int inspectionType, const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expectedValue); | 50 | virtual KAsync::Job<void> |
51 | inspect(int inspectionType, const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expectedValue); | ||
52 | 52 | ||
53 | int error() const; | 53 | int error() const; |
54 | 54 | ||
@@ -61,13 +61,15 @@ private slots: | |||
61 | 61 | ||
62 | protected: | 62 | protected: |
63 | void enableChangeReplay(bool); | 63 | void enableChangeReplay(bool); |
64 | void addType(const QByteArray &type, DomainTypeAdaptorFactoryInterface::Ptr factory, const QVector<Sink::Preprocessor*> &preprocessors); | 64 | void addType(const QByteArray &type, DomainTypeAdaptorFactoryInterface::Ptr factory, const QVector<Sink::Preprocessor *> &preprocessors); |
65 | virtual KAsync::Job<void> replay(Sink::Storage &synchronizationStore, const QByteArray &type, const QByteArray &key, const QByteArray &value); | 65 | virtual KAsync::Job<void> replay(Sink::Storage &synchronizationStore, const QByteArray &type, const QByteArray &key, const QByteArray &value); |
66 | void onProcessorError(int errorCode, const QString &errorMessage); | 66 | void onProcessorError(int errorCode, const QString &errorMessage); |
67 | void enqueueCommand(MessageQueue &mq, int commandId, const QByteArray &data); | 67 | void enqueueCommand(MessageQueue &mq, int commandId, const QByteArray &data); |
68 | 68 | ||
69 | static void createEntity(const QByteArray &localId, const QByteArray &bufferType, const Sink::ApplicationDomain::ApplicationDomainType &domainObject, DomainTypeAdaptorFactoryInterface &adaptorFactory, std::function<void(const QByteArray &)> callback); | 69 | static void createEntity(const QByteArray &localId, const QByteArray &bufferType, const Sink::ApplicationDomain::ApplicationDomainType &domainObject, |
70 | static void modifyEntity(const QByteArray &localId, qint64 revision, const QByteArray &bufferType, const Sink::ApplicationDomain::ApplicationDomainType &domainObject, DomainTypeAdaptorFactoryInterface &adaptorFactory, std::function<void(const QByteArray &)> callback); | 70 | DomainTypeAdaptorFactoryInterface &adaptorFactory, std::function<void(const QByteArray &)> callback); |
71 | static void modifyEntity(const QByteArray &localId, qint64 revision, const QByteArray &bufferType, const Sink::ApplicationDomain::ApplicationDomainType &domainObject, | ||
72 | DomainTypeAdaptorFactoryInterface &adaptorFactory, std::function<void(const QByteArray &)> callback); | ||
71 | static void deleteEntity(const QByteArray &localId, qint64 revision, const QByteArray &bufferType, std::function<void(const QByteArray &)> callback); | 73 | static void deleteEntity(const QByteArray &localId, qint64 revision, const QByteArray &bufferType, std::function<void(const QByteArray &)> callback); |
72 | 74 | ||
73 | /** | 75 | /** |
@@ -79,36 +81,38 @@ protected: | |||
79 | 81 | ||
80 | /** | 82 | /** |
81 | * Tries to find a local id for the remote id, and creates a new local id otherwise. | 83 | * Tries to find a local id for the remote id, and creates a new local id otherwise. |
82 | * | 84 | * |
83 | * The new local id is recorded in the local to remote id mapping. | 85 | * The new local id is recorded in the local to remote id mapping. |
84 | */ | 86 | */ |
85 | QByteArray resolveRemoteId(const QByteArray &type, const QByteArray &remoteId, Sink::Storage::Transaction &transaction); | 87 | QByteArray resolveRemoteId(const QByteArray &type, const QByteArray &remoteId, Sink::Storage::Transaction &transaction); |
86 | 88 | ||
87 | /** | 89 | /** |
88 | * Tries to find a remote id for a local id. | 90 | * Tries to find a remote id for a local id. |
89 | * | 91 | * |
90 | * This can fail if the entity hasn't been written back to the server yet. | 92 | * This can fail if the entity hasn't been written back to the server yet. |
91 | */ | 93 | */ |
92 | QByteArray resolveLocalId(const QByteArray &bufferType, const QByteArray &localId, Sink::Storage::Transaction &transaction); | 94 | QByteArray resolveLocalId(const QByteArray &bufferType, const QByteArray &localId, Sink::Storage::Transaction &transaction); |
93 | 95 | ||
94 | /** | 96 | /** |
95 | * A synchronous algorithm to remove entities that are no longer existing. | 97 | * A synchronous algorithm to remove entities that are no longer existing. |
96 | * | 98 | * |
97 | * A list of entities is generated by @param entryGenerator. | 99 | * A list of entities is generated by @param entryGenerator. |
98 | * The entiry Generator typically iterates over an index to produce all existing entries. | 100 | * The entiry Generator typically iterates over an index to produce all existing entries. |
99 | * This algorithm calls @param exists for every entity of type @param type, with its remoteId. For every entity where @param exists returns false, | 101 | * This algorithm calls @param exists for every entity of type @param type, with its remoteId. For every entity where @param exists returns false, |
100 | * an entity delete command is enqueued. | 102 | * an entity delete command is enqueued. |
101 | * | 103 | * |
102 | * All functions are called synchronously, and both @param entryGenerator and @param exists need to be synchronous. | 104 | * All functions are called synchronously, and both @param entryGenerator and @param exists need to be synchronous. |
103 | */ | 105 | */ |
104 | void scanForRemovals(Sink::Storage::Transaction &transaction, Sink::Storage::Transaction &synchronizationTransaction, const QByteArray &bufferType, const std::function<void(const std::function<void(const QByteArray &key)> &callback)> &entryGenerator, std::function<bool(const QByteArray &remoteId)> exists); | 106 | void scanForRemovals(Sink::Storage::Transaction &transaction, Sink::Storage::Transaction &synchronizationTransaction, const QByteArray &bufferType, |
107 | const std::function<void(const std::function<void(const QByteArray &key)> &callback)> &entryGenerator, std::function<bool(const QByteArray &remoteId)> exists); | ||
105 | 108 | ||
106 | /** | 109 | /** |
107 | * An algorithm to create or modify the entity. | 110 | * An algorithm to create or modify the entity. |
108 | * | 111 | * |
109 | * Depending on whether the entity is locally available, or has changed. | 112 | * Depending on whether the entity is locally available, or has changed. |
110 | */ | 113 | */ |
111 | void createOrModify(Sink::Storage::Transaction &transaction, Sink::Storage::Transaction &synchronizationTransaction, DomainTypeAdaptorFactoryInterface &adaptorFactory, const QByteArray &bufferType, const QByteArray &remoteId, const Sink::ApplicationDomain::ApplicationDomainType &entity); | 114 | void createOrModify(Sink::Storage::Transaction &transaction, Sink::Storage::Transaction &synchronizationTransaction, DomainTypeAdaptorFactoryInterface &adaptorFactory, |
115 | const QByteArray &bufferType, const QByteArray &remoteId, const Sink::ApplicationDomain::ApplicationDomainType &entity); | ||
112 | 116 | ||
113 | MessageQueue mUserQueue; | 117 | MessageQueue mUserQueue; |
114 | MessageQueue mSynchronizerQueue; | 118 | MessageQueue mSynchronizerQueue; |
@@ -122,5 +126,4 @@ private: | |||
122 | QTimer mCommitQueueTimer; | 126 | QTimer mCommitQueueTimer; |
123 | qint64 mClientLowerBoundRevision; | 127 | qint64 mClientLowerBoundRevision; |
124 | }; | 128 | }; |
125 | |||
126 | } | 129 | } |
diff --git a/common/index.cpp b/common/index.cpp index e35b838..b5e9980 100644 --- a/common/index.cpp +++ b/common/index.cpp | |||
@@ -7,17 +7,14 @@ | |||
7 | 7 | ||
8 | Index::Index(const QString &storageRoot, const QString &name, Sink::Storage::AccessMode mode) | 8 | Index::Index(const QString &storageRoot, const QString &name, Sink::Storage::AccessMode mode) |
9 | : mTransaction(Sink::Storage(storageRoot, name, mode).createTransaction(mode)), | 9 | : mTransaction(Sink::Storage(storageRoot, name, mode).createTransaction(mode)), |
10 | mDb(mTransaction.openDatabase(name.toLatin1(), std::function<void(const Sink::Storage::Error &)>(), true)), | 10 | mDb(mTransaction.openDatabase(name.toLatin1(), std::function<void(const Sink::Storage::Error &)>(), true)), |
11 | mName(name) | 11 | mName(name) |
12 | { | 12 | { |
13 | |||
14 | } | 13 | } |
15 | 14 | ||
16 | Index::Index(const QByteArray &name, Sink::Storage::Transaction &transaction) | 15 | Index::Index(const QByteArray &name, Sink::Storage::Transaction &transaction) |
17 | : mDb(transaction.openDatabase(name, std::function<void(const Sink::Storage::Error &)>(), true)), | 16 | : mDb(transaction.openDatabase(name, std::function<void(const Sink::Storage::Error &)>(), true)), mName(name) |
18 | mName(name) | ||
19 | { | 17 | { |
20 | |||
21 | } | 18 | } |
22 | 19 | ||
23 | void Index::add(const QByteArray &key, const QByteArray &value) | 20 | void Index::add(const QByteArray &key, const QByteArray &value) |
@@ -30,30 +27,23 @@ void Index::remove(const QByteArray &key, const QByteArray &value) | |||
30 | mDb.remove(key, value); | 27 | mDb.remove(key, value); |
31 | } | 28 | } |
32 | 29 | ||
33 | void Index::lookup(const QByteArray &key, const std::function<void(const QByteArray &value)> &resultHandler, | 30 | void Index::lookup(const QByteArray &key, const std::function<void(const QByteArray &value)> &resultHandler, const std::function<void(const Error &error)> &errorHandler, bool matchSubStringKeys) |
34 | const std::function<void(const Error &error)> &errorHandler, bool matchSubStringKeys) | ||
35 | { | 31 | { |
36 | mDb.scan(key, [this, resultHandler](const QByteArray &key, const QByteArray &value) -> bool { | 32 | mDb.scan(key, |
37 | resultHandler(value); | 33 | [this, resultHandler](const QByteArray &key, const QByteArray &value) -> bool { |
38 | return true; | 34 | resultHandler(value); |
39 | }, | 35 | return true; |
40 | [errorHandler](const Sink::Storage::Error &error) { | 36 | }, |
41 | Warning() << "Error while retrieving value" << error.message; | 37 | [errorHandler](const Sink::Storage::Error &error) { |
42 | errorHandler(Error(error.store, error.code, error.message)); | 38 | Warning() << "Error while retrieving value" << error.message; |
43 | }, | 39 | errorHandler(Error(error.store, error.code, error.message)); |
44 | matchSubStringKeys); | 40 | }, |
41 | matchSubStringKeys); | ||
45 | } | 42 | } |
46 | 43 | ||
47 | QByteArray Index::lookup(const QByteArray &key) | 44 | QByteArray Index::lookup(const QByteArray &key) |
48 | { | 45 | { |
49 | QByteArray result; | 46 | QByteArray result; |
50 | lookup(key, | 47 | lookup(key, [&result](const QByteArray &value) { result = value; }, [this](const Index::Error &error) { Trace() << "Error while retrieving value" << error.message; }); |
51 | [&result](const QByteArray &value) { | ||
52 | result = value; | ||
53 | }, | ||
54 | [this](const Index::Error &error) { | ||
55 | Trace() << "Error while retrieving value" << error.message; | ||
56 | }); | ||
57 | return result; | 48 | return result; |
58 | } | 49 | } |
59 | |||
diff --git a/common/index.h b/common/index.h index 3ee322a..0345f56 100644 --- a/common/index.h +++ b/common/index.h | |||
@@ -12,15 +12,17 @@ | |||
12 | class SINK_EXPORT Index | 12 | class SINK_EXPORT Index |
13 | { | 13 | { |
14 | public: | 14 | public: |
15 | enum ErrorCodes { | 15 | enum ErrorCodes |
16 | { | ||
16 | IndexNotAvailable = -1 | 17 | IndexNotAvailable = -1 |
17 | }; | 18 | }; |
18 | 19 | ||
19 | class Error | 20 | class Error |
20 | { | 21 | { |
21 | public: | 22 | public: |
22 | Error(const QByteArray &s, int c, const QByteArray &m) | 23 | Error(const QByteArray &s, int c, const QByteArray &m) : store(s), message(m), code(c) |
23 | : store(s), message(m), code(c) {} | 24 | { |
25 | } | ||
24 | QByteArray store; | 26 | QByteArray store; |
25 | QByteArray message; | 27 | QByteArray message; |
26 | int code; | 28 | int code; |
@@ -32,8 +34,8 @@ public: | |||
32 | void add(const QByteArray &key, const QByteArray &value); | 34 | void add(const QByteArray &key, const QByteArray &value); |
33 | void remove(const QByteArray &key, const QByteArray &value); | 35 | void remove(const QByteArray &key, const QByteArray &value); |
34 | 36 | ||
35 | void lookup(const QByteArray &key, const std::function<void(const QByteArray &value)> &resultHandler, | 37 | void lookup(const QByteArray &key, const std::function<void(const QByteArray &value)> &resultHandler, const std::function<void(const Error &error)> &errorHandler, |
36 | const std::function<void(const Error &error)> &errorHandler, bool matchSubStringKeys = false); | 38 | bool matchSubStringKeys = false); |
37 | QByteArray lookup(const QByteArray &key); | 39 | QByteArray lookup(const QByteArray &key); |
38 | 40 | ||
39 | private: | 41 | private: |
diff --git a/common/indexupdater.h b/common/indexupdater.h index ced220b..deaaa16 100644 --- a/common/indexupdater.h +++ b/common/indexupdater.h | |||
@@ -21,14 +21,11 @@ | |||
21 | #include <pipeline.h> | 21 | #include <pipeline.h> |
22 | #include <index.h> | 22 | #include <index.h> |
23 | 23 | ||
24 | class IndexUpdater : public Sink::Preprocessor { | 24 | class IndexUpdater : public Sink::Preprocessor |
25 | { | ||
25 | public: | 26 | public: |
26 | IndexUpdater(const QByteArray &index, const QByteArray &type, const QByteArray &property) | 27 | IndexUpdater(const QByteArray &index, const QByteArray &type, const QByteArray &property) : mIndexIdentifier(index), mBufferType(type), mProperty(property) |
27 | :mIndexIdentifier(index), | ||
28 | mBufferType(type), | ||
29 | mProperty(property) | ||
30 | { | 28 | { |
31 | |||
32 | } | 29 | } |
33 | 30 | ||
34 | void newEntity(const QByteArray &uid, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &newEntity, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | 31 | void newEntity(const QByteArray &uid, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &newEntity, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE |
@@ -36,7 +33,8 @@ public: | |||
36 | add(newEntity.getProperty(mProperty), uid, transaction); | 33 | add(newEntity.getProperty(mProperty), uid, transaction); |
37 | } | 34 | } |
38 | 35 | ||
39 | void modifiedEntity(const QByteArray &uid, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &oldEntity, const Sink::ApplicationDomain::BufferAdaptor &newEntity, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | 36 | void modifiedEntity(const QByteArray &uid, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &oldEntity, const Sink::ApplicationDomain::BufferAdaptor &newEntity, |
37 | Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | ||
40 | { | 38 | { |
41 | remove(oldEntity.getProperty(mProperty), uid, transaction); | 39 | remove(oldEntity.getProperty(mProperty), uid, transaction); |
42 | add(newEntity.getProperty(mProperty), uid, transaction); | 40 | add(newEntity.getProperty(mProperty), uid, transaction); |
@@ -57,7 +55,7 @@ private: | |||
57 | 55 | ||
58 | void remove(const QVariant &value, const QByteArray &uid, Sink::Storage::Transaction &transaction) | 56 | void remove(const QVariant &value, const QByteArray &uid, Sink::Storage::Transaction &transaction) |
59 | { | 57 | { |
60 | //TODO hide notfound error | 58 | // TODO hide notfound error |
61 | Index(mIndexIdentifier, transaction).remove(value.toByteArray(), uid); | 59 | Index(mIndexIdentifier, transaction).remove(value.toByteArray(), uid); |
62 | } | 60 | } |
63 | 61 | ||
@@ -66,15 +64,17 @@ private: | |||
66 | QByteArray mProperty; | 64 | QByteArray mProperty; |
67 | }; | 65 | }; |
68 | 66 | ||
69 | template<typename DomainType> | 67 | template <typename DomainType> |
70 | class DefaultIndexUpdater : public Sink::Preprocessor { | 68 | class DefaultIndexUpdater : public Sink::Preprocessor |
69 | { | ||
71 | public: | 70 | public: |
72 | void newEntity(const QByteArray &uid, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &newEntity, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | 71 | void newEntity(const QByteArray &uid, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &newEntity, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE |
73 | { | 72 | { |
74 | Sink::ApplicationDomain::TypeImplementation<DomainType>::index(uid, newEntity, transaction); | 73 | Sink::ApplicationDomain::TypeImplementation<DomainType>::index(uid, newEntity, transaction); |
75 | } | 74 | } |
76 | 75 | ||
77 | void modifiedEntity(const QByteArray &uid, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &oldEntity, const Sink::ApplicationDomain::BufferAdaptor &newEntity, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | 76 | void modifiedEntity(const QByteArray &uid, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &oldEntity, const Sink::ApplicationDomain::BufferAdaptor &newEntity, |
77 | Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | ||
78 | { | 78 | { |
79 | Sink::ApplicationDomain::TypeImplementation<DomainType>::removeIndex(uid, oldEntity, transaction); | 79 | Sink::ApplicationDomain::TypeImplementation<DomainType>::removeIndex(uid, oldEntity, transaction); |
80 | Sink::ApplicationDomain::TypeImplementation<DomainType>::index(uid, newEntity, transaction); | 80 | Sink::ApplicationDomain::TypeImplementation<DomainType>::index(uid, newEntity, transaction); |
diff --git a/common/inspection.h b/common/inspection.h index d85eab6..7abcd1c 100644 --- a/common/inspection.h +++ b/common/inspection.h | |||
@@ -24,9 +24,10 @@ | |||
24 | #include "applicationdomaintype.h" | 24 | #include "applicationdomaintype.h" |
25 | 25 | ||
26 | namespace Sink { | 26 | namespace Sink { |
27 | namespace ResourceControl { | 27 | namespace ResourceControl { |
28 | 28 | ||
29 | struct Inspection { | 29 | struct Inspection |
30 | { | ||
30 | static Inspection PropertyInspection(const Sink::ApplicationDomain::Entity &entity, const QByteArray &property, const QVariant &expectedValue) | 31 | static Inspection PropertyInspection(const Sink::ApplicationDomain::Entity &entity, const QByteArray &property, const QVariant &expectedValue) |
31 | { | 32 | { |
32 | Inspection inspection; | 33 | Inspection inspection; |
@@ -46,7 +47,8 @@ struct Inspection { | |||
46 | return inspection; | 47 | return inspection; |
47 | } | 48 | } |
48 | 49 | ||
49 | enum Type { | 50 | enum Type |
51 | { | ||
50 | PropertyInspectionType, | 52 | PropertyInspectionType, |
51 | ExistenceInspectionType | 53 | ExistenceInspectionType |
52 | }; | 54 | }; |
@@ -55,6 +57,5 @@ struct Inspection { | |||
55 | QByteArray property; | 57 | QByteArray property; |
56 | QVariant expectedValue; | 58 | QVariant expectedValue; |
57 | }; | 59 | }; |
58 | 60 | } | |
59 | } | ||
60 | } | 61 | } |
diff --git a/common/listener.cpp b/common/listener.cpp index ed6f305..145267a 100644 --- a/common/listener.cpp +++ b/common/listener.cpp | |||
@@ -51,8 +51,7 @@ Listener::Listener(const QByteArray &resourceInstanceIdentifier, QObject *parent | |||
51 | m_clientBufferProcessesTimer(new QTimer(this)), | 51 | m_clientBufferProcessesTimer(new QTimer(this)), |
52 | m_messageId(0) | 52 | m_messageId(0) |
53 | { | 53 | { |
54 | connect(m_server, &QLocalServer::newConnection, | 54 | connect(m_server, &QLocalServer::newConnection, this, &Listener::acceptConnection); |
55 | this, &Listener::acceptConnection); | ||
56 | Trace() << "Trying to open " << m_resourceInstanceIdentifier; | 55 | Trace() << "Trying to open " << m_resourceInstanceIdentifier; |
57 | 56 | ||
58 | if (!m_server->listen(QString::fromLatin1(m_resourceInstanceIdentifier))) { | 57 | if (!m_server->listen(QString::fromLatin1(m_resourceInstanceIdentifier))) { |
@@ -77,12 +76,11 @@ Listener::Listener(const QByteArray &resourceInstanceIdentifier, QObject *parent | |||
77 | } | 76 | } |
78 | }); | 77 | }); |
79 | 78 | ||
80 | //TODO: experiment with different timeouts | 79 | // TODO: experiment with different timeouts |
81 | // or even just drop down to invoking the method queued? => invoke queued unless we need throttling | 80 | // or even just drop down to invoking the method queued? => invoke queued unless we need throttling |
82 | m_clientBufferProcessesTimer->setInterval(0); | 81 | m_clientBufferProcessesTimer->setInterval(0); |
83 | m_clientBufferProcessesTimer->setSingleShot(true); | 82 | m_clientBufferProcessesTimer->setSingleShot(true); |
84 | connect(m_clientBufferProcessesTimer, &QTimer::timeout, | 83 | connect(m_clientBufferProcessesTimer, &QTimer::timeout, this, &Listener::processClientBuffers); |
85 | this, &Listener::processClientBuffers); | ||
86 | } | 84 | } |
87 | 85 | ||
88 | Listener::~Listener() | 86 | Listener::~Listener() |
@@ -91,7 +89,7 @@ Listener::~Listener() | |||
91 | 89 | ||
92 | void Listener::closeAllConnections() | 90 | void Listener::closeAllConnections() |
93 | { | 91 | { |
94 | for (Client &client: m_connections) { | 92 | for (Client &client : m_connections) { |
95 | if (client.socket) { | 93 | if (client.socket) { |
96 | disconnect(client.socket, 0, this, 0); | 94 | disconnect(client.socket, 0, this, 0); |
97 | client.socket->close(); | 95 | client.socket->close(); |
@@ -114,13 +112,11 @@ void Listener::acceptConnection() | |||
114 | } | 112 | } |
115 | 113 | ||
116 | m_connections << Client("Unknown Client", socket); | 114 | m_connections << Client("Unknown Client", socket); |
117 | connect(socket, &QIODevice::readyRead, | 115 | connect(socket, &QIODevice::readyRead, this, &Listener::onDataAvailable); |
118 | this, &Listener::onDataAvailable); | 116 | connect(socket, &QLocalSocket::disconnected, this, &Listener::clientDropped); |
119 | connect(socket, &QLocalSocket::disconnected, | ||
120 | this, &Listener::clientDropped); | ||
121 | m_checkConnectionsTimer->stop(); | 117 | m_checkConnectionsTimer->stop(); |
122 | 118 | ||
123 | //If this is the first client, set the lower limit for revision cleanup | 119 | // If this is the first client, set the lower limit for revision cleanup |
124 | if (m_connections.size() == 1) { | 120 | if (m_connections.size() == 1) { |
125 | loadResource()->setLowerBoundRevision(0); | 121 | loadResource()->setLowerBoundRevision(0); |
126 | } | 122 | } |
@@ -157,7 +153,7 @@ void Listener::clientDropped() | |||
157 | 153 | ||
158 | void Listener::checkConnections() | 154 | void Listener::checkConnections() |
159 | { | 155 | { |
160 | //If this was the last client, disengage the lower limit for revision cleanup | 156 | // If this was the last client, disengage the lower limit for revision cleanup |
161 | if (m_connections.isEmpty()) { | 157 | if (m_connections.isEmpty()) { |
162 | loadResource()->setLowerBoundRevision(std::numeric_limits<qint64>::max()); | 158 | loadResource()->setLowerBoundRevision(std::numeric_limits<qint64>::max()); |
163 | } | 159 | } |
@@ -176,7 +172,7 @@ void Listener::onDataAvailable() | |||
176 | void Listener::readFromSocket(QLocalSocket *socket) | 172 | void Listener::readFromSocket(QLocalSocket *socket) |
177 | { | 173 | { |
178 | Trace() << "Reading from socket..."; | 174 | Trace() << "Reading from socket..."; |
179 | for (Client &client: m_connections) { | 175 | for (Client &client : m_connections) { |
180 | if (client.socket == socket) { | 176 | if (client.socket == socket) { |
181 | client.commandBuffer += socket->readAll(); | 177 | client.commandBuffer += socket->readAll(); |
182 | if (!m_clientBufferProcessesTimer->isActive()) { | 178 | if (!m_clientBufferProcessesTimer->isActive()) { |
@@ -189,11 +185,11 @@ void Listener::readFromSocket(QLocalSocket *socket) | |||
189 | 185 | ||
190 | void Listener::processClientBuffers() | 186 | void Listener::processClientBuffers() |
191 | { | 187 | { |
192 | //TODO: we should not process all clients, but iterate async over them and process | 188 | // TODO: we should not process all clients, but iterate async over them and process |
193 | // one command from each in turn to ensure all clients get fair handling of | 189 | // one command from each in turn to ensure all clients get fair handling of |
194 | // commands? | 190 | // commands? |
195 | bool again = false; | 191 | bool again = false; |
196 | for (Client &client: m_connections) { | 192 | for (Client &client : m_connections) { |
197 | if (!client.socket || !client.socket->isValid() || client.commandBuffer.isEmpty()) { | 193 | if (!client.socket || !client.socket->isValid() || client.commandBuffer.isEmpty()) { |
198 | continue; | 194 | continue; |
199 | } | 195 | } |
@@ -237,9 +233,10 @@ void Listener::processCommand(int commandId, uint messageId, const QByteArray &c | |||
237 | job = job.then<void>(loadResource()->processAllMessages()); | 233 | job = job.then<void>(loadResource()->processAllMessages()); |
238 | } | 234 | } |
239 | job.then<void>([callback, timer]() { | 235 | job.then<void>([callback, timer]() { |
240 | Trace() << "Sync took " << Sink::Log::TraceTime(timer->elapsed()); | 236 | Trace() << "Sync took " << Sink::Log::TraceTime(timer->elapsed()); |
241 | callback(true); | 237 | callback(true); |
242 | }).exec(); | 238 | }) |
239 | .exec(); | ||
243 | return; | 240 | return; |
244 | } else { | 241 | } else { |
245 | Warning() << "received invalid command"; | 242 | Warning() << "received invalid command"; |
@@ -256,7 +253,7 @@ void Listener::processCommand(int commandId, uint messageId, const QByteArray &c | |||
256 | break; | 253 | break; |
257 | case Sink::Commands::ShutdownCommand: | 254 | case Sink::Commands::ShutdownCommand: |
258 | Log() << QString("\tReceived shutdown command from %1").arg(client.name); | 255 | Log() << QString("\tReceived shutdown command from %1").arg(client.name); |
259 | //Immediately reject new connections | 256 | // Immediately reject new connections |
260 | m_server->close(); | 257 | m_server->close(); |
261 | QTimer::singleShot(0, this, &Listener::quit); | 258 | QTimer::singleShot(0, this, &Listener::quit); |
262 | break; | 259 | break; |
@@ -273,16 +270,14 @@ void Listener::processCommand(int commandId, uint messageId, const QByteArray &c | |||
273 | Warning() << "received invalid command"; | 270 | Warning() << "received invalid command"; |
274 | } | 271 | } |
275 | loadResource()->setLowerBoundRevision(lowerBoundRevision()); | 272 | loadResource()->setLowerBoundRevision(lowerBoundRevision()); |
276 | } | 273 | } break; |
277 | break; | ||
278 | case Sink::Commands::RemoveFromDiskCommand: { | 274 | case Sink::Commands::RemoveFromDiskCommand: { |
279 | Log() << QString("\tReceived a remove from disk command from %1").arg(client.name); | 275 | Log() << QString("\tReceived a remove from disk command from %1").arg(client.name); |
280 | m_resource->removeDataFromDisk(); | 276 | m_resource->removeDataFromDisk(); |
281 | delete m_resource; | 277 | delete m_resource; |
282 | m_resource = nullptr; | 278 | m_resource = nullptr; |
283 | loadResource()->setLowerBoundRevision(0); | 279 | loadResource()->setLowerBoundRevision(0); |
284 | } | 280 | } break; |
285 | break; | ||
286 | default: | 281 | default: |
287 | if (commandId > Sink::Commands::CustomCommand) { | 282 | if (commandId > Sink::Commands::CustomCommand) { |
288 | Log() << QString("\tReceived custom command from %1: ").arg(client.name) << commandId; | 283 | Log() << QString("\tReceived custom command from %1: ").arg(client.name) << commandId; |
@@ -313,7 +308,7 @@ qint64 Listener::lowerBoundRevision() | |||
313 | 308 | ||
314 | void Listener::quit() | 309 | void Listener::quit() |
315 | { | 310 | { |
316 | //Broadcast shutdown notifications to open clients, so they don't try to restart the resource | 311 | // Broadcast shutdown notifications to open clients, so they don't try to restart the resource |
317 | auto command = Sink::Commands::CreateNotification(m_fbb, Sink::Commands::NotificationType::NotificationType_Shutdown); | 312 | auto command = Sink::Commands::CreateNotification(m_fbb, Sink::Commands::NotificationType::NotificationType_Shutdown); |
318 | Sink::Commands::FinishNotificationBuffer(m_fbb, command); | 313 | Sink::Commands::FinishNotificationBuffer(m_fbb, command); |
319 | for (Client &client : m_connections) { | 314 | for (Client &client : m_connections) { |
@@ -323,7 +318,7 @@ void Listener::quit() | |||
323 | } | 318 | } |
324 | m_fbb.Clear(); | 319 | m_fbb.Clear(); |
325 | 320 | ||
326 | //Connections will be cleaned up later | 321 | // Connections will be cleaned up later |
327 | emit noClients(); | 322 | emit noClients(); |
328 | } | 323 | } |
329 | 324 | ||
@@ -334,12 +329,12 @@ bool Listener::processClientBuffer(Client &client) | |||
334 | return false; | 329 | return false; |
335 | } | 330 | } |
336 | 331 | ||
337 | const uint messageId = *(uint*)client.commandBuffer.constData(); | 332 | const uint messageId = *(uint *)client.commandBuffer.constData(); |
338 | const int commandId = *(int*)(client.commandBuffer.constData() + sizeof(uint)); | 333 | const int commandId = *(int *)(client.commandBuffer.constData() + sizeof(uint)); |
339 | const uint size = *(uint*)(client.commandBuffer.constData() + sizeof(int) + sizeof(uint)); | 334 | const uint size = *(uint *)(client.commandBuffer.constData() + sizeof(int) + sizeof(uint)); |
340 | Trace() << "Received message. Id:" << messageId << " CommandId: " << commandId << " Size: " << size; | 335 | Trace() << "Received message. Id:" << messageId << " CommandId: " << commandId << " Size: " << size; |
341 | 336 | ||
342 | //TODO: reject messages above a certain size? | 337 | // TODO: reject messages above a certain size? |
343 | 338 | ||
344 | const bool commandComplete = size <= uint(client.commandBuffer.size() - headerSize); | 339 | const bool commandComplete = size <= uint(client.commandBuffer.size() - headerSize); |
345 | if (commandComplete) { | 340 | if (commandComplete) { |
@@ -386,7 +381,7 @@ void Listener::updateClientsWithRevision(qint64 revision) | |||
386 | auto command = Sink::Commands::CreateRevisionUpdate(m_fbb, revision); | 381 | auto command = Sink::Commands::CreateRevisionUpdate(m_fbb, revision); |
387 | Sink::Commands::FinishRevisionUpdateBuffer(m_fbb, command); | 382 | Sink::Commands::FinishRevisionUpdateBuffer(m_fbb, command); |
388 | 383 | ||
389 | for (const Client &client: m_connections) { | 384 | for (const Client &client : m_connections) { |
390 | if (!client.socket || !client.socket->isValid()) { | 385 | if (!client.socket || !client.socket->isValid()) { |
391 | continue; | 386 | continue; |
392 | } | 387 | } |
@@ -423,10 +418,8 @@ Sink::Resource *Listener::loadResource() | |||
423 | m_resource = resourceFactory->createResource(m_resourceInstanceIdentifier); | 418 | m_resource = resourceFactory->createResource(m_resourceInstanceIdentifier); |
424 | Trace() << QString("Resource factory: %1").arg((qlonglong)resourceFactory); | 419 | Trace() << QString("Resource factory: %1").arg((qlonglong)resourceFactory); |
425 | Trace() << QString("\tResource: %1").arg((qlonglong)m_resource); | 420 | Trace() << QString("\tResource: %1").arg((qlonglong)m_resource); |
426 | connect(m_resource, &Sink::Resource::revisionUpdated, | 421 | connect(m_resource, &Sink::Resource::revisionUpdated, this, &Listener::refreshRevision); |
427 | this, &Listener::refreshRevision); | 422 | connect(m_resource, &Sink::Resource::notify, this, &Listener::notify); |
428 | connect(m_resource, &Sink::Resource::notify, | ||
429 | this, &Listener::notify); | ||
430 | } else { | 423 | } else { |
431 | ErrorMsg() << "Failed to load resource " << m_resourceName; | 424 | ErrorMsg() << "Failed to load resource " << m_resourceName; |
432 | m_resource = new Sink::Resource; | 425 | m_resource = new Sink::Resource; |
diff --git a/common/listener.h b/common/listener.h index 49ded1a..aca7c50 100644 --- a/common/listener.h +++ b/common/listener.h | |||
@@ -26,10 +26,9 @@ | |||
26 | #include <QLocalSocket> | 26 | #include <QLocalSocket> |
27 | #include <flatbuffers/flatbuffers.h> | 27 | #include <flatbuffers/flatbuffers.h> |
28 | 28 | ||
29 | namespace Sink | 29 | namespace Sink { |
30 | { | 30 | class Resource; |
31 | class Resource; | 31 | class Notification; |
32 | class Notification; | ||
33 | } | 32 | } |
34 | 33 | ||
35 | class QTimer; | 34 | class QTimer; |
@@ -38,16 +37,11 @@ class QLocalServer; | |||
38 | class Client | 37 | class Client |
39 | { | 38 | { |
40 | public: | 39 | public: |
41 | Client() | 40 | Client() : socket(nullptr), currentRevision(0) |
42 | : socket(nullptr), | ||
43 | currentRevision(0) | ||
44 | { | 41 | { |
45 | } | 42 | } |
46 | 43 | ||
47 | Client(const QString &n, QLocalSocket *s) | 44 | Client(const QString &n, QLocalSocket *s) : name(n), socket(s), currentRevision(0) |
48 | : name(n), | ||
49 | socket(s), | ||
50 | currentRevision(0) | ||
51 | { | 45 | { |
52 | } | 46 | } |
53 | 47 | ||
diff --git a/common/log.cpp b/common/log.cpp index 96c6f82..b0f6237 100644 --- a/common/log.cpp +++ b/common/log.cpp | |||
@@ -16,67 +16,88 @@ static QSharedPointer<QSettings> config() | |||
16 | return QSharedPointer<QSettings>::create(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/sink/log.ini", QSettings::IniFormat); | 16 | return QSharedPointer<QSettings>::create(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/sink/log.ini", QSettings::IniFormat); |
17 | } | 17 | } |
18 | 18 | ||
19 | class DebugStream: public QIODevice | 19 | class DebugStream : public QIODevice |
20 | { | 20 | { |
21 | public: | 21 | public: |
22 | QString m_location; | 22 | QString m_location; |
23 | DebugStream() | 23 | DebugStream() : QIODevice() |
24 | : QIODevice() | ||
25 | { | 24 | { |
26 | open(WriteOnly); | 25 | open(WriteOnly); |
27 | } | 26 | } |
28 | virtual ~DebugStream(); | 27 | virtual ~DebugStream(); |
29 | 28 | ||
30 | bool isSequential() const { return true; } | 29 | bool isSequential() const |
31 | qint64 readData(char *, qint64) { return 0; /* eof */ } | 30 | { |
32 | qint64 readLineData(char *, qint64) { return 0; /* eof */ } | 31 | return true; |
32 | } | ||
33 | qint64 readData(char *, qint64) | ||
34 | { | ||
35 | return 0; /* eof */ | ||
36 | } | ||
37 | qint64 readLineData(char *, qint64) | ||
38 | { | ||
39 | return 0; /* eof */ | ||
40 | } | ||
33 | qint64 writeData(const char *data, qint64 len) | 41 | qint64 writeData(const char *data, qint64 len) |
34 | { | 42 | { |
35 | std::cout << data << std::endl; | 43 | std::cout << data << std::endl; |
36 | return len; | 44 | return len; |
37 | } | 45 | } |
46 | |||
38 | private: | 47 | private: |
39 | Q_DISABLE_COPY(DebugStream) | 48 | Q_DISABLE_COPY(DebugStream) |
40 | }; | 49 | }; |
41 | 50 | ||
42 | //Virtual method anchor | 51 | // Virtual method anchor |
43 | DebugStream::~DebugStream() | 52 | DebugStream::~DebugStream() |
44 | {} | 53 | { |
54 | } | ||
45 | 55 | ||
46 | class NullStream: public QIODevice | 56 | class NullStream : public QIODevice |
47 | { | 57 | { |
48 | public: | 58 | public: |
49 | NullStream() | 59 | NullStream() : QIODevice() |
50 | : QIODevice() | ||
51 | { | 60 | { |
52 | open(WriteOnly); | 61 | open(WriteOnly); |
53 | } | 62 | } |
54 | virtual ~NullStream(); | 63 | virtual ~NullStream(); |
55 | 64 | ||
56 | bool isSequential() const { return true; } | 65 | bool isSequential() const |
57 | qint64 readData(char *, qint64) { return 0; /* eof */ } | 66 | { |
58 | qint64 readLineData(char *, qint64) { return 0; /* eof */ } | 67 | return true; |
68 | } | ||
69 | qint64 readData(char *, qint64) | ||
70 | { | ||
71 | return 0; /* eof */ | ||
72 | } | ||
73 | qint64 readLineData(char *, qint64) | ||
74 | { | ||
75 | return 0; /* eof */ | ||
76 | } | ||
59 | qint64 writeData(const char *data, qint64 len) | 77 | qint64 writeData(const char *data, qint64 len) |
60 | { | 78 | { |
61 | return len; | 79 | return len; |
62 | } | 80 | } |
81 | |||
63 | private: | 82 | private: |
64 | Q_DISABLE_COPY(NullStream) | 83 | Q_DISABLE_COPY(NullStream) |
65 | }; | 84 | }; |
66 | 85 | ||
67 | //Virtual method anchor | 86 | // Virtual method anchor |
68 | NullStream::~NullStream() | 87 | NullStream::~NullStream() |
69 | {} | 88 | { |
70 | 89 | } | |
71 | /* | 90 | |
72 | * ANSI color codes: | 91 | /* |
73 | * 0: reset colors/style | 92 | * ANSI color codes: |
74 | * 1: bold | 93 | * 0: reset colors/style |
75 | * 4: underline | 94 | * 1: bold |
76 | * 30 - 37: black, red, green, yellow, blue, magenta, cyan, and white text | 95 | * 4: underline |
77 | * 40 - 47: black, red, green, yellow, blue, magenta, cyan, and white background | 96 | * 30 - 37: black, red, green, yellow, blue, magenta, cyan, and white text |
78 | */ | 97 | * 40 - 47: black, red, green, yellow, blue, magenta, cyan, and white background |
79 | enum ANSI_Colors { | 98 | */ |
99 | enum ANSI_Colors | ||
100 | { | ||
80 | DoNothing = -1, | 101 | DoNothing = -1, |
81 | Reset = 0, | 102 | Reset = 0, |
82 | Bold = 1, | 103 | Bold = 1, |
@@ -211,7 +232,7 @@ static bool caseInsensitiveContains(const QByteArray &pattern, const QByteArrayL | |||
211 | return false; | 232 | return false; |
212 | } | 233 | } |
213 | 234 | ||
214 | QDebug Sink::Log::debugStream(DebugLevel debugLevel, int line, const char* file, const char* function, const char* debugArea) | 235 | QDebug Sink::Log::debugStream(DebugLevel debugLevel, int line, const char *file, const char *function, const char *debugArea) |
215 | { | 236 | { |
216 | static NullStream nullstream; | 237 | static NullStream nullstream; |
217 | if (debugLevel < debugOutputLevel()) { | 238 | if (debugLevel < debugOutputLevel()) { |
diff --git a/common/log.h b/common/log.h index 415c7f7..0e92ea9 100644 --- a/common/log.h +++ b/common/log.h | |||
@@ -6,7 +6,8 @@ | |||
6 | namespace Sink { | 6 | namespace Sink { |
7 | namespace Log { | 7 | namespace Log { |
8 | 8 | ||
9 | enum DebugLevel { | 9 | enum DebugLevel |
10 | { | ||
10 | Trace, | 11 | Trace, |
11 | Log, | 12 | Log, |
12 | Warning, | 13 | Warning, |
@@ -24,14 +25,15 @@ DebugLevel SINK_EXPORT debugLevelFromName(const QByteArray &name); | |||
24 | void SINK_EXPORT setDebugOutputLevel(DebugLevel); | 25 | void SINK_EXPORT setDebugOutputLevel(DebugLevel); |
25 | DebugLevel SINK_EXPORT debugOutputLevel(); | 26 | DebugLevel SINK_EXPORT debugOutputLevel(); |
26 | 27 | ||
27 | enum FilterType { | 28 | enum FilterType |
29 | { | ||
28 | Area, | 30 | Area, |
29 | ApplicationName | 31 | ApplicationName |
30 | }; | 32 | }; |
31 | 33 | ||
32 | /** | 34 | /** |
33 | * Sets a debug output filter. | 35 | * Sets a debug output filter. |
34 | * | 36 | * |
35 | * Everything that is not matching the filter is ignored. | 37 | * Everything that is not matching the filter is ignored. |
36 | * An empty filter matches everything. | 38 | * An empty filter matches everything. |
37 | * | 39 | * |
@@ -53,7 +55,7 @@ QByteArrayList SINK_EXPORT debugOutputFilter(FilterType type); | |||
53 | void SINK_EXPORT setDebugOutputFields(const QByteArrayList &filter); | 55 | void SINK_EXPORT setDebugOutputFields(const QByteArrayList &filter); |
54 | QByteArrayList SINK_EXPORT debugOutputFields(); | 56 | QByteArrayList SINK_EXPORT debugOutputFields(); |
55 | 57 | ||
56 | QDebug SINK_EXPORT debugStream(DebugLevel debugLevel, int line, const char* file, const char* function, const char* debugArea = 0); | 58 | QDebug SINK_EXPORT debugStream(DebugLevel debugLevel, int line, const char *file, const char *function, const char *debugArea = 0); |
57 | 59 | ||
58 | struct SINK_EXPORT TraceTime | 60 | struct SINK_EXPORT TraceTime |
59 | { | 61 | { |
@@ -66,7 +68,6 @@ inline QDebug SINK_EXPORT operator<<(QDebug d, const TraceTime &time) | |||
66 | d << time.time << "[ms]"; | 68 | d << time.time << "[ms]"; |
67 | return d; | 69 | return d; |
68 | } | 70 | } |
69 | |||
70 | } | 71 | } |
71 | } | 72 | } |
72 | 73 | ||
@@ -83,5 +84,5 @@ inline QDebug SINK_EXPORT operator<<(QDebug d, const TraceTime &time) | |||
83 | #define Trace() Sink::Log::debugStream(Sink::Log::DebugLevel::Trace, __LINE__, __FILE__, Q_FUNC_INFO, DEBUG_AREA) | 84 | #define Trace() Sink::Log::debugStream(Sink::Log::DebugLevel::Trace, __LINE__, __FILE__, Q_FUNC_INFO, DEBUG_AREA) |
84 | #define Log() Sink::Log::debugStream(Sink::Log::DebugLevel::Log, __LINE__, __FILE__, Q_FUNC_INFO, DEBUG_AREA) | 85 | #define Log() Sink::Log::debugStream(Sink::Log::DebugLevel::Log, __LINE__, __FILE__, Q_FUNC_INFO, DEBUG_AREA) |
85 | #define Warning() Sink::Log::debugStream(Sink::Log::DebugLevel::Warning, __LINE__, __FILE__, Q_FUNC_INFO, DEBUG_AREA) | 86 | #define Warning() Sink::Log::debugStream(Sink::Log::DebugLevel::Warning, __LINE__, __FILE__, Q_FUNC_INFO, DEBUG_AREA) |
86 | //FIXME Error clashes with Storage::Error and MessageQueue::Error | 87 | // FIXME Error clashes with Storage::Error and MessageQueue::Error |
87 | #define ErrorMsg() Sink::Log::debugStream(Sink::Log::DebugLevel::Error, __LINE__, __FILE__, Q_FUNC_INFO, DEBUG_AREA) | 88 | #define ErrorMsg() Sink::Log::debugStream(Sink::Log::DebugLevel::Error, __LINE__, __FILE__, Q_FUNC_INFO, DEBUG_AREA) |
diff --git a/common/messagequeue.cpp b/common/messagequeue.cpp index 73198a5..fd86635 100644 --- a/common/messagequeue.cpp +++ b/common/messagequeue.cpp | |||
@@ -3,41 +3,38 @@ | |||
3 | #include <QDebug> | 3 | #include <QDebug> |
4 | #include <log.h> | 4 | #include <log.h> |
5 | 5 | ||
6 | static KAsync::Job<void> waitForCompletion(QList<KAsync::Future<void> > &futures) | 6 | static KAsync::Job<void> waitForCompletion(QList<KAsync::Future<void>> &futures) |
7 | { | 7 | { |
8 | auto context = new QObject; | 8 | auto context = new QObject; |
9 | return KAsync::start<void>([futures, context](KAsync::Future<void> &future) { | 9 | return KAsync::start<void>([futures, context](KAsync::Future<void> &future) { |
10 | const auto total = futures.size(); | 10 | const auto total = futures.size(); |
11 | auto count = QSharedPointer<int>::create(); | 11 | auto count = QSharedPointer<int>::create(); |
12 | int i = 0; | 12 | int i = 0; |
13 | for (KAsync::Future<void> subFuture : futures) { | 13 | for (KAsync::Future<void> subFuture : futures) { |
14 | i++; | 14 | i++; |
15 | if (subFuture.isFinished()) { | 15 | if (subFuture.isFinished()) { |
16 | *count += 1; | 16 | *count += 1; |
17 | continue; | 17 | continue; |
18 | } | 18 | } |
19 | //FIXME bind lifetime all watcher to future (repectively the main job | 19 | // FIXME bind lifetime all watcher to future (repectively the main job |
20 | auto watcher = QSharedPointer<KAsync::FutureWatcher<void> >::create(); | 20 | auto watcher = QSharedPointer<KAsync::FutureWatcher<void>>::create(); |
21 | QObject::connect(watcher.data(), &KAsync::FutureWatcher<void>::futureReady, | 21 | QObject::connect(watcher.data(), &KAsync::FutureWatcher<void>::futureReady, [count, total, &future]() { |
22 | [count, total, &future](){ | 22 | *count += 1; |
23 | *count += 1; | 23 | if (*count == total) { |
24 | if (*count == total) { | 24 | future.setFinished(); |
25 | future.setFinished(); | 25 | } |
26 | } | 26 | }); |
27 | }); | 27 | watcher->setFuture(subFuture); |
28 | watcher->setFuture(subFuture); | 28 | context->setProperty(QString("future%1").arg(i).toLatin1().data(), QVariant::fromValue(watcher)); |
29 | context->setProperty(QString("future%1").arg(i).toLatin1().data(), QVariant::fromValue(watcher)); | 29 | } |
30 | } | 30 | if (*count == total) { |
31 | if (*count == total) { | 31 | future.setFinished(); |
32 | future.setFinished(); | 32 | } |
33 | } | 33 | }) |
34 | }).then<void>([context]() { | 34 | .then<void>([context]() { delete context; }); |
35 | delete context; | ||
36 | }); | ||
37 | } | 35 | } |
38 | 36 | ||
39 | MessageQueue::MessageQueue(const QString &storageRoot, const QString &name) | 37 | MessageQueue::MessageQueue(const QString &storageRoot, const QString &name) : mStorage(storageRoot, name, Sink::Storage::ReadWrite) |
40 | : mStorage(storageRoot, name, Sink::Storage::ReadWrite) | ||
41 | { | 38 | { |
42 | } | 39 | } |
43 | 40 | ||
@@ -47,7 +44,7 @@ MessageQueue::~MessageQueue() | |||
47 | 44 | ||
48 | void MessageQueue::enqueue(void const *msg, size_t size) | 45 | void MessageQueue::enqueue(void const *msg, size_t size) |
49 | { | 46 | { |
50 | enqueue(QByteArray::fromRawData(static_cast<const char*>(msg), size)); | 47 | enqueue(QByteArray::fromRawData(static_cast<const char *>(msg), size)); |
51 | } | 48 | } |
52 | 49 | ||
53 | void MessageQueue::startTransaction() | 50 | void MessageQueue::startTransaction() |
@@ -96,19 +93,13 @@ void MessageQueue::processRemovals() | |||
96 | mPendingRemoval.clear(); | 93 | mPendingRemoval.clear(); |
97 | } | 94 | } |
98 | 95 | ||
99 | void MessageQueue::dequeue(const std::function<void(void *ptr, int size, std::function<void(bool success)>)> &resultHandler, | 96 | void MessageQueue::dequeue(const std::function<void(void *ptr, int size, std::function<void(bool success)>)> &resultHandler, const std::function<void(const Error &error)> &errorHandler) |
100 | const std::function<void(const Error &error)> &errorHandler) | ||
101 | { | 97 | { |
102 | dequeueBatch(1, [resultHandler](const QByteArray &value) { | 98 | dequeueBatch(1, [resultHandler](const QByteArray &value) { |
103 | return KAsync::start<void>([&value,resultHandler](KAsync::Future<void> &future) { | 99 | return KAsync::start<void>([&value, resultHandler](KAsync::Future<void> &future) { |
104 | resultHandler(const_cast<void*>(static_cast<const void*>(value.data())), value.size(), [&future](bool success){ | 100 | resultHandler(const_cast<void *>(static_cast<const void *>(value.data())), value.size(), [&future](bool success) { future.setFinished(); }); |
105 | future.setFinished(); | ||
106 | }); | ||
107 | }); | 101 | }); |
108 | }).then<void>([](){}, | 102 | }).then<void>([]() {}, [errorHandler](int error, const QString &errorString) { errorHandler(Error("messagequeue", error, errorString.toLatin1())); }).exec(); |
109 | [errorHandler](int error, const QString &errorString) { | ||
110 | errorHandler(Error("messagequeue", error, errorString.toLatin1())); | ||
111 | }).exec(); | ||
112 | } | 103 | } |
113 | 104 | ||
114 | KAsync::Job<void> MessageQueue::dequeueBatch(int maxBatchSize, const std::function<KAsync::Job<void>(const QByteArray &)> &resultHandler) | 105 | KAsync::Job<void> MessageQueue::dequeueBatch(int maxBatchSize, const std::function<KAsync::Job<void>(const QByteArray &)> &resultHandler) |
@@ -116,41 +107,46 @@ KAsync::Job<void> MessageQueue::dequeueBatch(int maxBatchSize, const std::functi | |||
116 | auto resultCount = QSharedPointer<int>::create(0); | 107 | auto resultCount = QSharedPointer<int>::create(0); |
117 | return KAsync::start<void>([this, maxBatchSize, resultHandler, resultCount](KAsync::Future<void> &future) { | 108 | return KAsync::start<void>([this, maxBatchSize, resultHandler, resultCount](KAsync::Future<void> &future) { |
118 | int count = 0; | 109 | int count = 0; |
119 | QList<KAsync::Future<void> > waitCondition; | 110 | QList<KAsync::Future<void>> waitCondition; |
120 | mStorage.createTransaction(Sink::Storage::ReadOnly).openDatabase().scan("", [this, resultHandler, resultCount, &count, maxBatchSize, &waitCondition](const QByteArray &key, const QByteArray &value) -> bool { | 111 | mStorage.createTransaction(Sink::Storage::ReadOnly) |
121 | if (Sink::Storage::isInternalKey(key) || mPendingRemoval.contains(key)) { | 112 | .openDatabase() |
122 | return true; | 113 | .scan("", |
123 | } | 114 | [this, resultHandler, resultCount, &count, maxBatchSize, &waitCondition](const QByteArray &key, const QByteArray &value) -> bool { |
124 | *resultCount += 1; | 115 | if (Sink::Storage::isInternalKey(key) || mPendingRemoval.contains(key)) { |
125 | //We need a copy of the key here, otherwise we can't store it in the lambda (the pointers will become invalid) | 116 | return true; |
126 | mPendingRemoval << QByteArray(key.constData(), key.size()); | 117 | } |
118 | *resultCount += 1; | ||
119 | // We need a copy of the key here, otherwise we can't store it in the lambda (the pointers will become invalid) | ||
120 | mPendingRemoval << QByteArray(key.constData(), key.size()); | ||
127 | 121 | ||
128 | waitCondition << resultHandler(value).exec(); | 122 | waitCondition << resultHandler(value).exec(); |
129 | 123 | ||
130 | count++; | 124 | count++; |
131 | if (count < maxBatchSize) { | 125 | if (count < maxBatchSize) { |
132 | return true; | 126 | return true; |
133 | } | 127 | } |
134 | return false; | 128 | return false; |
135 | }, | 129 | }, |
136 | [](const Sink::Storage::Error &error) { | 130 | [](const Sink::Storage::Error &error) { |
137 | ErrorMsg() << "Error while retrieving value" << error.message; | 131 | ErrorMsg() << "Error while retrieving value" << error.message; |
138 | // errorHandler(Error(error.store, error.code, error.message)); | 132 | // errorHandler(Error(error.store, error.code, error.message)); |
139 | }); | 133 | }); |
140 | 134 | ||
141 | // Trace() << "Waiting on " << waitCondition.size() << " results"; | 135 | // Trace() << "Waiting on " << waitCondition.size() << " results"; |
142 | ::waitForCompletion(waitCondition).then<void>([this, resultCount, &future]() { | 136 | ::waitForCompletion(waitCondition) |
143 | processRemovals(); | 137 | .then<void>([this, resultCount, &future]() { |
144 | if (*resultCount == 0) { | 138 | processRemovals(); |
145 | future.setError(static_cast<int>(ErrorCodes::NoMessageFound), "No message found"); | 139 | if (*resultCount == 0) { |
146 | future.setFinished(); | 140 | future.setError(static_cast<int>(ErrorCodes::NoMessageFound), "No message found"); |
147 | } else { | 141 | future.setFinished(); |
148 | if (isEmpty()) { | 142 | } else { |
149 | emit this->drained(); | 143 | if (isEmpty()) { |
144 | emit this->drained(); | ||
145 | } | ||
146 | future.setFinished(); | ||
150 | } | 147 | } |
151 | future.setFinished(); | 148 | }) |
152 | } | 149 | .exec(); |
153 | }).exec(); | ||
154 | }); | 150 | }); |
155 | } | 151 | } |
156 | 152 | ||
@@ -160,16 +156,15 @@ bool MessageQueue::isEmpty() | |||
160 | auto t = mStorage.createTransaction(Sink::Storage::ReadOnly); | 156 | auto t = mStorage.createTransaction(Sink::Storage::ReadOnly); |
161 | auto db = t.openDatabase(); | 157 | auto db = t.openDatabase(); |
162 | if (db) { | 158 | if (db) { |
163 | db.scan("", [&count, this](const QByteArray &key, const QByteArray &value) -> bool { | 159 | db.scan("", |
164 | if (!Sink::Storage::isInternalKey(key) && !mPendingRemoval.contains(key)) { | 160 | [&count, this](const QByteArray &key, const QByteArray &value) -> bool { |
165 | count++; | 161 | if (!Sink::Storage::isInternalKey(key) && !mPendingRemoval.contains(key)) { |
166 | return false; | 162 | count++; |
167 | } | 163 | return false; |
168 | return true; | 164 | } |
169 | }, | 165 | return true; |
170 | [](const Sink::Storage::Error &error) { | 166 | }, |
171 | ErrorMsg() << "Error while checking if empty" << error.message; | 167 | [](const Sink::Storage::Error &error) { ErrorMsg() << "Error while checking if empty" << error.message; }); |
172 | }); | ||
173 | } | 168 | } |
174 | return count == 0; | 169 | return count == 0; |
175 | } | 170 | } |
diff --git a/common/messagequeue.h b/common/messagequeue.h index 9399055..6f0bddb 100644 --- a/common/messagequeue.h +++ b/common/messagequeue.h | |||
@@ -16,14 +16,16 @@ class SINK_EXPORT MessageQueue : public QObject | |||
16 | { | 16 | { |
17 | Q_OBJECT | 17 | Q_OBJECT |
18 | public: | 18 | public: |
19 | enum ErrorCodes { | 19 | enum ErrorCodes |
20 | { | ||
20 | NoMessageFound | 21 | NoMessageFound |
21 | }; | 22 | }; |
22 | class Error | 23 | class Error |
23 | { | 24 | { |
24 | public: | 25 | public: |
25 | Error(const QByteArray &s, int c, const QByteArray &m) | 26 | Error(const QByteArray &s, int c, const QByteArray &m) : store(s), message(m), code(c) |
26 | : store(s), message(m), code(c) {} | 27 | { |
28 | } | ||
27 | QByteArray store; | 29 | QByteArray store; |
28 | QByteArray message; | 30 | QByteArray message; |
29 | int code; | 31 | int code; |
@@ -35,11 +37,10 @@ public: | |||
35 | void startTransaction(); | 37 | void startTransaction(); |
36 | void enqueue(void const *msg, size_t size); | 38 | void enqueue(void const *msg, size_t size); |
37 | void enqueue(const QByteArray &value); | 39 | void enqueue(const QByteArray &value); |
38 | //Dequeue a message. This will return a new message everytime called. | 40 | // Dequeue a message. This will return a new message everytime called. |
39 | //Call the result handler with a success response to remove the message from the store. | 41 | // Call the result handler with a success response to remove the message from the store. |
40 | //TODO track processing progress to avoid processing the same message with the same preprocessor twice? | 42 | // TODO track processing progress to avoid processing the same message with the same preprocessor twice? |
41 | void dequeue(const std::function<void(void *ptr, int size, std::function<void(bool success)>)> & resultHandler, | 43 | void dequeue(const std::function<void(void *ptr, int size, std::function<void(bool success)>)> &resultHandler, const std::function<void(const Error &error)> &errorHandler); |
42 | const std::function<void(const Error &error)> &errorHandler); | ||
43 | KAsync::Job<void> dequeueBatch(int maxBatchSize, const std::function<KAsync::Job<void>(const QByteArray &)> &resultHandler); | 44 | KAsync::Job<void> dequeueBatch(int maxBatchSize, const std::function<KAsync::Job<void>(const QByteArray &)> &resultHandler); |
44 | bool isEmpty(); | 45 | bool isEmpty(); |
45 | 46 | ||
diff --git a/common/modelresult.cpp b/common/modelresult.cpp index ceefa76..1c06a7d 100644 --- a/common/modelresult.cpp +++ b/common/modelresult.cpp | |||
@@ -34,11 +34,9 @@ static uint qHash(const Sink::ApplicationDomain::ApplicationDomainType &type) | |||
34 | return qHash(type.resourceInstanceIdentifier() + type.identifier()); | 34 | return qHash(type.resourceInstanceIdentifier() + type.identifier()); |
35 | } | 35 | } |
36 | 36 | ||
37 | template<class T, class Ptr> | 37 | template <class T, class Ptr> |
38 | ModelResult<T, Ptr>::ModelResult(const Sink::Query &query, const QList<QByteArray> &propertyColumns) | 38 | ModelResult<T, Ptr>::ModelResult(const Sink::Query &query, const QList<QByteArray> &propertyColumns) |
39 | :QAbstractItemModel(), | 39 | : QAbstractItemModel(), mPropertyColumns(propertyColumns), mQuery(query) |
40 | mPropertyColumns(propertyColumns), | ||
41 | mQuery(query) | ||
42 | { | 40 | { |
43 | } | 41 | } |
44 | 42 | ||
@@ -50,7 +48,7 @@ static qint64 getIdentifier(const QModelIndex &idx) | |||
50 | return idx.internalId(); | 48 | return idx.internalId(); |
51 | } | 49 | } |
52 | 50 | ||
53 | template<class T, class Ptr> | 51 | template <class T, class Ptr> |
54 | qint64 ModelResult<T, Ptr>::parentId(const Ptr &value) | 52 | qint64 ModelResult<T, Ptr>::parentId(const Ptr &value) |
55 | { | 53 | { |
56 | if (!mQuery.parentProperty.isEmpty()) { | 54 | if (!mQuery.parentProperty.isEmpty()) { |
@@ -62,19 +60,19 @@ qint64 ModelResult<T, Ptr>::parentId(const Ptr &value) | |||
62 | return 0; | 60 | return 0; |
63 | } | 61 | } |
64 | 62 | ||
65 | template<class T, class Ptr> | 63 | template <class T, class Ptr> |
66 | int ModelResult<T, Ptr>::rowCount(const QModelIndex &parent) const | 64 | int ModelResult<T, Ptr>::rowCount(const QModelIndex &parent) const |
67 | { | 65 | { |
68 | return mTree[getIdentifier(parent)].size(); | 66 | return mTree[getIdentifier(parent)].size(); |
69 | } | 67 | } |
70 | 68 | ||
71 | template<class T, class Ptr> | 69 | template <class T, class Ptr> |
72 | int ModelResult<T, Ptr>::columnCount(const QModelIndex &parent) const | 70 | int ModelResult<T, Ptr>::columnCount(const QModelIndex &parent) const |
73 | { | 71 | { |
74 | return mPropertyColumns.size(); | 72 | return mPropertyColumns.size(); |
75 | } | 73 | } |
76 | 74 | ||
77 | template<class T, class Ptr> | 75 | template <class T, class Ptr> |
78 | QVariant ModelResult<T, Ptr>::headerData(int section, Qt::Orientation orientation, int role) const | 76 | QVariant ModelResult<T, Ptr>::headerData(int section, Qt::Orientation orientation, int role) const |
79 | { | 77 | { |
80 | if (role == Qt::DisplayRole) { | 78 | if (role == Qt::DisplayRole) { |
@@ -85,7 +83,7 @@ QVariant ModelResult<T, Ptr>::headerData(int section, Qt::Orientation orientatio | |||
85 | return QVariant(); | 83 | return QVariant(); |
86 | } | 84 | } |
87 | 85 | ||
88 | template<class T, class Ptr> | 86 | template <class T, class Ptr> |
89 | QVariant ModelResult<T, Ptr>::data(const QModelIndex &index, int role) const | 87 | QVariant ModelResult<T, Ptr>::data(const QModelIndex &index, int role) const |
90 | { | 88 | { |
91 | if (role == DomainObjectRole && index.isValid()) { | 89 | if (role == DomainObjectRole && index.isValid()) { |
@@ -94,7 +92,7 @@ QVariant ModelResult<T, Ptr>::data(const QModelIndex &index, int role) const | |||
94 | } | 92 | } |
95 | if (role == DomainObjectBaseRole && index.isValid()) { | 93 | if (role == DomainObjectBaseRole && index.isValid()) { |
96 | Q_ASSERT(mEntities.contains(index.internalId())); | 94 | Q_ASSERT(mEntities.contains(index.internalId())); |
97 | return QVariant::fromValue(mEntities.value(index.internalId()). template staticCast<Sink::ApplicationDomain::ApplicationDomainType>()); | 95 | return QVariant::fromValue(mEntities.value(index.internalId()).template staticCast<Sink::ApplicationDomain::ApplicationDomainType>()); |
98 | } | 96 | } |
99 | if (role == ChildrenFetchedRole) { | 97 | if (role == ChildrenFetchedRole) { |
100 | return childrenFetched(index); | 98 | return childrenFetched(index); |
@@ -111,7 +109,7 @@ QVariant ModelResult<T, Ptr>::data(const QModelIndex &index, int role) const | |||
111 | return QVariant(); | 109 | return QVariant(); |
112 | } | 110 | } |
113 | 111 | ||
114 | template<class T, class Ptr> | 112 | template <class T, class Ptr> |
115 | QModelIndex ModelResult<T, Ptr>::index(int row, int column, const QModelIndex &parent) const | 113 | QModelIndex ModelResult<T, Ptr>::index(int row, int column, const QModelIndex &parent) const |
116 | { | 114 | { |
117 | const auto id = getIdentifier(parent); | 115 | const auto id = getIdentifier(parent); |
@@ -124,7 +122,7 @@ QModelIndex ModelResult<T, Ptr>::index(int row, int column, const QModelIndex &p | |||
124 | return QModelIndex(); | 122 | return QModelIndex(); |
125 | } | 123 | } |
126 | 124 | ||
127 | template<class T, class Ptr> | 125 | template <class T, class Ptr> |
128 | QModelIndex ModelResult<T, Ptr>::createIndexFromId(const qint64 &id) const | 126 | QModelIndex ModelResult<T, Ptr>::createIndexFromId(const qint64 &id) const |
129 | { | 127 | { |
130 | if (id == 0) { | 128 | if (id == 0) { |
@@ -135,7 +133,7 @@ QModelIndex ModelResult<T, Ptr>::createIndexFromId(const qint64 &id) const | |||
135 | return createIndex(row, 0, id); | 133 | return createIndex(row, 0, id); |
136 | } | 134 | } |
137 | 135 | ||
138 | template<class T, class Ptr> | 136 | template <class T, class Ptr> |
139 | QModelIndex ModelResult<T, Ptr>::parent(const QModelIndex &index) const | 137 | QModelIndex ModelResult<T, Ptr>::parent(const QModelIndex &index) const |
140 | { | 138 | { |
141 | auto id = getIdentifier(index); | 139 | auto id = getIdentifier(index); |
@@ -143,7 +141,7 @@ QModelIndex ModelResult<T, Ptr>::parent(const QModelIndex &index) const | |||
143 | return createIndexFromId(parentId); | 141 | return createIndexFromId(parentId); |
144 | } | 142 | } |
145 | 143 | ||
146 | template<class T, class Ptr> | 144 | template <class T, class Ptr> |
147 | bool ModelResult<T, Ptr>::hasChildren(const QModelIndex &parent) const | 145 | bool ModelResult<T, Ptr>::hasChildren(const QModelIndex &parent) const |
148 | { | 146 | { |
149 | if (mQuery.parentProperty.isEmpty() && parent.isValid()) { | 147 | if (mQuery.parentProperty.isEmpty() && parent.isValid()) { |
@@ -152,26 +150,26 @@ bool ModelResult<T, Ptr>::hasChildren(const QModelIndex &parent) const | |||
152 | return QAbstractItemModel::hasChildren(parent); | 150 | return QAbstractItemModel::hasChildren(parent); |
153 | } | 151 | } |
154 | 152 | ||
155 | template<class T, class Ptr> | 153 | template <class T, class Ptr> |
156 | bool ModelResult<T, Ptr>::canFetchMore(const QModelIndex &parent) const | 154 | bool ModelResult<T, Ptr>::canFetchMore(const QModelIndex &parent) const |
157 | { | 155 | { |
158 | const auto id = parent.internalId(); | 156 | const auto id = parent.internalId(); |
159 | return !mEntityChildrenFetched.contains(id) || mEntityChildrenFetchComplete.contains(id); | 157 | return !mEntityChildrenFetched.contains(id) || mEntityChildrenFetchComplete.contains(id); |
160 | } | 158 | } |
161 | 159 | ||
162 | template<class T, class Ptr> | 160 | template <class T, class Ptr> |
163 | void ModelResult<T, Ptr>::fetchMore(const QModelIndex &parent) | 161 | void ModelResult<T, Ptr>::fetchMore(const QModelIndex &parent) |
164 | { | 162 | { |
165 | Trace() << "Fetching more: " << parent; | 163 | Trace() << "Fetching more: " << parent; |
166 | fetchEntities(parent); | 164 | fetchEntities(parent); |
167 | } | 165 | } |
168 | 166 | ||
169 | template<class T, class Ptr> | 167 | template <class T, class Ptr> |
170 | void ModelResult<T, Ptr>::add(const Ptr &value) | 168 | void ModelResult<T, Ptr>::add(const Ptr &value) |
171 | { | 169 | { |
172 | const auto childId = qHash(*value); | 170 | const auto childId = qHash(*value); |
173 | const auto id = parentId(value); | 171 | const auto id = parentId(value); |
174 | //Ignore updates we get before the initial fetch is done | 172 | // Ignore updates we get before the initial fetch is done |
175 | if (!mEntityChildrenFetched.contains(id)) { | 173 | if (!mEntityChildrenFetched.contains(id)) { |
176 | Trace() << "Too early" << id; | 174 | Trace() << "Too early" << id; |
177 | return; | 175 | return; |
@@ -199,7 +197,7 @@ void ModelResult<T, Ptr>::add(const Ptr &value) | |||
199 | } | 197 | } |
200 | 198 | ||
201 | 199 | ||
202 | template<class T, class Ptr> | 200 | template <class T, class Ptr> |
203 | void ModelResult<T, Ptr>::remove(const Ptr &value) | 201 | void ModelResult<T, Ptr>::remove(const Ptr &value) |
204 | { | 202 | { |
205 | auto childId = qHash(*value); | 203 | auto childId = qHash(*value); |
@@ -211,11 +209,11 @@ void ModelResult<T, Ptr>::remove(const Ptr &value) | |||
211 | mEntities.remove(childId); | 209 | mEntities.remove(childId); |
212 | mTree[id].removeAll(childId); | 210 | mTree[id].removeAll(childId); |
213 | mParents.remove(childId); | 211 | mParents.remove(childId); |
214 | //TODO remove children | 212 | // TODO remove children |
215 | endRemoveRows(); | 213 | endRemoveRows(); |
216 | } | 214 | } |
217 | 215 | ||
218 | template<class T, class Ptr> | 216 | template <class T, class Ptr> |
219 | void ModelResult<T, Ptr>::fetchEntities(const QModelIndex &parent) | 217 | void ModelResult<T, Ptr>::fetchEntities(const QModelIndex &parent) |
220 | { | 218 | { |
221 | const auto id = getIdentifier(parent); | 219 | const auto id = getIdentifier(parent); |
@@ -229,26 +227,20 @@ void ModelResult<T, Ptr>::fetchEntities(const QModelIndex &parent) | |||
229 | } | 227 | } |
230 | } | 228 | } |
231 | 229 | ||
232 | template<class T, class Ptr> | 230 | template <class T, class Ptr> |
233 | void ModelResult<T, Ptr>::setFetcher(const std::function<void(const Ptr &parent)> &fetcher) | 231 | void ModelResult<T, Ptr>::setFetcher(const std::function<void(const Ptr &parent)> &fetcher) |
234 | { | 232 | { |
235 | Trace() << "Setting fetcher"; | 233 | Trace() << "Setting fetcher"; |
236 | loadEntities = fetcher; | 234 | loadEntities = fetcher; |
237 | } | 235 | } |
238 | 236 | ||
239 | template<class T, class Ptr> | 237 | template <class T, class Ptr> |
240 | void ModelResult<T, Ptr>::setEmitter(const typename Sink::ResultEmitter<Ptr>::Ptr &emitter) | 238 | void ModelResult<T, Ptr>::setEmitter(const typename Sink::ResultEmitter<Ptr>::Ptr &emitter) |
241 | { | 239 | { |
242 | setFetcher([this](const Ptr &parent) {mEmitter->fetch(parent);}); | 240 | setFetcher([this](const Ptr &parent) { mEmitter->fetch(parent); }); |
243 | emitter->onAdded([this](const Ptr &value) { | 241 | emitter->onAdded([this](const Ptr &value) { this->add(value); }); |
244 | this->add(value); | 242 | emitter->onModified([this](const Ptr &value) { this->modify(value); }); |
245 | }); | 243 | emitter->onRemoved([this](const Ptr &value) { this->remove(value); }); |
246 | emitter->onModified([this](const Ptr &value) { | ||
247 | this->modify(value); | ||
248 | }); | ||
249 | emitter->onRemoved([this](const Ptr &value) { | ||
250 | this->remove(value); | ||
251 | }); | ||
252 | emitter->onInitialResultSetComplete([this](const Ptr &parent) { | 244 | emitter->onInitialResultSetComplete([this](const Ptr &parent) { |
253 | const qint64 parentId = parent ? qHash(*parent) : 0; | 245 | const qint64 parentId = parent ? qHash(*parent) : 0; |
254 | const auto parentIndex = createIndexFromId(parentId); | 246 | const auto parentIndex = createIndexFromId(parentId); |
@@ -258,18 +250,18 @@ void ModelResult<T, Ptr>::setEmitter(const typename Sink::ResultEmitter<Ptr>::Pt | |||
258 | mEmitter = emitter; | 250 | mEmitter = emitter; |
259 | } | 251 | } |
260 | 252 | ||
261 | template<class T, class Ptr> | 253 | template <class T, class Ptr> |
262 | bool ModelResult<T, Ptr>::childrenFetched(const QModelIndex &index) const | 254 | bool ModelResult<T, Ptr>::childrenFetched(const QModelIndex &index) const |
263 | { | 255 | { |
264 | return mEntityChildrenFetchComplete.contains(getIdentifier(index)); | 256 | return mEntityChildrenFetchComplete.contains(getIdentifier(index)); |
265 | } | 257 | } |
266 | 258 | ||
267 | template<class T, class Ptr> | 259 | template <class T, class Ptr> |
268 | void ModelResult<T, Ptr>::modify(const Ptr &value) | 260 | void ModelResult<T, Ptr>::modify(const Ptr &value) |
269 | { | 261 | { |
270 | auto childId = qHash(*value); | 262 | auto childId = qHash(*value); |
271 | auto id = parentId(value); | 263 | auto id = parentId(value); |
272 | //Ignore updates we get before the initial fetch is done | 264 | // Ignore updates we get before the initial fetch is done |
273 | if (!mEntityChildrenFetched.contains(id)) { | 265 | if (!mEntityChildrenFetched.contains(id)) { |
274 | return; | 266 | return; |
275 | } | 267 | } |
@@ -278,7 +270,7 @@ void ModelResult<T, Ptr>::modify(const Ptr &value) | |||
278 | auto i = mTree[id].indexOf(childId); | 270 | auto i = mTree[id].indexOf(childId); |
279 | mEntities.remove(childId); | 271 | mEntities.remove(childId); |
280 | mEntities.insert(childId, value); | 272 | mEntities.insert(childId, value); |
281 | //TODO check for change of parents | 273 | // TODO check for change of parents |
282 | auto idx = index(i, 0, parent); | 274 | auto idx = index(i, 0, parent); |
283 | emit dataChanged(idx, idx); | 275 | emit dataChanged(idx, idx); |
284 | } | 276 | } |
diff --git a/common/modelresult.h b/common/modelresult.h index 062517f..0f0c06a 100644 --- a/common/modelresult.h +++ b/common/modelresult.h | |||
@@ -28,11 +28,12 @@ | |||
28 | #include "query.h" | 28 | #include "query.h" |
29 | #include "resultprovider.h" | 29 | #include "resultprovider.h" |
30 | 30 | ||
31 | template<class T, class Ptr> | 31 | template <class T, class Ptr> |
32 | class ModelResult : public QAbstractItemModel | 32 | class ModelResult : public QAbstractItemModel |
33 | { | 33 | { |
34 | public: | 34 | public: |
35 | enum Roles { | 35 | enum Roles |
36 | { | ||
36 | DomainObjectRole = Qt::UserRole + 1, | 37 | DomainObjectRole = Qt::UserRole + 1, |
37 | ChildrenFetchedRole, | 38 | ChildrenFetchedRole, |
38 | DomainObjectBaseRole | 39 | DomainObjectBaseRole |
@@ -46,7 +47,7 @@ public: | |||
46 | int columnCount(const QModelIndex &parent = QModelIndex()) const; | 47 | int columnCount(const QModelIndex &parent = QModelIndex()) const; |
47 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; | 48 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; |
48 | QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; | 49 | QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; |
49 | QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const; | 50 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; |
50 | QModelIndex parent(const QModelIndex &index) const; | 51 | QModelIndex parent(const QModelIndex &index) const; |
51 | bool hasChildren(const QModelIndex &parent = QModelIndex()) const; | 52 | bool hasChildren(const QModelIndex &parent = QModelIndex()) const; |
52 | 53 | ||
@@ -66,7 +67,7 @@ private: | |||
66 | QModelIndex createIndexFromId(const qint64 &id) const; | 67 | QModelIndex createIndexFromId(const qint64 &id) const; |
67 | void fetchEntities(const QModelIndex &parent); | 68 | void fetchEntities(const QModelIndex &parent); |
68 | 69 | ||
69 | //TODO we should be able to directly use T as index, with an appropriate hash function, and thus have a QMap<T, T> and QList<T> | 70 | // TODO we should be able to directly use T as index, with an appropriate hash function, and thus have a QMap<T, T> and QList<T> |
70 | QMap<qint64 /* entity id */, Ptr> mEntities; | 71 | QMap<qint64 /* entity id */, Ptr> mEntities; |
71 | QMap<qint64 /* parent entity id */, QList<qint64> /* child entity id*/> mTree; | 72 | QMap<qint64 /* parent entity id */, QList<qint64> /* child entity id*/> mTree; |
72 | QMap<qint64 /* child entity id */, qint64 /* parent entity id*/> mParents; | 73 | QMap<qint64 /* child entity id */, qint64 /* parent entity id*/> mParents; |
@@ -77,4 +78,3 @@ private: | |||
77 | std::function<void(const Ptr &)> loadEntities; | 78 | std::function<void(const Ptr &)> loadEntities; |
78 | typename Sink::ResultEmitter<Ptr>::Ptr mEmitter; | 79 | typename Sink::ResultEmitter<Ptr>::Ptr mEmitter; |
79 | }; | 80 | }; |
80 | |||
diff --git a/common/notification.h b/common/notification.h index cf69a99..0eb796d 100644 --- a/common/notification.h +++ b/common/notification.h | |||
@@ -22,8 +22,7 @@ | |||
22 | #include "sink_export.h" | 22 | #include "sink_export.h" |
23 | #include <QString> | 23 | #include <QString> |
24 | 24 | ||
25 | namespace Sink | 25 | namespace Sink { |
26 | { | ||
27 | 26 | ||
28 | /** | 27 | /** |
29 | * A notification | 28 | * A notification |
@@ -36,5 +35,4 @@ public: | |||
36 | QString message; | 35 | QString message; |
37 | int code; | 36 | int code; |
38 | }; | 37 | }; |
39 | |||
40 | } | 38 | } |
diff --git a/common/notifier.cpp b/common/notifier.cpp index e4248df..25d0b85 100644 --- a/common/notifier.cpp +++ b/common/notifier.cpp | |||
@@ -27,20 +27,18 @@ | |||
27 | 27 | ||
28 | using namespace Sink; | 28 | using namespace Sink; |
29 | 29 | ||
30 | class Sink::Notifier::Private { | 30 | class Sink::Notifier::Private |
31 | { | ||
31 | public: | 32 | public: |
32 | Private() | 33 | Private() : context(new QObject) |
33 | : context(new QObject) | ||
34 | { | 34 | { |
35 | |||
36 | } | 35 | } |
37 | QList<QSharedPointer<ResourceAccess> > resourceAccess; | 36 | QList<QSharedPointer<ResourceAccess>> resourceAccess; |
38 | QList<std::function<void(const Notification &)> > handler; | 37 | QList<std::function<void(const Notification &)>> handler; |
39 | QSharedPointer<QObject> context; | 38 | QSharedPointer<QObject> context; |
40 | }; | 39 | }; |
41 | 40 | ||
42 | Notifier::Notifier(const QSharedPointer<ResourceAccess> &resourceAccess) | 41 | Notifier::Notifier(const QSharedPointer<ResourceAccess> &resourceAccess) : d(new Sink::Notifier::Private) |
43 | : d(new Sink::Notifier::Private) | ||
44 | { | 42 | { |
45 | QObject::connect(resourceAccess.data(), &ResourceAccess::notification, d->context.data(), [this](const Notification ¬ification) { | 43 | QObject::connect(resourceAccess.data(), &ResourceAccess::notification, d->context.data(), [this](const Notification ¬ification) { |
46 | for (const auto &handler : d->handler) { | 44 | for (const auto &handler : d->handler) { |
@@ -50,8 +48,7 @@ Notifier::Notifier(const QSharedPointer<ResourceAccess> &resourceAccess) | |||
50 | d->resourceAccess << resourceAccess; | 48 | d->resourceAccess << resourceAccess; |
51 | } | 49 | } |
52 | 50 | ||
53 | Notifier::Notifier(const QByteArray &instanceIdentifier) | 51 | Notifier::Notifier(const QByteArray &instanceIdentifier) : d(new Sink::Notifier::Private) |
54 | : d(new Sink::Notifier::Private) | ||
55 | { | 52 | { |
56 | auto resourceAccess = Sink::ResourceAccess::Ptr::create(instanceIdentifier); | 53 | auto resourceAccess = Sink::ResourceAccess::Ptr::create(instanceIdentifier); |
57 | resourceAccess->open(); | 54 | resourceAccess->open(); |
diff --git a/common/notifier.h b/common/notifier.h index d16a311..9e75dde 100644 --- a/common/notifier.h +++ b/common/notifier.h | |||
@@ -32,7 +32,8 @@ namespace Sink { | |||
32 | class ResourceAccess; | 32 | class ResourceAccess; |
33 | class Notification; | 33 | class Notification; |
34 | 34 | ||
35 | class SINK_EXPORT Notifier { | 35 | class SINK_EXPORT Notifier |
36 | { | ||
36 | public: | 37 | public: |
37 | Notifier(const QSharedPointer<ResourceAccess> &resourceAccess); | 38 | Notifier(const QSharedPointer<ResourceAccess> &resourceAccess); |
38 | Notifier(const QByteArray &resourceInstanceIdentifier); | 39 | Notifier(const QByteArray &resourceInstanceIdentifier); |
@@ -42,5 +43,4 @@ private: | |||
42 | class Private; | 43 | class Private; |
43 | QSharedPointer<Private> d; | 44 | QSharedPointer<Private> d; |
44 | }; | 45 | }; |
45 | |||
46 | } | 46 | } |
diff --git a/common/pipeline.cpp b/common/pipeline.cpp index 35e582b..65a2f5b 100644 --- a/common/pipeline.cpp +++ b/common/pipeline.cpp | |||
@@ -40,21 +40,18 @@ | |||
40 | #undef DEBUG_AREA | 40 | #undef DEBUG_AREA |
41 | #define DEBUG_AREA "resource.pipeline" | 41 | #define DEBUG_AREA "resource.pipeline" |
42 | 42 | ||
43 | namespace Sink | 43 | namespace Sink { |
44 | { | ||
45 | 44 | ||
46 | class Pipeline::Private | 45 | class Pipeline::Private |
47 | { | 46 | { |
48 | public: | 47 | public: |
49 | Private(const QString &resourceName) | 48 | Private(const QString &resourceName) : storage(Sink::storageLocation(), resourceName, Storage::ReadWrite), revisionChanged(false) |
50 | : storage(Sink::storageLocation(), resourceName, Storage::ReadWrite), | ||
51 | revisionChanged(false) | ||
52 | { | 49 | { |
53 | } | 50 | } |
54 | 51 | ||
55 | Storage storage; | 52 | Storage storage; |
56 | Storage::Transaction transaction; | 53 | Storage::Transaction transaction; |
57 | QHash<QString, QVector<Preprocessor *> > processors; | 54 | QHash<QString, QVector<Preprocessor *>> processors; |
58 | QHash<QString, DomainTypeAdaptorFactoryInterface::Ptr> adaptorFactory; | 55 | QHash<QString, DomainTypeAdaptorFactoryInterface::Ptr> adaptorFactory; |
59 | bool revisionChanged; | 56 | bool revisionChanged; |
60 | void storeNewRevision(qint64 newRevision, const flatbuffers::FlatBufferBuilder &fbb, const QByteArray &bufferType, const QByteArray &uid); | 57 | void storeNewRevision(qint64 newRevision, const flatbuffers::FlatBufferBuilder &fbb, const QByteArray &bufferType, const QByteArray &uid); |
@@ -64,20 +61,16 @@ public: | |||
64 | 61 | ||
65 | void Pipeline::Private::storeNewRevision(qint64 newRevision, const flatbuffers::FlatBufferBuilder &fbb, const QByteArray &bufferType, const QByteArray &uid) | 62 | void Pipeline::Private::storeNewRevision(qint64 newRevision, const flatbuffers::FlatBufferBuilder &fbb, const QByteArray &bufferType, const QByteArray &uid) |
66 | { | 63 | { |
67 | Storage::mainDatabase(transaction, bufferType).write(Storage::assembleKey(uid, newRevision), BufferUtils::extractBuffer(fbb), | 64 | Storage::mainDatabase(transaction, bufferType) |
68 | [uid, newRevision](const Storage::Error &error) { | 65 | .write(Storage::assembleKey(uid, newRevision), BufferUtils::extractBuffer(fbb), |
69 | Warning() << "Failed to write entity" << uid << newRevision; | 66 | [uid, newRevision](const Storage::Error &error) { Warning() << "Failed to write entity" << uid << newRevision; }); |
70 | } | ||
71 | ); | ||
72 | revisionChanged = true; | 67 | revisionChanged = true; |
73 | Storage::setMaxRevision(transaction, newRevision); | 68 | Storage::setMaxRevision(transaction, newRevision); |
74 | Storage::recordRevision(transaction, newRevision, uid, bufferType); | 69 | Storage::recordRevision(transaction, newRevision, uid, bufferType); |
75 | } | 70 | } |
76 | 71 | ||
77 | 72 | ||
78 | Pipeline::Pipeline(const QString &resourceName, QObject *parent) | 73 | Pipeline::Pipeline(const QString &resourceName, QObject *parent) : QObject(parent), d(new Private(resourceName)) |
79 | : QObject(parent), | ||
80 | d(new Private(resourceName)) | ||
81 | { | 74 | { |
82 | } | 75 | } |
83 | 76 | ||
@@ -98,8 +91,8 @@ void Pipeline::setAdaptorFactory(const QString &entityType, DomainTypeAdaptorFac | |||
98 | 91 | ||
99 | void Pipeline::startTransaction() | 92 | void Pipeline::startTransaction() |
100 | { | 93 | { |
101 | //TODO call for all types | 94 | // TODO call for all types |
102 | //But avoid doing it during cleanup | 95 | // But avoid doing it during cleanup |
103 | // for (auto processor : d->processors[bufferType]) { | 96 | // for (auto processor : d->processors[bufferType]) { |
104 | // processor->startBatch(); | 97 | // processor->startBatch(); |
105 | // } | 98 | // } |
@@ -114,14 +107,15 @@ void Pipeline::startTransaction() | |||
114 | 107 | ||
115 | void Pipeline::commit() | 108 | void Pipeline::commit() |
116 | { | 109 | { |
117 | //TODO call for all types | 110 | // TODO call for all types |
118 | //But avoid doing it during cleanup | 111 | // But avoid doing it during cleanup |
119 | // for (auto processor : d->processors[bufferType]) { | 112 | // for (auto processor : d->processors[bufferType]) { |
120 | // processor->finalize(); | 113 | // processor->finalize(); |
121 | // } | 114 | // } |
122 | const auto revision = Storage::maxRevision(d->transaction); | 115 | const auto revision = Storage::maxRevision(d->transaction); |
123 | const auto elapsed = d->transactionTime.elapsed(); | 116 | const auto elapsed = d->transactionTime.elapsed(); |
124 | Trace() << "Committing revision: " << revision << ":" << d->transactionItemCount << " items in: " << Log::TraceTime(elapsed) << " " << (double)elapsed/(double)qMax(d->transactionItemCount, 1) << "[ms/item]"; | 117 | Trace() << "Committing revision: " << revision << ":" << d->transactionItemCount << " items in: " << Log::TraceTime(elapsed) << " " |
118 | << (double)elapsed / (double)qMax(d->transactionItemCount, 1) << "[ms/item]"; | ||
125 | if (d->transaction) { | 119 | if (d->transaction) { |
126 | d->transaction.commit(); | 120 | d->transaction.commit(); |
127 | } | 121 | } |
@@ -157,7 +151,7 @@ KAsync::Job<qint64> Pipeline::newEntity(void const *command, size_t size) | |||
157 | auto createEntity = Commands::GetCreateEntity(command); | 151 | auto createEntity = Commands::GetCreateEntity(command); |
158 | 152 | ||
159 | const bool replayToSource = createEntity->replayToSource(); | 153 | const bool replayToSource = createEntity->replayToSource(); |
160 | const QByteArray bufferType = QByteArray(reinterpret_cast<char const*>(createEntity->domainType()->Data()), createEntity->domainType()->size()); | 154 | const QByteArray bufferType = QByteArray(reinterpret_cast<char const *>(createEntity->domainType()->Data()), createEntity->domainType()->size()); |
161 | { | 155 | { |
162 | flatbuffers::Verifier verifyer(reinterpret_cast<const uint8_t *>(createEntity->delta()->Data()), createEntity->delta()->size()); | 156 | flatbuffers::Verifier verifyer(reinterpret_cast<const uint8_t *>(createEntity->delta()->Data()), createEntity->delta()->size()); |
163 | if (!VerifyEntityBuffer(verifyer)) { | 157 | if (!VerifyEntityBuffer(verifyer)) { |
@@ -173,7 +167,7 @@ KAsync::Job<qint64> Pipeline::newEntity(void const *command, size_t size) | |||
173 | 167 | ||
174 | QByteArray key; | 168 | QByteArray key; |
175 | if (createEntity->entityId()) { | 169 | if (createEntity->entityId()) { |
176 | key = QByteArray(reinterpret_cast<char const*>(createEntity->entityId()->Data()), createEntity->entityId()->size()); | 170 | key = QByteArray(reinterpret_cast<char const *>(createEntity->entityId()->Data()), createEntity->entityId()->size()); |
177 | if (Storage::mainDatabase(d->transaction, bufferType).contains(key)) { | 171 | if (Storage::mainDatabase(d->transaction, bufferType).contains(key)) { |
178 | ErrorMsg() << "An entity with this id already exists: " << key; | 172 | ErrorMsg() << "An entity with this id already exists: " << key; |
179 | return KAsync::error<qint64>(0); | 173 | return KAsync::error<qint64>(0); |
@@ -186,7 +180,7 @@ KAsync::Job<qint64> Pipeline::newEntity(void const *command, size_t size) | |||
186 | Q_ASSERT(!key.isEmpty()); | 180 | Q_ASSERT(!key.isEmpty()); |
187 | const qint64 newRevision = Storage::maxRevision(d->transaction) + 1; | 181 | const qint64 newRevision = Storage::maxRevision(d->transaction) + 1; |
188 | 182 | ||
189 | //Add metadata buffer | 183 | // Add metadata buffer |
190 | flatbuffers::FlatBufferBuilder metadataFbb; | 184 | flatbuffers::FlatBufferBuilder metadataFbb; |
191 | auto metadataBuilder = MetadataBuilder(metadataFbb); | 185 | auto metadataBuilder = MetadataBuilder(metadataFbb); |
192 | metadataBuilder.add_revision(newRevision); | 186 | metadataBuilder.add_revision(newRevision); |
@@ -196,7 +190,8 @@ KAsync::Job<qint64> Pipeline::newEntity(void const *command, size_t size) | |||
196 | FinishMetadataBuffer(metadataFbb, metadataBuffer); | 190 | FinishMetadataBuffer(metadataFbb, metadataBuffer); |
197 | 191 | ||
198 | flatbuffers::FlatBufferBuilder fbb; | 192 | flatbuffers::FlatBufferBuilder fbb; |
199 | EntityBuffer::assembleEntityBuffer(fbb, metadataFbb.GetBufferPointer(), metadataFbb.GetSize(), entity->resource()->Data(), entity->resource()->size(), entity->local()->Data(), entity->local()->size()); | 193 | EntityBuffer::assembleEntityBuffer( |
194 | fbb, metadataFbb.GetBufferPointer(), metadataFbb.GetSize(), entity->resource()->Data(), entity->resource()->size(), entity->local()->Data(), entity->local()->size()); | ||
200 | 195 | ||
201 | d->storeNewRevision(newRevision, fbb, bufferType, key); | 196 | d->storeNewRevision(newRevision, fbb, bufferType, key); |
202 | 197 | ||
@@ -207,20 +202,19 @@ KAsync::Job<qint64> Pipeline::newEntity(void const *command, size_t size) | |||
207 | } | 202 | } |
208 | 203 | ||
209 | Log() << "Pipeline: wrote entity: " << key << newRevision << bufferType; | 204 | Log() << "Pipeline: wrote entity: " << key << newRevision << bufferType; |
210 | Storage::mainDatabase(d->transaction, bufferType).scan(Storage::assembleKey(key, newRevision), [this, bufferType, newRevision, adaptorFactory, key](const QByteArray &, const QByteArray &value) -> bool { | 205 | Storage::mainDatabase(d->transaction, bufferType) |
211 | auto entity = GetEntity(value); | 206 | .scan(Storage::assembleKey(key, newRevision), |
212 | Q_ASSERT(entity->resource() || entity->local()); | 207 | [this, bufferType, newRevision, adaptorFactory, key](const QByteArray &, const QByteArray &value) -> bool { |
213 | auto adaptor = adaptorFactory->createAdaptor(*entity); | 208 | auto entity = GetEntity(value); |
214 | for (auto processor : d->processors[bufferType]) { | 209 | Q_ASSERT(entity->resource() || entity->local()); |
215 | processor->newEntity(key, newRevision, *adaptor, d->transaction); | 210 | auto adaptor = adaptorFactory->createAdaptor(*entity); |
216 | } | 211 | for (auto processor : d->processors[bufferType]) { |
217 | return false; | 212 | processor->newEntity(key, newRevision, *adaptor, d->transaction); |
218 | }, [this](const Storage::Error &error) { | 213 | } |
219 | ErrorMsg() << "Failed to find value in pipeline: " << error.message; | 214 | return false; |
220 | }); | 215 | }, |
221 | return KAsync::start<qint64>([newRevision](){ | 216 | [this](const Storage::Error &error) { ErrorMsg() << "Failed to find value in pipeline: " << error.message; }); |
222 | return newRevision; | 217 | return KAsync::start<qint64>([newRevision]() { return newRevision; }); |
223 | }); | ||
224 | } | 218 | } |
225 | 219 | ||
226 | KAsync::Job<qint64> Pipeline::modifiedEntity(void const *command, size_t size) | 220 | KAsync::Job<qint64> Pipeline::modifiedEntity(void const *command, size_t size) |
@@ -242,9 +236,9 @@ KAsync::Job<qint64> Pipeline::modifiedEntity(void const *command, size_t size) | |||
242 | 236 | ||
243 | const qint64 baseRevision = modifyEntity->revision(); | 237 | const qint64 baseRevision = modifyEntity->revision(); |
244 | const bool replayToSource = modifyEntity->replayToSource(); | 238 | const bool replayToSource = modifyEntity->replayToSource(); |
245 | //TODO rename modifyEntity->domainType to bufferType | 239 | // TODO rename modifyEntity->domainType to bufferType |
246 | const QByteArray bufferType = QByteArray(reinterpret_cast<char const*>(modifyEntity->domainType()->Data()), modifyEntity->domainType()->size()); | 240 | const QByteArray bufferType = QByteArray(reinterpret_cast<char const *>(modifyEntity->domainType()->Data()), modifyEntity->domainType()->size()); |
247 | const QByteArray key = QByteArray(reinterpret_cast<char const*>(modifyEntity->entityId()->Data()), modifyEntity->entityId()->size()); | 241 | const QByteArray key = QByteArray(reinterpret_cast<char const *>(modifyEntity->entityId()->Data()), modifyEntity->entityId()->size()); |
248 | if (bufferType.isEmpty() || key.isEmpty()) { | 242 | if (bufferType.isEmpty() || key.isEmpty()) { |
249 | Warning() << "entity type or key " << bufferType << key; | 243 | Warning() << "entity type or key " << bufferType << key; |
250 | return KAsync::error<qint64>(0); | 244 | return KAsync::error<qint64>(0); |
@@ -257,7 +251,7 @@ KAsync::Job<qint64> Pipeline::modifiedEntity(void const *command, size_t size) | |||
257 | } | 251 | } |
258 | } | 252 | } |
259 | 253 | ||
260 | //TODO use only readPropertyMapper and writePropertyMapper | 254 | // TODO use only readPropertyMapper and writePropertyMapper |
261 | auto adaptorFactory = d->adaptorFactory.value(bufferType); | 255 | auto adaptorFactory = d->adaptorFactory.value(bufferType); |
262 | if (!adaptorFactory) { | 256 | if (!adaptorFactory) { |
263 | Warning() << "no adaptor factory for type " << bufferType; | 257 | Warning() << "no adaptor factory for type " << bufferType; |
@@ -269,30 +263,30 @@ KAsync::Job<qint64> Pipeline::modifiedEntity(void const *command, size_t size) | |||
269 | auto diff = adaptorFactory->createAdaptor(*diffEntity); | 263 | auto diff = adaptorFactory->createAdaptor(*diffEntity); |
270 | 264 | ||
271 | QSharedPointer<ApplicationDomain::BufferAdaptor> current; | 265 | QSharedPointer<ApplicationDomain::BufferAdaptor> current; |
272 | Storage::mainDatabase(d->transaction, bufferType).findLatest(key, [¤t, adaptorFactory](const QByteArray &key, const QByteArray &data) -> bool { | 266 | Storage::mainDatabase(d->transaction, bufferType) |
273 | EntityBuffer buffer(const_cast<const char *>(data.data()), data.size()); | 267 | .findLatest(key, |
274 | if (!buffer.isValid()) { | 268 | [¤t, adaptorFactory](const QByteArray &key, const QByteArray &data) -> bool { |
275 | Warning() << "Read invalid buffer from disk"; | 269 | EntityBuffer buffer(const_cast<const char *>(data.data()), data.size()); |
276 | } else { | 270 | if (!buffer.isValid()) { |
277 | current = adaptorFactory->createAdaptor(buffer.entity()); | 271 | Warning() << "Read invalid buffer from disk"; |
278 | } | 272 | } else { |
279 | return false; | 273 | current = adaptorFactory->createAdaptor(buffer.entity()); |
280 | }, | 274 | } |
281 | [baseRevision](const Storage::Error &error) { | 275 | return false; |
282 | Warning() << "Failed to read old revision from storage: " << error.message << "Revision: " << baseRevision; | 276 | }, |
283 | }); | 277 | [baseRevision](const Storage::Error &error) { Warning() << "Failed to read old revision from storage: " << error.message << "Revision: " << baseRevision; }); |
284 | 278 | ||
285 | if (!current) { | 279 | if (!current) { |
286 | Warning() << "Failed to read local value " << key; | 280 | Warning() << "Failed to read local value " << key; |
287 | return KAsync::error<qint64>(0); | 281 | return KAsync::error<qint64>(0); |
288 | } | 282 | } |
289 | 283 | ||
290 | //resource and uid don't matter at this point | 284 | // resource and uid don't matter at this point |
291 | const ApplicationDomain::ApplicationDomainType existingObject("", "", newRevision, current); | 285 | const ApplicationDomain::ApplicationDomainType existingObject("", "", newRevision, current); |
292 | auto newObject = ApplicationDomain::ApplicationDomainType::getInMemoryRepresentation<ApplicationDomain::ApplicationDomainType>(existingObject); | 286 | auto newObject = ApplicationDomain::ApplicationDomainType::getInMemoryRepresentation<ApplicationDomain::ApplicationDomainType>(existingObject); |
293 | 287 | ||
294 | //Apply diff | 288 | // Apply diff |
295 | //FIXME only apply the properties that are available in the buffer | 289 | // FIXME only apply the properties that are available in the buffer |
296 | Trace() << "Applying changed properties: " << diff->availableProperties(); | 290 | Trace() << "Applying changed properties: " << diff->availableProperties(); |
297 | QSet<QByteArray> changeset; | 291 | QSet<QByteArray> changeset; |
298 | for (const auto &property : diff->availableProperties()) { | 292 | for (const auto &property : diff->availableProperties()) { |
@@ -302,17 +296,17 @@ KAsync::Job<qint64> Pipeline::modifiedEntity(void const *command, size_t size) | |||
302 | newObject->setProperty(property, value); | 296 | newObject->setProperty(property, value); |
303 | } | 297 | } |
304 | } | 298 | } |
305 | //Altough we only set some properties, we want all to be serialized | 299 | // Altough we only set some properties, we want all to be serialized |
306 | newObject->setChangedProperties(changeset); | 300 | newObject->setChangedProperties(changeset); |
307 | 301 | ||
308 | //Remove deletions | 302 | // Remove deletions |
309 | if (modifyEntity->deletions()) { | 303 | if (modifyEntity->deletions()) { |
310 | for (const auto &property : *modifyEntity->deletions()) { | 304 | for (const auto &property : *modifyEntity->deletions()) { |
311 | newObject->setProperty(BufferUtils::extractBuffer(property), QVariant()); | 305 | newObject->setProperty(BufferUtils::extractBuffer(property), QVariant()); |
312 | } | 306 | } |
313 | } | 307 | } |
314 | 308 | ||
315 | //Add metadata buffer | 309 | // Add metadata buffer |
316 | flatbuffers::FlatBufferBuilder metadataFbb; | 310 | flatbuffers::FlatBufferBuilder metadataFbb; |
317 | auto metadataBuilder = MetadataBuilder(metadataFbb); | 311 | auto metadataBuilder = MetadataBuilder(metadataFbb); |
318 | metadataBuilder.add_revision(newRevision); | 312 | metadataBuilder.add_revision(newRevision); |
@@ -326,22 +320,21 @@ KAsync::Job<qint64> Pipeline::modifiedEntity(void const *command, size_t size) | |||
326 | 320 | ||
327 | d->storeNewRevision(newRevision, fbb, bufferType, key); | 321 | d->storeNewRevision(newRevision, fbb, bufferType, key); |
328 | Log() << "Pipeline: modified entity: " << key << newRevision << bufferType; | 322 | Log() << "Pipeline: modified entity: " << key << newRevision << bufferType; |
329 | Storage::mainDatabase(d->transaction, bufferType).scan(Storage::assembleKey(key, newRevision), [this, bufferType, newRevision, adaptorFactory, current, key](const QByteArray &k, const QByteArray &value) -> bool { | 323 | Storage::mainDatabase(d->transaction, bufferType) |
330 | if (value.isEmpty()) { | 324 | .scan(Storage::assembleKey(key, newRevision), |
331 | ErrorMsg() << "Read buffer is empty."; | 325 | [this, bufferType, newRevision, adaptorFactory, current, key](const QByteArray &k, const QByteArray &value) -> bool { |
332 | } | 326 | if (value.isEmpty()) { |
333 | auto entity = GetEntity(value.data()); | 327 | ErrorMsg() << "Read buffer is empty."; |
334 | auto newEntity = adaptorFactory->createAdaptor(*entity); | 328 | } |
335 | for (auto processor : d->processors[bufferType]) { | 329 | auto entity = GetEntity(value.data()); |
336 | processor->modifiedEntity(key, newRevision, *current, *newEntity, d->transaction); | 330 | auto newEntity = adaptorFactory->createAdaptor(*entity); |
337 | } | 331 | for (auto processor : d->processors[bufferType]) { |
338 | return false; | 332 | processor->modifiedEntity(key, newRevision, *current, *newEntity, d->transaction); |
339 | }, [this](const Storage::Error &error) { | 333 | } |
340 | ErrorMsg() << "Failed to find value in pipeline: " << error.message; | 334 | return false; |
341 | }); | 335 | }, |
342 | return KAsync::start<qint64>([newRevision](){ | 336 | [this](const Storage::Error &error) { ErrorMsg() << "Failed to find value in pipeline: " << error.message; }); |
343 | return newRevision; | 337 | return KAsync::start<qint64>([newRevision]() { return newRevision; }); |
344 | }); | ||
345 | } | 338 | } |
346 | 339 | ||
347 | KAsync::Job<qint64> Pipeline::deletedEntity(void const *command, size_t size) | 340 | KAsync::Job<qint64> Pipeline::deletedEntity(void const *command, size_t size) |
@@ -359,26 +352,25 @@ KAsync::Job<qint64> Pipeline::deletedEntity(void const *command, size_t size) | |||
359 | auto deleteEntity = Commands::GetDeleteEntity(command); | 352 | auto deleteEntity = Commands::GetDeleteEntity(command); |
360 | 353 | ||
361 | const bool replayToSource = deleteEntity->replayToSource(); | 354 | const bool replayToSource = deleteEntity->replayToSource(); |
362 | const QByteArray bufferType = QByteArray(reinterpret_cast<char const*>(deleteEntity->domainType()->Data()), deleteEntity->domainType()->size()); | 355 | const QByteArray bufferType = QByteArray(reinterpret_cast<char const *>(deleteEntity->domainType()->Data()), deleteEntity->domainType()->size()); |
363 | const QByteArray key = QByteArray(reinterpret_cast<char const*>(deleteEntity->entityId()->Data()), deleteEntity->entityId()->size()); | 356 | const QByteArray key = QByteArray(reinterpret_cast<char const *>(deleteEntity->entityId()->Data()), deleteEntity->entityId()->size()); |
364 | 357 | ||
365 | bool found = false; | 358 | bool found = false; |
366 | bool alreadyRemoved = false; | 359 | bool alreadyRemoved = false; |
367 | Storage::mainDatabase(d->transaction, bufferType).findLatest(key, [&found, &alreadyRemoved](const QByteArray &key, const QByteArray &data) -> bool { | 360 | Storage::mainDatabase(d->transaction, bufferType) |
368 | auto entity = GetEntity(data.data()); | 361 | .findLatest(key, |
369 | if (entity && entity->metadata()) { | 362 | [&found, &alreadyRemoved](const QByteArray &key, const QByteArray &data) -> bool { |
370 | auto metadata = GetMetadata(entity->metadata()->Data()); | 363 | auto entity = GetEntity(data.data()); |
371 | found = true; | 364 | if (entity && entity->metadata()) { |
372 | if (metadata->operation() == Operation_Removal) { | 365 | auto metadata = GetMetadata(entity->metadata()->Data()); |
373 | alreadyRemoved = true; | 366 | found = true; |
374 | } | 367 | if (metadata->operation() == Operation_Removal) { |
375 | 368 | alreadyRemoved = true; | |
376 | } | 369 | } |
377 | return false; | 370 | } |
378 | }, | 371 | return false; |
379 | [](const Storage::Error &error) { | 372 | }, |
380 | Warning() << "Failed to read old revision from storage: " << error.message; | 373 | [](const Storage::Error &error) { Warning() << "Failed to read old revision from storage: " << error.message; }); |
381 | }); | ||
382 | 374 | ||
383 | if (!found) { | 375 | if (!found) { |
384 | Warning() << "Failed to find entity " << key; | 376 | Warning() << "Failed to find entity " << key; |
@@ -391,7 +383,7 @@ KAsync::Job<qint64> Pipeline::deletedEntity(void const *command, size_t size) | |||
391 | 383 | ||
392 | const qint64 newRevision = Storage::maxRevision(d->transaction) + 1; | 384 | const qint64 newRevision = Storage::maxRevision(d->transaction) + 1; |
393 | 385 | ||
394 | //Add metadata buffer | 386 | // Add metadata buffer |
395 | flatbuffers::FlatBufferBuilder metadataFbb; | 387 | flatbuffers::FlatBufferBuilder metadataFbb; |
396 | auto metadataBuilder = MetadataBuilder(metadataFbb); | 388 | auto metadataBuilder = MetadataBuilder(metadataFbb); |
397 | metadataBuilder.add_revision(newRevision); | 389 | metadataBuilder.add_revision(newRevision); |
@@ -410,28 +402,27 @@ KAsync::Job<qint64> Pipeline::deletedEntity(void const *command, size_t size) | |||
410 | } | 402 | } |
411 | 403 | ||
412 | QSharedPointer<ApplicationDomain::BufferAdaptor> current; | 404 | QSharedPointer<ApplicationDomain::BufferAdaptor> current; |
413 | Storage::mainDatabase(d->transaction, bufferType).findLatest(key, [this, bufferType, newRevision, adaptorFactory, key, ¤t](const QByteArray &, const QByteArray &data) -> bool { | 405 | Storage::mainDatabase(d->transaction, bufferType) |
414 | EntityBuffer buffer(const_cast<const char *>(data.data()), data.size()); | 406 | .findLatest(key, |
415 | if (!buffer.isValid()) { | 407 | [this, bufferType, newRevision, adaptorFactory, key, ¤t](const QByteArray &, const QByteArray &data) -> bool { |
416 | Warning() << "Read invalid buffer from disk"; | 408 | EntityBuffer buffer(const_cast<const char *>(data.data()), data.size()); |
417 | } else { | 409 | if (!buffer.isValid()) { |
418 | current = adaptorFactory->createAdaptor(buffer.entity()); | 410 | Warning() << "Read invalid buffer from disk"; |
419 | } | 411 | } else { |
420 | return false; | 412 | current = adaptorFactory->createAdaptor(buffer.entity()); |
421 | }, [this](const Storage::Error &error) { | 413 | } |
422 | ErrorMsg() << "Failed to find value in pipeline: " << error.message; | 414 | return false; |
423 | }); | 415 | }, |
416 | [this](const Storage::Error &error) { ErrorMsg() << "Failed to find value in pipeline: " << error.message; }); | ||
424 | 417 | ||
425 | d->storeNewRevision(newRevision, fbb, bufferType, key); | 418 | d->storeNewRevision(newRevision, fbb, bufferType, key); |
426 | Log() << "Pipeline: deleted entity: "<< newRevision; | 419 | Log() << "Pipeline: deleted entity: " << newRevision; |
427 | 420 | ||
428 | for (auto processor : d->processors[bufferType]) { | 421 | for (auto processor : d->processors[bufferType]) { |
429 | processor->deletedEntity(key, newRevision, *current, d->transaction); | 422 | processor->deletedEntity(key, newRevision, *current, d->transaction); |
430 | } | 423 | } |
431 | 424 | ||
432 | return KAsync::start<qint64>([newRevision](){ | 425 | return KAsync::start<qint64>([newRevision]() { return newRevision; }); |
433 | return newRevision; | ||
434 | }); | ||
435 | } | 426 | } |
436 | 427 | ||
437 | void Pipeline::cleanupRevision(qint64 revision) | 428 | void Pipeline::cleanupRevision(qint64 revision) |
@@ -439,24 +430,25 @@ void Pipeline::cleanupRevision(qint64 revision) | |||
439 | const auto uid = Storage::getUidFromRevision(d->transaction, revision); | 430 | const auto uid = Storage::getUidFromRevision(d->transaction, revision); |
440 | const auto bufferType = Storage::getTypeFromRevision(d->transaction, revision); | 431 | const auto bufferType = Storage::getTypeFromRevision(d->transaction, revision); |
441 | Trace() << "Cleaning up revision " << revision << uid << bufferType; | 432 | Trace() << "Cleaning up revision " << revision << uid << bufferType; |
442 | Storage::mainDatabase(d->transaction, bufferType).scan(uid, [&](const QByteArray &key, const QByteArray &data) -> bool { | 433 | Storage::mainDatabase(d->transaction, bufferType) |
443 | EntityBuffer buffer(const_cast<const char *>(data.data()), data.size()); | 434 | .scan(uid, |
444 | if (!buffer.isValid()) { | 435 | [&](const QByteArray &key, const QByteArray &data) -> bool { |
445 | Warning() << "Read invalid buffer from disk"; | 436 | EntityBuffer buffer(const_cast<const char *>(data.data()), data.size()); |
446 | } else { | 437 | if (!buffer.isValid()) { |
447 | const auto metadata = flatbuffers::GetRoot<Metadata>(buffer.metadataBuffer()); | 438 | Warning() << "Read invalid buffer from disk"; |
448 | const qint64 rev = metadata->revision(); | 439 | } else { |
449 | //Remove old revisions, and the current if the entity has already been removed | 440 | const auto metadata = flatbuffers::GetRoot<Metadata>(buffer.metadataBuffer()); |
450 | if (rev < revision || metadata->operation() == Operation_Removal) { | 441 | const qint64 rev = metadata->revision(); |
451 | Storage::removeRevision(d->transaction, rev); | 442 | // Remove old revisions, and the current if the entity has already been removed |
452 | Storage::mainDatabase(d->transaction, bufferType).remove(key); | 443 | if (rev < revision || metadata->operation() == Operation_Removal) { |
453 | } | 444 | Storage::removeRevision(d->transaction, rev); |
454 | } | 445 | Storage::mainDatabase(d->transaction, bufferType).remove(key); |
455 | 446 | } | |
456 | return true; | 447 | } |
457 | }, [](const Storage::Error &error) { | 448 | |
458 | Warning() << "Error while reading: " << error.message; | 449 | return true; |
459 | }, true); | 450 | }, |
451 | [](const Storage::Error &error) { Warning() << "Error while reading: " << error.message; }, true); | ||
460 | Storage::setCleanedUpRevision(d->transaction, revision); | 452 | Storage::setCleanedUpRevision(d->transaction, revision); |
461 | } | 453 | } |
462 | 454 | ||
@@ -465,8 +457,7 @@ qint64 Pipeline::cleanedUpRevision() | |||
465 | return Storage::cleanedUpRevision(d->transaction); | 457 | return Storage::cleanedUpRevision(d->transaction); |
466 | } | 458 | } |
467 | 459 | ||
468 | Preprocessor::Preprocessor() | 460 | Preprocessor::Preprocessor() : d(0) |
469 | : d(0) | ||
470 | { | 461 | { |
471 | } | 462 | } |
472 | 463 | ||
diff --git a/common/pipeline.h b/common/pipeline.h index 0f989e4..dc2cc4d 100644 --- a/common/pipeline.h +++ b/common/pipeline.h | |||
@@ -32,8 +32,7 @@ | |||
32 | 32 | ||
33 | #include "domainadaptor.h" | 33 | #include "domainadaptor.h" |
34 | 34 | ||
35 | namespace Sink | 35 | namespace Sink { |
36 | { | ||
37 | 36 | ||
38 | class Preprocessor; | 37 | class Preprocessor; |
39 | 38 | ||
@@ -74,7 +73,7 @@ signals: | |||
74 | 73 | ||
75 | private: | 74 | private: |
76 | class Private; | 75 | class Private; |
77 | Private * const d; | 76 | Private *const d; |
78 | }; | 77 | }; |
79 | 78 | ||
80 | class SINK_EXPORT Preprocessor | 79 | class SINK_EXPORT Preprocessor |
@@ -85,14 +84,14 @@ public: | |||
85 | 84 | ||
86 | virtual void startBatch(); | 85 | virtual void startBatch(); |
87 | virtual void newEntity(const QByteArray &key, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &newEntity, Sink::Storage::Transaction &transaction) = 0; | 86 | virtual void newEntity(const QByteArray &key, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &newEntity, Sink::Storage::Transaction &transaction) = 0; |
88 | virtual void modifiedEntity(const QByteArray &key, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &oldEntity, const Sink::ApplicationDomain::BufferAdaptor &newEntity, Sink::Storage::Transaction &transaction) = 0; | 87 | virtual void modifiedEntity(const QByteArray &key, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &oldEntity, |
88 | const Sink::ApplicationDomain::BufferAdaptor &newEntity, Sink::Storage::Transaction &transaction) = 0; | ||
89 | virtual void deletedEntity(const QByteArray &key, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &oldEntity, Sink::Storage::Transaction &transaction) = 0; | 89 | virtual void deletedEntity(const QByteArray &key, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &oldEntity, Sink::Storage::Transaction &transaction) = 0; |
90 | virtual void finalize(); | 90 | virtual void finalize(); |
91 | 91 | ||
92 | private: | 92 | private: |
93 | class Private; | 93 | class Private; |
94 | Private * const d; | 94 | Private *const d; |
95 | }; | 95 | }; |
96 | 96 | ||
97 | } // namespace Sink | 97 | } // namespace Sink |
98 | |||
diff --git a/common/propertymapper.cpp b/common/propertymapper.cpp index 5348b11..ebe5cb3 100644 --- a/common/propertymapper.cpp +++ b/common/propertymapper.cpp | |||
@@ -51,7 +51,7 @@ template <> | |||
51 | QVariant propertyToVariant<QString>(const flatbuffers::String *property) | 51 | QVariant propertyToVariant<QString>(const flatbuffers::String *property) |
52 | { | 52 | { |
53 | if (property) { | 53 | if (property) { |
54 | //We have to copy the memory, otherwise it would become eventually invalid | 54 | // We have to copy the memory, otherwise it would become eventually invalid |
55 | return QString::fromStdString(property->c_str()); | 55 | return QString::fromStdString(property->c_str()); |
56 | } | 56 | } |
57 | return QVariant(); | 57 | return QVariant(); |
@@ -61,7 +61,7 @@ template <> | |||
61 | QVariant propertyToVariant<QByteArray>(const flatbuffers::String *property) | 61 | QVariant propertyToVariant<QByteArray>(const flatbuffers::String *property) |
62 | { | 62 | { |
63 | if (property) { | 63 | if (property) { |
64 | //We have to copy the memory, otherwise it would become eventually invalid | 64 | // We have to copy the memory, otherwise it would become eventually invalid |
65 | return QString::fromStdString(property->c_str()).toUtf8(); | 65 | return QString::fromStdString(property->c_str()).toUtf8(); |
66 | } | 66 | } |
67 | return QVariant(); | 67 | return QVariant(); |
@@ -71,7 +71,7 @@ template <> | |||
71 | QVariant propertyToVariant<QByteArray>(const flatbuffers::Vector<uint8_t> *property) | 71 | QVariant propertyToVariant<QByteArray>(const flatbuffers::Vector<uint8_t> *property) |
72 | { | 72 | { |
73 | if (property) { | 73 | if (property) { |
74 | //We have to copy the memory, otherwise it would become eventually invalid | 74 | // We have to copy the memory, otherwise it would become eventually invalid |
75 | return QByteArray(reinterpret_cast<const char *>(property->Data()), property->Length()); | 75 | return QByteArray(reinterpret_cast<const char *>(property->Data()), property->Length()); |
76 | } | 76 | } |
77 | return QVariant(); | 77 | return QVariant(); |
@@ -87,7 +87,7 @@ template <> | |||
87 | QVariant propertyToVariant<QDateTime>(const flatbuffers::String *property) | 87 | QVariant propertyToVariant<QDateTime>(const flatbuffers::String *property) |
88 | { | 88 | { |
89 | if (property) { | 89 | if (property) { |
90 | //We have to copy the memory, otherwise it would become eventually invalid | 90 | // We have to copy the memory, otherwise it would become eventually invalid |
91 | return QDateTime::fromString(QString::fromStdString(property->c_str())); | 91 | return QDateTime::fromString(QString::fromStdString(property->c_str())); |
92 | } | 92 | } |
93 | return QVariant(); | 93 | return QVariant(); |
diff --git a/common/propertymapper.h b/common/propertymapper.h index 57202ab..cf8ce7b 100644 --- a/common/propertymapper.h +++ b/common/propertymapper.h | |||
@@ -49,7 +49,7 @@ QVariant SINK_EXPORT propertyToVariant(const flatbuffers::Vector<uint8_t> *); | |||
49 | * a virtual method per property, the property mapper can be filled with accessors | 49 | * a virtual method per property, the property mapper can be filled with accessors |
50 | * that extract the properties from resource types. | 50 | * that extract the properties from resource types. |
51 | */ | 51 | */ |
52 | template<typename BufferType> | 52 | template <typename BufferType> |
53 | class ReadPropertyMapper | 53 | class ReadPropertyMapper |
54 | { | 54 | { |
55 | public: | 55 | public: |
@@ -63,63 +63,66 @@ public: | |||
63 | } | 63 | } |
64 | return QVariant(); | 64 | return QVariant(); |
65 | } | 65 | } |
66 | bool hasMapping(const QByteArray &key) const { return mReadAccessors.contains(key); } | 66 | bool hasMapping(const QByteArray &key) const |
67 | QList<QByteArray> availableProperties() const { return mReadAccessors.keys(); } | 67 | { |
68 | void addMapping(const QByteArray &property, const std::function<QVariant(BufferType const *)> &mapping) { | 68 | return mReadAccessors.contains(key); |
69 | } | ||
70 | QList<QByteArray> availableProperties() const | ||
71 | { | ||
72 | return mReadAccessors.keys(); | ||
73 | } | ||
74 | void addMapping(const QByteArray &property, const std::function<QVariant(BufferType const *)> &mapping) | ||
75 | { | ||
69 | mReadAccessors.insert(property, mapping); | 76 | mReadAccessors.insert(property, mapping); |
70 | } | 77 | } |
71 | 78 | ||
72 | template <typename T, typename Buffer> | 79 | template <typename T, typename Buffer> |
73 | void addMapping(const QByteArray &name, const flatbuffers::String *(Buffer::*f)() const) | 80 | void addMapping(const QByteArray &name, const flatbuffers::String *(Buffer::*f)() const) |
74 | { | 81 | { |
75 | addMapping(name, [f](Buffer const *buffer) -> QVariant { | 82 | addMapping(name, [f](Buffer const *buffer) -> QVariant { return propertyToVariant<T>((buffer->*f)()); }); |
76 | return propertyToVariant<T>((buffer->*f)()); | ||
77 | }); | ||
78 | } | 83 | } |
79 | 84 | ||
80 | template <typename T, typename Buffer> | 85 | template <typename T, typename Buffer> |
81 | void addMapping(const QByteArray &name, uint8_t (Buffer::*f)() const) | 86 | void addMapping(const QByteArray &name, uint8_t (Buffer::*f)() const) |
82 | { | 87 | { |
83 | addMapping(name, [f](Buffer const *buffer) -> QVariant { | 88 | addMapping(name, [f](Buffer const *buffer) -> QVariant { return propertyToVariant<T>((buffer->*f)()); }); |
84 | return propertyToVariant<T>((buffer->*f)()); | ||
85 | }); | ||
86 | } | 89 | } |
87 | 90 | ||
88 | template <typename T, typename Buffer> | 91 | template <typename T, typename Buffer> |
89 | void addMapping(const QByteArray &name, bool (Buffer::*f)() const) | 92 | void addMapping(const QByteArray &name, bool (Buffer::*f)() const) |
90 | { | 93 | { |
91 | addMapping(name, [f](Buffer const *buffer) -> QVariant { | 94 | addMapping(name, [f](Buffer const *buffer) -> QVariant { return propertyToVariant<T>((buffer->*f)()); }); |
92 | return propertyToVariant<T>((buffer->*f)()); | ||
93 | }); | ||
94 | } | 95 | } |
95 | 96 | ||
96 | template <typename T, typename Buffer> | 97 | template <typename T, typename Buffer> |
97 | void addMapping(const QByteArray &name, const flatbuffers::Vector<uint8_t> * (Buffer::*f)() const) | 98 | void addMapping(const QByteArray &name, const flatbuffers::Vector<uint8_t> *(Buffer::*f)() const) |
98 | { | 99 | { |
99 | addMapping(name, [f](Buffer const *buffer) -> QVariant { | 100 | addMapping(name, [f](Buffer const *buffer) -> QVariant { return propertyToVariant<T>((buffer->*f)()); }); |
100 | return propertyToVariant<T>((buffer->*f)()); | ||
101 | }); | ||
102 | } | 101 | } |
103 | 102 | ||
104 | private: | 103 | private: |
105 | QHash<QByteArray, std::function<QVariant(BufferType const *)> > mReadAccessors; | 104 | QHash<QByteArray, std::function<QVariant(BufferType const *)>> mReadAccessors; |
106 | }; | 105 | }; |
107 | 106 | ||
108 | template<typename BufferBuilder> | 107 | template <typename BufferBuilder> |
109 | class WritePropertyMapper | 108 | class WritePropertyMapper |
110 | { | 109 | { |
111 | public: | 110 | public: |
112 | virtual ~WritePropertyMapper(){}; | 111 | virtual ~WritePropertyMapper(){}; |
113 | 112 | ||
114 | virtual void setProperty(const QByteArray &key, const QVariant &value, QList<std::function<void(BufferBuilder &)> > &builderCalls, flatbuffers::FlatBufferBuilder &fbb) const | 113 | virtual void setProperty(const QByteArray &key, const QVariant &value, QList<std::function<void(BufferBuilder &)>> &builderCalls, flatbuffers::FlatBufferBuilder &fbb) const |
115 | { | 114 | { |
116 | if (mWriteAccessors.contains(key)) { | 115 | if (mWriteAccessors.contains(key)) { |
117 | auto accessor = mWriteAccessors.value(key); | 116 | auto accessor = mWriteAccessors.value(key); |
118 | builderCalls << accessor(value, fbb); | 117 | builderCalls << accessor(value, fbb); |
119 | } | 118 | } |
120 | } | 119 | } |
121 | bool hasMapping(const QByteArray &key) const { return mWriteAccessors.contains(key); } | 120 | bool hasMapping(const QByteArray &key) const |
122 | void addMapping(const QByteArray &property, const std::function<std::function<void(BufferBuilder &)>(const QVariant &, flatbuffers::FlatBufferBuilder &)> &mapping) { | 121 | { |
122 | return mWriteAccessors.contains(key); | ||
123 | } | ||
124 | void addMapping(const QByteArray &property, const std::function<std::function<void(BufferBuilder &)>(const QVariant &, flatbuffers::FlatBufferBuilder &)> &mapping) | ||
125 | { | ||
123 | mWriteAccessors.insert(property, mapping); | 126 | mWriteAccessors.insert(property, mapping); |
124 | } | 127 | } |
125 | 128 | ||
@@ -127,9 +130,7 @@ public: | |||
127 | void addMapping(const QByteArray &name, void (BufferBuilder::*f)(uint8_t)) | 130 | void addMapping(const QByteArray &name, void (BufferBuilder::*f)(uint8_t)) |
128 | { | 131 | { |
129 | addMapping(name, [f](const QVariant &value, flatbuffers::FlatBufferBuilder &fbb) -> std::function<void(BufferBuilder &)> { | 132 | addMapping(name, [f](const QVariant &value, flatbuffers::FlatBufferBuilder &fbb) -> std::function<void(BufferBuilder &)> { |
130 | return [value, f](BufferBuilder &builder) { | 133 | return [value, f](BufferBuilder &builder) { (builder.*f)(value.value<T>()); }; |
131 | (builder.*f)(value.value<T>()); | ||
132 | }; | ||
133 | }); | 134 | }); |
134 | } | 135 | } |
135 | 136 | ||
@@ -137,9 +138,7 @@ public: | |||
137 | void addMapping(const QByteArray &name, void (BufferBuilder::*f)(bool)) | 138 | void addMapping(const QByteArray &name, void (BufferBuilder::*f)(bool)) |
138 | { | 139 | { |
139 | addMapping(name, [f](const QVariant &value, flatbuffers::FlatBufferBuilder &fbb) -> std::function<void(BufferBuilder &)> { | 140 | addMapping(name, [f](const QVariant &value, flatbuffers::FlatBufferBuilder &fbb) -> std::function<void(BufferBuilder &)> { |
140 | return [value, f](BufferBuilder &builder) { | 141 | return [value, f](BufferBuilder &builder) { (builder.*f)(value.value<T>()); }; |
141 | (builder.*f)(value.value<T>()); | ||
142 | }; | ||
143 | }); | 142 | }); |
144 | } | 143 | } |
145 | 144 | ||
@@ -148,23 +147,19 @@ public: | |||
148 | { | 147 | { |
149 | addMapping(name, [f](const QVariant &value, flatbuffers::FlatBufferBuilder &fbb) -> std::function<void(BufferBuilder &)> { | 148 | addMapping(name, [f](const QVariant &value, flatbuffers::FlatBufferBuilder &fbb) -> std::function<void(BufferBuilder &)> { |
150 | auto offset = variantToProperty<T>(value, fbb); | 149 | auto offset = variantToProperty<T>(value, fbb); |
151 | return [offset, f](BufferBuilder &builder) { | 150 | return [offset, f](BufferBuilder &builder) { (builder.*f)(offset); }; |
152 | (builder.*f)(offset); | ||
153 | }; | ||
154 | }); | 151 | }); |
155 | } | 152 | } |
156 | 153 | ||
157 | template <typename T> | 154 | template <typename T> |
158 | void addMapping(const QByteArray &name, void (BufferBuilder::*f)(flatbuffers::Offset<flatbuffers::Vector<uint8_t> >)) | 155 | void addMapping(const QByteArray &name, void (BufferBuilder::*f)(flatbuffers::Offset<flatbuffers::Vector<uint8_t>>)) |
159 | { | 156 | { |
160 | addMapping(name, [f](const QVariant &value, flatbuffers::FlatBufferBuilder &fbb) -> std::function<void(BufferBuilder &)> { | 157 | addMapping(name, [f](const QVariant &value, flatbuffers::FlatBufferBuilder &fbb) -> std::function<void(BufferBuilder &)> { |
161 | auto offset = variantToProperty<T>(value, fbb); | 158 | auto offset = variantToProperty<T>(value, fbb); |
162 | return [offset, f](BufferBuilder &builder) { | 159 | return [offset, f](BufferBuilder &builder) { (builder.*f)(offset); }; |
163 | (builder.*f)(offset); | ||
164 | }; | ||
165 | }); | 160 | }); |
166 | } | 161 | } |
162 | |||
167 | private: | 163 | private: |
168 | QHash<QByteArray, std::function<std::function<void(BufferBuilder &)>(const QVariant &, flatbuffers::FlatBufferBuilder &)> > mWriteAccessors; | 164 | QHash<QByteArray, std::function<std::function<void(BufferBuilder &)>(const QVariant &, flatbuffers::FlatBufferBuilder &)>> mWriteAccessors; |
169 | }; | 165 | }; |
170 | |||
diff --git a/common/query.h b/common/query.h index 60c5630..3a56c9f 100644 --- a/common/query.h +++ b/common/query.h | |||
@@ -32,7 +32,8 @@ namespace Sink { | |||
32 | class Query | 32 | class Query |
33 | { | 33 | { |
34 | public: | 34 | public: |
35 | enum Flag { | 35 | enum Flag |
36 | { | ||
36 | /** Leave the query running an contiously update the result set. */ | 37 | /** Leave the query running an contiously update the result set. */ |
37 | LiveQuery | 38 | LiveQuery |
38 | }; | 39 | }; |
@@ -102,11 +103,11 @@ public: | |||
102 | return query; | 103 | return query; |
103 | } | 104 | } |
104 | 105 | ||
105 | Query(Flags flags = Flags()) | 106 | Query(Flags flags = Flags()) : limit(0) |
106 | : limit(0) | 107 | { |
107 | {} | 108 | } |
108 | 109 | ||
109 | Query& operator+=(const Query& rhs) | 110 | Query &operator+=(const Query &rhs) |
110 | { | 111 | { |
111 | resources += rhs.resources; | 112 | resources += rhs.resources; |
112 | ids += rhs.ids; | 113 | ids += rhs.ids; |
@@ -121,7 +122,7 @@ public: | |||
121 | return *this; | 122 | return *this; |
122 | } | 123 | } |
123 | 124 | ||
124 | friend Query operator+(Query lhs, const Query& rhs) | 125 | friend Query operator+(Query lhs, const Query &rhs) |
125 | { | 126 | { |
126 | lhs += rhs; | 127 | lhs += rhs; |
127 | return lhs; | 128 | return lhs; |
@@ -136,7 +137,6 @@ public: | |||
136 | bool liveQuery; | 137 | bool liveQuery; |
137 | int limit; | 138 | int limit; |
138 | }; | 139 | }; |
139 | |||
140 | } | 140 | } |
141 | 141 | ||
142 | Q_DECLARE_OPERATORS_FOR_FLAGS(Sink::Query::Flags) | 142 | Q_DECLARE_OPERATORS_FOR_FLAGS(Sink::Query::Flags) |
diff --git a/common/queryrunner.cpp b/common/queryrunner.cpp index 5ac1344..c150159 100644 --- a/common/queryrunner.cpp +++ b/common/queryrunner.cpp | |||
@@ -39,11 +39,12 @@ using namespace Sink; | |||
39 | * This is a worker object that can be moved to a thread to execute the query. | 39 | * This is a worker object that can be moved to a thread to execute the query. |
40 | * The only interaction point is the ResultProvider, which handles the threadsafe reporting of the result. | 40 | * The only interaction point is the ResultProvider, which handles the threadsafe reporting of the result. |
41 | */ | 41 | */ |
42 | template<typename DomainType> | 42 | template <typename DomainType> |
43 | class QueryWorker : public QObject | 43 | class QueryWorker : public QObject |
44 | { | 44 | { |
45 | public: | 45 | public: |
46 | QueryWorker(const Sink::Query &query, const QByteArray &instanceIdentifier, const DomainTypeAdaptorFactoryInterface::Ptr &, const QByteArray &bufferType, const QueryRunnerBase::ResultTransformation &transformation); | 46 | QueryWorker(const Sink::Query &query, const QByteArray &instanceIdentifier, const DomainTypeAdaptorFactoryInterface::Ptr &, const QByteArray &bufferType, |
47 | const QueryRunnerBase::ResultTransformation &transformation); | ||
47 | virtual ~QueryWorker(); | 48 | virtual ~QueryWorker(); |
48 | 49 | ||
49 | qint64 executeIncrementalQuery(const Sink::Query &query, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider); | 50 | qint64 executeIncrementalQuery(const Sink::Query &query, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider); |
@@ -52,14 +53,17 @@ public: | |||
52 | private: | 53 | private: |
53 | void replaySet(ResultSet &resultSet, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, const QList<QByteArray> &properties, int offset, int batchSize); | 54 | void replaySet(ResultSet &resultSet, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, const QList<QByteArray> &properties, int offset, int batchSize); |
54 | 55 | ||
55 | void readEntity(const Sink::Storage::NamedDatabase &db, const QByteArray &key, const std::function<void(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &, Sink::Operation)> &resultCallback); | 56 | void readEntity(const Sink::Storage::NamedDatabase &db, const QByteArray &key, |
57 | const std::function<void(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &, Sink::Operation)> &resultCallback); | ||
56 | 58 | ||
57 | ResultSet loadInitialResultSet(const Sink::Query &query, Sink::Storage::Transaction &transaction, QSet<QByteArray> &remainingFilters, QByteArray &remainingSorting); | 59 | ResultSet loadInitialResultSet(const Sink::Query &query, Sink::Storage::Transaction &transaction, QSet<QByteArray> &remainingFilters, QByteArray &remainingSorting); |
58 | ResultSet loadIncrementalResultSet(qint64 baseRevision, const Sink::Query &query, Sink::Storage::Transaction &transaction, QSet<QByteArray> &remainingFilters); | 60 | ResultSet loadIncrementalResultSet(qint64 baseRevision, const Sink::Query &query, Sink::Storage::Transaction &transaction, QSet<QByteArray> &remainingFilters); |
59 | 61 | ||
60 | ResultSet filterAndSortSet(ResultSet &resultSet, const std::function<bool(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &domainObject)> &filter, const Sink::Storage::NamedDatabase &db, bool initialQuery, const QByteArray &sortProperty); | 62 | ResultSet filterAndSortSet(ResultSet &resultSet, const std::function<bool(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &domainObject)> &filter, |
63 | const Sink::Storage::NamedDatabase &db, bool initialQuery, const QByteArray &sortProperty); | ||
61 | std::function<bool(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &domainObject)> getFilter(const QSet<QByteArray> remainingFilters, const Sink::Query &query); | 64 | std::function<bool(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &domainObject)> getFilter(const QSet<QByteArray> remainingFilters, const Sink::Query &query); |
62 | qint64 load(const Sink::Query &query, const std::function<ResultSet(Sink::Storage::Transaction &, QSet<QByteArray> &, QByteArray &)> &baseSetRetriever, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, bool initialQuery, int offset, int batchSize); | 65 | qint64 load(const Sink::Query &query, const std::function<ResultSet(Sink::Storage::Transaction &, QSet<QByteArray> &, QByteArray &)> &baseSetRetriever, |
66 | Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, bool initialQuery, int offset, int batchSize); | ||
63 | 67 | ||
64 | private: | 68 | private: |
65 | QueryRunnerBase::ResultTransformation mResultTransformation; | 69 | QueryRunnerBase::ResultTransformation mResultTransformation; |
@@ -70,176 +74,171 @@ private: | |||
70 | }; | 74 | }; |
71 | 75 | ||
72 | 76 | ||
73 | template<class DomainType> | 77 | template <class DomainType> |
74 | QueryRunner<DomainType>::QueryRunner(const Sink::Query &query, const Sink::ResourceAccessInterface::Ptr &resourceAccess, const QByteArray &instanceIdentifier, const DomainTypeAdaptorFactoryInterface::Ptr &factory, const QByteArray &bufferType) | 78 | QueryRunner<DomainType>::QueryRunner(const Sink::Query &query, const Sink::ResourceAccessInterface::Ptr &resourceAccess, const QByteArray &instanceIdentifier, |
75 | : QueryRunnerBase(), | 79 | const DomainTypeAdaptorFactoryInterface::Ptr &factory, const QByteArray &bufferType) |
76 | mResourceAccess(resourceAccess), | 80 | : QueryRunnerBase(), mResourceAccess(resourceAccess), mResultProvider(new ResultProvider<typename DomainType::Ptr>), mOffset(0), mBatchSize(query.limit) |
77 | mResultProvider(new ResultProvider<typename DomainType::Ptr>), | ||
78 | mOffset(0), | ||
79 | mBatchSize(query.limit) | ||
80 | { | 81 | { |
81 | Trace() << "Starting query"; | 82 | Trace() << "Starting query"; |
82 | if (query.limit && query.sortProperty.isEmpty()) { | 83 | if (query.limit && query.sortProperty.isEmpty()) { |
83 | Warning() << "A limited query without sorting is typically a bad idea."; | 84 | Warning() << "A limited query without sorting is typically a bad idea."; |
84 | } | 85 | } |
85 | //We delegate loading of initial data to the result provider, os it can decide for itself what it needs to load. | 86 | // We delegate loading of initial data to the result provider, os it can decide for itself what it needs to load. |
86 | mResultProvider->setFetcher([=](const typename DomainType::Ptr &parent) { | 87 | mResultProvider->setFetcher([=](const typename DomainType::Ptr &parent) { |
87 | Trace() << "Running fetcher. Offset: " << mOffset << " Batchsize: " << mBatchSize; | 88 | Trace() << "Running fetcher. Offset: " << mOffset << " Batchsize: " << mBatchSize; |
88 | auto resultProvider = mResultProvider; | 89 | auto resultProvider = mResultProvider; |
89 | async::run<qint64>([=]() -> qint64 { | 90 | async::run<qint64>([=]() -> qint64 { |
90 | QueryWorker<DomainType> worker(query, instanceIdentifier, factory, bufferType, mResultTransformation); | 91 | QueryWorker<DomainType> worker(query, instanceIdentifier, factory, bufferType, mResultTransformation); |
91 | const qint64 newRevision = worker.executeInitialQuery(query, parent, *resultProvider, mOffset, mBatchSize); | 92 | const qint64 newRevision = worker.executeInitialQuery(query, parent, *resultProvider, mOffset, mBatchSize); |
92 | return newRevision; | 93 | return newRevision; |
93 | }) | 94 | }) |
94 | .template then<void, qint64>([query, this](qint64 newRevision) { | 95 | .template then<void, qint64>([query, this](qint64 newRevision) { |
95 | mOffset += mBatchSize; | 96 | mOffset += mBatchSize; |
96 | //Only send the revision replayed information if we're connected to the resource, there's no need to start the resource otherwise. | 97 | // Only send the revision replayed information if we're connected to the resource, there's no need to start the resource otherwise. |
97 | if (query.liveQuery) { | 98 | if (query.liveQuery) { |
98 | mResourceAccess->sendRevisionReplayedCommand(newRevision); | 99 | mResourceAccess->sendRevisionReplayedCommand(newRevision); |
99 | } | 100 | } |
100 | }).exec(); | 101 | }) |
102 | .exec(); | ||
101 | }); | 103 | }); |
102 | 104 | ||
103 | // In case of a live query we keep the runner for as long alive as the result provider exists | 105 | // In case of a live query we keep the runner for as long alive as the result provider exists |
104 | if (query.liveQuery) { | 106 | if (query.liveQuery) { |
105 | //Incremental updates are always loaded directly, leaving it up to the result to discard the changes if they are not interesting | 107 | // Incremental updates are always loaded directly, leaving it up to the result to discard the changes if they are not interesting |
106 | setQuery([=] () -> KAsync::Job<void> { | 108 | setQuery([=]() -> KAsync::Job<void> { |
107 | auto resultProvider = mResultProvider; | 109 | auto resultProvider = mResultProvider; |
108 | return async::run<qint64>([=]() -> qint64 { | 110 | return async::run<qint64>([=]() -> qint64 { |
109 | QueryWorker<DomainType> worker(query, instanceIdentifier, factory, bufferType, mResultTransformation); | 111 | QueryWorker<DomainType> worker(query, instanceIdentifier, factory, bufferType, mResultTransformation); |
110 | const qint64 newRevision = worker.executeIncrementalQuery(query, *resultProvider); | 112 | const qint64 newRevision = worker.executeIncrementalQuery(query, *resultProvider); |
111 | return newRevision; | 113 | return newRevision; |
112 | }) | 114 | }) |
113 | .template then<void, qint64>([query, this](qint64 newRevision) { | 115 | .template then<void, qint64>([query, this](qint64 newRevision) { |
114 | //Only send the revision replayed information if we're connected to the resource, there's no need to start the resource otherwise. | 116 | // Only send the revision replayed information if we're connected to the resource, there's no need to start the resource otherwise. |
115 | mResourceAccess->sendRevisionReplayedCommand(newRevision); | 117 | mResourceAccess->sendRevisionReplayedCommand(newRevision); |
116 | }); | 118 | }); |
117 | }); | 119 | }); |
118 | //Ensure the connection is open, if it wasn't already opened | 120 | // Ensure the connection is open, if it wasn't already opened |
119 | //TODO If we are not connected already, we have to check for the latest revision once connected, otherwise we could miss some updates | 121 | // TODO If we are not connected already, we have to check for the latest revision once connected, otherwise we could miss some updates |
120 | mResourceAccess->open(); | 122 | mResourceAccess->open(); |
121 | QObject::connect(mResourceAccess.data(), &Sink::ResourceAccess::revisionChanged, this, &QueryRunner::revisionChanged); | 123 | QObject::connect(mResourceAccess.data(), &Sink::ResourceAccess::revisionChanged, this, &QueryRunner::revisionChanged); |
122 | } | 124 | } |
123 | } | 125 | } |
124 | 126 | ||
125 | template<class DomainType> | 127 | template <class DomainType> |
126 | QueryRunner<DomainType>::~QueryRunner() | 128 | QueryRunner<DomainType>::~QueryRunner() |
127 | { | 129 | { |
128 | Trace() << "Stopped query"; | 130 | Trace() << "Stopped query"; |
129 | } | 131 | } |
130 | 132 | ||
131 | template<class DomainType> | 133 | template <class DomainType> |
132 | void QueryRunner<DomainType>::setResultTransformation(const ResultTransformation &transformation) | 134 | void QueryRunner<DomainType>::setResultTransformation(const ResultTransformation &transformation) |
133 | { | 135 | { |
134 | mResultTransformation = transformation; | 136 | mResultTransformation = transformation; |
135 | } | 137 | } |
136 | 138 | ||
137 | template<class DomainType> | 139 | template <class DomainType> |
138 | typename Sink::ResultEmitter<typename DomainType::Ptr>::Ptr QueryRunner<DomainType>::emitter() | 140 | typename Sink::ResultEmitter<typename DomainType::Ptr>::Ptr QueryRunner<DomainType>::emitter() |
139 | { | 141 | { |
140 | return mResultProvider->emitter(); | 142 | return mResultProvider->emitter(); |
141 | } | 143 | } |
142 | 144 | ||
143 | 145 | ||
144 | |||
145 | static inline ResultSet fullScan(const Sink::Storage::Transaction &transaction, const QByteArray &bufferType) | 146 | static inline ResultSet fullScan(const Sink::Storage::Transaction &transaction, const QByteArray &bufferType) |
146 | { | 147 | { |
147 | //TODO use a result set with an iterator, to read values on demand | 148 | // TODO use a result set with an iterator, to read values on demand |
148 | QVector<QByteArray> keys; | 149 | QVector<QByteArray> keys; |
149 | Storage::mainDatabase(transaction, bufferType).scan(QByteArray(), [&](const QByteArray &key, const QByteArray &value) -> bool { | 150 | Storage::mainDatabase(transaction, bufferType) |
150 | //Skip internals | 151 | .scan(QByteArray(), |
151 | if (Sink::Storage::isInternalKey(key)) { | 152 | [&](const QByteArray &key, const QByteArray &value) -> bool { |
152 | return true; | 153 | // Skip internals |
153 | } | 154 | if (Sink::Storage::isInternalKey(key)) { |
154 | keys << Sink::Storage::uidFromKey(key); | 155 | return true; |
155 | return true; | 156 | } |
156 | }, | 157 | keys << Sink::Storage::uidFromKey(key); |
157 | [](const Sink::Storage::Error &error) { | 158 | return true; |
158 | Warning() << "Error during query: " << error.message; | 159 | }, |
159 | }); | 160 | [](const Sink::Storage::Error &error) { Warning() << "Error during query: " << error.message; }); |
160 | 161 | ||
161 | Trace() << "Full scan retrieved " << keys.size() << " results."; | 162 | Trace() << "Full scan retrieved " << keys.size() << " results."; |
162 | return ResultSet(keys); | 163 | return ResultSet(keys); |
163 | } | 164 | } |
164 | 165 | ||
165 | 166 | ||
166 | template<class DomainType> | 167 | template <class DomainType> |
167 | QueryWorker<DomainType>::QueryWorker(const Sink::Query &query, const QByteArray &instanceIdentifier, const DomainTypeAdaptorFactoryInterface::Ptr &factory, const QByteArray &bufferType, const QueryRunnerBase::ResultTransformation &transformation) | 168 | QueryWorker<DomainType>::QueryWorker(const Sink::Query &query, const QByteArray &instanceIdentifier, const DomainTypeAdaptorFactoryInterface::Ptr &factory, |
168 | : QObject(), | 169 | const QByteArray &bufferType, const QueryRunnerBase::ResultTransformation &transformation) |
169 | mResultTransformation(transformation), | 170 | : QObject(), mResultTransformation(transformation), mDomainTypeAdaptorFactory(factory), mResourceInstanceIdentifier(instanceIdentifier), mBufferType(bufferType), mQuery(query) |
170 | mDomainTypeAdaptorFactory(factory), | ||
171 | mResourceInstanceIdentifier(instanceIdentifier), | ||
172 | mBufferType(bufferType), | ||
173 | mQuery(query) | ||
174 | { | 171 | { |
175 | Trace() << "Starting query worker"; | 172 | Trace() << "Starting query worker"; |
176 | } | 173 | } |
177 | 174 | ||
178 | template<class DomainType> | 175 | template <class DomainType> |
179 | QueryWorker<DomainType>::~QueryWorker() | 176 | QueryWorker<DomainType>::~QueryWorker() |
180 | { | 177 | { |
181 | Trace() << "Stopped query worker"; | 178 | Trace() << "Stopped query worker"; |
182 | } | 179 | } |
183 | 180 | ||
184 | template<class DomainType> | 181 | template <class DomainType> |
185 | void QueryWorker<DomainType>::replaySet(ResultSet &resultSet, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, const QList<QByteArray> &properties, int offset, int batchSize) | 182 | void QueryWorker<DomainType>::replaySet(ResultSet &resultSet, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, const QList<QByteArray> &properties, int offset, int batchSize) |
186 | { | 183 | { |
187 | Trace() << "Skipping over " << offset << " results"; | 184 | Trace() << "Skipping over " << offset << " results"; |
188 | resultSet.skip(offset); | 185 | resultSet.skip(offset); |
189 | int counter; | 186 | int counter; |
190 | for (counter = 0; !batchSize || (counter < batchSize); counter++) { | 187 | for (counter = 0; !batchSize || (counter < batchSize); counter++) { |
191 | const bool ret = resultSet.next([this, &resultProvider, &counter, &properties, batchSize](const Sink::ApplicationDomain::ApplicationDomainType::Ptr &value, Sink::Operation operation) -> bool { | 188 | const bool ret = |
192 | //FIXME allow maildir resource to set the mimeMessage property | 189 | resultSet.next([this, &resultProvider, &counter, &properties, batchSize](const Sink::ApplicationDomain::ApplicationDomainType::Ptr &value, Sink::Operation operation) -> bool { |
193 | auto valueCopy = Sink::ApplicationDomain::ApplicationDomainType::getInMemoryRepresentation<DomainType>(*value, properties).template staticCast<DomainType>(); | 190 | // FIXME allow maildir resource to set the mimeMessage property |
194 | if (mResultTransformation) { | 191 | auto valueCopy = Sink::ApplicationDomain::ApplicationDomainType::getInMemoryRepresentation<DomainType>(*value, properties).template staticCast<DomainType>(); |
195 | mResultTransformation(*valueCopy); | 192 | if (mResultTransformation) { |
196 | } | 193 | mResultTransformation(*valueCopy); |
197 | switch (operation) { | 194 | } |
198 | case Sink::Operation_Creation: | 195 | switch (operation) { |
199 | // Trace() << "Got creation"; | 196 | case Sink::Operation_Creation: |
200 | resultProvider.add(valueCopy); | 197 | // Trace() << "Got creation"; |
201 | break; | 198 | resultProvider.add(valueCopy); |
202 | case Sink::Operation_Modification: | 199 | break; |
203 | // Trace() << "Got modification"; | 200 | case Sink::Operation_Modification: |
204 | resultProvider.modify(valueCopy); | 201 | // Trace() << "Got modification"; |
205 | break; | 202 | resultProvider.modify(valueCopy); |
206 | case Sink::Operation_Removal: | 203 | break; |
207 | // Trace() << "Got removal"; | 204 | case Sink::Operation_Removal: |
208 | resultProvider.remove(valueCopy); | 205 | // Trace() << "Got removal"; |
209 | break; | 206 | resultProvider.remove(valueCopy); |
210 | } | 207 | break; |
211 | return true; | 208 | } |
212 | }); | 209 | return true; |
210 | }); | ||
213 | if (!ret) { | 211 | if (!ret) { |
214 | break; | 212 | break; |
215 | } | 213 | } |
216 | }; | 214 | }; |
217 | Trace() << "Replayed " << counter << " results." << "Limit " << batchSize; | 215 | Trace() << "Replayed " << counter << " results." |
216 | << "Limit " << batchSize; | ||
218 | } | 217 | } |
219 | 218 | ||
220 | template<class DomainType> | 219 | template <class DomainType> |
221 | void QueryWorker<DomainType>::readEntity(const Sink::Storage::NamedDatabase &db, const QByteArray &key, const std::function<void(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &, Sink::Operation)> &resultCallback) | 220 | void QueryWorker<DomainType>::readEntity(const Sink::Storage::NamedDatabase &db, const QByteArray &key, |
221 | const std::function<void(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &, Sink::Operation)> &resultCallback) | ||
222 | { | 222 | { |
223 | //This only works for a 1:1 mapping of resource to domain types. | 223 | // This only works for a 1:1 mapping of resource to domain types. |
224 | //Not i.e. for tags that are stored as flags in each entity of an imap store. | 224 | // Not i.e. for tags that are stored as flags in each entity of an imap store. |
225 | //additional properties that don't have a 1:1 mapping (such as separately stored tags), | 225 | // additional properties that don't have a 1:1 mapping (such as separately stored tags), |
226 | //could be added to the adaptor. | 226 | // could be added to the adaptor. |
227 | db.findLatest(key, [=](const QByteArray &key, const QByteArray &value) -> bool { | 227 | db.findLatest(key, |
228 | Sink::EntityBuffer buffer(value.data(), value.size()); | 228 | [=](const QByteArray &key, const QByteArray &value) -> bool { |
229 | const Sink::Entity &entity = buffer.entity(); | 229 | Sink::EntityBuffer buffer(value.data(), value.size()); |
230 | const auto metadataBuffer = Sink::EntityBuffer::readBuffer<Sink::Metadata>(entity.metadata()); | 230 | const Sink::Entity &entity = buffer.entity(); |
231 | const qint64 revision = metadataBuffer ? metadataBuffer->revision() : -1; | 231 | const auto metadataBuffer = Sink::EntityBuffer::readBuffer<Sink::Metadata>(entity.metadata()); |
232 | const auto operation = metadataBuffer ? metadataBuffer->operation() : Sink::Operation_Creation; | 232 | const qint64 revision = metadataBuffer ? metadataBuffer->revision() : -1; |
233 | auto adaptor = mDomainTypeAdaptorFactory->createAdaptor(entity); | 233 | const auto operation = metadataBuffer ? metadataBuffer->operation() : Sink::Operation_Creation; |
234 | resultCallback(DomainType::Ptr::create(mResourceInstanceIdentifier, Sink::Storage::uidFromKey(key), revision, adaptor), operation); | 234 | auto adaptor = mDomainTypeAdaptorFactory->createAdaptor(entity); |
235 | return false; | 235 | resultCallback(DomainType::Ptr::create(mResourceInstanceIdentifier, Sink::Storage::uidFromKey(key), revision, adaptor), operation); |
236 | }, | 236 | return false; |
237 | [](const Sink::Storage::Error &error) { | 237 | }, |
238 | Warning() << "Error during query: " << error.message; | 238 | [](const Sink::Storage::Error &error) { Warning() << "Error during query: " << error.message; }); |
239 | }); | ||
240 | } | 239 | } |
241 | 240 | ||
242 | template<class DomainType> | 241 | template <class DomainType> |
243 | ResultSet QueryWorker<DomainType>::loadInitialResultSet(const Sink::Query &query, Sink::Storage::Transaction &transaction, QSet<QByteArray> &remainingFilters, QByteArray &remainingSorting) | 242 | ResultSet QueryWorker<DomainType>::loadInitialResultSet(const Sink::Query &query, Sink::Storage::Transaction &transaction, QSet<QByteArray> &remainingFilters, QByteArray &remainingSorting) |
244 | { | 243 | { |
245 | if (!query.ids.isEmpty()) { | 244 | if (!query.ids.isEmpty()) { |
@@ -253,15 +252,15 @@ ResultSet QueryWorker<DomainType>::loadInitialResultSet(const Sink::Query &query | |||
253 | remainingSorting = query.sortProperty; | 252 | remainingSorting = query.sortProperty; |
254 | } | 253 | } |
255 | 254 | ||
256 | //We do a full scan if there were no indexes available to create the initial set. | 255 | // We do a full scan if there were no indexes available to create the initial set. |
257 | if (appliedFilters.isEmpty()) { | 256 | if (appliedFilters.isEmpty()) { |
258 | //TODO this should be replaced by an index lookup as well | 257 | // TODO this should be replaced by an index lookup as well |
259 | resultSet = fullScan(transaction, mBufferType); | 258 | resultSet = fullScan(transaction, mBufferType); |
260 | } | 259 | } |
261 | return resultSet; | 260 | return resultSet; |
262 | } | 261 | } |
263 | 262 | ||
264 | template<class DomainType> | 263 | template <class DomainType> |
265 | ResultSet QueryWorker<DomainType>::loadIncrementalResultSet(qint64 baseRevision, const Sink::Query &query, Sink::Storage::Transaction &transaction, QSet<QByteArray> &remainingFilters) | 264 | ResultSet QueryWorker<DomainType>::loadIncrementalResultSet(qint64 baseRevision, const Sink::Query &query, Sink::Storage::Transaction &transaction, QSet<QByteArray> &remainingFilters) |
266 | { | 265 | { |
267 | const auto bufferType = mBufferType; | 266 | const auto bufferType = mBufferType; |
@@ -269,13 +268,13 @@ ResultSet QueryWorker<DomainType>::loadIncrementalResultSet(qint64 baseRevision, | |||
269 | remainingFilters = query.propertyFilter.keys().toSet(); | 268 | remainingFilters = query.propertyFilter.keys().toSet(); |
270 | return ResultSet([bufferType, revisionCounter, &transaction]() -> QByteArray { | 269 | return ResultSet([bufferType, revisionCounter, &transaction]() -> QByteArray { |
271 | const qint64 topRevision = Sink::Storage::maxRevision(transaction); | 270 | const qint64 topRevision = Sink::Storage::maxRevision(transaction); |
272 | //Spit out the revision keys one by one. | 271 | // Spit out the revision keys one by one. |
273 | while (*revisionCounter <= topRevision) { | 272 | while (*revisionCounter <= topRevision) { |
274 | const auto uid = Sink::Storage::getUidFromRevision(transaction, *revisionCounter); | 273 | const auto uid = Sink::Storage::getUidFromRevision(transaction, *revisionCounter); |
275 | const auto type = Sink::Storage::getTypeFromRevision(transaction, *revisionCounter); | 274 | const auto type = Sink::Storage::getTypeFromRevision(transaction, *revisionCounter); |
276 | // Trace() << "Revision" << *revisionCounter << type << uid; | 275 | // Trace() << "Revision" << *revisionCounter << type << uid; |
277 | if (type != bufferType) { | 276 | if (type != bufferType) { |
278 | //Skip revision | 277 | // Skip revision |
279 | *revisionCounter += 1; | 278 | *revisionCounter += 1; |
280 | continue; | 279 | continue; |
281 | } | 280 | } |
@@ -284,45 +283,47 @@ ResultSet QueryWorker<DomainType>::loadIncrementalResultSet(qint64 baseRevision, | |||
284 | return key; | 283 | return key; |
285 | } | 284 | } |
286 | Trace() << "Finished reading incremental result set:" << *revisionCounter; | 285 | Trace() << "Finished reading incremental result set:" << *revisionCounter; |
287 | //We're done | 286 | // We're done |
288 | return QByteArray(); | 287 | return QByteArray(); |
289 | }); | 288 | }); |
290 | } | 289 | } |
291 | 290 | ||
292 | template<class DomainType> | 291 | template <class DomainType> |
293 | ResultSet QueryWorker<DomainType>::filterAndSortSet(ResultSet &resultSet, const std::function<bool(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &domainObject)> &filter, const Sink::Storage::NamedDatabase &db, bool initialQuery, const QByteArray &sortProperty) | 292 | ResultSet QueryWorker<DomainType>::filterAndSortSet(ResultSet &resultSet, const std::function<bool(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &domainObject)> &filter, |
293 | const Sink::Storage::NamedDatabase &db, bool initialQuery, const QByteArray &sortProperty) | ||
294 | { | 294 | { |
295 | const bool sortingRequired = !sortProperty.isEmpty(); | 295 | const bool sortingRequired = !sortProperty.isEmpty(); |
296 | if (initialQuery && sortingRequired) { | 296 | if (initialQuery && sortingRequired) { |
297 | Trace() << "Sorting the resultset in memory according to property: " << sortProperty; | 297 | Trace() << "Sorting the resultset in memory according to property: " << sortProperty; |
298 | //Sort the complete set by reading the sort property and filling into a sorted map | 298 | // Sort the complete set by reading the sort property and filling into a sorted map |
299 | auto sortedMap = QSharedPointer<QMap<QByteArray, QByteArray>>::create(); | 299 | auto sortedMap = QSharedPointer<QMap<QByteArray, QByteArray>>::create(); |
300 | while (resultSet.next()) { | 300 | while (resultSet.next()) { |
301 | //readEntity is only necessary if we actually want to filter or know the operation type (but not a big deal if we do it always I guess) | 301 | // readEntity is only necessary if we actually want to filter or know the operation type (but not a big deal if we do it always I guess) |
302 | readEntity(db, resultSet.id(), [this, filter, initialQuery, sortedMap, sortProperty, &resultSet](const Sink::ApplicationDomain::ApplicationDomainType::Ptr &domainObject, Sink::Operation operation) { | 302 | readEntity(db, resultSet.id(), |
303 | //We're not interested in removals during the initial query | 303 | [this, filter, initialQuery, sortedMap, sortProperty, &resultSet](const Sink::ApplicationDomain::ApplicationDomainType::Ptr &domainObject, Sink::Operation operation) { |
304 | if ((operation != Sink::Operation_Removal) && filter(domainObject)) { | 304 | // We're not interested in removals during the initial query |
305 | if (!sortProperty.isEmpty()) { | 305 | if ((operation != Sink::Operation_Removal) && filter(domainObject)) { |
306 | const auto sortValue = domainObject->getProperty(sortProperty); | 306 | if (!sortProperty.isEmpty()) { |
307 | if (sortValue.type() == QVariant::DateTime) { | 307 | const auto sortValue = domainObject->getProperty(sortProperty); |
308 | sortedMap->insert(QByteArray::number(std::numeric_limits<unsigned int>::max() - sortValue.toDateTime().toTime_t()), domainObject->identifier()); | 308 | if (sortValue.type() == QVariant::DateTime) { |
309 | sortedMap->insert(QByteArray::number(std::numeric_limits<unsigned int>::max() - sortValue.toDateTime().toTime_t()), domainObject->identifier()); | ||
310 | } else { | ||
311 | sortedMap->insert(sortValue.toString().toLatin1(), domainObject->identifier()); | ||
312 | } | ||
309 | } else { | 313 | } else { |
310 | sortedMap->insert(sortValue.toString().toLatin1(), domainObject->identifier()); | 314 | sortedMap->insert(domainObject->identifier(), domainObject->identifier()); |
311 | } | 315 | } |
312 | } else { | ||
313 | sortedMap->insert(domainObject->identifier(), domainObject->identifier()); | ||
314 | } | 316 | } |
315 | } | 317 | }); |
316 | }); | ||
317 | } | 318 | } |
318 | 319 | ||
319 | Trace() << "Sorted " << sortedMap->size() << " values."; | 320 | Trace() << "Sorted " << sortedMap->size() << " values."; |
320 | auto iterator = QSharedPointer<QMapIterator<QByteArray, QByteArray> >::create(*sortedMap); | 321 | auto iterator = QSharedPointer<QMapIterator<QByteArray, QByteArray>>::create(*sortedMap); |
321 | ResultSet::ValueGenerator generator = [this, iterator, sortedMap, &db, filter, initialQuery](std::function<void(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &, Sink::Operation)> callback) -> bool { | 322 | ResultSet::ValueGenerator generator = [this, iterator, sortedMap, &db, filter, initialQuery]( |
323 | std::function<void(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &, Sink::Operation)> callback) -> bool { | ||
322 | if (iterator->hasNext()) { | 324 | if (iterator->hasNext()) { |
323 | readEntity(db, iterator->next().value(), [this, filter, callback, initialQuery](const Sink::ApplicationDomain::ApplicationDomainType::Ptr &domainObject, Sink::Operation operation) { | 325 | readEntity(db, iterator->next().value(), [this, filter, callback, initialQuery](const Sink::ApplicationDomain::ApplicationDomainType::Ptr &domainObject, |
324 | callback(domainObject, Sink::Operation_Creation); | 326 | Sink::Operation operation) { callback(domainObject, Sink::Operation_Creation); }); |
325 | }); | ||
326 | return true; | 327 | return true; |
327 | } | 328 | } |
328 | return false; | 329 | return false; |
@@ -336,19 +337,21 @@ ResultSet QueryWorker<DomainType>::filterAndSortSet(ResultSet &resultSet, const | |||
336 | return ResultSet(generator, skip); | 337 | return ResultSet(generator, skip); |
337 | } else { | 338 | } else { |
338 | auto resultSetPtr = QSharedPointer<ResultSet>::create(resultSet); | 339 | auto resultSetPtr = QSharedPointer<ResultSet>::create(resultSet); |
339 | ResultSet::ValueGenerator generator = [this, resultSetPtr, &db, filter, initialQuery](std::function<void(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &, Sink::Operation)> callback) -> bool { | 340 | ResultSet::ValueGenerator generator = [this, resultSetPtr, &db, filter, initialQuery]( |
341 | std::function<void(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &, Sink::Operation)> callback) -> bool { | ||
340 | if (resultSetPtr->next()) { | 342 | if (resultSetPtr->next()) { |
341 | //readEntity is only necessary if we actually want to filter or know the operation type (but not a big deal if we do it always I guess) | 343 | // readEntity is only necessary if we actually want to filter or know the operation type (but not a big deal if we do it always I guess) |
342 | readEntity(db, resultSetPtr->id(), [this, filter, callback, initialQuery](const Sink::ApplicationDomain::ApplicationDomainType::Ptr &domainObject, Sink::Operation operation) { | 344 | readEntity(db, resultSetPtr->id(), [this, filter, callback, initialQuery](const Sink::ApplicationDomain::ApplicationDomainType::Ptr &domainObject, Sink::Operation operation) { |
343 | if (initialQuery) { | 345 | if (initialQuery) { |
344 | //We're not interested in removals during the initial query | 346 | // We're not interested in removals during the initial query |
345 | if ((operation != Sink::Operation_Removal) && filter(domainObject)) { | 347 | if ((operation != Sink::Operation_Removal) && filter(domainObject)) { |
346 | //In the initial set every entity is new | 348 | // In the initial set every entity is new |
347 | callback(domainObject, Sink::Operation_Creation); | 349 | callback(domainObject, Sink::Operation_Creation); |
348 | } } else { | 350 | } |
349 | //Always remove removals, they probably don't match due to non-available properties | 351 | } else { |
352 | // Always remove removals, they probably don't match due to non-available properties | ||
350 | if ((operation == Sink::Operation_Removal) || filter(domainObject)) { | 353 | if ((operation == Sink::Operation_Removal) || filter(domainObject)) { |
351 | //TODO only replay if this is in the currently visible set (or just always replay, worst case we have a couple to many results) | 354 | // TODO only replay if this is in the currently visible set (or just always replay, worst case we have a couple to many results) |
352 | callback(domainObject, operation); | 355 | callback(domainObject, operation); |
353 | } | 356 | } |
354 | } | 357 | } |
@@ -357,15 +360,14 @@ ResultSet QueryWorker<DomainType>::filterAndSortSet(ResultSet &resultSet, const | |||
357 | } | 360 | } |
358 | return false; | 361 | return false; |
359 | }; | 362 | }; |
360 | auto skip = [resultSetPtr]() { | 363 | auto skip = [resultSetPtr]() { resultSetPtr->skip(1); }; |
361 | resultSetPtr->skip(1); | ||
362 | }; | ||
363 | return ResultSet(generator, skip); | 364 | return ResultSet(generator, skip); |
364 | } | 365 | } |
365 | } | 366 | } |
366 | 367 | ||
367 | template<class DomainType> | 368 | template <class DomainType> |
368 | std::function<bool(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &domainObject)> QueryWorker<DomainType>::getFilter(const QSet<QByteArray> remainingFilters, const Sink::Query &query) | 369 | std::function<bool(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &domainObject)> |
370 | QueryWorker<DomainType>::getFilter(const QSet<QByteArray> remainingFilters, const Sink::Query &query) | ||
369 | { | 371 | { |
370 | return [remainingFilters, query](const Sink::ApplicationDomain::ApplicationDomainType::Ptr &domainObject) -> bool { | 372 | return [remainingFilters, query](const Sink::ApplicationDomain::ApplicationDomainType::Ptr &domainObject) -> bool { |
371 | if (!query.ids.isEmpty()) { | 373 | if (!query.ids.isEmpty()) { |
@@ -376,7 +378,7 @@ std::function<bool(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &do | |||
376 | for (const auto &filterProperty : remainingFilters) { | 378 | for (const auto &filterProperty : remainingFilters) { |
377 | const auto property = domainObject->getProperty(filterProperty); | 379 | const auto property = domainObject->getProperty(filterProperty); |
378 | if (property.isValid()) { | 380 | if (property.isValid()) { |
379 | //TODO implement other comparison operators than equality | 381 | // TODO implement other comparison operators than equality |
380 | if (property != query.propertyFilter.value(filterProperty)) { | 382 | if (property != query.propertyFilter.value(filterProperty)) { |
381 | Trace() << "Filtering entity due to property mismatch on filter: " << filterProperty << property << ":" << query.propertyFilter.value(filterProperty); | 383 | Trace() << "Filtering entity due to property mismatch on filter: " << filterProperty << property << ":" << query.propertyFilter.value(filterProperty); |
382 | return false; | 384 | return false; |
@@ -389,16 +391,15 @@ std::function<bool(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &do | |||
389 | }; | 391 | }; |
390 | } | 392 | } |
391 | 393 | ||
392 | template<class DomainType> | 394 | template <class DomainType> |
393 | qint64 QueryWorker<DomainType>::load(const Sink::Query &query, const std::function<ResultSet(Sink::Storage::Transaction &, QSet<QByteArray> &, QByteArray &)> &baseSetRetriever, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, bool initialQuery, int offset, int batchSize) | 395 | qint64 QueryWorker<DomainType>::load(const Sink::Query &query, const std::function<ResultSet(Sink::Storage::Transaction &, QSet<QByteArray> &, QByteArray &)> &baseSetRetriever, |
396 | Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, bool initialQuery, int offset, int batchSize) | ||
394 | { | 397 | { |
395 | QTime time; | 398 | QTime time; |
396 | time.start(); | 399 | time.start(); |
397 | 400 | ||
398 | Sink::Storage storage(Sink::storageLocation(), mResourceInstanceIdentifier); | 401 | Sink::Storage storage(Sink::storageLocation(), mResourceInstanceIdentifier); |
399 | storage.setDefaultErrorHandler([](const Sink::Storage::Error &error) { | 402 | storage.setDefaultErrorHandler([](const Sink::Storage::Error &error) { Warning() << "Error during query: " << error.store << error.message; }); |
400 | Warning() << "Error during query: " << error.store << error.message; | ||
401 | }); | ||
402 | auto transaction = storage.createTransaction(Sink::Storage::ReadOnly); | 403 | auto transaction = storage.createTransaction(Sink::Storage::ReadOnly); |
403 | auto db = Storage::mainDatabase(transaction, mBufferType); | 404 | auto db = Storage::mainDatabase(transaction, mBufferType); |
404 | 405 | ||
@@ -414,7 +415,7 @@ qint64 QueryWorker<DomainType>::load(const Sink::Query &query, const std::functi | |||
414 | return Sink::Storage::maxRevision(transaction); | 415 | return Sink::Storage::maxRevision(transaction); |
415 | } | 416 | } |
416 | 417 | ||
417 | template<class DomainType> | 418 | template <class DomainType> |
418 | qint64 QueryWorker<DomainType>::executeIncrementalQuery(const Sink::Query &query, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider) | 419 | qint64 QueryWorker<DomainType>::executeIncrementalQuery(const Sink::Query &query, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider) |
419 | { | 420 | { |
420 | QTime time; | 421 | QTime time; |
@@ -429,8 +430,9 @@ qint64 QueryWorker<DomainType>::executeIncrementalQuery(const Sink::Query &query | |||
429 | return revision; | 430 | return revision; |
430 | } | 431 | } |
431 | 432 | ||
432 | template<class DomainType> | 433 | template <class DomainType> |
433 | qint64 QueryWorker<DomainType>::executeInitialQuery(const Sink::Query &query, const typename DomainType::Ptr &parent, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, int offset, int batchsize) | 434 | qint64 QueryWorker<DomainType>::executeInitialQuery( |
435 | const Sink::Query &query, const typename DomainType::Ptr &parent, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, int offset, int batchsize) | ||
434 | { | 436 | { |
435 | QTime time; | 437 | QTime time; |
436 | time.start(); | 438 | time.start(); |
diff --git a/common/queryrunner.h b/common/queryrunner.h index 436e2e0..adaf297 100644 --- a/common/queryrunner.h +++ b/common/queryrunner.h | |||
@@ -70,18 +70,19 @@ private: | |||
70 | 70 | ||
71 | /** | 71 | /** |
72 | * A QueryRunner runs a query and updates the corresponding result set. | 72 | * A QueryRunner runs a query and updates the corresponding result set. |
73 | * | 73 | * |
74 | * The lifetime of the QueryRunner is defined by the resut set (otherwise it's doing useless work), | 74 | * The lifetime of the QueryRunner is defined by the resut set (otherwise it's doing useless work), |
75 | * and by how long a result set must be updated. If the query is one off the runner dies after the execution, | 75 | * and by how long a result set must be updated. If the query is one off the runner dies after the execution, |
76 | * otherwise it lives on the react to changes and updates the corresponding result set. | 76 | * otherwise it lives on the react to changes and updates the corresponding result set. |
77 | * | 77 | * |
78 | * QueryRunner has to keep ResourceAccess alive in order to keep getting updates. | 78 | * QueryRunner has to keep ResourceAccess alive in order to keep getting updates. |
79 | */ | 79 | */ |
80 | template<typename DomainType> | 80 | template <typename DomainType> |
81 | class QueryRunner : public QueryRunnerBase | 81 | class QueryRunner : public QueryRunnerBase |
82 | { | 82 | { |
83 | public: | 83 | public: |
84 | QueryRunner(const Sink::Query &query, const Sink::ResourceAccessInterface::Ptr &, const QByteArray &instanceIdentifier, const DomainTypeAdaptorFactoryInterface::Ptr &, const QByteArray &bufferType); | 84 | QueryRunner(const Sink::Query &query, const Sink::ResourceAccessInterface::Ptr &, const QByteArray &instanceIdentifier, const DomainTypeAdaptorFactoryInterface::Ptr &, |
85 | const QByteArray &bufferType); | ||
85 | virtual ~QueryRunner(); | 86 | virtual ~QueryRunner(); |
86 | 87 | ||
87 | /** | 88 | /** |
@@ -94,9 +95,8 @@ public: | |||
94 | 95 | ||
95 | private: | 96 | private: |
96 | QSharedPointer<Sink::ResourceAccessInterface> mResourceAccess; | 97 | QSharedPointer<Sink::ResourceAccessInterface> mResourceAccess; |
97 | QSharedPointer<Sink::ResultProvider<typename DomainType::Ptr> > mResultProvider; | 98 | QSharedPointer<Sink::ResultProvider<typename DomainType::Ptr>> mResultProvider; |
98 | ResultTransformation mResultTransformation; | 99 | ResultTransformation mResultTransformation; |
99 | int mOffset; | 100 | int mOffset; |
100 | int mBatchSize; | 101 | int mBatchSize; |
101 | }; | 102 | }; |
102 | |||
diff --git a/common/resource.cpp b/common/resource.cpp index 5cbb2f2..6713686 100644 --- a/common/resource.cpp +++ b/common/resource.cpp | |||
@@ -27,19 +27,16 @@ | |||
27 | 27 | ||
28 | #include "facadefactory.h" | 28 | #include "facadefactory.h" |
29 | 29 | ||
30 | namespace Sink | 30 | namespace Sink { |
31 | { | ||
32 | 31 | ||
33 | Resource::Resource() | 32 | Resource::Resource() : QObject(), d(0) |
34 | : QObject(), | ||
35 | d(0) | ||
36 | { | 33 | { |
37 | Q_UNUSED(d); | 34 | Q_UNUSED(d); |
38 | } | 35 | } |
39 | 36 | ||
40 | Resource::~Resource() | 37 | Resource::~Resource() |
41 | { | 38 | { |
42 | //delete d; | 39 | // delete d; |
43 | } | 40 | } |
44 | 41 | ||
45 | void Resource::processCommand(int commandId, const QByteArray &data) | 42 | void Resource::processCommand(int commandId, const QByteArray &data) |
@@ -71,21 +68,19 @@ void Resource::removeDataFromDisk() | |||
71 | class ResourceFactory::Private | 68 | class ResourceFactory::Private |
72 | { | 69 | { |
73 | public: | 70 | public: |
74 | static QHash<QString, QPointer<ResourceFactory> > s_loadedFactories; | 71 | static QHash<QString, QPointer<ResourceFactory>> s_loadedFactories; |
75 | }; | 72 | }; |
76 | 73 | ||
77 | QHash<QString, QPointer<ResourceFactory> > ResourceFactory::Private::s_loadedFactories; | 74 | QHash<QString, QPointer<ResourceFactory>> ResourceFactory::Private::s_loadedFactories; |
78 | 75 | ||
79 | ResourceFactory::ResourceFactory(QObject *parent) | 76 | ResourceFactory::ResourceFactory(QObject *parent) : QObject(parent), d(0) |
80 | : QObject(parent), | ||
81 | d(0) | ||
82 | { | 77 | { |
83 | Q_UNUSED(d); | 78 | Q_UNUSED(d); |
84 | } | 79 | } |
85 | 80 | ||
86 | ResourceFactory::~ResourceFactory() | 81 | ResourceFactory::~ResourceFactory() |
87 | { | 82 | { |
88 | //delete d; | 83 | // delete d; |
89 | } | 84 | } |
90 | 85 | ||
91 | ResourceFactory *ResourceFactory::load(const QString &resourceName) | 86 | ResourceFactory *ResourceFactory::load(const QString &resourceName) |
@@ -95,15 +90,15 @@ ResourceFactory *ResourceFactory::load(const QString &resourceName) | |||
95 | return factory; | 90 | return factory; |
96 | } | 91 | } |
97 | 92 | ||
98 | for (auto const &path: QCoreApplication::instance()->libraryPaths()) { | 93 | for (auto const &path : QCoreApplication::instance()->libraryPaths()) { |
99 | if (path.endsWith(QLatin1String("plugins"))) { | 94 | if (path.endsWith(QLatin1String("plugins"))) { |
100 | QDir pluginDir(path); | 95 | QDir pluginDir(path); |
101 | //TODO: centralize this so that it is easy to change centrally | 96 | // TODO: centralize this so that it is easy to change centrally |
102 | // also ref'd in cmake as ${SINK_RESOURCE_PLUGINS_PATH} | 97 | // also ref'd in cmake as ${SINK_RESOURCE_PLUGINS_PATH} |
103 | pluginDir.cd(QStringLiteral("sink")); | 98 | pluginDir.cd(QStringLiteral("sink")); |
104 | pluginDir.cd(QStringLiteral("resources")); | 99 | pluginDir.cd(QStringLiteral("resources")); |
105 | 100 | ||
106 | for (const QString &fileName: pluginDir.entryList(QDir::Files)) { | 101 | for (const QString &fileName : pluginDir.entryList(QDir::Files)) { |
107 | const QString path = pluginDir.absoluteFilePath(fileName); | 102 | const QString path = pluginDir.absoluteFilePath(fileName); |
108 | QPluginLoader loader(path); | 103 | QPluginLoader loader(path); |
109 | 104 | ||
@@ -115,7 +110,7 @@ ResourceFactory *ResourceFactory::load(const QString &resourceName) | |||
115 | if (factory) { | 110 | if (factory) { |
116 | Private::s_loadedFactories.insert(resourceName, factory); | 111 | Private::s_loadedFactories.insert(resourceName, factory); |
117 | factory->registerFacades(FacadeFactory::instance()); | 112 | factory->registerFacades(FacadeFactory::instance()); |
118 | //TODO: if we need more data on it const QJsonObject json = loader.metaData()[QStringLiteral("MetaData")].toObject(); | 113 | // TODO: if we need more data on it const QJsonObject json = loader.metaData()[QStringLiteral("MetaData")].toObject(); |
119 | return factory; | 114 | return factory; |
120 | } else { | 115 | } else { |
121 | qWarning() << "Plugin for" << resourceName << "from plugin" << loader.fileName() << "produced the wrong object type:" << object; | 116 | qWarning() << "Plugin for" << resourceName << "from plugin" << loader.fileName() << "produced the wrong object type:" << object; |
@@ -135,7 +130,7 @@ ResourceFactory *ResourceFactory::load(const QString &resourceName) | |||
135 | 130 | ||
136 | } // namespace Sink | 131 | } // namespace Sink |
137 | 132 | ||
138 | //Ignore warning I don't know how to fix in a moc file | 133 | // Ignore warning I don't know how to fix in a moc file |
139 | #pragma clang diagnostic push | 134 | #pragma clang diagnostic push |
140 | #pragma clang diagnostic ignored "-Wundefined-reinterpret-cast" | 135 | #pragma clang diagnostic ignored "-Wundefined-reinterpret-cast" |
141 | #include "moc_resource.cpp" | 136 | #include "moc_resource.cpp" |
diff --git a/common/resource.h b/common/resource.h index d0100f6..0e7cd11 100644 --- a/common/resource.h +++ b/common/resource.h | |||
@@ -24,8 +24,7 @@ | |||
24 | #include <Async/Async> | 24 | #include <Async/Async> |
25 | #include "notification.h" | 25 | #include "notification.h" |
26 | 26 | ||
27 | namespace Sink | 27 | namespace Sink { |
28 | { | ||
29 | class FacadeFactory; | 28 | class FacadeFactory; |
30 | 29 | ||
31 | /** | 30 | /** |
@@ -66,7 +65,7 @@ signals: | |||
66 | 65 | ||
67 | private: | 66 | private: |
68 | class Private; | 67 | class Private; |
69 | Private * const d; | 68 | Private *const d; |
70 | }; | 69 | }; |
71 | 70 | ||
72 | /** | 71 | /** |
@@ -85,11 +84,9 @@ public: | |||
85 | 84 | ||
86 | private: | 85 | private: |
87 | class Private; | 86 | class Private; |
88 | Private * const d; | 87 | Private *const d; |
89 | }; | 88 | }; |
90 | 89 | ||
91 | } // namespace Sink | 90 | } // namespace Sink |
92 | 91 | ||
93 | Q_DECLARE_INTERFACE(Sink::ResourceFactory, "org.kde.sink.resourcefactory") | 92 | Q_DECLARE_INTERFACE(Sink::ResourceFactory, "org.kde.sink.resourcefactory") |
94 | |||
95 | |||
diff --git a/common/resourceaccess.cpp b/common/resourceaccess.cpp index 0716ae2..c8c8189 100644 --- a/common/resourceaccess.cpp +++ b/common/resourceaccess.cpp | |||
@@ -53,27 +53,20 @@ static void queuedInvoke(const std::function<void()> &f, QObject *context = 0) | |||
53 | { | 53 | { |
54 | auto timer = QSharedPointer<QTimer>::create(); | 54 | auto timer = QSharedPointer<QTimer>::create(); |
55 | timer->setSingleShot(true); | 55 | timer->setSingleShot(true); |
56 | QObject::connect(timer.data(), &QTimer::timeout, context, [f, timer]() { | 56 | QObject::connect(timer.data(), &QTimer::timeout, context, [f, timer]() { f(); }); |
57 | f(); | ||
58 | }); | ||
59 | timer->start(0); | 57 | timer->start(0); |
60 | } | 58 | } |
61 | 59 | ||
62 | namespace Sink | 60 | namespace Sink { |
63 | { | ||
64 | 61 | ||
65 | struct QueuedCommand | 62 | struct QueuedCommand |
66 | { | 63 | { |
67 | public: | 64 | public: |
68 | QueuedCommand(int commandId, const std::function<void(int, const QString &)> &callback) | 65 | QueuedCommand(int commandId, const std::function<void(int, const QString &)> &callback) : commandId(commandId), callback(callback) |
69 | : commandId(commandId), | 66 | { |
70 | callback(callback) | 67 | } |
71 | {} | 68 | |
72 | 69 | QueuedCommand(int commandId, const QByteArray &b, const std::function<void(int, const QString &)> &callback) : commandId(commandId), buffer(b), callback(callback) | |
73 | QueuedCommand(int commandId, const QByteArray &b, const std::function<void(int, const QString &)> &callback) | ||
74 | : commandId(commandId), | ||
75 | buffer(b), | ||
76 | callback(callback) | ||
77 | { | 70 | { |
78 | } | 71 | } |
79 | 72 | ||
@@ -102,17 +95,14 @@ public: | |||
102 | QByteArray partialMessageBuffer; | 95 | QByteArray partialMessageBuffer; |
103 | QVector<QSharedPointer<QueuedCommand>> commandQueue; | 96 | QVector<QSharedPointer<QueuedCommand>> commandQueue; |
104 | QMap<uint, QSharedPointer<QueuedCommand>> pendingCommands; | 97 | QMap<uint, QSharedPointer<QueuedCommand>> pendingCommands; |
105 | QMultiMap<uint, std::function<void(int error, const QString &errorMessage)> > resultHandler; | 98 | QMultiMap<uint, std::function<void(int error, const QString &errorMessage)>> resultHandler; |
106 | QSet<uint> completeCommands; | 99 | QSet<uint> completeCommands; |
107 | uint messageId; | 100 | uint messageId; |
108 | bool openingSocket; | 101 | bool openingSocket; |
109 | }; | 102 | }; |
110 | 103 | ||
111 | ResourceAccess::Private::Private(const QByteArray &name, const QByteArray &instanceIdentifier, ResourceAccess *q) | 104 | ResourceAccess::Private::Private(const QByteArray &name, const QByteArray &instanceIdentifier, ResourceAccess *q) |
112 | : resourceName(name), | 105 | : resourceName(name), resourceInstanceIdentifier(instanceIdentifier), messageId(0), openingSocket(false) |
113 | resourceInstanceIdentifier(instanceIdentifier), | ||
114 | messageId(0), | ||
115 | openingSocket(false) | ||
116 | { | 106 | { |
117 | } | 107 | } |
118 | 108 | ||
@@ -124,7 +114,7 @@ void ResourceAccess::Private::abortPendingOperations() | |||
124 | } | 114 | } |
125 | auto handlers = resultHandler.values(); | 115 | auto handlers = resultHandler.values(); |
126 | resultHandler.clear(); | 116 | resultHandler.clear(); |
127 | for(auto handler : handlers) { | 117 | for (auto handler : handlers) { |
128 | handler(1, "The resource closed unexpectedly"); | 118 | handler(1, "The resource closed unexpectedly"); |
129 | } | 119 | } |
130 | } | 120 | } |
@@ -132,20 +122,20 @@ void ResourceAccess::Private::abortPendingOperations() | |||
132 | void ResourceAccess::Private::callCallbacks() | 122 | void ResourceAccess::Private::callCallbacks() |
133 | { | 123 | { |
134 | for (auto id : completeCommands) { | 124 | for (auto id : completeCommands) { |
135 | //We remove the callbacks first because the handler can kill resourceaccess directly | 125 | // We remove the callbacks first because the handler can kill resourceaccess directly |
136 | const auto callbacks = resultHandler.values(id); | 126 | const auto callbacks = resultHandler.values(id); |
137 | resultHandler.remove(id); | 127 | resultHandler.remove(id); |
138 | for(auto handler : callbacks) { | 128 | for (auto handler : callbacks) { |
139 | handler(0, QString()); | 129 | handler(0, QString()); |
140 | } | 130 | } |
141 | } | 131 | } |
142 | } | 132 | } |
143 | 133 | ||
144 | //Connects to server and returns connected socket on success | 134 | // Connects to server and returns connected socket on success |
145 | KAsync::Job<QSharedPointer<QLocalSocket> > ResourceAccess::connectToServer(const QByteArray &identifier) | 135 | KAsync::Job<QSharedPointer<QLocalSocket>> ResourceAccess::connectToServer(const QByteArray &identifier) |
146 | { | 136 | { |
147 | auto s = QSharedPointer<QLocalSocket>::create(); | 137 | auto s = QSharedPointer<QLocalSocket>::create(); |
148 | return KAsync::start<QSharedPointer<QLocalSocket> >([identifier, s](KAsync::Future<QSharedPointer<QLocalSocket> > &future) { | 138 | return KAsync::start<QSharedPointer<QLocalSocket>>([identifier, s](KAsync::Future<QSharedPointer<QLocalSocket>> &future) { |
149 | s->setServerName(identifier); | 139 | s->setServerName(identifier); |
150 | auto context = new QObject; | 140 | auto context = new QObject; |
151 | QObject::connect(s.data(), &QLocalSocket::connected, context, [&future, &s, context]() { | 141 | QObject::connect(s.data(), &QLocalSocket::connected, context, [&future, &s, context]() { |
@@ -154,7 +144,7 @@ KAsync::Job<QSharedPointer<QLocalSocket> > ResourceAccess::connectToServer(const | |||
154 | future.setValue(s); | 144 | future.setValue(s); |
155 | future.setFinished(); | 145 | future.setFinished(); |
156 | }); | 146 | }); |
157 | QObject::connect(s.data(), static_cast<void(QLocalSocket::*)(QLocalSocket::LocalSocketError)>(&QLocalSocket::error), context, [&future, context](QLocalSocket::LocalSocketError) { | 147 | QObject::connect(s.data(), static_cast<void (QLocalSocket::*)(QLocalSocket::LocalSocketError)>(&QLocalSocket::error), context, [&future, context](QLocalSocket::LocalSocketError) { |
158 | delete context; | 148 | delete context; |
159 | future.setError(-1, "Failed to connect to server."); | 149 | future.setError(-1, "Failed to connect to server."); |
160 | }); | 150 | }); |
@@ -164,66 +154,67 @@ KAsync::Job<QSharedPointer<QLocalSocket> > ResourceAccess::connectToServer(const | |||
164 | 154 | ||
165 | KAsync::Job<void> ResourceAccess::Private::tryToConnect() | 155 | KAsync::Job<void> ResourceAccess::Private::tryToConnect() |
166 | { | 156 | { |
167 | //We may have a socket from the last connection leftover | 157 | // We may have a socket from the last connection leftover |
168 | socket.reset(); | 158 | socket.reset(); |
169 | auto counter = QSharedPointer<int>::create(0); | 159 | auto counter = QSharedPointer<int>::create(0); |
170 | return KAsync::dowhile([this]() -> bool { | 160 | return KAsync::dowhile([this]() -> bool { return !socket; }, |
171 | return !socket; | 161 | [this, counter](KAsync::Future<void> &future) { |
172 | }, | 162 | TracePrivate() << "Loop"; |
173 | [this, counter](KAsync::Future<void> &future) { | 163 | connectToServer(resourceInstanceIdentifier) |
174 | TracePrivate() << "Loop"; | 164 | .then<void, QSharedPointer<QLocalSocket>>( |
175 | connectToServer(resourceInstanceIdentifier) | 165 | [this, &future](const QSharedPointer<QLocalSocket> &s) { |
176 | .then<void, QSharedPointer<QLocalSocket> >([this, &future](const QSharedPointer<QLocalSocket> &s) { | 166 | Q_ASSERT(s); |
177 | Q_ASSERT(s); | 167 | socket = s; |
178 | socket = s; | 168 | future.setFinished(); |
179 | future.setFinished(); | 169 | }, |
180 | }, [&future, counter, this](int errorCode, const QString &errorString) { | 170 | [&future, counter, this](int errorCode, const QString &errorString) { |
181 | static int waitTime = 10; | 171 | static int waitTime = 10; |
182 | static int timeout = 500; | 172 | static int timeout = 500; |
183 | static int maxRetries = timeout / waitTime; | 173 | static int maxRetries = timeout / waitTime; |
184 | if (*counter > maxRetries) { | 174 | if (*counter > maxRetries) { |
185 | TracePrivate() << "Giving up"; | 175 | TracePrivate() << "Giving up"; |
186 | future.setError(-1, "Failed to connect to socket"); | 176 | future.setError(-1, "Failed to connect to socket"); |
187 | } else { | 177 | } else { |
188 | KAsync::wait(waitTime).then<void>([&future]() { | 178 | KAsync::wait(waitTime).then<void>([&future]() { future.setFinished(); }).exec(); |
189 | future.setFinished(); | 179 | } |
190 | }).exec(); | 180 | *counter = *counter + 1; |
191 | } | 181 | }) |
192 | *counter = *counter + 1; | 182 | .exec(); |
193 | }) | 183 | }); |
194 | .exec(); | ||
195 | }); | ||
196 | } | 184 | } |
197 | 185 | ||
198 | KAsync::Job<void> ResourceAccess::Private::initializeSocket() | 186 | KAsync::Job<void> ResourceAccess::Private::initializeSocket() |
199 | { | 187 | { |
200 | return KAsync::start<void>([this](KAsync::Future<void> &future) { | 188 | return KAsync::start<void>([this](KAsync::Future<void> &future) { |
201 | TracePrivate() << "Trying to connect"; | 189 | TracePrivate() << "Trying to connect"; |
202 | connectToServer(resourceInstanceIdentifier).then<void, QSharedPointer<QLocalSocket> >([this, &future](const QSharedPointer<QLocalSocket> &s) { | 190 | connectToServer(resourceInstanceIdentifier) |
203 | TracePrivate() << "Connected to resource, without having to start it."; | 191 | .then<void, QSharedPointer<QLocalSocket>>( |
204 | Q_ASSERT(s); | 192 | [this, &future](const QSharedPointer<QLocalSocket> &s) { |
205 | socket = s; | 193 | TracePrivate() << "Connected to resource, without having to start it."; |
206 | future.setFinished(); | 194 | Q_ASSERT(s); |
207 | }, | 195 | socket = s; |
208 | [this, &future](int errorCode, const QString &errorString) { | ||
209 | TracePrivate() << "Failed to connect, starting resource"; | ||
210 | //We failed to connect, so let's start the resource | ||
211 | QStringList args; | ||
212 | args << resourceInstanceIdentifier; | ||
213 | qint64 pid = 0; | ||
214 | if (QProcess::startDetached("sink_synchronizer", args, QDir::homePath(), &pid)) { | ||
215 | TracePrivate() << "Started resource " << pid; | ||
216 | tryToConnect() | ||
217 | .then<void>([&future]() { | ||
218 | future.setFinished(); | 196 | future.setFinished(); |
219 | }, [this, &future](int errorCode, const QString &errorString) { | 197 | }, |
220 | Warning() << "Failed to connect to started resource"; | 198 | [this, &future](int errorCode, const QString &errorString) { |
221 | future.setError(errorCode, errorString); | 199 | TracePrivate() << "Failed to connect, starting resource"; |
222 | }).exec(); | 200 | // We failed to connect, so let's start the resource |
223 | } else { | 201 | QStringList args; |
224 | Warning() << "Failed to start resource"; | 202 | args << resourceInstanceIdentifier; |
225 | } | 203 | qint64 pid = 0; |
226 | }).exec(); | 204 | if (QProcess::startDetached("sink_synchronizer", args, QDir::homePath(), &pid)) { |
205 | TracePrivate() << "Started resource " << pid; | ||
206 | tryToConnect() | ||
207 | .then<void>([&future]() { future.setFinished(); }, | ||
208 | [this, &future](int errorCode, const QString &errorString) { | ||
209 | Warning() << "Failed to connect to started resource"; | ||
210 | future.setError(errorCode, errorString); | ||
211 | }) | ||
212 | .exec(); | ||
213 | } else { | ||
214 | Warning() << "Failed to start resource"; | ||
215 | } | ||
216 | }) | ||
217 | .exec(); | ||
227 | }); | 218 | }); |
228 | } | 219 | } |
229 | 220 | ||
@@ -235,8 +226,7 @@ static QByteArray getResourceName(const QByteArray &instanceIdentifier) | |||
235 | } | 226 | } |
236 | 227 | ||
237 | ResourceAccess::ResourceAccess(const QByteArray &resourceInstanceIdentifier) | 228 | ResourceAccess::ResourceAccess(const QByteArray &resourceInstanceIdentifier) |
238 | : ResourceAccessInterface(), | 229 | : ResourceAccessInterface(), d(new Private(getResourceName(resourceInstanceIdentifier), resourceInstanceIdentifier, this)) |
239 | d(new Private(getResourceName(resourceInstanceIdentifier), resourceInstanceIdentifier, this)) | ||
240 | { | 230 | { |
241 | Log() << "Starting access"; | 231 | Log() << "Starting access"; |
242 | } | 232 | } |
@@ -280,10 +270,10 @@ KAsync::Job<void> ResourceAccess::sendCommand(int commandId) | |||
280 | }); | 270 | }); |
281 | } | 271 | } |
282 | 272 | ||
283 | KAsync::Job<void> ResourceAccess::sendCommand(int commandId, flatbuffers::FlatBufferBuilder &fbb) | 273 | KAsync::Job<void> ResourceAccess::sendCommand(int commandId, flatbuffers::FlatBufferBuilder &fbb) |
284 | { | 274 | { |
285 | //The flatbuffer is transient, but we want to store it until the job is executed | 275 | // The flatbuffer is transient, but we want to store it until the job is executed |
286 | QByteArray buffer(reinterpret_cast<const char*>(fbb.GetBufferPointer()), fbb.GetSize()); | 276 | QByteArray buffer(reinterpret_cast<const char *>(fbb.GetBufferPointer()), fbb.GetSize()); |
287 | return KAsync::start<void>([commandId, buffer, this](KAsync::Future<void> &f) { | 277 | return KAsync::start<void>([commandId, buffer, this](KAsync::Future<void> &f) { |
288 | auto callback = [&f](int error, const QString &errorMessage) { | 278 | auto callback = [&f](int error, const QString &errorMessage) { |
289 | if (error) { | 279 | if (error) { |
@@ -313,7 +303,7 @@ KAsync::Job<void> ResourceAccess::synchronizeResource(bool sourceSync, bool loca | |||
313 | KAsync::Job<void> ResourceAccess::sendCreateCommand(const QByteArray &resourceBufferType, const QByteArray &buffer) | 303 | KAsync::Job<void> ResourceAccess::sendCreateCommand(const QByteArray &resourceBufferType, const QByteArray &buffer) |
314 | { | 304 | { |
315 | flatbuffers::FlatBufferBuilder fbb; | 305 | flatbuffers::FlatBufferBuilder fbb; |
316 | //This is the resource buffer type and not the domain type | 306 | // This is the resource buffer type and not the domain type |
317 | auto type = fbb.CreateString(resourceBufferType.constData()); | 307 | auto type = fbb.CreateString(resourceBufferType.constData()); |
318 | auto delta = Sink::EntityBuffer::appendAsVector(fbb, buffer.constData(), buffer.size()); | 308 | auto delta = Sink::EntityBuffer::appendAsVector(fbb, buffer.constData(), buffer.size()); |
319 | auto location = Sink::Commands::CreateCreateEntity(fbb, 0, type, delta); | 309 | auto location = Sink::Commands::CreateCreateEntity(fbb, 0, type, delta); |
@@ -322,13 +312,14 @@ KAsync::Job<void> ResourceAccess::sendCreateCommand(const QByteArray &resourceBu | |||
322 | return sendCommand(Sink::Commands::CreateEntityCommand, fbb); | 312 | return sendCommand(Sink::Commands::CreateEntityCommand, fbb); |
323 | } | 313 | } |
324 | 314 | ||
325 | KAsync::Job<void> ResourceAccess::sendModifyCommand(const QByteArray &uid, qint64 revision, const QByteArray &resourceBufferType, const QByteArrayList &deletedProperties, const QByteArray &buffer) | 315 | KAsync::Job<void> |
316 | ResourceAccess::sendModifyCommand(const QByteArray &uid, qint64 revision, const QByteArray &resourceBufferType, const QByteArrayList &deletedProperties, const QByteArray &buffer) | ||
326 | { | 317 | { |
327 | flatbuffers::FlatBufferBuilder fbb; | 318 | flatbuffers::FlatBufferBuilder fbb; |
328 | auto entityId = fbb.CreateString(uid.constData()); | 319 | auto entityId = fbb.CreateString(uid.constData()); |
329 | //This is the resource buffer type and not the domain type | 320 | // This is the resource buffer type and not the domain type |
330 | auto type = fbb.CreateString(resourceBufferType.constData()); | 321 | auto type = fbb.CreateString(resourceBufferType.constData()); |
331 | //FIXME | 322 | // FIXME |
332 | auto deletions = 0; | 323 | auto deletions = 0; |
333 | auto delta = Sink::EntityBuffer::appendAsVector(fbb, buffer.constData(), buffer.size()); | 324 | auto delta = Sink::EntityBuffer::appendAsVector(fbb, buffer.constData(), buffer.size()); |
334 | auto location = Sink::Commands::CreateModifyEntity(fbb, revision, entityId, deletions, type, delta); | 325 | auto location = Sink::Commands::CreateModifyEntity(fbb, revision, entityId, deletions, type, delta); |
@@ -341,7 +332,7 @@ KAsync::Job<void> ResourceAccess::sendDeleteCommand(const QByteArray &uid, qint6 | |||
341 | { | 332 | { |
342 | flatbuffers::FlatBufferBuilder fbb; | 333 | flatbuffers::FlatBufferBuilder fbb; |
343 | auto entityId = fbb.CreateString(uid.constData()); | 334 | auto entityId = fbb.CreateString(uid.constData()); |
344 | //This is the resource buffer type and not the domain type | 335 | // This is the resource buffer type and not the domain type |
345 | auto type = fbb.CreateString(resourceBufferType.constData()); | 336 | auto type = fbb.CreateString(resourceBufferType.constData()); |
346 | auto location = Sink::Commands::CreateDeleteEntity(fbb, revision, entityId, type); | 337 | auto location = Sink::Commands::CreateDeleteEntity(fbb, revision, entityId, type); |
347 | Sink::Commands::FinishDeleteEntityBuffer(fbb, location); | 338 | Sink::Commands::FinishDeleteEntityBuffer(fbb, location); |
@@ -358,7 +349,8 @@ KAsync::Job<void> ResourceAccess::sendRevisionReplayedCommand(qint64 revision) | |||
358 | return sendCommand(Sink::Commands::RevisionReplayedCommand, fbb); | 349 | return sendCommand(Sink::Commands::RevisionReplayedCommand, fbb); |
359 | } | 350 | } |
360 | 351 | ||
361 | KAsync::Job<void> ResourceAccess::sendInspectionCommand(const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expectedValue) | 352 | KAsync::Job<void> |
353 | ResourceAccess::sendInspectionCommand(const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expectedValue) | ||
362 | { | 354 | { |
363 | flatbuffers::FlatBufferBuilder fbb; | 355 | flatbuffers::FlatBufferBuilder fbb; |
364 | auto id = fbb.CreateString(inspectionId.toStdString()); | 356 | auto id = fbb.CreateString(inspectionId.toStdString()); |
@@ -371,7 +363,7 @@ KAsync::Job<void> ResourceAccess::sendInspectionCommand(const QByteArray &inspec | |||
371 | s << expectedValue; | 363 | s << expectedValue; |
372 | 364 | ||
373 | auto expected = fbb.CreateString(array.toStdString()); | 365 | auto expected = fbb.CreateString(array.toStdString()); |
374 | auto location = Sink::Commands::CreateInspection (fbb, id, 0, entity, domain, prop, expected); | 366 | auto location = Sink::Commands::CreateInspection(fbb, id, 0, entity, domain, prop, expected); |
375 | Sink::Commands::FinishInspectionBuffer(fbb, location); | 367 | Sink::Commands::FinishInspectionBuffer(fbb, location); |
376 | open(); | 368 | open(); |
377 | return sendCommand(Sink::Commands::InspectionCommand, fbb); | 369 | return sendCommand(Sink::Commands::InspectionCommand, fbb); |
@@ -389,21 +381,21 @@ void ResourceAccess::open() | |||
389 | auto time = QSharedPointer<QTime>::create(); | 381 | auto time = QSharedPointer<QTime>::create(); |
390 | time->start(); | 382 | time->start(); |
391 | d->openingSocket = true; | 383 | d->openingSocket = true; |
392 | d->initializeSocket().then<void>([this, time]() { | 384 | d->initializeSocket() |
393 | Trace() << "Socket is initialized." << Log::TraceTime(time->elapsed()); | 385 | .then<void>( |
394 | d->openingSocket = false; | 386 | [this, time]() { |
395 | QObject::connect(d->socket.data(), &QLocalSocket::disconnected, | 387 | Trace() << "Socket is initialized." << Log::TraceTime(time->elapsed()); |
396 | this, &ResourceAccess::disconnected); | 388 | d->openingSocket = false; |
397 | QObject::connect(d->socket.data(), SIGNAL(error(QLocalSocket::LocalSocketError)), | 389 | QObject::connect(d->socket.data(), &QLocalSocket::disconnected, this, &ResourceAccess::disconnected); |
398 | this, SLOT(connectionError(QLocalSocket::LocalSocketError))); | 390 | QObject::connect(d->socket.data(), SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(connectionError(QLocalSocket::LocalSocketError))); |
399 | QObject::connect(d->socket.data(), &QIODevice::readyRead, | 391 | QObject::connect(d->socket.data(), &QIODevice::readyRead, this, &ResourceAccess::readResourceMessage); |
400 | this, &ResourceAccess::readResourceMessage); | 392 | connected(); |
401 | connected(); | 393 | }, |
402 | }, | 394 | [this](int error, const QString &errorString) { |
403 | [this](int error, const QString &errorString) { | 395 | d->openingSocket = false; |
404 | d->openingSocket = false; | 396 | Warning() << "Failed to initialize socket " << errorString; |
405 | Warning() << "Failed to initialize socket " << errorString; | 397 | }) |
406 | }).exec(); | 398 | .exec(); |
407 | } | 399 | } |
408 | 400 | ||
409 | void ResourceAccess::close() | 401 | void ResourceAccess::close() |
@@ -417,7 +409,7 @@ void ResourceAccess::close() | |||
417 | void ResourceAccess::sendCommand(const QSharedPointer<QueuedCommand> &command) | 409 | void ResourceAccess::sendCommand(const QSharedPointer<QueuedCommand> &command) |
418 | { | 410 | { |
419 | Q_ASSERT(isReady()); | 411 | Q_ASSERT(isReady()); |
420 | //TODO: we should have a timeout for commands | 412 | // TODO: we should have a timeout for commands |
421 | d->messageId++; | 413 | d->messageId++; |
422 | const auto messageId = d->messageId; | 414 | const auto messageId = d->messageId; |
423 | Log() << QString("Sending command \"%1\" with messageId %2").arg(QString(Sink::Commands::name(command->commandId))).arg(d->messageId); | 415 | Log() << QString("Sending command \"%1\" with messageId %2").arg(QString(Sink::Commands::name(command->commandId))).arg(d->messageId); |
@@ -427,17 +419,17 @@ void ResourceAccess::sendCommand(const QSharedPointer<QueuedCommand> &command) | |||
427 | d->pendingCommands.remove(messageId); | 419 | d->pendingCommands.remove(messageId); |
428 | command->callback(errorCode, errorMessage); | 420 | command->callback(errorCode, errorMessage); |
429 | }); | 421 | }); |
430 | //Keep track of the command until we're sure it arrived | 422 | // Keep track of the command until we're sure it arrived |
431 | d->pendingCommands.insert(d->messageId, command); | 423 | d->pendingCommands.insert(d->messageId, command); |
432 | Commands::write(d->socket.data(), d->messageId, command->commandId, command->buffer.constData(), command->buffer.size()); | 424 | Commands::write(d->socket.data(), d->messageId, command->commandId, command->buffer.constData(), command->buffer.size()); |
433 | } | 425 | } |
434 | 426 | ||
435 | void ResourceAccess::processCommandQueue() | 427 | void ResourceAccess::processCommandQueue() |
436 | { | 428 | { |
437 | //TODO: serialize instead of blast them all through the socket? | 429 | // TODO: serialize instead of blast them all through the socket? |
438 | Trace() << "We have " << d->commandQueue.size() << " queued commands"; | 430 | Trace() << "We have " << d->commandQueue.size() << " queued commands"; |
439 | Trace() << "Pending commands: " << d->pendingCommands.size(); | 431 | Trace() << "Pending commands: " << d->pendingCommands.size(); |
440 | for (auto command: d->commandQueue) { | 432 | for (auto command : d->commandQueue) { |
441 | sendCommand(command); | 433 | sendCommand(command); |
442 | } | 434 | } |
443 | d->commandQueue.clear(); | 435 | d->commandQueue.clear(); |
@@ -446,7 +438,7 @@ void ResourceAccess::processCommandQueue() | |||
446 | void ResourceAccess::processPendingCommandQueue() | 438 | void ResourceAccess::processPendingCommandQueue() |
447 | { | 439 | { |
448 | Trace() << "We have " << d->pendingCommands.size() << " pending commands"; | 440 | Trace() << "We have " << d->pendingCommands.size() << " pending commands"; |
449 | for (auto command: d->pendingCommands) { | 441 | for (auto command : d->pendingCommands) { |
450 | Trace() << "Reenquing command " << command->commandId; | 442 | Trace() << "Reenquing command " << command->commandId; |
451 | d->commandQueue << command; | 443 | d->commandQueue << command; |
452 | } | 444 | } |
@@ -471,9 +463,9 @@ void ResourceAccess::connected() | |||
471 | Commands::write(d->socket.data(), ++d->messageId, Commands::HandshakeCommand, fbb); | 463 | Commands::write(d->socket.data(), ++d->messageId, Commands::HandshakeCommand, fbb); |
472 | } | 464 | } |
473 | 465 | ||
474 | //Reenqueue pending commands, we failed to send them | 466 | // Reenqueue pending commands, we failed to send them |
475 | processPendingCommandQueue(); | 467 | processPendingCommandQueue(); |
476 | //Send queued commands | 468 | // Send queued commands |
477 | processCommandQueue(); | 469 | processCommandQueue(); |
478 | 470 | ||
479 | emit ready(true); | 471 | emit ready(true); |
@@ -510,7 +502,8 @@ void ResourceAccess::readResourceMessage() | |||
510 | d->partialMessageBuffer += d->socket->readAll(); | 502 | d->partialMessageBuffer += d->socket->readAll(); |
511 | 503 | ||
512 | // should be scheduled rather than processed all at once | 504 | // should be scheduled rather than processed all at once |
513 | while (processMessageBuffer()) {} | 505 | while (processMessageBuffer()) { |
506 | } | ||
514 | } | 507 | } |
515 | 508 | ||
516 | bool ResourceAccess::processMessageBuffer() | 509 | bool ResourceAccess::processMessageBuffer() |
@@ -521,9 +514,9 @@ bool ResourceAccess::processMessageBuffer() | |||
521 | return false; | 514 | return false; |
522 | } | 515 | } |
523 | 516 | ||
524 | //const uint messageId = *(int*)(d->partialMessageBuffer.constData()); | 517 | // const uint messageId = *(int*)(d->partialMessageBuffer.constData()); |
525 | const int commandId = *(int*)(d->partialMessageBuffer.constData() + sizeof(uint)); | 518 | const int commandId = *(int *)(d->partialMessageBuffer.constData() + sizeof(uint)); |
526 | const uint size = *(int*)(d->partialMessageBuffer.constData() + sizeof(int) + sizeof(uint)); | 519 | const uint size = *(int *)(d->partialMessageBuffer.constData() + sizeof(int) + sizeof(uint)); |
527 | 520 | ||
528 | if (size > (uint)(d->partialMessageBuffer.size() - headerSize)) { | 521 | if (size > (uint)(d->partialMessageBuffer.size() - headerSize)) { |
529 | Warning() << "command too small"; | 522 | Warning() << "command too small"; |
@@ -546,10 +539,8 @@ bool ResourceAccess::processMessageBuffer() | |||
546 | Log() << QString("Command with messageId %1 completed %2").arg(buffer->id()).arg(buffer->success() ? "sucessfully" : "unsuccessfully"); | 539 | Log() << QString("Command with messageId %1 completed %2").arg(buffer->id()).arg(buffer->success() ? "sucessfully" : "unsuccessfully"); |
547 | 540 | ||
548 | d->completeCommands << buffer->id(); | 541 | d->completeCommands << buffer->id(); |
549 | //The callbacks can result in this object getting destroyed directly, so we need to ensure we finish our work first | 542 | // The callbacks can result in this object getting destroyed directly, so we need to ensure we finish our work first |
550 | queuedInvoke([=]() { | 543 | queuedInvoke([=]() { d->callCallbacks(); }, this); |
551 | d->callCallbacks(); | ||
552 | }, this); | ||
553 | break; | 544 | break; |
554 | } | 545 | } |
555 | case Commands::NotificationCommand: { | 546 | case Commands::NotificationCommand: { |
@@ -563,21 +554,18 @@ bool ResourceAccess::processMessageBuffer() | |||
563 | Log() << "Received inspection notification."; | 554 | Log() << "Received inspection notification."; |
564 | Notification n; | 555 | Notification n; |
565 | if (buffer->identifier()) { | 556 | if (buffer->identifier()) { |
566 | //Don't use fromRawData, the buffer is gone once we invoke emit notification | 557 | // Don't use fromRawData, the buffer is gone once we invoke emit notification |
567 | n.id = BufferUtils::extractBufferCopy(buffer->identifier()); | 558 | n.id = BufferUtils::extractBufferCopy(buffer->identifier()); |
568 | } | 559 | } |
569 | if (buffer->message()) { | 560 | if (buffer->message()) { |
570 | //Don't use fromRawData, the buffer is gone once we invoke emit notification | 561 | // Don't use fromRawData, the buffer is gone once we invoke emit notification |
571 | n.message = BufferUtils::extractBufferCopy(buffer->message()); | 562 | n.message = BufferUtils::extractBufferCopy(buffer->message()); |
572 | } | 563 | } |
573 | n.type = buffer->type(); | 564 | n.type = buffer->type(); |
574 | n.code = buffer->code(); | 565 | n.code = buffer->code(); |
575 | //The callbacks can result in this object getting destroyed directly, so we need to ensure we finish our work first | 566 | // The callbacks can result in this object getting destroyed directly, so we need to ensure we finish our work first |
576 | queuedInvoke([=]() { | 567 | queuedInvoke([=]() { emit notification(n); }, this); |
577 | emit notification(n); | 568 | } break; |
578 | }, this); | ||
579 | } | ||
580 | break; | ||
581 | case Sink::Commands::NotificationType::NotificationType_Status: | 569 | case Sink::Commands::NotificationType::NotificationType_Status: |
582 | case Sink::Commands::NotificationType::NotificationType_Warning: | 570 | case Sink::Commands::NotificationType::NotificationType_Warning: |
583 | case Sink::Commands::NotificationType::NotificationType_Progress: | 571 | case Sink::Commands::NotificationType::NotificationType_Progress: |
@@ -608,7 +596,7 @@ ResourceAccessFactory &ResourceAccessFactory::instance() | |||
608 | Sink::ResourceAccess::Ptr ResourceAccessFactory::getAccess(const QByteArray &instanceIdentifier) | 596 | Sink::ResourceAccess::Ptr ResourceAccessFactory::getAccess(const QByteArray &instanceIdentifier) |
609 | { | 597 | { |
610 | if (!mCache.contains(instanceIdentifier)) { | 598 | if (!mCache.contains(instanceIdentifier)) { |
611 | //Reuse the pointer if something else kept the resourceaccess alive | 599 | // Reuse the pointer if something else kept the resourceaccess alive |
612 | if (mWeakCache.contains(instanceIdentifier)) { | 600 | if (mWeakCache.contains(instanceIdentifier)) { |
613 | auto sharedPointer = mWeakCache.value(instanceIdentifier).toStrongRef(); | 601 | auto sharedPointer = mWeakCache.value(instanceIdentifier).toStrongRef(); |
614 | if (sharedPointer) { | 602 | if (sharedPointer) { |
@@ -616,7 +604,7 @@ Sink::ResourceAccess::Ptr ResourceAccessFactory::getAccess(const QByteArray &ins | |||
616 | } | 604 | } |
617 | } | 605 | } |
618 | if (!mCache.contains(instanceIdentifier)) { | 606 | if (!mCache.contains(instanceIdentifier)) { |
619 | //Create a new instance if necessary | 607 | // Create a new instance if necessary |
620 | auto sharedPointer = Sink::ResourceAccess::Ptr::create(instanceIdentifier); | 608 | auto sharedPointer = Sink::ResourceAccess::Ptr::create(instanceIdentifier); |
621 | QObject::connect(sharedPointer.data(), &Sink::ResourceAccess::ready, sharedPointer.data(), [this, instanceIdentifier](bool ready) { | 609 | QObject::connect(sharedPointer.data(), &Sink::ResourceAccess::ready, sharedPointer.data(), [this, instanceIdentifier](bool ready) { |
622 | if (!ready) { | 610 | if (!ready) { |
@@ -629,10 +617,8 @@ Sink::ResourceAccess::Ptr ResourceAccessFactory::getAccess(const QByteArray &ins | |||
629 | } | 617 | } |
630 | if (!mTimer.contains(instanceIdentifier)) { | 618 | if (!mTimer.contains(instanceIdentifier)) { |
631 | auto timer = new QTimer; | 619 | auto timer = new QTimer; |
632 | //Drop connection after 3 seconds (which is a random value) | 620 | // Drop connection after 3 seconds (which is a random value) |
633 | QObject::connect(timer, &QTimer::timeout, timer, [this, instanceIdentifier]() { | 621 | QObject::connect(timer, &QTimer::timeout, timer, [this, instanceIdentifier]() { mCache.remove(instanceIdentifier); }); |
634 | mCache.remove(instanceIdentifier); | ||
635 | }); | ||
636 | timer->setInterval(3000); | 622 | timer->setInterval(3000); |
637 | mTimer.insert(instanceIdentifier, timer); | 623 | mTimer.insert(instanceIdentifier, timer); |
638 | } | 624 | } |
@@ -640,7 +626,6 @@ Sink::ResourceAccess::Ptr ResourceAccessFactory::getAccess(const QByteArray &ins | |||
640 | timer->start(); | 626 | timer->start(); |
641 | return mCache.value(instanceIdentifier); | 627 | return mCache.value(instanceIdentifier); |
642 | } | 628 | } |
643 | |||
644 | } | 629 | } |
645 | 630 | ||
646 | #pragma clang diagnostic push | 631 | #pragma clang diagnostic push |
diff --git a/common/resourceaccess.h b/common/resourceaccess.h index ce7e174..bd9af65 100644 --- a/common/resourceaccess.h +++ b/common/resourceaccess.h | |||
@@ -30,8 +30,7 @@ | |||
30 | #include <flatbuffers/flatbuffers.h> | 30 | #include <flatbuffers/flatbuffers.h> |
31 | #include "notification.h" | 31 | #include "notification.h" |
32 | 32 | ||
33 | namespace Sink | 33 | namespace Sink { |
34 | { | ||
35 | 34 | ||
36 | struct QueuedCommand; | 35 | struct QueuedCommand; |
37 | 36 | ||
@@ -41,17 +40,37 @@ class SINK_EXPORT ResourceAccessInterface : public QObject | |||
41 | public: | 40 | public: |
42 | typedef QSharedPointer<ResourceAccessInterface> Ptr; | 41 | typedef QSharedPointer<ResourceAccessInterface> Ptr; |
43 | 42 | ||
44 | ResourceAccessInterface() {} | 43 | ResourceAccessInterface() |
45 | virtual ~ResourceAccessInterface() {} | 44 | { |
45 | } | ||
46 | virtual ~ResourceAccessInterface() | ||
47 | { | ||
48 | } | ||
46 | virtual KAsync::Job<void> sendCommand(int commandId) = 0; | 49 | virtual KAsync::Job<void> sendCommand(int commandId) = 0; |
47 | virtual KAsync::Job<void> sendCommand(int commandId, flatbuffers::FlatBufferBuilder &fbb) = 0; | 50 | virtual KAsync::Job<void> sendCommand(int commandId, flatbuffers::FlatBufferBuilder &fbb) = 0; |
48 | virtual KAsync::Job<void> synchronizeResource(bool remoteSync, bool localSync) = 0; | 51 | virtual KAsync::Job<void> synchronizeResource(bool remoteSync, bool localSync) = 0; |
49 | 52 | ||
50 | virtual KAsync::Job<void> sendCreateCommand(const QByteArray &resourceBufferType, const QByteArray &buffer) { return KAsync::null<void>(); }; | 53 | virtual KAsync::Job<void> sendCreateCommand(const QByteArray &resourceBufferType, const QByteArray &buffer) |
51 | virtual KAsync::Job<void> sendModifyCommand(const QByteArray &uid, qint64 revision, const QByteArray &resourceBufferType, const QByteArrayList &deletedProperties, const QByteArray &buffer) { return KAsync::null<void>(); }; | 54 | { |
52 | virtual KAsync::Job<void> sendDeleteCommand(const QByteArray &uid, qint64 revision, const QByteArray &resourceBufferType) { return KAsync::null<void>(); }; | 55 | return KAsync::null<void>(); |
53 | virtual KAsync::Job<void> sendRevisionReplayedCommand(qint64 revision) {return KAsync::null<void>(); }; | 56 | }; |
54 | virtual KAsync::Job<void> sendInspectionCommand(const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expecedValue) {return KAsync::null<void>(); }; | 57 | virtual KAsync::Job<void> sendModifyCommand(const QByteArray &uid, qint64 revision, const QByteArray &resourceBufferType, const QByteArrayList &deletedProperties, const QByteArray &buffer) |
58 | { | ||
59 | return KAsync::null<void>(); | ||
60 | }; | ||
61 | virtual KAsync::Job<void> sendDeleteCommand(const QByteArray &uid, qint64 revision, const QByteArray &resourceBufferType) | ||
62 | { | ||
63 | return KAsync::null<void>(); | ||
64 | }; | ||
65 | virtual KAsync::Job<void> sendRevisionReplayedCommand(qint64 revision) | ||
66 | { | ||
67 | return KAsync::null<void>(); | ||
68 | }; | ||
69 | virtual KAsync::Job<void> | ||
70 | sendInspectionCommand(const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expecedValue) | ||
71 | { | ||
72 | return KAsync::null<void>(); | ||
73 | }; | ||
55 | 74 | ||
56 | signals: | 75 | signals: |
57 | void ready(bool isReady); | 76 | void ready(bool isReady); |
@@ -79,21 +98,23 @@ public: | |||
79 | KAsync::Job<void> sendCommand(int commandId, flatbuffers::FlatBufferBuilder &fbb) Q_DECL_OVERRIDE; | 98 | KAsync::Job<void> sendCommand(int commandId, flatbuffers::FlatBufferBuilder &fbb) Q_DECL_OVERRIDE; |
80 | KAsync::Job<void> synchronizeResource(bool remoteSync, bool localSync) Q_DECL_OVERRIDE; | 99 | KAsync::Job<void> synchronizeResource(bool remoteSync, bool localSync) Q_DECL_OVERRIDE; |
81 | KAsync::Job<void> sendCreateCommand(const QByteArray &resourceBufferType, const QByteArray &buffer) Q_DECL_OVERRIDE; | 100 | KAsync::Job<void> sendCreateCommand(const QByteArray &resourceBufferType, const QByteArray &buffer) Q_DECL_OVERRIDE; |
82 | KAsync::Job<void> sendModifyCommand(const QByteArray &uid, qint64 revision, const QByteArray &resourceBufferType, const QByteArrayList &deletedProperties, const QByteArray &buffer) Q_DECL_OVERRIDE; | 101 | KAsync::Job<void> |
102 | sendModifyCommand(const QByteArray &uid, qint64 revision, const QByteArray &resourceBufferType, const QByteArrayList &deletedProperties, const QByteArray &buffer) Q_DECL_OVERRIDE; | ||
83 | KAsync::Job<void> sendDeleteCommand(const QByteArray &uid, qint64 revision, const QByteArray &resourceBufferType) Q_DECL_OVERRIDE; | 103 | KAsync::Job<void> sendDeleteCommand(const QByteArray &uid, qint64 revision, const QByteArray &resourceBufferType) Q_DECL_OVERRIDE; |
84 | KAsync::Job<void> sendRevisionReplayedCommand(qint64 revision) Q_DECL_OVERRIDE; | 104 | KAsync::Job<void> sendRevisionReplayedCommand(qint64 revision) Q_DECL_OVERRIDE; |
85 | KAsync::Job<void> sendInspectionCommand(const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expecedValue) Q_DECL_OVERRIDE; | 105 | KAsync::Job<void> |
106 | sendInspectionCommand(const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expecedValue) Q_DECL_OVERRIDE; | ||
86 | /** | 107 | /** |
87 | * Tries to connect to server, and returns a connected socket on success. | 108 | * Tries to connect to server, and returns a connected socket on success. |
88 | */ | 109 | */ |
89 | static KAsync::Job<QSharedPointer<QLocalSocket> > connectToServer(const QByteArray &identifier); | 110 | static KAsync::Job<QSharedPointer<QLocalSocket>> connectToServer(const QByteArray &identifier); |
90 | 111 | ||
91 | public slots: | 112 | public slots: |
92 | void open() Q_DECL_OVERRIDE; | 113 | void open() Q_DECL_OVERRIDE; |
93 | void close() Q_DECL_OVERRIDE; | 114 | void close() Q_DECL_OVERRIDE; |
94 | 115 | ||
95 | private slots: | 116 | private slots: |
96 | //TODO: move these to the Private class | 117 | // TODO: move these to the Private class |
97 | void disconnected(); | 118 | void disconnected(); |
98 | void connectionError(QLocalSocket::LocalSocketError error); | 119 | void connectionError(QLocalSocket::LocalSocketError error); |
99 | void readResourceMessage(); | 120 | void readResourceMessage(); |
@@ -108,23 +129,22 @@ private: | |||
108 | void processPendingCommandQueue(); | 129 | void processPendingCommandQueue(); |
109 | 130 | ||
110 | class Private; | 131 | class Private; |
111 | Private * const d; | 132 | Private *const d; |
112 | }; | 133 | }; |
113 | 134 | ||
114 | /** | 135 | /** |
115 | * A factory for resource access instances that caches the instance for some time. | 136 | * A factory for resource access instances that caches the instance for some time. |
116 | * | 137 | * |
117 | * This avoids constantly recreating connections, and should allow a single process to have one connection per resource. | 138 | * This avoids constantly recreating connections, and should allow a single process to have one connection per resource. |
118 | */ | 139 | */ |
119 | class ResourceAccessFactory { | 140 | class ResourceAccessFactory |
141 | { | ||
120 | public: | 142 | public: |
121 | static ResourceAccessFactory &instance(); | 143 | static ResourceAccessFactory &instance(); |
122 | Sink::ResourceAccess::Ptr getAccess(const QByteArray &instanceIdentifier); | 144 | Sink::ResourceAccess::Ptr getAccess(const QByteArray &instanceIdentifier); |
123 | 145 | ||
124 | QHash<QByteArray, QWeakPointer<Sink::ResourceAccess> > mWeakCache; | 146 | QHash<QByteArray, QWeakPointer<Sink::ResourceAccess>> mWeakCache; |
125 | QHash<QByteArray, Sink::ResourceAccess::Ptr> mCache; | 147 | QHash<QByteArray, Sink::ResourceAccess::Ptr> mCache; |
126 | QHash<QByteArray, QTimer*> mTimer; | 148 | QHash<QByteArray, QTimer *> mTimer; |
127 | }; | 149 | }; |
128 | |||
129 | |||
130 | } | 150 | } |
diff --git a/common/resourceconfig.cpp b/common/resourceconfig.cpp index a34340b..b988718 100644 --- a/common/resourceconfig.cpp +++ b/common/resourceconfig.cpp | |||
@@ -101,4 +101,3 @@ QMap<QByteArray, QVariant> ResourceConfig::getConfiguration(const QByteArray &id | |||
101 | } | 101 | } |
102 | return configuration; | 102 | return configuration; |
103 | } | 103 | } |
104 | |||
diff --git a/common/resourcecontrol.cpp b/common/resourcecontrol.cpp index 20125ac..d8b0972 100644 --- a/common/resourcecontrol.cpp +++ b/common/resourcecontrol.cpp | |||
@@ -32,28 +32,31 @@ | |||
32 | #undef DEBUG_AREA | 32 | #undef DEBUG_AREA |
33 | #define DEBUG_AREA "client.resourcecontrol" | 33 | #define DEBUG_AREA "client.resourcecontrol" |
34 | 34 | ||
35 | namespace Sink | 35 | namespace Sink { |
36 | { | ||
37 | 36 | ||
38 | KAsync::Job<void> ResourceControl::shutdown(const QByteArray &identifier) | 37 | KAsync::Job<void> ResourceControl::shutdown(const QByteArray &identifier) |
39 | { | 38 | { |
40 | Trace() << "shutdown " << identifier; | 39 | Trace() << "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).then<void, QSharedPointer<QLocalSocket>>([identifier, time](QSharedPointer<QLocalSocket> socket, KAsync::Future<void> &future) { | 42 | return ResourceAccess::connectToServer(identifier) |
44 | //We can't currently reuse the socket | 43 | .then<void, QSharedPointer<QLocalSocket>>( |
45 | socket->close(); | 44 | [identifier, time](QSharedPointer<QLocalSocket> socket, KAsync::Future<void> &future) { |
46 | auto resourceAccess = ResourceAccessFactory::instance().getAccess(identifier); | 45 | // We can't currently reuse the socket |
47 | resourceAccess->open(); | 46 | socket->close(); |
48 | resourceAccess->sendCommand(Sink::Commands::ShutdownCommand).then<void>([&future, resourceAccess, time]() { | 47 | auto resourceAccess = ResourceAccessFactory::instance().getAccess(identifier); |
49 | Trace() << "Shutdown complete." << Log::TraceTime(time->elapsed()); | 48 | resourceAccess->open(); |
50 | future.setFinished(); | 49 | resourceAccess->sendCommand(Sink::Commands::ShutdownCommand) |
51 | }).exec(); | 50 | .then<void>([&future, resourceAccess, time]() { |
52 | }, | 51 | Trace() << "Shutdown complete." << Log::TraceTime(time->elapsed()); |
53 | [](int, const QString &) { | 52 | future.setFinished(); |
54 | Trace() << "Resource is already closed."; | 53 | }) |
55 | //Resource isn't started, nothing to shutdown | 54 | .exec(); |
56 | }); | 55 | }, |
56 | [](int, const QString &) { | ||
57 | Trace() << "Resource is already closed."; | ||
58 | // Resource isn't started, nothing to shutdown | ||
59 | }); | ||
57 | } | 60 | } |
58 | 61 | ||
59 | KAsync::Job<void> ResourceControl::start(const QByteArray &identifier) | 62 | KAsync::Job<void> ResourceControl::start(const QByteArray &identifier) |
@@ -63,23 +66,19 @@ KAsync::Job<void> ResourceControl::start(const QByteArray &identifier) | |||
63 | time->start(); | 66 | time->start(); |
64 | auto resourceAccess = ResourceAccessFactory::instance().getAccess(identifier); | 67 | auto resourceAccess = ResourceAccessFactory::instance().getAccess(identifier); |
65 | resourceAccess->open(); | 68 | resourceAccess->open(); |
66 | return resourceAccess->sendCommand(Sink::Commands::PingCommand).then<void>([resourceAccess, time]() { | 69 | return resourceAccess->sendCommand(Sink::Commands::PingCommand).then<void>([resourceAccess, time]() { Trace() << "Start complete." << Log::TraceTime(time->elapsed()); }); |
67 | Trace() << "Start complete." << Log::TraceTime(time->elapsed()); | ||
68 | }); | ||
69 | } | 70 | } |
70 | 71 | ||
71 | KAsync::Job<void> ResourceControl::flushMessageQueue(const QByteArrayList &resourceIdentifier) | 72 | KAsync::Job<void> ResourceControl::flushMessageQueue(const QByteArrayList &resourceIdentifier) |
72 | { | 73 | { |
73 | Trace() << "flushMessageQueue" << resourceIdentifier; | 74 | Trace() << "flushMessageQueue" << resourceIdentifier; |
74 | return KAsync::iterate(resourceIdentifier) | 75 | return KAsync::iterate(resourceIdentifier) |
75 | .template each<void, QByteArray>([](const QByteArray &resource, KAsync::Future<void> &future) { | 76 | .template each<void, QByteArray>([](const QByteArray &resource, KAsync::Future<void> &future) { |
76 | Trace() << "Flushing message queue " << resource; | 77 | Trace() << "Flushing message queue " << resource; |
77 | auto resourceAccess = ResourceAccessFactory::instance().getAccess(resource); | 78 | auto resourceAccess = ResourceAccessFactory::instance().getAccess(resource); |
78 | resourceAccess->open(); | 79 | resourceAccess->open(); |
79 | resourceAccess->synchronizeResource(false, true).then<void>([&future, resourceAccess]() { | 80 | resourceAccess->synchronizeResource(false, true).then<void>([&future, resourceAccess]() { future.setFinished(); }).exec(); |
80 | future.setFinished(); | 81 | }); |
81 | }).exec(); | ||
82 | }); | ||
83 | } | 82 | } |
84 | 83 | ||
85 | KAsync::Job<void> ResourceControl::flushReplayQueue(const QByteArrayList &resourceIdentifier) | 84 | KAsync::Job<void> ResourceControl::flushReplayQueue(const QByteArrayList &resourceIdentifier) |
@@ -114,7 +113,7 @@ KAsync::Job<void> ResourceControl::inspect(const Inspection &inspectionCommand) | |||
114 | }); | 113 | }); |
115 | } | 114 | } |
116 | 115 | ||
117 | #define REGISTER_TYPE(T) template KAsync::Job<void> ResourceControl::inspect<T>(const Inspection &); \ | 116 | #define REGISTER_TYPE(T) template KAsync::Job<void> ResourceControl::inspect<T>(const Inspection &); |
118 | 117 | ||
119 | REGISTER_TYPE(ApplicationDomain::Event); | 118 | REGISTER_TYPE(ApplicationDomain::Event); |
120 | REGISTER_TYPE(ApplicationDomain::Mail); | 119 | REGISTER_TYPE(ApplicationDomain::Mail); |
@@ -122,4 +121,3 @@ REGISTER_TYPE(ApplicationDomain::Folder); | |||
122 | REGISTER_TYPE(ApplicationDomain::SinkResource); | 121 | REGISTER_TYPE(ApplicationDomain::SinkResource); |
123 | 122 | ||
124 | } // namespace Sink | 123 | } // namespace Sink |
125 | |||
diff --git a/common/resourcecontrol.h b/common/resourcecontrol.h index 5bfa67f..d483153 100644 --- a/common/resourcecontrol.h +++ b/common/resourcecontrol.h | |||
@@ -40,7 +40,7 @@ KAsync::Job<void> SINK_EXPORT shutdown(const QByteArray &resourceIdentifier); | |||
40 | 40 | ||
41 | /** | 41 | /** |
42 | * Start resource. | 42 | * Start resource. |
43 | * | 43 | * |
44 | * The resource is ready for operation once this command completes. | 44 | * The resource is ready for operation once this command completes. |
45 | * This command is only necessary if a resource was shutdown previously, | 45 | * This command is only necessary if a resource was shutdown previously, |
46 | * otherwise the resource process will automatically start as necessary. | 46 | * otherwise the resource process will automatically start as necessary. |
@@ -56,7 +56,5 @@ KAsync::Job<void> SINK_EXPORT flushMessageQueue(const QByteArrayList &resourceId | |||
56 | * Flushes any pending messages that haven't been replayed to the source. | 56 | * Flushes any pending messages that haven't been replayed to the source. |
57 | */ | 57 | */ |
58 | KAsync::Job<void> SINK_EXPORT flushReplayQueue(const QByteArrayList &resourceIdentifier); | 58 | KAsync::Job<void> SINK_EXPORT flushReplayQueue(const QByteArrayList &resourceIdentifier); |
59 | |||
60 | } | ||
61 | } | 59 | } |
62 | 60 | } | |
diff --git a/common/resourcefacade.cpp b/common/resourcefacade.cpp index 414e390..9294926 100644 --- a/common/resourcefacade.cpp +++ b/common/resourcefacade.cpp | |||
@@ -24,15 +24,12 @@ | |||
24 | #include "storage.h" | 24 | #include "storage.h" |
25 | #include <QDir> | 25 | #include <QDir> |
26 | 26 | ||
27 | ResourceFacade::ResourceFacade(const QByteArray &) | 27 | ResourceFacade::ResourceFacade(const QByteArray &) : Sink::StoreFacade<Sink::ApplicationDomain::SinkResource>() |
28 | : Sink::StoreFacade<Sink::ApplicationDomain::SinkResource>() | ||
29 | { | 28 | { |
30 | |||
31 | } | 29 | } |
32 | 30 | ||
33 | ResourceFacade::~ResourceFacade() | 31 | ResourceFacade::~ResourceFacade() |
34 | { | 32 | { |
35 | |||
36 | } | 33 | } |
37 | 34 | ||
38 | KAsync::Job<void> ResourceFacade::create(const Sink::ApplicationDomain::SinkResource &resource) | 35 | KAsync::Job<void> ResourceFacade::create(const Sink::ApplicationDomain::SinkResource &resource) |
@@ -40,14 +37,14 @@ KAsync::Job<void> ResourceFacade::create(const Sink::ApplicationDomain::SinkReso | |||
40 | return KAsync::start<void>([resource, this]() { | 37 | return KAsync::start<void>([resource, this]() { |
41 | const QByteArray type = resource.getProperty("type").toByteArray(); | 38 | const QByteArray type = resource.getProperty("type").toByteArray(); |
42 | const QByteArray providedIdentifier = resource.getProperty("identifier").toByteArray(); | 39 | const QByteArray providedIdentifier = resource.getProperty("identifier").toByteArray(); |
43 | //It is currently a requirement that the resource starts with the type | 40 | // It is currently a requirement that the resource starts with the type |
44 | const QByteArray identifier = providedIdentifier.isEmpty() ? ResourceConfig::newIdentifier(type) : providedIdentifier; | 41 | const QByteArray identifier = providedIdentifier.isEmpty() ? ResourceConfig::newIdentifier(type) : providedIdentifier; |
45 | ResourceConfig::addResource(identifier, type); | 42 | ResourceConfig::addResource(identifier, type); |
46 | auto changedProperties = resource.changedProperties(); | 43 | auto changedProperties = resource.changedProperties(); |
47 | changedProperties.removeOne("identifier"); | 44 | changedProperties.removeOne("identifier"); |
48 | changedProperties.removeOne("type"); | 45 | changedProperties.removeOne("type"); |
49 | if (!changedProperties.isEmpty()) { | 46 | if (!changedProperties.isEmpty()) { |
50 | //We have some configuration values | 47 | // We have some configuration values |
51 | QMap<QByteArray, QVariant> configurationValues; | 48 | QMap<QByteArray, QVariant> configurationValues; |
52 | for (const auto &property : changedProperties) { | 49 | for (const auto &property : changedProperties) { |
53 | configurationValues.insert(property, resource.getProperty(property)); | 50 | configurationValues.insert(property, resource.getProperty(property)); |
@@ -69,7 +66,7 @@ KAsync::Job<void> ResourceFacade::modify(const Sink::ApplicationDomain::SinkReso | |||
69 | changedProperties.removeOne("identifier"); | 66 | changedProperties.removeOne("identifier"); |
70 | changedProperties.removeOne("type"); | 67 | changedProperties.removeOne("type"); |
71 | if (!changedProperties.isEmpty()) { | 68 | if (!changedProperties.isEmpty()) { |
72 | //We have some configuration values | 69 | // We have some configuration values |
73 | QMap<QByteArray, QVariant> configurationValues; | 70 | QMap<QByteArray, QVariant> configurationValues; |
74 | for (const auto &property : changedProperties) { | 71 | for (const auto &property : changedProperties) { |
75 | configurationValues.insert(property, resource.getProperty(property)); | 72 | configurationValues.insert(property, resource.getProperty(property)); |
@@ -88,7 +85,7 @@ KAsync::Job<void> ResourceFacade::remove(const Sink::ApplicationDomain::SinkReso | |||
88 | return; | 85 | return; |
89 | } | 86 | } |
90 | ResourceConfig::removeResource(identifier); | 87 | ResourceConfig::removeResource(identifier); |
91 | //TODO shutdown resource, or use the resource process with a --remove option to cleanup (so we can take advantage of the file locking) | 88 | // TODO shutdown resource, or use the resource process with a --remove option to cleanup (so we can take advantage of the file locking) |
92 | QDir dir(Sink::storageLocation()); | 89 | QDir dir(Sink::storageLocation()); |
93 | for (const auto &folder : dir.entryList(QStringList() << identifier + "*")) { | 90 | for (const auto &folder : dir.entryList(QStringList() << identifier + "*")) { |
94 | Sink::Storage(Sink::storageLocation(), folder, Sink::Storage::ReadWrite).removeFromDisk(); | 91 | Sink::Storage(Sink::storageLocation(), folder, Sink::Storage::ReadWrite).removeFromDisk(); |
@@ -96,14 +93,12 @@ KAsync::Job<void> ResourceFacade::remove(const Sink::ApplicationDomain::SinkReso | |||
96 | }); | 93 | }); |
97 | } | 94 | } |
98 | 95 | ||
99 | QPair<KAsync::Job<void>, typename Sink::ResultEmitter<Sink::ApplicationDomain::SinkResource::Ptr>::Ptr > ResourceFacade::load(const Sink::Query &query) | 96 | QPair<KAsync::Job<void>, typename Sink::ResultEmitter<Sink::ApplicationDomain::SinkResource::Ptr>::Ptr> ResourceFacade::load(const Sink::Query &query) |
100 | { | 97 | { |
101 | auto resultProvider = new Sink::ResultProvider<typename Sink::ApplicationDomain::SinkResource::Ptr>(); | 98 | auto resultProvider = new Sink::ResultProvider<typename Sink::ApplicationDomain::SinkResource::Ptr>(); |
102 | auto emitter = resultProvider->emitter(); | 99 | auto emitter = resultProvider->emitter(); |
103 | resultProvider->setFetcher([](const QSharedPointer<Sink::ApplicationDomain::SinkResource> &) {}); | 100 | resultProvider->setFetcher([](const QSharedPointer<Sink::ApplicationDomain::SinkResource> &) {}); |
104 | resultProvider->onDone([resultProvider]() { | 101 | resultProvider->onDone([resultProvider]() { delete resultProvider; }); |
105 | delete resultProvider; | ||
106 | }); | ||
107 | auto job = KAsync::start<void>([query, resultProvider]() { | 102 | auto job = KAsync::start<void>([query, resultProvider]() { |
108 | const auto configuredResources = ResourceConfig::getResources(); | 103 | const auto configuredResources = ResourceConfig::getResources(); |
109 | for (const auto &res : configuredResources.keys()) { | 104 | for (const auto &res : configuredResources.keys()) { |
@@ -114,10 +109,9 @@ QPair<KAsync::Job<void>, typename Sink::ResultEmitter<Sink::ApplicationDomain::S | |||
114 | resultProvider->add(resource); | 109 | resultProvider->add(resource); |
115 | } | 110 | } |
116 | } | 111 | } |
117 | //TODO initialResultSetComplete should be implicit | 112 | // TODO initialResultSetComplete should be implicit |
118 | resultProvider->initialResultSetComplete(Sink::ApplicationDomain::SinkResource::Ptr()); | 113 | resultProvider->initialResultSetComplete(Sink::ApplicationDomain::SinkResource::Ptr()); |
119 | resultProvider->complete(); | 114 | resultProvider->complete(); |
120 | }); | 115 | }); |
121 | return qMakePair(job, emitter); | 116 | return qMakePair(job, emitter); |
122 | } | 117 | } |
123 | |||
diff --git a/common/resourcefacade.h b/common/resourcefacade.h index 5ddaa79..3de0e25 100644 --- a/common/resourcefacade.h +++ b/common/resourcefacade.h | |||
@@ -26,8 +26,8 @@ | |||
26 | #include "common/domain/applicationdomaintype.h" | 26 | #include "common/domain/applicationdomaintype.h" |
27 | 27 | ||
28 | namespace Sink { | 28 | namespace Sink { |
29 | class Query; | 29 | class Query; |
30 | class Inspection; | 30 | class Inspection; |
31 | } | 31 | } |
32 | 32 | ||
33 | class ResourceFacade : public Sink::StoreFacade<Sink::ApplicationDomain::SinkResource> | 33 | class ResourceFacade : public Sink::StoreFacade<Sink::ApplicationDomain::SinkResource> |
@@ -38,6 +38,5 @@ public: | |||
38 | KAsync::Job<void> create(const Sink::ApplicationDomain::SinkResource &resource) Q_DECL_OVERRIDE; | 38 | KAsync::Job<void> create(const Sink::ApplicationDomain::SinkResource &resource) Q_DECL_OVERRIDE; |
39 | KAsync::Job<void> modify(const Sink::ApplicationDomain::SinkResource &resource) Q_DECL_OVERRIDE; | 39 | KAsync::Job<void> modify(const Sink::ApplicationDomain::SinkResource &resource) Q_DECL_OVERRIDE; |
40 | KAsync::Job<void> remove(const Sink::ApplicationDomain::SinkResource &resource) Q_DECL_OVERRIDE; | 40 | KAsync::Job<void> remove(const Sink::ApplicationDomain::SinkResource &resource) Q_DECL_OVERRIDE; |
41 | QPair<KAsync::Job<void>, typename Sink::ResultEmitter<Sink::ApplicationDomain::SinkResource::Ptr>::Ptr > load(const Sink::Query &query) Q_DECL_OVERRIDE; | 41 | QPair<KAsync::Job<void>, typename Sink::ResultEmitter<Sink::ApplicationDomain::SinkResource::Ptr>::Ptr> load(const Sink::Query &query) Q_DECL_OVERRIDE; |
42 | }; | 42 | }; |
43 | |||
diff --git a/common/resultprovider.h b/common/resultprovider.h index 2d6efbe..5561ff2 100644 --- a/common/resultprovider.h +++ b/common/resultprovider.h | |||
@@ -32,22 +32,19 @@ namespace Sink { | |||
32 | /** | 32 | /** |
33 | * Query result set | 33 | * Query result set |
34 | */ | 34 | */ |
35 | template<class T> | 35 | template <class T> |
36 | class ResultEmitter; | 36 | class ResultEmitter; |
37 | 37 | ||
38 | template<class T> | 38 | template <class T> |
39 | class ResultProviderInterface | 39 | class ResultProviderInterface |
40 | { | 40 | { |
41 | public: | 41 | public: |
42 | ResultProviderInterface() | 42 | ResultProviderInterface() : mRevision(0) |
43 | : mRevision(0) | ||
44 | { | 43 | { |
45 | |||
46 | } | 44 | } |
47 | 45 | ||
48 | virtual ~ResultProviderInterface() | 46 | virtual ~ResultProviderInterface() |
49 | { | 47 | { |
50 | |||
51 | } | 48 | } |
52 | 49 | ||
53 | virtual void add(const T &value) = 0; | 50 | virtual void add(const T &value) = 0; |
@@ -75,17 +72,18 @@ private: | |||
75 | /* | 72 | /* |
76 | * The promise side for the result emitter | 73 | * The promise side for the result emitter |
77 | */ | 74 | */ |
78 | template<class T> | 75 | template <class T> |
79 | class ResultProvider : public ResultProviderInterface<T> { | 76 | class ResultProvider : public ResultProviderInterface<T> |
77 | { | ||
80 | private: | 78 | private: |
81 | void callInMainThreadOnEmitter(void (ResultEmitter<T>::*f)()) | 79 | void callInMainThreadOnEmitter(void (ResultEmitter<T>::*f)()) |
82 | { | 80 | { |
83 | //We use the eventloop to call the addHandler directly from the main eventloop. | 81 | // We use the eventloop to call the addHandler directly from the main eventloop. |
84 | //That way the result emitter implementation doesn't have to care about threadsafety at all. | 82 | // That way the result emitter implementation doesn't have to care about threadsafety at all. |
85 | //The alternative would be to make all handlers of the emitter threadsafe. | 83 | // The alternative would be to make all handlers of the emitter threadsafe. |
86 | if (auto emitter = mResultEmitter.toStrongRef()) { | 84 | if (auto emitter = mResultEmitter.toStrongRef()) { |
87 | auto weakEmitter = mResultEmitter; | 85 | auto weakEmitter = mResultEmitter; |
88 | //We don't want to keep the emitter alive here, so we only capture a weak reference | 86 | // We don't want to keep the emitter alive here, so we only capture a weak reference |
89 | emitter->mThreadBoundary.callInMainThread([weakEmitter, f]() { | 87 | emitter->mThreadBoundary.callInMainThread([weakEmitter, f]() { |
90 | if (auto strongRef = weakEmitter.toStrongRef()) { | 88 | if (auto strongRef = weakEmitter.toStrongRef()) { |
91 | (strongRef.data()->*f)(); | 89 | (strongRef.data()->*f)(); |
@@ -96,27 +94,27 @@ private: | |||
96 | 94 | ||
97 | void callInMainThreadOnEmitter(const std::function<void()> &f) | 95 | void callInMainThreadOnEmitter(const std::function<void()> &f) |
98 | { | 96 | { |
99 | //We use the eventloop to call the addHandler directly from the main eventloop. | 97 | // We use the eventloop to call the addHandler directly from the main eventloop. |
100 | //That way the result emitter implementation doesn't have to care about threadsafety at all. | 98 | // That way the result emitter implementation doesn't have to care about threadsafety at all. |
101 | //The alternative would be to make all handlers of the emitter threadsafe. | 99 | // The alternative would be to make all handlers of the emitter threadsafe. |
102 | if (auto emitter = mResultEmitter.toStrongRef()) { | 100 | if (auto emitter = mResultEmitter.toStrongRef()) { |
103 | emitter->mThreadBoundary.callInMainThread(f); | 101 | emitter->mThreadBoundary.callInMainThread(f); |
104 | } | 102 | } |
105 | } | 103 | } |
106 | 104 | ||
107 | public: | 105 | public: |
108 | typedef QSharedPointer<ResultProvider<T> > Ptr; | 106 | typedef QSharedPointer<ResultProvider<T>> Ptr; |
109 | 107 | ||
110 | virtual ~ResultProvider() | 108 | virtual ~ResultProvider() |
111 | { | 109 | { |
112 | } | 110 | } |
113 | 111 | ||
114 | //Called from worker thread | 112 | // Called from worker thread |
115 | void add(const T &value) | 113 | void add(const T &value) |
116 | { | 114 | { |
117 | //Because I don't know how to use bind | 115 | // Because I don't know how to use bind |
118 | auto weakEmitter = mResultEmitter; | 116 | auto weakEmitter = mResultEmitter; |
119 | callInMainThreadOnEmitter([weakEmitter, value](){ | 117 | callInMainThreadOnEmitter([weakEmitter, value]() { |
120 | if (auto strongRef = weakEmitter.toStrongRef()) { | 118 | if (auto strongRef = weakEmitter.toStrongRef()) { |
121 | strongRef->addHandler(value); | 119 | strongRef->addHandler(value); |
122 | } | 120 | } |
@@ -125,9 +123,9 @@ public: | |||
125 | 123 | ||
126 | void modify(const T &value) | 124 | void modify(const T &value) |
127 | { | 125 | { |
128 | //Because I don't know how to use bind | 126 | // Because I don't know how to use bind |
129 | auto weakEmitter = mResultEmitter; | 127 | auto weakEmitter = mResultEmitter; |
130 | callInMainThreadOnEmitter([weakEmitter, value](){ | 128 | callInMainThreadOnEmitter([weakEmitter, value]() { |
131 | if (auto strongRef = weakEmitter.toStrongRef()) { | 129 | if (auto strongRef = weakEmitter.toStrongRef()) { |
132 | strongRef->modifyHandler(value); | 130 | strongRef->modifyHandler(value); |
133 | } | 131 | } |
@@ -136,9 +134,9 @@ public: | |||
136 | 134 | ||
137 | void remove(const T &value) | 135 | void remove(const T &value) |
138 | { | 136 | { |
139 | //Because I don't know how to use bind | 137 | // Because I don't know how to use bind |
140 | auto weakEmitter = mResultEmitter; | 138 | auto weakEmitter = mResultEmitter; |
141 | callInMainThreadOnEmitter([weakEmitter, value](){ | 139 | callInMainThreadOnEmitter([weakEmitter, value]() { |
142 | if (auto strongRef = weakEmitter.toStrongRef()) { | 140 | if (auto strongRef = weakEmitter.toStrongRef()) { |
143 | strongRef->removeHandler(value); | 141 | strongRef->removeHandler(value); |
144 | } | 142 | } |
@@ -147,16 +145,16 @@ public: | |||
147 | 145 | ||
148 | void initialResultSetComplete(const T &parent) | 146 | void initialResultSetComplete(const T &parent) |
149 | { | 147 | { |
150 | //Because I don't know how to use bind | 148 | // Because I don't know how to use bind |
151 | auto weakEmitter = mResultEmitter; | 149 | auto weakEmitter = mResultEmitter; |
152 | callInMainThreadOnEmitter([weakEmitter, parent](){ | 150 | callInMainThreadOnEmitter([weakEmitter, parent]() { |
153 | if (auto strongRef = weakEmitter.toStrongRef()) { | 151 | if (auto strongRef = weakEmitter.toStrongRef()) { |
154 | strongRef->initialResultSetComplete(parent); | 152 | strongRef->initialResultSetComplete(parent); |
155 | } | 153 | } |
156 | }); | 154 | }); |
157 | } | 155 | } |
158 | 156 | ||
159 | //Called from worker thread | 157 | // Called from worker thread |
160 | void complete() | 158 | void complete() |
161 | { | 159 | { |
162 | callInMainThreadOnEmitter(&ResultEmitter<T>::complete); | 160 | callInMainThreadOnEmitter(&ResultEmitter<T>::complete); |
@@ -168,11 +166,14 @@ public: | |||
168 | } | 166 | } |
169 | 167 | ||
170 | 168 | ||
171 | QSharedPointer<ResultEmitter<T> > emitter() | 169 | QSharedPointer<ResultEmitter<T>> emitter() |
172 | { | 170 | { |
173 | if (!mResultEmitter) { | 171 | if (!mResultEmitter) { |
174 | //We have to go over a separate var and return that, otherwise we'd delete the emitter immediately again | 172 | // We have to go over a separate var and return that, otherwise we'd delete the emitter immediately again |
175 | auto sharedPtr = QSharedPointer<ResultEmitter<T> >(new ResultEmitter<T>, [this](ResultEmitter<T> *emitter){ mThreadBoundary->callInMainThread([this]() {done();}); delete emitter; }); | 173 | auto sharedPtr = QSharedPointer<ResultEmitter<T>>(new ResultEmitter<T>, [this](ResultEmitter<T> *emitter) { |
174 | mThreadBoundary->callInMainThread([this]() { done(); }); | ||
175 | delete emitter; | ||
176 | }); | ||
176 | mResultEmitter = sharedPtr; | 177 | mResultEmitter = sharedPtr; |
177 | sharedPtr->setFetcher([this](const T &parent) { | 178 | sharedPtr->setFetcher([this](const T &parent) { |
178 | Q_ASSERT(mFetcher); | 179 | Q_ASSERT(mFetcher); |
@@ -192,7 +193,7 @@ public: | |||
192 | 193 | ||
193 | bool isDone() const | 194 | bool isDone() const |
194 | { | 195 | { |
195 | //The existance of the emitter currently defines wether we're done or not. | 196 | // The existance of the emitter currently defines wether we're done or not. |
196 | return mResultEmitter.toStrongRef().isNull(); | 197 | return mResultEmitter.toStrongRef().isNull(); |
197 | } | 198 | } |
198 | 199 | ||
@@ -208,12 +209,12 @@ private: | |||
208 | if (mOnDoneCallback) { | 209 | if (mOnDoneCallback) { |
209 | auto callback = mOnDoneCallback; | 210 | auto callback = mOnDoneCallback; |
210 | mOnDoneCallback = std::function<void()>(); | 211 | mOnDoneCallback = std::function<void()>(); |
211 | //This may delete this object | 212 | // This may delete this object |
212 | callback(); | 213 | callback(); |
213 | } | 214 | } |
214 | } | 215 | } |
215 | 216 | ||
216 | QWeakPointer<ResultEmitter<T> > mResultEmitter; | 217 | QWeakPointer<ResultEmitter<T>> mResultEmitter; |
217 | std::function<void()> mOnDoneCallback; | 218 | std::function<void()> mOnDoneCallback; |
218 | QSharedPointer<async::ThreadBoundary> mThreadBoundary; | 219 | QSharedPointer<async::ThreadBoundary> mThreadBoundary; |
219 | std::function<void(const T &parent)> mFetcher; | 220 | std::function<void(const T &parent)> mFetcher; |
@@ -231,32 +232,32 @@ private: | |||
231 | * * build sync interfaces that block when accessing the value | 232 | * * build sync interfaces that block when accessing the value |
232 | * | 233 | * |
233 | */ | 234 | */ |
234 | template<class DomainType> | 235 | template <class DomainType> |
235 | class ResultEmitter { | 236 | class ResultEmitter |
237 | { | ||
236 | public: | 238 | public: |
237 | typedef QSharedPointer<ResultEmitter<DomainType> > Ptr; | 239 | typedef QSharedPointer<ResultEmitter<DomainType>> Ptr; |
238 | 240 | ||
239 | virtual ~ResultEmitter() | 241 | virtual ~ResultEmitter() |
240 | { | 242 | { |
241 | |||
242 | } | 243 | } |
243 | 244 | ||
244 | void onAdded(const std::function<void(const DomainType&)> &handler) | 245 | void onAdded(const std::function<void(const DomainType &)> &handler) |
245 | { | 246 | { |
246 | addHandler = handler; | 247 | addHandler = handler; |
247 | } | 248 | } |
248 | 249 | ||
249 | void onModified(const std::function<void(const DomainType&)> &handler) | 250 | void onModified(const std::function<void(const DomainType &)> &handler) |
250 | { | 251 | { |
251 | modifyHandler = handler; | 252 | modifyHandler = handler; |
252 | } | 253 | } |
253 | 254 | ||
254 | void onRemoved(const std::function<void(const DomainType&)> &handler) | 255 | void onRemoved(const std::function<void(const DomainType &)> &handler) |
255 | { | 256 | { |
256 | removeHandler = handler; | 257 | removeHandler = handler; |
257 | } | 258 | } |
258 | 259 | ||
259 | void onInitialResultSetComplete(const std::function<void(const DomainType&)> &handler) | 260 | void onInitialResultSetComplete(const std::function<void(const DomainType &)> &handler) |
260 | { | 261 | { |
261 | initialResultSetCompleteHandler = handler; | 262 | initialResultSetCompleteHandler = handler; |
262 | } | 263 | } |
@@ -322,10 +323,10 @@ public: | |||
322 | private: | 323 | private: |
323 | friend class ResultProvider<DomainType>; | 324 | friend class ResultProvider<DomainType>; |
324 | 325 | ||
325 | std::function<void(const DomainType&)> addHandler; | 326 | std::function<void(const DomainType &)> addHandler; |
326 | std::function<void(const DomainType&)> modifyHandler; | 327 | std::function<void(const DomainType &)> modifyHandler; |
327 | std::function<void(const DomainType&)> removeHandler; | 328 | std::function<void(const DomainType &)> removeHandler; |
328 | std::function<void(const DomainType&)> initialResultSetCompleteHandler; | 329 | std::function<void(const DomainType &)> initialResultSetCompleteHandler; |
329 | std::function<void(void)> completeHandler; | 330 | std::function<void(void)> completeHandler; |
330 | std::function<void(void)> clearHandler; | 331 | std::function<void(void)> clearHandler; |
331 | 332 | ||
@@ -333,37 +334,28 @@ private: | |||
333 | async::ThreadBoundary mThreadBoundary; | 334 | async::ThreadBoundary mThreadBoundary; |
334 | }; | 335 | }; |
335 | 336 | ||
336 | template<class DomainType> | 337 | template <class DomainType> |
337 | class AggregatingResultEmitter : public ResultEmitter<DomainType> { | 338 | class AggregatingResultEmitter : public ResultEmitter<DomainType> |
339 | { | ||
338 | public: | 340 | public: |
339 | typedef QSharedPointer<AggregatingResultEmitter<DomainType> > Ptr; | 341 | typedef QSharedPointer<AggregatingResultEmitter<DomainType>> Ptr; |
340 | 342 | ||
341 | void addEmitter(const typename ResultEmitter<DomainType>::Ptr &emitter) | 343 | void addEmitter(const typename ResultEmitter<DomainType>::Ptr &emitter) |
342 | { | 344 | { |
343 | emitter->onAdded([this](const DomainType &value) { | 345 | emitter->onAdded([this](const DomainType &value) { this->add(value); }); |
344 | this->add(value); | 346 | emitter->onModified([this](const DomainType &value) { this->modify(value); }); |
345 | }); | 347 | emitter->onRemoved([this](const DomainType &value) { this->remove(value); }); |
346 | emitter->onModified([this](const DomainType &value) { | ||
347 | this->modify(value); | ||
348 | }); | ||
349 | emitter->onRemoved([this](const DomainType &value) { | ||
350 | this->remove(value); | ||
351 | }); | ||
352 | auto ptr = emitter.data(); | 348 | auto ptr = emitter.data(); |
353 | emitter->onInitialResultSetComplete([this, ptr](const DomainType &parent) { | 349 | emitter->onInitialResultSetComplete([this, ptr](const DomainType &parent) { |
354 | auto hashValue = qHash(parent); | 350 | auto hashValue = qHash(parent); |
355 | mInitialResultSetInProgress.remove(hashValue, ptr); | 351 | mInitialResultSetInProgress.remove(hashValue, ptr); |
356 | //Normally a parent is only in a single resource, except the toplevel (invalid) parent | 352 | // Normally a parent is only in a single resource, except the toplevel (invalid) parent |
357 | if (!mInitialResultSetInProgress.contains(hashValue)) { | 353 | if (!mInitialResultSetInProgress.contains(hashValue)) { |
358 | this->initialResultSetComplete(parent); | 354 | this->initialResultSetComplete(parent); |
359 | } | 355 | } |
360 | }); | 356 | }); |
361 | emitter->onComplete([this]() { | 357 | emitter->onComplete([this]() { this->complete(); }); |
362 | this->complete(); | 358 | emitter->onClear([this]() { this->clear(); }); |
363 | }); | ||
364 | emitter->onClear([this]() { | ||
365 | this->clear(); | ||
366 | }); | ||
367 | mEmitter << emitter; | 359 | mEmitter << emitter; |
368 | } | 360 | } |
369 | 361 | ||
@@ -382,10 +374,6 @@ public: | |||
382 | 374 | ||
383 | private: | 375 | private: |
384 | QList<typename ResultEmitter<DomainType>::Ptr> mEmitter; | 376 | QList<typename ResultEmitter<DomainType>::Ptr> mEmitter; |
385 | QMultiMap<qint64, ResultEmitter<DomainType>*> mInitialResultSetInProgress; | 377 | QMultiMap<qint64, ResultEmitter<DomainType> *> mInitialResultSetInProgress; |
386 | }; | 378 | }; |
387 | |||
388 | |||
389 | |||
390 | } | 379 | } |
391 | |||
diff --git a/common/resultset.cpp b/common/resultset.cpp index 6e1479a..293035b 100644 --- a/common/resultset.cpp +++ b/common/resultset.cpp | |||
@@ -20,56 +20,38 @@ | |||
20 | 20 | ||
21 | #include "common/log.h" | 21 | #include "common/log.h" |
22 | 22 | ||
23 | ResultSet::ResultSet() | 23 | ResultSet::ResultSet() : mIt(nullptr) |
24 | : mIt(nullptr) | ||
25 | { | 24 | { |
26 | |||
27 | } | 25 | } |
28 | 26 | ||
29 | ResultSet::ResultSet(const ValueGenerator &generator, const SkipValue &skip) | 27 | ResultSet::ResultSet(const ValueGenerator &generator, const SkipValue &skip) : mIt(nullptr), mValueGenerator(generator), mSkip(skip) |
30 | : mIt(nullptr), | ||
31 | mValueGenerator(generator), | ||
32 | mSkip(skip) | ||
33 | { | 28 | { |
34 | |||
35 | } | 29 | } |
36 | 30 | ||
37 | ResultSet::ResultSet(const IdGenerator &generator) | 31 | ResultSet::ResultSet(const IdGenerator &generator) : mIt(nullptr), mGenerator(generator), mSkip([this]() { next(); }) |
38 | : mIt(nullptr), | ||
39 | mGenerator(generator), | ||
40 | mSkip([this]() { | ||
41 | next(); | ||
42 | }) | ||
43 | { | 32 | { |
44 | |||
45 | } | 33 | } |
46 | 34 | ||
47 | ResultSet::ResultSet(const QVector<QByteArray> &resultSet) | 35 | ResultSet::ResultSet(const QVector<QByteArray> &resultSet) |
48 | : mResultSet(resultSet), | 36 | : mResultSet(resultSet), |
49 | mIt(mResultSet.constBegin()), | 37 | mIt(mResultSet.constBegin()), |
50 | mSkip([this]() { | 38 | mSkip([this]() { |
51 | if (mIt != mResultSet.constEnd()) { | 39 | if (mIt != mResultSet.constEnd()) { |
52 | mIt++; | 40 | mIt++; |
53 | } | 41 | } |
54 | }), | 42 | }), |
55 | mFirst(true) | 43 | mFirst(true) |
56 | { | 44 | { |
57 | |||
58 | } | 45 | } |
59 | 46 | ||
60 | ResultSet::ResultSet(const ResultSet &other) | 47 | ResultSet::ResultSet(const ResultSet &other) : mResultSet(other.mResultSet), mIt(nullptr), mFirst(true) |
61 | : mResultSet(other.mResultSet), | ||
62 | mIt(nullptr), | ||
63 | mFirst(true) | ||
64 | { | 48 | { |
65 | if (other.mValueGenerator) { | 49 | if (other.mValueGenerator) { |
66 | mValueGenerator = other.mValueGenerator; | 50 | mValueGenerator = other.mValueGenerator; |
67 | mSkip = other.mSkip; | 51 | mSkip = other.mSkip; |
68 | } else if (other.mGenerator) { | 52 | } else if (other.mGenerator) { |
69 | mGenerator = other.mGenerator; | 53 | mGenerator = other.mGenerator; |
70 | mSkip = [this]() { | 54 | mSkip = [this]() { next(); }; |
71 | next(); | ||
72 | }; | ||
73 | } else { | 55 | } else { |
74 | mResultSet = other.mResultSet; | 56 | mResultSet = other.mResultSet; |
75 | mIt = mResultSet.constBegin(); | 57 | mIt = mResultSet.constBegin(); |
@@ -96,7 +78,7 @@ bool ResultSet::next() | |||
96 | return true; | 78 | return true; |
97 | } | 79 | } |
98 | } else { | 80 | } else { |
99 | next([](const Sink::ApplicationDomain::ApplicationDomainType::Ptr &value, Sink::Operation){ return false; }); | 81 | next([](const Sink::ApplicationDomain::ApplicationDomainType::Ptr &value, Sink::Operation) { return false; }); |
100 | } | 82 | } |
101 | return false; | 83 | return false; |
102 | } | 84 | } |
diff --git a/common/resultset.h b/common/resultset.h index e513460..88f7055 100644 --- a/common/resultset.h +++ b/common/resultset.h | |||
@@ -28,34 +28,34 @@ | |||
28 | * | 28 | * |
29 | * We'll eventually want to lazy load results in next(). | 29 | * We'll eventually want to lazy load results in next(). |
30 | */ | 30 | */ |
31 | class ResultSet { | 31 | class ResultSet |
32 | public: | 32 | { |
33 | typedef std::function<bool(std::function<void(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &, Sink::Operation)>)> ValueGenerator; | 33 | public: |
34 | typedef std::function<QByteArray()> IdGenerator; | 34 | typedef std::function<bool(std::function<void(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &, Sink::Operation)>)> ValueGenerator; |
35 | typedef std::function<void()> SkipValue; | 35 | typedef std::function<QByteArray()> IdGenerator; |
36 | 36 | typedef std::function<void()> SkipValue; | |
37 | ResultSet(); | 37 | |
38 | ResultSet(const ValueGenerator &generator, const SkipValue &skip); | 38 | ResultSet(); |
39 | ResultSet(const IdGenerator &generator); | 39 | ResultSet(const ValueGenerator &generator, const SkipValue &skip); |
40 | ResultSet(const QVector<QByteArray> &resultSet); | 40 | ResultSet(const IdGenerator &generator); |
41 | ResultSet(const ResultSet &other); | 41 | ResultSet(const QVector<QByteArray> &resultSet); |
42 | 42 | ResultSet(const ResultSet &other); | |
43 | bool next(); | 43 | |
44 | bool next(std::function<bool(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &value, Sink::Operation)> callback); | 44 | bool next(); |
45 | 45 | bool next(std::function<bool(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &value, Sink::Operation)> callback); | |
46 | void skip(int number); | 46 | |
47 | 47 | void skip(int number); | |
48 | QByteArray id(); | 48 | |
49 | 49 | QByteArray id(); | |
50 | bool isEmpty(); | 50 | |
51 | 51 | bool isEmpty(); | |
52 | private: | 52 | |
53 | QVector<QByteArray> mResultSet; | 53 | private: |
54 | QVector<QByteArray>::ConstIterator mIt; | 54 | QVector<QByteArray> mResultSet; |
55 | QByteArray mCurrentValue; | 55 | QVector<QByteArray>::ConstIterator mIt; |
56 | IdGenerator mGenerator; | 56 | QByteArray mCurrentValue; |
57 | ValueGenerator mValueGenerator; | 57 | IdGenerator mGenerator; |
58 | SkipValue mSkip; | 58 | ValueGenerator mValueGenerator; |
59 | bool mFirst; | 59 | SkipValue mSkip; |
60 | bool mFirst; | ||
60 | }; | 61 | }; |
61 | |||
diff --git a/common/storage.h b/common/storage.h index 663d192..b051daa 100644 --- a/common/storage.h +++ b/common/storage.h | |||
@@ -26,14 +26,19 @@ | |||
26 | #include <functional> | 26 | #include <functional> |
27 | #include <QString> | 27 | #include <QString> |
28 | 28 | ||
29 | namespace Sink | 29 | namespace Sink { |
30 | { | ||
31 | 30 | ||
32 | class SINK_EXPORT Storage { | 31 | class SINK_EXPORT Storage |
32 | { | ||
33 | public: | 33 | public: |
34 | enum AccessMode { ReadOnly, ReadWrite }; | 34 | enum AccessMode |
35 | { | ||
36 | ReadOnly, | ||
37 | ReadWrite | ||
38 | }; | ||
35 | 39 | ||
36 | enum ErrorCodes { | 40 | enum ErrorCodes |
41 | { | ||
37 | GenericError, | 42 | GenericError, |
38 | NotOpen, | 43 | NotOpen, |
39 | ReadOnlyError, | 44 | ReadOnlyError, |
@@ -44,8 +49,9 @@ public: | |||
44 | class Error | 49 | class Error |
45 | { | 50 | { |
46 | public: | 51 | public: |
47 | Error(const QByteArray &s, int c, const QByteArray &m) | 52 | Error(const QByteArray &s, int c, const QByteArray &m) : store(s), message(m), code(c) |
48 | : store(s), message(m), code(c) {} | 53 | { |
54 | } | ||
49 | QByteArray store; | 55 | QByteArray store; |
50 | QByteArray message; | 56 | QByteArray message; |
51 | int code; | 57 | int code; |
@@ -65,13 +71,11 @@ public: | |||
65 | /** | 71 | /** |
66 | * Remove a key | 72 | * Remove a key |
67 | */ | 73 | */ |
68 | void remove(const QByteArray &key, | 74 | void remove(const QByteArray &key, const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()); |
69 | const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()); | ||
70 | /** | 75 | /** |
71 | * Remove a key-value pair | 76 | * Remove a key-value pair |
72 | */ | 77 | */ |
73 | void remove(const QByteArray &key, const QByteArray &value, | 78 | void remove(const QByteArray &key, const QByteArray &value, const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()); |
74 | const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()); | ||
75 | 79 | ||
76 | /** | 80 | /** |
77 | * Read values with a given key. | 81 | * Read values with a given key. |
@@ -82,9 +86,8 @@ public: | |||
82 | * | 86 | * |
83 | * @return The number of values retrieved. | 87 | * @return The number of values retrieved. |
84 | */ | 88 | */ |
85 | int scan(const QByteArray &key, | 89 | int scan(const QByteArray &key, const std::function<bool(const QByteArray &key, const QByteArray &value)> &resultHandler, |
86 | const std::function<bool(const QByteArray &key, const QByteArray &value)> &resultHandler, | 90 | const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>(), bool findSubstringKeys = false) const; |
87 | const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>(), bool findSubstringKeys = false) const; | ||
88 | 91 | ||
89 | /** | 92 | /** |
90 | * Finds the last value in a series matched by prefix. | 93 | * Finds the last value in a series matched by prefix. |
@@ -92,28 +95,29 @@ public: | |||
92 | * This is used to match by uid prefix and find the highest revision. | 95 | * This is used to match by uid prefix and find the highest revision. |
93 | * Note that this relies on a key scheme like $uid$revision. | 96 | * Note that this relies on a key scheme like $uid$revision. |
94 | */ | 97 | */ |
95 | void findLatest(const QByteArray &uid, | 98 | void findLatest(const QByteArray &uid, const std::function<void(const QByteArray &key, const QByteArray &value)> &resultHandler, |
96 | const std::function<void(const QByteArray &key, const QByteArray &value)> &resultHandler, | 99 | const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()) const; |
97 | const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()) const; | ||
98 | 100 | ||
99 | /** | 101 | /** |
100 | * Returns true if the database contains the substring key. | 102 | * Returns true if the database contains the substring key. |
101 | */ | 103 | */ |
102 | bool contains(const QByteArray &uid); | 104 | bool contains(const QByteArray &uid); |
103 | 105 | ||
104 | NamedDatabase(NamedDatabase&& other) : d(other.d) | 106 | NamedDatabase(NamedDatabase &&other) : d(other.d) |
105 | { | 107 | { |
106 | d = other.d; | 108 | d = other.d; |
107 | other.d = nullptr; | 109 | other.d = nullptr; |
108 | } | 110 | } |
109 | 111 | ||
110 | NamedDatabase& operator=(NamedDatabase&& other) { | 112 | NamedDatabase &operator=(NamedDatabase &&other) |
113 | { | ||
111 | d = other.d; | 114 | d = other.d; |
112 | other.d = nullptr; | 115 | other.d = nullptr; |
113 | return *this; | 116 | return *this; |
114 | } | 117 | } |
115 | 118 | ||
116 | operator bool() const { | 119 | operator bool() const |
120 | { | ||
117 | return (d != nullptr); | 121 | return (d != nullptr); |
118 | } | 122 | } |
119 | 123 | ||
@@ -121,10 +125,10 @@ public: | |||
121 | 125 | ||
122 | private: | 126 | private: |
123 | friend Transaction; | 127 | friend Transaction; |
124 | NamedDatabase(NamedDatabase& other); | 128 | NamedDatabase(NamedDatabase &other); |
125 | NamedDatabase& operator=(NamedDatabase& other); | 129 | NamedDatabase &operator=(NamedDatabase &other); |
126 | class Private; | 130 | class Private; |
127 | NamedDatabase(Private*); | 131 | NamedDatabase(Private *); |
128 | Private *d; | 132 | Private *d; |
129 | }; | 133 | }; |
130 | 134 | ||
@@ -138,37 +142,39 @@ public: | |||
138 | 142 | ||
139 | QList<QByteArray> getDatabaseNames() const; | 143 | QList<QByteArray> getDatabaseNames() const; |
140 | 144 | ||
141 | NamedDatabase openDatabase(const QByteArray &name = QByteArray("default"), const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>(), bool allowDuplicates = false) const; | 145 | NamedDatabase openDatabase(const QByteArray &name = QByteArray("default"), |
146 | const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>(), bool allowDuplicates = false) const; | ||
142 | 147 | ||
143 | Transaction(Transaction&& other) : d(other.d) | 148 | Transaction(Transaction &&other) : d(other.d) |
144 | { | 149 | { |
145 | d = other.d; | 150 | d = other.d; |
146 | other.d = nullptr; | 151 | other.d = nullptr; |
147 | } | 152 | } |
148 | Transaction& operator=(Transaction&& other) { | 153 | Transaction &operator=(Transaction &&other) |
154 | { | ||
149 | d = other.d; | 155 | d = other.d; |
150 | other.d = nullptr; | 156 | other.d = nullptr; |
151 | return *this; | 157 | return *this; |
152 | } | 158 | } |
153 | 159 | ||
154 | operator bool() const { | 160 | operator bool() const |
161 | { | ||
155 | return (d != nullptr); | 162 | return (d != nullptr); |
156 | } | 163 | } |
157 | 164 | ||
158 | private: | 165 | private: |
159 | Transaction(Transaction& other); | 166 | Transaction(Transaction &other); |
160 | Transaction& operator=(Transaction& other); | 167 | Transaction &operator=(Transaction &other); |
161 | friend Storage; | 168 | friend Storage; |
162 | class Private; | 169 | class Private; |
163 | Transaction(Private*); | 170 | Transaction(Private *); |
164 | Private *d; | 171 | Private *d; |
165 | }; | 172 | }; |
166 | 173 | ||
167 | Storage(const QString &storageRoot, const QString &name, AccessMode mode = ReadOnly); | 174 | Storage(const QString &storageRoot, const QString &name, AccessMode mode = ReadOnly); |
168 | ~Storage(); | 175 | ~Storage(); |
169 | 176 | ||
170 | Transaction createTransaction(AccessMode mode = ReadWrite, | 177 | Transaction createTransaction(AccessMode mode = ReadWrite, const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()); |
171 | const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()); | ||
172 | 178 | ||
173 | /** | 179 | /** |
174 | * Set the default error handler. | 180 | * Set the default error handler. |
@@ -178,7 +184,7 @@ public: | |||
178 | 184 | ||
179 | /** | 185 | /** |
180 | * A basic error handler that writes to std::cerr. | 186 | * A basic error handler that writes to std::cerr. |
181 | * | 187 | * |
182 | * Used if nothing else is configured. | 188 | * Used if nothing else is configured. |
183 | */ | 189 | */ |
184 | static std::function<void(const Storage::Error &error)> basicErrorHandler(); | 190 | static std::function<void(const Storage::Error &error)> basicErrorHandler(); |
@@ -188,7 +194,7 @@ public: | |||
188 | 194 | ||
189 | /** | 195 | /** |
190 | * Clears all cached environments. | 196 | * Clears all cached environments. |
191 | * | 197 | * |
192 | * This only ever has to be called if a database was removed from another process. | 198 | * This only ever has to be called if a database was removed from another process. |
193 | */ | 199 | */ |
194 | static void clearEnv(); | 200 | static void clearEnv(); |
@@ -220,8 +226,7 @@ private: | |||
220 | 226 | ||
221 | private: | 227 | private: |
222 | class Private; | 228 | class Private; |
223 | Private * const d; | 229 | Private *const d; |
224 | }; | 230 | }; |
225 | 231 | ||
226 | } // namespace Sink | 232 | } // namespace Sink |
227 | |||
diff --git a/common/storage_common.cpp b/common/storage_common.cpp index 0b842d1..2873f5f 100644 --- a/common/storage_common.cpp +++ b/common/storage_common.cpp | |||
@@ -23,8 +23,7 @@ | |||
23 | 23 | ||
24 | #include "log.h" | 24 | #include "log.h" |
25 | 25 | ||
26 | namespace Sink | 26 | namespace Sink { |
27 | { | ||
28 | 27 | ||
29 | static const char *s_internalPrefix = "__internal"; | 28 | static const char *s_internalPrefix = "__internal"; |
30 | static const int s_internalPrefixSize = strlen(s_internalPrefix); | 29 | static const int s_internalPrefixSize = strlen(s_internalPrefix); |
@@ -60,14 +59,16 @@ void Storage::setMaxRevision(Sink::Storage::Transaction &transaction, qint64 rev | |||
60 | qint64 Storage::maxRevision(const Sink::Storage::Transaction &transaction) | 59 | qint64 Storage::maxRevision(const Sink::Storage::Transaction &transaction) |
61 | { | 60 | { |
62 | qint64 r = 0; | 61 | qint64 r = 0; |
63 | transaction.openDatabase().scan("__internal_maxRevision", [&](const QByteArray &, const QByteArray &revision) -> bool { | 62 | transaction.openDatabase().scan("__internal_maxRevision", |
64 | r = revision.toLongLong(); | 63 | [&](const QByteArray &, const QByteArray &revision) -> bool { |
65 | return false; | 64 | r = revision.toLongLong(); |
66 | }, [](const Error &error){ | 65 | return false; |
67 | if (error.code != Sink::Storage::NotFound) { | 66 | }, |
68 | Warning() << "Coultn'd find the maximum revision."; | 67 | [](const Error &error) { |
69 | } | 68 | if (error.code != Sink::Storage::NotFound) { |
70 | }); | 69 | Warning() << "Coultn'd find the maximum revision."; |
70 | } | ||
71 | }); | ||
71 | return r; | 72 | return r; |
72 | } | 73 | } |
73 | 74 | ||
@@ -79,44 +80,48 @@ void Storage::setCleanedUpRevision(Sink::Storage::Transaction &transaction, qint | |||
79 | qint64 Storage::cleanedUpRevision(const Sink::Storage::Transaction &transaction) | 80 | qint64 Storage::cleanedUpRevision(const Sink::Storage::Transaction &transaction) |
80 | { | 81 | { |
81 | qint64 r = 0; | 82 | qint64 r = 0; |
82 | transaction.openDatabase().scan("__internal_cleanedUpRevision", [&](const QByteArray &, const QByteArray &revision) -> bool { | 83 | transaction.openDatabase().scan("__internal_cleanedUpRevision", |
83 | r = revision.toLongLong(); | 84 | [&](const QByteArray &, const QByteArray &revision) -> bool { |
84 | return false; | 85 | r = revision.toLongLong(); |
85 | }, [](const Error &error){ | 86 | return false; |
86 | if (error.code != Sink::Storage::NotFound) { | 87 | }, |
87 | Warning() << "Coultn'd find the maximum revision."; | 88 | [](const Error &error) { |
88 | } | 89 | if (error.code != Sink::Storage::NotFound) { |
89 | }); | 90 | Warning() << "Coultn'd find the maximum revision."; |
91 | } | ||
92 | }); | ||
90 | return r; | 93 | return r; |
91 | } | 94 | } |
92 | 95 | ||
93 | QByteArray Storage::getUidFromRevision(const Sink::Storage::Transaction &transaction, qint64 revision) | 96 | QByteArray Storage::getUidFromRevision(const Sink::Storage::Transaction &transaction, qint64 revision) |
94 | { | 97 | { |
95 | QByteArray uid; | 98 | QByteArray uid; |
96 | transaction.openDatabase("revisions").scan(QByteArray::number(revision), [&](const QByteArray &, const QByteArray &value) -> bool { | 99 | transaction.openDatabase("revisions") |
97 | uid = value; | 100 | .scan(QByteArray::number(revision), |
98 | return false; | 101 | [&](const QByteArray &, const QByteArray &value) -> bool { |
99 | }, [revision](const Error &error){ | 102 | uid = value; |
100 | Warning() << "Coultn'd find uid for revision " << revision; | 103 | return false; |
101 | }); | 104 | }, |
105 | [revision](const Error &error) { Warning() << "Coultn'd find uid for revision " << revision; }); | ||
102 | return uid; | 106 | return uid; |
103 | } | 107 | } |
104 | 108 | ||
105 | QByteArray Storage::getTypeFromRevision(const Sink::Storage::Transaction &transaction, qint64 revision) | 109 | QByteArray Storage::getTypeFromRevision(const Sink::Storage::Transaction &transaction, qint64 revision) |
106 | { | 110 | { |
107 | QByteArray type; | 111 | QByteArray type; |
108 | transaction.openDatabase("revisionType").scan(QByteArray::number(revision), [&](const QByteArray &, const QByteArray &value) -> bool { | 112 | transaction.openDatabase("revisionType") |
109 | type = value; | 113 | .scan(QByteArray::number(revision), |
110 | return false; | 114 | [&](const QByteArray &, const QByteArray &value) -> bool { |
111 | }, [revision](const Error &error){ | 115 | type = value; |
112 | Warning() << "Coultn'd find type for revision " << revision; | 116 | return false; |
113 | }); | 117 | }, |
118 | [revision](const Error &error) { Warning() << "Coultn'd find type for revision " << revision; }); | ||
114 | return type; | 119 | return type; |
115 | } | 120 | } |
116 | 121 | ||
117 | void Storage::recordRevision(Sink::Storage::Transaction &transaction, qint64 revision, const QByteArray &uid, const QByteArray &type) | 122 | void Storage::recordRevision(Sink::Storage::Transaction &transaction, qint64 revision, const QByteArray &uid, const QByteArray &type) |
118 | { | 123 | { |
119 | //TODO use integerkeys | 124 | // TODO use integerkeys |
120 | transaction.openDatabase("revisions").write(QByteArray::number(revision), uid); | 125 | transaction.openDatabase("revisions").write(QByteArray::number(revision), uid); |
121 | transaction.openDatabase("revisionType").write(QByteArray::number(revision), type); | 126 | transaction.openDatabase("revisionType").write(QByteArray::number(revision), type); |
122 | } | 127 | } |
@@ -164,11 +169,12 @@ Storage::NamedDatabase Storage::mainDatabase(const Sink::Storage::Transaction &t | |||
164 | bool Storage::NamedDatabase::contains(const QByteArray &uid) | 169 | bool Storage::NamedDatabase::contains(const QByteArray &uid) |
165 | { | 170 | { |
166 | bool found = false; | 171 | bool found = false; |
167 | scan(uid, [&found](const QByteArray &, const QByteArray &) -> bool { | 172 | scan(uid, |
168 | found = true; | 173 | [&found](const QByteArray &, const QByteArray &) -> bool { |
169 | return false; | 174 | found = true; |
170 | }, [this](const Sink::Storage::Error &error) { | 175 | return false; |
171 | }, true); | 176 | }, |
177 | [this](const Sink::Storage::Error &error) {}, true); | ||
172 | return found; | 178 | return found; |
173 | } | 179 | } |
174 | 180 | ||
diff --git a/common/storage_lmdb.cpp b/common/storage_lmdb.cpp index 2d8b187..878a5d9 100644 --- a/common/storage_lmdb.cpp +++ b/common/storage_lmdb.cpp | |||
@@ -56,17 +56,12 @@ class Storage::NamedDatabase::Private | |||
56 | { | 56 | { |
57 | public: | 57 | public: |
58 | Private(const QByteArray &_db, bool _allowDuplicates, const std::function<void(const Storage::Error &error)> &_defaultErrorHandler, const QString &_name, MDB_txn *_txn) | 58 | Private(const QByteArray &_db, bool _allowDuplicates, const std::function<void(const Storage::Error &error)> &_defaultErrorHandler, const QString &_name, MDB_txn *_txn) |
59 | : db(_db), | 59 | : db(_db), transaction(_txn), allowDuplicates(_allowDuplicates), defaultErrorHandler(_defaultErrorHandler), name(_name) |
60 | transaction(_txn), | ||
61 | allowDuplicates(_allowDuplicates), | ||
62 | defaultErrorHandler(_defaultErrorHandler), | ||
63 | name(_name) | ||
64 | { | 60 | { |
65 | } | 61 | } |
66 | 62 | ||
67 | ~Private() | 63 | ~Private() |
68 | { | 64 | { |
69 | |||
70 | } | 65 | } |
71 | 66 | ||
72 | QByteArray db; | 67 | QByteArray db; |
@@ -88,7 +83,7 @@ public: | |||
88 | if (const int rc = mdb_dbi_open(transaction, db.constData(), flags, &dbi)) { | 83 | if (const int rc = mdb_dbi_open(transaction, db.constData(), flags, &dbi)) { |
89 | dbi = 0; | 84 | dbi = 0; |
90 | transaction = 0; | 85 | transaction = 0; |
91 | //The database is not existing, ignore in read-only mode | 86 | // The database is not existing, ignore in read-only mode |
92 | if (!(readOnly && rc == MDB_NOTFOUND)) { | 87 | if (!(readOnly && rc == MDB_NOTFOUND)) { |
93 | Error error(name.toLatin1(), ErrorCodes::GenericError, "Error while opening database: " + QByteArray(mdb_strerror(rc))); | 88 | Error error(name.toLatin1(), ErrorCodes::GenericError, "Error while opening database: " + QByteArray(mdb_strerror(rc))); |
94 | errorHandler ? errorHandler(error) : defaultErrorHandler(error); | 89 | errorHandler ? errorHandler(error) : defaultErrorHandler(error); |
@@ -99,14 +94,11 @@ public: | |||
99 | } | 94 | } |
100 | }; | 95 | }; |
101 | 96 | ||
102 | Storage::NamedDatabase::NamedDatabase() | 97 | Storage::NamedDatabase::NamedDatabase() : d(nullptr) |
103 | : d(nullptr) | ||
104 | { | 98 | { |
105 | |||
106 | } | 99 | } |
107 | 100 | ||
108 | Storage::NamedDatabase::NamedDatabase(NamedDatabase::Private *prv) | 101 | Storage::NamedDatabase::NamedDatabase(NamedDatabase::Private *prv) : d(prv) |
109 | : d(prv) | ||
110 | { | 102 | { |
111 | } | 103 | } |
112 | 104 | ||
@@ -138,9 +130,9 @@ bool Storage::NamedDatabase::write(const QByteArray &sKey, const QByteArray &sVa | |||
138 | int rc; | 130 | int rc; |
139 | MDB_val key, data; | 131 | MDB_val key, data; |
140 | key.mv_size = keySize; | 132 | key.mv_size = keySize; |
141 | key.mv_data = const_cast<void*>(keyPtr); | 133 | key.mv_data = const_cast<void *>(keyPtr); |
142 | data.mv_size = valueSize; | 134 | data.mv_size = valueSize; |
143 | data.mv_data = const_cast<void*>(valuePtr); | 135 | data.mv_data = const_cast<void *>(valuePtr); |
144 | rc = mdb_put(d->transaction, d->dbi, &key, &data, 0); | 136 | rc = mdb_put(d->transaction, d->dbi, &key, &data, 0); |
145 | 137 | ||
146 | if (rc) { | 138 | if (rc) { |
@@ -151,14 +143,12 @@ bool Storage::NamedDatabase::write(const QByteArray &sKey, const QByteArray &sVa | |||
151 | return !rc; | 143 | return !rc; |
152 | } | 144 | } |
153 | 145 | ||
154 | void Storage::NamedDatabase::remove(const QByteArray &k, | 146 | void Storage::NamedDatabase::remove(const QByteArray &k, const std::function<void(const Storage::Error &error)> &errorHandler) |
155 | const std::function<void(const Storage::Error &error)> &errorHandler) | ||
156 | { | 147 | { |
157 | remove(k, QByteArray(), errorHandler); | 148 | remove(k, QByteArray(), errorHandler); |
158 | } | 149 | } |
159 | 150 | ||
160 | void Storage::NamedDatabase::remove(const QByteArray &k, const QByteArray &value, | 151 | void Storage::NamedDatabase::remove(const QByteArray &k, const QByteArray &value, const std::function<void(const Storage::Error &error)> &errorHandler) |
161 | const std::function<void(const Storage::Error &error)> &errorHandler) | ||
162 | { | 152 | { |
163 | if (!d || !d->transaction) { | 153 | if (!d || !d->transaction) { |
164 | if (d) { | 154 | if (d) { |
@@ -171,13 +161,13 @@ void Storage::NamedDatabase::remove(const QByteArray &k, const QByteArray &value | |||
171 | int rc; | 161 | int rc; |
172 | MDB_val key; | 162 | MDB_val key; |
173 | key.mv_size = k.size(); | 163 | key.mv_size = k.size(); |
174 | key.mv_data = const_cast<void*>(static_cast<const void*>(k.data())); | 164 | key.mv_data = const_cast<void *>(static_cast<const void *>(k.data())); |
175 | if (value.isEmpty()) { | 165 | if (value.isEmpty()) { |
176 | rc = mdb_del(d->transaction, d->dbi, &key, 0); | 166 | rc = mdb_del(d->transaction, d->dbi, &key, 0); |
177 | } else { | 167 | } else { |
178 | MDB_val data; | 168 | MDB_val data; |
179 | data.mv_size = value.size(); | 169 | data.mv_size = value.size(); |
180 | data.mv_data = const_cast<void*>(static_cast<const void*>(value.data())); | 170 | data.mv_data = const_cast<void *>(static_cast<const void *>(value.data())); |
181 | rc = mdb_del(d->transaction, d->dbi, &key, &data); | 171 | rc = mdb_del(d->transaction, d->dbi, &key, &data); |
182 | } | 172 | } |
183 | 173 | ||
@@ -187,13 +177,11 @@ void Storage::NamedDatabase::remove(const QByteArray &k, const QByteArray &value | |||
187 | } | 177 | } |
188 | } | 178 | } |
189 | 179 | ||
190 | int Storage::NamedDatabase::scan(const QByteArray &k, | 180 | int Storage::NamedDatabase::scan(const QByteArray &k, const std::function<bool(const QByteArray &key, const QByteArray &value)> &resultHandler, |
191 | const std::function<bool(const QByteArray &key, const QByteArray &value)> &resultHandler, | 181 | const std::function<void(const Storage::Error &error)> &errorHandler, bool findSubstringKeys) const |
192 | const std::function<void(const Storage::Error &error)> &errorHandler, | ||
193 | bool findSubstringKeys) const | ||
194 | { | 182 | { |
195 | if (!d || !d->transaction) { | 183 | if (!d || !d->transaction) { |
196 | //Not an error. We rely on this to read nothing from non-existing databases. | 184 | // Not an error. We rely on this to read nothing from non-existing databases. |
197 | return 0; | 185 | return 0; |
198 | } | 186 | } |
199 | 187 | ||
@@ -202,7 +190,7 @@ int Storage::NamedDatabase::scan(const QByteArray &k, | |||
202 | MDB_val data; | 190 | MDB_val data; |
203 | MDB_cursor *cursor; | 191 | MDB_cursor *cursor; |
204 | 192 | ||
205 | key.mv_data = (void*)k.constData(); | 193 | key.mv_data = (void *)k.constData(); |
206 | key.mv_size = k.size(); | 194 | key.mv_size = k.size(); |
207 | 195 | ||
208 | rc = mdb_cursor_open(d->transaction, d->dbi, &cursor); | 196 | rc = mdb_cursor_open(d->transaction, d->dbi, &cursor); |
@@ -220,21 +208,21 @@ int Storage::NamedDatabase::scan(const QByteArray &k, | |||
220 | op = MDB_SET_RANGE; | 208 | op = MDB_SET_RANGE; |
221 | } | 209 | } |
222 | if ((rc = mdb_cursor_get(cursor, &key, &data, op)) == 0) { | 210 | if ((rc = mdb_cursor_get(cursor, &key, &data, op)) == 0) { |
223 | //The first lookup will find a key that is equal or greather than our key | 211 | // The first lookup will find a key that is equal or greather than our key |
224 | if (QByteArray::fromRawData((char*)key.mv_data, key.mv_size).startsWith(k)) { | 212 | if (QByteArray::fromRawData((char *)key.mv_data, key.mv_size).startsWith(k)) { |
225 | numberOfRetrievedValues++; | 213 | numberOfRetrievedValues++; |
226 | if (resultHandler(QByteArray::fromRawData((char*)key.mv_data, key.mv_size), QByteArray::fromRawData((char*)data.mv_data, data.mv_size))) { | 214 | if (resultHandler(QByteArray::fromRawData((char *)key.mv_data, key.mv_size), QByteArray::fromRawData((char *)data.mv_data, data.mv_size))) { |
227 | if (findSubstringKeys) { | 215 | if (findSubstringKeys) { |
228 | //Reset the key to what we search for | 216 | // Reset the key to what we search for |
229 | key.mv_data = (void*)k.constData(); | 217 | key.mv_data = (void *)k.constData(); |
230 | key.mv_size = k.size(); | 218 | key.mv_size = k.size(); |
231 | } | 219 | } |
232 | MDB_cursor_op nextOp = (d->allowDuplicates && !findSubstringKeys) ? MDB_NEXT_DUP : MDB_NEXT; | 220 | MDB_cursor_op nextOp = (d->allowDuplicates && !findSubstringKeys) ? MDB_NEXT_DUP : MDB_NEXT; |
233 | while ((rc = mdb_cursor_get(cursor, &key, &data, nextOp)) == 0) { | 221 | while ((rc = mdb_cursor_get(cursor, &key, &data, nextOp)) == 0) { |
234 | //Every consequent lookup simply iterates through the list | 222 | // Every consequent lookup simply iterates through the list |
235 | if (QByteArray::fromRawData((char*)key.mv_data, key.mv_size).startsWith(k)) { | 223 | if (QByteArray::fromRawData((char *)key.mv_data, key.mv_size).startsWith(k)) { |
236 | numberOfRetrievedValues++; | 224 | numberOfRetrievedValues++; |
237 | if (!resultHandler(QByteArray::fromRawData((char*)key.mv_data, key.mv_size), QByteArray::fromRawData((char*)data.mv_data, data.mv_size))) { | 225 | if (!resultHandler(QByteArray::fromRawData((char *)key.mv_data, key.mv_size), QByteArray::fromRawData((char *)data.mv_data, data.mv_size))) { |
238 | break; | 226 | break; |
239 | } | 227 | } |
240 | } | 228 | } |
@@ -243,14 +231,14 @@ int Storage::NamedDatabase::scan(const QByteArray &k, | |||
243 | } | 231 | } |
244 | } | 232 | } |
245 | 233 | ||
246 | //We never find the last value | 234 | // We never find the last value |
247 | if (rc == MDB_NOTFOUND) { | 235 | if (rc == MDB_NOTFOUND) { |
248 | rc = 0; | 236 | rc = 0; |
249 | } | 237 | } |
250 | } else { | 238 | } else { |
251 | if ((rc = mdb_cursor_get(cursor, &key, &data, MDB_SET)) == 0) { | 239 | if ((rc = mdb_cursor_get(cursor, &key, &data, MDB_SET)) == 0) { |
252 | numberOfRetrievedValues++; | 240 | numberOfRetrievedValues++; |
253 | resultHandler(QByteArray::fromRawData((char*)key.mv_data, key.mv_size), QByteArray::fromRawData((char*)data.mv_data, data.mv_size)); | 241 | resultHandler(QByteArray::fromRawData((char *)key.mv_data, key.mv_size), QByteArray::fromRawData((char *)data.mv_data, data.mv_size)); |
254 | } | 242 | } |
255 | } | 243 | } |
256 | 244 | ||
@@ -264,12 +252,11 @@ int Storage::NamedDatabase::scan(const QByteArray &k, | |||
264 | return numberOfRetrievedValues; | 252 | return numberOfRetrievedValues; |
265 | } | 253 | } |
266 | 254 | ||
267 | void Storage::NamedDatabase::findLatest(const QByteArray &k, | 255 | void Storage::NamedDatabase::findLatest(const QByteArray &k, const std::function<void(const QByteArray &key, const QByteArray &value)> &resultHandler, |
268 | const std::function<void(const QByteArray &key, const QByteArray &value)> &resultHandler, | 256 | const std::function<void(const Storage::Error &error)> &errorHandler) const |
269 | const std::function<void(const Storage::Error &error)> &errorHandler) const | ||
270 | { | 257 | { |
271 | if (!d || !d->transaction) { | 258 | if (!d || !d->transaction) { |
272 | //Not an error. We rely on this to read nothing from non-existing databases. | 259 | // Not an error. We rely on this to read nothing from non-existing databases. |
273 | return; | 260 | return; |
274 | } | 261 | } |
275 | 262 | ||
@@ -278,7 +265,7 @@ void Storage::NamedDatabase::findLatest(const QByteArray &k, | |||
278 | MDB_val data; | 265 | MDB_val data; |
279 | MDB_cursor *cursor; | 266 | MDB_cursor *cursor; |
280 | 267 | ||
281 | key.mv_data = (void*)k.constData(); | 268 | key.mv_data = (void *)k.constData(); |
282 | key.mv_size = k.size(); | 269 | key.mv_size = k.size(); |
283 | 270 | ||
284 | rc = mdb_cursor_open(d->transaction, d->dbi, &cursor); | 271 | rc = mdb_cursor_open(d->transaction, d->dbi, &cursor); |
@@ -290,10 +277,10 @@ void Storage::NamedDatabase::findLatest(const QByteArray &k, | |||
290 | 277 | ||
291 | MDB_cursor_op op = MDB_SET_RANGE; | 278 | MDB_cursor_op op = MDB_SET_RANGE; |
292 | if ((rc = mdb_cursor_get(cursor, &key, &data, op)) == 0) { | 279 | if ((rc = mdb_cursor_get(cursor, &key, &data, op)) == 0) { |
293 | //The first lookup will find a key that is equal or greather than our key | 280 | // The first lookup will find a key that is equal or greather than our key |
294 | if (QByteArray::fromRawData((char*)key.mv_data, key.mv_size).startsWith(k)) { | 281 | if (QByteArray::fromRawData((char *)key.mv_data, key.mv_size).startsWith(k)) { |
295 | bool advanced = false; | 282 | bool advanced = false; |
296 | while (QByteArray::fromRawData((char*)key.mv_data, key.mv_size).startsWith(k)) { | 283 | while (QByteArray::fromRawData((char *)key.mv_data, key.mv_size).startsWith(k)) { |
297 | advanced = true; | 284 | advanced = true; |
298 | MDB_cursor_op nextOp = MDB_NEXT; | 285 | MDB_cursor_op nextOp = MDB_NEXT; |
299 | rc = mdb_cursor_get(cursor, &key, &data, nextOp); | 286 | rc = mdb_cursor_get(cursor, &key, &data, nextOp); |
@@ -303,17 +290,17 @@ void Storage::NamedDatabase::findLatest(const QByteArray &k, | |||
303 | } | 290 | } |
304 | if (advanced) { | 291 | if (advanced) { |
305 | MDB_cursor_op prefOp = MDB_PREV; | 292 | MDB_cursor_op prefOp = MDB_PREV; |
306 | //We read past the end above, just take the last value | 293 | // We read past the end above, just take the last value |
307 | if (rc == MDB_NOTFOUND) { | 294 | if (rc == MDB_NOTFOUND) { |
308 | prefOp = MDB_LAST; | 295 | prefOp = MDB_LAST; |
309 | } | 296 | } |
310 | rc = mdb_cursor_get(cursor, &key, &data, prefOp); | 297 | rc = mdb_cursor_get(cursor, &key, &data, prefOp); |
311 | resultHandler(QByteArray::fromRawData((char*)key.mv_data, key.mv_size), QByteArray::fromRawData((char*)data.mv_data, data.mv_size)); | 298 | resultHandler(QByteArray::fromRawData((char *)key.mv_data, key.mv_size), QByteArray::fromRawData((char *)data.mv_data, data.mv_size)); |
312 | } | 299 | } |
313 | } | 300 | } |
314 | } | 301 | } |
315 | 302 | ||
316 | //We never find the last value | 303 | // We never find the last value |
317 | if (rc == MDB_NOTFOUND) { | 304 | if (rc == MDB_NOTFOUND) { |
318 | rc = 0; | 305 | rc = 0; |
319 | } | 306 | } |
@@ -350,25 +337,15 @@ qint64 Storage::NamedDatabase::getSize() | |||
350 | } | 337 | } |
351 | 338 | ||
352 | 339 | ||
353 | |||
354 | |||
355 | class Storage::Transaction::Private | 340 | class Storage::Transaction::Private |
356 | { | 341 | { |
357 | public: | 342 | public: |
358 | Private(bool _requestRead, const std::function<void(const Storage::Error &error)> &_defaultErrorHandler, const QString &_name, MDB_env *_env) | 343 | Private(bool _requestRead, const std::function<void(const Storage::Error &error)> &_defaultErrorHandler, const QString &_name, MDB_env *_env) |
359 | : env(_env), | 344 | : env(_env), requestedRead(_requestRead), defaultErrorHandler(_defaultErrorHandler), name(_name), implicitCommit(false), error(false), modificationCounter(0) |
360 | requestedRead(_requestRead), | ||
361 | defaultErrorHandler(_defaultErrorHandler), | ||
362 | name(_name), | ||
363 | implicitCommit(false), | ||
364 | error(false), | ||
365 | modificationCounter(0) | ||
366 | { | 345 | { |
367 | |||
368 | } | 346 | } |
369 | ~Private() | 347 | ~Private() |
370 | { | 348 | { |
371 | |||
372 | } | 349 | } |
373 | 350 | ||
374 | MDB_env *env; | 351 | MDB_env *env; |
@@ -391,14 +368,11 @@ public: | |||
391 | } | 368 | } |
392 | }; | 369 | }; |
393 | 370 | ||
394 | Storage::Transaction::Transaction() | 371 | Storage::Transaction::Transaction() : d(nullptr) |
395 | : d(nullptr) | ||
396 | { | 372 | { |
397 | |||
398 | } | 373 | } |
399 | 374 | ||
400 | Storage::Transaction::Transaction(Transaction::Private *prv) | 375 | Storage::Transaction::Transaction(Transaction::Private *prv) : d(prv) |
401 | : d(prv) | ||
402 | { | 376 | { |
403 | d->startTransaction(); | 377 | d->startTransaction(); |
404 | } | 378 | } |
@@ -449,7 +423,7 @@ Storage::NamedDatabase Storage::Transaction::openDatabase(const QByteArray &db, | |||
449 | if (!d) { | 423 | if (!d) { |
450 | return Storage::NamedDatabase(); | 424 | return Storage::NamedDatabase(); |
451 | } | 425 | } |
452 | //We don't now if anything changed | 426 | // We don't now if anything changed |
453 | d->implicitCommit = true; | 427 | d->implicitCommit = true; |
454 | auto p = new Storage::NamedDatabase::Private(db, allowDuplicates, d->defaultErrorHandler, d->name, d->transaction); | 428 | auto p = new Storage::NamedDatabase::Private(db, allowDuplicates, d->defaultErrorHandler, d->name, d->transaction); |
455 | if (!p->openDatabase(d->requestedRead, errorHandler)) { | 429 | if (!p->openDatabase(d->requestedRead, errorHandler)) { |
@@ -475,9 +449,9 @@ QList<QByteArray> Storage::Transaction::getDatabaseNames() const | |||
475 | 449 | ||
476 | mdb_cursor_open(d->transaction, d->dbi, &cursor); | 450 | mdb_cursor_open(d->transaction, d->dbi, &cursor); |
477 | if ((rc = mdb_cursor_get(cursor, &key, &data, MDB_FIRST)) == 0) { | 451 | if ((rc = mdb_cursor_get(cursor, &key, &data, MDB_FIRST)) == 0) { |
478 | list << QByteArray::fromRawData((char*)key.mv_data, key.mv_size); | 452 | list << QByteArray::fromRawData((char *)key.mv_data, key.mv_size); |
479 | while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { | 453 | while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { |
480 | list << QByteArray::fromRawData((char*)key.mv_data, key.mv_size); | 454 | list << QByteArray::fromRawData((char *)key.mv_data, key.mv_size); |
481 | } | 455 | } |
482 | } else { | 456 | } else { |
483 | Warning() << "Failed to get a value" << rc; | 457 | Warning() << "Failed to get a value" << rc; |
@@ -489,9 +463,6 @@ QList<QByteArray> Storage::Transaction::getDatabaseNames() const | |||
489 | } | 463 | } |
490 | 464 | ||
491 | 465 | ||
492 | |||
493 | |||
494 | |||
495 | class Storage::Private | 466 | class Storage::Private |
496 | { | 467 | { |
497 | public: | 468 | public: |
@@ -504,17 +475,13 @@ public: | |||
504 | MDB_env *env; | 475 | MDB_env *env; |
505 | AccessMode mode; | 476 | AccessMode mode; |
506 | static QMutex sMutex; | 477 | static QMutex sMutex; |
507 | static QHash<QString, MDB_env*> sEnvironments; | 478 | static QHash<QString, MDB_env *> sEnvironments; |
508 | }; | 479 | }; |
509 | 480 | ||
510 | QMutex Storage::Private::sMutex; | 481 | QMutex Storage::Private::sMutex; |
511 | QHash<QString, MDB_env*> Storage::Private::sEnvironments; | 482 | QHash<QString, MDB_env *> Storage::Private::sEnvironments; |
512 | 483 | ||
513 | Storage::Private::Private(const QString &s, const QString &n, AccessMode m) | 484 | Storage::Private::Private(const QString &s, const QString &n, AccessMode m) : storageRoot(s), name(n), env(0), mode(m) |
514 | : storageRoot(s), | ||
515 | name(n), | ||
516 | env(0), | ||
517 | mode(m) | ||
518 | { | 485 | { |
519 | const QString fullPath(storageRoot + '/' + name); | 486 | const QString fullPath(storageRoot + '/' + name); |
520 | QFileInfo dirInfo(fullPath); | 487 | QFileInfo dirInfo(fullPath); |
@@ -525,11 +492,11 @@ Storage::Private::Private(const QString &s, const QString &n, AccessMode m) | |||
525 | if (mode == ReadWrite && !dirInfo.permission(QFile::WriteOwner)) { | 492 | if (mode == ReadWrite && !dirInfo.permission(QFile::WriteOwner)) { |
526 | qCritical() << fullPath << "does not have write permissions. Aborting"; | 493 | qCritical() << fullPath << "does not have write permissions. Aborting"; |
527 | } else if (dirInfo.exists()) { | 494 | } else if (dirInfo.exists()) { |
528 | //Ensure the environment is only created once | 495 | // Ensure the environment is only created once |
529 | QMutexLocker locker(&sMutex); | 496 | QMutexLocker locker(&sMutex); |
530 | 497 | ||
531 | /* | 498 | /* |
532 | * It seems we can only ever have one environment open in the process. | 499 | * It seems we can only ever have one environment open in the process. |
533 | * Otherwise multi-threading breaks. | 500 | * Otherwise multi-threading breaks. |
534 | */ | 501 | */ |
535 | env = sEnvironments.value(fullPath); | 502 | env = sEnvironments.value(fullPath); |
@@ -549,8 +516,8 @@ Storage::Private::Private(const QString &s, const QString &n, AccessMode m) | |||
549 | mdb_env_close(env); | 516 | mdb_env_close(env); |
550 | env = 0; | 517 | env = 0; |
551 | } else { | 518 | } else { |
552 | //FIXME: dynamic resize | 519 | // FIXME: dynamic resize |
553 | const size_t dbSize = (size_t)10485760 * (size_t)8000; //1MB * 8000 | 520 | const size_t dbSize = (size_t)10485760 * (size_t)8000; // 1MB * 8000 |
554 | mdb_env_set_mapsize(env, dbSize); | 521 | mdb_env_set_mapsize(env, dbSize); |
555 | sEnvironments.insert(fullPath, env); | 522 | sEnvironments.insert(fullPath, env); |
556 | } | 523 | } |
@@ -561,7 +528,7 @@ Storage::Private::Private(const QString &s, const QString &n, AccessMode m) | |||
561 | 528 | ||
562 | Storage::Private::~Private() | 529 | Storage::Private::~Private() |
563 | { | 530 | { |
564 | //Since we can have only one environment open per process, we currently leak the environments. | 531 | // Since we can have only one environment open per process, we currently leak the environments. |
565 | // if (env) { | 532 | // if (env) { |
566 | // //mdb_dbi_close should not be necessary and is potentially dangerous (see docs) | 533 | // //mdb_dbi_close should not be necessary and is potentially dangerous (see docs) |
567 | // mdb_dbi_close(env, dbi); | 534 | // mdb_dbi_close(env, dbi); |
@@ -569,8 +536,7 @@ Storage::Private::~Private() | |||
569 | // } | 536 | // } |
570 | } | 537 | } |
571 | 538 | ||
572 | Storage::Storage(const QString &storageRoot, const QString &name, AccessMode mode) | 539 | Storage::Storage(const QString &storageRoot, const QString &name, AccessMode mode) : d(new Private(storageRoot, name, mode)) |
573 | : d(new Private(storageRoot, name, mode)) | ||
574 | { | 540 | { |
575 | } | 541 | } |
576 | 542 | ||
diff --git a/common/store.cpp b/common/store.cpp index 6847d22..68f73c8 100644 --- a/common/store.cpp +++ b/common/store.cpp | |||
@@ -38,8 +38,7 @@ | |||
38 | #undef DEBUG_AREA | 38 | #undef DEBUG_AREA |
39 | #define DEBUG_AREA "client.store" | 39 | #define DEBUG_AREA "client.store" |
40 | 40 | ||
41 | namespace Sink | 41 | namespace Sink { |
42 | { | ||
43 | 42 | ||
44 | QString Store::storageLocation() | 43 | QString Store::storageLocation() |
45 | { | 44 | { |
@@ -48,7 +47,7 @@ QString Store::storageLocation() | |||
48 | 47 | ||
49 | static QList<QByteArray> getResources(const QList<QByteArray> &resourceFilter, const QByteArray &type) | 48 | static QList<QByteArray> getResources(const QList<QByteArray> &resourceFilter, const QByteArray &type) |
50 | { | 49 | { |
51 | //Return the global resource (signified by an empty name) for types that don't eblong to a specific resource | 50 | // Return the global resource (signified by an empty name) for types that don't eblong to a specific resource |
52 | if (type == "sinkresource") { | 51 | if (type == "sinkresource") { |
53 | return QList<QByteArray>() << ""; | 52 | return QList<QByteArray>() << ""; |
54 | } | 53 | } |
@@ -56,7 +55,7 @@ static QList<QByteArray> getResources(const QList<QByteArray> &resourceFilter, c | |||
56 | const auto configuredResources = ResourceConfig::getResources(); | 55 | const auto configuredResources = ResourceConfig::getResources(); |
57 | if (resourceFilter.isEmpty()) { | 56 | if (resourceFilter.isEmpty()) { |
58 | for (const auto &res : configuredResources.keys()) { | 57 | for (const auto &res : configuredResources.keys()) { |
59 | //TODO filter by entity type | 58 | // TODO filter by entity type |
60 | resources << res; | 59 | resources << res; |
61 | } | 60 | } |
62 | } else { | 61 | } else { |
@@ -82,7 +81,7 @@ QSharedPointer<QAbstractItemModel> Store::loadModel(Query query) | |||
82 | Trace() << " Ids: " << query.ids; | 81 | Trace() << " Ids: " << query.ids; |
83 | Trace() << " IsLive: " << query.liveQuery; | 82 | Trace() << " IsLive: " << query.liveQuery; |
84 | Trace() << " Sorting: " << query.sortProperty; | 83 | Trace() << " Sorting: " << query.sortProperty; |
85 | auto model = QSharedPointer<ModelResult<DomainType, typename DomainType::Ptr> >::create(query, query.requestedProperties); | 84 | auto model = QSharedPointer<ModelResult<DomainType, typename DomainType::Ptr>>::create(query, query.requestedProperties); |
86 | 85 | ||
87 | //* Client defines lifetime of model | 86 | //* Client defines lifetime of model |
88 | //* The model lifetime defines the duration of live-queries | 87 | //* The model lifetime defines the duration of live-queries |
@@ -95,120 +94,117 @@ QSharedPointer<QAbstractItemModel> Store::loadModel(Query query) | |||
95 | auto aggregatingEmitter = AggregatingResultEmitter<typename DomainType::Ptr>::Ptr::create(); | 94 | auto aggregatingEmitter = AggregatingResultEmitter<typename DomainType::Ptr>::Ptr::create(); |
96 | model->setEmitter(aggregatingEmitter); | 95 | model->setEmitter(aggregatingEmitter); |
97 | KAsync::iterate(resources) | 96 | KAsync::iterate(resources) |
98 | .template each<void, QByteArray>([query, aggregatingEmitter](const QByteArray &resource, KAsync::Future<void> &future) { | 97 | .template each<void, QByteArray>([query, aggregatingEmitter](const QByteArray &resource, KAsync::Future<void> &future) { |
99 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resource), resource); | 98 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resource), resource); |
100 | if (facade) { | 99 | if (facade) { |
101 | Trace() << "Trying to fetch from resource " << resource; | 100 | Trace() << "Trying to fetch from resource " << resource; |
102 | auto result = facade->load(query); | 101 | auto result = facade->load(query); |
103 | aggregatingEmitter->addEmitter(result.second); | 102 | aggregatingEmitter->addEmitter(result.second); |
104 | result.first.template then<void>([&future](){future.setFinished();}).exec(); | 103 | result.first.template then<void>([&future]() { future.setFinished(); }).exec(); |
105 | } else { | 104 | } else { |
106 | Trace() << "Couldn' find a facade for " << resource; | 105 | Trace() << "Couldn' find a facade for " << resource; |
107 | //Ignore the error and carry on | 106 | // Ignore the error and carry on |
108 | future.setFinished(); | 107 | future.setFinished(); |
109 | } | 108 | } |
110 | }).exec(); | 109 | }) |
110 | .exec(); | ||
111 | model->fetchMore(QModelIndex()); | 111 | model->fetchMore(QModelIndex()); |
112 | 112 | ||
113 | return model; | 113 | return model; |
114 | } | 114 | } |
115 | 115 | ||
116 | template <class DomainType> | 116 | template <class DomainType> |
117 | static std::shared_ptr<StoreFacade<DomainType> > getFacade(const QByteArray &resourceInstanceIdentifier) | 117 | static std::shared_ptr<StoreFacade<DomainType>> getFacade(const QByteArray &resourceInstanceIdentifier) |
118 | { | 118 | { |
119 | if (auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resourceInstanceIdentifier), resourceInstanceIdentifier)) { | 119 | if (auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resourceInstanceIdentifier), resourceInstanceIdentifier)) { |
120 | return facade; | 120 | return facade; |
121 | } | 121 | } |
122 | return std::make_shared<NullFacade<DomainType> >(); | 122 | return std::make_shared<NullFacade<DomainType>>(); |
123 | } | 123 | } |
124 | 124 | ||
125 | template <class DomainType> | 125 | template <class DomainType> |
126 | KAsync::Job<void> Store::create(const DomainType &domainObject) { | 126 | KAsync::Job<void> Store::create(const DomainType &domainObject) |
127 | //Potentially move to separate thread as well | 127 | { |
128 | // Potentially move to separate thread as well | ||
128 | auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier()); | 129 | auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier()); |
129 | return facade->create(domainObject).template then<void>([facade](){}, [](int errorCode, const QString &error) { | 130 | return facade->create(domainObject).template then<void>([facade]() {}, [](int errorCode, const QString &error) { Warning() << "Failed to create"; }); |
130 | Warning() << "Failed to create"; | ||
131 | }); | ||
132 | } | 131 | } |
133 | 132 | ||
134 | template <class DomainType> | 133 | template <class DomainType> |
135 | KAsync::Job<void> Store::modify(const DomainType &domainObject) | 134 | KAsync::Job<void> Store::modify(const DomainType &domainObject) |
136 | { | 135 | { |
137 | //Potentially move to separate thread as well | 136 | // Potentially move to separate thread as well |
138 | auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier()); | 137 | auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier()); |
139 | return facade->modify(domainObject).template then<void>([facade](){}, [](int errorCode, const QString &error) { | 138 | return facade->modify(domainObject).template then<void>([facade]() {}, [](int errorCode, const QString &error) { Warning() << "Failed to modify"; }); |
140 | Warning() << "Failed to modify"; | ||
141 | }); | ||
142 | } | 139 | } |
143 | 140 | ||
144 | template <class DomainType> | 141 | template <class DomainType> |
145 | KAsync::Job<void> Store::remove(const DomainType &domainObject) | 142 | KAsync::Job<void> Store::remove(const DomainType &domainObject) |
146 | { | 143 | { |
147 | //Potentially move to separate thread as well | 144 | // Potentially move to separate thread as well |
148 | auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier()); | 145 | auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier()); |
149 | return facade->remove(domainObject).template then<void>([facade](){}, [](int errorCode, const QString &error) { | 146 | return facade->remove(domainObject).template then<void>([facade]() {}, [](int errorCode, const QString &error) { Warning() << "Failed to remove"; }); |
150 | Warning() << "Failed to remove"; | ||
151 | }); | ||
152 | } | 147 | } |
153 | 148 | ||
154 | KAsync::Job<void> Store::removeDataFromDisk(const QByteArray &identifier) | 149 | KAsync::Job<void> Store::removeDataFromDisk(const QByteArray &identifier) |
155 | { | 150 | { |
156 | //All databases are going to become invalid, nuke the environments | 151 | // All databases are going to become invalid, nuke the environments |
157 | //TODO: all clients should react to a notification the resource | 152 | // TODO: all clients should react to a notification the resource |
158 | Sink::Storage::clearEnv(); | 153 | Sink::Storage::clearEnv(); |
159 | Trace() << "Remove data from disk " << identifier; | 154 | Trace() << "Remove data from disk " << identifier; |
160 | auto time = QSharedPointer<QTime>::create(); | 155 | auto time = QSharedPointer<QTime>::create(); |
161 | time->start(); | 156 | time->start(); |
162 | auto resourceAccess = ResourceAccessFactory::instance().getAccess(identifier); | 157 | auto resourceAccess = ResourceAccessFactory::instance().getAccess(identifier); |
163 | resourceAccess->open(); | 158 | resourceAccess->open(); |
164 | return resourceAccess->sendCommand(Sink::Commands::RemoveFromDiskCommand).then<void>([resourceAccess, time]() { | 159 | return resourceAccess->sendCommand(Sink::Commands::RemoveFromDiskCommand) |
165 | Trace() << "Remove from disk complete." << Log::TraceTime(time->elapsed()); | 160 | .then<void>([resourceAccess, time]() { Trace() << "Remove from disk complete." << Log::TraceTime(time->elapsed()); }); |
166 | }); | ||
167 | } | 161 | } |
168 | 162 | ||
169 | KAsync::Job<void> Store::synchronize(const Sink::Query &query) | 163 | KAsync::Job<void> Store::synchronize(const Sink::Query &query) |
170 | { | 164 | { |
171 | Trace() << "synchronize" << query.resources; | 165 | Trace() << "synchronize" << query.resources; |
172 | return KAsync::iterate(query.resources) | 166 | return KAsync::iterate(query.resources) |
173 | .template each<void, QByteArray>([query](const QByteArray &resource, KAsync::Future<void> &future) { | 167 | .template each<void, QByteArray>([query](const QByteArray &resource, KAsync::Future<void> &future) { |
174 | Trace() << "Synchronizing " << resource; | 168 | Trace() << "Synchronizing " << resource; |
175 | auto resourceAccess = ResourceAccessFactory::instance().getAccess(resource); | 169 | auto resourceAccess = ResourceAccessFactory::instance().getAccess(resource); |
176 | resourceAccess->open(); | 170 | resourceAccess->open(); |
177 | resourceAccess->synchronizeResource(true, false).then<void>([&future, resourceAccess]() { | 171 | resourceAccess->synchronizeResource(true, false).then<void>([&future, resourceAccess]() { future.setFinished(); }).exec(); |
178 | future.setFinished(); | 172 | }); |
179 | }).exec(); | ||
180 | }); | ||
181 | } | 173 | } |
182 | 174 | ||
183 | template <class DomainType> | 175 | template <class DomainType> |
184 | KAsync::Job<DomainType> Store::fetchOne(const Sink::Query &query) | 176 | KAsync::Job<DomainType> Store::fetchOne(const Sink::Query &query) |
185 | { | 177 | { |
186 | return KAsync::start<DomainType>([query](KAsync::Future<DomainType> &future) { | 178 | return KAsync::start<DomainType>([query](KAsync::Future<DomainType> &future) { |
187 | //FIXME We could do this more elegantly if composed jobs would have the correct type (In that case we'd simply return the value from then continuation, and could avoid the outer job entirely) | 179 | // FIXME We could do this more elegantly if composed jobs would have the correct type (In that case we'd simply return the value from then continuation, and could avoid the |
180 | // outer job entirely) | ||
188 | fetch<DomainType>(query, 1) | 181 | fetch<DomainType>(query, 1) |
189 | .template then<void, QList<typename DomainType::Ptr> >([&future](const QList<typename DomainType::Ptr> &list){ | 182 | .template then<void, QList<typename DomainType::Ptr>>( |
190 | future.setValue(*list.first()); | 183 | [&future](const QList<typename DomainType::Ptr> &list) { |
191 | future.setFinished(); | 184 | future.setValue(*list.first()); |
192 | }, [&future](int errorCode, const QString &errorMessage) { | 185 | future.setFinished(); |
193 | future.setError(errorCode, errorMessage); | 186 | }, |
194 | future.setFinished(); | 187 | [&future](int errorCode, const QString &errorMessage) { |
195 | }).exec(); | 188 | future.setError(errorCode, errorMessage); |
189 | future.setFinished(); | ||
190 | }) | ||
191 | .exec(); | ||
196 | }); | 192 | }); |
197 | } | 193 | } |
198 | 194 | ||
199 | template <class DomainType> | 195 | template <class DomainType> |
200 | KAsync::Job<QList<typename DomainType::Ptr> > Store::fetchAll(const Sink::Query &query) | 196 | KAsync::Job<QList<typename DomainType::Ptr>> Store::fetchAll(const Sink::Query &query) |
201 | { | 197 | { |
202 | return fetch<DomainType>(query); | 198 | return fetch<DomainType>(query); |
203 | } | 199 | } |
204 | 200 | ||
205 | template <class DomainType> | 201 | template <class DomainType> |
206 | KAsync::Job<QList<typename DomainType::Ptr> > Store::fetch(const Sink::Query &query, int minimumAmount) | 202 | KAsync::Job<QList<typename DomainType::Ptr>> Store::fetch(const Sink::Query &query, int minimumAmount) |
207 | { | 203 | { |
208 | auto model = loadModel<DomainType>(query); | 204 | auto model = loadModel<DomainType>(query); |
209 | auto list = QSharedPointer<QList<typename DomainType::Ptr> >::create(); | 205 | auto list = QSharedPointer<QList<typename DomainType::Ptr>>::create(); |
210 | auto context = QSharedPointer<QObject>::create(); | 206 | auto context = QSharedPointer<QObject>::create(); |
211 | return KAsync::start<QList<typename DomainType::Ptr> >([model, list, context, minimumAmount](KAsync::Future<QList<typename DomainType::Ptr> > &future) { | 207 | return KAsync::start<QList<typename DomainType::Ptr>>([model, list, context, minimumAmount](KAsync::Future<QList<typename DomainType::Ptr>> &future) { |
212 | if (model->rowCount() >= 1) { | 208 | if (model->rowCount() >= 1) { |
213 | for (int i = 0; i < model->rowCount(); i++) { | 209 | for (int i = 0; i < model->rowCount(); i++) { |
214 | list->append(model->index(i, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).template value<typename DomainType::Ptr>()); | 210 | list->append(model->index(i, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).template value<typename DomainType::Ptr>()); |
@@ -219,16 +215,17 @@ KAsync::Job<QList<typename DomainType::Ptr> > Store::fetch(const Sink::Query &qu | |||
219 | list->append(model->index(i, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).template value<typename DomainType::Ptr>()); | 215 | list->append(model->index(i, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).template value<typename DomainType::Ptr>()); |
220 | } | 216 | } |
221 | }); | 217 | }); |
222 | QObject::connect(model.data(), &QAbstractItemModel::dataChanged, context.data(), [model, &future, list, minimumAmount](const QModelIndex &, const QModelIndex &, const QVector<int> &roles) { | 218 | QObject::connect(model.data(), &QAbstractItemModel::dataChanged, context.data(), |
223 | if (roles.contains(ModelResult<DomainType, typename DomainType::Ptr>::ChildrenFetchedRole)) { | 219 | [model, &future, list, minimumAmount](const QModelIndex &, const QModelIndex &, const QVector<int> &roles) { |
224 | if (list->size() < minimumAmount) { | 220 | if (roles.contains(ModelResult<DomainType, typename DomainType::Ptr>::ChildrenFetchedRole)) { |
225 | future.setError(1, "Not enough values."); | 221 | if (list->size() < minimumAmount) { |
226 | } else { | 222 | future.setError(1, "Not enough values."); |
227 | future.setValue(*list); | 223 | } else { |
224 | future.setValue(*list); | ||
225 | } | ||
226 | future.setFinished(); | ||
228 | } | 227 | } |
229 | future.setFinished(); | 228 | }); |
230 | } | ||
231 | }); | ||
232 | } | 229 | } |
233 | if (model->data(QModelIndex(), ModelResult<DomainType, typename DomainType::Ptr>::ChildrenFetchedRole).toBool()) { | 230 | if (model->data(QModelIndex(), ModelResult<DomainType, typename DomainType::Ptr>::ChildrenFetchedRole).toBool()) { |
234 | if (list->size() < minimumAmount) { | 231 | if (list->size() < minimumAmount) { |
@@ -241,13 +238,14 @@ KAsync::Job<QList<typename DomainType::Ptr> > Store::fetch(const Sink::Query &qu | |||
241 | }); | 238 | }); |
242 | } | 239 | } |
243 | 240 | ||
244 | #define REGISTER_TYPE(T) template KAsync::Job<void> Store::remove<T>(const T &domainObject); \ | 241 | #define REGISTER_TYPE(T) \ |
245 | template KAsync::Job<void> Store::create<T>(const T &domainObject); \ | 242 | template KAsync::Job<void> Store::remove<T>(const T &domainObject); \ |
246 | template KAsync::Job<void> Store::modify<T>(const T &domainObject); \ | 243 | template KAsync::Job<void> Store::create<T>(const T &domainObject); \ |
244 | template KAsync::Job<void> Store::modify<T>(const T &domainObject); \ | ||
247 | template QSharedPointer<QAbstractItemModel> Store::loadModel<T>(Query query); \ | 245 | template QSharedPointer<QAbstractItemModel> Store::loadModel<T>(Query query); \ |
248 | template KAsync::Job<T> Store::fetchOne<T>(const Query &); \ | 246 | template KAsync::Job<T> Store::fetchOne<T>(const Query &); \ |
249 | template KAsync::Job<QList<T::Ptr> > Store::fetchAll<T>(const Query &); \ | 247 | template KAsync::Job<QList<T::Ptr>> Store::fetchAll<T>(const Query &); \ |
250 | template KAsync::Job<QList<T::Ptr> > Store::fetch<T>(const Query &, int); \ | 248 | template KAsync::Job<QList<T::Ptr>> Store::fetch<T>(const Query &, int); |
251 | 249 | ||
252 | REGISTER_TYPE(ApplicationDomain::Event); | 250 | REGISTER_TYPE(ApplicationDomain::Event); |
253 | REGISTER_TYPE(ApplicationDomain::Mail); | 251 | REGISTER_TYPE(ApplicationDomain::Mail); |
@@ -255,4 +253,3 @@ REGISTER_TYPE(ApplicationDomain::Folder); | |||
255 | REGISTER_TYPE(ApplicationDomain::SinkResource); | 253 | REGISTER_TYPE(ApplicationDomain::SinkResource); |
256 | 254 | ||
257 | } // namespace Sink | 255 | } // namespace Sink |
258 | |||
diff --git a/common/store.h b/common/store.h index 6696833..af8e971 100644 --- a/common/store.h +++ b/common/store.h | |||
@@ -35,7 +35,7 @@ namespace Sink { | |||
35 | 35 | ||
36 | /** | 36 | /** |
37 | * The unified Sink Store. | 37 | * The unified Sink Store. |
38 | * | 38 | * |
39 | * This is the primary interface for clients to interact with Sink. | 39 | * This is the primary interface for clients to interact with Sink. |
40 | * It provides a unified store where all data provided by various resources can be accessed and modified. | 40 | * It provides a unified store where all data provided by various resources can be accessed and modified. |
41 | */ | 41 | */ |
@@ -43,8 +43,9 @@ namespace Store { | |||
43 | 43 | ||
44 | QString SINK_EXPORT storageLocation(); | 44 | QString SINK_EXPORT storageLocation(); |
45 | 45 | ||
46 | enum Roles { | 46 | enum Roles |
47 | DomainObjectRole = Qt::UserRole + 1, //Must be the same as in ModelResult | 47 | { |
48 | DomainObjectRole = Qt::UserRole + 1, // Must be the same as in ModelResult | ||
48 | ChildrenFetchedRole, | 49 | ChildrenFetchedRole, |
49 | DomainObjectBaseRole | 50 | DomainObjectBaseRole |
50 | }; | 51 | }; |
@@ -63,7 +64,7 @@ KAsync::Job<void> SINK_EXPORT create(const DomainType &domainObject); | |||
63 | 64 | ||
64 | /** | 65 | /** |
65 | * Modify an entity. | 66 | * Modify an entity. |
66 | * | 67 | * |
67 | * This includes moving etc. since these are also simple settings on a property. | 68 | * This includes moving etc. since these are also simple settings on a property. |
68 | */ | 69 | */ |
69 | template <class DomainType> | 70 | template <class DomainType> |
@@ -82,7 +83,7 @@ KAsync::Job<void> SINK_EXPORT synchronize(const Sink::Query &query); | |||
82 | 83 | ||
83 | /** | 84 | /** |
84 | * Removes all resource data from disk. | 85 | * Removes all resource data from disk. |
85 | * | 86 | * |
86 | * This will not touch the configuration. All commands that that arrived at the resource before this command will be dropped. All commands that arrived later will be executed. | 87 | * This will not touch the configuration. All commands that that arrived at the resource before this command will be dropped. All commands that arrived later will be executed. |
87 | */ | 88 | */ |
88 | KAsync::Job<void> SINK_EXPORT removeDataFromDisk(const QByteArray &resourceIdentifier); | 89 | KAsync::Job<void> SINK_EXPORT removeDataFromDisk(const QByteArray &resourceIdentifier); |
@@ -91,11 +92,9 @@ template <class DomainType> | |||
91 | KAsync::Job<DomainType> SINK_EXPORT fetchOne(const Sink::Query &query); | 92 | KAsync::Job<DomainType> SINK_EXPORT fetchOne(const Sink::Query &query); |
92 | 93 | ||
93 | template <class DomainType> | 94 | template <class DomainType> |
94 | KAsync::Job<QList<typename DomainType::Ptr> > SINK_EXPORT fetchAll(const Sink::Query &query); | 95 | KAsync::Job<QList<typename DomainType::Ptr>> SINK_EXPORT fetchAll(const Sink::Query &query); |
95 | 96 | ||
96 | template <class DomainType> | 97 | template <class DomainType> |
97 | KAsync::Job<QList<typename DomainType::Ptr> > SINK_EXPORT fetch(const Sink::Query &query, int minimumAmount = 0); | 98 | KAsync::Job<QList<typename DomainType::Ptr>> SINK_EXPORT fetch(const Sink::Query &query, int minimumAmount = 0); |
98 | 99 | } | |
99 | } | ||
100 | } | 100 | } |
101 | |||
diff --git a/common/synclistresult.h b/common/synclistresult.h index 055714f..344c0ef 100644 --- a/common/synclistresult.h +++ b/common/synclistresult.h | |||
@@ -16,16 +16,13 @@ namespace async { | |||
16 | * | 16 | * |
17 | * WARNING: The nested eventloop can cause all sorts of trouble. Use only in testing code. | 17 | * WARNING: The nested eventloop can cause all sorts of trouble. Use only in testing code. |
18 | */ | 18 | */ |
19 | template<class T> | 19 | template <class T> |
20 | class SyncListResult : public QList<T> { | 20 | class SyncListResult : public QList<T> |
21 | { | ||
21 | public: | 22 | public: |
22 | SyncListResult(const QSharedPointer<Sink::ResultEmitter<T> > &emitter) | 23 | SyncListResult(const QSharedPointer<Sink::ResultEmitter<T>> &emitter) : QList<T>(), mEmitter(emitter) |
23 | :QList<T>(), | ||
24 | mEmitter(emitter) | ||
25 | { | 24 | { |
26 | emitter->onAdded([this](const T &value) { | 25 | emitter->onAdded([this](const T &value) { this->append(value); }); |
27 | this->append(value); | ||
28 | }); | ||
29 | emitter->onModified([this](const T &value) { | 26 | emitter->onModified([this](const T &value) { |
30 | for (auto it = this->begin(); it != this->end(); it++) { | 27 | for (auto it = this->begin(); it != this->end(); it++) { |
31 | if (**it == *value) { | 28 | if (**it == *value) { |
@@ -46,16 +43,12 @@ public: | |||
46 | emitter->onInitialResultSetComplete([this]() { | 43 | emitter->onInitialResultSetComplete([this]() { |
47 | if (eventLoopAborter) { | 44 | if (eventLoopAborter) { |
48 | eventLoopAborter(); | 45 | eventLoopAborter(); |
49 | //Be safe in case of a second invocation of the complete handler | 46 | // Be safe in case of a second invocation of the complete handler |
50 | eventLoopAborter = std::function<void()>(); | 47 | eventLoopAborter = std::function<void()>(); |
51 | } | 48 | } |
52 | }); | 49 | }); |
53 | emitter->onComplete([this]() { | 50 | emitter->onComplete([this]() { mEmitter.clear(); }); |
54 | mEmitter.clear(); | 51 | emitter->onClear([this]() { this->clear(); }); |
55 | }); | ||
56 | emitter->onClear([this]() { | ||
57 | this->clear(); | ||
58 | }); | ||
59 | } | 52 | } |
60 | 53 | ||
61 | void exec() | 54 | void exec() |
@@ -66,8 +59,7 @@ public: | |||
66 | } | 59 | } |
67 | 60 | ||
68 | private: | 61 | private: |
69 | QSharedPointer<Sink::ResultEmitter<T> > mEmitter; | 62 | QSharedPointer<Sink::ResultEmitter<T>> mEmitter; |
70 | std::function<void()> eventLoopAborter; | 63 | std::function<void()> eventLoopAborter; |
71 | }; | 64 | }; |
72 | |||
73 | } | 65 | } |
diff --git a/common/threadboundary.cpp b/common/threadboundary.cpp index 238f5b4..705009b 100644 --- a/common/threadboundary.cpp +++ b/common/threadboundary.cpp | |||
@@ -23,13 +23,12 @@ | |||
23 | Q_DECLARE_METATYPE(std::function<void()>); | 23 | Q_DECLARE_METATYPE(std::function<void()>); |
24 | 24 | ||
25 | namespace async { | 25 | namespace async { |
26 | ThreadBoundary::ThreadBoundary() | 26 | ThreadBoundary::ThreadBoundary() : QObject() |
27 | : QObject() | ||
28 | { | 27 | { |
29 | qRegisterMetaType<std::function<void()> >("std::function<void()>"); | 28 | qRegisterMetaType<std::function<void()>>("std::function<void()>"); |
30 | } | 29 | } |
31 | 30 | ||
32 | ThreadBoundary:: ~ThreadBoundary() | 31 | ThreadBoundary::~ThreadBoundary() |
33 | { | 32 | { |
34 | } | 33 | } |
35 | 34 | ||
@@ -47,6 +46,4 @@ void ThreadBoundary::runInMainThread(std::function<void()> f) | |||
47 | { | 46 | { |
48 | f(); | 47 | f(); |
49 | } | 48 | } |
50 | |||
51 | } | 49 | } |
52 | |||
diff --git a/common/threadboundary.h b/common/threadboundary.h index 7bea4ea..dd86b20 100644 --- a/common/threadboundary.h +++ b/common/threadboundary.h | |||
@@ -31,17 +31,17 @@ namespace async { | |||
31 | * A helper class to invoke a method in a different thread using the event loop. | 31 | * A helper class to invoke a method in a different thread using the event loop. |
32 | * The ThreadBoundary object must live in the thread where the function should be called. | 32 | * The ThreadBoundary object must live in the thread where the function should be called. |
33 | */ | 33 | */ |
34 | class SINK_EXPORT ThreadBoundary : public QObject { | 34 | class SINK_EXPORT ThreadBoundary : public QObject |
35 | { | ||
35 | Q_OBJECT | 36 | Q_OBJECT |
36 | public: | 37 | public: |
37 | ThreadBoundary(); | 38 | ThreadBoundary(); |
38 | virtual ~ThreadBoundary(); | 39 | virtual ~ThreadBoundary(); |
39 | 40 | ||
40 | //Call in worker thread | 41 | // Call in worker thread |
41 | void callInMainThread(std::function<void()> f); | 42 | void callInMainThread(std::function<void()> f); |
42 | public slots: | 43 | public slots: |
43 | //Get's called in main thread by it's eventloop | 44 | // Get's called in main thread by it's eventloop |
44 | void runInMainThread(std::function<void()> f); | 45 | void runInMainThread(std::function<void()> f); |
45 | }; | 46 | }; |
46 | |||
47 | } | 47 | } |
diff --git a/common/typeindex.cpp b/common/typeindex.cpp index ddf5df5..1321469 100644 --- a/common/typeindex.cpp +++ b/common/typeindex.cpp | |||
@@ -30,13 +30,13 @@ static QByteArray getByteArray(const QVariant &value) | |||
30 | if (value.isValid() && !value.toByteArray().isEmpty()) { | 30 | if (value.isValid() && !value.toByteArray().isEmpty()) { |
31 | return value.toByteArray(); | 31 | return value.toByteArray(); |
32 | } | 32 | } |
33 | //LMDB can't handle empty keys, so use something different | 33 | // LMDB can't handle empty keys, so use something different |
34 | return "toplevel"; | 34 | return "toplevel"; |
35 | } | 35 | } |
36 | 36 | ||
37 | static QByteArray toSortableByteArray(const QDateTime &date) | 37 | static QByteArray toSortableByteArray(const QDateTime &date) |
38 | { | 38 | { |
39 | //Sort invalid last | 39 | // Sort invalid last |
40 | if (!date.isValid()) { | 40 | if (!date.isValid()) { |
41 | return QByteArray::number(std::numeric_limits<unsigned int>::max()); | 41 | return QByteArray::number(std::numeric_limits<unsigned int>::max()); |
42 | } | 42 | } |
@@ -44,10 +44,8 @@ static QByteArray toSortableByteArray(const QDateTime &date) | |||
44 | } | 44 | } |
45 | 45 | ||
46 | 46 | ||
47 | TypeIndex::TypeIndex(const QByteArray &type) | 47 | TypeIndex::TypeIndex(const QByteArray &type) : mType(type) |
48 | : mType(type) | ||
49 | { | 48 | { |
50 | |||
51 | } | 49 | } |
52 | 50 | ||
53 | QByteArray TypeIndex::indexName(const QByteArray &property, const QByteArray &sortProperty) const | 51 | QByteArray TypeIndex::indexName(const QByteArray &property, const QByteArray &sortProperty) const |
@@ -58,7 +56,7 @@ QByteArray TypeIndex::indexName(const QByteArray &property, const QByteArray &so | |||
58 | return mType + ".index." + property + ".sort." + sortProperty; | 56 | return mType + ".index." + property + ".sort." + sortProperty; |
59 | } | 57 | } |
60 | 58 | ||
61 | template<> | 59 | template <> |
62 | void TypeIndex::addProperty<QByteArray>(const QByteArray &property) | 60 | void TypeIndex::addProperty<QByteArray>(const QByteArray &property) |
63 | { | 61 | { |
64 | auto indexer = [this, property](const QByteArray &identifier, const QVariant &value, Sink::Storage::Transaction &transaction) { | 62 | auto indexer = [this, property](const QByteArray &identifier, const QVariant &value, Sink::Storage::Transaction &transaction) { |
@@ -69,7 +67,7 @@ void TypeIndex::addProperty<QByteArray>(const QByteArray &property) | |||
69 | mProperties << property; | 67 | mProperties << property; |
70 | } | 68 | } |
71 | 69 | ||
72 | template<> | 70 | template <> |
73 | void TypeIndex::addProperty<QString>(const QByteArray &property) | 71 | void TypeIndex::addProperty<QString>(const QByteArray &property) |
74 | { | 72 | { |
75 | auto indexer = [this, property](const QByteArray &identifier, const QVariant &value, Sink::Storage::Transaction &transaction) { | 73 | auto indexer = [this, property](const QByteArray &identifier, const QVariant &value, Sink::Storage::Transaction &transaction) { |
@@ -80,7 +78,7 @@ void TypeIndex::addProperty<QString>(const QByteArray &property) | |||
80 | mProperties << property; | 78 | mProperties << property; |
81 | } | 79 | } |
82 | 80 | ||
83 | template<> | 81 | template <> |
84 | void TypeIndex::addProperty<QDateTime>(const QByteArray &property) | 82 | void TypeIndex::addProperty<QDateTime>(const QByteArray &property) |
85 | { | 83 | { |
86 | auto indexer = [this, property](const QByteArray &identifier, const QVariant &value, Sink::Storage::Transaction &transaction) { | 84 | auto indexer = [this, property](const QByteArray &identifier, const QVariant &value, Sink::Storage::Transaction &transaction) { |
@@ -94,7 +92,7 @@ void TypeIndex::addProperty<QDateTime>(const QByteArray &property) | |||
94 | mProperties << property; | 92 | mProperties << property; |
95 | } | 93 | } |
96 | 94 | ||
97 | template<> | 95 | template <> |
98 | void TypeIndex::addPropertyWithSorting<QByteArray, QDateTime>(const QByteArray &property, const QByteArray &sortProperty) | 96 | void TypeIndex::addPropertyWithSorting<QByteArray, QDateTime>(const QByteArray &property, const QByteArray &sortProperty) |
99 | { | 97 | { |
100 | auto indexer = [=](const QByteArray &identifier, const QVariant &value, const QVariant &sortValue, Sink::Storage::Transaction &transaction) { | 98 | auto indexer = [=](const QByteArray &identifier, const QVariant &value, const QVariant &sortValue, Sink::Storage::Transaction &transaction) { |
@@ -102,7 +100,7 @@ void TypeIndex::addPropertyWithSorting<QByteArray, QDateTime>(const QByteArray & | |||
102 | const auto propertyValue = getByteArray(value); | 100 | const auto propertyValue = getByteArray(value); |
103 | Index(indexName(property, sortProperty), transaction).add(propertyValue + toSortableByteArray(date), identifier); | 101 | Index(indexName(property, sortProperty), transaction).add(propertyValue + toSortableByteArray(date), identifier); |
104 | }; | 102 | }; |
105 | mSortIndexer.insert(property+sortProperty, indexer); | 103 | mSortIndexer.insert(property + sortProperty, indexer); |
106 | mSortedProperties.insert(property, sortProperty); | 104 | mSortedProperties.insert(property, sortProperty); |
107 | } | 105 | } |
108 | 106 | ||
@@ -116,7 +114,7 @@ void TypeIndex::add(const QByteArray &identifier, const Sink::ApplicationDomain: | |||
116 | for (auto it = mSortedProperties.constBegin(); it != mSortedProperties.constEnd(); it++) { | 114 | for (auto it = mSortedProperties.constBegin(); it != mSortedProperties.constEnd(); it++) { |
117 | const auto value = bufferAdaptor.getProperty(it.key()); | 115 | const auto value = bufferAdaptor.getProperty(it.key()); |
118 | const auto sortValue = bufferAdaptor.getProperty(it.value()); | 116 | const auto sortValue = bufferAdaptor.getProperty(it.value()); |
119 | auto indexer = mSortIndexer.value(it.key()+it.value()); | 117 | auto indexer = mSortIndexer.value(it.key() + it.value()); |
120 | indexer(identifier, value, sortValue, transaction); | 118 | indexer(identifier, value, sortValue, transaction); |
121 | } | 119 | } |
122 | } | 120 | } |
@@ -125,7 +123,7 @@ void TypeIndex::remove(const QByteArray &identifier, const Sink::ApplicationDoma | |||
125 | { | 123 | { |
126 | for (const auto &property : mProperties) { | 124 | for (const auto &property : mProperties) { |
127 | const auto value = bufferAdaptor.getProperty(property); | 125 | const auto value = bufferAdaptor.getProperty(property); |
128 | //FIXME don't always convert to byte array | 126 | // FIXME don't always convert to byte array |
129 | Index(indexName(property), transaction).remove(getByteArray(value), identifier); | 127 | Index(indexName(property), transaction).remove(getByteArray(value), identifier); |
130 | } | 128 | } |
131 | for (auto it = mSortedProperties.constBegin(); it != mSortedProperties.constEnd(); it++) { | 129 | for (auto it = mSortedProperties.constBegin(); it != mSortedProperties.constEnd(); it++) { |
@@ -147,12 +145,8 @@ ResultSet TypeIndex::query(const Sink::Query &query, QSet<QByteArray> &appliedFi | |||
147 | Index index(indexName(it.key(), it.value()), transaction); | 145 | Index index(indexName(it.key(), it.value()), transaction); |
148 | const auto lookupKey = getByteArray(query.propertyFilter.value(it.key())); | 146 | const auto lookupKey = getByteArray(query.propertyFilter.value(it.key())); |
149 | Trace() << "looking for " << lookupKey; | 147 | Trace() << "looking for " << lookupKey; |
150 | index.lookup(lookupKey, [&](const QByteArray &value) { | 148 | index.lookup(lookupKey, [&](const QByteArray &value) { keys << value; }, |
151 | keys << value; | 149 | [it](const Index::Error &error) { Warning() << "Error in index: " << error.message << it.key() << it.value(); }, true); |
152 | }, | ||
153 | [it](const Index::Error &error) { | ||
154 | Warning() << "Error in index: " << error.message << it.key() << it.value(); | ||
155 | }, true); | ||
156 | appliedFilters << it.key(); | 150 | appliedFilters << it.key(); |
157 | appliedSorting = it.value(); | 151 | appliedSorting = it.value(); |
158 | Trace() << "Index lookup on " << it.key() << it.value() << " found " << keys.size() << " keys."; | 152 | Trace() << "Index lookup on " << it.key() << it.value() << " found " << keys.size() << " keys."; |
@@ -163,12 +157,8 @@ ResultSet TypeIndex::query(const Sink::Query &query, QSet<QByteArray> &appliedFi | |||
163 | if (query.propertyFilter.contains(property)) { | 157 | if (query.propertyFilter.contains(property)) { |
164 | Index index(indexName(property), transaction); | 158 | Index index(indexName(property), transaction); |
165 | const auto lookupKey = getByteArray(query.propertyFilter.value(property)); | 159 | const auto lookupKey = getByteArray(query.propertyFilter.value(property)); |
166 | index.lookup(lookupKey, [&](const QByteArray &value) { | 160 | index.lookup( |
167 | keys << value; | 161 | lookupKey, [&](const QByteArray &value) { keys << value; }, [property](const Index::Error &error) { Warning() << "Error in index: " << error.message << property; }); |
168 | }, | ||
169 | [property](const Index::Error &error) { | ||
170 | Warning() << "Error in index: " << error.message << property; | ||
171 | }); | ||
172 | appliedFilters << property; | 162 | appliedFilters << property; |
173 | Trace() << "Index lookup on " << property << " found " << keys.size() << " keys."; | 163 | Trace() << "Index lookup on " << property << " found " << keys.size() << " keys."; |
174 | return ResultSet(keys); | 164 | return ResultSet(keys); |
@@ -177,4 +167,3 @@ ResultSet TypeIndex::query(const Sink::Query &query, QSet<QByteArray> &appliedFi | |||
177 | Trace() << "No matching index"; | 167 | Trace() << "No matching index"; |
178 | return ResultSet(keys); | 168 | return ResultSet(keys); |
179 | } | 169 | } |
180 | |||
diff --git a/common/typeindex.h b/common/typeindex.h index c19780c..a16179c 100644 --- a/common/typeindex.h +++ b/common/typeindex.h | |||
@@ -29,9 +29,9 @@ class TypeIndex | |||
29 | public: | 29 | public: |
30 | TypeIndex(const QByteArray &type); | 30 | TypeIndex(const QByteArray &type); |
31 | 31 | ||
32 | template<typename T> | 32 | template <typename T> |
33 | void addProperty(const QByteArray &property); | 33 | void addProperty(const QByteArray &property); |
34 | template<typename T, typename S> | 34 | template <typename T, typename S> |
35 | void addPropertyWithSorting(const QByteArray &property, const QByteArray &sortProperty); | 35 | void addPropertyWithSorting(const QByteArray &property, const QByteArray &sortProperty); |
36 | 36 | ||
37 | void add(const QByteArray &identifier, const Sink::ApplicationDomain::BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction); | 37 | void add(const QByteArray &identifier, const Sink::ApplicationDomain::BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction); |
@@ -44,7 +44,6 @@ private: | |||
44 | QByteArray mType; | 44 | QByteArray mType; |
45 | QByteArrayList mProperties; | 45 | QByteArrayList mProperties; |
46 | QMap<QByteArray, QByteArray> mSortedProperties; | 46 | QMap<QByteArray, QByteArray> mSortedProperties; |
47 | QHash<QByteArray, std::function<void(const QByteArray &identifier, const QVariant &value, Sink::Storage::Transaction &transaction)> > mIndexer; | 47 | QHash<QByteArray, std::function<void(const QByteArray &identifier, const QVariant &value, Sink::Storage::Transaction &transaction)>> mIndexer; |
48 | QHash<QByteArray, std::function<void(const QByteArray &identifier, const QVariant &value, const QVariant &sortValue, Sink::Storage::Transaction &transaction)> > mSortIndexer; | 48 | QHash<QByteArray, std::function<void(const QByteArray &identifier, const QVariant &value, const QVariant &sortValue, Sink::Storage::Transaction &transaction)>> mSortIndexer; |
49 | }; | 49 | }; |
50 | |||
diff --git a/sinksh/main.cpp b/sinksh/main.cpp index 4c00b9b..84f532d 100644 --- a/sinksh/main.cpp +++ b/sinksh/main.cpp | |||
@@ -44,10 +44,8 @@ int enterRepl() | |||
44 | } | 44 | } |
45 | 45 | ||
46 | Repl *repl = new Repl; | 46 | Repl *repl = new Repl; |
47 | QObject::connect(repl, &QStateMachine::finished, | 47 | QObject::connect(repl, &QStateMachine::finished, repl, &QObject::deleteLater); |
48 | repl, &QObject::deleteLater); | 48 | QObject::connect(repl, &QStateMachine::finished, QCoreApplication::instance(), &QCoreApplication::quit); |
49 | QObject::connect(repl, &QStateMachine::finished, | ||
50 | QCoreApplication::instance(), &QCoreApplication::quit); | ||
51 | 49 | ||
52 | State::setHasEventLoop(true); | 50 | State::setHasEventLoop(true); |
53 | int rv = QCoreApplication::instance()->exec(); | 51 | int rv = QCoreApplication::instance()->exec(); |
@@ -86,10 +84,10 @@ int main(int argc, char *argv[]) | |||
86 | { | 84 | { |
87 | const bool interactive = isatty(fileno(stdin)); | 85 | const bool interactive = isatty(fileno(stdin)); |
88 | const bool startRepl = (argc == 1) && interactive; | 86 | const bool startRepl = (argc == 1) && interactive; |
89 | //TODO: make a json command parse cause that would be awesomesauce | 87 | // TODO: make a json command parse cause that would be awesomesauce |
90 | const bool fromScript = !startRepl && QFile::exists(argv[1]); | 88 | const bool fromScript = !startRepl && QFile::exists(argv[1]); |
91 | 89 | ||
92 | //qDebug() << "state at startup is" << interactive << startRepl << fromScript; | 90 | // qDebug() << "state at startup is" << interactive << startRepl << fromScript; |
93 | 91 | ||
94 | QCoreApplication app(argc, argv); | 92 | QCoreApplication app(argc, argv); |
95 | app.setApplicationName(fromScript ? "interactive-app-shell" : argv[0]); | 93 | app.setApplicationName(fromScript ? "interactive-app-shell" : argv[0]); |
@@ -98,7 +96,7 @@ int main(int argc, char *argv[]) | |||
98 | return enterRepl(); | 96 | return enterRepl(); |
99 | } else if (fromScript) { | 97 | } else if (fromScript) { |
100 | QFile f(argv[1]); | 98 | QFile f(argv[1]); |
101 | if (!f.open(QIODevice::ReadOnly)) { | 99 | if (!f.open(QIODevice::ReadOnly)) { |
102 | return 1; | 100 | return 1; |
103 | } | 101 | } |
104 | 102 | ||
diff --git a/sinksh/sinksh_utils.cpp b/sinksh/sinksh_utils.cpp index d5b1c22..9ff966b 100644 --- a/sinksh/sinksh_utils.cpp +++ b/sinksh/sinksh_utils.cpp | |||
@@ -24,10 +24,12 @@ | |||
24 | 24 | ||
25 | #include "utils.h" | 25 | #include "utils.h" |
26 | 26 | ||
27 | namespace SinkshUtils | 27 | namespace SinkshUtils { |
28 | { | ||
29 | 28 | ||
30 | static QStringList s_types = QStringList() << "resource" << "folder" << "mail" << "event"; | 29 | static QStringList s_types = QStringList() << "resource" |
30 | << "folder" | ||
31 | << "mail" | ||
32 | << "event"; | ||
31 | 33 | ||
32 | bool isValidStoreType(const QString &type) | 34 | bool isValidStoreType(const QString &type) |
33 | { | 35 | { |
@@ -50,9 +52,9 @@ StoreBase &getStore(const QString &type) | |||
50 | return store; | 52 | return store; |
51 | } | 53 | } |
52 | 54 | ||
53 | //TODO: reinstate the warning+assert | 55 | // TODO: reinstate the warning+assert |
54 | //Q_ASSERT(false); | 56 | // Q_ASSERT(false); |
55 | //qWarning() << "Trying to get a store that doesn't exist, falling back to event"; | 57 | // qWarning() << "Trying to get a store that doesn't exist, falling back to event"; |
56 | static Store<Sink::ApplicationDomain::Event> store; | 58 | static Store<Sink::ApplicationDomain::Event> store; |
57 | return store; | 59 | return store; |
58 | } | 60 | } |
@@ -60,9 +62,12 @@ StoreBase &getStore(const QString &type) | |||
60 | QSharedPointer<QAbstractItemModel> loadModel(const QString &type, Sink::Query query) | 62 | QSharedPointer<QAbstractItemModel> loadModel(const QString &type, Sink::Query query) |
61 | { | 63 | { |
62 | if (type == "folder") { | 64 | if (type == "folder") { |
63 | query.requestedProperties << "name" << "parent"; | 65 | query.requestedProperties << "name" |
66 | << "parent"; | ||
64 | } else if (type == "mail") { | 67 | } else if (type == "mail") { |
65 | query.requestedProperties << "subject" << "folder" << "date"; | 68 | query.requestedProperties << "subject" |
69 | << "folder" | ||
70 | << "date"; | ||
66 | } else if (type == "event") { | 71 | } else if (type == "event") { |
67 | query.requestedProperties << "summary"; | 72 | query.requestedProperties << "summary"; |
68 | } else if (type == "resource") { | 73 | } else if (type == "resource") { |
@@ -80,7 +85,7 @@ QStringList resourceIds(State &state) | |||
80 | query.liveQuery = false; | 85 | query.liveQuery = false; |
81 | auto model = SinkshUtils::loadModel("resource", query); | 86 | auto model = SinkshUtils::loadModel("resource", query); |
82 | 87 | ||
83 | QObject::connect(model.data(), &QAbstractItemModel::rowsInserted, [model, &resources] (const QModelIndex &index, int start, int end) mutable { | 88 | QObject::connect(model.data(), &QAbstractItemModel::rowsInserted, [model, &resources](const QModelIndex &index, int start, int end) mutable { |
84 | for (int i = start; i <= end; i++) { | 89 | for (int i = start; i <= end; i++) { |
85 | auto object = model->data(model->index(i, 0, index), Sink::Store::DomainObjectBaseRole).value<Sink::ApplicationDomain::ApplicationDomainType::Ptr>(); | 90 | auto object = model->data(model->index(i, 0, index), Sink::Store::DomainObjectBaseRole).value<Sink::ApplicationDomain::ApplicationDomainType::Ptr>(); |
86 | resources << object->identifier(); | 91 | resources << object->identifier(); |
@@ -105,7 +110,10 @@ QStringList resourceCompleter(const QStringList &, const QString &fragment, Stat | |||
105 | 110 | ||
106 | QStringList resourceOrTypeCompleter(const QStringList &commands, const QString &fragment, State &state) | 111 | QStringList resourceOrTypeCompleter(const QStringList &commands, const QString &fragment, State &state) |
107 | { | 112 | { |
108 | static QStringList types = QStringList() << "resource" << "folder" << "mail" << "event"; | 113 | static QStringList types = QStringList() << "resource" |
114 | << "folder" | ||
115 | << "mail" | ||
116 | << "event"; | ||
109 | if (commands.count() == 1) { | 117 | if (commands.count() == 1) { |
110 | return Utils::filteredCompletions(s_types, fragment); | 118 | return Utils::filteredCompletions(s_types, fragment); |
111 | } | 119 | } |
@@ -120,7 +128,7 @@ QStringList typeCompleter(const QStringList &commands, const QString &fragment, | |||
120 | 128 | ||
121 | QMap<QString, QString> keyValueMapFromArgs(const QStringList &args) | 129 | QMap<QString, QString> keyValueMapFromArgs(const QStringList &args) |
122 | { | 130 | { |
123 | //TODO: this is not the most clever of algorithms. preserved during the port of commands | 131 | // TODO: this is not the most clever of algorithms. preserved during the port of commands |
124 | // from sink_client ... we can probably do better, however ;) | 132 | // from sink_client ... we can probably do better, however ;) |
125 | QMap<QString, QString> map; | 133 | QMap<QString, QString> map; |
126 | for (int i = 0; i + 2 <= args.size(); i += 2) { | 134 | for (int i = 0; i + 2 <= args.size(); i += 2) { |
@@ -129,6 +137,4 @@ QMap<QString, QString> keyValueMapFromArgs(const QStringList &args) | |||
129 | 137 | ||
130 | return map; | 138 | return map; |
131 | } | 139 | } |
132 | |||
133 | } | 140 | } |
134 | |||
diff --git a/sinksh/sinksh_utils.h b/sinksh/sinksh_utils.h index bc4f6e5..5f470ff 100644 --- a/sinksh/sinksh_utils.h +++ b/sinksh/sinksh_utils.h | |||
@@ -28,8 +28,7 @@ | |||
28 | 28 | ||
29 | #include "state.h" | 29 | #include "state.h" |
30 | 30 | ||
31 | namespace SinkshUtils | 31 | namespace SinkshUtils { |
32 | { | ||
33 | 32 | ||
34 | class StoreBase; | 33 | class StoreBase; |
35 | 34 | ||
@@ -45,9 +44,10 @@ QMap<QString, QString> keyValueMapFromArgs(const QStringList &args); | |||
45 | /** | 44 | /** |
46 | * A small abstraction layer to use the sink store with the type available as string. | 45 | * A small abstraction layer to use the sink store with the type available as string. |
47 | */ | 46 | */ |
48 | class StoreBase { | 47 | class StoreBase |
48 | { | ||
49 | public: | 49 | public: |
50 | virtual ~StoreBase() {}; | 50 | virtual ~StoreBase(){}; |
51 | virtual Sink::ApplicationDomain::ApplicationDomainType::Ptr getObject() = 0; | 51 | virtual Sink::ApplicationDomain::ApplicationDomainType::Ptr getObject() = 0; |
52 | virtual Sink::ApplicationDomain::ApplicationDomainType::Ptr getObject(const QByteArray &resourceInstanceIdentifier, const QByteArray &identifier = QByteArray()) = 0; | 52 | virtual Sink::ApplicationDomain::ApplicationDomainType::Ptr getObject(const QByteArray &resourceInstanceIdentifier, const QByteArray &identifier = QByteArray()) = 0; |
53 | virtual KAsync::Job<void> create(const Sink::ApplicationDomain::ApplicationDomainType &type) = 0; | 53 | virtual KAsync::Job<void> create(const Sink::ApplicationDomain::ApplicationDomainType &type) = 0; |
@@ -57,33 +57,37 @@ public: | |||
57 | }; | 57 | }; |
58 | 58 | ||
59 | template <typename T> | 59 | template <typename T> |
60 | class Store : public StoreBase { | 60 | class Store : public StoreBase |
61 | { | ||
61 | public: | 62 | public: |
62 | Sink::ApplicationDomain::ApplicationDomainType::Ptr getObject() Q_DECL_OVERRIDE { | 63 | Sink::ApplicationDomain::ApplicationDomainType::Ptr getObject() Q_DECL_OVERRIDE |
64 | { | ||
63 | return T::Ptr::create(); | 65 | return T::Ptr::create(); |
64 | } | 66 | } |
65 | 67 | ||
66 | Sink::ApplicationDomain::ApplicationDomainType::Ptr getObject(const QByteArray &resourceInstanceIdentifier, const QByteArray &identifier = QByteArray()) Q_DECL_OVERRIDE { | 68 | Sink::ApplicationDomain::ApplicationDomainType::Ptr getObject(const QByteArray &resourceInstanceIdentifier, const QByteArray &identifier = QByteArray()) Q_DECL_OVERRIDE |
69 | { | ||
67 | return T::Ptr::create(resourceInstanceIdentifier, identifier, 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); | 70 | return T::Ptr::create(resourceInstanceIdentifier, identifier, 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); |
68 | } | 71 | } |
69 | 72 | ||
70 | KAsync::Job<void> create(const Sink::ApplicationDomain::ApplicationDomainType &type) Q_DECL_OVERRIDE { | 73 | KAsync::Job<void> create(const Sink::ApplicationDomain::ApplicationDomainType &type) Q_DECL_OVERRIDE |
71 | return Sink::Store::create<T>(*static_cast<const T*>(&type)); | 74 | { |
75 | return Sink::Store::create<T>(*static_cast<const T *>(&type)); | ||
72 | } | 76 | } |
73 | 77 | ||
74 | KAsync::Job<void> modify(const Sink::ApplicationDomain::ApplicationDomainType &type) Q_DECL_OVERRIDE { | 78 | KAsync::Job<void> modify(const Sink::ApplicationDomain::ApplicationDomainType &type) Q_DECL_OVERRIDE |
75 | return Sink::Store::modify<T>(*static_cast<const T*>(&type)); | 79 | { |
80 | return Sink::Store::modify<T>(*static_cast<const T *>(&type)); | ||
76 | } | 81 | } |
77 | 82 | ||
78 | KAsync::Job<void> remove(const Sink::ApplicationDomain::ApplicationDomainType &type) Q_DECL_OVERRIDE { | 83 | KAsync::Job<void> remove(const Sink::ApplicationDomain::ApplicationDomainType &type) Q_DECL_OVERRIDE |
79 | return Sink::Store::remove<T>(*static_cast<const T*>(&type)); | 84 | { |
85 | return Sink::Store::remove<T>(*static_cast<const T *>(&type)); | ||
80 | } | 86 | } |
81 | 87 | ||
82 | QSharedPointer<QAbstractItemModel> loadModel(const Sink::Query &query) Q_DECL_OVERRIDE { | 88 | QSharedPointer<QAbstractItemModel> loadModel(const Sink::Query &query) Q_DECL_OVERRIDE |
89 | { | ||
83 | return Sink::Store::loadModel<T>(query); | 90 | return Sink::Store::loadModel<T>(query); |
84 | } | 91 | } |
85 | }; | 92 | }; |
86 | |||
87 | |||
88 | } | 93 | } |
89 | |||
diff --git a/sinksh/state.cpp b/sinksh/state.cpp index e03bf87..7fd3959 100644 --- a/sinksh/state.cpp +++ b/sinksh/state.cpp | |||
@@ -31,8 +31,7 @@ static bool s_hasEventLoop = false; | |||
31 | class State::Private | 31 | class State::Private |
32 | { | 32 | { |
33 | public: | 33 | public: |
34 | Private() | 34 | Private() : outStream(stdout) |
35 | : outStream(stdout) | ||
36 | { | 35 | { |
37 | } | 36 | } |
38 | 37 | ||
@@ -51,8 +50,7 @@ public: | |||
51 | QTextStream outStream; | 50 | QTextStream outStream; |
52 | }; | 51 | }; |
53 | 52 | ||
54 | State::State() | 53 | State::State() : d(new Private) |
55 | : d(new Private) | ||
56 | { | 54 | { |
57 | } | 55 | } |
58 | 56 | ||
@@ -141,4 +139,3 @@ QString State::loggingLevel() const | |||
141 | QByteArray rv = Sink::Log::debugLevelName(Sink::Log::debugOutputLevel()); | 139 | QByteArray rv = Sink::Log::debugLevelName(Sink::Log::debugOutputLevel()); |
142 | return rv.toLower(); | 140 | return rv.toLower(); |
143 | } | 141 | } |
144 | |||
diff --git a/sinksh/state.h b/sinksh/state.h index 3c4c2c7..2a0eb7c 100644 --- a/sinksh/state.h +++ b/sinksh/state.h | |||
@@ -47,6 +47,5 @@ public: | |||
47 | 47 | ||
48 | private: | 48 | private: |
49 | class Private; | 49 | class Private; |
50 | Private * const d; | 50 | Private *const d; |
51 | }; | 51 | }; |
52 | |||
diff --git a/sinksh/syntaxtree.cpp b/sinksh/syntaxtree.cpp index 4860582..3380b04 100644 --- a/sinksh/syntaxtree.cpp +++ b/sinksh/syntaxtree.cpp | |||
@@ -29,10 +29,7 @@ Syntax::Syntax() | |||
29 | } | 29 | } |
30 | 30 | ||
31 | Syntax::Syntax(const QString &k, const QString &helpText, std::function<bool(const QStringList &, State &)> l, Interactivity inter) | 31 | Syntax::Syntax(const QString &k, const QString &helpText, std::function<bool(const QStringList &, State &)> l, Interactivity inter) |
32 | : keyword(k), | 32 | : keyword(k), help(helpText), interactivity(inter), lambda(l) |
33 | help(helpText), | ||
34 | interactivity(inter), | ||
35 | lambda(l) | ||
36 | { | 33 | { |
37 | } | 34 | } |
38 | 35 | ||
@@ -75,10 +72,10 @@ bool SyntaxTree::run(const QStringList &commands) | |||
75 | m_state.printError(QObject::tr("Broken command... sorry :("), "st_broken"); | 72 | m_state.printError(QObject::tr("Broken command... sorry :("), "st_broken"); |
76 | } else { | 73 | } else { |
77 | QStringList keywordList; | 74 | QStringList keywordList; |
78 | for (auto syntax: command.first->children) { | 75 | for (auto syntax : command.first->children) { |
79 | keywordList << syntax.keyword; | 76 | keywordList << syntax.keyword; |
80 | } | 77 | } |
81 | const QString keywords = keywordList.join(" " ); | 78 | const QString keywords = keywordList.join(" "); |
82 | m_state.printError(QObject::tr("Command requires additional arguments, one of: %1").arg(keywords)); | 79 | m_state.printError(QObject::tr("Command requires additional arguments, one of: %1").arg(keywords)); |
83 | } | 80 | } |
84 | } else { | 81 | } else { |
@@ -129,9 +126,9 @@ Syntax::List SyntaxTree::nearestSyntax(const QStringList &words, const QString & | |||
129 | { | 126 | { |
130 | Syntax::List matches; | 127 | Syntax::List matches; |
131 | 128 | ||
132 | //qDebug() << "words are" << words; | 129 | // qDebug() << "words are" << words; |
133 | if (words.isEmpty()) { | 130 | if (words.isEmpty()) { |
134 | for (const Syntax &syntax: m_syntax) { | 131 | for (const Syntax &syntax : m_syntax) { |
135 | if (syntax.keyword.startsWith(fragment)) { | 132 | if (syntax.keyword.startsWith(fragment)) { |
136 | matches.push_back(syntax); | 133 | matches.push_back(syntax); |
137 | } | 134 | } |
@@ -153,7 +150,7 @@ Syntax::List SyntaxTree::nearestSyntax(const QStringList &words, const QString & | |||
153 | } | 150 | } |
154 | } | 151 | } |
155 | 152 | ||
156 | //qDebug() << "exiting with" << lastFullSyntax.keyword << words.last(); | 153 | // qDebug() << "exiting with" << lastFullSyntax.keyword << words.last(); |
157 | if (lastFullSyntax.keyword == words.last()) { | 154 | if (lastFullSyntax.keyword == words.last()) { |
158 | syntaxIt = lastFullSyntax.children; | 155 | syntaxIt = lastFullSyntax.children; |
159 | while (syntaxIt.hasNext()) { | 156 | while (syntaxIt.hasNext()) { |
@@ -175,7 +172,7 @@ State &SyntaxTree::state() | |||
175 | 172 | ||
176 | QStringList SyntaxTree::tokenize(const QString &text) | 173 | QStringList SyntaxTree::tokenize(const QString &text) |
177 | { | 174 | { |
178 | //TODO: properly tokenize (e.g. "foo bar" should not become ['"foo', 'bar"']a | 175 | // TODO: properly tokenize (e.g. "foo bar" should not become ['"foo', 'bar"']a |
179 | static const QVector<QChar> quoters = QVector<QChar>() << '"' << '\''; | 176 | static const QVector<QChar> quoters = QVector<QChar>() << '"' << '\''; |
180 | QStringList tokens; | 177 | QStringList tokens; |
181 | QString acc; | 178 | QString acc; |
@@ -218,4 +215,3 @@ QStringList SyntaxTree::tokenize(const QString &text) | |||
218 | 215 | ||
219 | return tokens; | 216 | return tokens; |
220 | } | 217 | } |
221 | |||
diff --git a/sinksh/syntaxtree.h b/sinksh/syntaxtree.h index 468aad3..be56067 100644 --- a/sinksh/syntaxtree.h +++ b/sinksh/syntaxtree.h | |||
@@ -32,16 +32,15 @@ class Syntax | |||
32 | public: | 32 | public: |
33 | typedef QVector<Syntax> List; | 33 | typedef QVector<Syntax> List; |
34 | 34 | ||
35 | enum Interactivity { | 35 | enum Interactivity |
36 | { | ||
36 | NotInteractive = 0, | 37 | NotInteractive = 0, |
37 | EventDriven | 38 | EventDriven |
38 | }; | 39 | }; |
39 | 40 | ||
40 | Syntax(); | 41 | Syntax(); |
41 | Syntax(const QString &keyword, | 42 | Syntax(const QString &keyword, const QString &helpText = QString(), |
42 | const QString &helpText = QString(), | 43 | std::function<bool(const QStringList &, State &)> lambda = std::function<bool(const QStringList &, State &)>(), Interactivity interactivity = NotInteractive); |
43 | std::function<bool(const QStringList &, State &)> lambda = std::function<bool(const QStringList &, State &)>(), | ||
44 | Interactivity interactivity = NotInteractive); | ||
45 | 44 | ||
46 | QString keyword; | 45 | QString keyword; |
47 | QString help; | 46 | QString help; |
diff --git a/sinksh/utils.cpp b/sinksh/utils.cpp index d2a28ed..7eea85f 100644 --- a/sinksh/utils.cpp +++ b/sinksh/utils.cpp | |||
@@ -19,8 +19,7 @@ | |||
19 | 19 | ||
20 | #include "utils.h" | 20 | #include "utils.h" |
21 | 21 | ||
22 | namespace Utils | 22 | namespace Utils { |
23 | { | ||
24 | 23 | ||
25 | QStringList filteredCompletions(const QStringList &possibleCompletions, const QString &commandFragment, Qt::CaseSensitivity cs) | 24 | QStringList filteredCompletions(const QStringList &possibleCompletions, const QString &commandFragment, Qt::CaseSensitivity cs) |
26 | { | 25 | { |
@@ -29,7 +28,7 @@ QStringList filteredCompletions(const QStringList &possibleCompletions, const QS | |||
29 | } | 28 | } |
30 | 29 | ||
31 | QStringList filtered; | 30 | QStringList filtered; |
32 | for (auto item: possibleCompletions) { | 31 | for (auto item : possibleCompletions) { |
33 | if (item.startsWith(commandFragment, cs)) { | 32 | if (item.startsWith(commandFragment, cs)) { |
34 | filtered << item; | 33 | filtered << item; |
35 | } | 34 | } |
@@ -39,4 +38,3 @@ QStringList filteredCompletions(const QStringList &possibleCompletions, const QS | |||
39 | } | 38 | } |
40 | 39 | ||
41 | } // namespace Utils | 40 | } // namespace Utils |
42 | |||
diff --git a/sinksh/utils.h b/sinksh/utils.h index 82be8d5..bcbdedb 100644 --- a/sinksh/utils.h +++ b/sinksh/utils.h | |||
@@ -21,10 +21,8 @@ | |||
21 | 21 | ||
22 | #include <QStringList> | 22 | #include <QStringList> |
23 | 23 | ||
24 | namespace Utils | 24 | namespace Utils { |
25 | { | ||
26 | 25 | ||
27 | QStringList filteredCompletions(const QStringList &possibleCompletions, const QString &commandFragment, Qt::CaseSensitivity cs = Qt::CaseSensitive); | 26 | QStringList filteredCompletions(const QStringList &possibleCompletions, const QString &commandFragment, Qt::CaseSensitivity cs = Qt::CaseSensitive); |
28 | 27 | ||
29 | } // namespace Utils | 28 | } // namespace Utils |
30 | |||
diff --git a/synchronizer/main.cpp b/synchronizer/main.cpp index d7a18e2..02cf365 100644 --- a/synchronizer/main.cpp +++ b/synchronizer/main.cpp | |||
@@ -29,33 +29,31 @@ | |||
29 | #undef DEBUG_AREA | 29 | #undef DEBUG_AREA |
30 | #define DEBUG_AREA "resource" | 30 | #define DEBUG_AREA "resource" |
31 | 31 | ||
32 | void crashHandler(int sig) { | 32 | void crashHandler(int sig) |
33 | { | ||
33 | std::fprintf(stderr, "Error: signal %d\n", sig); | 34 | std::fprintf(stderr, "Error: signal %d\n", sig); |
34 | 35 | ||
35 | QString s; | 36 | QString s; |
36 | void *trace[256]; | 37 | void *trace[256]; |
37 | int n = backtrace( trace, 256 ); | 38 | int n = backtrace(trace, 256); |
38 | if ( n ) { | 39 | if (n) { |
39 | char **strings = backtrace_symbols( trace, n ); | 40 | char **strings = backtrace_symbols(trace, n); |
40 | 41 | ||
41 | s = QLatin1String( "[\n" ); | 42 | s = QLatin1String("[\n"); |
42 | 43 | ||
43 | for ( int i = 0; i < n; ++i ) { | 44 | for (int i = 0; i < n; ++i) { |
44 | s += QString::number( i ) + | 45 | s += QString::number(i) + QLatin1String(": ") + QLatin1String(strings[i]) + QLatin1String("\n"); |
45 | QLatin1String( ": " ) + | ||
46 | QLatin1String( strings[i] ) + QLatin1String( "\n" ); | ||
47 | } | 46 | } |
48 | s += QLatin1String( "]\n" ); | 47 | s += QLatin1String("]\n"); |
49 | std::fprintf(stderr, "Backtrace: %s\n", s.toLatin1().data()); | 48 | std::fprintf(stderr, "Backtrace: %s\n", s.toLatin1().data()); |
50 | 49 | ||
51 | if ( strings ) { | 50 | if (strings) { |
52 | free( strings ); | 51 | free(strings); |
53 | } | 52 | } |
54 | |||
55 | } | 53 | } |
56 | 54 | ||
57 | std::system("exec gdb -p \"$PPID\" -ex \"thread apply all bt\""); | 55 | std::system("exec gdb -p \"$PPID\" -ex \"thread apply all bt\""); |
58 | //This only works if we actually have xterm and X11 available | 56 | // This only works if we actually have xterm and X11 available |
59 | // std::system("exec xterm -e gdb -p \"$PPID\""); | 57 | // std::system("exec xterm -e gdb -p \"$PPID\""); |
60 | 58 | ||
61 | std::abort(); | 59 | std::abort(); |
@@ -63,7 +61,7 @@ void crashHandler(int sig) { | |||
63 | 61 | ||
64 | int main(int argc, char *argv[]) | 62 | int main(int argc, char *argv[]) |
65 | { | 63 | { |
66 | //For crashes | 64 | // For crashes |
67 | signal(SIGSEGV, crashHandler); | 65 | signal(SIGSEGV, crashHandler); |
68 | QCoreApplication app(argc, argv); | 66 | QCoreApplication app(argc, argv); |
69 | 67 | ||
@@ -84,10 +82,8 @@ int main(int argc, char *argv[]) | |||
84 | 82 | ||
85 | Listener *listener = new Listener(instanceIdentifier, &app); | 83 | Listener *listener = new Listener(instanceIdentifier, &app); |
86 | 84 | ||
87 | QObject::connect(&app, &QCoreApplication::aboutToQuit, | 85 | QObject::connect(&app, &QCoreApplication::aboutToQuit, listener, &Listener::closeAllConnections); |
88 | listener, &Listener::closeAllConnections); | 86 | QObject::connect(listener, &Listener::noClients, &app, &QCoreApplication::quit); |
89 | QObject::connect(listener, &Listener::noClients, | ||
90 | &app, &QCoreApplication::quit); | ||
91 | 87 | ||
92 | return app.exec(); | 88 | return app.exec(); |
93 | } | 89 | } |
diff --git a/tests/clientapitest.cpp b/tests/clientapitest.cpp index 879ffc4..172232f 100644 --- a/tests/clientapitest.cpp +++ b/tests/clientapitest.cpp | |||
@@ -13,34 +13,41 @@ template <typename T> | |||
13 | class DummyResourceFacade : public Sink::StoreFacade<T> | 13 | class DummyResourceFacade : public Sink::StoreFacade<T> |
14 | { | 14 | { |
15 | public: | 15 | public: |
16 | static std::shared_ptr<DummyResourceFacade<T> > registerFacade(const QByteArray &instanceIdentifier = QByteArray()) | 16 | static std::shared_ptr<DummyResourceFacade<T>> registerFacade(const QByteArray &instanceIdentifier = QByteArray()) |
17 | { | 17 | { |
18 | static QMap<QByteArray, std::shared_ptr<DummyResourceFacade<T> > > map; | 18 | static QMap<QByteArray, std::shared_ptr<DummyResourceFacade<T>>> map; |
19 | auto facade = std::make_shared<DummyResourceFacade<T> >(); | 19 | auto facade = std::make_shared<DummyResourceFacade<T>>(); |
20 | map.insert(instanceIdentifier, facade); | 20 | map.insert(instanceIdentifier, facade); |
21 | bool alwaysReturnFacade = instanceIdentifier.isEmpty(); | 21 | bool alwaysReturnFacade = instanceIdentifier.isEmpty(); |
22 | Sink::FacadeFactory::instance().registerFacade<T, DummyResourceFacade<T> >("dummyresource", | 22 | Sink::FacadeFactory::instance().registerFacade<T, DummyResourceFacade<T>>("dummyresource", [alwaysReturnFacade](const QByteArray &instanceIdentifier) { |
23 | [alwaysReturnFacade](const QByteArray &instanceIdentifier) { | 23 | if (alwaysReturnFacade) { |
24 | if (alwaysReturnFacade) { | 24 | return map.value(QByteArray()); |
25 | return map.value(QByteArray()); | ||
26 | } | ||
27 | return map.value(instanceIdentifier); | ||
28 | } | 25 | } |
29 | ); | 26 | return map.value(instanceIdentifier); |
27 | }); | ||
30 | return facade; | 28 | return facade; |
31 | } | 29 | } |
32 | ~DummyResourceFacade(){}; | 30 | ~DummyResourceFacade(){}; |
33 | KAsync::Job<void> create(const T &domainObject) Q_DECL_OVERRIDE { return KAsync::null<void>(); }; | 31 | KAsync::Job<void> create(const T &domainObject) Q_DECL_OVERRIDE |
34 | KAsync::Job<void> modify(const T &domainObject) Q_DECL_OVERRIDE { return KAsync::null<void>(); }; | 32 | { |
35 | KAsync::Job<void> remove(const T &domainObject) Q_DECL_OVERRIDE { return KAsync::null<void>(); }; | 33 | return KAsync::null<void>(); |
36 | QPair<KAsync::Job<void>, typename Sink::ResultEmitter<typename T::Ptr>::Ptr > load(const Sink::Query &query) Q_DECL_OVERRIDE | 34 | }; |
35 | KAsync::Job<void> modify(const T &domainObject) Q_DECL_OVERRIDE | ||
36 | { | ||
37 | return KAsync::null<void>(); | ||
38 | }; | ||
39 | KAsync::Job<void> remove(const T &domainObject) Q_DECL_OVERRIDE | ||
40 | { | ||
41 | return KAsync::null<void>(); | ||
42 | }; | ||
43 | QPair<KAsync::Job<void>, typename Sink::ResultEmitter<typename T::Ptr>::Ptr> load(const Sink::Query &query) Q_DECL_OVERRIDE | ||
37 | { | 44 | { |
38 | auto resultProvider = new Sink::ResultProvider<typename T::Ptr>(); | 45 | auto resultProvider = new Sink::ResultProvider<typename T::Ptr>(); |
39 | resultProvider->onDone([resultProvider]() { | 46 | resultProvider->onDone([resultProvider]() { |
40 | Trace() << "Result provider is done"; | 47 | Trace() << "Result provider is done"; |
41 | delete resultProvider; | 48 | delete resultProvider; |
42 | }); | 49 | }); |
43 | //We have to do it this way, otherwise we're not setting the fetcher right | 50 | // We have to do it this way, otherwise we're not setting the fetcher right |
44 | auto emitter = resultProvider->emitter(); | 51 | auto emitter = resultProvider->emitter(); |
45 | 52 | ||
46 | resultProvider->setFetcher([query, resultProvider, this](const typename T::Ptr &parent) { | 53 | resultProvider->setFetcher([query, resultProvider, this](const typename T::Ptr &parent) { |
@@ -60,8 +67,7 @@ public: | |||
60 | } | 67 | } |
61 | resultProvider->initialResultSetComplete(parent); | 68 | resultProvider->initialResultSetComplete(parent); |
62 | }); | 69 | }); |
63 | auto job = KAsync::start<void>([query, resultProvider]() { | 70 | auto job = KAsync::start<void>([query, resultProvider]() {}); |
64 | }); | ||
65 | mResultProvider = resultProvider; | 71 | mResultProvider = resultProvider; |
66 | return qMakePair(job, emitter); | 72 | return qMakePair(job, emitter); |
67 | } | 73 | } |
@@ -73,7 +79,7 @@ public: | |||
73 | 79 | ||
74 | /** | 80 | /** |
75 | * Test of the client api implementation. | 81 | * Test of the client api implementation. |
76 | * | 82 | * |
77 | * This test works with injected dummy facades and thus doesn't write to storage. | 83 | * This test works with injected dummy facades and thus doesn't write to storage. |
78 | */ | 84 | */ |
79 | class ClientAPITest : public QObject | 85 | class ClientAPITest : public QObject |
@@ -113,7 +119,7 @@ private slots: | |||
113 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); | 119 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); |
114 | } | 120 | } |
115 | 121 | ||
116 | //TODO: This test doesn't belong to this testsuite | 122 | // TODO: This test doesn't belong to this testsuite |
117 | void resourceManagement() | 123 | void resourceManagement() |
118 | { | 124 | { |
119 | ResourceConfig::clear(); | 125 | ResourceConfig::clear(); |
@@ -158,13 +164,13 @@ private slots: | |||
158 | void testModelNested() | 164 | void testModelNested() |
159 | { | 165 | { |
160 | auto facade = DummyResourceFacade<Sink::ApplicationDomain::Folder>::registerFacade(); | 166 | auto facade = DummyResourceFacade<Sink::ApplicationDomain::Folder>::registerFacade(); |
161 | auto folder = QSharedPointer<Sink::ApplicationDomain::Folder>::create("resource", "id", 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); | 167 | auto folder = QSharedPointer<Sink::ApplicationDomain::Folder>::create("resource", "id", 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); |
162 | auto subfolder = QSharedPointer<Sink::ApplicationDomain::Folder>::create("resource", "subId", 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); | 168 | auto subfolder = QSharedPointer<Sink::ApplicationDomain::Folder>::create("resource", "subId", 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); |
163 | subfolder->setProperty("parent", "id"); | 169 | subfolder->setProperty("parent", "id"); |
164 | facade->results << folder << subfolder; | 170 | facade->results << folder << subfolder; |
165 | ResourceConfig::addResource("dummyresource.instance1", "dummyresource"); | 171 | ResourceConfig::addResource("dummyresource.instance1", "dummyresource"); |
166 | 172 | ||
167 | //Test | 173 | // Test |
168 | Sink::Query query; | 174 | Sink::Query query; |
169 | query.resources << "dummyresource.instance1"; | 175 | query.resources << "dummyresource.instance1"; |
170 | query.liveQuery = false; | 176 | query.liveQuery = false; |
@@ -181,13 +187,13 @@ private slots: | |||
181 | void testModelSignals() | 187 | void testModelSignals() |
182 | { | 188 | { |
183 | auto facade = DummyResourceFacade<Sink::ApplicationDomain::Folder>::registerFacade(); | 189 | auto facade = DummyResourceFacade<Sink::ApplicationDomain::Folder>::registerFacade(); |
184 | auto folder = QSharedPointer<Sink::ApplicationDomain::Folder>::create("resource", "id", 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); | 190 | auto folder = QSharedPointer<Sink::ApplicationDomain::Folder>::create("resource", "id", 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); |
185 | auto subfolder = QSharedPointer<Sink::ApplicationDomain::Folder>::create("resource", "subId", 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); | 191 | auto subfolder = QSharedPointer<Sink::ApplicationDomain::Folder>::create("resource", "subId", 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); |
186 | subfolder->setProperty("parent", "id"); | 192 | subfolder->setProperty("parent", "id"); |
187 | facade->results << folder << subfolder; | 193 | facade->results << folder << subfolder; |
188 | ResourceConfig::addResource("dummyresource.instance1", "dummyresource"); | 194 | ResourceConfig::addResource("dummyresource.instance1", "dummyresource"); |
189 | 195 | ||
190 | //Test | 196 | // Test |
191 | Sink::Query query; | 197 | Sink::Query query; |
192 | query.resources << "dummyresource.instance1"; | 198 | query.resources << "dummyresource.instance1"; |
193 | query.liveQuery = false; | 199 | query.liveQuery = false; |
@@ -203,13 +209,14 @@ private slots: | |||
203 | void testModelNestedLive() | 209 | void testModelNestedLive() |
204 | { | 210 | { |
205 | auto facade = DummyResourceFacade<Sink::ApplicationDomain::Folder>::registerFacade(); | 211 | auto facade = DummyResourceFacade<Sink::ApplicationDomain::Folder>::registerFacade(); |
206 | auto folder = QSharedPointer<Sink::ApplicationDomain::Folder>::create("dummyresource.instance1", "id", 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); | 212 | auto folder = QSharedPointer<Sink::ApplicationDomain::Folder>::create("dummyresource.instance1", "id", 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); |
207 | auto subfolder = QSharedPointer<Sink::ApplicationDomain::Folder>::create("dummyresource.instance1", "subId", 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); | 213 | auto subfolder = |
214 | QSharedPointer<Sink::ApplicationDomain::Folder>::create("dummyresource.instance1", "subId", 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); | ||
208 | subfolder->setProperty("parent", "id"); | 215 | subfolder->setProperty("parent", "id"); |
209 | facade->results << folder << subfolder; | 216 | facade->results << folder << subfolder; |
210 | ResourceConfig::addResource("dummyresource.instance1", "dummyresource"); | 217 | ResourceConfig::addResource("dummyresource.instance1", "dummyresource"); |
211 | 218 | ||
212 | //Test | 219 | // Test |
213 | Sink::Query query; | 220 | Sink::Query query; |
214 | query.resources << "dummyresource.instance1"; | 221 | query.resources << "dummyresource.instance1"; |
215 | query.liveQuery = true; | 222 | query.liveQuery = true; |
@@ -222,7 +229,7 @@ private slots: | |||
222 | 229 | ||
223 | auto resultProvider = facade->mResultProvider; | 230 | auto resultProvider = facade->mResultProvider; |
224 | 231 | ||
225 | //Test new toplevel folder | 232 | // Test new toplevel folder |
226 | { | 233 | { |
227 | QSignalSpy rowsInsertedSpy(model.data(), SIGNAL(rowsInserted(const QModelIndex &, int, int))); | 234 | QSignalSpy rowsInsertedSpy(model.data(), SIGNAL(rowsInserted(const QModelIndex &, int, int))); |
228 | auto folder2 = QSharedPointer<Sink::ApplicationDomain::Folder>::create("resource", "id2", 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); | 235 | auto folder2 = QSharedPointer<Sink::ApplicationDomain::Folder>::create("resource", "id2", 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); |
@@ -232,7 +239,7 @@ private slots: | |||
232 | QCOMPARE(rowsInsertedSpy.at(0).at(0).value<QModelIndex>(), QModelIndex()); | 239 | QCOMPARE(rowsInsertedSpy.at(0).at(0).value<QModelIndex>(), QModelIndex()); |
233 | } | 240 | } |
234 | 241 | ||
235 | //Test changed name | 242 | // Test changed name |
236 | { | 243 | { |
237 | QSignalSpy dataChanged(model.data(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &, const QVector<int> &))); | 244 | QSignalSpy dataChanged(model.data(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &, const QVector<int> &))); |
238 | folder->setProperty("subject", "modifiedSubject"); | 245 | folder->setProperty("subject", "modifiedSubject"); |
@@ -241,7 +248,7 @@ private slots: | |||
241 | QTRY_COMPARE(dataChanged.count(), 1); | 248 | QTRY_COMPARE(dataChanged.count(), 1); |
242 | } | 249 | } |
243 | 250 | ||
244 | //Test removal | 251 | // Test removal |
245 | { | 252 | { |
246 | QSignalSpy rowsRemovedSpy(model.data(), SIGNAL(rowsRemoved(const QModelIndex &, int, int))); | 253 | QSignalSpy rowsRemovedSpy(model.data(), SIGNAL(rowsRemoved(const QModelIndex &, int, int))); |
247 | folder->setProperty("subject", "modifiedSubject"); | 254 | folder->setProperty("subject", "modifiedSubject"); |
@@ -250,7 +257,7 @@ private slots: | |||
250 | QTRY_COMPARE(rowsRemovedSpy.count(), 1); | 257 | QTRY_COMPARE(rowsRemovedSpy.count(), 1); |
251 | } | 258 | } |
252 | 259 | ||
253 | //TODO: A modification can also be a move | 260 | // TODO: A modification can also be a move |
254 | } | 261 | } |
255 | 262 | ||
256 | void testLoadMultiResource() | 263 | void testLoadMultiResource() |
@@ -274,7 +281,7 @@ private slots: | |||
274 | }); | 281 | }); |
275 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); | 282 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); |
276 | QCOMPARE(model->rowCount(QModelIndex()), 2); | 283 | QCOMPARE(model->rowCount(QModelIndex()), 2); |
277 | //Ensure children fetched is only emitted once (when all resources are done) | 284 | // Ensure children fetched is only emitted once (when all resources are done) |
278 | QTest::qWait(50); | 285 | QTest::qWait(50); |
279 | QCOMPARE(childrenFetchedCount, 1); | 286 | QCOMPARE(childrenFetchedCount, 1); |
280 | } | 287 | } |
@@ -291,15 +298,12 @@ private slots: | |||
291 | 298 | ||
292 | bool gotValue = false; | 299 | bool gotValue = false; |
293 | auto result = Sink::Store::fetchOne<Sink::ApplicationDomain::Event>(query) | 300 | auto result = Sink::Store::fetchOne<Sink::ApplicationDomain::Event>(query) |
294 | .then<void, Sink::ApplicationDomain::Event>([&gotValue](const Sink::ApplicationDomain::Event &event) { | 301 | .then<void, Sink::ApplicationDomain::Event>([&gotValue](const Sink::ApplicationDomain::Event &event) { gotValue = true; }) |
295 | gotValue = true; | 302 | .exec(); |
296 | }).exec(); | ||
297 | result.waitForFinished(); | 303 | result.waitForFinished(); |
298 | QVERIFY(!result.errorCode()); | 304 | QVERIFY(!result.errorCode()); |
299 | QVERIFY(gotValue); | 305 | QVERIFY(gotValue); |
300 | } | 306 | } |
301 | |||
302 | |||
303 | }; | 307 | }; |
304 | 308 | ||
305 | QTEST_MAIN(ClientAPITest) | 309 | QTEST_MAIN(ClientAPITest) |
diff --git a/tests/databasepopulationandfacadequerybenchmark.cpp b/tests/databasepopulationandfacadequerybenchmark.cpp index 16537c0..4e886af 100644 --- a/tests/databasepopulationandfacadequerybenchmark.cpp +++ b/tests/databasepopulationandfacadequerybenchmark.cpp | |||
@@ -23,7 +23,7 @@ | |||
23 | 23 | ||
24 | /** | 24 | /** |
25 | * Benchmark read performance of the facade implementation. | 25 | * Benchmark read performance of the facade implementation. |
26 | * | 26 | * |
27 | * The memory used should grow linearly with the number of retrieved entities. | 27 | * The memory used should grow linearly with the number of retrieved entities. |
28 | * The memory used should be independent from the database size, after accounting for the memory mapped db. | 28 | * The memory used should be independent from the database size, after accounting for the memory mapped db. |
29 | */ | 29 | */ |
@@ -39,7 +39,7 @@ class DatabasePopulationAndFacadeQueryBenchmark : public QObject | |||
39 | void populateDatabase(int count) | 39 | void populateDatabase(int count) |
40 | { | 40 | { |
41 | Sink::Storage(Sink::storageLocation(), "identifier", Sink::Storage::ReadWrite).removeFromDisk(); | 41 | Sink::Storage(Sink::storageLocation(), "identifier", Sink::Storage::ReadWrite).removeFromDisk(); |
42 | //Setup | 42 | // Setup |
43 | auto domainTypeAdaptorFactory = QSharedPointer<TestEventAdaptorFactory>::create(); | 43 | auto domainTypeAdaptorFactory = QSharedPointer<TestEventAdaptorFactory>::create(); |
44 | { | 44 | { |
45 | Sink::Storage storage(Sink::storageLocation(), identifier, Sink::Storage::ReadWrite); | 45 | Sink::Storage storage(Sink::storageLocation(), identifier, Sink::Storage::ReadWrite); |
@@ -57,7 +57,7 @@ class DatabasePopulationAndFacadeQueryBenchmark : public QObject | |||
57 | domainObject->setProperty("attachment", attachment); | 57 | domainObject->setProperty("attachment", attachment); |
58 | flatbuffers::FlatBufferBuilder fbb; | 58 | flatbuffers::FlatBufferBuilder fbb; |
59 | domainTypeAdaptorFactory->createBuffer(*domainObject, fbb); | 59 | domainTypeAdaptorFactory->createBuffer(*domainObject, fbb); |
60 | const auto buffer = QByteArray::fromRawData(reinterpret_cast<const char*>(fbb.GetBufferPointer()), fbb.GetSize()); | 60 | const auto buffer = QByteArray::fromRawData(reinterpret_cast<const char *>(fbb.GetBufferPointer()), fbb.GetSize()); |
61 | const auto key = QUuid::createUuid().toString().toLatin1(); | 61 | const auto key = QUuid::createUuid().toString().toLatin1(); |
62 | db.write(key, buffer); | 62 | db.write(key, buffer); |
63 | bufferSizeTotal += buffer.size(); | 63 | bufferSizeTotal += buffer.size(); |
@@ -72,15 +72,15 @@ class DatabasePopulationAndFacadeQueryBenchmark : public QObject | |||
72 | auto size = db.getSize(); | 72 | auto size = db.getSize(); |
73 | auto onDisk = storage.diskUsage(); | 73 | auto onDisk = storage.diskUsage(); |
74 | auto writeAmplification = static_cast<double>(onDisk) / static_cast<double>(bufferSizeTotal); | 74 | auto writeAmplification = static_cast<double>(onDisk) / static_cast<double>(bufferSizeTotal); |
75 | std::cout << "Database size [kb]: " << size/1024 << std::endl; | 75 | std::cout << "Database size [kb]: " << size / 1024 << std::endl; |
76 | std::cout << "On disk [kb]: " << onDisk/1024 << std::endl; | 76 | std::cout << "On disk [kb]: " << onDisk / 1024 << std::endl; |
77 | std::cout << "Buffer size total [kb]: " << bufferSizeTotal/1024 << std::endl; | 77 | std::cout << "Buffer size total [kb]: " << bufferSizeTotal / 1024 << std::endl; |
78 | std::cout << "Key size total [kb]: " << keysSizeTotal/1024 << std::endl; | 78 | std::cout << "Key size total [kb]: " << keysSizeTotal / 1024 << std::endl; |
79 | std::cout << "Data size total [kb]: " << dataSizeTotal/1024 << std::endl; | 79 | std::cout << "Data size total [kb]: " << dataSizeTotal / 1024 << std::endl; |
80 | std::cout << "Write amplification: " << writeAmplification << std::endl; | 80 | std::cout << "Write amplification: " << writeAmplification << std::endl; |
81 | 81 | ||
82 | //The buffer has an overhead, but with a reasonable attachment size it should be relatively small | 82 | // The buffer has an overhead, but with a reasonable attachment size it should be relatively small |
83 | //A write amplification of 2 should be the worst case | 83 | // A write amplification of 2 should be the worst case |
84 | QVERIFY(writeAmplification < 2); | 84 | QVERIFY(writeAmplification < 2); |
85 | } | 85 | } |
86 | } | 86 | } |
@@ -91,13 +91,14 @@ class DatabasePopulationAndFacadeQueryBenchmark : public QObject | |||
91 | 91 | ||
92 | Sink::Query query; | 92 | Sink::Query query; |
93 | query.liveQuery = false; | 93 | query.liveQuery = false; |
94 | query.requestedProperties << "uid" << "summary"; | 94 | query.requestedProperties << "uid" |
95 | << "summary"; | ||
95 | 96 | ||
96 | //Benchmark | 97 | // Benchmark |
97 | QTime time; | 98 | QTime time; |
98 | time.start(); | 99 | time.start(); |
99 | 100 | ||
100 | auto resultSet = QSharedPointer<Sink::ResultProvider<Sink::ApplicationDomain::Event::Ptr> >::create(); | 101 | auto resultSet = QSharedPointer<Sink::ResultProvider<Sink::ApplicationDomain::Event::Ptr>>::create(); |
101 | auto resourceAccess = QSharedPointer<TestResourceAccess>::create(); | 102 | auto resourceAccess = QSharedPointer<TestResourceAccess>::create(); |
102 | TestResourceFacade facade(identifier, resourceAccess); | 103 | TestResourceFacade facade(identifier, resourceAccess); |
103 | 104 | ||
@@ -105,13 +106,9 @@ class DatabasePopulationAndFacadeQueryBenchmark : public QObject | |||
105 | ret.first.exec().waitForFinished(); | 106 | ret.first.exec().waitForFinished(); |
106 | auto emitter = ret.second; | 107 | auto emitter = ret.second; |
107 | QList<Sink::ApplicationDomain::Event::Ptr> list; | 108 | QList<Sink::ApplicationDomain::Event::Ptr> list; |
108 | emitter->onAdded([&list](const Sink::ApplicationDomain::Event::Ptr &event) { | 109 | emitter->onAdded([&list](const Sink::ApplicationDomain::Event::Ptr &event) { list << event; }); |
109 | list << event; | ||
110 | }); | ||
111 | bool done = false; | 110 | bool done = false; |
112 | emitter->onInitialResultSetComplete([&done](const Sink::ApplicationDomain::Event::Ptr &event) { | 111 | emitter->onInitialResultSetComplete([&done](const Sink::ApplicationDomain::Event::Ptr &event) { done = true; }); |
113 | done = true; | ||
114 | }); | ||
115 | emitter->fetch(Sink::ApplicationDomain::Event::Ptr()); | 112 | emitter->fetch(Sink::ApplicationDomain::Event::Ptr()); |
116 | QTRY_VERIFY(done); | 113 | QTRY_VERIFY(done); |
117 | QCOMPARE(list.size(), count); | 114 | QCOMPARE(list.size(), count); |
@@ -120,35 +117,35 @@ class DatabasePopulationAndFacadeQueryBenchmark : public QObject | |||
120 | 117 | ||
121 | const auto finalRss = getCurrentRSS(); | 118 | const auto finalRss = getCurrentRSS(); |
122 | const auto rssGrowth = finalRss - startingRss; | 119 | const auto rssGrowth = finalRss - startingRss; |
123 | //Since the database is memory mapped it is attributted to the resident set size. | 120 | // Since the database is memory mapped it is attributted to the resident set size. |
124 | const auto rssWithoutDb = finalRss - Sink::Storage(Sink::storageLocation(), identifier, Sink::Storage::ReadWrite).diskUsage(); | 121 | const auto rssWithoutDb = finalRss - Sink::Storage(Sink::storageLocation(), identifier, Sink::Storage::ReadWrite).diskUsage(); |
125 | const auto peakRss = getPeakRSS(); | 122 | const auto peakRss = getPeakRSS(); |
126 | //How much peak deviates from final rss in percent (should be around 0) | 123 | // How much peak deviates from final rss in percent (should be around 0) |
127 | const auto percentageRssError = static_cast<double>(peakRss - finalRss)*100.0/static_cast<double>(finalRss); | 124 | const auto percentageRssError = static_cast<double>(peakRss - finalRss) * 100.0 / static_cast<double>(finalRss); |
128 | auto rssGrowthPerEntity = rssGrowth/count; | 125 | auto rssGrowthPerEntity = rssGrowth / count; |
129 | 126 | ||
130 | std::cout << "Loaded " << list.size() << " results." << std::endl; | 127 | std::cout << "Loaded " << list.size() << " results." << std::endl; |
131 | std::cout << "The query took [ms]: " << elapsed << std::endl; | 128 | std::cout << "The query took [ms]: " << elapsed << std::endl; |
132 | std::cout << "Current Rss usage [kb]: " << finalRss/1024 << std::endl; | 129 | std::cout << "Current Rss usage [kb]: " << finalRss / 1024 << std::endl; |
133 | std::cout << "Peak Rss usage [kb]: " << peakRss/1024 << std::endl; | 130 | std::cout << "Peak Rss usage [kb]: " << peakRss / 1024 << std::endl; |
134 | std::cout << "Rss growth [kb]: " << rssGrowth/1024 << std::endl; | 131 | std::cout << "Rss growth [kb]: " << rssGrowth / 1024 << std::endl; |
135 | std::cout << "Rss growth per entity [byte]: " << rssGrowthPerEntity << std::endl; | 132 | std::cout << "Rss growth per entity [byte]: " << rssGrowthPerEntity << std::endl; |
136 | std::cout << "Rss without db [kb]: " << rssWithoutDb/1024 << std::endl; | 133 | std::cout << "Rss without db [kb]: " << rssWithoutDb / 1024 << std::endl; |
137 | std::cout << "Percentage error: " << percentageRssError << std::endl; | 134 | std::cout << "Percentage error: " << percentageRssError << std::endl; |
138 | 135 | ||
139 | HAWD::Dataset dataset("facade_query", mHawdState); | 136 | HAWD::Dataset dataset("facade_query", mHawdState); |
140 | HAWD::Dataset::Row row = dataset.row(); | 137 | HAWD::Dataset::Row row = dataset.row(); |
141 | row.setValue("rows", list.size()); | 138 | row.setValue("rows", list.size()); |
142 | row.setValue("queryResultPerMs", (qreal)list.size()/elapsed); | 139 | row.setValue("queryResultPerMs", (qreal)list.size() / elapsed); |
143 | dataset.insertRow(row); | 140 | dataset.insertRow(row); |
144 | HAWD::Formatter::print(dataset); | 141 | HAWD::Formatter::print(dataset); |
145 | 142 | ||
146 | mTimePerEntity << static_cast<double>(elapsed)/static_cast<double>(count); | 143 | mTimePerEntity << static_cast<double>(elapsed) / static_cast<double>(count); |
147 | mRssGrowthPerEntity << rssGrowthPerEntity; | 144 | mRssGrowthPerEntity << rssGrowthPerEntity; |
148 | 145 | ||
149 | QVERIFY(percentageRssError < 10); | 146 | QVERIFY(percentageRssError < 10); |
150 | //TODO This is much more than it should it seems, although adding the attachment results in pretty exactly a 1k increase, | 147 | // TODO This is much more than it should it seems, although adding the attachment results in pretty exactly a 1k increase, |
151 | //so it doesn't look like that memory is being duplicated. | 148 | // so it doesn't look like that memory is being duplicated. |
152 | QVERIFY(rssGrowthPerEntity < 3300); | 149 | QVERIFY(rssGrowthPerEntity < 3300); |
153 | 150 | ||
154 | // Print memory layout, RSS is what is in memory | 151 | // Print memory layout, RSS is what is in memory |
diff --git a/tests/domainadaptortest.cpp b/tests/domainadaptortest.cpp index 5939a31..ff75d21 100644 --- a/tests/domainadaptortest.cpp +++ b/tests/domainadaptortest.cpp | |||
@@ -54,7 +54,7 @@ private slots: | |||
54 | 54 | ||
55 | void testAdaptor() | 55 | void testAdaptor() |
56 | { | 56 | { |
57 | //Create entity buffer | 57 | // Create entity buffer |
58 | flatbuffers::FlatBufferBuilder metadataFbb; | 58 | flatbuffers::FlatBufferBuilder metadataFbb; |
59 | auto metadataBuilder = Sink::MetadataBuilder(metadataFbb); | 59 | auto metadataBuilder = Sink::MetadataBuilder(metadataFbb); |
60 | metadataBuilder.add_revision(1); | 60 | metadataBuilder.add_revision(1); |
@@ -75,19 +75,19 @@ private slots: | |||
75 | Sink::ApplicationDomain::Buffer::FinishEventBuffer(m_fbb, buffer); | 75 | Sink::ApplicationDomain::Buffer::FinishEventBuffer(m_fbb, buffer); |
76 | 76 | ||
77 | flatbuffers::FlatBufferBuilder fbb; | 77 | flatbuffers::FlatBufferBuilder fbb; |
78 | Sink::EntityBuffer::assembleEntityBuffer(fbb, metadataFbb.GetBufferPointer(), metadataFbb.GetSize(), m_fbb.GetBufferPointer(), m_fbb.GetSize(), m_fbb.GetBufferPointer(), m_fbb.GetSize()); | 78 | Sink::EntityBuffer::assembleEntityBuffer( |
79 | fbb, metadataFbb.GetBufferPointer(), metadataFbb.GetSize(), m_fbb.GetBufferPointer(), m_fbb.GetSize(), m_fbb.GetBufferPointer(), m_fbb.GetSize()); | ||
79 | 80 | ||
80 | //Extract entity buffer | 81 | // Extract entity buffer |
81 | { | 82 | { |
82 | std::string data(reinterpret_cast<const char*>(fbb.GetBufferPointer()), fbb.GetSize()); | 83 | std::string data(reinterpret_cast<const char *>(fbb.GetBufferPointer()), fbb.GetSize()); |
83 | Sink::EntityBuffer buffer((void*)(data.data()), data.size()); | 84 | Sink::EntityBuffer buffer((void *)(data.data()), data.size()); |
84 | 85 | ||
85 | TestFactory factory; | 86 | TestFactory factory; |
86 | auto adaptor = factory.createAdaptor(buffer.entity()); | 87 | auto adaptor = factory.createAdaptor(buffer.entity()); |
87 | QCOMPARE(adaptor->getProperty("summary").toString(), QString("summary1")); | 88 | QCOMPARE(adaptor->getProperty("summary").toString(), QString("summary1")); |
88 | } | 89 | } |
89 | } | 90 | } |
90 | |||
91 | }; | 91 | }; |
92 | 92 | ||
93 | QTEST_MAIN(DomainAdaptorTest) | 93 | QTEST_MAIN(DomainAdaptorTest) |
diff --git a/tests/dummyresourcebenchmark.cpp b/tests/dummyresourcebenchmark.cpp index 77b87fb..124abc1 100644 --- a/tests/dummyresourcebenchmark.cpp +++ b/tests/dummyresourcebenchmark.cpp | |||
@@ -44,40 +44,38 @@ private slots: | |||
44 | { | 44 | { |
45 | } | 45 | } |
46 | 46 | ||
47 | static KAsync::Job<void> waitForCompletion(QList<KAsync::Future<void> > &futures) | 47 | static KAsync::Job<void> waitForCompletion(QList<KAsync::Future<void>> &futures) |
48 | { | 48 | { |
49 | auto context = new QObject; | 49 | auto context = new QObject; |
50 | return KAsync::start<void>([futures, context](KAsync::Future<void> &future) { | 50 | return KAsync::start<void>([futures, context](KAsync::Future<void> &future) { |
51 | const auto total = futures.size(); | 51 | const auto total = futures.size(); |
52 | auto count = QSharedPointer<int>::create(); | 52 | auto count = QSharedPointer<int>::create(); |
53 | int i = 0; | 53 | int i = 0; |
54 | for (KAsync::Future<void> subFuture : futures) { | 54 | for (KAsync::Future<void> subFuture : futures) { |
55 | i++; | 55 | i++; |
56 | if (subFuture.isFinished()) { | 56 | if (subFuture.isFinished()) { |
57 | *count += 1; | 57 | *count += 1; |
58 | continue; | 58 | continue; |
59 | } | 59 | } |
60 | //FIXME bind lifetime all watcher to future (repectively the main job | 60 | // FIXME bind lifetime all watcher to future (repectively the main job |
61 | auto watcher = QSharedPointer<KAsync::FutureWatcher<void> >::create(); | 61 | auto watcher = QSharedPointer<KAsync::FutureWatcher<void>>::create(); |
62 | QObject::connect(watcher.data(), &KAsync::FutureWatcher<void>::futureReady, | 62 | QObject::connect(watcher.data(), &KAsync::FutureWatcher<void>::futureReady, [count, total, &future]() { |
63 | [count, total, &future](){ | 63 | *count += 1; |
64 | *count += 1; | 64 | if (*count == total) { |
65 | if (*count == total) { | 65 | future.setFinished(); |
66 | future.setFinished(); | 66 | } |
67 | } | 67 | }); |
68 | }); | 68 | watcher->setFuture(subFuture); |
69 | watcher->setFuture(subFuture); | 69 | context->setProperty(QString("future%1").arg(i).toLatin1().data(), QVariant::fromValue(watcher)); |
70 | context->setProperty(QString("future%1").arg(i).toLatin1().data(), QVariant::fromValue(watcher)); | 70 | } |
71 | } | 71 | }) |
72 | }).then<void>([context]() { | 72 | .then<void>([context]() { delete context; }); |
73 | delete context; | ||
74 | }); | ||
75 | } | 73 | } |
76 | 74 | ||
77 | //Ensure we can process a command in less than 0.1s | 75 | // Ensure we can process a command in less than 0.1s |
78 | void testCommandResponsiveness() | 76 | void testCommandResponsiveness() |
79 | { | 77 | { |
80 | //Test responsiveness including starting the process. | 78 | // Test responsiveness including starting the process. |
81 | Sink::Store::removeDataFromDisk("org.kde.dummy.instance1").exec().waitForFinished(); | 79 | Sink::Store::removeDataFromDisk("org.kde.dummy.instance1").exec().waitForFinished(); |
82 | 80 | ||
83 | QTime time; | 81 | QTime time; |
@@ -100,7 +98,7 @@ private slots: | |||
100 | 98 | ||
101 | Sink::Store::create<Sink::ApplicationDomain::Event>(event).exec(); | 99 | Sink::Store::create<Sink::ApplicationDomain::Event>(event).exec(); |
102 | 100 | ||
103 | //Wait for notification | 101 | // Wait for notification |
104 | QTRY_VERIFY(gotNotification); | 102 | QTRY_VERIFY(gotNotification); |
105 | 103 | ||
106 | 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()); |
@@ -114,7 +112,7 @@ private slots: | |||
114 | 112 | ||
115 | QTime time; | 113 | QTime time; |
116 | time.start(); | 114 | time.start(); |
117 | QList<KAsync::Future<void> > waitCondition; | 115 | QList<KAsync::Future<void>> waitCondition; |
118 | for (int i = 0; i < num; i++) { | 116 | for (int i = 0; i < num; i++) { |
119 | Sink::ApplicationDomain::Event event("org.kde.dummy.instance1"); | 117 | Sink::ApplicationDomain::Event event("org.kde.dummy.instance1"); |
120 | event.setProperty("uid", "testuid"); | 118 | event.setProperty("uid", "testuid"); |
@@ -125,7 +123,7 @@ private slots: | |||
125 | waitForCompletion(waitCondition).exec().waitForFinished(); | 123 | waitForCompletion(waitCondition).exec().waitForFinished(); |
126 | auto appendTime = time.elapsed(); | 124 | auto appendTime = time.elapsed(); |
127 | 125 | ||
128 | //Ensure everything is processed | 126 | // Ensure everything is processed |
129 | { | 127 | { |
130 | Sink::Query query; | 128 | Sink::Query query; |
131 | query.resources << "org.kde.dummy.instance1"; | 129 | query.resources << "org.kde.dummy.instance1"; |
@@ -137,13 +135,13 @@ private slots: | |||
137 | HAWD::Dataset::Row row = dataset.row(); | 135 | HAWD::Dataset::Row row = dataset.row(); |
138 | 136 | ||
139 | row.setValue("rows", num); | 137 | row.setValue("rows", num); |
140 | row.setValue("append", (qreal)num/appendTime); | 138 | row.setValue("append", (qreal)num / appendTime); |
141 | row.setValue("total", (qreal)num/allProcessedTime); | 139 | row.setValue("total", (qreal)num / allProcessedTime); |
142 | dataset.insertRow(row); | 140 | dataset.insertRow(row); |
143 | HAWD::Formatter::print(dataset); | 141 | HAWD::Formatter::print(dataset); |
144 | 142 | ||
145 | auto diskUsage = DummyResource::diskUsage("org.kde.dummy.instance1"); | 143 | auto diskUsage = DummyResource::diskUsage("org.kde.dummy.instance1"); |
146 | qDebug() << "Database size [kb]: " << diskUsage/1024; | 144 | qDebug() << "Database size [kb]: " << diskUsage / 1024; |
147 | 145 | ||
148 | // Print memory layout, RSS is what is in memory | 146 | // Print memory layout, RSS is what is in memory |
149 | // std::system("exec pmap -x \"$PPID\""); | 147 | // std::system("exec pmap -x \"$PPID\""); |
@@ -153,7 +151,7 @@ private slots: | |||
153 | { | 151 | { |
154 | QTime time; | 152 | QTime time; |
155 | time.start(); | 153 | time.start(); |
156 | //Measure query | 154 | // Measure query |
157 | { | 155 | { |
158 | time.start(); | 156 | time.start(); |
159 | Sink::Query query; | 157 | Sink::Query query; |
@@ -168,7 +166,7 @@ private slots: | |||
168 | HAWD::Dataset dataset("dummy_query_by_uid", m_hawdState); | 166 | HAWD::Dataset dataset("dummy_query_by_uid", m_hawdState); |
169 | HAWD::Dataset::Row row = dataset.row(); | 167 | HAWD::Dataset::Row row = dataset.row(); |
170 | row.setValue("rows", num); | 168 | row.setValue("rows", num); |
171 | row.setValue("read", (qreal)num/queryTime); | 169 | row.setValue("read", (qreal)num / queryTime); |
172 | dataset.insertRow(row); | 170 | dataset.insertRow(row); |
173 | HAWD::Formatter::print(dataset); | 171 | HAWD::Formatter::print(dataset); |
174 | } | 172 | } |
@@ -220,7 +218,7 @@ private slots: | |||
220 | } | 218 | } |
221 | auto appendTime = time.elapsed(); | 219 | auto appendTime = time.elapsed(); |
222 | 220 | ||
223 | //Wait until all messages have been processed | 221 | // Wait until all messages have been processed |
224 | resource.processAllMessages().exec().waitForFinished(); | 222 | resource.processAllMessages().exec().waitForFinished(); |
225 | 223 | ||
226 | auto allProcessedTime = time.elapsed(); | 224 | auto allProcessedTime = time.elapsed(); |
@@ -229,8 +227,8 @@ private slots: | |||
229 | HAWD::Dataset::Row row = dataset.row(); | 227 | HAWD::Dataset::Row row = dataset.row(); |
230 | 228 | ||
231 | row.setValue("rows", num); | 229 | row.setValue("rows", num); |
232 | row.setValue("append", (qreal)num/appendTime); | 230 | row.setValue("append", (qreal)num / appendTime); |
233 | row.setValue("total", (qreal)num/allProcessedTime); | 231 | row.setValue("total", (qreal)num / allProcessedTime); |
234 | dataset.insertRow(row); | 232 | dataset.insertRow(row); |
235 | HAWD::Formatter::print(dataset); | 233 | HAWD::Formatter::print(dataset); |
236 | 234 | ||
@@ -250,7 +248,7 @@ private slots: | |||
250 | 248 | ||
251 | static flatbuffers::FlatBufferBuilder fbb; | 249 | static flatbuffers::FlatBufferBuilder fbb; |
252 | fbb.Clear(); | 250 | fbb.Clear(); |
253 | //This is the resource buffer type and not the domain type | 251 | // This is the resource buffer type and not the domain type |
254 | auto entityId = fbb.CreateString(""); | 252 | auto entityId = fbb.CreateString(""); |
255 | auto type = fbb.CreateString("event"); | 253 | auto type = fbb.CreateString("event"); |
256 | // auto delta = fbb.CreateVector<uint8_t>(entityFbb.GetBufferPointer(), entityFbb.GetSize()); | 254 | // auto delta = fbb.CreateVector<uint8_t>(entityFbb.GetBufferPointer(), entityFbb.GetSize()); |
@@ -260,7 +258,7 @@ private slots: | |||
260 | } | 258 | } |
261 | } | 259 | } |
262 | 260 | ||
263 | //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 |
264 | void testCleanupForCompleteTest() | 262 | void testCleanupForCompleteTest() |
265 | { | 263 | { |
266 | Sink::Store::removeDataFromDisk("org.kde.dummy.instance1").exec().waitForFinished(); | 264 | Sink::Store::removeDataFromDisk("org.kde.dummy.instance1").exec().waitForFinished(); |
diff --git a/tests/dummyresourcetest.cpp b/tests/dummyresourcetest.cpp index 8b5a8fa..33304e1 100644 --- a/tests/dummyresourcetest.cpp +++ b/tests/dummyresourcetest.cpp | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | /** | 15 | /** |
16 | * Test of complete system using the dummy resource. | 16 | * Test of complete system using the dummy resource. |
17 | * | 17 | * |
18 | * This test requires the dummy resource installed. | 18 | * This test requires the dummy resource installed. |
19 | */ | 19 | */ |
20 | class DummyResourceTest : public QObject | 20 | class DummyResourceTest : public QObject |
@@ -65,7 +65,7 @@ private slots: | |||
65 | Sink::Query query; | 65 | Sink::Query query; |
66 | query.resources << "org.kde.dummy.instance1"; | 66 | query.resources << "org.kde.dummy.instance1"; |
67 | 67 | ||
68 | //Ensure all local data is processed | 68 | // Ensure all local data is processed |
69 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 69 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
70 | 70 | ||
71 | query.propertyFilter.insert("uid", "testuid"); | 71 | query.propertyFilter.insert("uid", "testuid"); |
@@ -89,7 +89,7 @@ private slots: | |||
89 | Sink::Query query; | 89 | Sink::Query query; |
90 | query.resources << "org.kde.dummy.instance1"; | 90 | query.resources << "org.kde.dummy.instance1"; |
91 | 91 | ||
92 | //Ensure all local data is processed | 92 | // Ensure all local data is processed |
93 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 93 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
94 | 94 | ||
95 | query.propertyFilter.insert("uid", "testuid"); | 95 | query.propertyFilter.insert("uid", "testuid"); |
@@ -117,7 +117,7 @@ private slots: | |||
117 | Sink::Query query; | 117 | Sink::Query query; |
118 | query.resources << "org.kde.dummy.instance1"; | 118 | query.resources << "org.kde.dummy.instance1"; |
119 | 119 | ||
120 | //Ensure all local data is processed | 120 | // Ensure all local data is processed |
121 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 121 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
122 | 122 | ||
123 | query.propertyFilter.insert("summary", "summaryValue2"); | 123 | query.propertyFilter.insert("summary", "summaryValue2"); |
@@ -135,7 +135,7 @@ private slots: | |||
135 | auto pipeline = QSharedPointer<Sink::Pipeline>::create("org.kde.dummy.instance1"); | 135 | auto pipeline = QSharedPointer<Sink::Pipeline>::create("org.kde.dummy.instance1"); |
136 | DummyResource resource("org.kde.dummy.instance1", pipeline); | 136 | DummyResource resource("org.kde.dummy.instance1", pipeline); |
137 | auto job = resource.synchronizeWithSource(); | 137 | auto job = resource.synchronizeWithSource(); |
138 | //TODO pass in optional timeout? | 138 | // TODO pass in optional timeout? |
139 | auto future = job.exec(); | 139 | auto future = job.exec(); |
140 | future.waitForFinished(); | 140 | future.waitForFinished(); |
141 | QVERIFY(!future.errorCode()); | 141 | QVERIFY(!future.errorCode()); |
@@ -150,7 +150,7 @@ private slots: | |||
150 | Sink::Query query; | 150 | Sink::Query query; |
151 | query.resources << "org.kde.dummy.instance1"; | 151 | query.resources << "org.kde.dummy.instance1"; |
152 | 152 | ||
153 | //Ensure all local data is processed | 153 | // Ensure all local data is processed |
154 | Sink::Store::synchronize(query).exec().waitForFinished(); | 154 | Sink::Store::synchronize(query).exec().waitForFinished(); |
155 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 155 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
156 | 156 | ||
@@ -167,7 +167,7 @@ private slots: | |||
167 | Sink::Query query; | 167 | Sink::Query query; |
168 | query.resources << "org.kde.dummy.instance1"; | 168 | query.resources << "org.kde.dummy.instance1"; |
169 | 169 | ||
170 | //Ensure all local data is processed | 170 | // Ensure all local data is processed |
171 | Sink::Store::synchronize(query).exec().waitForFinished(); | 171 | Sink::Store::synchronize(query).exec().waitForFinished(); |
172 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 172 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
173 | 173 | ||
@@ -191,10 +191,10 @@ private slots: | |||
191 | query.resources << "org.kde.dummy.instance1"; | 191 | query.resources << "org.kde.dummy.instance1"; |
192 | query.propertyFilter.insert("uid", "testuid"); | 192 | query.propertyFilter.insert("uid", "testuid"); |
193 | 193 | ||
194 | //Ensure all local data is processed | 194 | // Ensure all local data is processed |
195 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 195 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
196 | 196 | ||
197 | //Test create | 197 | // Test create |
198 | Sink::ApplicationDomain::Event event2; | 198 | Sink::ApplicationDomain::Event event2; |
199 | { | 199 | { |
200 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Event>(query); | 200 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Event>(query); |
@@ -210,10 +210,10 @@ private slots: | |||
210 | event2.setProperty("summary", "summaryValue2"); | 210 | event2.setProperty("summary", "summaryValue2"); |
211 | Sink::Store::modify<Sink::ApplicationDomain::Event>(event2).exec().waitForFinished(); | 211 | Sink::Store::modify<Sink::ApplicationDomain::Event>(event2).exec().waitForFinished(); |
212 | 212 | ||
213 | //Ensure all local data is processed | 213 | // Ensure all local data is processed |
214 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 214 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
215 | 215 | ||
216 | //Test modify | 216 | // Test modify |
217 | { | 217 | { |
218 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Event>(query); | 218 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Event>(query); |
219 | QTRY_COMPARE(model->rowCount(QModelIndex()), 1); | 219 | QTRY_COMPARE(model->rowCount(QModelIndex()), 1); |
@@ -225,10 +225,10 @@ private slots: | |||
225 | 225 | ||
226 | Sink::Store::remove<Sink::ApplicationDomain::Event>(event2).exec().waitForFinished(); | 226 | Sink::Store::remove<Sink::ApplicationDomain::Event>(event2).exec().waitForFinished(); |
227 | 227 | ||
228 | //Ensure all local data is processed | 228 | // Ensure all local data is processed |
229 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 229 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
230 | 230 | ||
231 | //Test remove | 231 | // Test remove |
232 | { | 232 | { |
233 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Event>(query); | 233 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Event>(query); |
234 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); | 234 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); |
@@ -253,7 +253,7 @@ private slots: | |||
253 | event.setProperty("summary", "summaryValue"); | 253 | event.setProperty("summary", "summaryValue"); |
254 | Sink::Store::create<Sink::ApplicationDomain::Event>(event).exec().waitForFinished(); | 254 | Sink::Store::create<Sink::ApplicationDomain::Event>(event).exec().waitForFinished(); |
255 | 255 | ||
256 | //Test create | 256 | // Test create |
257 | Sink::ApplicationDomain::Event event2; | 257 | Sink::ApplicationDomain::Event event2; |
258 | { | 258 | { |
259 | QTRY_COMPARE(model->rowCount(QModelIndex()), 1); | 259 | QTRY_COMPARE(model->rowCount(QModelIndex()), 1); |
@@ -267,9 +267,9 @@ private slots: | |||
267 | event2.setProperty("summary", "summaryValue2"); | 267 | event2.setProperty("summary", "summaryValue2"); |
268 | Sink::Store::modify<Sink::ApplicationDomain::Event>(event2).exec().waitForFinished(); | 268 | Sink::Store::modify<Sink::ApplicationDomain::Event>(event2).exec().waitForFinished(); |
269 | 269 | ||
270 | //Test modify | 270 | // Test modify |
271 | { | 271 | { |
272 | //TODO wait for a change signal | 272 | // TODO wait for a change signal |
273 | QTRY_COMPARE(model->rowCount(QModelIndex()), 1); | 273 | QTRY_COMPARE(model->rowCount(QModelIndex()), 1); |
274 | auto value = model->index(0, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).value<Sink::ApplicationDomain::Event::Ptr>(); | 274 | auto value = model->index(0, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).value<Sink::ApplicationDomain::Event::Ptr>(); |
275 | QCOMPARE(value->getProperty("uid").toByteArray(), QByteArray("testuid")); | 275 | QCOMPARE(value->getProperty("uid").toByteArray(), QByteArray("testuid")); |
@@ -278,12 +278,11 @@ private slots: | |||
278 | 278 | ||
279 | Sink::Store::remove<Sink::ApplicationDomain::Event>(event2).exec().waitForFinished(); | 279 | Sink::Store::remove<Sink::ApplicationDomain::Event>(event2).exec().waitForFinished(); |
280 | 280 | ||
281 | //Test remove | 281 | // Test remove |
282 | { | 282 | { |
283 | QTRY_COMPARE(model->rowCount(QModelIndex()), 0); | 283 | QTRY_COMPARE(model->rowCount(QModelIndex()), 0); |
284 | } | 284 | } |
285 | } | 285 | } |
286 | |||
287 | }; | 286 | }; |
288 | 287 | ||
289 | QTEST_MAIN(DummyResourceTest) | 288 | QTEST_MAIN(DummyResourceTest) |
diff --git a/tests/dummyresourcewritebenchmark.cpp b/tests/dummyresourcewritebenchmark.cpp index 539d189..b4ab438 100644 --- a/tests/dummyresourcewritebenchmark.cpp +++ b/tests/dummyresourcewritebenchmark.cpp | |||
@@ -123,39 +123,39 @@ class DummyResourceWriteBenchmark : public QObject | |||
123 | Q_UNUSED(appendTime); | 123 | Q_UNUSED(appendTime); |
124 | auto bufferSizeTotal = bufferSize * num; | 124 | auto bufferSizeTotal = bufferSize * num; |
125 | 125 | ||
126 | //Wait until all messages have been processed | 126 | // Wait until all messages have been processed |
127 | resource.processAllMessages().exec().waitForFinished(); | 127 | resource.processAllMessages().exec().waitForFinished(); |
128 | 128 | ||
129 | auto allProcessedTime = time.elapsed(); | 129 | auto allProcessedTime = time.elapsed(); |
130 | 130 | ||
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("org.kde.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); |
138 | auto rssGrowthPerEntity = rssGrowth/num; | 138 | auto rssGrowthPerEntity = rssGrowth / num; |
139 | std::cout << "Current Rss usage [kb]: " << finalRss/1024 << std::endl; | 139 | std::cout << "Current Rss usage [kb]: " << finalRss / 1024 << std::endl; |
140 | std::cout << "Peak Rss usage [kb]: " << peakRss/1024 << std::endl; | 140 | std::cout << "Peak Rss usage [kb]: " << peakRss / 1024 << std::endl; |
141 | std::cout << "Rss growth [kb]: " << rssGrowth/1024 << std::endl; | 141 | std::cout << "Rss growth [kb]: " << rssGrowth / 1024 << std::endl; |
142 | std::cout << "Rss growth per entity [byte]: " << rssGrowthPerEntity << std::endl; | 142 | std::cout << "Rss growth per entity [byte]: " << rssGrowthPerEntity << std::endl; |
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("org.kde.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; |
150 | std::cout << "Write amplification: " << writeAmplification << std::endl; | 150 | std::cout << "Write amplification: " << writeAmplification << std::endl; |
151 | 151 | ||
152 | 152 | ||
153 | mTimePerEntity << static_cast<double>(allProcessedTime)/static_cast<double>(num); | 153 | mTimePerEntity << static_cast<double>(allProcessedTime) / static_cast<double>(num); |
154 | mRssGrowthPerEntity << rssGrowthPerEntity; | 154 | mRssGrowthPerEntity << rssGrowthPerEntity; |
155 | 155 | ||
156 | QVERIFY(percentageRssError < 10); | 156 | QVERIFY(percentageRssError < 10); |
157 | //TODO This is much more than it should it seems, although adding the attachment results in pretty exactly a 1k increase, | 157 | // TODO This is much more than it should it seems, although adding the attachment results in pretty exactly a 1k increase, |
158 | //so it doesn't look like that memory is being duplicated. | 158 | // so it doesn't look like that memory is being duplicated. |
159 | QVERIFY(rssGrowthPerEntity < 2500); | 159 | QVERIFY(rssGrowthPerEntity < 2500); |
160 | 160 | ||
161 | // HAWD::Dataset dataset("dummy_write_in_process", m_hawdState); | 161 | // HAWD::Dataset dataset("dummy_write_in_process", m_hawdState); |
@@ -219,7 +219,7 @@ private slots: | |||
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("org.kde.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("org.kde.dummy.instance1"); |
diff --git a/tests/genericfacadetest.cpp b/tests/genericfacadetest.cpp index 397bf6a..8336875 100644 --- a/tests/genericfacadetest.cpp +++ b/tests/genericfacadetest.cpp | |||
@@ -9,7 +9,7 @@ | |||
9 | #include <common/resultprovider.h> | 9 | #include <common/resultprovider.h> |
10 | #include <common/synclistresult.h> | 10 | #include <common/synclistresult.h> |
11 | 11 | ||
12 | //Replace with something different | 12 | // Replace with something different |
13 | #include "event_generated.h" | 13 | #include "event_generated.h" |
14 | 14 | ||
15 | 15 | ||
@@ -34,7 +34,7 @@ private slots: | |||
34 | Sink::Query query; | 34 | Sink::Query query; |
35 | query.liveQuery = false; | 35 | query.liveQuery = false; |
36 | 36 | ||
37 | auto resultSet = QSharedPointer<Sink::ResultProvider<Sink::ApplicationDomain::Event::Ptr> >::create(); | 37 | auto resultSet = QSharedPointer<Sink::ResultProvider<Sink::ApplicationDomain::Event::Ptr>>::create(); |
38 | auto resourceAccess = QSharedPointer<TestResourceAccess>::create(); | 38 | auto resourceAccess = QSharedPointer<TestResourceAccess>::create(); |
39 | // storage->mResults << Sink::ApplicationDomain::Event::Ptr::create(); | 39 | // storage->mResults << Sink::ApplicationDomain::Event::Ptr::create(); |
40 | TestResourceFacade facade("identifier", resourceAccess); | 40 | TestResourceFacade facade("identifier", resourceAccess); |
@@ -44,7 +44,7 @@ private slots: | |||
44 | facade.load(query, *resultSet).exec().waitForFinished(); | 44 | facade.load(query, *resultSet).exec().waitForFinished(); |
45 | resultSet->initialResultSetComplete(); | 45 | resultSet->initialResultSetComplete(); |
46 | 46 | ||
47 | //We have to wait for the events that deliver the results to be processed by the eventloop | 47 | // We have to wait for the events that deliver the results to be processed by the eventloop |
48 | result.exec(); | 48 | result.exec(); |
49 | 49 | ||
50 | QCOMPARE(result.size(), 1); | 50 | QCOMPARE(result.size(), 1); |
@@ -55,7 +55,7 @@ private slots: | |||
55 | Sink::Query query; | 55 | Sink::Query query; |
56 | query.liveQuery = true; | 56 | query.liveQuery = true; |
57 | 57 | ||
58 | auto resultSet = QSharedPointer<Sink::ResultProvider<Sink::ApplicationDomain::Event::Ptr> >::create(); | 58 | auto resultSet = QSharedPointer<Sink::ResultProvider<Sink::ApplicationDomain::Event::Ptr>>::create(); |
59 | auto resourceAccess = QSharedPointer<TestResourceAccess>::create(); | 59 | auto resourceAccess = QSharedPointer<TestResourceAccess>::create(); |
60 | // storage->mResults << Sink::ApplicationDomain::Event::Ptr::create(); | 60 | // storage->mResults << Sink::ApplicationDomain::Event::Ptr::create(); |
61 | TestResourceFacade facade("identifier", resourceAccess); | 61 | TestResourceFacade facade("identifier", resourceAccess); |
@@ -68,13 +68,13 @@ private slots: | |||
68 | result.exec(); | 68 | result.exec(); |
69 | QCOMPARE(result.size(), 1); | 69 | QCOMPARE(result.size(), 1); |
70 | 70 | ||
71 | //Enter a second result | 71 | // Enter a second result |
72 | // storage->mResults.clear(); | 72 | // storage->mResults.clear(); |
73 | // storage->mResults << QSharedPointer<Sink::ApplicationDomain::Event>::create("resource", "id2", 0, QSharedPointer<Sink::ApplicationDomain::BufferAdaptor>()); | 73 | // storage->mResults << QSharedPointer<Sink::ApplicationDomain::Event>::create("resource", "id2", 0, QSharedPointer<Sink::ApplicationDomain::BufferAdaptor>()); |
74 | // storage->mLatestRevision = 2; | 74 | // storage->mLatestRevision = 2; |
75 | resourceAccess->emit revisionChanged(2); | 75 | resourceAccess->emit revisionChanged(2); |
76 | 76 | ||
77 | //Hack to get event loop in synclistresult to abort again | 77 | // Hack to get event loop in synclistresult to abort again |
78 | resultSet->initialResultSetComplete(); | 78 | resultSet->initialResultSetComplete(); |
79 | result.exec(); | 79 | result.exec(); |
80 | 80 | ||
@@ -86,7 +86,7 @@ private slots: | |||
86 | Sink::Query query; | 86 | Sink::Query query; |
87 | query.liveQuery = true; | 87 | query.liveQuery = true; |
88 | 88 | ||
89 | auto resultSet = QSharedPointer<Sink::ResultProvider<Sink::ApplicationDomain::Event::Ptr> >::create(); | 89 | auto resultSet = QSharedPointer<Sink::ResultProvider<Sink::ApplicationDomain::Event::Ptr>>::create(); |
90 | auto resourceAccess = QSharedPointer<TestResourceAccess>::create(); | 90 | auto resourceAccess = QSharedPointer<TestResourceAccess>::create(); |
91 | auto entity = QSharedPointer<Sink::ApplicationDomain::Event>::create("resource", "id2", 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); | 91 | auto entity = QSharedPointer<Sink::ApplicationDomain::Event>::create("resource", "id2", 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); |
92 | entity->setProperty("test", "test1"); | 92 | entity->setProperty("test", "test1"); |
@@ -101,7 +101,7 @@ private slots: | |||
101 | result.exec(); | 101 | result.exec(); |
102 | QCOMPARE(result.size(), 1); | 102 | QCOMPARE(result.size(), 1); |
103 | 103 | ||
104 | //Modify the entity again | 104 | // Modify the entity again |
105 | // storage->mResults.clear(); | 105 | // storage->mResults.clear(); |
106 | entity = QSharedPointer<Sink::ApplicationDomain::Event>::create("resource", "id2", 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); | 106 | entity = QSharedPointer<Sink::ApplicationDomain::Event>::create("resource", "id2", 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); |
107 | entity->setProperty("test", "test2"); | 107 | entity->setProperty("test", "test2"); |
@@ -109,7 +109,7 @@ private slots: | |||
109 | // storage->mLatestRevision = 2; | 109 | // storage->mLatestRevision = 2; |
110 | resourceAccess->emit revisionChanged(2); | 110 | resourceAccess->emit revisionChanged(2); |
111 | 111 | ||
112 | //Hack to get event loop in synclistresult to abort again | 112 | // Hack to get event loop in synclistresult to abort again |
113 | resultSet->initialResultSetComplete(); | 113 | resultSet->initialResultSetComplete(); |
114 | result.exec(); | 114 | result.exec(); |
115 | 115 | ||
@@ -122,7 +122,7 @@ private slots: | |||
122 | Sink::Query query; | 122 | Sink::Query query; |
123 | query.liveQuery = true; | 123 | query.liveQuery = true; |
124 | 124 | ||
125 | auto resultSet = QSharedPointer<Sink::ResultProvider<Sink::ApplicationDomain::Event::Ptr> >::create(); | 125 | auto resultSet = QSharedPointer<Sink::ResultProvider<Sink::ApplicationDomain::Event::Ptr>>::create(); |
126 | auto resourceAccess = QSharedPointer<TestResourceAccess>::create(); | 126 | auto resourceAccess = QSharedPointer<TestResourceAccess>::create(); |
127 | auto entity = QSharedPointer<Sink::ApplicationDomain::Event>::create("resource", "id2", 0, QSharedPointer<Sink::ApplicationDomain::BufferAdaptor>()); | 127 | auto entity = QSharedPointer<Sink::ApplicationDomain::Event>::create("resource", "id2", 0, QSharedPointer<Sink::ApplicationDomain::BufferAdaptor>()); |
128 | // storage->mResults << entity; | 128 | // storage->mResults << entity; |
@@ -136,13 +136,13 @@ private slots: | |||
136 | result.exec(); | 136 | result.exec(); |
137 | QCOMPARE(result.size(), 1); | 137 | QCOMPARE(result.size(), 1); |
138 | 138 | ||
139 | //Remove the entity again | 139 | // Remove the entity again |
140 | // storage->mResults.clear(); | 140 | // storage->mResults.clear(); |
141 | // storage->mRemovals << entity; | 141 | // storage->mRemovals << entity; |
142 | // storage->mLatestRevision = 2; | 142 | // storage->mLatestRevision = 2; |
143 | resourceAccess->emit revisionChanged(2); | 143 | resourceAccess->emit revisionChanged(2); |
144 | 144 | ||
145 | //Hack to get event loop in synclistresult to abort again | 145 | // Hack to get event loop in synclistresult to abort again |
146 | resultSet->initialResultSetComplete(); | 146 | resultSet->initialResultSetComplete(); |
147 | result.exec(); | 147 | result.exec(); |
148 | 148 | ||
diff --git a/tests/genericresourcebenchmark.cpp b/tests/genericresourcebenchmark.cpp index b3af6a6..a0a368c 100644 --- a/tests/genericresourcebenchmark.cpp +++ b/tests/genericresourcebenchmark.cpp | |||
@@ -60,7 +60,8 @@ static QByteArray createEntityBuffer() | |||
60 | return QByteArray(reinterpret_cast<const char *>(fbb.GetBufferPointer()), fbb.GetSize()); | 60 | return QByteArray(reinterpret_cast<const char *>(fbb.GetBufferPointer()), fbb.GetSize()); |
61 | } | 61 | } |
62 | 62 | ||
63 | class IndexUpdater : public Sink::Preprocessor { | 63 | class IndexUpdater : public Sink::Preprocessor |
64 | { | ||
64 | public: | 65 | public: |
65 | void newEntity(const QByteArray &uid, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &newEntity, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | 66 | void newEntity(const QByteArray &uid, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &newEntity, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE |
66 | { | 67 | { |
@@ -70,7 +71,8 @@ public: | |||
70 | } | 71 | } |
71 | } | 72 | } |
72 | 73 | ||
73 | void modifiedEntity(const QByteArray &key, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &oldEntity, const Sink::ApplicationDomain::BufferAdaptor &newEntity, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | 74 | void modifiedEntity(const QByteArray &key, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &oldEntity, const Sink::ApplicationDomain::BufferAdaptor &newEntity, |
75 | Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | ||
74 | { | 76 | { |
75 | } | 77 | } |
76 | 78 | ||
@@ -117,7 +119,7 @@ private slots: | |||
117 | } | 119 | } |
118 | auto appendTime = time.elapsed(); | 120 | auto appendTime = time.elapsed(); |
119 | 121 | ||
120 | //Wait until all messages have been processed | 122 | // Wait until all messages have been processed |
121 | resource.processAllMessages().exec().waitForFinished(); | 123 | resource.processAllMessages().exec().waitForFinished(); |
122 | 124 | ||
123 | auto allProcessedTime = time.elapsed(); | 125 | auto allProcessedTime = time.elapsed(); |
@@ -129,8 +131,8 @@ private slots: | |||
129 | HAWD::Dataset::Row row = dataset.row(); | 131 | HAWD::Dataset::Row row = dataset.row(); |
130 | 132 | ||
131 | row.setValue("rows", num); | 133 | row.setValue("rows", num); |
132 | row.setValue("append", (qreal)num/appendTime); | 134 | row.setValue("append", (qreal)num / appendTime); |
133 | row.setValue("total", (qreal)num/allProcessedTime); | 135 | row.setValue("total", (qreal)num / allProcessedTime); |
134 | dataset.insertRow(row); | 136 | dataset.insertRow(row); |
135 | HAWD::Formatter::print(dataset); | 137 | HAWD::Formatter::print(dataset); |
136 | } | 138 | } |
@@ -145,7 +147,7 @@ private slots: | |||
145 | const QByteArray resourceIdentifier = "org.kde.test.instance1"; | 147 | const QByteArray resourceIdentifier = "org.kde.test.instance1"; |
146 | auto indexer = QSharedPointer<IndexUpdater>::create(); | 148 | auto indexer = QSharedPointer<IndexUpdater>::create(); |
147 | 149 | ||
148 | pipeline->setPreprocessors("event", QVector<Sink::Preprocessor*>() << indexer.data()); | 150 | pipeline->setPreprocessors("event", QVector<Sink::Preprocessor *>() << indexer.data()); |
149 | pipeline->setAdaptorFactory("event", eventFactory); | 151 | pipeline->setAdaptorFactory("event", eventFactory); |
150 | 152 | ||
151 | TestResource resource("org.kde.test.instance1", pipeline); | 153 | TestResource resource("org.kde.test.instance1", pipeline); |
@@ -160,7 +162,7 @@ private slots: | |||
160 | } | 162 | } |
161 | auto appendTime = time.elapsed(); | 163 | auto appendTime = time.elapsed(); |
162 | 164 | ||
163 | //Wait until all messages have been processed | 165 | // Wait until all messages have been processed |
164 | resource.processAllMessages().exec().waitForFinished(); | 166 | resource.processAllMessages().exec().waitForFinished(); |
165 | 167 | ||
166 | auto allProcessedTime = time.elapsed(); | 168 | auto allProcessedTime = time.elapsed(); |
@@ -172,8 +174,8 @@ private slots: | |||
172 | HAWD::Dataset::Row row = dataset.row(); | 174 | HAWD::Dataset::Row row = dataset.row(); |
173 | 175 | ||
174 | row.setValue("rows", num); | 176 | row.setValue("rows", num); |
175 | row.setValue("append", (qreal)num/appendTime); | 177 | row.setValue("append", (qreal)num / appendTime); |
176 | row.setValue("total", (qreal)num/allProcessedTime); | 178 | row.setValue("total", (qreal)num / allProcessedTime); |
177 | dataset.insertRow(row); | 179 | dataset.insertRow(row); |
178 | HAWD::Formatter::print(dataset); | 180 | HAWD::Formatter::print(dataset); |
179 | } | 181 | } |
@@ -190,7 +192,7 @@ private slots: | |||
190 | 192 | ||
191 | static flatbuffers::FlatBufferBuilder fbb; | 193 | static flatbuffers::FlatBufferBuilder fbb; |
192 | fbb.Clear(); | 194 | fbb.Clear(); |
193 | //This is the resource buffer type and not the domain type | 195 | // This is the resource buffer type and not the domain type |
194 | auto type = fbb.CreateString("event"); | 196 | auto type = fbb.CreateString("event"); |
195 | // auto delta = fbb.CreateVector<uint8_t>(entityFbb.GetBufferPointer(), entityFbb.GetSize()); | 197 | // auto delta = fbb.CreateVector<uint8_t>(entityFbb.GetBufferPointer(), entityFbb.GetSize()); |
196 | auto delta = Sink::EntityBuffer::appendAsVector(fbb, entityFbb.GetBufferPointer(), entityFbb.GetSize()); | 198 | auto delta = Sink::EntityBuffer::appendAsVector(fbb, entityFbb.GetBufferPointer(), entityFbb.GetSize()); |
diff --git a/tests/genericresourcetest.cpp b/tests/genericresourcetest.cpp index a04c634..7474cbf 100644 --- a/tests/genericresourcetest.cpp +++ b/tests/genericresourcetest.cpp | |||
@@ -16,7 +16,7 @@ | |||
16 | 16 | ||
17 | /** | 17 | /** |
18 | * Test of the generic resource implementation. | 18 | * Test of the generic resource implementation. |
19 | * | 19 | * |
20 | * This test relies on a working pipeline implementation, and writes to storage. | 20 | * This test relies on a working pipeline implementation, and writes to storage. |
21 | */ | 21 | */ |
22 | class GenericResourceTest : public QObject | 22 | class GenericResourceTest : public QObject |
@@ -30,7 +30,7 @@ private slots: | |||
30 | Sink::Log::setDebugOutputLevel(Sink::Log::Trace); | 30 | Sink::Log::setDebugOutputLevel(Sink::Log::Trace); |
31 | } | 31 | } |
32 | 32 | ||
33 | ///Ensure the resource can process messages | 33 | /// Ensure the resource can process messages |
34 | void testProcessCommand() | 34 | void testProcessCommand() |
35 | { | 35 | { |
36 | flatbuffers::FlatBufferBuilder eventFbb; | 36 | flatbuffers::FlatBufferBuilder eventFbb; |
@@ -70,7 +70,7 @@ private slots: | |||
70 | QVERIFY(Sink::Commands::VerifyCreateEntityBuffer(verifyer)); | 70 | QVERIFY(Sink::Commands::VerifyCreateEntityBuffer(verifyer)); |
71 | } | 71 | } |
72 | 72 | ||
73 | //Actual test | 73 | // Actual test |
74 | auto pipeline = QSharedPointer<Sink::Pipeline>::create("org.kde.test.instance1"); | 74 | auto pipeline = QSharedPointer<Sink::Pipeline>::create("org.kde.test.instance1"); |
75 | QSignalSpy revisionSpy(pipeline.data(), SIGNAL(revisionUpdated(qint64))); | 75 | QSignalSpy revisionSpy(pipeline.data(), SIGNAL(revisionUpdated(qint64))); |
76 | QVERIFY(revisionSpy.isValid()); | 76 | QVERIFY(revisionSpy.isValid()); |
diff --git a/tests/getrssusage.cpp b/tests/getrssusage.cpp index 020c7d6..16fec52 100644 --- a/tests/getrssusage.cpp +++ b/tests/getrssusage.cpp | |||
@@ -21,7 +21,7 @@ | |||
21 | #if defined(__APPLE__) && defined(__MACH__) | 21 | #if defined(__APPLE__) && defined(__MACH__) |
22 | #include <mach/mach.h> | 22 | #include <mach/mach.h> |
23 | 23 | ||
24 | #elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__))) | 24 | #elif(defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__))) |
25 | #include <fcntl.h> | 25 | #include <fcntl.h> |
26 | #include <procfs.h> | 26 | #include <procfs.h> |
27 | 27 | ||
@@ -40,85 +40,79 @@ | |||
40 | * memory use) measured in bytes, or zero if the value cannot be | 40 | * memory use) measured in bytes, or zero if the value cannot be |
41 | * determined on this OS. | 41 | * determined on this OS. |
42 | */ | 42 | */ |
43 | size_t getPeakRSS( ) | 43 | size_t getPeakRSS() |
44 | { | 44 | { |
45 | #if defined(_WIN32) | 45 | #if defined(_WIN32) |
46 | /* Windows -------------------------------------------------- */ | 46 | /* Windows -------------------------------------------------- */ |
47 | PROCESS_MEMORY_COUNTERS info; | 47 | PROCESS_MEMORY_COUNTERS info; |
48 | GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) ); | 48 | GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)); |
49 | return (size_t)info.PeakWorkingSetSize; | 49 | return (size_t)info.PeakWorkingSetSize; |
50 | 50 | ||
51 | #elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__))) | 51 | #elif(defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__))) |
52 | /* AIX and Solaris ------------------------------------------ */ | 52 | /* AIX and Solaris ------------------------------------------ */ |
53 | struct psinfo psinfo; | 53 | struct psinfo psinfo; |
54 | int fd = -1; | 54 | int fd = -1; |
55 | if ( (fd = open( "/proc/self/psinfo", O_RDONLY )) == -1 ) | 55 | if ((fd = open("/proc/self/psinfo", O_RDONLY)) == -1) |
56 | return (size_t)0L; /* Can't open? */ | 56 | return (size_t)0L; /* Can't open? */ |
57 | if ( read( fd, &psinfo, sizeof(psinfo) ) != sizeof(psinfo) ) | 57 | if (read(fd, &psinfo, sizeof(psinfo)) != sizeof(psinfo)) { |
58 | { | 58 | close(fd); |
59 | close( fd ); | 59 | return (size_t)0L; /* Can't read? */ |
60 | return (size_t)0L; /* Can't read? */ | 60 | } |
61 | } | 61 | close(fd); |
62 | close( fd ); | 62 | return (size_t)(psinfo.pr_rssize * 1024L); |
63 | return (size_t)(psinfo.pr_rssize * 1024L); | ||
64 | 63 | ||
65 | #elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) | 64 | #elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) |
66 | /* BSD, Linux, and OSX -------------------------------------- */ | 65 | /* BSD, Linux, and OSX -------------------------------------- */ |
67 | struct rusage rusage; | 66 | struct rusage rusage; |
68 | getrusage( RUSAGE_SELF, &rusage ); | 67 | getrusage(RUSAGE_SELF, &rusage); |
69 | #if defined(__APPLE__) && defined(__MACH__) | 68 | #if defined(__APPLE__) && defined(__MACH__) |
70 | return (size_t)rusage.ru_maxrss; | 69 | return (size_t)rusage.ru_maxrss; |
71 | #else | 70 | #else |
72 | return (size_t)(rusage.ru_maxrss * 1024L); | 71 | return (size_t)(rusage.ru_maxrss * 1024L); |
73 | #endif | 72 | #endif |
74 | 73 | ||
75 | #else | 74 | #else |
76 | /* Unknown OS ----------------------------------------------- */ | 75 | /* Unknown OS ----------------------------------------------- */ |
77 | return (size_t)0L; /* Unsupported. */ | 76 | return (size_t)0L; /* Unsupported. */ |
78 | #endif | 77 | #endif |
79 | } | 78 | } |
80 | 79 | ||
81 | 80 | ||
82 | |||
83 | |||
84 | |||
85 | /** | 81 | /** |
86 | * Returns the current resident set size (physical memory use) measured | 82 | * Returns the current resident set size (physical memory use) measured |
87 | * in bytes, or zero if the value cannot be determined on this OS. | 83 | * in bytes, or zero if the value cannot be determined on this OS. |
88 | */ | 84 | */ |
89 | size_t getCurrentRSS( ) | 85 | size_t getCurrentRSS() |
90 | { | 86 | { |
91 | #if defined(_WIN32) | 87 | #if defined(_WIN32) |
92 | /* Windows -------------------------------------------------- */ | 88 | /* Windows -------------------------------------------------- */ |
93 | PROCESS_MEMORY_COUNTERS info; | 89 | PROCESS_MEMORY_COUNTERS info; |
94 | GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) ); | 90 | GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)); |
95 | return (size_t)info.WorkingSetSize; | 91 | return (size_t)info.WorkingSetSize; |
96 | 92 | ||
97 | #elif defined(__APPLE__) && defined(__MACH__) | 93 | #elif defined(__APPLE__) && defined(__MACH__) |
98 | /* OSX ------------------------------------------------------ */ | 94 | /* OSX ------------------------------------------------------ */ |
99 | struct mach_task_basic_info info; | 95 | struct mach_task_basic_info info; |
100 | mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT; | 96 | mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT; |
101 | if ( task_info( mach_task_self( ), MACH_TASK_BASIC_INFO, | 97 | if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &infoCount) != KERN_SUCCESS) |
102 | (task_info_t)&info, &infoCount ) != KERN_SUCCESS ) | 98 | return (size_t)0L; /* Can't access? */ |
103 | return (size_t)0L; /* Can't access? */ | 99 | return (size_t)info.resident_size; |
104 | return (size_t)info.resident_size; | ||
105 | 100 | ||
106 | #elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__) | 101 | #elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__) |
107 | /* Linux ---------------------------------------------------- */ | 102 | /* Linux ---------------------------------------------------- */ |
108 | long rss = 0L; | 103 | long rss = 0L; |
109 | FILE* fp = NULL; | 104 | FILE *fp = NULL; |
110 | if ( (fp = fopen( "/proc/self/statm", "r" )) == NULL ) | 105 | if ((fp = fopen("/proc/self/statm", "r")) == NULL) |
111 | return (size_t)0L; /* Can't open? */ | 106 | return (size_t)0L; /* Can't open? */ |
112 | if ( fscanf( fp, "%*s%ld", &rss ) != 1 ) | 107 | if (fscanf(fp, "%*s%ld", &rss) != 1) { |
113 | { | 108 | fclose(fp); |
114 | fclose( fp ); | 109 | return (size_t)0L; /* Can't read? */ |
115 | return (size_t)0L; /* Can't read? */ | 110 | } |
116 | } | 111 | fclose(fp); |
117 | fclose( fp ); | 112 | return (size_t)rss * (size_t)sysconf(_SC_PAGESIZE); |
118 | return (size_t)rss * (size_t)sysconf( _SC_PAGESIZE); | ||
119 | 113 | ||
120 | #else | 114 | #else |
121 | /* AIX, BSD, Solaris, and Unknown OS ------------------------ */ | 115 | /* AIX, BSD, Solaris, and Unknown OS ------------------------ */ |
122 | return (size_t)0L; /* Unsupported. */ | 116 | return (size_t)0L; /* Unsupported. */ |
123 | #endif | 117 | #endif |
124 | } | 118 | } |
diff --git a/tests/getrssusage.h b/tests/getrssusage.h index e47b14c..bc3d91e 100644 --- a/tests/getrssusage.h +++ b/tests/getrssusage.h | |||
@@ -22,7 +22,7 @@ | |||
22 | #if defined(__APPLE__) && defined(__MACH__) | 22 | #if defined(__APPLE__) && defined(__MACH__) |
23 | #include <mach/mach.h> | 23 | #include <mach/mach.h> |
24 | 24 | ||
25 | #elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__))) | 25 | #elif(defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__))) |
26 | #include <fcntl.h> | 26 | #include <fcntl.h> |
27 | #include <procfs.h> | 27 | #include <procfs.h> |
28 | 28 | ||
diff --git a/tests/indextest.cpp b/tests/indextest.cpp index 1676ecb..fa3ace4 100644 --- a/tests/indextest.cpp +++ b/tests/indextest.cpp | |||
@@ -29,42 +29,29 @@ private slots: | |||
29 | void testIndex() | 29 | void testIndex() |
30 | { | 30 | { |
31 | Index index("./testindex", "org.kde.dummy.testindex", Sink::Storage::ReadWrite); | 31 | Index index("./testindex", "org.kde.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"); |
35 | index.add("keyFoo", "value3"); | 35 | index.add("keyFoo", "value3"); |
36 | 36 | ||
37 | { | 37 | { |
38 | QList<QByteArray> values; | 38 | QList<QByteArray> values; |
39 | index.lookup(QByteArray("key"), [&values](const QByteArray &value) { | 39 | index.lookup(QByteArray("key"), [&values](const QByteArray &value) { values << value; }, [](const Index::Error &error) { qWarning() << "Error: "; }); |
40 | values << value; | ||
41 | }, | ||
42 | [](const Index::Error &error){ qWarning() << "Error: "; }); | ||
43 | QCOMPARE(values.size(), 1); | 40 | QCOMPARE(values.size(), 1); |
44 | } | 41 | } |
45 | { | 42 | { |
46 | QList<QByteArray> values; | 43 | QList<QByteArray> values; |
47 | index.lookup(QByteArray("keyFoo"), [&values](const QByteArray &value) { | 44 | index.lookup(QByteArray("keyFoo"), [&values](const QByteArray &value) { values << value; }, [](const Index::Error &error) { qWarning() << "Error: "; }); |
48 | values << value; | ||
49 | }, | ||
50 | [](const Index::Error &error){ qWarning() << "Error: "; }); | ||
51 | QCOMPARE(values.size(), 2); | 45 | QCOMPARE(values.size(), 2); |
52 | } | 46 | } |
53 | { | 47 | { |
54 | QList<QByteArray> values; | 48 | QList<QByteArray> values; |
55 | index.lookup(QByteArray("key3"), [&values](const QByteArray &value) { | 49 | index.lookup(QByteArray("key3"), [&values](const QByteArray &value) { values << value; }, [](const Index::Error &error) { qWarning() << "Error: "; }); |
56 | values << value; | ||
57 | }, | ||
58 | [](const Index::Error &error){ qWarning() << "Error: "; }); | ||
59 | QCOMPARE(values.size(), 0); | 50 | QCOMPARE(values.size(), 0); |
60 | } | 51 | } |
61 | { | 52 | { |
62 | QList<QByteArray> values; | 53 | QList<QByteArray> values; |
63 | index.lookup(QByteArray("key"), [&values](const QByteArray &value) { | 54 | index.lookup(QByteArray("key"), [&values](const QByteArray &value) { values << value; }, [](const Index::Error &error) { qWarning() << "Error: "; }, true); |
64 | values << value; | ||
65 | }, | ||
66 | [](const Index::Error &error){ qWarning() << "Error: "; }, | ||
67 | true); | ||
68 | QCOMPARE(values.size(), 3); | 55 | QCOMPARE(values.size(), 3); |
69 | } | 56 | } |
70 | } | 57 | } |
diff --git a/tests/inspectiontest.cpp b/tests/inspectiontest.cpp index cdf62e6..38bf23d 100644 --- a/tests/inspectiontest.cpp +++ b/tests/inspectiontest.cpp | |||
@@ -41,7 +41,7 @@ private slots: | |||
41 | 41 | ||
42 | Mail mail(QByteArray("org.kde.dummy.instance1"), QByteArray("identifier"), 0, QSharedPointer<MemoryBufferAdaptor::MemoryBufferAdaptor>::create()); | 42 | Mail mail(QByteArray("org.kde.dummy.instance1"), QByteArray("identifier"), 0, QSharedPointer<MemoryBufferAdaptor::MemoryBufferAdaptor>::create()); |
43 | 43 | ||
44 | //testInspection is a magic property that the dummyresource supports | 44 | // testInspection is a magic property that the dummyresource supports |
45 | auto inspectionCommand = ResourceControl::Inspection::PropertyInspection(mail, "testInspection", success); | 45 | auto inspectionCommand = ResourceControl::Inspection::PropertyInspection(mail, "testInspection", success); |
46 | auto result = ResourceControl::inspect<Mail>(inspectionCommand).exec(); | 46 | auto result = ResourceControl::inspect<Mail>(inspectionCommand).exec(); |
47 | result.waitForFinished(); | 47 | result.waitForFinished(); |
diff --git a/tests/maildirresourcetest.cpp b/tests/maildirresourcetest.cpp index d5f7f95..b5c1c3c 100644 --- a/tests/maildirresourcetest.cpp +++ b/tests/maildirresourcetest.cpp | |||
@@ -12,8 +12,7 @@ | |||
12 | #include "pipeline.h" | 12 | #include "pipeline.h" |
13 | #include "log.h" | 13 | #include "log.h" |
14 | 14 | ||
15 | static bool copyRecursively(const QString &srcFilePath, | 15 | static bool copyRecursively(const QString &srcFilePath, const QString &tgtFilePath) |
16 | const QString &tgtFilePath) | ||
17 | { | 16 | { |
18 | QFileInfo srcFileInfo(srcFilePath); | 17 | QFileInfo srcFileInfo(srcFilePath); |
19 | if (srcFileInfo.isDir()) { | 18 | if (srcFileInfo.isDir()) { |
@@ -26,10 +25,8 @@ static bool copyRecursively(const QString &srcFilePath, | |||
26 | QDir sourceDir(srcFilePath); | 25 | QDir sourceDir(srcFilePath); |
27 | QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System); | 26 | QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System); |
28 | foreach (const QString &fileName, fileNames) { | 27 | foreach (const QString &fileName, fileNames) { |
29 | const QString newSrcFilePath | 28 | const QString newSrcFilePath = srcFilePath + QLatin1Char('/') + fileName; |
30 | = srcFilePath + QLatin1Char('/') + fileName; | 29 | const QString newTgtFilePath = tgtFilePath + QLatin1Char('/') + fileName; |
31 | const QString newTgtFilePath | ||
32 | = tgtFilePath + QLatin1Char('/') + fileName; | ||
33 | if (!copyRecursively(newSrcFilePath, newTgtFilePath)) | 30 | if (!copyRecursively(newSrcFilePath, newTgtFilePath)) |
34 | return false; | 31 | return false; |
35 | } | 32 | } |
@@ -44,7 +41,7 @@ static bool copyRecursively(const QString &srcFilePath, | |||
44 | 41 | ||
45 | /** | 42 | /** |
46 | * Test of complete system using the maildir resource. | 43 | * Test of complete system using the maildir resource. |
47 | * | 44 | * |
48 | * This test requires the maildir resource installed. | 45 | * This test requires the maildir resource installed. |
49 | */ | 46 | */ |
50 | class MaildirResourceTest : public QObject | 47 | class MaildirResourceTest : public QObject |
@@ -89,7 +86,7 @@ private slots: | |||
89 | Sink::Query query; | 86 | Sink::Query query; |
90 | query.resources << "org.kde.maildir.instance1"; | 87 | query.resources << "org.kde.maildir.instance1"; |
91 | 88 | ||
92 | //Ensure all local data is processed | 89 | // Ensure all local data is processed |
93 | Sink::Store::synchronize(query).exec().waitForFinished(); | 90 | Sink::Store::synchronize(query).exec().waitForFinished(); |
94 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 91 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
95 | 92 | ||
@@ -104,7 +101,7 @@ private slots: | |||
104 | query.resources << "org.kde.maildir.instance1"; | 101 | query.resources << "org.kde.maildir.instance1"; |
105 | query.parentProperty = "parent"; | 102 | query.parentProperty = "parent"; |
106 | 103 | ||
107 | //Ensure all local data is processed | 104 | // Ensure all local data is processed |
108 | Sink::Store::synchronize(query).exec().waitForFinished(); | 105 | Sink::Store::synchronize(query).exec().waitForFinished(); |
109 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 106 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
110 | 107 | ||
@@ -121,23 +118,18 @@ private slots: | |||
121 | { | 118 | { |
122 | using namespace Sink; | 119 | using namespace Sink; |
123 | using namespace Sink::ApplicationDomain; | 120 | using namespace Sink::ApplicationDomain; |
124 | //Ensure all local data is processed | 121 | // Ensure all local data is processed |
125 | auto query = Query::ResourceFilter("org.kde.maildir.instance1"); | 122 | auto query = Query::ResourceFilter("org.kde.maildir.instance1"); |
126 | Store::synchronize(query).exec().waitForFinished(); | 123 | Store::synchronize(query).exec().waitForFinished(); |
127 | ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 124 | ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
128 | auto result = Store::fetchOne<Folder>( | 125 | auto result = Store::fetchOne<Folder>(Query::ResourceFilter("org.kde.maildir.instance1") + Query::RequestedProperties(QByteArrayList() << "name")) |
129 | Query::ResourceFilter("org.kde.maildir.instance1") + Query::RequestedProperties(QByteArrayList() << "name") | 126 | .then<QList<Mail::Ptr>, Folder>([](const Folder &folder) { |
130 | ) | 127 | Trace() << "Found a folder" << folder.identifier(); |
131 | .then<QList<Mail::Ptr>, Folder>([](const Folder &folder) { | 128 | return Store::fetchAll<Mail>(Query::PropertyFilter("folder", folder) + Query::RequestedProperties(QByteArrayList() << "folder" |
132 | Trace() << "Found a folder" << folder.identifier(); | 129 | << "subject")); |
133 | return Store::fetchAll<Mail>( | 130 | }) |
134 | Query::PropertyFilter("folder", folder) + Query::RequestedProperties(QByteArrayList() << "folder" << "subject") | 131 | .then<void, QList<Mail::Ptr>>([](const QList<Mail::Ptr> &mails) { QVERIFY(mails.size() >= 1); }) |
135 | ); | 132 | .exec(); |
136 | }) | ||
137 | .then<void, QList<Mail::Ptr> >([](const QList<Mail::Ptr> &mails) { | ||
138 | QVERIFY(mails.size() >= 1); | ||
139 | }) | ||
140 | .exec(); | ||
141 | result.waitForFinished(); | 133 | result.waitForFinished(); |
142 | QVERIFY(!result.errorCode()); | 134 | QVERIFY(!result.errorCode()); |
143 | } | 135 | } |
@@ -146,9 +138,12 @@ private slots: | |||
146 | { | 138 | { |
147 | Sink::Query query; | 139 | Sink::Query query; |
148 | query.resources << "org.kde.maildir.instance1"; | 140 | query.resources << "org.kde.maildir.instance1"; |
149 | query.requestedProperties << "folder" << "subject" << "mimeMessage" << "date"; | 141 | query.requestedProperties << "folder" |
142 | << "subject" | ||
143 | << "mimeMessage" | ||
144 | << "date"; | ||
150 | 145 | ||
151 | //Ensure all local data is processed | 146 | // Ensure all local data is processed |
152 | Sink::Store::synchronize(query).exec().waitForFinished(); | 147 | Sink::Store::synchronize(query).exec().waitForFinished(); |
153 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 148 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
154 | 149 | ||
@@ -171,7 +166,7 @@ private slots: | |||
171 | query.resources << "org.kde.maildir.instance1"; | 166 | query.resources << "org.kde.maildir.instance1"; |
172 | query.requestedProperties << "name"; | 167 | query.requestedProperties << "name"; |
173 | 168 | ||
174 | //Ensure all local data is processed | 169 | // Ensure all local data is processed |
175 | Sink::Store::synchronize(query).exec().waitForFinished(); | 170 | Sink::Store::synchronize(query).exec().waitForFinished(); |
176 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 171 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
177 | 172 | ||
@@ -179,7 +174,7 @@ private slots: | |||
179 | QDir dir(targetPath); | 174 | QDir dir(targetPath); |
180 | QVERIFY(dir.rename("inbox", "newbox")); | 175 | QVERIFY(dir.rename("inbox", "newbox")); |
181 | 176 | ||
182 | //Ensure all local data is processed | 177 | // Ensure all local data is processed |
183 | Sink::Store::synchronize(query).exec().waitForFinished(); | 178 | Sink::Store::synchronize(query).exec().waitForFinished(); |
184 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 179 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
185 | 180 | ||
@@ -193,13 +188,14 @@ private slots: | |||
193 | { | 188 | { |
194 | Sink::Query query; | 189 | Sink::Query query; |
195 | query.resources << "org.kde.maildir.instance1"; | 190 | query.resources << "org.kde.maildir.instance1"; |
196 | query.requestedProperties << "folder" << "subject"; | 191 | query.requestedProperties << "folder" |
192 | << "subject"; | ||
197 | 193 | ||
198 | //Ensure all local data is processed | 194 | // Ensure all local data is processed |
199 | Sink::Store::synchronize(query).exec().waitForFinished(); | 195 | Sink::Store::synchronize(query).exec().waitForFinished(); |
200 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 196 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
201 | 197 | ||
202 | //Ensure all local data is processed | 198 | // Ensure all local data is processed |
203 | Sink::Store::synchronize(query).exec().waitForFinished(); | 199 | Sink::Store::synchronize(query).exec().waitForFinished(); |
204 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 200 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
205 | 201 | ||
@@ -212,9 +208,10 @@ private slots: | |||
212 | { | 208 | { |
213 | Sink::Query query; | 209 | Sink::Query query; |
214 | query.resources << "org.kde.maildir.instance1"; | 210 | query.resources << "org.kde.maildir.instance1"; |
215 | query.requestedProperties << "folder" << "subject"; | 211 | query.requestedProperties << "folder" |
212 | << "subject"; | ||
216 | 213 | ||
217 | //Ensure all local data is processed | 214 | // Ensure all local data is processed |
218 | Sink::Store::synchronize(query).exec().waitForFinished(); | 215 | Sink::Store::synchronize(query).exec().waitForFinished(); |
219 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 216 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
220 | 217 | ||
@@ -222,7 +219,7 @@ private slots: | |||
222 | QFile file(targetPath); | 219 | QFile file(targetPath); |
223 | QVERIFY(file.remove()); | 220 | QVERIFY(file.remove()); |
224 | 221 | ||
225 | //Ensure all local data is processed | 222 | // Ensure all local data is processed |
226 | Sink::Store::synchronize(query).exec().waitForFinished(); | 223 | Sink::Store::synchronize(query).exec().waitForFinished(); |
227 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 224 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
228 | 225 | ||
@@ -236,7 +233,7 @@ private slots: | |||
236 | Sink::Query query; | 233 | Sink::Query query; |
237 | query.resources << "org.kde.maildir.instance1"; | 234 | query.resources << "org.kde.maildir.instance1"; |
238 | 235 | ||
239 | //Ensure all local data is processed | 236 | // Ensure all local data is processed |
240 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 237 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
241 | 238 | ||
242 | Sink::ApplicationDomain::Folder folder("org.kde.maildir.instance1"); | 239 | Sink::ApplicationDomain::Folder folder("org.kde.maildir.instance1"); |
@@ -244,7 +241,7 @@ private slots: | |||
244 | 241 | ||
245 | Sink::Store::create(folder).exec().waitForFinished(); | 242 | Sink::Store::create(folder).exec().waitForFinished(); |
246 | 243 | ||
247 | //Ensure all local data is processed | 244 | // Ensure all local data is processed |
248 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 245 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
249 | 246 | ||
250 | auto targetPath = tempDir.path() + "/maildir1/testCreateFolder"; | 247 | auto targetPath = tempDir.path() + "/maildir1/testCreateFolder"; |
@@ -284,16 +281,16 @@ private slots: | |||
284 | Sink::Query query; | 281 | Sink::Query query; |
285 | query.resources << "org.kde.maildir.instance1"; | 282 | query.resources << "org.kde.maildir.instance1"; |
286 | 283 | ||
287 | //Ensure all local data is processed | 284 | // Ensure all local data is processed |
288 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 285 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
289 | 286 | ||
290 | Sink::ApplicationDomain::Mail mail("org.kde.maildir.instance1"); | 287 | Sink::ApplicationDomain::Mail mail("org.kde.maildir.instance1"); |
291 | mail.setProperty("name", "testCreateMail"); | 288 | mail.setProperty("name", "testCreateMail"); |
292 | //FIXME instead of properties, ensure the mimeMessage property is used and the file is moved as expected | 289 | // FIXME instead of properties, ensure the mimeMessage property is used and the file is moved as expected |
293 | 290 | ||
294 | Sink::Store::create(mail).exec().waitForFinished(); | 291 | Sink::Store::create(mail).exec().waitForFinished(); |
295 | 292 | ||
296 | //Ensure all local data is processed | 293 | // Ensure all local data is processed |
297 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 294 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
298 | 295 | ||
299 | auto targetPath = tempDir.path() + "/maildir1/new"; | 296 | auto targetPath = tempDir.path() + "/maildir1/new"; |
@@ -312,25 +309,23 @@ private slots: | |||
312 | ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 309 | ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
313 | 310 | ||
314 | auto result = Store::fetchOne<Folder>( | 311 | auto result = Store::fetchOne<Folder>( |
315 | Query::ResourceFilter("org.kde.maildir.instance1") + Query::PropertyFilter("name", "maildir1") + Query::RequestedProperties(QByteArrayList() << "name") | 312 | Query::ResourceFilter("org.kde.maildir.instance1") + Query::PropertyFilter("name", "maildir1") + Query::RequestedProperties(QByteArrayList() << "name")) |
316 | ) | 313 | .then<void, KAsync::Job<void>, Folder>([query](const Folder &folder) { |
317 | .then<void, KAsync::Job<void>, Folder>([query](const Folder &folder) { | 314 | return Store::fetchAll<Mail>(Query::PropertyFilter("folder", folder) + Query::RequestedProperties(QByteArrayList() << "folder" |
318 | return Store::fetchAll<Mail>( | 315 | << "subject")) |
319 | Query::PropertyFilter("folder", folder) + Query::RequestedProperties(QByteArrayList() << "folder" << "subject") | 316 | .then<void, KAsync::Job<void>, QList<Mail::Ptr>>([query](const QList<Mail::Ptr> &mails) { |
320 | ) | 317 | // Can't use QCOMPARE because it tries to return FIXME Implement ASYNCCOMPARE |
321 | .then<void, KAsync::Job<void>, QList<Mail::Ptr> >([query](const QList<Mail::Ptr> &mails) { | 318 | if (mails.size() != 1) { |
322 | //Can't use QCOMPARE because it tries to return FIXME Implement ASYNCCOMPARE | 319 | return KAsync::error<void>(1, "Wrong number of mails."); |
323 | if (mails.size() != 1) { | 320 | } |
324 | return KAsync::error<void>(1, "Wrong number of mails."); | 321 | auto mail = mails.first(); |
325 | } | 322 | |
326 | auto mail = mails.first(); | 323 | return Store::remove(*mail) |
327 | 324 | .then(ResourceControl::flushReplayQueue(query.resources)) // The change needs to be replayed already | |
328 | return Store::remove(*mail) | 325 | .then(ResourceControl::inspect<Mail>(ResourceControl::Inspection::ExistenceInspection(*mail, false))); |
329 | .then(ResourceControl::flushReplayQueue(query.resources)) //The change needs to be replayed already | 326 | }); |
330 | .then(ResourceControl::inspect<Mail>(ResourceControl::Inspection::ExistenceInspection(*mail, false))); | 327 | }) |
331 | }); | 328 | .exec(); |
332 | }) | ||
333 | .exec(); | ||
334 | result.waitForFinished(); | 329 | result.waitForFinished(); |
335 | QVERIFY(!result.errorCode()); | 330 | QVERIFY(!result.errorCode()); |
336 | } | 331 | } |
@@ -347,61 +342,61 @@ private slots: | |||
347 | Folder f; | 342 | Folder f; |
348 | 343 | ||
349 | auto result = Store::fetchOne<Folder>( | 344 | auto result = Store::fetchOne<Folder>( |
350 | Query::ResourceFilter("org.kde.maildir.instance1") + Query::PropertyFilter("name", "maildir1") + Query::RequestedProperties(QByteArrayList() << "name") | 345 | Query::ResourceFilter("org.kde.maildir.instance1") + Query::PropertyFilter("name", "maildir1") + Query::RequestedProperties(QByteArrayList() << "name")) |
351 | ) | 346 | .then<void, KAsync::Job<void>, Folder>([query, &f](const Folder &folder) { |
352 | .then<void, KAsync::Job<void>, Folder>([query, &f](const Folder &folder) { | 347 | f = folder; |
353 | f = folder; | 348 | return Store::fetchAll<Mail>(Query::ResourceFilter("org.kde.maildir.instance1") + Query::PropertyFilter("folder", folder) + |
354 | return Store::fetchAll<Mail>( | 349 | Query::RequestedProperties(QByteArrayList() << "folder" |
355 | Query::ResourceFilter("org.kde.maildir.instance1") + Query::PropertyFilter("folder", folder) + Query::RequestedProperties(QByteArrayList() << "folder" << "subject") | 350 | << "subject")) |
356 | ) | 351 | .then<void, KAsync::Job<void>, QList<Mail::Ptr>>([query](const QList<Mail::Ptr> &mails) { |
357 | .then<void, KAsync::Job<void>, QList<Mail::Ptr> >([query](const QList<Mail::Ptr> &mails) { | 352 | // Can't use QCOMPARE because it tries to return FIXME Implement ASYNCCOMPARE |
358 | //Can't use QCOMPARE because it tries to return FIXME Implement ASYNCCOMPARE | 353 | if (mails.size() != 1) { |
359 | if (mails.size() != 1) { | 354 | return KAsync::error<void>(1, "Wrong number of mails."); |
360 | return KAsync::error<void>(1, "Wrong number of mails."); | 355 | } |
361 | } | 356 | auto mail = mails.first(); |
362 | auto mail = mails.first(); | 357 | mail->setProperty("unread", true); |
363 | mail->setProperty("unread", true); | 358 | return Store::modify(*mail) |
364 | return Store::modify(*mail) | 359 | .then<void>(ResourceControl::flushReplayQueue(query.resources)) // The change needs to be replayed already |
365 | .then<void>(ResourceControl::flushReplayQueue(query.resources)) //The change needs to be replayed already | 360 | .then(ResourceControl::inspect<Mail>(ResourceControl::Inspection::PropertyInspection(*mail, "unread", true))) |
366 | .then(ResourceControl::inspect<Mail>(ResourceControl::Inspection::PropertyInspection(*mail, "unread", true))) | 361 | .then(ResourceControl::inspect<Mail>(ResourceControl::Inspection::PropertyInspection(*mail, "subject", mail->getProperty("subject")))); |
367 | .then(ResourceControl::inspect<Mail>(ResourceControl::Inspection::PropertyInspection(*mail, "subject", mail->getProperty("subject")))); | 362 | }); |
368 | }); | 363 | }) |
369 | }) | 364 | .exec(); |
370 | .exec(); | ||
371 | result.waitForFinished(); | 365 | result.waitForFinished(); |
372 | QVERIFY(!result.errorCode()); | 366 | QVERIFY(!result.errorCode()); |
373 | 367 | ||
374 | //Verify that we can still query for all relevant information | 368 | // Verify that we can still query for all relevant information |
375 | auto result2 = Store::fetchAll<Mail>( | 369 | auto result2 = Store::fetchAll<Mail>( |
376 | Query::ResourceFilter("org.kde.maildir.instance1") + Query::PropertyFilter("folder", f) + Query::RequestedProperties(QByteArrayList() << "folder" << "subject" << "mimeMessage" << "unread") | 370 | Query::ResourceFilter("org.kde.maildir.instance1") + Query::PropertyFilter("folder", f) + Query::RequestedProperties(QByteArrayList() << "folder" |
377 | ) | 371 | << "subject" |
378 | .then<void, KAsync::Job<void>, QList<Mail::Ptr> >([](const QList<Mail::Ptr> &mails) { | 372 | << "mimeMessage" |
379 | //Can't use QCOMPARE because it tries to return FIXME Implement ASYNCCOMPARE | 373 | << "unread")) |
380 | if (mails.size() != 1) { | 374 | .then<void, KAsync::Job<void>, QList<Mail::Ptr>>([](const QList<Mail::Ptr> &mails) { |
381 | qWarning() << "Wrong number of mails"; | 375 | // Can't use QCOMPARE because it tries to return FIXME Implement ASYNCCOMPARE |
382 | return KAsync::error<void>(1, "Wrong number of mails."); | 376 | if (mails.size() != 1) { |
383 | } | 377 | qWarning() << "Wrong number of mails"; |
384 | auto mail = mails.first(); | 378 | return KAsync::error<void>(1, "Wrong number of mails."); |
385 | if (mail->getProperty("subject").toString().isEmpty()) { | 379 | } |
386 | qWarning() << "Wrong subject"; | 380 | auto mail = mails.first(); |
387 | return KAsync::error<void>(1, "Wrong subject."); | 381 | if (mail->getProperty("subject").toString().isEmpty()) { |
388 | } | 382 | qWarning() << "Wrong subject"; |
389 | if (mail->getProperty("unread").toBool() != true) { | 383 | return KAsync::error<void>(1, "Wrong subject."); |
390 | qWarning() << "Not unread"; | 384 | } |
391 | return KAsync::error<void>(1, "Not unread."); | 385 | if (mail->getProperty("unread").toBool() != true) { |
392 | } | 386 | qWarning() << "Not unread"; |
393 | QFileInfo info(mail->getProperty("mimeMessage").toString()); | 387 | return KAsync::error<void>(1, "Not unread."); |
394 | if (!info.exists()) { | 388 | } |
395 | qWarning() << "Wrong subject"; | 389 | QFileInfo info(mail->getProperty("mimeMessage").toString()); |
396 | return KAsync::error<void>(1, "Can't find mime message."); | 390 | if (!info.exists()) { |
397 | } | 391 | qWarning() << "Wrong subject"; |
398 | return KAsync::null<void>(); | 392 | return KAsync::error<void>(1, "Can't find mime message."); |
399 | }) | 393 | } |
400 | .exec(); | 394 | return KAsync::null<void>(); |
395 | }) | ||
396 | .exec(); | ||
401 | result2.waitForFinished(); | 397 | result2.waitForFinished(); |
402 | QVERIFY(!result2.errorCode()); | 398 | QVERIFY(!result2.errorCode()); |
403 | } | 399 | } |
404 | |||
405 | }; | 400 | }; |
406 | 401 | ||
407 | QTEST_MAIN(MaildirResourceTest) | 402 | QTEST_MAIN(MaildirResourceTest) |
diff --git a/tests/maildirsyncbenchmark.cpp b/tests/maildirsyncbenchmark.cpp index 7904a82..06c5ab1 100644 --- a/tests/maildirsyncbenchmark.cpp +++ b/tests/maildirsyncbenchmark.cpp | |||
@@ -16,8 +16,7 @@ | |||
16 | #include "log.h" | 16 | #include "log.h" |
17 | 17 | ||
18 | 18 | ||
19 | static bool copyRecursively(const QString &srcFilePath, | 19 | static bool copyRecursively(const QString &srcFilePath, const QString &tgtFilePath) |
20 | const QString &tgtFilePath) | ||
21 | { | 20 | { |
22 | QFileInfo srcFileInfo(srcFilePath); | 21 | QFileInfo srcFileInfo(srcFilePath); |
23 | if (srcFileInfo.isDir()) { | 22 | if (srcFileInfo.isDir()) { |
@@ -30,10 +29,8 @@ static bool copyRecursively(const QString &srcFilePath, | |||
30 | QDir sourceDir(srcFilePath); | 29 | QDir sourceDir(srcFilePath); |
31 | QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System); | 30 | QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System); |
32 | foreach (const QString &fileName, fileNames) { | 31 | foreach (const QString &fileName, fileNames) { |
33 | const QString newSrcFilePath | 32 | const QString newSrcFilePath = srcFilePath + QLatin1Char('/') + fileName; |
34 | = srcFilePath + QLatin1Char('/') + fileName; | 33 | const QString newTgtFilePath = tgtFilePath + QLatin1Char('/') + fileName; |
35 | const QString newTgtFilePath | ||
36 | = tgtFilePath + QLatin1Char('/') + fileName; | ||
37 | if (!copyRecursively(newSrcFilePath, newTgtFilePath)) | 34 | if (!copyRecursively(newSrcFilePath, newTgtFilePath)) |
38 | return false; | 35 | return false; |
39 | } | 36 | } |
@@ -48,7 +45,7 @@ static bool copyRecursively(const QString &srcFilePath, | |||
48 | 45 | ||
49 | /** | 46 | /** |
50 | * Test of complete system using the maildir resource. | 47 | * Test of complete system using the maildir resource. |
51 | * | 48 | * |
52 | * This test requires the maildir resource installed. | 49 | * This test requires the maildir resource installed. |
53 | */ | 50 | */ |
54 | class MaildirSyncBenchmark : public QObject | 51 | class MaildirSyncBenchmark : public QObject |
@@ -102,7 +99,6 @@ private slots: | |||
102 | // row.setValue("totalTime", allProcessedTime); | 99 | // row.setValue("totalTime", allProcessedTime); |
103 | // dataset.insertRow(row); | 100 | // dataset.insertRow(row); |
104 | // HAWD::Formatter::print(dataset); | 101 | // HAWD::Formatter::print(dataset); |
105 | |||
106 | } | 102 | } |
107 | }; | 103 | }; |
108 | 104 | ||
diff --git a/tests/mailquerybenchmark.cpp b/tests/mailquerybenchmark.cpp index ea919ac..6b93863 100644 --- a/tests/mailquerybenchmark.cpp +++ b/tests/mailquerybenchmark.cpp | |||
@@ -61,9 +61,9 @@ class MailQueryBenchmark : public QObject | |||
61 | auto pipeline = QSharedPointer<Sink::Pipeline>::create(resourceIdentifier); | 61 | auto pipeline = QSharedPointer<Sink::Pipeline>::create(resourceIdentifier); |
62 | 62 | ||
63 | auto mailFactory = QSharedPointer<TestMailAdaptorFactory>::create(); | 63 | auto mailFactory = QSharedPointer<TestMailAdaptorFactory>::create(); |
64 | auto indexer = QSharedPointer<DefaultIndexUpdater<Sink::ApplicationDomain::Mail> >::create(); | 64 | auto indexer = QSharedPointer<DefaultIndexUpdater<Sink::ApplicationDomain::Mail>>::create(); |
65 | 65 | ||
66 | pipeline->setPreprocessors("mail", QVector<Sink::Preprocessor*>() << indexer.data()); | 66 | pipeline->setPreprocessors("mail", QVector<Sink::Preprocessor *>() << indexer.data()); |
67 | pipeline->setAdaptorFactory("mail", mailFactory); | 67 | pipeline->setAdaptorFactory("mail", mailFactory); |
68 | 68 | ||
69 | auto domainTypeAdaptorFactory = QSharedPointer<TestMailAdaptorFactory>::create(); | 69 | auto domainTypeAdaptorFactory = QSharedPointer<TestMailAdaptorFactory>::create(); |
@@ -88,11 +88,11 @@ class MailQueryBenchmark : public QObject | |||
88 | const auto startingRss = getCurrentRSS(); | 88 | const auto startingRss = getCurrentRSS(); |
89 | 89 | ||
90 | 90 | ||
91 | //Benchmark | 91 | // Benchmark |
92 | QTime time; | 92 | QTime time; |
93 | time.start(); | 93 | time.start(); |
94 | 94 | ||
95 | auto resultSet = QSharedPointer<Sink::ResultProvider<Sink::ApplicationDomain::Mail::Ptr> >::create(); | 95 | auto resultSet = QSharedPointer<Sink::ResultProvider<Sink::ApplicationDomain::Mail::Ptr>>::create(); |
96 | auto resourceAccess = QSharedPointer<TestResourceAccess>::create(); | 96 | auto resourceAccess = QSharedPointer<TestResourceAccess>::create(); |
97 | TestMailResourceFacade facade(resourceIdentifier, resourceAccess); | 97 | TestMailResourceFacade facade(resourceIdentifier, resourceAccess); |
98 | 98 | ||
@@ -100,13 +100,9 @@ class MailQueryBenchmark : public QObject | |||
100 | ret.first.exec().waitForFinished(); | 100 | ret.first.exec().waitForFinished(); |
101 | auto emitter = ret.second; | 101 | auto emitter = ret.second; |
102 | QList<Sink::ApplicationDomain::Mail::Ptr> list; | 102 | QList<Sink::ApplicationDomain::Mail::Ptr> list; |
103 | emitter->onAdded([&list](const Sink::ApplicationDomain::Mail::Ptr &mail) { | 103 | emitter->onAdded([&list](const Sink::ApplicationDomain::Mail::Ptr &mail) { list << mail; }); |
104 | list << mail; | ||
105 | }); | ||
106 | bool done = false; | 104 | bool done = false; |
107 | emitter->onInitialResultSetComplete([&done](const Sink::ApplicationDomain::Mail::Ptr &mail) { | 105 | emitter->onInitialResultSetComplete([&done](const Sink::ApplicationDomain::Mail::Ptr &mail) { done = true; }); |
108 | done = true; | ||
109 | }); | ||
110 | emitter->fetch(Sink::ApplicationDomain::Mail::Ptr()); | 106 | emitter->fetch(Sink::ApplicationDomain::Mail::Ptr()); |
111 | QTRY_VERIFY(done); | 107 | QTRY_VERIFY(done); |
112 | QCOMPARE(list.size(), query.limit); | 108 | QCOMPARE(list.size(), query.limit); |
@@ -115,32 +111,32 @@ class MailQueryBenchmark : public QObject | |||
115 | 111 | ||
116 | const auto finalRss = getCurrentRSS(); | 112 | const auto finalRss = getCurrentRSS(); |
117 | const auto rssGrowth = finalRss - startingRss; | 113 | const auto rssGrowth = finalRss - startingRss; |
118 | //Since the database is memory mapped it is attributted to the resident set size. | 114 | // Since the database is memory mapped it is attributted to the resident set size. |
119 | const auto rssWithoutDb = finalRss - Sink::Storage(Sink::storageLocation(), resourceIdentifier, Sink::Storage::ReadWrite).diskUsage(); | 115 | const auto rssWithoutDb = finalRss - Sink::Storage(Sink::storageLocation(), resourceIdentifier, Sink::Storage::ReadWrite).diskUsage(); |
120 | const auto peakRss = getPeakRSS(); | 116 | const auto peakRss = getPeakRSS(); |
121 | //How much peak deviates from final rss in percent (should be around 0) | 117 | // How much peak deviates from final rss in percent (should be around 0) |
122 | const auto percentageRssError = static_cast<double>(peakRss - finalRss)*100.0/static_cast<double>(finalRss); | 118 | const auto percentageRssError = static_cast<double>(peakRss - finalRss) * 100.0 / static_cast<double>(finalRss); |
123 | auto rssGrowthPerEntity = rssGrowth/count; | 119 | auto rssGrowthPerEntity = rssGrowth / count; |
124 | 120 | ||
125 | std::cout << "Loaded " << list.size() << " results." << std::endl; | 121 | std::cout << "Loaded " << list.size() << " results." << std::endl; |
126 | std::cout << "The query took [ms]: " << elapsed << std::endl; | 122 | std::cout << "The query took [ms]: " << elapsed << std::endl; |
127 | std::cout << "Current Rss usage [kb]: " << finalRss/1024 << std::endl; | 123 | std::cout << "Current Rss usage [kb]: " << finalRss / 1024 << std::endl; |
128 | std::cout << "Peak Rss usage [kb]: " << peakRss/1024 << std::endl; | 124 | std::cout << "Peak Rss usage [kb]: " << peakRss / 1024 << std::endl; |
129 | std::cout << "Rss growth [kb]: " << rssGrowth/1024 << std::endl; | 125 | std::cout << "Rss growth [kb]: " << rssGrowth / 1024 << std::endl; |
130 | std::cout << "Rss growth per entity [byte]: " << rssGrowthPerEntity << std::endl; | 126 | std::cout << "Rss growth per entity [byte]: " << rssGrowthPerEntity << std::endl; |
131 | std::cout << "Rss without db [kb]: " << rssWithoutDb/1024 << std::endl; | 127 | std::cout << "Rss without db [kb]: " << rssWithoutDb / 1024 << std::endl; |
132 | std::cout << "Percentage error: " << percentageRssError << std::endl; | 128 | std::cout << "Percentage error: " << percentageRssError << std::endl; |
133 | 129 | ||
134 | HAWD::Dataset dataset("mail_query", mHawdState); | 130 | HAWD::Dataset dataset("mail_query", mHawdState); |
135 | HAWD::Dataset::Row row = dataset.row(); | 131 | HAWD::Dataset::Row row = dataset.row(); |
136 | row.setValue("rows", list.size()); | 132 | row.setValue("rows", list.size()); |
137 | row.setValue("queryResultPerMs", (qreal)list.size()/elapsed); | 133 | row.setValue("queryResultPerMs", (qreal)list.size() / elapsed); |
138 | dataset.insertRow(row); | 134 | dataset.insertRow(row); |
139 | HAWD::Formatter::print(dataset); | 135 | HAWD::Formatter::print(dataset); |
140 | 136 | ||
141 | QVERIFY(percentageRssError < 10); | 137 | QVERIFY(percentageRssError < 10); |
142 | //TODO This is much more than it should it seems, although adding the attachment results in pretty exactly a 1k increase, | 138 | // TODO This is much more than it should it seems, although adding the attachment results in pretty exactly a 1k increase, |
143 | //so it doesn't look like that memory is being duplicated. | 139 | // so it doesn't look like that memory is being duplicated. |
144 | QVERIFY(rssGrowthPerEntity < 3300); | 140 | QVERIFY(rssGrowthPerEntity < 3300); |
145 | 141 | ||
146 | // Print memory layout, RSS is what is in memory | 142 | // Print memory layout, RSS is what is in memory |
@@ -159,7 +155,9 @@ private slots: | |||
159 | { | 155 | { |
160 | Sink::Query query; | 156 | Sink::Query query; |
161 | query.liveQuery = false; | 157 | query.liveQuery = false; |
162 | query.requestedProperties << "uid" << "subject" << "date"; | 158 | query.requestedProperties << "uid" |
159 | << "subject" | ||
160 | << "date"; | ||
163 | query.sortProperty = "date"; | 161 | query.sortProperty = "date"; |
164 | query.propertyFilter.insert("folder", "folder1"); | 162 | query.propertyFilter.insert("folder", "folder1"); |
165 | query.limit = 1000; | 163 | query.limit = 1000; |
@@ -167,7 +165,6 @@ private slots: | |||
167 | populateDatabase(50000); | 165 | populateDatabase(50000); |
168 | testLoad(query, 50000); | 166 | testLoad(query, 50000); |
169 | } | 167 | } |
170 | |||
171 | }; | 168 | }; |
172 | 169 | ||
173 | QTEST_MAIN(MailQueryBenchmark) | 170 | QTEST_MAIN(MailQueryBenchmark) |
diff --git a/tests/messagequeuetest.cpp b/tests/messagequeuetest.cpp index 06a4ae6..484ff86 100644 --- a/tests/messagequeuetest.cpp +++ b/tests/messagequeuetest.cpp | |||
@@ -45,12 +45,7 @@ private slots: | |||
45 | MessageQueue queue(Sink::Store::storageLocation(), "org.kde.dummy.testqueue"); | 45 | MessageQueue queue(Sink::Store::storageLocation(), "org.kde.dummy.testqueue"); |
46 | bool gotValue = false; | 46 | bool gotValue = false; |
47 | bool gotError = false; | 47 | bool gotError = false; |
48 | queue.dequeue([&](void *ptr, int size, std::function<void(bool success)> callback) { | 48 | queue.dequeue([&](void *ptr, int size, std::function<void(bool success)> callback) { gotValue = true; }, [&](const MessageQueue::Error &error) { gotError = true; }); |
49 | gotValue = true; | ||
50 | }, | ||
51 | [&](const MessageQueue::Error &error) { | ||
52 | gotError = true; | ||
53 | }); | ||
54 | QVERIFY(!gotValue); | 49 | QVERIFY(!gotValue); |
55 | QVERIFY(!gotError); | 50 | QVERIFY(!gotError); |
56 | } | 51 | } |
@@ -69,9 +64,7 @@ private slots: | |||
69 | QSignalSpy spy(&queue, SIGNAL(drained())); | 64 | QSignalSpy spy(&queue, SIGNAL(drained())); |
70 | queue.enqueue("value1"); | 65 | queue.enqueue("value1"); |
71 | 66 | ||
72 | queue.dequeue([](void *ptr, int size, std::function<void(bool success)> callback) { | 67 | queue.dequeue([](void *ptr, int size, std::function<void(bool success)> callback) { callback(true); }, [](const MessageQueue::Error &error) {}); |
73 | callback(true); | ||
74 | }, [](const MessageQueue::Error &error) {}); | ||
75 | QCOMPARE(spy.size(), 1); | 68 | QCOMPARE(spy.size(), 1); |
76 | } | 69 | } |
77 | 70 | ||
@@ -91,15 +84,14 @@ private slots: | |||
91 | const auto expected = values.dequeue(); | 84 | const auto expected = values.dequeue(); |
92 | bool gotValue = false; | 85 | bool gotValue = false; |
93 | bool gotError = false; | 86 | bool gotError = false; |
94 | queue.dequeue([&](void *ptr, int size, std::function<void(bool success)> callback) { | 87 | queue.dequeue( |
95 | if (QByteArray(static_cast<char*>(ptr), size) == expected) { | 88 | [&](void *ptr, int size, std::function<void(bool success)> callback) { |
96 | gotValue = true; | 89 | if (QByteArray(static_cast<char *>(ptr), size) == expected) { |
97 | } | 90 | gotValue = true; |
98 | callback(true); | 91 | } |
99 | }, | 92 | callback(true); |
100 | [&](const MessageQueue::Error &error) { | 93 | }, |
101 | gotError = true; | 94 | [&](const MessageQueue::Error &error) { gotError = true; }); |
102 | }); | ||
103 | QVERIFY(gotValue); | 95 | QVERIFY(gotValue); |
104 | QVERIFY(!gotError); | 96 | QVERIFY(!gotError); |
105 | } | 97 | } |
@@ -123,22 +115,21 @@ private slots: | |||
123 | bool gotValue = false; | 115 | bool gotValue = false; |
124 | bool gotError = false; | 116 | bool gotError = false; |
125 | 117 | ||
126 | queue.dequeue([&](void *ptr, int size, std::function<void(bool success)> callback) { | 118 | queue.dequeue( |
127 | if (QByteArray(static_cast<char*>(ptr), size) == expected) { | 119 | [&](void *ptr, int size, std::function<void(bool success)> callback) { |
128 | gotValue = true; | 120 | if (QByteArray(static_cast<char *>(ptr), size) == expected) { |
129 | } | 121 | gotValue = true; |
130 | auto timer = new QTimer(); | 122 | } |
131 | timer->setSingleShot(true); | 123 | auto timer = new QTimer(); |
132 | QObject::connect(timer, &QTimer::timeout, [timer, callback, &eventLoop]() { | 124 | timer->setSingleShot(true); |
133 | delete timer; | 125 | QObject::connect(timer, &QTimer::timeout, [timer, callback, &eventLoop]() { |
134 | callback(true); | 126 | delete timer; |
135 | eventLoop.exit(); | 127 | callback(true); |
136 | }); | 128 | eventLoop.exit(); |
137 | timer->start(0); | 129 | }); |
138 | }, | 130 | timer->start(0); |
139 | [&](const MessageQueue::Error &error) { | 131 | }, |
140 | gotError = true; | 132 | [&](const MessageQueue::Error &error) { gotError = true; }); |
141 | }); | ||
142 | eventLoop.exec(); | 133 | eventLoop.exec(); |
143 | QVERIFY(gotValue); | 134 | QVERIFY(gotValue); |
144 | QVERIFY(!gotError); | 135 | QVERIFY(!gotError); |
@@ -155,13 +146,12 @@ private slots: | |||
155 | queue.enqueue("value1"); | 146 | queue.enqueue("value1"); |
156 | 147 | ||
157 | bool gotError = false; | 148 | bool gotError = false; |
158 | queue.dequeue([&](void *ptr, int size, std::function<void(bool success)> callback) { | 149 | queue.dequeue( |
159 | queue.enqueue("value3"); | 150 | [&](void *ptr, int size, std::function<void(bool success)> callback) { |
160 | callback(true); | 151 | queue.enqueue("value3"); |
161 | }, | 152 | callback(true); |
162 | [&](const MessageQueue::Error &error) { | 153 | }, |
163 | gotError = true; | 154 | [&](const MessageQueue::Error &error) { gotError = true; }); |
164 | }); | ||
165 | QVERIFY(!gotError); | 155 | QVERIFY(!gotError); |
166 | } | 156 | } |
167 | 157 | ||
@@ -174,15 +164,15 @@ private slots: | |||
174 | 164 | ||
175 | int count = 0; | 165 | int count = 0; |
176 | queue.dequeueBatch(2, [&count](const QByteArray &data) { | 166 | queue.dequeueBatch(2, [&count](const QByteArray &data) { |
177 | count++; | 167 | count++; |
178 | return KAsync::null<void>(); | 168 | return KAsync::null<void>(); |
179 | }).exec().waitForFinished(); | 169 | }).exec().waitForFinished(); |
180 | QCOMPARE(count, 2); | 170 | QCOMPARE(count, 2); |
181 | 171 | ||
182 | queue.dequeueBatch(1, [&count](const QByteArray &data) { | 172 | queue.dequeueBatch(1, [&count](const QByteArray &data) { |
183 | count++; | 173 | count++; |
184 | return KAsync::null<void>(); | 174 | return KAsync::null<void>(); |
185 | }).exec().waitForFinished(); | 175 | }).exec().waitForFinished(); |
186 | QCOMPARE(count, 3); | 176 | QCOMPARE(count, 3); |
187 | } | 177 | } |
188 | 178 | ||
@@ -203,7 +193,6 @@ private slots: | |||
203 | QVERIFY(!queue.isEmpty()); | 193 | QVERIFY(!queue.isEmpty()); |
204 | QCOMPARE(spy.count(), 1); | 194 | QCOMPARE(spy.count(), 1); |
205 | } | 195 | } |
206 | |||
207 | }; | 196 | }; |
208 | 197 | ||
209 | QTEST_MAIN(MessageQueueTest) | 198 | QTEST_MAIN(MessageQueueTest) |
diff --git a/tests/modelinteractivitytest.cpp b/tests/modelinteractivitytest.cpp index ad23e0f..d0a0920 100644 --- a/tests/modelinteractivitytest.cpp +++ b/tests/modelinteractivitytest.cpp | |||
@@ -16,20 +16,23 @@ static int blockingTime; | |||
16 | class TimeMeasuringApplication : public QCoreApplication | 16 | class TimeMeasuringApplication : public QCoreApplication |
17 | { | 17 | { |
18 | QElapsedTimer t; | 18 | QElapsedTimer t; |
19 | |||
19 | public: | 20 | public: |
20 | TimeMeasuringApplication(int& argc, char ** argv) : QCoreApplication(argc, argv) { } | 21 | TimeMeasuringApplication(int &argc, char **argv) : QCoreApplication(argc, argv) |
21 | virtual ~TimeMeasuringApplication() { } | 22 | { |
23 | } | ||
24 | virtual ~TimeMeasuringApplication() | ||
25 | { | ||
26 | } | ||
22 | 27 | ||
23 | virtual bool notify(QObject* receiver, QEvent* event) | 28 | virtual bool notify(QObject *receiver, QEvent *event) |
24 | { | 29 | { |
25 | t.start(); | 30 | t.start(); |
26 | const bool ret = QCoreApplication::notify(receiver, event); | 31 | const bool ret = QCoreApplication::notify(receiver, event); |
27 | if(t.elapsed() > 1) | 32 | if (t.elapsed() > 1) |
28 | std::cout << QString("processing event type %1 for object %2 took %3ms") | 33 | std::cout |
29 | .arg((int)event->type()) | 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() |
30 | .arg(""/* receiver->objectName().toLocal8Bit().data()*/) | 35 | << std::endl; |
31 | .arg((int)t.elapsed()) | ||
32 | .toStdString() << std::endl; | ||
33 | blockingTime += t.elapsed(); | 36 | blockingTime += t.elapsed(); |
34 | return ret; | 37 | return ret; |
35 | } | 38 | } |
@@ -62,7 +65,7 @@ private slots: | |||
62 | 65 | ||
63 | void testSingle() | 66 | void testSingle() |
64 | { | 67 | { |
65 | //Setup | 68 | // Setup |
66 | { | 69 | { |
67 | Sink::ApplicationDomain::Mail mail("org.kde.dummy.instance1"); | 70 | Sink::ApplicationDomain::Mail mail("org.kde.dummy.instance1"); |
68 | for (int i = 0; i < 1000; i++) { | 71 | for (int i = 0; i < 1000; i++) { |
@@ -76,13 +79,13 @@ private slots: | |||
76 | 79 | ||
77 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 80 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
78 | 81 | ||
79 | //Test | 82 | // Test |
80 | QTime time; | 83 | QTime time; |
81 | time.start(); | 84 | time.start(); |
82 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query); | 85 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query); |
83 | blockingTime += time.elapsed(); | 86 | blockingTime += time.elapsed(); |
84 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); | 87 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); |
85 | //Never block longer than 10 ms | 88 | // Never block longer than 10 ms |
86 | QVERIFY2(blockingTime < 10, QString("Total blocking time: %1").arg(blockingTime).toLatin1().data()); | 89 | QVERIFY2(blockingTime < 10, QString("Total blocking time: %1").arg(blockingTime).toLatin1().data()); |
87 | } | 90 | } |
88 | }; | 91 | }; |
diff --git a/tests/pipelinebenchmark.cpp b/tests/pipelinebenchmark.cpp index 5743830..0133a6c 100644 --- a/tests/pipelinebenchmark.cpp +++ b/tests/pipelinebenchmark.cpp | |||
@@ -54,7 +54,8 @@ | |||
54 | // } | 54 | // } |
55 | // } | 55 | // } |
56 | // | 56 | // |
57 | // void modifiedEntity(const QByteArray &key, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &oldEntity, const Sink::ApplicationDomain::BufferAdaptor &newEntity, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | 57 | // void modifiedEntity(const QByteArray &key, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &oldEntity, const Sink::ApplicationDomain::BufferAdaptor &newEntity, |
58 | // Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | ||
58 | // { | 59 | // { |
59 | // } | 60 | // } |
60 | // | 61 | // |
@@ -66,7 +67,7 @@ | |||
66 | 67 | ||
67 | /** | 68 | /** |
68 | * Benchmark pipeline processing speed. | 69 | * Benchmark pipeline processing speed. |
69 | * | 70 | * |
70 | * This benchmark especially highlights: | 71 | * This benchmark especially highlights: |
71 | * * Cost of an index in speed and size | 72 | * * Cost of an index in speed and size |
72 | */ | 73 | */ |
@@ -77,7 +78,7 @@ class PipelineBenchmark : public QObject | |||
77 | QByteArray resourceIdentifier; | 78 | QByteArray resourceIdentifier; |
78 | HAWD::State mHawdState; | 79 | HAWD::State mHawdState; |
79 | 80 | ||
80 | void populateDatabase(int count, const QVector<Sink::Preprocessor*> &preprocessors) | 81 | void populateDatabase(int count, const QVector<Sink::Preprocessor *> &preprocessors) |
81 | { | 82 | { |
82 | TestResource::removeFromDisk(resourceIdentifier); | 83 | TestResource::removeFromDisk(resourceIdentifier); |
83 | 84 | ||
@@ -112,18 +113,17 @@ class PipelineBenchmark : public QObject | |||
112 | // Print memory layout, RSS is what is in memory | 113 | // Print memory layout, RSS is what is in memory |
113 | // std::system("exec pmap -x \"$PPID\""); | 114 | // std::system("exec pmap -x \"$PPID\""); |
114 | // | 115 | // |
115 | std::cout << "Size: " << Sink::Storage(Sink::storageLocation(), resourceIdentifier, Sink::Storage::ReadOnly).diskUsage()/1024 << " [kb]" << std::endl; | 116 | std::cout << "Size: " << Sink::Storage(Sink::storageLocation(), resourceIdentifier, Sink::Storage::ReadOnly).diskUsage() / 1024 << " [kb]" << std::endl; |
116 | std::cout << "Time: " << allProcessedTime << " [ms]" << std::endl; | 117 | std::cout << "Time: " << allProcessedTime << " [ms]" << std::endl; |
117 | 118 | ||
118 | HAWD::Dataset dataset("pipeline", mHawdState); | 119 | HAWD::Dataset dataset("pipeline", mHawdState); |
119 | HAWD::Dataset::Row row = dataset.row(); | 120 | HAWD::Dataset::Row row = dataset.row(); |
120 | 121 | ||
121 | row.setValue("rows", count); | 122 | row.setValue("rows", count); |
122 | row.setValue("append", (qreal)count/appendTime); | 123 | row.setValue("append", (qreal)count / appendTime); |
123 | row.setValue("total", (qreal)count/allProcessedTime); | 124 | row.setValue("total", (qreal)count / allProcessedTime); |
124 | dataset.insertRow(row); | 125 | dataset.insertRow(row); |
125 | HAWD::Formatter::print(dataset); | 126 | HAWD::Formatter::print(dataset); |
126 | |||
127 | } | 127 | } |
128 | 128 | ||
129 | private slots: | 129 | private slots: |
@@ -136,15 +136,14 @@ private slots: | |||
136 | 136 | ||
137 | void testWithoutIndex() | 137 | void testWithoutIndex() |
138 | { | 138 | { |
139 | populateDatabase(10000, QVector<Sink::Preprocessor*>()); | 139 | populateDatabase(10000, QVector<Sink::Preprocessor *>()); |
140 | } | 140 | } |
141 | 141 | ||
142 | void testWithIndex() | 142 | void testWithIndex() |
143 | { | 143 | { |
144 | auto indexer = QSharedPointer<DefaultIndexUpdater<Sink::ApplicationDomain::Mail> >::create(); | 144 | auto indexer = QSharedPointer<DefaultIndexUpdater<Sink::ApplicationDomain::Mail>>::create(); |
145 | populateDatabase(10000, QVector<Sink::Preprocessor*>() << indexer.data()); | 145 | populateDatabase(10000, QVector<Sink::Preprocessor *>() << indexer.data()); |
146 | } | 146 | } |
147 | |||
148 | }; | 147 | }; |
149 | 148 | ||
150 | QTEST_MAIN(PipelineBenchmark) | 149 | QTEST_MAIN(PipelineBenchmark) |
diff --git a/tests/pipelinetest.cpp b/tests/pipelinetest.cpp index 92b7554..cdd260d 100644 --- a/tests/pipelinetest.cpp +++ b/tests/pipelinetest.cpp | |||
@@ -143,7 +143,8 @@ QByteArray deleteEntityCommand(const QByteArray &uid, qint64 revision) | |||
143 | return command; | 143 | return command; |
144 | } | 144 | } |
145 | 145 | ||
146 | class TestProcessor : public Sink::Preprocessor { | 146 | class TestProcessor : public Sink::Preprocessor |
147 | { | ||
147 | public: | 148 | public: |
148 | void newEntity(const QByteArray &uid, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &newEntity, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | 149 | void newEntity(const QByteArray &uid, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &newEntity, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE |
149 | { | 150 | { |
@@ -151,7 +152,8 @@ public: | |||
151 | newRevisions << revision; | 152 | newRevisions << revision; |
152 | } | 153 | } |
153 | 154 | ||
154 | void modifiedEntity(const QByteArray &uid, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &oldEntity, const Sink::ApplicationDomain::BufferAdaptor &newEntity, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | 155 | void modifiedEntity(const QByteArray &uid, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &oldEntity, const Sink::ApplicationDomain::BufferAdaptor &newEntity, |
156 | Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | ||
155 | { | 157 | { |
156 | modifiedUids << uid; | 158 | modifiedUids << uid; |
157 | modifiedRevisions << revision; | 159 | modifiedRevisions << revision; |
@@ -214,42 +216,42 @@ private slots: | |||
214 | auto adaptorFactory = QSharedPointer<TestEventAdaptorFactory>::create(); | 216 | auto adaptorFactory = QSharedPointer<TestEventAdaptorFactory>::create(); |
215 | pipeline.setAdaptorFactory("event", adaptorFactory); | 217 | pipeline.setAdaptorFactory("event", adaptorFactory); |
216 | 218 | ||
217 | //Create the initial revision | 219 | // Create the initial revision |
218 | pipeline.startTransaction(); | 220 | pipeline.startTransaction(); |
219 | pipeline.newEntity(command.constData(), command.size()); | 221 | pipeline.newEntity(command.constData(), command.size()); |
220 | pipeline.commit(); | 222 | pipeline.commit(); |
221 | 223 | ||
222 | //Get uid of written entity | 224 | // Get uid of written entity |
223 | auto keys = getKeys("org.kde.pipelinetest.instance1", "event.main"); | 225 | auto keys = getKeys("org.kde.pipelinetest.instance1", "event.main"); |
224 | QCOMPARE(keys.size(), 1); | 226 | QCOMPARE(keys.size(), 1); |
225 | const auto key = keys.first(); | 227 | const auto key = keys.first(); |
226 | const auto uid = Sink::Storage::uidFromKey(key); | 228 | const auto uid = Sink::Storage::uidFromKey(key); |
227 | 229 | ||
228 | //Execute the modification | 230 | // Execute the modification |
229 | entityFbb.Clear(); | 231 | entityFbb.Clear(); |
230 | auto modifyCommand = modifyEntityCommand(createEvent(entityFbb, "summary2"), uid, 1); | 232 | auto modifyCommand = modifyEntityCommand(createEvent(entityFbb, "summary2"), uid, 1); |
231 | pipeline.startTransaction(); | 233 | pipeline.startTransaction(); |
232 | pipeline.modifiedEntity(modifyCommand.constData(), modifyCommand.size()); | 234 | pipeline.modifiedEntity(modifyCommand.constData(), modifyCommand.size()); |
233 | pipeline.commit(); | 235 | pipeline.commit(); |
234 | 236 | ||
235 | //Ensure we've got the new revision with the modification | 237 | // Ensure we've got the new revision with the modification |
236 | auto buffer = getEntity("org.kde.pipelinetest.instance1", "event.main", Sink::Storage::assembleKey(uid, 2)); | 238 | auto buffer = getEntity("org.kde.pipelinetest.instance1", "event.main", Sink::Storage::assembleKey(uid, 2)); |
237 | QVERIFY(!buffer.isEmpty()); | 239 | QVERIFY(!buffer.isEmpty()); |
238 | Sink::EntityBuffer entityBuffer(buffer.data(), buffer.size()); | 240 | Sink::EntityBuffer entityBuffer(buffer.data(), buffer.size()); |
239 | auto adaptor = adaptorFactory->createAdaptor(entityBuffer.entity()); | 241 | auto adaptor = adaptorFactory->createAdaptor(entityBuffer.entity()); |
240 | QVERIFY2(adaptor->getProperty("summary").toString() == QString("summary2"), "The modification isn't applied."); | 242 | QVERIFY2(adaptor->getProperty("summary").toString() == QString("summary2"), "The modification isn't applied."); |
241 | //Ensure we didn't modify anything else | 243 | // Ensure we didn't modify anything else |
242 | QVERIFY2(adaptor->getProperty("description").toString() == QString("description"), "The modification has sideeffects."); | 244 | QVERIFY2(adaptor->getProperty("description").toString() == QString("description"), "The modification has sideeffects."); |
243 | 245 | ||
244 | //Both revisions are in the store at this point | 246 | // Both revisions are in the store at this point |
245 | QCOMPARE(getKeys("org.kde.pipelinetest.instance1", "event.main").size(), 2); | 247 | QCOMPARE(getKeys("org.kde.pipelinetest.instance1", "event.main").size(), 2); |
246 | 248 | ||
247 | //Cleanup old revisions | 249 | // Cleanup old revisions |
248 | pipeline.startTransaction(); | 250 | pipeline.startTransaction(); |
249 | pipeline.cleanupRevision(2); | 251 | pipeline.cleanupRevision(2); |
250 | pipeline.commit(); | 252 | pipeline.commit(); |
251 | 253 | ||
252 | //And now only the latest revision is left | 254 | // And now only the latest revision is left |
253 | QCOMPARE(getKeys("org.kde.pipelinetest.instance1", "event.main").size(), 1); | 255 | QCOMPARE(getKeys("org.kde.pipelinetest.instance1", "event.main").size(), 1); |
254 | } | 256 | } |
255 | 257 | ||
@@ -263,18 +265,18 @@ private slots: | |||
263 | auto adaptorFactory = QSharedPointer<TestEventAdaptorFactory>::create(); | 265 | auto adaptorFactory = QSharedPointer<TestEventAdaptorFactory>::create(); |
264 | pipeline.setAdaptorFactory("event", adaptorFactory); | 266 | pipeline.setAdaptorFactory("event", adaptorFactory); |
265 | 267 | ||
266 | //Create the initial revision | 268 | // Create the initial revision |
267 | pipeline.startTransaction(); | 269 | pipeline.startTransaction(); |
268 | pipeline.newEntity(command.constData(), command.size()); | 270 | pipeline.newEntity(command.constData(), command.size()); |
269 | pipeline.commit(); | 271 | pipeline.commit(); |
270 | 272 | ||
271 | //Get uid of written entity | 273 | // Get uid of written entity |
272 | auto keys = getKeys("org.kde.pipelinetest.instance1", "event.main"); | 274 | auto keys = getKeys("org.kde.pipelinetest.instance1", "event.main"); |
273 | QCOMPARE(keys.size(), 1); | 275 | QCOMPARE(keys.size(), 1); |
274 | const auto uid = Sink::Storage::uidFromKey(keys.first()); | 276 | const auto uid = Sink::Storage::uidFromKey(keys.first()); |
275 | 277 | ||
276 | 278 | ||
277 | //Create another operation inbetween | 279 | // Create another operation inbetween |
278 | { | 280 | { |
279 | entityFbb.Clear(); | 281 | entityFbb.Clear(); |
280 | auto command = createEntityCommand(createEvent(entityFbb)); | 282 | auto command = createEntityCommand(createEvent(entityFbb)); |
@@ -283,14 +285,14 @@ private slots: | |||
283 | pipeline.commit(); | 285 | pipeline.commit(); |
284 | } | 286 | } |
285 | 287 | ||
286 | //Execute the modification on revision 2 | 288 | // Execute the modification on revision 2 |
287 | entityFbb.Clear(); | 289 | entityFbb.Clear(); |
288 | auto modifyCommand = modifyEntityCommand(createEvent(entityFbb, "summary2"), uid, 2); | 290 | auto modifyCommand = modifyEntityCommand(createEvent(entityFbb, "summary2"), uid, 2); |
289 | pipeline.startTransaction(); | 291 | pipeline.startTransaction(); |
290 | pipeline.modifiedEntity(modifyCommand.constData(), modifyCommand.size()); | 292 | pipeline.modifiedEntity(modifyCommand.constData(), modifyCommand.size()); |
291 | pipeline.commit(); | 293 | pipeline.commit(); |
292 | 294 | ||
293 | //Ensure we've got the new revision with the modification | 295 | // Ensure we've got the new revision with the modification |
294 | auto buffer = getEntity("org.kde.pipelinetest.instance1", "event.main", Sink::Storage::assembleKey(uid, 3)); | 296 | auto buffer = getEntity("org.kde.pipelinetest.instance1", "event.main", Sink::Storage::assembleKey(uid, 3)); |
295 | QVERIFY(!buffer.isEmpty()); | 297 | QVERIFY(!buffer.isEmpty()); |
296 | Sink::EntityBuffer entityBuffer(buffer.data(), buffer.size()); | 298 | Sink::EntityBuffer entityBuffer(buffer.data(), buffer.size()); |
@@ -305,7 +307,7 @@ private slots: | |||
305 | Sink::Pipeline pipeline("org.kde.pipelinetest.instance1"); | 307 | Sink::Pipeline pipeline("org.kde.pipelinetest.instance1"); |
306 | pipeline.setAdaptorFactory("event", QSharedPointer<TestEventAdaptorFactory>::create()); | 308 | pipeline.setAdaptorFactory("event", QSharedPointer<TestEventAdaptorFactory>::create()); |
307 | 309 | ||
308 | //Create the initial revision | 310 | // Create the initial revision |
309 | pipeline.startTransaction(); | 311 | pipeline.startTransaction(); |
310 | pipeline.newEntity(command.constData(), command.size()); | 312 | pipeline.newEntity(command.constData(), command.size()); |
311 | pipeline.commit(); | 313 | pipeline.commit(); |
@@ -315,21 +317,21 @@ private slots: | |||
315 | 317 | ||
316 | const auto uid = Sink::Storage::uidFromKey(result.first()); | 318 | const auto uid = Sink::Storage::uidFromKey(result.first()); |
317 | 319 | ||
318 | //Delete entity | 320 | // Delete entity |
319 | auto deleteCommand = deleteEntityCommand(uid, 1); | 321 | auto deleteCommand = deleteEntityCommand(uid, 1); |
320 | pipeline.startTransaction(); | 322 | pipeline.startTransaction(); |
321 | pipeline.deletedEntity(deleteCommand.constData(), deleteCommand.size()); | 323 | pipeline.deletedEntity(deleteCommand.constData(), deleteCommand.size()); |
322 | pipeline.commit(); | 324 | pipeline.commit(); |
323 | 325 | ||
324 | //We have a new revision that indicates the deletion | 326 | // We have a new revision that indicates the deletion |
325 | QCOMPARE(getKeys("org.kde.pipelinetest.instance1", "event.main").size(), 2); | 327 | QCOMPARE(getKeys("org.kde.pipelinetest.instance1", "event.main").size(), 2); |
326 | 328 | ||
327 | //Cleanup old revisions | 329 | // Cleanup old revisions |
328 | pipeline.startTransaction(); | 330 | pipeline.startTransaction(); |
329 | pipeline.cleanupRevision(2); | 331 | pipeline.cleanupRevision(2); |
330 | pipeline.commit(); | 332 | pipeline.commit(); |
331 | 333 | ||
332 | //And all revisions are gone | 334 | // And all revisions are gone |
333 | QCOMPARE(getKeys("org.kde.pipelinetest.instance1", "event.main").size(), 0); | 335 | QCOMPARE(getKeys("org.kde.pipelinetest.instance1", "event.main").size(), 0); |
334 | } | 336 | } |
335 | 337 | ||
@@ -340,17 +342,17 @@ private slots: | |||
340 | TestProcessor testProcessor; | 342 | TestProcessor testProcessor; |
341 | 343 | ||
342 | Sink::Pipeline pipeline("org.kde.pipelinetest.instance1"); | 344 | Sink::Pipeline pipeline("org.kde.pipelinetest.instance1"); |
343 | pipeline.setPreprocessors("event", QVector<Sink::Preprocessor*>() << &testProcessor); | 345 | pipeline.setPreprocessors("event", QVector<Sink::Preprocessor *>() << &testProcessor); |
344 | pipeline.startTransaction(); | 346 | pipeline.startTransaction(); |
345 | pipeline.setAdaptorFactory("event", QSharedPointer<TestEventAdaptorFactory>::create()); | 347 | pipeline.setAdaptorFactory("event", QSharedPointer<TestEventAdaptorFactory>::create()); |
346 | 348 | ||
347 | //Actual test | 349 | // Actual test |
348 | { | 350 | { |
349 | auto command = createEntityCommand(createEvent(entityFbb)); | 351 | auto command = createEntityCommand(createEvent(entityFbb)); |
350 | pipeline.newEntity(command.constData(), command.size()); | 352 | pipeline.newEntity(command.constData(), command.size()); |
351 | QCOMPARE(testProcessor.newUids.size(), 1); | 353 | QCOMPARE(testProcessor.newUids.size(), 1); |
352 | QCOMPARE(testProcessor.newRevisions.size(), 1); | 354 | QCOMPARE(testProcessor.newRevisions.size(), 1); |
353 | //Key doesn't contain revision and is just the uid | 355 | // Key doesn't contain revision and is just the uid |
354 | QCOMPARE(testProcessor.newUids.at(0), Sink::Storage::uidFromKey(testProcessor.newUids.at(0))); | 356 | QCOMPARE(testProcessor.newUids.at(0), Sink::Storage::uidFromKey(testProcessor.newUids.at(0))); |
355 | } | 357 | } |
356 | pipeline.commit(); | 358 | pipeline.commit(); |
@@ -364,7 +366,7 @@ private slots: | |||
364 | pipeline.modifiedEntity(modifyCommand.constData(), modifyCommand.size()); | 366 | pipeline.modifiedEntity(modifyCommand.constData(), modifyCommand.size()); |
365 | QCOMPARE(testProcessor.modifiedUids.size(), 1); | 367 | QCOMPARE(testProcessor.modifiedUids.size(), 1); |
366 | QCOMPARE(testProcessor.modifiedRevisions.size(), 1); | 368 | QCOMPARE(testProcessor.modifiedRevisions.size(), 1); |
367 | //Key doesn't contain revision and is just the uid | 369 | // Key doesn't contain revision and is just the uid |
368 | QCOMPARE(testProcessor.modifiedUids.at(0), Sink::Storage::uidFromKey(testProcessor.modifiedUids.at(0))); | 370 | QCOMPARE(testProcessor.modifiedUids.at(0), Sink::Storage::uidFromKey(testProcessor.modifiedUids.at(0))); |
369 | } | 371 | } |
370 | pipeline.commit(); | 372 | pipeline.commit(); |
@@ -376,7 +378,7 @@ private slots: | |||
376 | QCOMPARE(testProcessor.deletedUids.size(), 1); | 378 | QCOMPARE(testProcessor.deletedUids.size(), 1); |
377 | QCOMPARE(testProcessor.deletedUids.size(), 1); | 379 | QCOMPARE(testProcessor.deletedUids.size(), 1); |
378 | QCOMPARE(testProcessor.deletedSummaries.size(), 1); | 380 | QCOMPARE(testProcessor.deletedSummaries.size(), 1); |
379 | //Key doesn't contain revision and is just the uid | 381 | // Key doesn't contain revision and is just the uid |
380 | QCOMPARE(testProcessor.deletedUids.at(0), Sink::Storage::uidFromKey(testProcessor.deletedUids.at(0))); | 382 | QCOMPARE(testProcessor.deletedUids.at(0), Sink::Storage::uidFromKey(testProcessor.deletedUids.at(0))); |
381 | QCOMPARE(testProcessor.deletedSummaries.at(0), QByteArray("summary2")); | 383 | QCOMPARE(testProcessor.deletedSummaries.at(0), QByteArray("summary2")); |
382 | } | 384 | } |
diff --git a/tests/querytest.cpp b/tests/querytest.cpp index 2531c25..7b9129e 100644 --- a/tests/querytest.cpp +++ b/tests/querytest.cpp | |||
@@ -42,12 +42,12 @@ private slots: | |||
42 | 42 | ||
43 | void testNoResources() | 43 | void testNoResources() |
44 | { | 44 | { |
45 | //Test | 45 | // Test |
46 | Sink::Query query; | 46 | Sink::Query query; |
47 | query.resources << "foobar"; | 47 | query.resources << "foobar"; |
48 | query.liveQuery = true; | 48 | query.liveQuery = true; |
49 | 49 | ||
50 | //We fetch before the data is available and rely on the live query mechanism to deliver the actual data | 50 | // We fetch before the data is available and rely on the live query mechanism to deliver the actual data |
51 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query); | 51 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query); |
52 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); | 52 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); |
53 | QCOMPARE(model->rowCount(), 0); | 53 | QCOMPARE(model->rowCount(), 0); |
@@ -56,39 +56,39 @@ private slots: | |||
56 | 56 | ||
57 | void testSingle() | 57 | void testSingle() |
58 | { | 58 | { |
59 | //Setup | 59 | // Setup |
60 | { | 60 | { |
61 | Sink::ApplicationDomain::Mail mail("org.kde.dummy.instance1"); | 61 | Sink::ApplicationDomain::Mail mail("org.kde.dummy.instance1"); |
62 | Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished(); | 62 | Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished(); |
63 | } | 63 | } |
64 | 64 | ||
65 | //Test | 65 | // Test |
66 | Sink::Query query; | 66 | Sink::Query query; |
67 | query.resources << "org.kde.dummy.instance1"; | 67 | query.resources << "org.kde.dummy.instance1"; |
68 | query.liveQuery = true; | 68 | query.liveQuery = true; |
69 | 69 | ||
70 | //We fetch before the data is available and rely on the live query mechanism to deliver the actual data | 70 | // We fetch before the data is available and rely on the live query mechanism to deliver the actual data |
71 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query); | 71 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query); |
72 | QTRY_COMPARE(model->rowCount(), 1); | 72 | QTRY_COMPARE(model->rowCount(), 1); |
73 | } | 73 | } |
74 | 74 | ||
75 | void testSingleWithDelay() | 75 | void testSingleWithDelay() |
76 | { | 76 | { |
77 | //Setup | 77 | // Setup |
78 | { | 78 | { |
79 | Sink::ApplicationDomain::Mail mail("org.kde.dummy.instance1"); | 79 | Sink::ApplicationDomain::Mail mail("org.kde.dummy.instance1"); |
80 | Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished(); | 80 | Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished(); |
81 | } | 81 | } |
82 | 82 | ||
83 | //Test | 83 | // Test |
84 | Sink::Query query; | 84 | Sink::Query query; |
85 | query.resources << "org.kde.dummy.instance1"; | 85 | query.resources << "org.kde.dummy.instance1"; |
86 | query.liveQuery = false; | 86 | query.liveQuery = false; |
87 | 87 | ||
88 | //Ensure all local data is processed | 88 | // Ensure all local data is processed |
89 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 89 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
90 | 90 | ||
91 | //We fetch after the data is available and don't rely on the live query mechanism to deliver the actual data | 91 | // We fetch after the data is available and don't rely on the live query mechanism to deliver the actual data |
92 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query); | 92 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query); |
93 | 93 | ||
94 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); | 94 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); |
@@ -98,7 +98,7 @@ private slots: | |||
98 | void testById() | 98 | void testById() |
99 | { | 99 | { |
100 | QByteArray id; | 100 | QByteArray id; |
101 | //Setup | 101 | // Setup |
102 | { | 102 | { |
103 | Sink::ApplicationDomain::Mail mail("org.kde.dummy.instance1"); | 103 | Sink::ApplicationDomain::Mail mail("org.kde.dummy.instance1"); |
104 | Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished(); | 104 | Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished(); |
@@ -107,17 +107,17 @@ private slots: | |||
107 | Sink::Query query; | 107 | Sink::Query query; |
108 | query.resources << "org.kde.dummy.instance1"; | 108 | query.resources << "org.kde.dummy.instance1"; |
109 | 109 | ||
110 | //Ensure all local data is processed | 110 | // Ensure all local data is processed |
111 | Sink::Store::synchronize(query).exec().waitForFinished(); | 111 | Sink::Store::synchronize(query).exec().waitForFinished(); |
112 | 112 | ||
113 | //We fetch before the data is available and rely on the live query mechanism to deliver the actual data | 113 | // We fetch before the data is available and rely on the live query mechanism to deliver the actual data |
114 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query); | 114 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query); |
115 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); | 115 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); |
116 | QVERIFY(model->rowCount() >= 1); | 116 | QVERIFY(model->rowCount() >= 1); |
117 | id = model->index(0, 0).data(Sink::Store::DomainObjectRole).value<Sink::ApplicationDomain::Mail::Ptr>()->identifier(); | 117 | id = model->index(0, 0).data(Sink::Store::DomainObjectRole).value<Sink::ApplicationDomain::Mail::Ptr>()->identifier(); |
118 | } | 118 | } |
119 | 119 | ||
120 | //Test | 120 | // Test |
121 | Sink::Query query; | 121 | Sink::Query query; |
122 | query.resources << "org.kde.dummy.instance1"; | 122 | query.resources << "org.kde.dummy.instance1"; |
123 | query.ids << id; | 123 | query.ids << id; |
@@ -128,18 +128,18 @@ private slots: | |||
128 | 128 | ||
129 | void testFolder() | 129 | void testFolder() |
130 | { | 130 | { |
131 | //Setup | 131 | // Setup |
132 | { | 132 | { |
133 | Sink::ApplicationDomain::Folder folder("org.kde.dummy.instance1"); | 133 | Sink::ApplicationDomain::Folder folder("org.kde.dummy.instance1"); |
134 | Sink::Store::create<Sink::ApplicationDomain::Folder>(folder).exec().waitForFinished(); | 134 | Sink::Store::create<Sink::ApplicationDomain::Folder>(folder).exec().waitForFinished(); |
135 | } | 135 | } |
136 | 136 | ||
137 | //Test | 137 | // Test |
138 | Sink::Query query; | 138 | Sink::Query query; |
139 | query.resources << "org.kde.dummy.instance1"; | 139 | query.resources << "org.kde.dummy.instance1"; |
140 | query.liveQuery = true; | 140 | query.liveQuery = true; |
141 | 141 | ||
142 | //We fetch before the data is available and rely on the live query mechanism to deliver the actual data | 142 | // We fetch before the data is available and rely on the live query mechanism to deliver the actual data |
143 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Folder>(query); | 143 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Folder>(query); |
144 | QTRY_COMPARE(model->rowCount(), 1); | 144 | QTRY_COMPARE(model->rowCount(), 1); |
145 | auto folderEntity = model->index(0, 0).data(Sink::Store::DomainObjectRole).value<Sink::ApplicationDomain::Folder::Ptr>(); | 145 | auto folderEntity = model->index(0, 0).data(Sink::Store::DomainObjectRole).value<Sink::ApplicationDomain::Folder::Ptr>(); |
@@ -148,7 +148,7 @@ private slots: | |||
148 | 148 | ||
149 | void testFolderTree() | 149 | void testFolderTree() |
150 | { | 150 | { |
151 | //Setup | 151 | // Setup |
152 | { | 152 | { |
153 | Sink::ApplicationDomain::Folder folder("org.kde.dummy.instance1"); | 153 | Sink::ApplicationDomain::Folder folder("org.kde.dummy.instance1"); |
154 | Sink::Store::create<Sink::ApplicationDomain::Folder>(folder).exec().waitForFinished(); | 154 | Sink::Store::create<Sink::ApplicationDomain::Folder>(folder).exec().waitForFinished(); |
@@ -156,7 +156,7 @@ private slots: | |||
156 | Sink::Query query; | 156 | Sink::Query query; |
157 | query.resources << "org.kde.dummy.instance1"; | 157 | query.resources << "org.kde.dummy.instance1"; |
158 | 158 | ||
159 | //Ensure all local data is processed | 159 | // Ensure all local data is processed |
160 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 160 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
161 | 161 | ||
162 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Folder>(query); | 162 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Folder>(query); |
@@ -171,15 +171,15 @@ private slots: | |||
171 | Sink::Store::create<Sink::ApplicationDomain::Folder>(subfolder).exec().waitForFinished(); | 171 | Sink::Store::create<Sink::ApplicationDomain::Folder>(subfolder).exec().waitForFinished(); |
172 | } | 172 | } |
173 | 173 | ||
174 | //Test | 174 | // Test |
175 | Sink::Query query; | 175 | Sink::Query query; |
176 | query.resources << "org.kde.dummy.instance1"; | 176 | query.resources << "org.kde.dummy.instance1"; |
177 | query.parentProperty = "parent"; | 177 | query.parentProperty = "parent"; |
178 | 178 | ||
179 | //Ensure all local data is processed | 179 | // Ensure all local data is processed |
180 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 180 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
181 | 181 | ||
182 | //We fetch after the data is available and don't rely on the live query mechanism to deliver the actual data | 182 | // We fetch after the data is available and don't rely on the live query mechanism to deliver the actual data |
183 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Folder>(query); | 183 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Folder>(query); |
184 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); | 184 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); |
185 | QCOMPARE(model->rowCount(), 1); | 185 | QCOMPARE(model->rowCount(), 1); |
@@ -190,7 +190,7 @@ private slots: | |||
190 | 190 | ||
191 | void testMailByUid() | 191 | void testMailByUid() |
192 | { | 192 | { |
193 | //Setup | 193 | // Setup |
194 | { | 194 | { |
195 | Sink::ApplicationDomain::Mail mail("org.kde.dummy.instance1"); | 195 | Sink::ApplicationDomain::Mail mail("org.kde.dummy.instance1"); |
196 | mail.setProperty("uid", "test1"); | 196 | mail.setProperty("uid", "test1"); |
@@ -198,16 +198,16 @@ private slots: | |||
198 | Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished(); | 198 | Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished(); |
199 | } | 199 | } |
200 | 200 | ||
201 | //Test | 201 | // Test |
202 | Sink::Query query; | 202 | Sink::Query query; |
203 | query.resources << "org.kde.dummy.instance1"; | 203 | query.resources << "org.kde.dummy.instance1"; |
204 | query.liveQuery = false; | 204 | query.liveQuery = false; |
205 | query.propertyFilter.insert("uid", "test1"); | 205 | query.propertyFilter.insert("uid", "test1"); |
206 | 206 | ||
207 | //Ensure all local data is processed | 207 | // Ensure all local data is processed |
208 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 208 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
209 | 209 | ||
210 | //We fetch before the data is available and rely on the live query mechanism to deliver the actual data | 210 | // We fetch before the data is available and rely on the live query mechanism to deliver the actual data |
211 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query); | 211 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query); |
212 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); | 212 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); |
213 | QCOMPARE(model->rowCount(), 1); | 213 | QCOMPARE(model->rowCount(), 1); |
@@ -215,7 +215,7 @@ private slots: | |||
215 | 215 | ||
216 | void testMailByFolder() | 216 | void testMailByFolder() |
217 | { | 217 | { |
218 | //Setup | 218 | // Setup |
219 | Sink::ApplicationDomain::Folder::Ptr folderEntity; | 219 | Sink::ApplicationDomain::Folder::Ptr folderEntity; |
220 | { | 220 | { |
221 | Sink::ApplicationDomain::Folder folder("org.kde.dummy.instance1"); | 221 | Sink::ApplicationDomain::Folder folder("org.kde.dummy.instance1"); |
@@ -224,7 +224,7 @@ private slots: | |||
224 | Sink::Query query; | 224 | Sink::Query query; |
225 | query.resources << "org.kde.dummy.instance1"; | 225 | query.resources << "org.kde.dummy.instance1"; |
226 | 226 | ||
227 | //Ensure all local data is processed | 227 | // Ensure all local data is processed |
228 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 228 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
229 | 229 | ||
230 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Folder>(query); | 230 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Folder>(query); |
@@ -240,15 +240,15 @@ private slots: | |||
240 | Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished(); | 240 | Sink::Store::create<Sink::ApplicationDomain::Mail>(mail).exec().waitForFinished(); |
241 | } | 241 | } |
242 | 242 | ||
243 | //Test | 243 | // Test |
244 | Sink::Query query; | 244 | Sink::Query query; |
245 | query.resources << "org.kde.dummy.instance1"; | 245 | query.resources << "org.kde.dummy.instance1"; |
246 | query.propertyFilter.insert("folder", folderEntity->identifier()); | 246 | query.propertyFilter.insert("folder", folderEntity->identifier()); |
247 | 247 | ||
248 | //Ensure all local data is processed | 248 | // Ensure all local data is processed |
249 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 249 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
250 | 250 | ||
251 | //We fetch before the data is available and rely on the live query mechanism to deliver the actual data | 251 | // We fetch before the data is available and rely on the live query mechanism to deliver the actual data |
252 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query); | 252 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query); |
253 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); | 253 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); |
254 | QCOMPARE(model->rowCount(), 1); | 254 | QCOMPARE(model->rowCount(), 1); |
@@ -256,7 +256,7 @@ private slots: | |||
256 | 256 | ||
257 | void testMailByFolderSortedByDate() | 257 | void testMailByFolderSortedByDate() |
258 | { | 258 | { |
259 | //Setup | 259 | // Setup |
260 | Sink::ApplicationDomain::Folder::Ptr folderEntity; | 260 | Sink::ApplicationDomain::Folder::Ptr folderEntity; |
261 | { | 261 | { |
262 | Sink::ApplicationDomain::Folder folder("org.kde.dummy.instance1"); | 262 | Sink::ApplicationDomain::Folder folder("org.kde.dummy.instance1"); |
@@ -265,7 +265,7 @@ private slots: | |||
265 | Sink::Query query; | 265 | Sink::Query query; |
266 | query.resources << "org.kde.dummy.instance1"; | 266 | query.resources << "org.kde.dummy.instance1"; |
267 | 267 | ||
268 | //Ensure all local data is processed | 268 | // Ensure all local data is processed |
269 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 269 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
270 | 270 | ||
271 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Folder>(query); | 271 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Folder>(query); |
@@ -299,7 +299,7 @@ private slots: | |||
299 | } | 299 | } |
300 | } | 300 | } |
301 | 301 | ||
302 | //Test | 302 | // Test |
303 | Sink::Query query; | 303 | Sink::Query query; |
304 | query.resources << "org.kde.dummy.instance1"; | 304 | query.resources << "org.kde.dummy.instance1"; |
305 | query.propertyFilter.insert("folder", folderEntity->identifier()); | 305 | query.propertyFilter.insert("folder", folderEntity->identifier()); |
@@ -307,19 +307,19 @@ private slots: | |||
307 | query.limit = 1; | 307 | query.limit = 1; |
308 | query.liveQuery = false; | 308 | query.liveQuery = false; |
309 | 309 | ||
310 | //Ensure all local data is processed | 310 | // Ensure all local data is processed |
311 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); | 311 | Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); |
312 | 312 | ||
313 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query); | 313 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query); |
314 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); | 314 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); |
315 | //The model is not sorted, but the limited set is sorted, so we can only test for the latest result. | 315 | // The model is not sorted, but the limited set is sorted, so we can only test for the latest result. |
316 | QCOMPARE(model->rowCount(), 1); | 316 | QCOMPARE(model->rowCount(), 1); |
317 | QCOMPARE(model->index(0, 0).data(Sink::Store::DomainObjectRole).value<Sink::ApplicationDomain::Mail::Ptr>()->getProperty("uid").toByteArray(), QByteArray("testLatest")); | 317 | QCOMPARE(model->index(0, 0).data(Sink::Store::DomainObjectRole).value<Sink::ApplicationDomain::Mail::Ptr>()->getProperty("uid").toByteArray(), QByteArray("testLatest")); |
318 | 318 | ||
319 | model->fetchMore(QModelIndex()); | 319 | model->fetchMore(QModelIndex()); |
320 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); | 320 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); |
321 | QCOMPARE(model->rowCount(), 2); | 321 | QCOMPARE(model->rowCount(), 2); |
322 | //We can't make any assumptions about the order of the indexes | 322 | // We can't make any assumptions about the order of the indexes |
323 | // QCOMPARE(model->index(1, 0).data(Sink::Store::DomainObjectRole).value<Sink::ApplicationDomain::Mail::Ptr>()->getProperty("uid").toByteArray(), QByteArray("testSecond")); | 323 | // QCOMPARE(model->index(1, 0).data(Sink::Store::DomainObjectRole).value<Sink::ApplicationDomain::Mail::Ptr>()->getProperty("uid").toByteArray(), QByteArray("testSecond")); |
324 | } | 324 | } |
325 | }; | 325 | }; |
diff --git a/tests/resourcecommunicationtest.cpp b/tests/resourcecommunicationtest.cpp index db8703e..2daf372 100644 --- a/tests/resourcecommunicationtest.cpp +++ b/tests/resourcecommunicationtest.cpp | |||
@@ -51,14 +51,13 @@ private slots: | |||
51 | int errors = 0; | 51 | int errors = 0; |
52 | for (int i = 0; i < count; i++) { | 52 | for (int i = 0; i < count; i++) { |
53 | auto result = resourceAccess.sendCommand(Sink::Commands::PingCommand) | 53 | auto result = resourceAccess.sendCommand(Sink::Commands::PingCommand) |
54 | .then<void>([&complete]() { | 54 | .then<void>([&complete]() { complete++; }, |
55 | complete++; | 55 | [&errors, &complete](int error, const QString &msg) { |
56 | }, | 56 | qWarning() << msg; |
57 | [&errors, &complete](int error, const QString &msg) { | 57 | errors++; |
58 | qWarning() << msg; | 58 | complete++; |
59 | errors++; | 59 | }) |
60 | complete++; | 60 | .exec(); |
61 | }).exec(); | ||
62 | } | 61 | } |
63 | QTRY_COMPARE(complete, count); | 62 | QTRY_COMPARE(complete, count); |
64 | QVERIFY(!errors); | 63 | QVERIFY(!errors); |
@@ -77,17 +76,18 @@ private slots: | |||
77 | int errors = 0; | 76 | int errors = 0; |
78 | for (int i = 0; i < count; i++) { | 77 | for (int i = 0; i < count; i++) { |
79 | resourceAccess.sendCommand(Sink::Commands::PingCommand) | 78 | resourceAccess.sendCommand(Sink::Commands::PingCommand) |
80 | .then<void>([&complete]() { | 79 | .then<void>([&complete]() { complete++; }, |
81 | complete++; | 80 | [&errors, &complete](int error, const QString &msg) { |
82 | }, | 81 | qWarning() << msg; |
83 | [&errors, &complete](int error, const QString &msg) { | 82 | errors++; |
84 | qWarning() << msg; | 83 | complete++; |
85 | errors++; | 84 | }) |
86 | complete++; | 85 | .then<void>([&resourceAccess]() { |
87 | }).then<void>([&resourceAccess]() { | ||
88 | resourceAccess.close(); | 86 | resourceAccess.close(); |
89 | resourceAccess.open(); | 87 | resourceAccess.open(); |
90 | }).exec().waitForFinished(); | 88 | }) |
89 | .exec() | ||
90 | .waitForFinished(); | ||
91 | } | 91 | } |
92 | QTRY_COMPARE(complete, count); | 92 | QTRY_COMPARE(complete, count); |
93 | QVERIFY(!errors); | 93 | QVERIFY(!errors); |
diff --git a/tests/storagebenchmark.cpp b/tests/storagebenchmark.cpp index 8498df9..a1ddcc9 100644 --- a/tests/storagebenchmark.cpp +++ b/tests/storagebenchmark.cpp | |||
@@ -18,7 +18,7 @@ using namespace flatbuffers; | |||
18 | 18 | ||
19 | static QByteArray createEvent() | 19 | static QByteArray createEvent() |
20 | { | 20 | { |
21 | static const size_t attachmentSize = 1024*2; // 2KB | 21 | static const size_t attachmentSize = 1024 * 2; // 2KB |
22 | static uint8_t rawData[attachmentSize]; | 22 | static uint8_t rawData[attachmentSize]; |
23 | static FlatBufferBuilder fbb; | 23 | static FlatBufferBuilder fbb; |
24 | fbb.Clear(); | 24 | fbb.Clear(); |
@@ -26,13 +26,13 @@ static QByteArray createEvent() | |||
26 | uint8_t *rawDataPtr = Q_NULLPTR; | 26 | uint8_t *rawDataPtr = Q_NULLPTR; |
27 | auto summary = fbb.CreateString("summary"); | 27 | auto summary = fbb.CreateString("summary"); |
28 | auto data = fbb.CreateUninitializedVector<uint8_t>(attachmentSize, &rawDataPtr); | 28 | auto data = fbb.CreateUninitializedVector<uint8_t>(attachmentSize, &rawDataPtr); |
29 | //auto data = fbb.CreateVector(rawData, attachmentSize); | 29 | // auto data = fbb.CreateVector(rawData, attachmentSize); |
30 | Calendar::EventBuilder eventBuilder(fbb); | 30 | Calendar::EventBuilder eventBuilder(fbb); |
31 | eventBuilder.add_summary(summary); | 31 | eventBuilder.add_summary(summary); |
32 | eventBuilder.add_attachment(data); | 32 | eventBuilder.add_attachment(data); |
33 | auto eventLocation = eventBuilder.Finish(); | 33 | auto eventLocation = eventBuilder.Finish(); |
34 | Calendar::FinishEventBuffer(fbb, eventLocation); | 34 | Calendar::FinishEventBuffer(fbb, eventLocation); |
35 | memcpy((void*)rawDataPtr, rawData, attachmentSize); | 35 | memcpy((void *)rawDataPtr, rawData, attachmentSize); |
36 | } | 36 | } |
37 | 37 | ||
38 | return QByteArray::fromRawData(reinterpret_cast<const char *>(fbb.GetBufferPointer()), fbb.GetSize()); | 38 | return QByteArray::fromRawData(reinterpret_cast<const char *>(fbb.GetBufferPointer()), fbb.GetSize()); |
@@ -45,7 +45,7 @@ class StorageBenchmark : public QObject | |||
45 | { | 45 | { |
46 | Q_OBJECT | 46 | Q_OBJECT |
47 | private: | 47 | private: |
48 | //This should point to a directory on disk and not a ramdisk (since we're measuring performance) | 48 | // This should point to a directory on disk and not a ramdisk (since we're measuring performance) |
49 | QString testDataPath; | 49 | QString testDataPath; |
50 | QString dbName; | 50 | QString dbName; |
51 | QString filePath; | 51 | QString filePath; |
@@ -76,7 +76,7 @@ private slots: | |||
76 | 76 | ||
77 | QTime time; | 77 | QTime time; |
78 | time.start(); | 78 | time.start(); |
79 | //Test db write time | 79 | // Test db write time |
80 | { | 80 | { |
81 | auto transaction = store->createTransaction(Sink::Storage::ReadWrite); | 81 | auto transaction = store->createTransaction(Sink::Storage::ReadWrite); |
82 | for (int i = 0; i < count; i++) { | 82 | for (int i = 0; i < count; i++) { |
@@ -91,7 +91,7 @@ private slots: | |||
91 | qreal dbWriteDuration = time.restart(); | 91 | qreal dbWriteDuration = time.restart(); |
92 | qreal dbWriteOpsPerMs = count / dbWriteDuration; | 92 | qreal dbWriteOpsPerMs = count / dbWriteDuration; |
93 | 93 | ||
94 | //Test file write time | 94 | // Test file write time |
95 | { | 95 | { |
96 | std::ofstream myfile; | 96 | std::ofstream myfile; |
97 | myfile.open(filePath.toStdString()); | 97 | myfile.open(filePath.toStdString()); |
@@ -103,7 +103,7 @@ private slots: | |||
103 | qreal fileWriteDuration = time.restart(); | 103 | qreal fileWriteDuration = time.restart(); |
104 | qreal fileWriteOpsPerMs = count / fileWriteDuration; | 104 | qreal fileWriteOpsPerMs = count / fileWriteDuration; |
105 | 105 | ||
106 | //Db read time | 106 | // Db read time |
107 | { | 107 | { |
108 | auto transaction = store->createTransaction(Sink::Storage::ReadOnly); | 108 | auto transaction = store->createTransaction(Sink::Storage::ReadOnly); |
109 | auto db = transaction.openDatabase(); | 109 | auto db = transaction.openDatabase(); |
@@ -127,10 +127,10 @@ private slots: | |||
127 | void testSizes() | 127 | void testSizes() |
128 | { | 128 | { |
129 | Sink::Storage store(testDataPath, dbName); | 129 | Sink::Storage store(testDataPath, dbName); |
130 | qDebug() << "Database size [kb]: " << store.diskUsage()/1024; | 130 | qDebug() << "Database size [kb]: " << store.diskUsage() / 1024; |
131 | 131 | ||
132 | QFileInfo fileInfo(filePath); | 132 | QFileInfo fileInfo(filePath); |
133 | qDebug() << "File size [kb]: " << fileInfo.size()/1024; | 133 | qDebug() << "File size [kb]: " << fileInfo.size() / 1024; |
134 | } | 134 | } |
135 | 135 | ||
136 | void testScan() | 136 | void testScan() |
@@ -139,13 +139,15 @@ private slots: | |||
139 | 139 | ||
140 | QBENCHMARK { | 140 | QBENCHMARK { |
141 | int hit = 0; | 141 | int hit = 0; |
142 | store->createTransaction(Sink::Storage::ReadOnly).openDatabase().scan("", [&](const QByteArray &key, const QByteArray &value) -> bool { | 142 | store->createTransaction(Sink::Storage::ReadOnly) |
143 | if (key == "key10000") { | 143 | .openDatabase() |
144 | //qDebug() << "hit"; | 144 | .scan("", [&](const QByteArray &key, const QByteArray &value) -> bool { |
145 | hit++; | 145 | if (key == "key10000") { |
146 | } | 146 | // qDebug() << "hit"; |
147 | return true; | 147 | hit++; |
148 | }); | 148 | } |
149 | return true; | ||
150 | }); | ||
149 | QCOMPARE(hit, 1); | 151 | QCOMPARE(hit, 1); |
150 | } | 152 | } |
151 | } | 153 | } |
diff --git a/tests/storagetest.cpp b/tests/storagetest.cpp index ebd9b8f..31809ce 100644 --- a/tests/storagetest.cpp +++ b/tests/storagetest.cpp | |||
@@ -24,7 +24,7 @@ private: | |||
24 | Sink::Storage storage(testDataPath, dbName, Sink::Storage::ReadWrite); | 24 | Sink::Storage storage(testDataPath, dbName, Sink::Storage::ReadWrite); |
25 | auto transaction = storage.createTransaction(Sink::Storage::ReadWrite); | 25 | auto transaction = storage.createTransaction(Sink::Storage::ReadWrite); |
26 | for (int i = 0; i < count; i++) { | 26 | for (int i = 0; i < count; i++) { |
27 | //This should perhaps become an implementation detail of the db? | 27 | // This should perhaps become an implementation detail of the db? |
28 | if (i % 10000 == 0) { | 28 | if (i % 10000 == 0) { |
29 | if (i > 0) { | 29 | if (i > 0) { |
30 | transaction.commit(); | 30 | transaction.commit(); |
@@ -41,19 +41,20 @@ private: | |||
41 | bool success = true; | 41 | bool success = true; |
42 | bool keyMatch = true; | 42 | bool keyMatch = true; |
43 | const auto reference = keyPrefix + QByteArray::number(i); | 43 | const auto reference = keyPrefix + QByteArray::number(i); |
44 | storage.createTransaction(Sink::Storage::ReadOnly).openDatabase().scan(keyPrefix + QByteArray::number(i), | 44 | storage.createTransaction(Sink::Storage::ReadOnly) |
45 | [&keyMatch, &reference](const QByteArray &key, const QByteArray &value) -> bool { | 45 | .openDatabase() |
46 | if (value != reference) { | 46 | .scan(keyPrefix + QByteArray::number(i), |
47 | qDebug() << "Mismatch while reading"; | 47 | [&keyMatch, &reference](const QByteArray &key, const QByteArray &value) -> bool { |
48 | keyMatch = false; | 48 | if (value != reference) { |
49 | } | 49 | qDebug() << "Mismatch while reading"; |
50 | return keyMatch; | 50 | keyMatch = false; |
51 | }, | 51 | } |
52 | [&success](const Sink::Storage::Error &error) { | 52 | return keyMatch; |
53 | qDebug() << error.message; | 53 | }, |
54 | success = false; | 54 | [&success](const Sink::Storage::Error &error) { |
55 | } | 55 | qDebug() << error.message; |
56 | ); | 56 | success = false; |
57 | }); | ||
57 | return success && keyMatch; | 58 | return success && keyMatch; |
58 | } | 59 | } |
59 | 60 | ||
@@ -87,7 +88,7 @@ private slots: | |||
87 | 88 | ||
88 | populate(count); | 89 | populate(count); |
89 | 90 | ||
90 | //ensure we can read everything back correctly | 91 | // ensure we can read everything back correctly |
91 | { | 92 | { |
92 | Sink::Storage storage(testDataPath, dbName); | 93 | Sink::Storage storage(testDataPath, dbName); |
93 | for (int i = 0; i < count; i++) { | 94 | for (int i = 0; i < count; i++) { |
@@ -101,31 +102,35 @@ private slots: | |||
101 | const int count = 100; | 102 | const int count = 100; |
102 | populate(count); | 103 | populate(count); |
103 | 104 | ||
104 | //ensure we can scan for values | 105 | // ensure we can scan for values |
105 | { | 106 | { |
106 | int hit = 0; | 107 | int hit = 0; |
107 | Sink::Storage store(testDataPath, dbName); | 108 | Sink::Storage store(testDataPath, dbName); |
108 | store.createTransaction(Sink::Storage::ReadOnly).openDatabase().scan("", [&](const QByteArray &key, const QByteArray &value) -> bool { | 109 | store.createTransaction(Sink::Storage::ReadOnly) |
109 | if (key == "key50") { | 110 | .openDatabase() |
110 | hit++; | 111 | .scan("", [&](const QByteArray &key, const QByteArray &value) -> bool { |
111 | } | 112 | if (key == "key50") { |
112 | return true; | 113 | hit++; |
113 | }); | 114 | } |
115 | return true; | ||
116 | }); | ||
114 | QCOMPARE(hit, 1); | 117 | QCOMPARE(hit, 1); |
115 | } | 118 | } |
116 | 119 | ||
117 | //ensure we can read a single value | 120 | // ensure we can read a single value |
118 | { | 121 | { |
119 | int hit = 0; | 122 | int hit = 0; |
120 | bool foundInvalidValue = false; | 123 | bool foundInvalidValue = false; |
121 | Sink::Storage store(testDataPath, dbName); | 124 | Sink::Storage store(testDataPath, dbName); |
122 | store.createTransaction(Sink::Storage::ReadOnly).openDatabase().scan("key50", [&](const QByteArray &key, const QByteArray &value) -> bool { | 125 | store.createTransaction(Sink::Storage::ReadOnly) |
123 | if (key != "key50") { | 126 | .openDatabase() |
124 | foundInvalidValue = true; | 127 | .scan("key50", [&](const QByteArray &key, const QByteArray &value) -> bool { |
125 | } | 128 | if (key != "key50") { |
126 | hit++; | 129 | foundInvalidValue = true; |
127 | return true; | 130 | } |
128 | }); | 131 | hit++; |
132 | return true; | ||
133 | }); | ||
129 | QVERIFY(!foundInvalidValue); | 134 | QVERIFY(!foundInvalidValue); |
130 | QCOMPARE(hit, 1); | 135 | QCOMPARE(hit, 1); |
131 | } | 136 | } |
@@ -137,9 +142,7 @@ private slots: | |||
137 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); | 142 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); |
138 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); | 143 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); |
139 | transaction.openDatabase().scan("key1", [&](const QByteArray &key, const QByteArray &value) -> bool { | 144 | transaction.openDatabase().scan("key1", [&](const QByteArray &key, const QByteArray &value) -> bool { |
140 | transaction.openDatabase().remove(key, [](const Sink::Storage::Error &) { | 145 | transaction.openDatabase().remove(key, [](const Sink::Storage::Error &) { QVERIFY(false); }); |
141 | QVERIFY(false); | ||
142 | }); | ||
143 | return false; | 146 | return false; |
144 | }); | 147 | }); |
145 | } | 148 | } |
@@ -148,12 +151,12 @@ private slots: | |||
148 | { | 151 | { |
149 | populate(3); | 152 | populate(3); |
150 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); | 153 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); |
151 | store.createTransaction(Sink::Storage::ReadOnly).openDatabase().scan("key1", [&](const QByteArray &key, const QByteArray &value) -> bool { | 154 | store.createTransaction(Sink::Storage::ReadOnly) |
152 | store.createTransaction(Sink::Storage::ReadWrite).openDatabase().remove(key, [](const Sink::Storage::Error &) { | 155 | .openDatabase() |
153 | QVERIFY(false); | 156 | .scan("key1", [&](const QByteArray &key, const QByteArray &value) -> bool { |
157 | store.createTransaction(Sink::Storage::ReadWrite).openDatabase().remove(key, [](const Sink::Storage::Error &) { QVERIFY(false); }); | ||
158 | return false; | ||
154 | }); | 159 | }); |
155 | return false; | ||
156 | }); | ||
157 | } | 160 | } |
158 | 161 | ||
159 | void testReadEmptyDb() | 162 | void testReadEmptyDb() |
@@ -166,14 +169,15 @@ private slots: | |||
166 | qDebug() << error.message; | 169 | qDebug() << error.message; |
167 | gotError = true; | 170 | gotError = true; |
168 | }); | 171 | }); |
169 | int numValues = db.scan("", [&](const QByteArray &key, const QByteArray &value) -> bool { | 172 | int numValues = db.scan("", |
170 | gotResult = true; | 173 | [&](const QByteArray &key, const QByteArray &value) -> bool { |
171 | return false; | 174 | gotResult = true; |
172 | }, | 175 | return false; |
173 | [&](const Sink::Storage::Error &error) { | 176 | }, |
174 | qDebug() << error.message; | 177 | [&](const Sink::Storage::Error &error) { |
175 | gotError = true; | 178 | qDebug() << error.message; |
176 | }); | 179 | gotError = true; |
180 | }); | ||
177 | QCOMPARE(numValues, 0); | 181 | QCOMPARE(numValues, 0); |
178 | QVERIFY(!gotResult); | 182 | QVERIFY(!gotResult); |
179 | QVERIFY(!gotError); | 183 | QVERIFY(!gotError); |
@@ -181,20 +185,20 @@ private slots: | |||
181 | 185 | ||
182 | void testConcurrentRead() | 186 | void testConcurrentRead() |
183 | { | 187 | { |
184 | //With a count of 10000 this test is more likely to expose problems, but also takes some time to execute. | 188 | // With a count of 10000 this test is more likely to expose problems, but also takes some time to execute. |
185 | const int count = 1000; | 189 | const int count = 1000; |
186 | 190 | ||
187 | populate(count); | 191 | populate(count); |
188 | // QTest::qWait(500); | 192 | // QTest::qWait(500); |
189 | 193 | ||
190 | //We repeat the test a bunch of times since failing is relatively random | 194 | // We repeat the test a bunch of times since failing is relatively random |
191 | for (int tries = 0; tries < 10; tries++) { | 195 | for (int tries = 0; tries < 10; tries++) { |
192 | bool error = false; | 196 | bool error = false; |
193 | //Try to concurrently read | 197 | // Try to concurrently read |
194 | QList<QFuture<void> > futures; | 198 | QList<QFuture<void>> futures; |
195 | const int concurrencyLevel = 20; | 199 | const int concurrencyLevel = 20; |
196 | for (int num = 0; num < concurrencyLevel; num++) { | 200 | for (int num = 0; num < concurrencyLevel; num++) { |
197 | futures << QtConcurrent::run([this, count, &error](){ | 201 | futures << QtConcurrent::run([this, count, &error]() { |
198 | Sink::Storage storage(testDataPath, dbName, Sink::Storage::ReadOnly); | 202 | Sink::Storage storage(testDataPath, dbName, Sink::Storage::ReadOnly); |
199 | Sink::Storage storage2(testDataPath, dbName + "2", Sink::Storage::ReadOnly); | 203 | Sink::Storage storage2(testDataPath, dbName + "2", Sink::Storage::ReadOnly); |
200 | for (int i = 0; i < count; i++) { | 204 | for (int i = 0; i < count; i++) { |
@@ -205,7 +209,7 @@ private slots: | |||
205 | } | 209 | } |
206 | }); | 210 | }); |
207 | } | 211 | } |
208 | for(auto future : futures) { | 212 | for (auto future : futures) { |
209 | future.waitForFinished(); | 213 | future.waitForFinished(); |
210 | } | 214 | } |
211 | QVERIFY(!error); | 215 | QVERIFY(!error); |
@@ -226,17 +230,18 @@ private slots: | |||
226 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); | 230 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); |
227 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); | 231 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); |
228 | auto db = transaction.openDatabase("default", nullptr, false); | 232 | auto db = transaction.openDatabase("default", nullptr, false); |
229 | db.write("key","value"); | 233 | db.write("key", "value"); |
230 | db.write("key","value"); | 234 | db.write("key", "value"); |
231 | 235 | ||
232 | int numValues = db.scan("", [&](const QByteArray &key, const QByteArray &value) -> bool { | 236 | int numValues = db.scan("", |
233 | gotResult = true; | 237 | [&](const QByteArray &key, const QByteArray &value) -> bool { |
234 | return true; | 238 | gotResult = true; |
235 | }, | 239 | return true; |
236 | [&](const Sink::Storage::Error &error) { | 240 | }, |
237 | qDebug() << error.message; | 241 | [&](const Sink::Storage::Error &error) { |
238 | gotError = true; | 242 | qDebug() << error.message; |
239 | }); | 243 | gotError = true; |
244 | }); | ||
240 | 245 | ||
241 | QCOMPARE(numValues, 1); | 246 | QCOMPARE(numValues, 1); |
242 | QVERIFY(!gotError); | 247 | QVERIFY(!gotError); |
@@ -249,16 +254,17 @@ private slots: | |||
249 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); | 254 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); |
250 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); | 255 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); |
251 | auto db = transaction.openDatabase("default", nullptr, true); | 256 | auto db = transaction.openDatabase("default", nullptr, true); |
252 | db.write("key","value1"); | 257 | db.write("key", "value1"); |
253 | db.write("key","value2"); | 258 | db.write("key", "value2"); |
254 | int numValues = db.scan("key", [&](const QByteArray &key, const QByteArray &value) -> bool { | 259 | int numValues = db.scan("key", |
255 | gotResult = true; | 260 | [&](const QByteArray &key, const QByteArray &value) -> bool { |
256 | return true; | 261 | gotResult = true; |
257 | }, | 262 | return true; |
258 | [&](const Sink::Storage::Error &error) { | 263 | }, |
259 | qDebug() << error.message; | 264 | [&](const Sink::Storage::Error &error) { |
260 | gotError = true; | 265 | qDebug() << error.message; |
261 | }); | 266 | gotError = true; |
267 | }); | ||
262 | 268 | ||
263 | QCOMPARE(numValues, 2); | 269 | QCOMPARE(numValues, 2); |
264 | QVERIFY(!gotError); | 270 | QVERIFY(!gotError); |
@@ -269,14 +275,17 @@ private slots: | |||
269 | bool gotResult = false; | 275 | bool gotResult = false; |
270 | bool gotError = false; | 276 | bool gotError = false; |
271 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadOnly); | 277 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadOnly); |
272 | int numValues = store.createTransaction(Sink::Storage::ReadOnly).openDatabase("test").scan("", [&](const QByteArray &key, const QByteArray &value) -> bool { | 278 | int numValues = store.createTransaction(Sink::Storage::ReadOnly) |
273 | gotResult = true; | 279 | .openDatabase("test") |
274 | return false; | 280 | .scan("", |
275 | }, | 281 | [&](const QByteArray &key, const QByteArray &value) -> bool { |
276 | [&](const Sink::Storage::Error &error) { | 282 | gotResult = true; |
277 | qDebug() << error.message; | 283 | return false; |
278 | gotError = true; | 284 | }, |
279 | }); | 285 | [&](const Sink::Storage::Error &error) { |
286 | qDebug() << error.message; | ||
287 | gotError = true; | ||
288 | }); | ||
280 | QCOMPARE(numValues, 0); | 289 | QCOMPARE(numValues, 0); |
281 | QVERIFY(!gotResult); | 290 | QVERIFY(!gotResult); |
282 | QVERIFY(!gotError); | 291 | QVERIFY(!gotError); |
@@ -286,10 +295,12 @@ private slots: | |||
286 | { | 295 | { |
287 | bool gotError = false; | 296 | bool gotError = false; |
288 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); | 297 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); |
289 | store.createTransaction(Sink::Storage::ReadWrite).openDatabase("test").write("key1", "value1", [&](const Sink::Storage::Error &error) { | 298 | store.createTransaction(Sink::Storage::ReadWrite) |
290 | qDebug() << error.message; | 299 | .openDatabase("test") |
291 | gotError = true; | 300 | .write("key1", "value1", [&](const Sink::Storage::Error &error) { |
292 | }); | 301 | qDebug() << error.message; |
302 | gotError = true; | ||
303 | }); | ||
293 | QVERIFY(!gotError); | 304 | QVERIFY(!gotError); |
294 | } | 305 | } |
295 | 306 | ||
@@ -297,24 +308,24 @@ private slots: | |||
297 | { | 308 | { |
298 | bool gotError = false; | 309 | bool gotError = false; |
299 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); | 310 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); |
300 | store.createTransaction(Sink::Storage::ReadWrite).openDatabase("test", nullptr, true).write("key1", "value1", [&](const Sink::Storage::Error &error) { | 311 | store.createTransaction(Sink::Storage::ReadWrite) |
301 | qDebug() << error.message; | 312 | .openDatabase("test", nullptr, true) |
302 | gotError = true; | 313 | .write("key1", "value1", [&](const Sink::Storage::Error &error) { |
303 | }); | 314 | qDebug() << error.message; |
315 | gotError = true; | ||
316 | }); | ||
304 | QVERIFY(!gotError); | 317 | QVERIFY(!gotError); |
305 | } | 318 | } |
306 | 319 | ||
307 | //By default we want only exact matches | 320 | // By default we want only exact matches |
308 | void testSubstringKeys() | 321 | void testSubstringKeys() |
309 | { | 322 | { |
310 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); | 323 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); |
311 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); | 324 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); |
312 | auto db = transaction.openDatabase("test", nullptr, true); | 325 | auto db = transaction.openDatabase("test", nullptr, true); |
313 | db.write("sub","value1"); | 326 | db.write("sub", "value1"); |
314 | db.write("subsub","value2"); | 327 | db.write("subsub", "value2"); |
315 | int numValues = db.scan("sub", [&](const QByteArray &key, const QByteArray &value) -> bool { | 328 | int numValues = db.scan("sub", [&](const QByteArray &key, const QByteArray &value) -> bool { return true; }); |
316 | return true; | ||
317 | }); | ||
318 | 329 | ||
319 | QCOMPARE(numValues, 1); | 330 | QCOMPARE(numValues, 1); |
320 | } | 331 | } |
@@ -324,12 +335,10 @@ private slots: | |||
324 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); | 335 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); |
325 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); | 336 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); |
326 | auto db = transaction.openDatabase("test", nullptr, false); | 337 | auto db = transaction.openDatabase("test", nullptr, false); |
327 | db.write("sub","value1"); | 338 | db.write("sub", "value1"); |
328 | db.write("subsub","value2"); | 339 | db.write("subsub", "value2"); |
329 | db.write("wubsub","value3"); | 340 | db.write("wubsub", "value3"); |
330 | int numValues = db.scan("sub", [&](const QByteArray &key, const QByteArray &value) -> bool { | 341 | int numValues = db.scan("sub", [&](const QByteArray &key, const QByteArray &value) -> bool { return true; }, nullptr, true); |
331 | return true; | ||
332 | }, nullptr, true); | ||
333 | 342 | ||
334 | QCOMPARE(numValues, 2); | 343 | QCOMPARE(numValues, 2); |
335 | } | 344 | } |
@@ -339,12 +348,10 @@ private slots: | |||
339 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); | 348 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); |
340 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); | 349 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); |
341 | auto db = transaction.openDatabase("test", nullptr, true); | 350 | auto db = transaction.openDatabase("test", nullptr, true); |
342 | db.write("sub","value1"); | 351 | db.write("sub", "value1"); |
343 | db.write("subsub","value2"); | 352 | db.write("subsub", "value2"); |
344 | db.write("wubsub","value3"); | 353 | db.write("wubsub", "value3"); |
345 | int numValues = db.scan("sub", [&](const QByteArray &key, const QByteArray &value) -> bool { | 354 | int numValues = db.scan("sub", [&](const QByteArray &key, const QByteArray &value) -> bool { return true; }, nullptr, true); |
346 | return true; | ||
347 | }, nullptr, true); | ||
348 | 355 | ||
349 | QCOMPARE(numValues, 2); | 356 | QCOMPARE(numValues, 2); |
350 | } | 357 | } |
@@ -354,9 +361,9 @@ private slots: | |||
354 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); | 361 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); |
355 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); | 362 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); |
356 | auto db = transaction.openDatabase("test", nullptr, false); | 363 | auto db = transaction.openDatabase("test", nullptr, false); |
357 | db.write("sub_2","value2"); | 364 | db.write("sub_2", "value2"); |
358 | db.write("sub_1","value1"); | 365 | db.write("sub_1", "value1"); |
359 | db.write("sub_3","value3"); | 366 | db.write("sub_3", "value3"); |
360 | QList<QByteArray> results; | 367 | QList<QByteArray> results; |
361 | int numValues = db.scan("sub", [&](const QByteArray &key, const QByteArray &value) -> bool { | 368 | int numValues = db.scan("sub", [&](const QByteArray &key, const QByteArray &value) -> bool { |
362 | results << value; | 369 | results << value; |
@@ -369,16 +376,14 @@ private slots: | |||
369 | QCOMPARE(results.at(2), QByteArray("value3")); | 376 | QCOMPARE(results.at(2), QByteArray("value3")); |
370 | } | 377 | } |
371 | 378 | ||
372 | //Ensure we don't retrieve a key that is greater than the current key. We only want equal keys. | 379 | // Ensure we don't retrieve a key that is greater than the current key. We only want equal keys. |
373 | void testKeyRange() | 380 | void testKeyRange() |
374 | { | 381 | { |
375 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); | 382 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); |
376 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); | 383 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); |
377 | auto db = transaction.openDatabase("test", nullptr, true); | 384 | auto db = transaction.openDatabase("test", nullptr, true); |
378 | db.write("sub1","value1"); | 385 | db.write("sub1", "value1"); |
379 | int numValues = db.scan("sub", [&](const QByteArray &key, const QByteArray &value) -> bool { | 386 | int numValues = db.scan("sub", [&](const QByteArray &key, const QByteArray &value) -> bool { return true; }); |
380 | return true; | ||
381 | }); | ||
382 | 387 | ||
383 | QCOMPARE(numValues, 0); | 388 | QCOMPARE(numValues, 0); |
384 | } | 389 | } |
@@ -388,14 +393,12 @@ private slots: | |||
388 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); | 393 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); |
389 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); | 394 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); |
390 | auto db = transaction.openDatabase("test", nullptr, false); | 395 | auto db = transaction.openDatabase("test", nullptr, false); |
391 | db.write("sub1","value1"); | 396 | db.write("sub1", "value1"); |
392 | db.write("sub2","value2"); | 397 | db.write("sub2", "value2"); |
393 | db.write("wub3","value3"); | 398 | db.write("wub3", "value3"); |
394 | db.write("wub4","value4"); | 399 | db.write("wub4", "value4"); |
395 | QByteArray result; | 400 | QByteArray result; |
396 | db.findLatest("sub", [&](const QByteArray &key, const QByteArray &value) { | 401 | db.findLatest("sub", [&](const QByteArray &key, const QByteArray &value) { result = value; }); |
397 | result = value; | ||
398 | }); | ||
399 | 402 | ||
400 | QCOMPARE(result, QByteArray("value2")); | 403 | QCOMPARE(result, QByteArray("value2")); |
401 | } | 404 | } |
@@ -405,11 +408,9 @@ private slots: | |||
405 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); | 408 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); |
406 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); | 409 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); |
407 | auto db = transaction.openDatabase("test", nullptr, false); | 410 | auto db = transaction.openDatabase("test", nullptr, false); |
408 | db.write("sub2","value2"); | 411 | db.write("sub2", "value2"); |
409 | QByteArray result; | 412 | QByteArray result; |
410 | db.findLatest("sub", [&](const QByteArray &key, const QByteArray &value) { | 413 | db.findLatest("sub", [&](const QByteArray &key, const QByteArray &value) { result = value; }); |
411 | result = value; | ||
412 | }); | ||
413 | 414 | ||
414 | QCOMPARE(result, QByteArray("value2")); | 415 | QCOMPARE(result, QByteArray("value2")); |
415 | } | 416 | } |
@@ -419,12 +420,10 @@ private slots: | |||
419 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); | 420 | Sink::Storage store(testDataPath, dbName, Sink::Storage::ReadWrite); |
420 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); | 421 | auto transaction = store.createTransaction(Sink::Storage::ReadWrite); |
421 | auto db = transaction.openDatabase("test", nullptr, false); | 422 | auto db = transaction.openDatabase("test", nullptr, false); |
422 | db.write("sub2","value2"); | 423 | db.write("sub2", "value2"); |
423 | db.write("wub3","value3"); | 424 | db.write("wub3", "value3"); |
424 | QByteArray result; | 425 | QByteArray result; |
425 | db.findLatest("wub", [&](const QByteArray &key, const QByteArray &value) { | 426 | db.findLatest("wub", [&](const QByteArray &key, const QByteArray &value) { result = value; }); |
426 | result = value; | ||
427 | }); | ||
428 | 427 | ||
429 | QCOMPARE(result, QByteArray("value3")); | 428 | QCOMPARE(result, QByteArray("value3")); |
430 | } | 429 | } |
diff --git a/tests/testimplementations.h b/tests/testimplementations.h index adfdab3..688875d 100644 --- a/tests/testimplementations.h +++ b/tests/testimplementations.h | |||
@@ -28,7 +28,7 @@ | |||
28 | #include <common/genericresource.h> | 28 | #include <common/genericresource.h> |
29 | #include <common/commands.h> | 29 | #include <common/commands.h> |
30 | 30 | ||
31 | //Replace with something different | 31 | // Replace with something different |
32 | #include "event_generated.h" | 32 | #include "event_generated.h" |
33 | #include "mail_generated.h" | 33 | #include "mail_generated.h" |
34 | #include "createentity_generated.h" | 34 | #include "createentity_generated.h" |
@@ -36,37 +36,48 @@ | |||
36 | class TestEventAdaptorFactory : public DomainTypeAdaptorFactory<Sink::ApplicationDomain::Event, Sink::ApplicationDomain::Buffer::Event, Sink::ApplicationDomain::Buffer::EventBuilder> | 36 | class TestEventAdaptorFactory : public DomainTypeAdaptorFactory<Sink::ApplicationDomain::Event, Sink::ApplicationDomain::Buffer::Event, Sink::ApplicationDomain::Buffer::EventBuilder> |
37 | { | 37 | { |
38 | public: | 38 | public: |
39 | TestEventAdaptorFactory() | 39 | TestEventAdaptorFactory() : DomainTypeAdaptorFactory() |
40 | : DomainTypeAdaptorFactory() | ||
41 | { | 40 | { |
42 | } | 41 | } |
43 | 42 | ||
44 | virtual ~TestEventAdaptorFactory() {}; | 43 | virtual ~TestEventAdaptorFactory(){}; |
45 | }; | 44 | }; |
46 | 45 | ||
47 | class TestMailAdaptorFactory : public DomainTypeAdaptorFactory<Sink::ApplicationDomain::Mail, Sink::ApplicationDomain::Buffer::Mail, Sink::ApplicationDomain::Buffer::MailBuilder> | 46 | class TestMailAdaptorFactory : public DomainTypeAdaptorFactory<Sink::ApplicationDomain::Mail, Sink::ApplicationDomain::Buffer::Mail, Sink::ApplicationDomain::Buffer::MailBuilder> |
48 | { | 47 | { |
49 | public: | 48 | public: |
50 | TestMailAdaptorFactory() | 49 | TestMailAdaptorFactory() : DomainTypeAdaptorFactory() |
51 | : DomainTypeAdaptorFactory() | ||
52 | { | 50 | { |
53 | } | 51 | } |
54 | 52 | ||
55 | virtual ~TestMailAdaptorFactory() {}; | 53 | virtual ~TestMailAdaptorFactory(){}; |
56 | }; | 54 | }; |
57 | 55 | ||
58 | class TestResourceAccess : public Sink::ResourceAccessInterface | 56 | class TestResourceAccess : public Sink::ResourceAccessInterface |
59 | { | 57 | { |
60 | Q_OBJECT | 58 | Q_OBJECT |
61 | public: | 59 | public: |
62 | virtual ~TestResourceAccess() {}; | 60 | virtual ~TestResourceAccess(){}; |
63 | KAsync::Job<void> sendCommand(int commandId) Q_DECL_OVERRIDE { return KAsync::null<void>(); } | 61 | KAsync::Job<void> sendCommand(int commandId) Q_DECL_OVERRIDE |
64 | KAsync::Job<void> sendCommand(int commandId, flatbuffers::FlatBufferBuilder &fbb) Q_DECL_OVERRIDE { return KAsync::null<void>(); } | 62 | { |
65 | KAsync::Job<void> synchronizeResource(bool remoteSync, bool localSync) Q_DECL_OVERRIDE { return KAsync::null<void>(); } | 63 | return KAsync::null<void>(); |
64 | } | ||
65 | KAsync::Job<void> sendCommand(int commandId, flatbuffers::FlatBufferBuilder &fbb) Q_DECL_OVERRIDE | ||
66 | { | ||
67 | return KAsync::null<void>(); | ||
68 | } | ||
69 | KAsync::Job<void> synchronizeResource(bool remoteSync, bool localSync) Q_DECL_OVERRIDE | ||
70 | { | ||
71 | return KAsync::null<void>(); | ||
72 | } | ||
66 | 73 | ||
67 | public slots: | 74 | public slots: |
68 | void open() Q_DECL_OVERRIDE {} | 75 | void open() Q_DECL_OVERRIDE |
69 | void close() Q_DECL_OVERRIDE {} | 76 | { |
77 | } | ||
78 | void close() Q_DECL_OVERRIDE | ||
79 | { | ||
80 | } | ||
70 | }; | 81 | }; |
71 | 82 | ||
72 | class TestResourceFacade : public Sink::GenericFacade<Sink::ApplicationDomain::Event> | 83 | class TestResourceFacade : public Sink::GenericFacade<Sink::ApplicationDomain::Event> |
@@ -75,11 +86,9 @@ public: | |||
75 | TestResourceFacade(const QByteArray &instanceIdentifier, const QSharedPointer<Sink::ResourceAccessInterface> resourceAccess) | 86 | TestResourceFacade(const QByteArray &instanceIdentifier, const QSharedPointer<Sink::ResourceAccessInterface> resourceAccess) |
76 | : Sink::GenericFacade<Sink::ApplicationDomain::Event>(instanceIdentifier, QSharedPointer<TestEventAdaptorFactory>::create(), resourceAccess) | 87 | : Sink::GenericFacade<Sink::ApplicationDomain::Event>(instanceIdentifier, QSharedPointer<TestEventAdaptorFactory>::create(), resourceAccess) |
77 | { | 88 | { |
78 | |||
79 | } | 89 | } |
80 | virtual ~TestResourceFacade() | 90 | virtual ~TestResourceFacade() |
81 | { | 91 | { |
82 | |||
83 | } | 92 | } |
84 | }; | 93 | }; |
85 | 94 | ||
@@ -89,19 +98,16 @@ public: | |||
89 | TestMailResourceFacade(const QByteArray &instanceIdentifier, const QSharedPointer<Sink::ResourceAccessInterface> resourceAccess) | 98 | TestMailResourceFacade(const QByteArray &instanceIdentifier, const QSharedPointer<Sink::ResourceAccessInterface> resourceAccess) |
90 | : Sink::GenericFacade<Sink::ApplicationDomain::Mail>(instanceIdentifier, QSharedPointer<TestMailAdaptorFactory>::create(), resourceAccess) | 99 | : Sink::GenericFacade<Sink::ApplicationDomain::Mail>(instanceIdentifier, QSharedPointer<TestMailAdaptorFactory>::create(), resourceAccess) |
91 | { | 100 | { |
92 | |||
93 | } | 101 | } |
94 | virtual ~TestMailResourceFacade() | 102 | virtual ~TestMailResourceFacade() |
95 | { | 103 | { |
96 | |||
97 | } | 104 | } |
98 | }; | 105 | }; |
99 | 106 | ||
100 | class TestResource : public Sink::GenericResource | 107 | class TestResource : public Sink::GenericResource |
101 | { | 108 | { |
102 | public: | 109 | public: |
103 | TestResource(const QByteArray &instanceIdentifier, QSharedPointer<Sink::Pipeline> pipeline) | 110 | TestResource(const QByteArray &instanceIdentifier, QSharedPointer<Sink::Pipeline> pipeline) : Sink::GenericResource(instanceIdentifier, pipeline) |
104 | : Sink::GenericResource(instanceIdentifier, pipeline) | ||
105 | { | 111 | { |
106 | } | 112 | } |
107 | 113 | ||
@@ -126,4 +132,3 @@ QByteArray createCommand(const DomainType &domainObject, DomainTypeAdaptorFactor | |||
126 | Sink::Commands::FinishCreateEntityBuffer(fbb, location); | 132 | Sink::Commands::FinishCreateEntityBuffer(fbb, location); |
127 | return QByteArray(reinterpret_cast<const char *>(fbb.GetBufferPointer()), fbb.GetSize()); | 133 | return QByteArray(reinterpret_cast<const char *>(fbb.GetBufferPointer()), fbb.GetSize()); |
128 | } | 134 | } |
129 | |||