From 95801103c1fc773b074eea1b2d03820099ac09a6 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Wed, 10 Dec 2014 21:54:04 +0100 Subject: Storage: implemented scan This can replace all our read calls. Note that we need a different API for databases where the value needs to be loaded first, so we can do a key scan before loading values. With this we can do key + value scans in one though. --- common/storage.h | 4 ++++ common/storage_common.cpp | 5 +++++ common/storage_lmdb.cpp | 14 +++++++++++--- tests/storagetest.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 3 deletions(-) diff --git a/common/storage.h b/common/storage.h index e5e592c..55688d4 100644 --- a/common/storage.h +++ b/common/storage.h @@ -34,6 +34,10 @@ public: void read(const std::string &sKey, const std::function & resultHandler, const std::function &errorHandler); + void scan(const std::string &sKey, const std::function &resultHandler); + void scan(const std::string &sKey, + const std::function & resultHandler, + const std::function &errorHandler); qint64 diskUsage() const; void removeFromDisk() const; diff --git a/common/storage_common.cpp b/common/storage_common.cpp index bc1acc4..246611c 100644 --- a/common/storage_common.cpp +++ b/common/storage_common.cpp @@ -19,3 +19,8 @@ void Storage::read(const std::string &sKey, const std::function &resultHandler) +{ + scan(sKey, resultHandler, &errorHandler); +} + diff --git a/common/storage_lmdb.cpp b/common/storage_lmdb.cpp index b7102aa..95af3a2 100644 --- a/common/storage_lmdb.cpp +++ b/common/storage_lmdb.cpp @@ -210,6 +210,15 @@ void Storage::read(const std::string &sKey, void Storage::read(const std::string &sKey, const std::function &resultHandler, const std::function &errorHandler) +{ + scan(sKey, [resultHandler](void *keyPtr, int keySize, void *valuePtr, int valueSize) { + return resultHandler(valuePtr, valueSize); + }, errorHandler); +} + +void Storage::scan(const std::string &sKey, + const std::function &resultHandler, + const std::function &errorHandler) { if (!d->env) { Error error(d->name.toStdString(), -1, "Not open"); @@ -243,10 +252,9 @@ void Storage::read(const std::string &sKey, } if (sKey.empty()) { - std::cout << "Iterating over all values of store!" << std::endl; rc = mdb_cursor_get(cursor, &key, &data, MDB_FIRST); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { - if (!resultHandler(key.mv_data, data.mv_size)) { + if (!resultHandler(key.mv_data, key.mv_size, data.mv_data, data.mv_size)) { break; } } @@ -257,7 +265,7 @@ void Storage::read(const std::string &sKey, } } else { if ((rc = mdb_cursor_get(cursor, &key, &data, MDB_SET)) == 0) { - resultHandler(data.mv_data, data.mv_size); + resultHandler(key.mv_data, key.mv_size, data.mv_data, data.mv_size); } else { std::cout << "couldn't find value " << sKey << " " << std::endl; } diff --git a/tests/storagetest.cpp b/tests/storagetest.cpp index 1974355..b3313c0 100644 --- a/tests/storagetest.cpp +++ b/tests/storagetest.cpp @@ -82,6 +82,44 @@ private Q_SLOTS: storage.removeFromDisk(); } + void testScan() + { + const int count = 100; + populate(count); + + //ensure we can scan for values + { + int hit = 0; + Storage store(testDataPath, dbName); + store.scan("", [&](void *keyValue, int keySize, void *dataValue, int dataSize) -> bool { + if (std::string(static_cast(keyValue), keySize) == "key50") { + hit++; + } + return true; + }); + QCOMPARE(hit, 1); + } + + //ensure we can read a single value + { + int hit = 0; + bool foundInvalidValue = false; + Storage store(testDataPath, dbName); + store.scan("key50", [&](void *keyValue, int keySize, void *dataValue, int dataSize) -> bool { + if (std::string(static_cast(keyValue), keySize) != "key50") { + foundInvalidValue = true; + } + hit++; + return true; + }); + QVERIFY(!foundInvalidValue); + QCOMPARE(hit, 1); + } + + Storage storage(testDataPath, dbName); + storage.removeFromDisk(); + } + void testConcurrentRead() { const int count = 10000; -- cgit v1.2.3