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.cpp71
1 files changed, 59 insertions, 12 deletions
diff --git a/common/storage_lmdb.cpp b/common/storage_lmdb.cpp
index 1516e69..a247e38 100644
--- a/common/storage_lmdb.cpp
+++ b/common/storage_lmdb.cpp
@@ -253,22 +253,69 @@ int Storage::NamedDatabase::scan(const QByteArray &k,
253 253
254 return numberOfRetrievedValues; 254 return numberOfRetrievedValues;
255} 255}
256void Storage::NamedDatabase::findLatest(const QByteArray &uid, 256
257void Storage::NamedDatabase::findLatest(const QByteArray &k,
257 const std::function<void(const QByteArray &key, const QByteArray &value)> &resultHandler, 258 const std::function<void(const QByteArray &key, const QByteArray &value)> &resultHandler,
258 const std::function<void(const Storage::Error &error)> &errorHandler) const 259 const std::function<void(const Storage::Error &error)> &errorHandler) const
259{ 260{
260 QByteArray latestKey; 261 if (!d || !d->transaction) {
261 scan(uid, [&](const QByteArray &key, const QByteArray &value) -> bool { 262 //Not an error. We rely on this to read nothing from non-existing databases.
262 latestKey = key; 263 return;
263 return true; 264 }
264 },
265 errorHandler, true);
266 265
267 scan(latestKey, [=](const QByteArray &key, const QByteArray &value) -> bool { 266 int rc;
268 resultHandler(key, value); 267 MDB_val key;
269 return false; 268 MDB_val data;
270 }, 269 MDB_cursor *cursor;
271 errorHandler); 270
271 key.mv_data = (void*)k.constData();
272 key.mv_size = k.size();
273
274 rc = mdb_cursor_open(d->transaction, d->dbi, &cursor);
275 if (rc) {
276 Error error(d->name.toLatin1(), getErrorCode(rc), QByteArray("Error during mdb_cursor open: ") + QByteArray(mdb_strerror(rc)));
277 errorHandler ? errorHandler(error) : d->defaultErrorHandler(error);
278 return;
279 }
280
281 MDB_cursor_op op = MDB_SET_RANGE;
282 if ((rc = mdb_cursor_get(cursor, &key, &data, op)) == 0) {
283 //The first lookup will find a key that is equal or greather than our key
284 if (QByteArray::fromRawData((char*)key.mv_data, key.mv_size).startsWith(k)) {
285 bool advanced = false;
286 while (QByteArray::fromRawData((char*)key.mv_data, key.mv_size).startsWith(k)) {
287 advanced = true;
288 MDB_cursor_op nextOp = MDB_NEXT;
289 rc = mdb_cursor_get(cursor, &key, &data, nextOp);
290 if (rc) {
291 break;
292 }
293 }
294 if (advanced) {
295 MDB_cursor_op prefOp = MDB_PREV;
296 //We read past the end above, just take the last value
297 if (rc == MDB_NOTFOUND) {
298 prefOp = MDB_LAST;
299 }
300 rc = mdb_cursor_get(cursor, &key, &data, prefOp);
301 resultHandler(QByteArray::fromRawData((char*)key.mv_data, key.mv_size), QByteArray::fromRawData((char*)data.mv_data, data.mv_size));
302 }
303 }
304 }
305
306 //We never find the last value
307 if (rc == MDB_NOTFOUND) {
308 rc = 0;
309 }
310
311 mdb_cursor_close(cursor);
312
313 if (rc) {
314 Error error(d->name.toLatin1(), getErrorCode(rc), QByteArray("Key: ") + k + " : " + QByteArray(mdb_strerror(rc)));
315 errorHandler ? errorHandler(error) : d->defaultErrorHandler(error);
316 }
317
318 return;
272} 319}
273 320
274 321