diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2015-12-01 11:10:37 +0100 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2015-12-01 11:10:37 +0100 |
commit | 44edbee0f0b2fcf13e2ee388a90a8dd1f84a329e (patch) | |
tree | 71d265b2bce5a15981976e334ed182fa6d37c45f | |
parent | 377c86144221ffc5b49bdaa9b8dcc3507fe4a50f (diff) | |
download | sink-44edbee0f0b2fcf13e2ee388a90a8dd1f84a329e.tar.gz sink-44edbee0f0b2fcf13e2ee388a90a8dd1f84a329e.zip |
Resolve remoteIds during sync
Remote id's need to be resolved while syncing any references.
This is done by the synchronizer by consulting the rid to entity id
mapping. If the referenced entity doesn't exist yet we create a local
id anyways, that we then need to pick up once the actual entity arrives.
-rw-r--r-- | common/commands/createentity.fbs | 1 | ||||
-rw-r--r-- | common/index.cpp | 13 | ||||
-rw-r--r-- | common/index.h | 1 | ||||
-rw-r--r-- | common/pipeline.cpp | 9 | ||||
-rw-r--r-- | common/resourceaccess.cpp | 2 | ||||
-rw-r--r-- | examples/dummyresource/dummystore.cpp | 7 | ||||
-rw-r--r-- | examples/dummyresource/resourcefactory.cpp | 22 | ||||
-rw-r--r-- | examples/dummyresource/resourcefactory.h | 1 | ||||
-rw-r--r-- | tests/dummyresourcebenchmark.cpp | 3 |
9 files changed, 53 insertions, 6 deletions
diff --git a/common/commands/createentity.fbs b/common/commands/createentity.fbs index 23eeff9..a5bc95c 100644 --- a/common/commands/createentity.fbs +++ b/common/commands/createentity.fbs | |||
@@ -1,6 +1,7 @@ | |||
1 | namespace Akonadi2.Commands; | 1 | namespace Akonadi2.Commands; |
2 | 2 | ||
3 | table CreateEntity { | 3 | table CreateEntity { |
4 | entityId: string; | ||
4 | domainType: string; | 5 | domainType: string; |
5 | delta: [ubyte]; | 6 | delta: [ubyte]; |
6 | } | 7 | } |
diff --git a/common/index.cpp b/common/index.cpp index 2fc0fe3..f4de93c 100644 --- a/common/index.cpp +++ b/common/index.cpp | |||
@@ -38,3 +38,16 @@ void Index::lookup(const QByteArray &key, const std::function<void(const QByteAr | |||
38 | ); | 38 | ); |
39 | } | 39 | } |
40 | 40 | ||
41 | QByteArray Index::lookup(const QByteArray &key) | ||
42 | { | ||
43 | QByteArray result; | ||
44 | lookup(key, | ||
45 | [&result](const QByteArray &value) { | ||
46 | result = value; | ||
47 | }, | ||
48 | [](const Index::Error &error) { | ||
49 | qDebug() << "Error while retrieving value" << error.message; | ||
50 | }); | ||
51 | return result; | ||
52 | } | ||
53 | |||
diff --git a/common/index.h b/common/index.h index 0ca32af..6b06d26 100644 --- a/common/index.h +++ b/common/index.h | |||
@@ -33,6 +33,7 @@ public: | |||
33 | 33 | ||
34 | void lookup(const QByteArray &key, const std::function<void(const QByteArray &value)> &resultHandler, | 34 | void lookup(const QByteArray &key, const std::function<void(const QByteArray &value)> &resultHandler, |
35 | const std::function<void(const Error &error)> &errorHandler); | 35 | const std::function<void(const Error &error)> &errorHandler); |
36 | QByteArray lookup(const QByteArray &key); | ||
36 | 37 | ||
37 | private: | 38 | private: |
38 | Q_DISABLE_COPY(Index); | 39 | Q_DISABLE_COPY(Index); |
diff --git a/common/pipeline.cpp b/common/pipeline.cpp index 0ce478b..16d8329 100644 --- a/common/pipeline.cpp +++ b/common/pipeline.cpp | |||
@@ -150,7 +150,14 @@ KAsync::Job<qint64> Pipeline::newEntity(void const *command, size_t size) | |||
150 | return KAsync::error<qint64>(0); | 150 | return KAsync::error<qint64>(0); |
151 | } | 151 | } |
152 | 152 | ||
153 | const auto key = QUuid::createUuid().toString().toUtf8(); | 153 | QByteArray key; |
154 | if (createEntity->entityId()) { | ||
155 | key = QByteArray(reinterpret_cast<char const*>(createEntity->entityId()->Data()), createEntity->entityId()->size()); | ||
156 | } | ||
157 | if (key.isEmpty()) { | ||
158 | key = QUuid::createUuid().toString().toUtf8(); | ||
159 | } | ||
160 | Q_ASSERT(!key.isEmpty()); | ||
154 | const qint64 newRevision = Akonadi2::Storage::maxRevision(d->transaction) + 1; | 161 | const qint64 newRevision = Akonadi2::Storage::maxRevision(d->transaction) + 1; |
155 | 162 | ||
156 | //Add metadata buffer | 163 | //Add metadata buffer |
diff --git a/common/resourceaccess.cpp b/common/resourceaccess.cpp index be25533..8988032 100644 --- a/common/resourceaccess.cpp +++ b/common/resourceaccess.cpp | |||
@@ -296,7 +296,7 @@ KAsync::Job<void> ResourceAccess::sendCreateCommand(const QByteArray &resourceBu | |||
296 | //This is the resource buffer type and not the domain type | 296 | //This is the resource buffer type and not the domain type |
297 | auto type = fbb.CreateString(resourceBufferType.constData()); | 297 | auto type = fbb.CreateString(resourceBufferType.constData()); |
298 | auto delta = Akonadi2::EntityBuffer::appendAsVector(fbb, buffer.constData(), buffer.size()); | 298 | auto delta = Akonadi2::EntityBuffer::appendAsVector(fbb, buffer.constData(), buffer.size()); |
299 | auto location = Akonadi2::Commands::CreateCreateEntity(fbb, type, delta); | 299 | auto location = Akonadi2::Commands::CreateCreateEntity(fbb, 0, type, delta); |
300 | Akonadi2::Commands::FinishCreateEntityBuffer(fbb, location); | 300 | Akonadi2::Commands::FinishCreateEntityBuffer(fbb, location); |
301 | open(); | 301 | open(); |
302 | return sendCommand(Akonadi2::Commands::CreateEntityCommand, fbb); | 302 | return sendCommand(Akonadi2::Commands::CreateEntityCommand, fbb); |
diff --git a/examples/dummyresource/dummystore.cpp b/examples/dummyresource/dummystore.cpp index 458695f..8592a30 100644 --- a/examples/dummyresource/dummystore.cpp +++ b/examples/dummyresource/dummystore.cpp | |||
@@ -64,9 +64,14 @@ QMap<QString, QMap<QString, QVariant> > populateMails() | |||
64 | QMap<QString, QMap<QString, QVariant> > populateFolders() | 64 | QMap<QString, QMap<QString, QVariant> > populateFolders() |
65 | { | 65 | { |
66 | QMap<QString, QMap<QString, QVariant>> content; | 66 | QMap<QString, QMap<QString, QVariant>> content; |
67 | for (int i = 0; i < 5; i++) { | 67 | int i = 0; |
68 | for (i = 0; i < 5; i++) { | ||
68 | content.insert(QString("key%1").arg(i), createFolder(i)); | 69 | content.insert(QString("key%1").arg(i), createFolder(i)); |
69 | } | 70 | } |
71 | i++; | ||
72 | auto folder = createFolder(i); | ||
73 | folder.insert("parent", "key0"); | ||
74 | content.insert(QString("key%1").arg(i), folder); | ||
70 | return content; | 75 | return content; |
71 | } | 76 | } |
72 | 77 | ||
diff --git a/examples/dummyresource/resourcefactory.cpp b/examples/dummyresource/resourcefactory.cpp index e524c3f..8dae749 100644 --- a/examples/dummyresource/resourcefactory.cpp +++ b/examples/dummyresource/resourcefactory.cpp | |||
@@ -36,6 +36,7 @@ | |||
36 | #include "definitions.h" | 36 | #include "definitions.h" |
37 | #include "facadefactory.h" | 37 | #include "facadefactory.h" |
38 | #include <QDate> | 38 | #include <QDate> |
39 | #include <QUuid> | ||
39 | 40 | ||
40 | //This is the resources entity type, and not the domain type | 41 | //This is the resources entity type, and not the domain type |
41 | #define ENTITY_TYPE_EVENT "event" | 42 | #define ENTITY_TYPE_EVENT "event" |
@@ -182,6 +183,19 @@ void DummyResource::createMail(const QByteArray &ridBuffer, const QMap<QString, | |||
182 | Akonadi2::EntityBuffer::assembleEntityBuffer(entityFbb, 0, 0, 0, 0, m_fbb.GetBufferPointer(), m_fbb.GetSize()); | 183 | Akonadi2::EntityBuffer::assembleEntityBuffer(entityFbb, 0, 0, 0, 0, m_fbb.GetBufferPointer(), m_fbb.GetSize()); |
183 | } | 184 | } |
184 | 185 | ||
186 | QString DummyResource::resolveRemoteId(const QString &remoteId) | ||
187 | { | ||
188 | //Lookup local id for remote id, or insert a new pair otherwise | ||
189 | Akonadi2::Storage store(Akonadi2::storageLocation(), mResourceInstanceIdentifier + ".synchronization", Akonadi2::Storage::ReadWrite); | ||
190 | auto transaction = store.createTransaction(Akonadi2::Storage::ReadWrite); | ||
191 | QByteArray akonadiId = Index("rid.mapping", transaction).lookup(remoteId.toLatin1()); | ||
192 | if (akonadiId.isEmpty()) { | ||
193 | akonadiId = QUuid::createUuid().toString().toUtf8(); | ||
194 | Index("rid.mapping", transaction).add(remoteId.toLatin1(), akonadiId); | ||
195 | } | ||
196 | return akonadiId; | ||
197 | } | ||
198 | |||
185 | void DummyResource::createFolder(const QByteArray &ridBuffer, const QMap<QString, QVariant> &data, flatbuffers::FlatBufferBuilder &entityFbb) | 199 | void DummyResource::createFolder(const QByteArray &ridBuffer, const QMap<QString, QVariant> &data, flatbuffers::FlatBufferBuilder &entityFbb) |
186 | { | 200 | { |
187 | //Map the source format to the buffer format (which happens to be an exact copy here) | 201 | //Map the source format to the buffer format (which happens to be an exact copy here) |
@@ -190,7 +204,8 @@ void DummyResource::createFolder(const QByteArray &ridBuffer, const QMap<QString | |||
190 | bool hasParent = false; | 204 | bool hasParent = false; |
191 | if (!data.value("parent").toString().isEmpty()) { | 205 | if (!data.value("parent").toString().isEmpty()) { |
192 | hasParent = true; | 206 | hasParent = true; |
193 | parent = m_fbb.CreateString(data.value("parent").toString().toStdString()); | 207 | auto akonadiId = resolveRemoteId(data.value("parent").toString()); |
208 | parent = m_fbb.CreateString(akonadiId.toStdString()); | ||
194 | } | 209 | } |
195 | 210 | ||
196 | auto builder = Akonadi2::ApplicationDomain::Buffer::FolderBuilder(m_fbb); | 211 | auto builder = Akonadi2::ApplicationDomain::Buffer::FolderBuilder(m_fbb); |
@@ -222,11 +237,14 @@ void DummyResource::synchronize(const QString &bufferType, const QMap<QString, Q | |||
222 | flatbuffers::FlatBufferBuilder entityFbb; | 237 | flatbuffers::FlatBufferBuilder entityFbb; |
223 | createEntity(it.key().toUtf8(), it.value(), entityFbb); | 238 | createEntity(it.key().toUtf8(), it.value(), entityFbb); |
224 | 239 | ||
240 | auto akonadiId = resolveRemoteId(it.key()); | ||
241 | |||
225 | flatbuffers::FlatBufferBuilder fbb; | 242 | flatbuffers::FlatBufferBuilder fbb; |
226 | //This is the resource type and not the domain type | 243 | //This is the resource type and not the domain type |
244 | auto entityId = fbb.CreateString(akonadiId.toStdString()); | ||
227 | auto type = fbb.CreateString(bufferType.toStdString()); | 245 | auto type = fbb.CreateString(bufferType.toStdString()); |
228 | auto delta = Akonadi2::EntityBuffer::appendAsVector(fbb, entityFbb.GetBufferPointer(), entityFbb.GetSize()); | 246 | auto delta = Akonadi2::EntityBuffer::appendAsVector(fbb, entityFbb.GetBufferPointer(), entityFbb.GetSize()); |
229 | auto location = Akonadi2::Commands::CreateCreateEntity(fbb, type, delta); | 247 | auto location = Akonadi2::Commands::CreateCreateEntity(fbb, entityId, type, delta); |
230 | Akonadi2::Commands::FinishCreateEntityBuffer(fbb, location); | 248 | Akonadi2::Commands::FinishCreateEntityBuffer(fbb, location); |
231 | 249 | ||
232 | enqueueCommand(mSynchronizerQueue, Akonadi2::Commands::CreateEntityCommand, QByteArray::fromRawData(reinterpret_cast<char const *>(fbb.GetBufferPointer()), fbb.GetSize())); | 250 | enqueueCommand(mSynchronizerQueue, Akonadi2::Commands::CreateEntityCommand, QByteArray::fromRawData(reinterpret_cast<char const *>(fbb.GetBufferPointer()), fbb.GetSize())); |
diff --git a/examples/dummyresource/resourcefactory.h b/examples/dummyresource/resourcefactory.h index 67681ae..f7882ca 100644 --- a/examples/dummyresource/resourcefactory.h +++ b/examples/dummyresource/resourcefactory.h | |||
@@ -36,6 +36,7 @@ public: | |||
36 | KAsync::Job<void> synchronizeWithSource() Q_DECL_OVERRIDE; | 36 | KAsync::Job<void> synchronizeWithSource() Q_DECL_OVERRIDE; |
37 | static void removeFromDisk(const QByteArray &instanceIdentifier); | 37 | static void removeFromDisk(const QByteArray &instanceIdentifier); |
38 | private: | 38 | private: |
39 | QString resolveRemoteId(const QString &remoteId); | ||
39 | void createEvent(const QByteArray &rid, const QMap<QString, QVariant> &data, flatbuffers::FlatBufferBuilder &entityFbb); | 40 | void createEvent(const QByteArray &rid, const QMap<QString, QVariant> &data, flatbuffers::FlatBufferBuilder &entityFbb); |
40 | void createMail(const QByteArray &rid, const QMap<QString, QVariant> &data, flatbuffers::FlatBufferBuilder &entityFbb); | 41 | void createMail(const QByteArray &rid, const QMap<QString, QVariant> &data, flatbuffers::FlatBufferBuilder &entityFbb); |
41 | void createFolder(const QByteArray &rid, const QMap<QString, QVariant> &data, flatbuffers::FlatBufferBuilder &entityFbb); | 42 | void createFolder(const QByteArray &rid, const QMap<QString, QVariant> &data, flatbuffers::FlatBufferBuilder &entityFbb); |
diff --git a/tests/dummyresourcebenchmark.cpp b/tests/dummyresourcebenchmark.cpp index 6eaf065..94a4e72 100644 --- a/tests/dummyresourcebenchmark.cpp +++ b/tests/dummyresourcebenchmark.cpp | |||
@@ -188,10 +188,11 @@ private Q_SLOTS: | |||
188 | static flatbuffers::FlatBufferBuilder fbb; | 188 | static flatbuffers::FlatBufferBuilder fbb; |
189 | fbb.Clear(); | 189 | fbb.Clear(); |
190 | //This is the resource buffer type and not the domain type | 190 | //This is the resource buffer type and not the domain type |
191 | auto entityId = fbb.CreateString(""); | ||
191 | auto type = fbb.CreateString("event"); | 192 | auto type = fbb.CreateString("event"); |
192 | // auto delta = fbb.CreateVector<uint8_t>(entityFbb.GetBufferPointer(), entityFbb.GetSize()); | 193 | // auto delta = fbb.CreateVector<uint8_t>(entityFbb.GetBufferPointer(), entityFbb.GetSize()); |
193 | auto delta = Akonadi2::EntityBuffer::appendAsVector(fbb, entityFbb.GetBufferPointer(), entityFbb.GetSize()); | 194 | auto delta = Akonadi2::EntityBuffer::appendAsVector(fbb, entityFbb.GetBufferPointer(), entityFbb.GetSize()); |
194 | auto location = Akonadi2::Commands::CreateCreateEntity(fbb, type, delta); | 195 | auto location = Akonadi2::Commands::CreateCreateEntity(fbb, entityId, type, delta); |
195 | Akonadi2::Commands::FinishCreateEntityBuffer(fbb, location); | 196 | Akonadi2::Commands::FinishCreateEntityBuffer(fbb, location); |
196 | } | 197 | } |
197 | } | 198 | } |