diff options
Diffstat (limited to 'dummyresource/facade.cpp')
-rw-r--r-- | dummyresource/facade.cpp | 89 |
1 files changed, 23 insertions, 66 deletions
diff --git a/dummyresource/facade.cpp b/dummyresource/facade.cpp index 949b4c4..1477fcf 100644 --- a/dummyresource/facade.cpp +++ b/dummyresource/facade.cpp | |||
@@ -28,7 +28,6 @@ | |||
28 | #include "event_generated.h" | 28 | #include "event_generated.h" |
29 | #include "entity_generated.h" | 29 | #include "entity_generated.h" |
30 | #include "metadata_generated.h" | 30 | #include "metadata_generated.h" |
31 | #include "createentity_generated.h" | ||
32 | #include "domainadaptor.h" | 31 | #include "domainadaptor.h" |
33 | #include <common/entitybuffer.h> | 32 | #include <common/entitybuffer.h> |
34 | #include <common/index.h> | 33 | #include <common/index.h> |
@@ -37,9 +36,9 @@ | |||
37 | using namespace DummyCalendar; | 36 | using namespace DummyCalendar; |
38 | using namespace flatbuffers; | 37 | using namespace flatbuffers; |
39 | 38 | ||
39 | |||
40 | DummyResourceFacade::DummyResourceFacade() | 40 | DummyResourceFacade::DummyResourceFacade() |
41 | : Akonadi2::StoreFacade<Akonadi2::Domain::Event>(), | 41 | : Akonadi2::GenericFacade<Akonadi2::ApplicationDomain::Event>("org.kde.dummy"), |
42 | mResourceAccess(new Akonadi2::ResourceAccess("org.kde.dummy")), | ||
43 | mFactory(new DummyEventAdaptorFactory) | 42 | mFactory(new DummyEventAdaptorFactory) |
44 | { | 43 | { |
45 | } | 44 | } |
@@ -48,38 +47,30 @@ DummyResourceFacade::~DummyResourceFacade() | |||
48 | { | 47 | { |
49 | } | 48 | } |
50 | 49 | ||
51 | Async::Job<void> DummyResourceFacade::create(const Akonadi2::Domain::Event &domainObject) | 50 | Async::Job<void> DummyResourceFacade::create(const Akonadi2::ApplicationDomain::Event &domainObject) |
52 | { | 51 | { |
53 | flatbuffers::FlatBufferBuilder entityFbb; | 52 | flatbuffers::FlatBufferBuilder entityFbb; |
54 | mFactory->createBuffer(domainObject, entityFbb); | 53 | mFactory->createBuffer(domainObject, entityFbb); |
55 | 54 | return sendCreateCommand("event", QByteArray::fromRawData(reinterpret_cast<const char*>(entityFbb.GetBufferPointer()), entityFbb.GetSize())); | |
56 | flatbuffers::FlatBufferBuilder fbb; | ||
57 | //This is the resource buffer type and not the domain type | ||
58 | auto type = fbb.CreateString("event"); | ||
59 | auto delta = fbb.CreateVector<uint8_t>(entityFbb.GetBufferPointer(), entityFbb.GetSize()); | ||
60 | auto location = Akonadi2::Commands::CreateCreateEntity(fbb, type, delta); | ||
61 | Akonadi2::Commands::FinishCreateEntityBuffer(fbb, location); | ||
62 | mResourceAccess->open(); | ||
63 | return mResourceAccess->sendCommand(Akonadi2::Commands::CreateEntityCommand, fbb); | ||
64 | } | 55 | } |
65 | 56 | ||
66 | Async::Job<void> DummyResourceFacade::modify(const Akonadi2::Domain::Event &domainObject) | 57 | Async::Job<void> DummyResourceFacade::modify(const Akonadi2::ApplicationDomain::Event &domainObject) |
67 | { | 58 | { |
68 | //Create message buffer and send to resource | 59 | //Create message buffer and send to resource |
69 | return Async::null<void>(); | 60 | return Async::null<void>(); |
70 | } | 61 | } |
71 | 62 | ||
72 | Async::Job<void> DummyResourceFacade::remove(const Akonadi2::Domain::Event &domainObject) | 63 | Async::Job<void> DummyResourceFacade::remove(const Akonadi2::ApplicationDomain::Event &domainObject) |
73 | { | 64 | { |
74 | //Create message buffer and send to resource | 65 | //Create message buffer and send to resource |
75 | return Async::null<void>(); | 66 | return Async::null<void>(); |
76 | } | 67 | } |
77 | 68 | ||
78 | static std::function<bool(const std::string &key, DummyEvent const *buffer, Akonadi2::Domain::Buffer::Event const *local)> prepareQuery(const Akonadi2::Query &query) | 69 | static std::function<bool(const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local)> prepareQuery(const Akonadi2::Query &query) |
79 | { | 70 | { |
80 | //Compose some functions to make query matching fast. | 71 | //Compose some functions to make query matching fast. |
81 | //This way we can process the query once, and convert all values into something that can be compared quickly | 72 | //This way we can process the query once, and convert all values into something that can be compared quickly |
82 | std::function<bool(const std::string &key, DummyEvent const *buffer, Akonadi2::Domain::Buffer::Event const *local)> preparedQuery; | 73 | std::function<bool(const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local)> preparedQuery; |
83 | if (!query.ids.isEmpty()) { | 74 | if (!query.ids.isEmpty()) { |
84 | //Match by id | 75 | //Match by id |
85 | //TODO: for id's a direct lookup would be way faster | 76 | //TODO: for id's a direct lookup would be way faster |
@@ -90,7 +81,7 @@ static std::function<bool(const std::string &key, DummyEvent const *buffer, Akon | |||
90 | for (const auto &id : query.ids) { | 81 | for (const auto &id : query.ids) { |
91 | ids << id.toStdString(); | 82 | ids << id.toStdString(); |
92 | } | 83 | } |
93 | preparedQuery = [ids](const std::string &key, DummyEvent const *buffer, Akonadi2::Domain::Buffer::Event const *local) { | 84 | preparedQuery = [ids](const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local) { |
94 | if (ids.contains(key)) { | 85 | if (ids.contains(key)) { |
95 | return true; | 86 | return true; |
96 | } | 87 | } |
@@ -99,7 +90,7 @@ static std::function<bool(const std::string &key, DummyEvent const *buffer, Akon | |||
99 | } else if (!query.propertyFilter.isEmpty()) { | 90 | } else if (!query.propertyFilter.isEmpty()) { |
100 | if (query.propertyFilter.contains("uid")) { | 91 | if (query.propertyFilter.contains("uid")) { |
101 | const QByteArray uid = query.propertyFilter.value("uid").toByteArray(); | 92 | const QByteArray uid = query.propertyFilter.value("uid").toByteArray(); |
102 | preparedQuery = [uid](const std::string &key, DummyEvent const *buffer, Akonadi2::Domain::Buffer::Event const *local) { | 93 | preparedQuery = [uid](const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local) { |
103 | if (local && local->uid() && (QByteArray::fromRawData(local->uid()->c_str(), local->uid()->size()) == uid)) { | 94 | if (local && local->uid() && (QByteArray::fromRawData(local->uid()->c_str(), local->uid()->size()) == uid)) { |
104 | return true; | 95 | return true; |
105 | } | 96 | } |
@@ -108,32 +99,14 @@ static std::function<bool(const std::string &key, DummyEvent const *buffer, Akon | |||
108 | } | 99 | } |
109 | } else { | 100 | } else { |
110 | //Match everything | 101 | //Match everything |
111 | preparedQuery = [](const std::string &key, DummyEvent const *buffer, Akonadi2::Domain::Buffer::Event const *local) { | 102 | preparedQuery = [](const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local) { |
112 | return true; | 103 | return true; |
113 | }; | 104 | }; |
114 | } | 105 | } |
115 | return preparedQuery; | 106 | return preparedQuery; |
116 | } | 107 | } |
117 | 108 | ||
118 | Async::Job<void> DummyResourceFacade::synchronizeResource(bool sync, bool processAll) | 109 | void DummyResourceFacade::readValue(QSharedPointer<Akonadi2::Storage> storage, const QByteArray &key, const std::function<void(const Akonadi2::ApplicationDomain::Event::Ptr &)> &resultCallback, std::function<bool(const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local)> preparedQuery) |
119 | { | ||
120 | //TODO check if a sync is necessary | ||
121 | //TODO Only sync what was requested | ||
122 | //TODO timeout | ||
123 | |||
124 | if (sync || processAll) { | ||
125 | return Async::start<void>([=](Async::Future<void> &future) { | ||
126 | mResourceAccess->open(); | ||
127 | mResourceAccess->synchronizeResource(sync, processAll).then<void>([&future](Async::Future<void> &f) { | ||
128 | future.setFinished(); | ||
129 | f.setFinished(); | ||
130 | }).exec(); | ||
131 | }); | ||
132 | } | ||
133 | return Async::null<void>(); | ||
134 | } | ||
135 | |||
136 | void DummyResourceFacade::readValue(QSharedPointer<Akonadi2::Storage> storage, const QByteArray &key, const std::function<void(const Akonadi2::Domain::Event::Ptr &)> &resultCallback, std::function<bool(const std::string &key, DummyEvent const *buffer, Akonadi2::Domain::Buffer::Event const *local)> preparedQuery) | ||
137 | { | 110 | { |
138 | storage->scan(key, [=](void *keyValue, int keySize, void *dataValue, int dataSize) -> bool { | 111 | storage->scan(key, [=](void *keyValue, int keySize, void *dataValue, int dataSize) -> bool { |
139 | 112 | ||
@@ -145,31 +118,11 @@ void DummyResourceFacade::readValue(QSharedPointer<Akonadi2::Storage> storage, c | |||
145 | //Extract buffers | 118 | //Extract buffers |
146 | Akonadi2::EntityBuffer buffer(dataValue, dataSize); | 119 | Akonadi2::EntityBuffer buffer(dataValue, dataSize); |
147 | 120 | ||
148 | DummyEvent const *resourceBuffer = 0; | 121 | const auto resourceBuffer = Akonadi2::EntityBuffer::readBuffer<DummyEvent>(buffer.entity().resource()); |
149 | if (auto resourceData = buffer.entity().resource()) { | 122 | const auto localBuffer = Akonadi2::EntityBuffer::readBuffer<Akonadi2::ApplicationDomain::Buffer::Event>(buffer.entity().local()); |
150 | flatbuffers::Verifier verifyer(resourceData->Data(), resourceData->size()); | 123 | const auto metadataBuffer = Akonadi2::EntityBuffer::readBuffer<Akonadi2::Metadata>(buffer.entity().metadata()); |
151 | if (VerifyDummyEventBuffer(verifyer)) { | ||
152 | resourceBuffer = GetDummyEvent(resourceData->Data()); | ||
153 | } | ||
154 | } | ||
155 | |||
156 | Akonadi2::Domain::Buffer::Event const *localBuffer = 0; | ||
157 | if (auto localData = buffer.entity().local()) { | ||
158 | flatbuffers::Verifier verifyer(localData->Data(), localData->size()); | ||
159 | if (Akonadi2::Domain::Buffer::VerifyEventBuffer(verifyer)) { | ||
160 | localBuffer = Akonadi2::Domain::Buffer::GetEvent(localData->Data()); | ||
161 | } | ||
162 | } | ||
163 | |||
164 | Akonadi2::Metadata const *metadataBuffer = 0; | ||
165 | if (auto metadataData = buffer.entity().metadata()) { | ||
166 | flatbuffers::Verifier verifyer(metadataData->Data(), metadataData->size()); | ||
167 | if (Akonadi2::VerifyMetadataBuffer(verifyer)) { | ||
168 | metadataBuffer = Akonadi2::GetMetadata(metadataData->Data()); | ||
169 | } | ||
170 | } | ||
171 | 124 | ||
172 | if (!resourceBuffer || !metadataBuffer) { | 125 | if ((!resourceBuffer && !localBuffer) || !metadataBuffer) { |
173 | qWarning() << "invalid buffer " << QByteArray::fromRawData(static_cast<char*>(keyValue), keySize); | 126 | qWarning() << "invalid buffer " << QByteArray::fromRawData(static_cast<char*>(keyValue), keySize); |
174 | return true; | 127 | return true; |
175 | } | 128 | } |
@@ -182,8 +135,9 @@ void DummyResourceFacade::readValue(QSharedPointer<Akonadi2::Storage> storage, c | |||
182 | //Not i.e. for tags that are stored as flags in each entity of an imap store. | 135 | //Not i.e. for tags that are stored as flags in each entity of an imap store. |
183 | auto adaptor = mFactory->createAdaptor(buffer.entity()); | 136 | auto adaptor = mFactory->createAdaptor(buffer.entity()); |
184 | //TODO only copy requested properties | 137 | //TODO only copy requested properties |
185 | auto memoryAdaptor = QSharedPointer<Akonadi2::Domain::MemoryBufferAdaptor>::create(*adaptor); | 138 | auto memoryAdaptor = QSharedPointer<Akonadi2::ApplicationDomain::MemoryBufferAdaptor>::create(*adaptor); |
186 | auto event = QSharedPointer<Akonadi2::Domain::Event>::create("org.kde.dummy", QString::fromUtf8(static_cast<char*>(keyValue), keySize), revision, memoryAdaptor); | 139 | // here we could copy additional properties that don't have a 1:1 mapping, such as separately stored tags. |
140 | auto event = QSharedPointer<Akonadi2::ApplicationDomain::Event>::create("org.kde.dummy", QByteArray::fromRawData(static_cast<char*>(keyValue), keySize), revision, memoryAdaptor); | ||
187 | resultCallback(event); | 141 | resultCallback(event); |
188 | } | 142 | } |
189 | return true; | 143 | return true; |
@@ -193,7 +147,7 @@ void DummyResourceFacade::readValue(QSharedPointer<Akonadi2::Storage> storage, c | |||
193 | }); | 147 | }); |
194 | } | 148 | } |
195 | 149 | ||
196 | Async::Job<void> DummyResourceFacade::load(const Akonadi2::Query &query, const std::function<void(const Akonadi2::Domain::Event::Ptr &)> &resultCallback) | 150 | Async::Job<void> DummyResourceFacade::load(const Akonadi2::Query &query, const std::function<void(const Akonadi2::ApplicationDomain::Event::Ptr &)> &resultCallback) |
197 | { | 151 | { |
198 | return synchronizeResource(query.syncOnDemand, query.processAll).then<void>([=](Async::Future<void> &future) { | 152 | return synchronizeResource(query.syncOnDemand, query.processAll).then<void>([=](Async::Future<void> &future) { |
199 | //Now that the sync is complete we can execute the query | 153 | //Now that the sync is complete we can execute the query |
@@ -201,6 +155,9 @@ Async::Job<void> DummyResourceFacade::load(const Akonadi2::Query &query, const s | |||
201 | 155 | ||
202 | auto storage = QSharedPointer<Akonadi2::Storage>::create(Akonadi2::Store::storageLocation(), "org.kde.dummy"); | 156 | auto storage = QSharedPointer<Akonadi2::Storage>::create(Akonadi2::Store::storageLocation(), "org.kde.dummy"); |
203 | 157 | ||
158 | //TODO use transaction over full query and record store revision. We'll need it to update the query. | ||
159 | |||
160 | //Index lookups | ||
204 | QVector<QByteArray> keys; | 161 | QVector<QByteArray> keys; |
205 | if (query.propertyFilter.contains("uid")) { | 162 | if (query.propertyFilter.contains("uid")) { |
206 | static Index uidIndex(Akonadi2::Store::storageLocation(), "org.kde.dummy.index.uid", Akonadi2::Storage::ReadOnly); | 163 | static Index uidIndex(Akonadi2::Store::storageLocation(), "org.kde.dummy.index.uid", Akonadi2::Storage::ReadOnly); |