summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2014-12-10 21:54:04 +0100
committerChristian Mollekopf <chrigi_1@fastmail.fm>2014-12-10 21:54:04 +0100
commit95801103c1fc773b074eea1b2d03820099ac09a6 (patch)
treeb55445cddc451b68ff171fceb729e4cc602b2531
parent4911df72dbc202dfcc4c64bb0ba311d7513707ae (diff)
downloadsink-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.h4
-rw-r--r--common/storage_common.cpp5
-rw-r--r--common/storage_lmdb.cpp14
-rw-r--r--tests/storagetest.cpp38
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
22void 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
219void 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;