summaryrefslogtreecommitdiffstats
path: root/common/storage_lmdb.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/storage_lmdb.cpp')
-rw-r--r--common/storage_lmdb.cpp47
1 files changed, 38 insertions, 9 deletions
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,
169 169
170int Storage::NamedDatabase::scan(const QByteArray &k, 170int Storage::NamedDatabase::scan(const QByteArray &k,
171 const std::function<bool(const QByteArray &key, const QByteArray &value)> &resultHandler, 171 const std::function<bool(const QByteArray &key, const QByteArray &value)> &resultHandler,
172 const std::function<void(const Storage::Error &error)> &errorHandler) const 172 const std::function<void(const Storage::Error &error)> &errorHandler,
173 bool findSubstringKeys) const
173{ 174{
174 if (!d || !d->transaction) { 175 if (!d || !d->transaction) {
175 //Not an error. We rely on this to read nothing from non-existing databases. 176 //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,
193 194
194 int numberOfRetrievedValues = 0; 195 int numberOfRetrievedValues = 0;
195 196
196 if (k.isEmpty() || d->allowDuplicates) { 197 if (k.isEmpty() || d->allowDuplicates || findSubstringKeys) {
197 if ((rc = mdb_cursor_get(cursor, &key, &data, d->allowDuplicates ? MDB_SET : MDB_FIRST)) == 0) { 198 MDB_cursor_op op = d->allowDuplicates ? MDB_SET : MDB_FIRST;
198 numberOfRetrievedValues++; 199 if (findSubstringKeys) {
199 if (resultHandler(QByteArray::fromRawData((char*)key.mv_data, key.mv_size), QByteArray::fromRawData((char*)data.mv_data, data.mv_size))) { 200 op = MDB_SET_RANGE;
200 while ((rc = mdb_cursor_get(cursor, &key, &data, d->allowDuplicates ? MDB_NEXT_DUP : MDB_NEXT)) == 0) { 201 }
201 numberOfRetrievedValues++; 202 if ((rc = mdb_cursor_get(cursor, &key, &data, op)) == 0) {
202 if (!resultHandler(QByteArray::fromRawData((char*)key.mv_data, key.mv_size), QByteArray::fromRawData((char*)data.mv_data, data.mv_size))) { 203 //The first lookup will find a key that is equal or greather than our key
203 break; 204 if (QByteArray::fromRawData((char*)key.mv_data, key.mv_size).startsWith(k)) {
205 numberOfRetrievedValues++;
206 if (resultHandler(QByteArray::fromRawData((char*)key.mv_data, key.mv_size), QByteArray::fromRawData((char*)data.mv_data, data.mv_size))) {
207 MDB_cursor_op nextOp = d->allowDuplicates ? MDB_NEXT_DUP : MDB_NEXT;
208 while ((rc = mdb_cursor_get(cursor, &key, &data, nextOp)) == 0) {
209 //Every consequent lookup simply iterates through the list
210 if (QByteArray::fromRawData((char*)key.mv_data, key.mv_size).startsWith(k)) {
211 numberOfRetrievedValues++;
212 if (!resultHandler(QByteArray::fromRawData((char*)key.mv_data, key.mv_size), QByteArray::fromRawData((char*)data.mv_data, data.mv_size))) {
213 break;
214 }
215 }
204 } 216 }
205 } 217 }
206 } 218 }
@@ -226,6 +238,23 @@ int Storage::NamedDatabase::scan(const QByteArray &k,
226 238
227 return numberOfRetrievedValues; 239 return numberOfRetrievedValues;
228} 240}
241void Storage::NamedDatabase::findLatest(const QByteArray &uid,
242 const std::function<void(const QByteArray &key, const QByteArray &value)> &resultHandler,
243 const std::function<void(const Storage::Error &error)> &errorHandler) const
244{
245 QByteArray latestKey;
246 scan(uid, [&](const QByteArray &key, const QByteArray &value) -> bool {
247 latestKey = key;
248 return true;
249 },
250 errorHandler, true);
251
252 scan(latestKey, [=](const QByteArray &key, const QByteArray &value) -> bool {
253 resultHandler(key, value);
254 return false;
255 },
256 errorHandler);
257}
229 258
230 259
231 260