diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2014-12-10 21:54:04 +0100 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2014-12-10 21:54:04 +0100 |
commit | 95801103c1fc773b074eea1b2d03820099ac09a6 (patch) | |
tree | b55445cddc451b68ff171fceb729e4cc602b2531 | |
parent | 4911df72dbc202dfcc4c64bb0ba311d7513707ae (diff) | |
download | sink-95801103c1fc773b074eea1b2d03820099ac09a6.tar.gz sink-95801103c1fc773b074eea1b2d03820099ac09a6.zip |
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.
-rw-r--r-- | common/storage.h | 4 | ||||
-rw-r--r-- | common/storage_common.cpp | 5 | ||||
-rw-r--r-- | common/storage_lmdb.cpp | 14 | ||||
-rw-r--r-- | 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: | |||
34 | void read(const std::string &sKey, | 34 | void read(const std::string &sKey, |
35 | const std::function<bool(void *ptr, int size)> & resultHandler, | 35 | const std::function<bool(void *ptr, int size)> & resultHandler, |
36 | const std::function<void(const Storage::Error &error)> &errorHandler); | 36 | const std::function<void(const Storage::Error &error)> &errorHandler); |
37 | void scan(const std::string &sKey, const std::function<bool(void *keyPtr, int keySize, void *valuePtr, int valueSize)> &resultHandler); | ||
38 | void scan(const std::string &sKey, | ||
39 | const std::function<bool(void *keyPtr, int keySize, void *valuePtr, int valueSize)> & resultHandler, | ||
40 | const std::function<void(const Storage::Error &error)> &errorHandler); | ||
37 | 41 | ||
38 | qint64 diskUsage() const; | 42 | qint64 diskUsage() const; |
39 | void removeFromDisk() const; | 43 | 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<bool(void *ptr, | |||
19 | read(sKey, resultHandler, &errorHandler); | 19 | read(sKey, resultHandler, &errorHandler); |
20 | } | 20 | } |
21 | 21 | ||
22 | void Storage::scan(const std::string &sKey, const std::function<bool(void *keyPtr, int keySize, void *valuePtr, int valueSize)> &resultHandler) | ||
23 | { | ||
24 | scan(sKey, resultHandler, &errorHandler); | ||
25 | } | ||
26 | |||
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 | |||
@@ -211,6 +211,15 @@ void Storage::read(const std::string &sKey, | |||
211 | const std::function<bool(void *ptr, int size)> &resultHandler, | 211 | const std::function<bool(void *ptr, int size)> &resultHandler, |
212 | const std::function<void(const Storage::Error &error)> &errorHandler) | 212 | const std::function<void(const Storage::Error &error)> &errorHandler) |
213 | { | 213 | { |
214 | scan(sKey, [resultHandler](void *keyPtr, int keySize, void *valuePtr, int valueSize) { | ||
215 | return resultHandler(valuePtr, valueSize); | ||
216 | }, errorHandler); | ||
217 | } | ||
218 | |||
219 | void Storage::scan(const std::string &sKey, | ||
220 | const std::function<bool(void *keyPtr, int keySize, void *valuePtr, int valueSize)> &resultHandler, | ||
221 | const std::function<void(const Storage::Error &error)> &errorHandler) | ||
222 | { | ||
214 | if (!d->env) { | 223 | if (!d->env) { |
215 | Error error(d->name.toStdString(), -1, "Not open"); | 224 | Error error(d->name.toStdString(), -1, "Not open"); |
216 | errorHandler(error); | 225 | errorHandler(error); |
@@ -243,10 +252,9 @@ void Storage::read(const std::string &sKey, | |||
243 | } | 252 | } |
244 | 253 | ||
245 | if (sKey.empty()) { | 254 | if (sKey.empty()) { |
246 | std::cout << "Iterating over all values of store!" << std::endl; | ||
247 | rc = mdb_cursor_get(cursor, &key, &data, MDB_FIRST); | 255 | rc = mdb_cursor_get(cursor, &key, &data, MDB_FIRST); |
248 | while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { | 256 | while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { |
249 | if (!resultHandler(key.mv_data, data.mv_size)) { | 257 | if (!resultHandler(key.mv_data, key.mv_size, data.mv_data, data.mv_size)) { |
250 | break; | 258 | break; |
251 | } | 259 | } |
252 | } | 260 | } |
@@ -257,7 +265,7 @@ void Storage::read(const std::string &sKey, | |||
257 | } | 265 | } |
258 | } else { | 266 | } else { |
259 | if ((rc = mdb_cursor_get(cursor, &key, &data, MDB_SET)) == 0) { | 267 | if ((rc = mdb_cursor_get(cursor, &key, &data, MDB_SET)) == 0) { |
260 | resultHandler(data.mv_data, data.mv_size); | 268 | resultHandler(key.mv_data, key.mv_size, data.mv_data, data.mv_size); |
261 | } else { | 269 | } else { |
262 | std::cout << "couldn't find value " << sKey << " " << std::endl; | 270 | std::cout << "couldn't find value " << sKey << " " << std::endl; |
263 | } | 271 | } |
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: | |||
82 | storage.removeFromDisk(); | 82 | storage.removeFromDisk(); |
83 | } | 83 | } |
84 | 84 | ||
85 | void testScan() | ||
86 | { | ||
87 | const int count = 100; | ||
88 | populate(count); | ||
89 | |||
90 | //ensure we can scan for values | ||
91 | { | ||
92 | int hit = 0; | ||
93 | Storage store(testDataPath, dbName); | ||
94 | store.scan("", [&](void *keyValue, int keySize, void *dataValue, int dataSize) -> bool { | ||
95 | if (std::string(static_cast<char*>(keyValue), keySize) == "key50") { | ||
96 | hit++; | ||
97 | } | ||
98 | return true; | ||
99 | }); | ||
100 | QCOMPARE(hit, 1); | ||
101 | } | ||
102 | |||
103 | //ensure we can read a single value | ||
104 | { | ||
105 | int hit = 0; | ||
106 | bool foundInvalidValue = false; | ||
107 | Storage store(testDataPath, dbName); | ||
108 | store.scan("key50", [&](void *keyValue, int keySize, void *dataValue, int dataSize) -> bool { | ||
109 | if (std::string(static_cast<char*>(keyValue), keySize) != "key50") { | ||
110 | foundInvalidValue = true; | ||
111 | } | ||
112 | hit++; | ||
113 | return true; | ||
114 | }); | ||
115 | QVERIFY(!foundInvalidValue); | ||
116 | QCOMPARE(hit, 1); | ||
117 | } | ||
118 | |||
119 | Storage storage(testDataPath, dbName); | ||
120 | storage.removeFromDisk(); | ||
121 | } | ||
122 | |||
85 | void testConcurrentRead() | 123 | void testConcurrentRead() |
86 | { | 124 | { |
87 | const int count = 10000; | 125 | const int count = 10000; |