summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/CMakeLists.txt1
-rw-r--r--common/changereplay.cpp14
-rw-r--r--common/storage.h6
-rw-r--r--common/storage/entitystore.cpp73
-rw-r--r--common/storage/entitystore.h1
-rw-r--r--common/storage/key.cpp156
-rw-r--r--common/storage/key.h100
-rw-r--r--common/storage_common.cpp17
-rw-r--r--common/synchronizer.cpp3
-rw-r--r--common/typeindex.cpp9
-rw-r--r--common/utils.h13
-rw-r--r--sinksh/syntax_modules/sink_inspect.cpp4
-rw-r--r--tests/pipelinetest.cpp40
-rw-r--r--tests/storagetest.cpp12
14 files changed, 368 insertions, 81 deletions
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index 970990f..7c4630b 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -73,6 +73,7 @@ add_library(${PROJECT_NAME} SHARED
73 specialpurposepreprocessor.cpp 73 specialpurposepreprocessor.cpp
74 datastorequery.cpp 74 datastorequery.cpp
75 storage/entitystore.cpp 75 storage/entitystore.cpp
76 storage/key.cpp
76 indexer.cpp 77 indexer.cpp
77 mail/threadindexer.cpp 78 mail/threadindexer.cpp
78 mail/fulltextindexer.cpp 79 mail/fulltextindexer.cpp
diff --git a/common/changereplay.cpp b/common/changereplay.cpp
index 0adbd78..d7f46dc 100644
--- a/common/changereplay.cpp
+++ b/common/changereplay.cpp
@@ -23,6 +23,7 @@
23#include "log.h" 23#include "log.h"
24#include "definitions.h" 24#include "definitions.h"
25#include "bufferutils.h" 25#include "bufferutils.h"
26#include "storage/key.h"
26 27
27#include <QTimer> 28#include <QTimer>
28 29
@@ -113,10 +114,13 @@ KAsync::Job<void> ChangeReplay::replayNextRevision()
113 if (uid.isEmpty() || type.isEmpty()) { 114 if (uid.isEmpty() || type.isEmpty()) {
114 SinkErrorCtx(mLogCtx) << "Failed to read uid or type for revison: " << revision << uid << type; 115 SinkErrorCtx(mLogCtx) << "Failed to read uid or type for revison: " << revision << uid << type;
115 } else { 116 } else {
116 const auto key = DataStore::assembleKey(uid, revision); 117 // TODO: should not use internal representations
118 const auto key = Storage::Key(Storage::Identifier::fromDisplayByteArray(uid), revision);
119 const auto internalKey = key.toInternalByteArray();
120 const auto displayKey = key.toDisplayByteArray();
117 QByteArray entityBuffer; 121 QByteArray entityBuffer;
118 DataStore::mainDatabase(mMainStoreTransaction, type) 122 DataStore::mainDatabase(mMainStoreTransaction, type)
119 .scan(key, 123 .scan(internalKey,
120 [&entityBuffer](const QByteArray &key, const QByteArray &value) -> bool { 124 [&entityBuffer](const QByteArray &key, const QByteArray &value) -> bool {
121 entityBuffer = value; 125 entityBuffer = value;
122 return false; 126 return false;
@@ -126,9 +130,9 @@ KAsync::Job<void> ChangeReplay::replayNextRevision()
126 if (entityBuffer.isEmpty()) { 130 if (entityBuffer.isEmpty()) {
127 SinkErrorCtx(mLogCtx) << "Failed to replay change " << key; 131 SinkErrorCtx(mLogCtx) << "Failed to replay change " << key;
128 } else { 132 } else {
129 if (canReplay(type, key, entityBuffer)) { 133 if (canReplay(type, displayKey, entityBuffer)) {
130 SinkTraceCtx(mLogCtx) << "Replaying " << key; 134 SinkTraceCtx(mLogCtx) << "Replaying " << displayKey;
131 replayJob = replay(type, key, entityBuffer); 135 replayJob = replay(type, displayKey, entityBuffer);
132 //Set the last revision we tried to replay 136 //Set the last revision we tried to replay
133 *lastReplayedRevision = revision; 137 *lastReplayedRevision = revision;
134 //Execute replay job and commit 138 //Execute replay job and commit
diff --git a/common/storage.h b/common/storage.h
index a8c486c..8904148 100644
--- a/common/storage.h
+++ b/common/storage.h
@@ -22,8 +22,10 @@
22#pragma once 22#pragma once
23 23
24#include "sink_export.h" 24#include "sink_export.h"
25#include "utils.h"
25#include <string> 26#include <string>
26#include <functional> 27#include <functional>
28#include <QUuid>
27#include <QString> 29#include <QString>
28#include <QMap> 30#include <QMap>
29 31
@@ -237,10 +239,6 @@ public:
237 static bool isInternalKey(void *key, int keySize); 239 static bool isInternalKey(void *key, int keySize);
238 static bool isInternalKey(const QByteArray &key); 240 static bool isInternalKey(const QByteArray &key);
239 241
240 static QByteArray assembleKey(const QByteArray &key, qint64 revision);
241 static QByteArray uidFromKey(const QByteArray &key);
242 static qint64 revisionFromKey(const QByteArray &key);
243
244 static NamedDatabase mainDatabase(const Transaction &, const QByteArray &type); 242 static NamedDatabase mainDatabase(const Transaction &, const QByteArray &type);
245 243
246 static QByteArray generateUid(); 244 static QByteArray generateUid();
diff --git a/common/storage/entitystore.cpp b/common/storage/entitystore.cpp
index dd6bbf0..3addf94 100644
--- a/common/storage/entitystore.cpp
+++ b/common/storage/entitystore.cpp
@@ -237,8 +237,10 @@ bool EntityStore::add(const QByteArray &type, ApplicationDomainType entity, bool
237 flatbuffers::FlatBufferBuilder fbb; 237 flatbuffers::FlatBufferBuilder fbb;
238 d->resourceContext.adaptorFactory(type).createBuffer(entity, fbb, metadataFbb.GetBufferPointer(), metadataFbb.GetSize()); 238 d->resourceContext.adaptorFactory(type).createBuffer(entity, fbb, metadataFbb.GetBufferPointer(), metadataFbb.GetSize());
239 239
240 const auto key = Key(Identifier::fromDisplayByteArray(entity.identifier()), newRevision);
241
240 DataStore::mainDatabase(d->transaction, type) 242 DataStore::mainDatabase(d->transaction, type)
241 .write(DataStore::assembleKey(entity.identifier(), newRevision), BufferUtils::extractBuffer(fbb), 243 .write(key.toInternalByteArray(), BufferUtils::extractBuffer(fbb),
242 [&](const DataStore::Error &error) { SinkWarningCtx(d->logCtx) << "Failed to write entity" << entity.identifier() << newRevision; }); 244 [&](const DataStore::Error &error) { SinkWarningCtx(d->logCtx) << "Failed to write entity" << entity.identifier() << newRevision; });
243 DataStore::setMaxRevision(d->transaction, newRevision); 245 DataStore::setMaxRevision(d->transaction, newRevision);
244 DataStore::recordRevision(d->transaction, newRevision, entity.identifier(), type); 246 DataStore::recordRevision(d->transaction, newRevision, entity.identifier(), type);
@@ -311,8 +313,10 @@ bool EntityStore::modify(const QByteArray &type, const ApplicationDomainType &cu
311 flatbuffers::FlatBufferBuilder fbb; 313 flatbuffers::FlatBufferBuilder fbb;
312 d->resourceContext.adaptorFactory(type).createBuffer(newEntity, fbb, metadataFbb.GetBufferPointer(), metadataFbb.GetSize()); 314 d->resourceContext.adaptorFactory(type).createBuffer(newEntity, fbb, metadataFbb.GetBufferPointer(), metadataFbb.GetSize());
313 315
316 const auto key = Key(Identifier::fromDisplayByteArray(newEntity.identifier()), newRevision);
317
314 DataStore::mainDatabase(d->transaction, type) 318 DataStore::mainDatabase(d->transaction, type)
315 .write(DataStore::assembleKey(newEntity.identifier(), newRevision), BufferUtils::extractBuffer(fbb), 319 .write(key.toInternalByteArray(), BufferUtils::extractBuffer(fbb),
316 [&](const DataStore::Error &error) { SinkWarningCtx(d->logCtx) << "Failed to write entity" << newEntity.identifier() << newRevision; }); 320 [&](const DataStore::Error &error) { SinkWarningCtx(d->logCtx) << "Failed to write entity" << newEntity.identifier() << newRevision; });
317 DataStore::setMaxRevision(d->transaction, newRevision); 321 DataStore::setMaxRevision(d->transaction, newRevision);
318 DataStore::recordRevision(d->transaction, newRevision, newEntity.identifier(), type); 322 DataStore::recordRevision(d->transaction, newRevision, newEntity.identifier(), type);
@@ -346,8 +350,10 @@ bool EntityStore::remove(const QByteArray &type, const ApplicationDomainType &cu
346 flatbuffers::FlatBufferBuilder fbb; 350 flatbuffers::FlatBufferBuilder fbb;
347 EntityBuffer::assembleEntityBuffer(fbb, metadataFbb.GetBufferPointer(), metadataFbb.GetSize(), 0, 0, 0, 0); 351 EntityBuffer::assembleEntityBuffer(fbb, metadataFbb.GetBufferPointer(), metadataFbb.GetSize(), 0, 0, 0, 0);
348 352
353 const auto key = Key(Identifier::fromDisplayByteArray(uid), newRevision);
354
349 DataStore::mainDatabase(d->transaction, type) 355 DataStore::mainDatabase(d->transaction, type)
350 .write(DataStore::assembleKey(uid, newRevision), BufferUtils::extractBuffer(fbb), 356 .write(key.toInternalByteArray(), BufferUtils::extractBuffer(fbb),
351 [&](const DataStore::Error &error) { SinkWarningCtx(d->logCtx) << "Failed to write entity" << uid << newRevision; }); 357 [&](const DataStore::Error &error) { SinkWarningCtx(d->logCtx) << "Failed to write entity" << uid << newRevision; });
352 DataStore::setMaxRevision(d->transaction, newRevision); 358 DataStore::setMaxRevision(d->transaction, newRevision);
353 DataStore::recordRevision(d->transaction, newRevision, uid, type); 359 DataStore::recordRevision(d->transaction, newRevision, uid, type);
@@ -365,8 +371,9 @@ void EntityStore::cleanupEntityRevisionsUntil(qint64 revision)
365 return; 371 return;
366 } 372 }
367 SinkTraceCtx(d->logCtx) << "Cleaning up revision " << revision << uid << bufferType; 373 SinkTraceCtx(d->logCtx) << "Cleaning up revision " << revision << uid << bufferType;
374 const auto internalUid = Identifier::fromDisplayByteArray(uid).toInternalByteArray();
368 DataStore::mainDatabase(d->transaction, bufferType) 375 DataStore::mainDatabase(d->transaction, bufferType)
369 .scan(uid, 376 .scan(internalUid,
370 [&](const QByteArray &key, const QByteArray &data) -> bool { 377 [&](const QByteArray &key, const QByteArray &data) -> bool {
371 EntityBuffer buffer(const_cast<const char *>(data.data()), data.size()); 378 EntityBuffer buffer(const_cast<const char *>(data.data()), data.size());
372 if (!buffer.isValid()) { 379 if (!buffer.isValid()) {
@@ -428,7 +435,7 @@ QVector<QByteArray> EntityStore::fullScan(const QByteArray &type)
428 DataStore::mainDatabase(d->getTransaction(), type) 435 DataStore::mainDatabase(d->getTransaction(), type)
429 .scan(QByteArray(), 436 .scan(QByteArray(),
430 [&](const QByteArray &key, const QByteArray &value) -> bool { 437 [&](const QByteArray &key, const QByteArray &value) -> bool {
431 const auto uid = DataStore::uidFromKey(key); 438 const auto uid = Sink::Storage::Key::fromInternalByteArray(key).identifier().toDisplayByteArray();
432 if (keys.contains(uid)) { 439 if (keys.contains(uid)) {
433 //Not something that should persist if the replay works, so we keep a message for now. 440 //Not something that should persist if the replay works, so we keep a message for now.
434 SinkTraceCtx(d->logCtx) << "Multiple revisions for key: " << key; 441 SinkTraceCtx(d->logCtx) << "Multiple revisions for key: " << key;
@@ -479,16 +486,26 @@ void EntityStore::indexLookup(const QByteArray &type, const QByteArray &property
479 /* }); */ 486 /* }); */
480} 487}
481 488
482void EntityStore::readLatest(const QByteArray &type, const QByteArray &uid, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback) 489void EntityStore::readLatest(const QByteArray &type, const QByteArray &key, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback)
483{ 490{
484 Q_ASSERT(d); 491 Q_ASSERT(d);
485 Q_ASSERT(!uid.isEmpty()); 492 Q_ASSERT(!key.isEmpty());
493 // TODO: we shouldn't pass whole keys to this function
494 // check the testSingle test from querytest
495 const auto internalKey = [&key]() {
496 if(key.size() == Identifier::DISPLAY_REPR_SIZE) {
497 return Identifier::fromDisplayByteArray(key).toInternalByteArray();
498 } else {
499 return Key::fromDisplayByteArray(key).toInternalByteArray();
500 }
501 }();
486 auto db = DataStore::mainDatabase(d->getTransaction(), type); 502 auto db = DataStore::mainDatabase(d->getTransaction(), type);
487 db.findLatest(uid, 503 db.findLatest(internalKey,
488 [=](const QByteArray &key, const QByteArray &value) { 504 [=](const QByteArray &key, const QByteArray &value) {
489 callback(DataStore::uidFromKey(key), Sink::EntityBuffer(value.data(), value.size())); 505 const auto uid = Sink::Storage::Key::fromInternalByteArray(key).identifier().toDisplayByteArray();
506 callback(uid, Sink::EntityBuffer(value.data(), value.size()));
490 }, 507 },
491 [&](const DataStore::Error &error) { SinkWarningCtx(d->logCtx) << "Error during readLatest query: " << error.message << uid; }); 508 [&](const DataStore::Error &error) { SinkWarningCtx(d->logCtx) << "Error during readLatest query: " << error.message << key; });
492} 509}
493 510
494void EntityStore::readLatest(const QByteArray &type, const QByteArray &uid, const std::function<void(const ApplicationDomainType &)> callback) 511void EntityStore::readLatest(const QByteArray &type, const QByteArray &uid, const std::function<void(const ApplicationDomainType &)> callback)
@@ -516,12 +533,14 @@ ApplicationDomain::ApplicationDomainType EntityStore::readLatest(const QByteArra
516 return dt; 533 return dt;
517} 534}
518 535
519void EntityStore::readEntity(const QByteArray &type, const QByteArray &key, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback) 536void EntityStore::readEntity(const QByteArray &type, const QByteArray &displayKey, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback)
520{ 537{
538 const auto key = Key::fromDisplayByteArray(displayKey);
521 auto db = DataStore::mainDatabase(d->getTransaction(), type); 539 auto db = DataStore::mainDatabase(d->getTransaction(), type);
522 db.scan(key, 540 db.scan(key.toInternalByteArray(),
523 [=](const QByteArray &key, const QByteArray &value) -> bool { 541 [=](const QByteArray &key, const QByteArray &value) -> bool {
524 callback(DataStore::uidFromKey(key), Sink::EntityBuffer(value.data(), value.size())); 542 const auto uid = Sink::Storage::Key::fromInternalByteArray(key).identifier().toDisplayByteArray();
543 callback(uid, Sink::EntityBuffer(value.data(), value.size()));
525 return false; 544 return false;
526 }, 545 },
527 [&](const DataStore::Error &error) { SinkWarningCtx(d->logCtx) << "Error during readEntity query: " << error.message << key; }); 546 [&](const DataStore::Error &error) { SinkWarningCtx(d->logCtx) << "Error during readEntity query: " << error.message << key; });
@@ -567,9 +586,10 @@ void EntityStore::readRevisions(qint64 baseRevision, const QByteArray &expectedT
567 revisionCounter++; 586 revisionCounter++;
568 continue; 587 continue;
569 } 588 }
570 const auto key = DataStore::assembleKey(uid, revisionCounter); 589 const auto key = Key(Identifier::fromDisplayByteArray(uid), revisionCounter);
590
571 revisionCounter++; 591 revisionCounter++;
572 callback(key); 592 callback(key.toDisplayByteArray());
573 } 593 }
574} 594}
575 595
@@ -577,16 +597,18 @@ void EntityStore::readPrevious(const QByteArray &type, const QByteArray &uid, qi
577{ 597{
578 auto db = DataStore::mainDatabase(d->getTransaction(), type); 598 auto db = DataStore::mainDatabase(d->getTransaction(), type);
579 qint64 latestRevision = 0; 599 qint64 latestRevision = 0;
580 db.scan(uid, 600 const auto internalUid = Identifier::fromDisplayByteArray(uid).toInternalByteArray();
601 db.scan(internalUid,
581 [&latestRevision, revision](const QByteArray &key, const QByteArray &) -> bool { 602 [&latestRevision, revision](const QByteArray &key, const QByteArray &) -> bool {
582 const auto foundRevision = DataStore::revisionFromKey(key); 603 const auto foundRevision = Key::fromInternalByteArray(key).revision().toQint64();
583 if (foundRevision < revision && foundRevision > latestRevision) { 604 if (foundRevision < revision && foundRevision > latestRevision) {
584 latestRevision = foundRevision; 605 latestRevision = foundRevision;
585 } 606 }
586 return true; 607 return true;
587 }, 608 },
588 [&](const DataStore::Error &error) { SinkWarningCtx(d->logCtx) << "Failed to read current value from storage: " << error.message; }, true); 609 [&](const DataStore::Error &error) { SinkWarningCtx(d->logCtx) << "Failed to read current value from storage: " << error.message; }, true);
589 readEntity(type, DataStore::assembleKey(uid, latestRevision), callback); 610 const auto key = Key(Identifier::fromDisplayByteArray(uid), latestRevision);
611 readEntity(type, key.toDisplayByteArray(), callback);
590} 612}
591 613
592void EntityStore::readPrevious(const QByteArray &type, const QByteArray &uid, qint64 revision, const std::function<void(const ApplicationDomainType &)> callback) 614void EntityStore::readPrevious(const QByteArray &type, const QByteArray &uid, qint64 revision, const std::function<void(const ApplicationDomainType &)> callback)
@@ -612,15 +634,18 @@ void EntityStore::readAllUids(const QByteArray &type, const std::function<void(c
612 634
613bool EntityStore::contains(const QByteArray &type, const QByteArray &uid) 635bool EntityStore::contains(const QByteArray &type, const QByteArray &uid)
614{ 636{
615 return DataStore::mainDatabase(d->getTransaction(), type).contains(uid); 637 Q_ASSERT(!uid.isEmpty());
638 const auto internalUid = Identifier::fromDisplayByteArray(uid).toInternalByteArray();
639 return DataStore::mainDatabase(d->getTransaction(), type).contains(internalUid);
616} 640}
617 641
618bool EntityStore::exists(const QByteArray &type, const QByteArray &uid) 642bool EntityStore::exists(const QByteArray &type, const QByteArray &uid)
619{ 643{
620 bool found = false; 644 bool found = false;
621 bool alreadyRemoved = false; 645 bool alreadyRemoved = false;
646 const auto internalUid = Identifier::fromDisplayByteArray(uid).toInternalByteArray();
622 DataStore::mainDatabase(d->transaction, type) 647 DataStore::mainDatabase(d->transaction, type)
623 .findLatest(uid, 648 .findLatest(internalUid,
624 [&found, &alreadyRemoved](const QByteArray &key, const QByteArray &data) { 649 [&found, &alreadyRemoved](const QByteArray &key, const QByteArray &data) {
625 auto entity = GetEntity(data.data()); 650 auto entity = GetEntity(data.data());
626 if (entity && entity->metadata()) { 651 if (entity && entity->metadata()) {
@@ -647,12 +672,14 @@ void EntityStore::readRevisions(const QByteArray &type, const QByteArray &uid, q
647{ 672{
648 Q_ASSERT(d); 673 Q_ASSERT(d);
649 Q_ASSERT(!uid.isEmpty()); 674 Q_ASSERT(!uid.isEmpty());
675 const auto internalUid = Identifier::fromDisplayByteArray(uid).toInternalByteArray();
650 DataStore::mainDatabase(d->transaction, type) 676 DataStore::mainDatabase(d->transaction, type)
651 .scan(uid, 677 .scan(internalUid,
652 [&](const QByteArray &key, const QByteArray &value) -> bool { 678 [&](const QByteArray &key, const QByteArray &value) -> bool {
653 const auto revision = DataStore::revisionFromKey(key); 679 const auto parsedKey = Key::fromInternalByteArray(key);
680 const auto revision = parsedKey.revision().toQint64();
654 if (revision >= startingRevision) { 681 if (revision >= startingRevision) {
655 callback(DataStore::uidFromKey(key), revision, Sink::EntityBuffer(value.data(), value.size())); 682 callback(parsedKey.identifier().toDisplayByteArray(), revision, Sink::EntityBuffer(value.data(), value.size()));
656 } 683 }
657 return true; 684 return true;
658 }, 685 },
diff --git a/common/storage/entitystore.h b/common/storage/entitystore.h
index 69de76c..1dcd285 100644
--- a/common/storage/entitystore.h
+++ b/common/storage/entitystore.h
@@ -25,6 +25,7 @@
25#include "domaintypeadaptorfactoryinterface.h" 25#include "domaintypeadaptorfactoryinterface.h"
26#include "query.h" 26#include "query.h"
27#include "storage.h" 27#include "storage.h"
28#include "key.h"
28#include "resourcecontext.h" 29#include "resourcecontext.h"
29#include "metadata_generated.h" 30#include "metadata_generated.h"
30 31
diff --git a/common/storage/key.cpp b/common/storage/key.cpp
new file mode 100644
index 0000000..01a3e3a
--- /dev/null
+++ b/common/storage/key.cpp
@@ -0,0 +1,156 @@
1/*
2 * Copyright (C) 2014 Christian Mollekopf <chrigi_1@fastmail.fm>
3 * Copyright (C) 2018 Rémi Nicole <minijackson@riseup.net>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) version 3, or any
9 * later version accepted by the membership of KDE e.V. (or its
10 * successor approved by the membership of KDE e.V.), which shall
11 * act as a proxy defined in Section 6 of version 3 of the license.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include "key.h"
23#include "utils.h"
24
25using Sink::Storage::Identifier;
26using Sink::Storage::Key;
27using Sink::Storage::Revision;
28
29QDebug &operator<<(QDebug &dbg, const Identifier &id)
30{
31 dbg << id.toDisplayString();
32 return dbg;
33}
34
35QDebug &operator<<(QDebug &dbg, const Revision &rev)
36{
37 dbg << rev.toDisplayString();
38 return dbg;
39}
40
41QDebug &operator<<(QDebug &dbg, const Key &key)
42{
43 dbg << key.toDisplayString();
44 return dbg;
45}
46
47// Identifier
48
49QByteArray Identifier::toInternalByteArray() const
50{
51 return uid.toRfc4122();
52}
53
54Identifier Identifier::fromInternalByteArray(const QByteArray &bytes)
55{
56 Q_ASSERT(bytes.size() == INTERNAL_REPR_SIZE);
57 return Identifier(QUuid::fromRfc4122(bytes));
58}
59
60QString Identifier::toDisplayString() const
61{
62 return uid.toString();
63}
64
65QByteArray Identifier::toDisplayByteArray() const
66{
67 return uid.toByteArray();
68}
69
70Identifier Identifier::fromDisplayByteArray(const QByteArray &bytes)
71{
72 Q_ASSERT(bytes.size() == DISPLAY_REPR_SIZE);
73 return Identifier(QUuid(bytes));
74}
75
76// Revision
77
78QByteArray Revision::toInternalByteArray() const
79{
80 return padNumber(rev);
81}
82
83Revision Revision::fromInternalByteArray(const QByteArray &bytes)
84{
85 Q_ASSERT(bytes.size() == INTERNAL_REPR_SIZE);
86 return Revision(bytes.toLongLong());
87}
88
89QString Revision::toDisplayString() const
90{
91 return QString::fromUtf8(toInternalByteArray());
92}
93
94QByteArray Revision::toDisplayByteArray() const
95{
96 return toInternalByteArray();
97}
98
99Revision Revision::fromDisplayByteArray(const QByteArray &bytes)
100{
101 Q_ASSERT(bytes.size() == DISPLAY_REPR_SIZE);
102 return fromInternalByteArray(bytes);
103}
104
105qint64 Revision::toQint64() const
106{
107 return rev;
108}
109
110// Key
111
112QByteArray Key::toInternalByteArray() const
113{
114 return id.toInternalByteArray() + rev.toInternalByteArray();
115}
116
117Key Key::fromInternalByteArray(const QByteArray &bytes)
118{
119 Q_ASSERT(bytes.size() == INTERNAL_REPR_SIZE);
120 auto idBytes = bytes.mid(0, Identifier::INTERNAL_REPR_SIZE);
121 auto revBytes = bytes.mid(Identifier::INTERNAL_REPR_SIZE);
122 return Key(Identifier::fromInternalByteArray(idBytes), Revision::fromInternalByteArray(revBytes));
123}
124
125QString Key::toDisplayString() const
126{
127 return id.toDisplayString() + rev.toDisplayString();
128}
129
130QByteArray Key::toDisplayByteArray() const
131{
132 return id.toDisplayByteArray() + rev.toDisplayByteArray();
133}
134
135Key Key::fromDisplayByteArray(const QByteArray &bytes)
136{
137 Q_ASSERT(bytes.size() == DISPLAY_REPR_SIZE);
138 auto idBytes = bytes.mid(0, Identifier::DISPLAY_REPR_SIZE);
139 auto revBytes = bytes.mid(Identifier::DISPLAY_REPR_SIZE);
140 return Key(Identifier::fromDisplayByteArray(idBytes), Revision::fromDisplayByteArray(revBytes));
141}
142
143const Identifier &Key::identifier() const
144{
145 return id;
146}
147
148const Revision &Key::revision() const
149{
150 return rev;
151}
152
153void Key::setRevision(const Revision &newRev)
154{
155 rev = newRev;
156}
diff --git a/common/storage/key.h b/common/storage/key.h
new file mode 100644
index 0000000..76dbd13
--- /dev/null
+++ b/common/storage/key.h
@@ -0,0 +1,100 @@
1/*
2 * Copyright (C) 2014 Christian Mollekopf <chrigi_1@fastmail.fm>
3 * Copyright (C) 2018 Rémi Nicole <minijackson@riseup.net>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) version 3, or any
9 * later version accepted by the membership of KDE e.V. (or its
10 * successor approved by the membership of KDE e.V.), which shall
11 * act as a proxy defined in Section 6 of version 3 of the license.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#pragma once
23
24#include "sink_export.h"
25
26#include <QByteArray>
27#include <QDebug>
28#include <QUuid>
29
30namespace Sink {
31namespace Storage {
32
33class Identifier
34{
35public:
36 // RFC 4122 Section 4.1.2 says 128 bits -> 16 bytes
37 static const constexpr size_t INTERNAL_REPR_SIZE = 16;
38 static const constexpr size_t DISPLAY_REPR_SIZE = 38;
39
40 Identifier() : uid(QUuid::createUuid()){};
41
42 QByteArray toInternalByteArray() const;
43 static Identifier fromInternalByteArray(const QByteArray &bytes);
44 QString toDisplayString() const;
45 QByteArray toDisplayByteArray() const;
46 static Identifier fromDisplayByteArray(const QByteArray &bytes);
47
48private:
49 explicit Identifier(const QUuid &uid) : uid(uid) {}
50 QUuid uid;
51};
52
53class Revision
54{
55public:
56 // qint64 has a 19 digit decimal representation
57 static const constexpr size_t INTERNAL_REPR_SIZE = 19;
58 static const constexpr size_t DISPLAY_REPR_SIZE = 19;
59
60 Revision(qint64 rev) : rev(rev) {}
61
62 QByteArray toInternalByteArray() const;
63 static Revision fromInternalByteArray(const QByteArray &bytes);
64 QString toDisplayString() const;
65 QByteArray toDisplayByteArray() const;
66 static Revision fromDisplayByteArray(const QByteArray &bytes);
67 qint64 toQint64() const;
68
69private:
70 qint64 rev;
71};
72
73class Key
74{
75public:
76 static const constexpr size_t INTERNAL_REPR_SIZE = Identifier::INTERNAL_REPR_SIZE + Revision::INTERNAL_REPR_SIZE;
77 static const constexpr size_t DISPLAY_REPR_SIZE = Identifier::DISPLAY_REPR_SIZE + Revision::DISPLAY_REPR_SIZE;
78
79 Key(const Identifier &id, const Revision &rev) : id(id), rev(rev) {}
80
81 QByteArray toInternalByteArray() const;
82 static Key fromInternalByteArray(const QByteArray &bytes);
83 QString toDisplayString() const;
84 QByteArray toDisplayByteArray() const;
85 static Key fromDisplayByteArray(const QByteArray &bytes);
86 const Identifier &identifier() const;
87 const Revision &revision() const;
88 void setRevision(const Revision &newRev);
89
90private:
91 Identifier id;
92 Revision rev;
93};
94
95} // namespace Storage
96} // namespace Sink
97
98SINK_EXPORT QDebug& operator<<(QDebug &dbg, const Sink::Storage::Identifier &);
99SINK_EXPORT QDebug& operator<<(QDebug &dbg, const Sink::Storage::Revision &);
100SINK_EXPORT QDebug& operator<<(QDebug &dbg, const Sink::Storage::Key &);
diff --git a/common/storage_common.cpp b/common/storage_common.cpp
index 057dce4..f96097a 100644
--- a/common/storage_common.cpp
+++ b/common/storage_common.cpp
@@ -194,23 +194,6 @@ bool DataStore::isInternalKey(const QByteArray &key)
194 return key.startsWith(s_internalPrefix); 194 return key.startsWith(s_internalPrefix);
195} 195}
196 196
197QByteArray DataStore::assembleKey(const QByteArray &key, qint64 revision)
198{
199 Q_ASSERT(revision <= 9223372036854775807);
200 Q_ASSERT(key.size() == s_lengthOfUid);
201 return key + QByteArray::number(revision).rightJustified(19, '0', false);
202}
203
204QByteArray DataStore::uidFromKey(const QByteArray &key)
205{
206 return key.mid(0, s_lengthOfUid);
207}
208
209qint64 DataStore::revisionFromKey(const QByteArray &key)
210{
211 return key.mid(s_lengthOfUid + 1).toLongLong();
212}
213
214QByteArray DataStore::generateUid() 197QByteArray DataStore::generateUid()
215{ 198{
216 return createUuid(); 199 return createUuid();
diff --git a/common/synchronizer.cpp b/common/synchronizer.cpp
index 71091a6..a43ec06 100644
--- a/common/synchronizer.cpp
+++ b/common/synchronizer.cpp
@@ -616,7 +616,8 @@ KAsync::Job<void> Synchronizer::replay(const QByteArray &type, const QByteArray
616 Q_ASSERT(mEntityStore->hasTransaction()); 616 Q_ASSERT(mEntityStore->hasTransaction());
617 617
618 const auto operation = metadataBuffer ? metadataBuffer->operation() : Sink::Operation_Creation; 618 const auto operation = metadataBuffer ? metadataBuffer->operation() : Sink::Operation_Creation;
619 const auto uid = Sink::Storage::DataStore::uidFromKey(key); 619 // TODO: should not use internal representations
620 const auto uid = Sink::Storage::Key::fromDisplayByteArray(key).identifier().toDisplayByteArray();
620 const auto modifiedProperties = metadataBuffer->modifiedProperties() ? BufferUtils::fromVector(*metadataBuffer->modifiedProperties()) : QByteArrayList(); 621 const auto modifiedProperties = metadataBuffer->modifiedProperties() ? BufferUtils::fromVector(*metadataBuffer->modifiedProperties()) : QByteArrayList();
621 QByteArray oldRemoteId; 622 QByteArray oldRemoteId;
622 623
diff --git a/common/typeindex.cpp b/common/typeindex.cpp
index b18791f..0b78d59 100644
--- a/common/typeindex.cpp
+++ b/common/typeindex.cpp
@@ -25,8 +25,6 @@
25#include <QDateTime> 25#include <QDateTime>
26#include <QDataStream> 26#include <QDataStream>
27 27
28#include <cmath>
29
30using namespace Sink; 28using namespace Sink;
31 29
32static QByteArray getByteArray(const QVariant &value) 30static QByteArray getByteArray(const QVariant &value)
@@ -53,13 +51,6 @@ static QByteArray getByteArray(const QVariant &value)
53 return "toplevel"; 51 return "toplevel";
54} 52}
55 53
56template <typename T>
57static QByteArray padNumber(T number)
58{
59 static T uint_num_digits = (T)std::log10(std::numeric_limits<T>::max()) + 1;
60 return QByteArray::number(number).rightJustified(uint_num_digits, '0');
61}
62
63static QByteArray toSortableByteArrayImpl(const QDateTime &date) 54static QByteArray toSortableByteArrayImpl(const QDateTime &date)
64{ 55{
65 // Sort invalid last 56 // Sort invalid last
diff --git a/common/utils.h b/common/utils.h
index 253de61..7066d79 100644
--- a/common/utils.h
+++ b/common/utils.h
@@ -20,6 +20,17 @@
20 20
21#include <QByteArray> 21#include <QByteArray>
22 22
23#include <cmath>
24
23namespace Sink { 25namespace Sink {
24 QByteArray createUuid(); 26
27QByteArray createUuid();
28
29template <typename T>
30static QByteArray padNumber(T number)
31{
32 static T uint_num_digits = (T)std::log10(std::numeric_limits<T>::max()) + 1;
33 return QByteArray::number(number).rightJustified(uint_num_digits, '0');
25} 34}
35
36} // namespace Sink
diff --git a/sinksh/syntax_modules/sink_inspect.cpp b/sinksh/syntax_modules/sink_inspect.cpp
index e0e30c7..7a41ef0 100644
--- a/sinksh/syntax_modules/sink_inspect.cpp
+++ b/sinksh/syntax_modules/sink_inspect.cpp
@@ -32,6 +32,8 @@
32#include "common/bufferutils.h" 32#include "common/bufferutils.h"
33#include "common/fulltextindex.h" 33#include "common/fulltextindex.h"
34 34
35#include "storage/key.h"
36
35#include "sinksh_utils.h" 37#include "sinksh_utils.h"
36#include "state.h" 38#include "state.h"
37#include "syntaxtree.h" 39#include "syntaxtree.h"
@@ -88,7 +90,7 @@ bool inspect(const QStringList &args, State &state)
88 90
89 QSet<QByteArray> uids; 91 QSet<QByteArray> uids;
90 db.scan("", [&] (const QByteArray &key, const QByteArray &data) { 92 db.scan("", [&] (const QByteArray &key, const QByteArray &data) {
91 uids.insert(Sink::Storage::DataStore::uidFromKey(key)); 93 uids.insert(Sink::Storage::Key::fromInternalByteArray(key).identifier().toDisplayByteArray());
92 return true; 94 return true;
93 }, 95 },
94 [&](const Sink::Storage::DataStore::Error &e) { 96 [&](const Sink::Storage::DataStore::Error &e) {
diff --git a/tests/pipelinetest.cpp b/tests/pipelinetest.cpp
index 45e2fbb..b41a5c2 100644
--- a/tests/pipelinetest.cpp
+++ b/tests/pipelinetest.cpp
@@ -20,6 +20,7 @@
20#include "domainadaptor.h" 20#include "domainadaptor.h"
21#include "definitions.h" 21#include "definitions.h"
22#include "adaptorfactoryregistry.h" 22#include "adaptorfactoryregistry.h"
23#include "storage/key.h"
23 24
24static void removeFromDisk(const QString &name) 25static void removeFromDisk(const QString &name)
25{ 26{
@@ -250,8 +251,8 @@ private slots:
250 // Get uid of written entity 251 // Get uid of written entity
251 auto keys = getKeys(instanceIdentifier(), "event.main"); 252 auto keys = getKeys(instanceIdentifier(), "event.main");
252 QCOMPARE(keys.size(), 1); 253 QCOMPARE(keys.size(), 1);
253 const auto key = keys.first(); 254 auto key = Sink::Storage::Key::fromInternalByteArray(keys.first());
254 const auto uid = Sink::Storage::DataStore::uidFromKey(key); 255 const auto uid = key.identifier().toDisplayByteArray();
255 256
256 // Execute the modification 257 // Execute the modification
257 entityFbb.Clear(); 258 entityFbb.Clear();
@@ -260,8 +261,10 @@ private slots:
260 pipeline.modifiedEntity(modifyCommand.constData(), modifyCommand.size()); 261 pipeline.modifiedEntity(modifyCommand.constData(), modifyCommand.size());
261 pipeline.commit(); 262 pipeline.commit();
262 263
264 key.setRevision(2);
265
263 // Ensure we've got the new revision with the modification 266 // Ensure we've got the new revision with the modification
264 auto buffer = getEntity(instanceIdentifier(), "event.main", Sink::Storage::DataStore::assembleKey(uid, 2)); 267 auto buffer = getEntity(instanceIdentifier(), "event.main", key.toInternalByteArray());
265 QVERIFY(!buffer.isEmpty()); 268 QVERIFY(!buffer.isEmpty());
266 Sink::EntityBuffer entityBuffer(buffer.data(), buffer.size()); 269 Sink::EntityBuffer entityBuffer(buffer.data(), buffer.size());
267 auto adaptor = adaptorFactory->createAdaptor(entityBuffer.entity()); 270 auto adaptor = adaptorFactory->createAdaptor(entityBuffer.entity());
@@ -296,7 +299,8 @@ private slots:
296 // Get uid of written entity 299 // Get uid of written entity
297 auto keys = getKeys(instanceIdentifier(), "event.main"); 300 auto keys = getKeys(instanceIdentifier(), "event.main");
298 QCOMPARE(keys.size(), 1); 301 QCOMPARE(keys.size(), 1);
299 const auto uid = Sink::Storage::DataStore::uidFromKey(keys.first()); 302 auto key = Sink::Storage::Key::fromInternalByteArray(keys.first());
303 const auto uid = key.identifier().toDisplayByteArray();
300 304
301 305
302 // Create another operation inbetween 306 // Create another operation inbetween
@@ -315,8 +319,10 @@ private slots:
315 pipeline.modifiedEntity(modifyCommand.constData(), modifyCommand.size()); 319 pipeline.modifiedEntity(modifyCommand.constData(), modifyCommand.size());
316 pipeline.commit(); 320 pipeline.commit();
317 321
322 key.setRevision(3);
323
318 // Ensure we've got the new revision with the modification 324 // Ensure we've got the new revision with the modification
319 auto buffer = getEntity(instanceIdentifier(), "event.main", Sink::Storage::DataStore::assembleKey(uid, 3)); 325 auto buffer = getEntity(instanceIdentifier(), "event.main", key.toInternalByteArray());
320 QVERIFY(!buffer.isEmpty()); 326 QVERIFY(!buffer.isEmpty());
321 Sink::EntityBuffer entityBuffer(buffer.data(), buffer.size()); 327 Sink::EntityBuffer entityBuffer(buffer.data(), buffer.size());
322 auto adaptor = adaptorFactory->createAdaptor(entityBuffer.entity()); 328 auto adaptor = adaptorFactory->createAdaptor(entityBuffer.entity());
@@ -337,7 +343,7 @@ private slots:
337 auto result = getKeys(instanceIdentifier(), "event.main"); 343 auto result = getKeys(instanceIdentifier(), "event.main");
338 QCOMPARE(result.size(), 1); 344 QCOMPARE(result.size(), 1);
339 345
340 const auto uid = Sink::Storage::DataStore::uidFromKey(result.first()); 346 const auto uid = Sink::Storage::Key::fromInternalByteArray(result.first()).identifier().toDisplayByteArray();
341 347
342 // Delete entity 348 // Delete entity
343 auto deleteCommand = deleteEntityCommand(uid, 1); 349 auto deleteCommand = deleteEntityCommand(uid, 1);
@@ -372,22 +378,22 @@ private slots:
372 pipeline.newEntity(command.constData(), command.size()); 378 pipeline.newEntity(command.constData(), command.size());
373 QCOMPARE(testProcessor->newUids.size(), 1); 379 QCOMPARE(testProcessor->newUids.size(), 1);
374 QCOMPARE(testProcessor->newRevisions.size(), 1); 380 QCOMPARE(testProcessor->newRevisions.size(), 1);
375 // Key doesn't contain revision and is just the uid 381 const auto uid = Sink::Storage::Identifier::fromDisplayByteArray(testProcessor->newUids.at(0)).toDisplayByteArray();
376 QCOMPARE(testProcessor->newUids.at(0), Sink::Storage::DataStore::uidFromKey(testProcessor->newUids.at(0))); 382 QCOMPARE(testProcessor->newUids.at(0), uid);
377 } 383 }
378 pipeline.commit(); 384 pipeline.commit();
379 entityFbb.Clear(); 385 entityFbb.Clear();
380 pipeline.startTransaction(); 386 pipeline.startTransaction();
381 auto keys = getKeys(instanceIdentifier(), "event.main"); 387 auto keys = getKeys(instanceIdentifier(), "event.main");
382 QCOMPARE(keys.size(), 1); 388 QCOMPARE(keys.size(), 1);
383 const auto uid = Sink::Storage::DataStore::uidFromKey(keys.first()); 389 const auto uid = Sink::Storage::Key::fromInternalByteArray(keys.first()).identifier().toDisplayByteArray();
384 { 390 {
385 auto modifyCommand = modifyEntityCommand(createEvent(entityFbb, "summary2"), uid, 1); 391 auto modifyCommand = modifyEntityCommand(createEvent(entityFbb, "summary2"), uid, 1);
386 pipeline.modifiedEntity(modifyCommand.constData(), modifyCommand.size()); 392 pipeline.modifiedEntity(modifyCommand.constData(), modifyCommand.size());
387 QCOMPARE(testProcessor->modifiedUids.size(), 1); 393 QCOMPARE(testProcessor->modifiedUids.size(), 1);
388 QCOMPARE(testProcessor->modifiedRevisions.size(), 1); 394 QCOMPARE(testProcessor->modifiedRevisions.size(), 1);
389 // Key doesn't contain revision and is just the uid 395 const auto uid2 = Sink::Storage::Identifier::fromDisplayByteArray(testProcessor->modifiedUids.at(0)).toDisplayByteArray();
390 QCOMPARE(testProcessor->modifiedUids.at(0), Sink::Storage::DataStore::uidFromKey(testProcessor->modifiedUids.at(0))); 396 QCOMPARE(testProcessor->modifiedUids.at(0), uid2);
391 } 397 }
392 pipeline.commit(); 398 pipeline.commit();
393 entityFbb.Clear(); 399 entityFbb.Clear();
@@ -398,8 +404,8 @@ private slots:
398 QCOMPARE(testProcessor->deletedUids.size(), 1); 404 QCOMPARE(testProcessor->deletedUids.size(), 1);
399 QCOMPARE(testProcessor->deletedUids.size(), 1); 405 QCOMPARE(testProcessor->deletedUids.size(), 1);
400 QCOMPARE(testProcessor->deletedSummaries.size(), 1); 406 QCOMPARE(testProcessor->deletedSummaries.size(), 1);
401 // Key doesn't contain revision and is just the uid 407 const auto uid2 = Sink::Storage::Identifier::fromDisplayByteArray(testProcessor->modifiedUids.at(0)).toDisplayByteArray();
402 QCOMPARE(testProcessor->deletedUids.at(0), Sink::Storage::DataStore::uidFromKey(testProcessor->deletedUids.at(0))); 408 QCOMPARE(testProcessor->deletedUids.at(0), uid2);
403 QCOMPARE(testProcessor->deletedSummaries.at(0), QByteArray("summary2")); 409 QCOMPARE(testProcessor->deletedSummaries.at(0), QByteArray("summary2"));
404 } 410 }
405 } 411 }
@@ -421,8 +427,8 @@ private slots:
421 // Get uid of written entity 427 // Get uid of written entity
422 auto keys = getKeys(instanceIdentifier(), "event.main"); 428 auto keys = getKeys(instanceIdentifier(), "event.main");
423 QCOMPARE(keys.size(), 1); 429 QCOMPARE(keys.size(), 1);
424 const auto key = keys.first(); 430 auto key = Sink::Storage::Key::fromInternalByteArray(keys.first());
425 const auto uid = Sink::Storage::DataStore::uidFromKey(key); 431 const auto uid = key.identifier().toDisplayByteArray();
426 432
427 //Simulate local modification 433 //Simulate local modification
428 { 434 {
@@ -444,8 +450,10 @@ private slots:
444 pipeline.commit(); 450 pipeline.commit();
445 } 451 }
446 452
453 key.setRevision(3);
454
447 // Ensure we've got the new revision with the modification 455 // Ensure we've got the new revision with the modification
448 auto buffer = getEntity(instanceIdentifier(), "event.main", Sink::Storage::DataStore::assembleKey(uid, 3)); 456 auto buffer = getEntity(instanceIdentifier(), "event.main", key.toInternalByteArray());
449 QVERIFY(!buffer.isEmpty()); 457 QVERIFY(!buffer.isEmpty());
450 Sink::EntityBuffer entityBuffer(buffer.data(), buffer.size()); 458 Sink::EntityBuffer entityBuffer(buffer.data(), buffer.size());
451 auto adaptor = adaptorFactory->createAdaptor(entityBuffer.entity()); 459 auto adaptor = adaptorFactory->createAdaptor(entityBuffer.entity());
diff --git a/tests/storagetest.cpp b/tests/storagetest.cpp
index 96368a7..e165616 100644
--- a/tests/storagetest.cpp
+++ b/tests/storagetest.cpp
@@ -7,6 +7,7 @@
7#include <QtConcurrent/QtConcurrentRun> 7#include <QtConcurrent/QtConcurrentRun>
8 8
9#include "common/storage.h" 9#include "common/storage.h"
10#include "storage/key.h"
10 11
11/** 12/**
12 * Test of the storage implementation to ensure it can do the low level operations as expected. 13 * Test of the storage implementation to ensure it can do the low level operations as expected.
@@ -499,8 +500,11 @@ private slots:
499 auto db = transaction.openDatabase("test", nullptr, false); 500 auto db = transaction.openDatabase("test", nullptr, false);
500 const auto uid = "{c5d06a9f-1534-4c52-b8ea-415db68bdadf}"; 501 const auto uid = "{c5d06a9f-1534-4c52-b8ea-415db68bdadf}";
501 //Ensure we can sort 1 and 10 properly (by default string comparison 10 comes before 6) 502 //Ensure we can sort 1 and 10 properly (by default string comparison 10 comes before 6)
502 db.write(Sink::Storage::DataStore::assembleKey(uid, 6), "value1"); 503 const auto id = Sink::Storage::Identifier::fromDisplayByteArray(uid);
503 db.write(Sink::Storage::DataStore::assembleKey(uid, 10), "value2"); 504 auto key = Sink::Storage::Key(id, 6);
505 db.write(key.toInternalByteArray(), "value1");
506 key.setRevision(10);
507 db.write(key.toInternalByteArray(), "value2");
504 db.findLatest(uid, [&](const QByteArray &key, const QByteArray &value) { result = value; }); 508 db.findLatest(uid, [&](const QByteArray &key, const QByteArray &value) { result = value; });
505 QCOMPARE(result, QByteArray("value2")); 509 QCOMPARE(result, QByteArray("value2"));
506 } 510 }
@@ -732,7 +736,7 @@ private slots:
732 Sink::Storage::DataStore::clearEnv(); 736 Sink::Storage::DataStore::clearEnv();
733 737
734 //Try to read-only dynamic opening of the db. 738 //Try to read-only dynamic opening of the db.
735 //This is the case if we don't have all databases available upon initializatoin and we don't (e.g. because the db hasn't been created yet) 739 //This is the case if we don't have all databases available upon initializatoin and we don't (e.g. because the db hasn't been created yet)
736 { 740 {
737 // Trick the db into not loading all dbs by passing in a bogus layout. 741 // Trick the db into not loading all dbs by passing in a bogus layout.
738 Sink::Storage::DataStore store(testDataPath, {dbName, {{"bogus", 0}}}, Sink::Storage::DataStore::ReadOnly); 742 Sink::Storage::DataStore store(testDataPath, {dbName, {{"bogus", 0}}}, Sink::Storage::DataStore::ReadOnly);
@@ -750,7 +754,7 @@ private slots:
750 754
751 Sink::Storage::DataStore::clearEnv(); 755 Sink::Storage::DataStore::clearEnv();
752 //Try to read-write dynamic opening of the db. 756 //Try to read-write dynamic opening of the db.
753 //This is the case if we don't have all databases available upon initializatoin and we don't (e.g. because the db hasn't been created yet) 757 //This is the case if we don't have all databases available upon initializatoin and we don't (e.g. because the db hasn't been created yet)
754 { 758 {
755 // Trick the db into not loading all dbs by passing in a bogus layout. 759 // Trick the db into not loading all dbs by passing in a bogus layout.
756 Sink::Storage::DataStore store(testDataPath, {dbName, {{"bogus", 0}}}, Sink::Storage::DataStore::ReadWrite); 760 Sink::Storage::DataStore store(testDataPath, {dbName, {{"bogus", 0}}}, Sink::Storage::DataStore::ReadWrite);