diff options
Diffstat (limited to 'dummyresource')
-rw-r--r-- | dummyresource/facade.cpp | 48 | ||||
-rw-r--r-- | dummyresource/resourcefactory.cpp | 94 | ||||
-rw-r--r-- | dummyresource/resourcefactory.h | 3 |
3 files changed, 99 insertions, 46 deletions
diff --git a/dummyresource/facade.cpp b/dummyresource/facade.cpp index 458aba6..d3974e9 100644 --- a/dummyresource/facade.cpp +++ b/dummyresource/facade.cpp | |||
@@ -26,8 +26,9 @@ | |||
26 | #include "common/commands.h" | 26 | #include "common/commands.h" |
27 | #include "dummycalendar_generated.h" | 27 | #include "dummycalendar_generated.h" |
28 | #include "event_generated.h" | 28 | #include "event_generated.h" |
29 | #include "entitybuffer_generated.h" | 29 | #include "entity_generated.h" |
30 | #include "metadata_generated.h" | 30 | #include "metadata_generated.h" |
31 | #include <common/entitybuffer.h> | ||
31 | 32 | ||
32 | using namespace DummyCalendar; | 33 | using namespace DummyCalendar; |
33 | using namespace flatbuffers; | 34 | using namespace flatbuffers; |
@@ -199,14 +200,47 @@ void DummyResourceFacade::load(const Akonadi2::Query &query, const std::function | |||
199 | storage->startTransaction(Akonadi2::Storage::ReadOnly); | 200 | storage->startTransaction(Akonadi2::Storage::ReadOnly); |
200 | //Because we have no indexes yet, we always do a full scan | 201 | //Because we have no indexes yet, we always do a full scan |
201 | storage->scan("", [=](void *keyValue, int keySize, void *dataValue, int dataSize) -> bool { | 202 | storage->scan("", [=](void *keyValue, int keySize, void *dataValue, int dataSize) -> bool { |
202 | qDebug() << QString::fromStdString(std::string(static_cast<char*>(keyValue), keySize)); | 203 | |
203 | auto buffer = Akonadi2::GetEntityBuffer(dataValue); | 204 | //Skip internals |
204 | auto resourceBuffer = GetDummyEvent(buffer->resource()); | 205 | if (QByteArray::fromRawData(static_cast<char*>(keyValue), keySize).startsWith("__internal")) { |
205 | auto metadataBuffer = Akonadi2::GetMetadata(buffer->resource()); | 206 | return true; |
206 | auto localBuffer = Akonadi2::Domain::Buffer::GetEvent(buffer->local()); | 207 | } |
208 | |||
209 | //Extract buffers | ||
210 | Akonadi2::EntityBuffer buffer(dataValue, dataSize); | ||
211 | |||
212 | DummyEvent const *resourceBuffer = 0; | ||
213 | if (auto resourceData = buffer.resourceBuffer()) { | ||
214 | flatbuffers::Verifier verifyer(resourceData->Data(), resourceData->size()); | ||
215 | if (VerifyDummyEventBuffer(verifyer)) { | ||
216 | resourceBuffer = GetDummyEvent(resourceData); | ||
217 | } | ||
218 | } | ||
219 | |||
220 | Akonadi2::Metadata const *metadataBuffer = 0; | ||
221 | if (auto metadataData = buffer.metadataBuffer()) { | ||
222 | flatbuffers::Verifier verifyer(metadataData->Data(), metadataData->size()); | ||
223 | if (Akonadi2::VerifyMetadataBuffer(verifyer)) { | ||
224 | metadataBuffer = Akonadi2::GetMetadata(metadataData); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | Akonadi2::Domain::Buffer::Event const *localBuffer = 0; | ||
229 | if (auto localData = buffer.localBuffer()) { | ||
230 | flatbuffers::Verifier verifyer(localData->Data(), localData->size()); | ||
231 | if (Akonadi2::Domain::Buffer::VerifyEventBuffer(verifyer)) { | ||
232 | localBuffer = Akonadi2::Domain::Buffer::GetEvent(localData); | ||
233 | } | ||
234 | } | ||
235 | |||
236 | if (!resourceBuffer || !metadataBuffer) { | ||
237 | qWarning() << "invalid buffer " << QString::fromStdString(std::string(static_cast<char*>(keyValue), keySize)); | ||
238 | return true; | ||
239 | } | ||
240 | |||
207 | //We probably only want to create all buffers after the scan | 241 | //We probably only want to create all buffers after the scan |
208 | if (preparedQuery && preparedQuery(std::string(static_cast<char*>(keyValue), keySize), resourceBuffer)) { | 242 | if (preparedQuery && preparedQuery(std::string(static_cast<char*>(keyValue), keySize), resourceBuffer)) { |
209 | qint64 revision = metadataBuffer->revision(); | 243 | qint64 revision = metadataBuffer ? metadataBuffer->revision() : -1; |
210 | auto adaptor = QSharedPointer<DummyEventAdaptor>::create(); | 244 | auto adaptor = QSharedPointer<DummyEventAdaptor>::create(); |
211 | adaptor->mLocalBuffer = localBuffer; | 245 | adaptor->mLocalBuffer = localBuffer; |
212 | adaptor->mResourceBuffer = resourceBuffer; | 246 | adaptor->mResourceBuffer = resourceBuffer; |
diff --git a/dummyresource/resourcefactory.cpp b/dummyresource/resourcefactory.cpp index 6b93985..c9e4d7a 100644 --- a/dummyresource/resourcefactory.cpp +++ b/dummyresource/resourcefactory.cpp | |||
@@ -19,7 +19,9 @@ | |||
19 | 19 | ||
20 | #include "resourcefactory.h" | 20 | #include "resourcefactory.h" |
21 | #include "facade.h" | 21 | #include "facade.h" |
22 | #include "entitybuffer.h" | ||
22 | #include "dummycalendar_generated.h" | 23 | #include "dummycalendar_generated.h" |
24 | #include "metadata_generated.h" | ||
23 | #include <QUuid> | 25 | #include <QUuid> |
24 | 26 | ||
25 | static std::string createEvent() | 27 | static std::string createEvent() |
@@ -64,51 +66,67 @@ void findByRemoteId(QSharedPointer<Akonadi2::Storage> storage, const QString &ri | |||
64 | //TODO lookup in rid index instead of doing a full scan | 66 | //TODO lookup in rid index instead of doing a full scan |
65 | const std::string ridString = rid.toStdString(); | 67 | const std::string ridString = rid.toStdString(); |
66 | storage->scan("", [&](void *keyValue, int keySize, void *dataValue, int dataSize) -> bool { | 68 | storage->scan("", [&](void *keyValue, int keySize, void *dataValue, int dataSize) -> bool { |
67 | auto eventBuffer = DummyCalendar::GetDummyEvent(dataValue); | 69 | if (QByteArray::fromRawData(static_cast<char*>(keyValue), keySize).startsWith("__internal")) { |
68 | if (std::string(eventBuffer->remoteId()->c_str(), eventBuffer->remoteId()->size()) == ridString) { | 70 | return true; |
69 | callback(keyValue, keySize, dataValue, dataSize); | ||
70 | } | 71 | } |
72 | |||
73 | Akonadi2::EntityBuffer::extractResourceBuffer(dataValue, dataSize, [&](const flatbuffers::Vector<uint8_t> *buffer) { | ||
74 | flatbuffers::Verifier verifier(buffer->Data(), buffer->size()); | ||
75 | if (DummyCalendar::VerifyDummyEventBuffer(verifier)) { | ||
76 | DummyCalendar::DummyEvent const *resourceBuffer = DummyCalendar::GetDummyEvent(buffer->Data()); | ||
77 | if (resourceBuffer && resourceBuffer->remoteId()) { | ||
78 | if (std::string(resourceBuffer->remoteId()->c_str(), resourceBuffer->remoteId()->size()) == ridString) { | ||
79 | callback(keyValue, keySize, dataValue, dataSize); | ||
80 | } | ||
81 | } | ||
82 | } | ||
83 | }); | ||
71 | return true; | 84 | return true; |
72 | }); | 85 | }); |
73 | } | 86 | } |
74 | 87 | ||
75 | void DummyResource::synchronizeWithSource(Akonadi2::Pipeline *pipeline) | 88 | Async::Job<void> DummyResource::synchronizeWithSource(Akonadi2::Pipeline *pipeline) |
76 | { | 89 | { |
77 | //TODO use a read-only transaction during the complete sync to sync against a defined revision | 90 | return Async::start<void>([this, pipeline](Async::Future<void> &f) { |
78 | 91 | //TODO use a read-only transaction during the complete sync to sync against a defined revision | |
79 | qDebug() << "synchronize with source"; | 92 | auto storage = QSharedPointer<Akonadi2::Storage>::create(Akonadi2::Store::storageLocation(), "org.kde.dummy"); |
80 | 93 | for (auto it = s_dataSource.constBegin(); it != s_dataSource.constEnd(); it++) { | |
81 | auto storage = QSharedPointer<Akonadi2::Storage>::create(Akonadi2::Store::storageLocation(), "org.kde.dummy"); | 94 | bool isNew = true; |
82 | for (auto it = s_dataSource.constBegin(); it != s_dataSource.constEnd(); it++) { | 95 | if (storage->exists()) { |
83 | bool isNew = true; | 96 | findByRemoteId(storage, it.key(), [&](void *keyValue, int keySize, void *dataValue, int dataSize) { |
84 | if (storage->exists()) { | 97 | isNew = false; |
85 | findByRemoteId(storage, it.key(), [&](void *keyValue, int keySize, void *dataValue, int dataSize) { | 98 | }); |
86 | isNew = false; | 99 | } |
87 | }); | 100 | if (isNew) { |
88 | } | 101 | m_fbb.Clear(); |
89 | 102 | ||
90 | if (isNew) { | 103 | const QByteArray data = it.value().toUtf8(); |
91 | //TODO: perhaps it would be more convenient to populate the domain types? | 104 | auto eventBuffer = DummyCalendar::GetDummyEvent(data.data()); |
92 | //Resource specific parts are not accessible that way, but then we would only have to implement the property mapping in one place | 105 | |
93 | const QByteArray data = it.value().toUtf8(); | 106 | //Map the source format to the buffer format (which happens to be an exact copy here) |
94 | auto eventBuffer = DummyCalendar::GetDummyEvent(data.data()); | 107 | auto summary = m_fbb.CreateString(eventBuffer->summary()->c_str()); |
95 | 108 | auto rid = m_fbb.CreateString(it.key().toStdString().c_str()); | |
96 | //Map the source format to the buffer format (which happens to be an exact copy here) | 109 | auto description = m_fbb.CreateString(it.key().toStdString().c_str()); |
97 | auto builder = DummyCalendar::DummyEventBuilder(m_fbb); | 110 | static uint8_t rawData[100]; |
98 | builder.add_summary(m_fbb.CreateString(eventBuffer->summary()->c_str())); | 111 | auto attachment = m_fbb.CreateVector(rawData, 100); |
99 | auto buffer = builder.Finish(); | 112 | |
100 | DummyCalendar::FinishDummyEventBuffer(m_fbb, buffer); | 113 | auto builder = DummyCalendar::DummyEventBuilder(m_fbb); |
101 | 114 | builder.add_summary(summary); | |
102 | //TODO toRFC4122 would probably be more efficient, but results in non-printable keys. | 115 | builder.add_remoteId(rid); |
103 | const auto key = QUuid::createUuid().toString().toUtf8(); | 116 | builder.add_description(description); |
104 | //TODO can we really just start populating the buffer and pass the buffer builder? | 117 | builder.add_attachment(attachment); |
105 | qDebug() << "new event"; | 118 | auto buffer = builder.Finish(); |
106 | pipeline->newEntity(key, m_fbb.GetBufferPointer(), m_fbb.GetSize()); | 119 | DummyCalendar::FinishDummyEventBuffer(m_fbb, buffer); |
107 | } else { //modification | 120 | //TODO toRFC4122 would probably be more efficient, but results in non-printable keys. |
108 | //TODO diff and create modification if necessary | 121 | const auto key = QUuid::createUuid().toString().toUtf8(); |
122 | pipeline->newEntity(key, m_fbb.GetBufferPointer(), m_fbb.GetSize()); | ||
123 | } else { //modification | ||
124 | //TODO diff and create modification if necessary | ||
125 | } | ||
109 | } | 126 | } |
110 | } | 127 | //TODO find items to remove |
111 | //TODO find items to remove | 128 | f.setFinished(); |
129 | }); | ||
112 | } | 130 | } |
113 | 131 | ||
114 | void DummyResource::processCommand(int commandId, const QByteArray &data, uint size, Akonadi2::Pipeline *pipeline) | 132 | void DummyResource::processCommand(int commandId, const QByteArray &data, uint size, Akonadi2::Pipeline *pipeline) |
diff --git a/dummyresource/resourcefactory.h b/dummyresource/resourcefactory.h index 807a654..dba674f 100644 --- a/dummyresource/resourcefactory.h +++ b/dummyresource/resourcefactory.h | |||
@@ -20,6 +20,7 @@ | |||
20 | #pragma once | 20 | #pragma once |
21 | 21 | ||
22 | #include "common/resource.h" | 22 | #include "common/resource.h" |
23 | #include "async/src/async.h" | ||
23 | 24 | ||
24 | #include <flatbuffers/flatbuffers.h> | 25 | #include <flatbuffers/flatbuffers.h> |
25 | 26 | ||
@@ -30,7 +31,7 @@ class DummyResource : public Akonadi2::Resource | |||
30 | { | 31 | { |
31 | public: | 32 | public: |
32 | DummyResource(); | 33 | DummyResource(); |
33 | void synchronizeWithSource(Akonadi2::Pipeline *pipeline); | 34 | Async::Job<void> synchronizeWithSource(Akonadi2::Pipeline *pipeline); |
34 | void processCommand(int commandId, const QByteArray &data, uint size, Akonadi2::Pipeline *pipeline); | 35 | void processCommand(int commandId, const QByteArray &data, uint size, Akonadi2::Pipeline *pipeline); |
35 | 36 | ||
36 | private: | 37 | private: |