diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/changereplay.cpp | 4 | ||||
-rw-r--r-- | common/storage.h | 156 | ||||
-rw-r--r-- | common/storage/entitystore.cpp | 66 | ||||
-rw-r--r-- | common/storage_common.cpp | 29 | ||||
-rw-r--r-- | common/synchronizer.cpp | 3 | ||||
-rw-r--r-- | common/typeindex.cpp | 9 | ||||
-rw-r--r-- | common/utils.cpp | 1 | ||||
-rw-r--r-- | common/utils.h | 13 |
8 files changed, 245 insertions, 36 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 | ||
43 | class Identifier | ||
44 | { | ||
45 | public: | ||
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 | |||
79 | private: | ||
80 | explicit Identifier(const QUuid &uid) : uid(uid) {} | ||
81 | QUuid uid; | ||
82 | }; | ||
83 | |||
84 | class Revision | ||
85 | { | ||
86 | public: | ||
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 | |||
125 | private: | ||
126 | qint64 rev; | ||
127 | }; | ||
128 | |||
129 | class Key | ||
130 | { | ||
131 | public: | ||
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 | |||
183 | private: | ||
184 | Identifier id; | ||
185 | Revision rev; | ||
186 | }; | ||
187 | |||
41 | class SINK_EXPORT DataStore | 188 | class SINK_EXPORT DataStore |
42 | { | 189 | { |
43 | public: | 190 | public: |
@@ -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 | ||
262 | SINK_EXPORT QDebug& operator<<(QDebug &dbg, const Sink::Storage::DataStore::Error &error); | 409 | SINK_EXPORT QDebug& operator<<(QDebug &dbg, const Sink::Storage::DataStore::Error &error); |
410 | SINK_EXPORT QDebug& operator<<(QDebug &dbg, const Sink::Storage::Identifier &); | ||
411 | SINK_EXPORT QDebug& operator<<(QDebug &dbg, const Sink::Storage::Revision &); | ||
412 | SINK_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 | ||
482 | void EntityStore::readLatest(const QByteArray &type, const QByteArray &uid, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback) | 488 | void 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 | ||
494 | void EntityStore::readLatest(const QByteArray &type, const QByteArray &uid, const std::function<void(const ApplicationDomainType &)> callback) | 508 | void 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 | ||
519 | void EntityStore::readEntity(const QByteArray &type, const QByteArray &key, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback) | 533 | // TODO: check every usage |
534 | void 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 | ||
592 | void EntityStore::readPrevious(const QByteArray &type, const QByteArray &uid, qint64 revision, const std::function<void(const ApplicationDomainType &)> callback) | 613 | void 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 | ||
613 | bool EntityStore::contains(const QByteArray &type, const QByteArray &uid) | 634 | bool 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 | ||
618 | bool EntityStore::exists(const QByteArray &type, const QByteArray &uid) | 645 | bool 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 | |||
27 | QDebug& operator<<(QDebug &dbg, const Sink::Storage::DataStore::Error &error) | 29 | QDebug& 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 | ||
35 | QDebug& operator<<(QDebug &dbg, const Sink::Storage::Identifier &id) | ||
36 | { | ||
37 | dbg << id.toDisplayString(); | ||
38 | return dbg; | ||
39 | } | ||
40 | |||
41 | QDebug& operator<<(QDebug &dbg, const Sink::Storage::Revision &rev) | ||
42 | { | ||
43 | dbg << rev.toDisplayString(); | ||
44 | return dbg; | ||
45 | } | ||
46 | |||
47 | QDebug& operator<<(QDebug &dbg, const Sink::Storage::Key &key) | ||
48 | { | ||
49 | dbg << key.toDisplayString(); | ||
50 | return dbg; | ||
51 | } | ||
52 | |||
33 | namespace Sink { | 53 | namespace Sink { |
34 | namespace Storage { | 54 | namespace Storage { |
35 | 55 | ||
36 | static const char *s_internalPrefix = "__internal"; | 56 | static const char *s_internalPrefix = "__internal"; |
37 | static const int s_internalPrefixSize = strlen(s_internalPrefix); | 57 | static const int s_internalPrefixSize = strlen(s_internalPrefix); |
38 | static const int s_lengthOfUid = 38; | 58 | static 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 | ||
40 | DbLayout::DbLayout() | 62 | DbLayout::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 | /* | ||
197 | QByteArray DataStore::assembleKey(const QByteArray &key, qint64 revision) | 220 | QByteArray 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 | ||
204 | QByteArray DataStore::uidFromKey(const QByteArray &key) | 227 | //QByteArray DataStore::uidFromKey(const QByteArray &key) |
228 | Identifier 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 | ||
209 | qint64 DataStore::revisionFromKey(const QByteArray &key) | 233 | qint64 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 | ||
214 | QByteArray DataStore::generateUid() | 239 | QByteArray 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 | |||
30 | using namespace Sink; | 28 | using namespace Sink; |
31 | 29 | ||
32 | static QByteArray getByteArray(const QVariant &value) | 30 | static 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 | ||
56 | template <typename T> | ||
57 | static 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 | |||
63 | static QByteArray toSortableByteArrayImpl(const QDateTime &date) | 54 | static 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 @@ | |||
22 | QByteArray Sink::createUuid() | 22 | QByteArray 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 | |||
23 | namespace Sink { | 25 | namespace Sink { |
24 | QByteArray createUuid(); | 26 | |
27 | QByteArray createUuid(); | ||
28 | |||
29 | template <typename T> | ||
30 | static 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 | ||