From 50f737b8549fb1b380c753d36be3fafe0ec4a768 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Fri, 11 Sep 2015 09:31:24 +0200 Subject: Storage: substring search and findLatest --- common/storage.h | 11 +++++++++-- common/storage_common.cpp | 11 +++++++++++ common/storage_lmdb.cpp | 47 ++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 58 insertions(+), 11 deletions(-) (limited to 'common') diff --git a/common/storage.h b/common/storage.h index d186b2e..98b12ed 100644 --- a/common/storage.h +++ b/common/storage.h @@ -76,9 +76,13 @@ public: * * @return The number of values retrieved. */ - int scan(const QByteArray &k, + int scan(const QByteArray &key, const std::function &resultHandler, - const std::function &errorHandler = std::function()) const; + const std::function &errorHandler = std::function(), bool findSubstringKeys = false) const; + + void findLatest(const QByteArray &uid, + const std::function &resultHandler, + const std::function &errorHandler = std::function()) const; NamedDatabase(NamedDatabase&& other) : d(other.d) { @@ -170,6 +174,9 @@ public: static bool isInternalKey(void *key, int keySize); static bool isInternalKey(const QByteArray &key); + static QByteArray assembleKey(const QByteArray &key, qint64 revision); + static QByteArray uidFromKey(const QByteArray &key); + private: std::function mErrorHandler; diff --git a/common/storage_common.cpp b/common/storage_common.cpp index f22150a..28fb4c2 100644 --- a/common/storage_common.cpp +++ b/common/storage_common.cpp @@ -93,4 +93,15 @@ bool Storage::isInternalKey(const QByteArray &key) return key.startsWith(s_internalPrefix); } +QByteArray Storage::assembleKey(const QByteArray &key, qint64 revision) +{ + Q_ASSERT(key.size() == 38); + return key + QByteArray::number(revision); +} + +QByteArray Storage::uidFromKey(const QByteArray &key) +{ + return key.mid(0, 38); +} + } // namespace Akonadi2 diff --git a/common/storage_lmdb.cpp b/common/storage_lmdb.cpp index a048a71..3073d37 100644 --- a/common/storage_lmdb.cpp +++ b/common/storage_lmdb.cpp @@ -169,7 +169,8 @@ void Storage::NamedDatabase::remove(const QByteArray &k, int Storage::NamedDatabase::scan(const QByteArray &k, const std::function &resultHandler, - const std::function &errorHandler) const + const std::function &errorHandler, + bool findSubstringKeys) const { if (!d || !d->transaction) { //Not an error. We rely on this to read nothing from non-existing databases. @@ -193,14 +194,25 @@ int Storage::NamedDatabase::scan(const QByteArray &k, int numberOfRetrievedValues = 0; - if (k.isEmpty() || d->allowDuplicates) { - if ((rc = mdb_cursor_get(cursor, &key, &data, d->allowDuplicates ? MDB_SET : MDB_FIRST)) == 0) { - numberOfRetrievedValues++; - if (resultHandler(QByteArray::fromRawData((char*)key.mv_data, key.mv_size), QByteArray::fromRawData((char*)data.mv_data, data.mv_size))) { - while ((rc = mdb_cursor_get(cursor, &key, &data, d->allowDuplicates ? MDB_NEXT_DUP : MDB_NEXT)) == 0) { - numberOfRetrievedValues++; - if (!resultHandler(QByteArray::fromRawData((char*)key.mv_data, key.mv_size), QByteArray::fromRawData((char*)data.mv_data, data.mv_size))) { - break; + if (k.isEmpty() || d->allowDuplicates || findSubstringKeys) { + MDB_cursor_op op = d->allowDuplicates ? MDB_SET : MDB_FIRST; + if (findSubstringKeys) { + op = MDB_SET_RANGE; + } + if ((rc = mdb_cursor_get(cursor, &key, &data, op)) == 0) { + //The first lookup will find a key that is equal or greather than our key + if (QByteArray::fromRawData((char*)key.mv_data, key.mv_size).startsWith(k)) { + numberOfRetrievedValues++; + if (resultHandler(QByteArray::fromRawData((char*)key.mv_data, key.mv_size), QByteArray::fromRawData((char*)data.mv_data, data.mv_size))) { + MDB_cursor_op nextOp = d->allowDuplicates ? MDB_NEXT_DUP : MDB_NEXT; + while ((rc = mdb_cursor_get(cursor, &key, &data, nextOp)) == 0) { + //Every consequent lookup simply iterates through the list + if (QByteArray::fromRawData((char*)key.mv_data, key.mv_size).startsWith(k)) { + numberOfRetrievedValues++; + if (!resultHandler(QByteArray::fromRawData((char*)key.mv_data, key.mv_size), QByteArray::fromRawData((char*)data.mv_data, data.mv_size))) { + break; + } + } } } } @@ -226,6 +238,23 @@ int Storage::NamedDatabase::scan(const QByteArray &k, return numberOfRetrievedValues; } +void Storage::NamedDatabase::findLatest(const QByteArray &uid, + const std::function &resultHandler, + const std::function &errorHandler) const +{ + QByteArray latestKey; + scan(uid, [&](const QByteArray &key, const QByteArray &value) -> bool { + latestKey = key; + return true; + }, + errorHandler, true); + + scan(latestKey, [=](const QByteArray &key, const QByteArray &value) -> bool { + resultHandler(key, value); + return false; + }, + errorHandler); +} -- cgit v1.2.3