summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/changereplay.cpp4
-rw-r--r--common/storage.h156
-rw-r--r--common/storage/entitystore.cpp66
-rw-r--r--common/storage_common.cpp29
-rw-r--r--common/synchronizer.cpp3
-rw-r--r--common/typeindex.cpp9
-rw-r--r--common/utils.cpp1
-rw-r--r--common/utils.h13
-rw-r--r--sinksh/syntax_modules/sink_inspect.cpp3
-rw-r--r--tests/pipelinetest.cpp29
-rw-r--r--tests/storagetest.cpp10
11 files changed, 272 insertions, 51 deletions
diff --git a/common/changereplay.cpp b/common/changereplay.cpp
index 0adbd78..e81f52c 100644
--- a/common/changereplay.cpp
+++ b/common/changereplay.cpp
@@ -113,7 +113,9 @@ KAsync::Job<void> ChangeReplay::replayNextRevision()
113 if (uid.isEmpty() || type.isEmpty()) { 113 if (uid.isEmpty() || type.isEmpty()) {
114 SinkErrorCtx(mLogCtx) << "Failed to read uid or type for revison: " << revision << uid << type; 114 SinkErrorCtx(mLogCtx) << "Failed to read uid or type for revison: " << revision << uid << type;
115 } else { 115 } else {
116 const auto key = DataStore::assembleKey(uid, revision); 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).toInternalByteArray();
117 QByteArray entityBuffer; 119 QByteArray entityBuffer;
118 DataStore::mainDatabase(mMainStoreTransaction, type) 120 DataStore::mainDatabase(mMainStoreTransaction, type)
119 .scan(key, 121 .scan(key,
diff --git a/common/storage.h b/common/storage.h
index a8c486c..3cc5adf 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
@@ -38,6 +40,151 @@ struct SINK_EXPORT DbLayout {
38 Databases tables; 40 Databases tables;
39}; 41};
40 42
43class Identifier
44{
45public:
46 // RFC 4122 Section 4.1.2 says 128 bits -> 16 bytes
47 static const constexpr size_t INTERNAL_REPR_SIZE = 16;
48 static const constexpr size_t DISPLAY_REPR_SIZE = 38;
49
50 Identifier() : uid(QUuid::createUuid()) {};
51
52 QByteArray toInternalByteArray() const
53 {
54 return uid.toRfc4122();
55 }
56
57 static Identifier fromInternalByteArray(const QByteArray &bytes)
58 {
59 Q_ASSERT(bytes.size() == INTERNAL_REPR_SIZE);
60 return Identifier(QUuid::fromRfc4122(bytes));
61 }
62
63 QString toDisplayString() const
64 {
65 return uid.toString();
66 }
67
68 QByteArray toDisplayByteArray() const
69 {
70 return uid.toByteArray();
71 }
72
73 static Identifier fromDisplayByteArray(const QByteArray &bytes)
74 {
75 Q_ASSERT(bytes.size() == DISPLAY_REPR_SIZE);
76 return Identifier(QUuid::fromString(QString::fromUtf8(bytes)));
77 }
78
79private:
80 explicit Identifier(const QUuid &uid) : uid(uid) {}
81 QUuid uid;
82};
83
84class Revision
85{
86public:
87 // qint64 has a 19 digit decimal representation
88 static const constexpr size_t INTERNAL_REPR_SIZE = 19;
89 static const constexpr size_t DISPLAY_REPR_SIZE = 19;
90
91 Revision(qint64 rev) : rev(rev) {}
92
93 QByteArray toInternalByteArray() const
94 {
95 return padNumber(rev);
96 }
97
98 static Revision fromInternalByteArray(const QByteArray &bytes)
99 {
100 Q_ASSERT(bytes.size() == INTERNAL_REPR_SIZE);
101 return Revision(bytes.toLongLong());
102 }
103
104 QString toDisplayString() const
105 {
106 return QString::fromUtf8(toInternalByteArray());
107 }
108
109 QByteArray toDisplayByteArray() const
110 {
111 return toInternalByteArray();
112 }
113
114 static Revision fromDisplayByteArray(const QByteArray &bytes)
115 {
116 Q_ASSERT(bytes.size() == DISPLAY_REPR_SIZE);
117 return fromInternalByteArray(bytes);
118 }
119
120 qint64 toQint64() const
121 {
122 return rev;
123 }
124
125private:
126 qint64 rev;
127};
128
129class Key
130{
131public:
132 static const constexpr size_t INTERNAL_REPR_SIZE = Identifier::INTERNAL_REPR_SIZE + Revision::INTERNAL_REPR_SIZE;
133 static const constexpr size_t DISPLAY_REPR_SIZE = Identifier::DISPLAY_REPR_SIZE + Revision::DISPLAY_REPR_SIZE;
134
135 Key(const Identifier &id, const Revision &rev) : id(id), rev(rev) {}
136
137 QByteArray toInternalByteArray() const
138 {
139 return id.toInternalByteArray() + rev.toInternalByteArray();
140 }
141
142 static Key fromInternalByteArray(const QByteArray &bytes)
143 {
144 Q_ASSERT(bytes.size() == INTERNAL_REPR_SIZE);
145 auto idBytes = bytes.mid(0, Identifier::INTERNAL_REPR_SIZE);
146 auto revBytes = bytes.mid(Identifier::INTERNAL_REPR_SIZE);
147 return Key(Identifier::fromInternalByteArray(idBytes), Revision::fromInternalByteArray(revBytes));
148 }
149
150 QString toDisplayString() const
151 {
152 return id.toDisplayString() + rev.toDisplayString();
153 }
154
155 QByteArray toDisplayByteArray() const
156 {
157 return id.toDisplayByteArray() + rev.toDisplayByteArray();
158 }
159
160 static Key fromDisplayByteArray(const QByteArray &bytes)
161 {
162 Q_ASSERT(bytes.size() == DISPLAY_REPR_SIZE);
163 auto idBytes = bytes.mid(0, Identifier::DISPLAY_REPR_SIZE);
164 auto revBytes = bytes.mid(Identifier::DISPLAY_REPR_SIZE);
165 return Key(Identifier::fromDisplayByteArray(idBytes), Revision::fromDisplayByteArray(revBytes));
166 }
167
168 const Identifier &identifier() const
169 {
170 return id;
171 }
172
173 const Revision &revision() const
174 {
175 return rev;
176 }
177
178 void setRevision(const Revision &newRev)
179 {
180 rev = newRev;
181 }
182
183private:
184 Identifier id;
185 Revision rev;
186};
187
41class SINK_EXPORT DataStore 188class SINK_EXPORT DataStore
42{ 189{
43public: 190public:
@@ -237,9 +384,9 @@ public:
237 static bool isInternalKey(void *key, int keySize); 384 static bool isInternalKey(void *key, int keySize);
238 static bool isInternalKey(const QByteArray &key); 385 static bool isInternalKey(const QByteArray &key);
239 386
240 static QByteArray assembleKey(const QByteArray &key, qint64 revision); 387 //static QByteArray assembleKey(const QByteArray &key, qint64 revision);
241 static QByteArray uidFromKey(const QByteArray &key); 388 //static Identifier uidFromKey(const QByteArray &key);
242 static qint64 revisionFromKey(const QByteArray &key); 389 //static qint64 revisionFromKey(const QByteArray &key);
243 390
244 static NamedDatabase mainDatabase(const Transaction &, const QByteArray &type); 391 static NamedDatabase mainDatabase(const Transaction &, const QByteArray &type);
245 392
@@ -260,3 +407,6 @@ private:
260} // namespace Sink 407} // namespace Sink
261 408
262SINK_EXPORT QDebug& operator<<(QDebug &dbg, const Sink::Storage::DataStore::Error &error); 409SINK_EXPORT QDebug& operator<<(QDebug &dbg, const Sink::Storage::DataStore::Error &error);
410SINK_EXPORT QDebug& operator<<(QDebug &dbg, const Sink::Storage::Identifier &);
411SINK_EXPORT QDebug& operator<<(QDebug &dbg, const Sink::Storage::Revision &);
412SINK_EXPORT QDebug& operator<<(QDebug &dbg, const Sink::Storage::Key &);
diff --git a/common/storage/entitystore.cpp b/common/storage/entitystore.cpp
index dd6bbf0..f74d3df 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);
@@ -428,7 +434,7 @@ QVector<QByteArray> EntityStore::fullScan(const QByteArray &type)
428 DataStore::mainDatabase(d->getTransaction(), type) 434 DataStore::mainDatabase(d->getTransaction(), type)
429 .scan(QByteArray(), 435 .scan(QByteArray(),
430 [&](const QByteArray &key, const QByteArray &value) -> bool { 436 [&](const QByteArray &key, const QByteArray &value) -> bool {
431 const auto uid = DataStore::uidFromKey(key); 437 const auto uid = Sink::Storage::Key::fromInternalByteArray(key).identifier().toDisplayByteArray();
432 if (keys.contains(uid)) { 438 if (keys.contains(uid)) {
433 //Not something that should persist if the replay works, so we keep a message for now. 439 //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; 440 SinkTraceCtx(d->logCtx) << "Multiple revisions for key: " << key;
@@ -479,16 +485,24 @@ void EntityStore::indexLookup(const QByteArray &type, const QByteArray &property
479 /* }); */ 485 /* }); */
480} 486}
481 487
482void EntityStore::readLatest(const QByteArray &type, const QByteArray &uid, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback) 488void EntityStore::readLatest(const QByteArray &type, const QByteArray &key, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback)
483{ 489{
484 Q_ASSERT(d); 490 Q_ASSERT(d);
485 Q_ASSERT(!uid.isEmpty()); 491 Q_ASSERT(!key.isEmpty());
492 const auto internalKey = [&key]() {
493 if(key.size() == Identifier::DISPLAY_REPR_SIZE) {
494 return Identifier::fromDisplayByteArray(key).toInternalByteArray();
495 } else {
496 return Key::fromDisplayByteArray(key).toInternalByteArray();
497 }
498 }();
486 auto db = DataStore::mainDatabase(d->getTransaction(), type); 499 auto db = DataStore::mainDatabase(d->getTransaction(), type);
487 db.findLatest(uid, 500 db.findLatest(internalKey,
488 [=](const QByteArray &key, const QByteArray &value) { 501 [=](const QByteArray &key, const QByteArray &value) {
489 callback(DataStore::uidFromKey(key), Sink::EntityBuffer(value.data(), value.size())); 502 const auto uid = Sink::Storage::Key::fromInternalByteArray(key).identifier().toDisplayByteArray();
503 callback(uid, Sink::EntityBuffer(value.data(), value.size()));
490 }, 504 },
491 [&](const DataStore::Error &error) { SinkWarningCtx(d->logCtx) << "Error during readLatest query: " << error.message << uid; }); 505 [&](const DataStore::Error &error) { SinkWarningCtx(d->logCtx) << "Error during readLatest query: " << error.message << key; });
492} 506}
493 507
494void EntityStore::readLatest(const QByteArray &type, const QByteArray &uid, const std::function<void(const ApplicationDomainType &)> callback) 508void EntityStore::readLatest(const QByteArray &type, const QByteArray &uid, const std::function<void(const ApplicationDomainType &)> callback)
@@ -516,12 +530,15 @@ ApplicationDomain::ApplicationDomainType EntityStore::readLatest(const QByteArra
516 return dt; 530 return dt;
517} 531}
518 532
519void EntityStore::readEntity(const QByteArray &type, const QByteArray &key, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback) 533// TODO: check every usage
534void EntityStore::readEntity(const QByteArray &type, const QByteArray &displayKey, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback)
520{ 535{
536 const auto key = Key::fromDisplayByteArray(displayKey);
521 auto db = DataStore::mainDatabase(d->getTransaction(), type); 537 auto db = DataStore::mainDatabase(d->getTransaction(), type);
522 db.scan(key, 538 db.scan(key.toInternalByteArray(),
523 [=](const QByteArray &key, const QByteArray &value) -> bool { 539 [=](const QByteArray &key, const QByteArray &value) -> bool {
524 callback(DataStore::uidFromKey(key), Sink::EntityBuffer(value.data(), value.size())); 540 const auto uid = Sink::Storage::Key::fromInternalByteArray(key).identifier().toDisplayByteArray();
541 callback(uid, Sink::EntityBuffer(value.data(), value.size()));
525 return false; 542 return false;
526 }, 543 },
527 [&](const DataStore::Error &error) { SinkWarningCtx(d->logCtx) << "Error during readEntity query: " << error.message << key; }); 544 [&](const DataStore::Error &error) { SinkWarningCtx(d->logCtx) << "Error during readEntity query: " << error.message << key; });
@@ -567,9 +584,10 @@ void EntityStore::readRevisions(qint64 baseRevision, const QByteArray &expectedT
567 revisionCounter++; 584 revisionCounter++;
568 continue; 585 continue;
569 } 586 }
570 const auto key = DataStore::assembleKey(uid, revisionCounter); 587 const auto key = Key(Identifier::fromDisplayByteArray(uid), revisionCounter);
588
571 revisionCounter++; 589 revisionCounter++;
572 callback(key); 590 callback(key.toDisplayByteArray());
573 } 591 }
574} 592}
575 593
@@ -577,16 +595,19 @@ void EntityStore::readPrevious(const QByteArray &type, const QByteArray &uid, qi
577{ 595{
578 auto db = DataStore::mainDatabase(d->getTransaction(), type); 596 auto db = DataStore::mainDatabase(d->getTransaction(), type);
579 qint64 latestRevision = 0; 597 qint64 latestRevision = 0;
580 db.scan(uid, 598 const auto internalUid = Identifier::fromDisplayByteArray(uid).toInternalByteArray();
599 db.scan(internalUid,
581 [&latestRevision, revision](const QByteArray &key, const QByteArray &) -> bool { 600 [&latestRevision, revision](const QByteArray &key, const QByteArray &) -> bool {
582 const auto foundRevision = DataStore::revisionFromKey(key); 601 //const auto foundRevision = DataStore::revisionFromKey(key);
602 const auto foundRevision = Key::fromInternalByteArray(key).revision().toQint64();
583 if (foundRevision < revision && foundRevision > latestRevision) { 603 if (foundRevision < revision && foundRevision > latestRevision) {
584 latestRevision = foundRevision; 604 latestRevision = foundRevision;
585 } 605 }
586 return true; 606 return true;
587 }, 607 },
588 [&](const DataStore::Error &error) { SinkWarningCtx(d->logCtx) << "Failed to read current value from storage: " << error.message; }, true); 608 [&](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); 609 const auto key = Key(Identifier::fromDisplayByteArray(uid), latestRevision);
610 readEntity(type, key.toDisplayByteArray(), callback);
590} 611}
591 612
592void EntityStore::readPrevious(const QByteArray &type, const QByteArray &uid, qint64 revision, const std::function<void(const ApplicationDomainType &)> callback) 613void EntityStore::readPrevious(const QByteArray &type, const QByteArray &uid, qint64 revision, const std::function<void(const ApplicationDomainType &)> callback)
@@ -612,15 +633,22 @@ void EntityStore::readAllUids(const QByteArray &type, const std::function<void(c
612 633
613bool EntityStore::contains(const QByteArray &type, const QByteArray &uid) 634bool EntityStore::contains(const QByteArray &type, const QByteArray &uid)
614{ 635{
615 return DataStore::mainDatabase(d->getTransaction(), type).contains(uid); 636 // Because of pipeline using this function with new entities
637 // TODO: maybe modify pipeline instead?
638 if(uid.isEmpty()) {
639 return false;
640 }
641 const auto internalUid = Identifier::fromDisplayByteArray(uid).toInternalByteArray();
642 return DataStore::mainDatabase(d->getTransaction(), type).contains(internalUid);
616} 643}
617 644
618bool EntityStore::exists(const QByteArray &type, const QByteArray &uid) 645bool EntityStore::exists(const QByteArray &type, const QByteArray &uid)
619{ 646{
620 bool found = false; 647 bool found = false;
621 bool alreadyRemoved = false; 648 bool alreadyRemoved = false;
649 const auto internalUid = Identifier::fromDisplayByteArray(uid).toInternalByteArray();
622 DataStore::mainDatabase(d->transaction, type) 650 DataStore::mainDatabase(d->transaction, type)
623 .findLatest(uid, 651 .findLatest(internalUid,
624 [&found, &alreadyRemoved](const QByteArray &key, const QByteArray &data) { 652 [&found, &alreadyRemoved](const QByteArray &key, const QByteArray &data) {
625 auto entity = GetEntity(data.data()); 653 auto entity = GetEntity(data.data());
626 if (entity && entity->metadata()) { 654 if (entity && entity->metadata()) {
diff --git a/common/storage_common.cpp b/common/storage_common.cpp
index 057dce4..b36ffcb 100644
--- a/common/storage_common.cpp
+++ b/common/storage_common.cpp
@@ -24,18 +24,40 @@
24#include "log.h" 24#include "log.h"
25#include "utils.h" 25#include "utils.h"
26 26
27#include <QUuid>
28
27QDebug& operator<<(QDebug &dbg, const Sink::Storage::DataStore::Error &error) 29QDebug& operator<<(QDebug &dbg, const Sink::Storage::DataStore::Error &error)
28{ 30{
29 dbg << error.message << "Code: " << error.code << "Db: " << error.store; 31 dbg << error.message << "Code: " << error.code << "Db: " << error.store;
30 return dbg; 32 return dbg;
31} 33}
32 34
35QDebug& operator<<(QDebug &dbg, const Sink::Storage::Identifier &id)
36{
37 dbg << id.toDisplayString();
38 return dbg;
39}
40
41QDebug& operator<<(QDebug &dbg, const Sink::Storage::Revision &rev)
42{
43 dbg << rev.toDisplayString();
44 return dbg;
45}
46
47QDebug& operator<<(QDebug &dbg, const Sink::Storage::Key &key)
48{
49 dbg << key.toDisplayString();
50 return dbg;
51}
52
33namespace Sink { 53namespace Sink {
34namespace Storage { 54namespace Storage {
35 55
36static const char *s_internalPrefix = "__internal"; 56static const char *s_internalPrefix = "__internal";
37static const int s_internalPrefixSize = strlen(s_internalPrefix); 57static const int s_internalPrefixSize = strlen(s_internalPrefix);
38static const int s_lengthOfUid = 38; 58static const int s_lengthOfUid = 38;
59// RFC 4122 Section 4.1.2 says 128 bits -> 16 bytes
60//static const int s_lengthOfUid = 16;
39 61
40DbLayout::DbLayout() 62DbLayout::DbLayout()
41{ 63{
@@ -194,6 +216,7 @@ bool DataStore::isInternalKey(const QByteArray &key)
194 return key.startsWith(s_internalPrefix); 216 return key.startsWith(s_internalPrefix);
195} 217}
196 218
219/*
197QByteArray DataStore::assembleKey(const QByteArray &key, qint64 revision) 220QByteArray DataStore::assembleKey(const QByteArray &key, qint64 revision)
198{ 221{
199 Q_ASSERT(revision <= 9223372036854775807); 222 Q_ASSERT(revision <= 9223372036854775807);
@@ -201,15 +224,17 @@ QByteArray DataStore::assembleKey(const QByteArray &key, qint64 revision)
201 return key + QByteArray::number(revision).rightJustified(19, '0', false); 224 return key + QByteArray::number(revision).rightJustified(19, '0', false);
202} 225}
203 226
204QByteArray DataStore::uidFromKey(const QByteArray &key) 227//QByteArray DataStore::uidFromKey(const QByteArray &key)
228Identifier DataStore::uidFromKey(const QByteArray &key)
205{ 229{
206 return key.mid(0, s_lengthOfUid); 230 return Identifier::fromByteArray(key.mid(0, s_lengthOfUid));
207} 231}
208 232
209qint64 DataStore::revisionFromKey(const QByteArray &key) 233qint64 DataStore::revisionFromKey(const QByteArray &key)
210{ 234{
211 return key.mid(s_lengthOfUid + 1).toLongLong(); 235 return key.mid(s_lengthOfUid + 1).toLongLong();
212} 236}
237*/
213 238
214QByteArray DataStore::generateUid() 239QByteArray DataStore::generateUid()
215{ 240{
diff --git a/common/synchronizer.cpp b/common/synchronizer.cpp
index 41ab1e9..f19c08a 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 //const auto uid = Sink::Storage::DataStore::uidFromKey(key);
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.cpp b/common/utils.cpp
index 3c54db4..e98365c 100644
--- a/common/utils.cpp
+++ b/common/utils.cpp
@@ -22,4 +22,5 @@
22QByteArray Sink::createUuid() 22QByteArray Sink::createUuid()
23{ 23{
24 return QUuid::createUuid().toByteArray(); 24 return QUuid::createUuid().toByteArray();
25 //return QUuid::createUuid().toRfc4122();
25} 26}
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 1a964cf..b496fe6 100644
--- a/sinksh/syntax_modules/sink_inspect.cpp
+++ b/sinksh/syntax_modules/sink_inspect.cpp
@@ -90,7 +90,8 @@ bool inspect(const QStringList &args, State &state)
90 90
91 QSet<QByteArray> uids; 91 QSet<QByteArray> uids;
92 db.scan("", [&] (const QByteArray &key, const QByteArray &data) { 92 db.scan("", [&] (const QByteArray &key, const QByteArray &data) {
93 uids.insert(Sink::Storage::DataStore::uidFromKey(key)); 93 //uids.insert(Sink::Storage::DataStore::uidFromKey(key));
94 uids.insert(Sink::Storage::Key::fromInternalByteArray(key).identifier().toDisplayByteArray());
94 return true; 95 return true;
95 }, 96 },
96 [&](const Sink::Storage::DataStore::Error &e) { 97 [&](const Sink::Storage::DataStore::Error &e) {
diff --git a/tests/pipelinetest.cpp b/tests/pipelinetest.cpp
index 45e2fbb..7431deb 100644
--- a/tests/pipelinetest.cpp
+++ b/tests/pipelinetest.cpp
@@ -250,8 +250,9 @@ private slots:
250 // Get uid of written entity 250 // Get uid of written entity
251 auto keys = getKeys(instanceIdentifier(), "event.main"); 251 auto keys = getKeys(instanceIdentifier(), "event.main");
252 QCOMPARE(keys.size(), 1); 252 QCOMPARE(keys.size(), 1);
253 const auto key = keys.first(); 253 auto key = Sink::Storage::Key::fromInternalByteArray(keys.first());
254 const auto uid = Sink::Storage::DataStore::uidFromKey(key); 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);
@@ -373,21 +379,23 @@ private slots:
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 // Key doesn't contain revision and is just the uid
376 QCOMPARE(testProcessor->newUids.at(0), Sink::Storage::DataStore::uidFromKey(testProcessor->newUids.at(0))); 382 const auto uid = Sink::Storage::Key::fromDisplayByteArray(testProcessor->newUids.at(0)).identifier().toDisplayByteArray();
383 QCOMPARE(testProcessor->newUids.at(0), uid);
377 } 384 }
378 pipeline.commit(); 385 pipeline.commit();
379 entityFbb.Clear(); 386 entityFbb.Clear();
380 pipeline.startTransaction(); 387 pipeline.startTransaction();
381 auto keys = getKeys(instanceIdentifier(), "event.main"); 388 auto keys = getKeys(instanceIdentifier(), "event.main");
382 QCOMPARE(keys.size(), 1); 389 QCOMPARE(keys.size(), 1);
383 const auto uid = Sink::Storage::DataStore::uidFromKey(keys.first()); 390 const auto uid = Sink::Storage::Key::fromDisplayByteArray(keys.first()).identifier().toDisplayByteArray();
384 { 391 {
385 auto modifyCommand = modifyEntityCommand(createEvent(entityFbb, "summary2"), uid, 1); 392 auto modifyCommand = modifyEntityCommand(createEvent(entityFbb, "summary2"), uid, 1);
386 pipeline.modifiedEntity(modifyCommand.constData(), modifyCommand.size()); 393 pipeline.modifiedEntity(modifyCommand.constData(), modifyCommand.size());
387 QCOMPARE(testProcessor->modifiedUids.size(), 1); 394 QCOMPARE(testProcessor->modifiedUids.size(), 1);
388 QCOMPARE(testProcessor->modifiedRevisions.size(), 1); 395 QCOMPARE(testProcessor->modifiedRevisions.size(), 1);
389 // Key doesn't contain revision and is just the uid 396 // Key doesn't contain revision and is just the uid
390 QCOMPARE(testProcessor->modifiedUids.at(0), Sink::Storage::DataStore::uidFromKey(testProcessor->modifiedUids.at(0))); 397 const auto uid2 = Sink::Storage::Key::fromDisplayByteArray(testProcessor->modifiedUids.at(0)).identifier().toDisplayByteArray();
398 QCOMPARE(testProcessor->modifiedUids.at(0), uid2);
391 } 399 }
392 pipeline.commit(); 400 pipeline.commit();
393 entityFbb.Clear(); 401 entityFbb.Clear();
@@ -399,7 +407,8 @@ private slots:
399 QCOMPARE(testProcessor->deletedUids.size(), 1); 407 QCOMPARE(testProcessor->deletedUids.size(), 1);
400 QCOMPARE(testProcessor->deletedSummaries.size(), 1); 408 QCOMPARE(testProcessor->deletedSummaries.size(), 1);
401 // Key doesn't contain revision and is just the uid 409 // Key doesn't contain revision and is just the uid
402 QCOMPARE(testProcessor->deletedUids.at(0), Sink::Storage::DataStore::uidFromKey(testProcessor->deletedUids.at(0))); 410 const auto uid2 = Sink::Storage::Key::fromDisplayByteArray(testProcessor->modifiedUids.at(0)).identifier().toDisplayByteArray();
411 QCOMPARE(testProcessor->deletedUids.at(0), uid2);
403 QCOMPARE(testProcessor->deletedSummaries.at(0), QByteArray("summary2")); 412 QCOMPARE(testProcessor->deletedSummaries.at(0), QByteArray("summary2"));
404 } 413 }
405 } 414 }
diff --git a/tests/storagetest.cpp b/tests/storagetest.cpp
index bca91b1..40492f0 100644
--- a/tests/storagetest.cpp
+++ b/tests/storagetest.cpp
@@ -456,8 +456,10 @@ private slots:
456 auto db = transaction.openDatabase("test", nullptr, false); 456 auto db = transaction.openDatabase("test", nullptr, false);
457 const auto uid = "{c5d06a9f-1534-4c52-b8ea-415db68bdadf}"; 457 const auto uid = "{c5d06a9f-1534-4c52-b8ea-415db68bdadf}";
458 //Ensure we can sort 1 and 10 properly (by default string comparison 10 comes before 6) 458 //Ensure we can sort 1 and 10 properly (by default string comparison 10 comes before 6)
459 db.write(Sink::Storage::DataStore::assembleKey(uid, 6), "value1"); 459 const auto key1 = Sink::Storage::Key(Sink::Storage::Identifier::fromDisplayByteArray(uid), 6);
460 db.write(Sink::Storage::DataStore::assembleKey(uid, 10), "value2"); 460 db.write(key1.toInternalByteArray(), "value1");
461 const auto key2 = Sink::Storage::Key(Sink::Storage::Identifier::fromDisplayByteArray(uid), 10);
462 db.write(key2.toInternalByteArray(), "value2");
461 db.findLatest(uid, [&](const QByteArray &key, const QByteArray &value) { result = value; }); 463 db.findLatest(uid, [&](const QByteArray &key, const QByteArray &value) { result = value; });
462 QCOMPARE(result, QByteArray("value2")); 464 QCOMPARE(result, QByteArray("value2"));
463 } 465 }
@@ -689,7 +691,7 @@ private slots:
689 Sink::Storage::DataStore::clearEnv(); 691 Sink::Storage::DataStore::clearEnv();
690 692
691 //Try to read-only dynamic opening of the db. 693 //Try to read-only dynamic opening of the db.
692 //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) 694 //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)
693 { 695 {
694 // Trick the db into not loading all dbs by passing in a bogus layout. 696 // Trick the db into not loading all dbs by passing in a bogus layout.
695 Sink::Storage::DataStore store(testDataPath, {dbName, {{"bogus", 0}}}, Sink::Storage::DataStore::ReadOnly); 697 Sink::Storage::DataStore store(testDataPath, {dbName, {{"bogus", 0}}}, Sink::Storage::DataStore::ReadOnly);
@@ -707,7 +709,7 @@ private slots:
707 709
708 Sink::Storage::DataStore::clearEnv(); 710 Sink::Storage::DataStore::clearEnv();
709 //Try to read-write dynamic opening of the db. 711 //Try to read-write dynamic opening of the db.
710 //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) 712 //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)
711 { 713 {
712 // Trick the db into not loading all dbs by passing in a bogus layout. 714 // Trick the db into not loading all dbs by passing in a bogus layout.
713 Sink::Storage::DataStore store(testDataPath, {dbName, {{"bogus", 0}}}, Sink::Storage::DataStore::ReadWrite); 715 Sink::Storage::DataStore store(testDataPath, {dbName, {{"bogus", 0}}}, Sink::Storage::DataStore::ReadWrite);