diff options
author | Rémi Nicole <nicole@kolabsystems.com> | 2018-05-24 12:10:24 +0200 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2018-05-24 12:17:15 +0200 |
commit | 0456cef80e909e545897ac9eb107fd832d4dfde8 (patch) | |
tree | 5878f19df4089c166637380850a6bc101fa20a82 /common/storage_lmdb.cpp | |
parent | 7e910179f1349d1245211933d95cda2dc13cd617 (diff) | |
download | sink-0456cef80e909e545897ac9eb107fd832d4dfde8.tar.gz sink-0456cef80e909e545897ac9eb107fd832d4dfde8.zip |
Add findAllInRange function in the storage layer
Summary:
In preparation of the support for ranged queries.
Notes:
Since they are pretty similar, it could be nice to refactor `scan` and `findAllInRange` to use common 3rd function
Test Plan: This is tested in storagetest.cpp
Reviewers: cmollekopf
Tags: #sink
Differential Revision: https://phabricator.kde.org/D13066
Diffstat (limited to 'common/storage_lmdb.cpp')
-rw-r--r-- | common/storage_lmdb.cpp | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/common/storage_lmdb.cpp b/common/storage_lmdb.cpp index bf631a8..4ac5724 100644 --- a/common/storage_lmdb.cpp +++ b/common/storage_lmdb.cpp | |||
@@ -551,6 +551,60 @@ void DataStore::NamedDatabase::findLatest(const QByteArray &k, const std::functi | |||
551 | return; | 551 | return; |
552 | } | 552 | } |
553 | 553 | ||
554 | int DataStore::NamedDatabase::findAllInRange(const QByteArray &lowerBound, const QByteArray &upperBound, | ||
555 | const std::function<void(const QByteArray &key, const QByteArray &value)> &resultHandler, | ||
556 | const std::function<void(const DataStore::Error &error)> &errorHandler) const | ||
557 | { | ||
558 | if (!d || !d->transaction) { | ||
559 | // Not an error. We rely on this to read nothing from non-existing databases. | ||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | MDB_cursor *cursor; | ||
564 | if (int rc = mdb_cursor_open(d->transaction, d->dbi, &cursor)) { | ||
565 | // Invalid arguments can mean that the transaction doesn't contain the db dbi | ||
566 | Error error(d->name.toLatin1() + d->db, getErrorCode(rc), | ||
567 | QByteArray("Error during mdb_cursor_open: ") + QByteArray(mdb_strerror(rc)) + | ||
568 | ". Lower bound: " + lowerBound + " Upper bound: " + upperBound); | ||
569 | errorHandler ? errorHandler(error) : d->defaultErrorHandler(error); | ||
570 | return 0; | ||
571 | } | ||
572 | |||
573 | int numberOfRetrievedValues = 0; | ||
574 | |||
575 | MDB_val firstKey = { .mv_size = (size_t)lowerBound.size(), .mv_data = (void *)lowerBound.constData() }; | ||
576 | MDB_val idealLastKey = { .mv_size = (size_t)upperBound.size(), .mv_data = (void *)upperBound.constData() }; | ||
577 | MDB_val lastKey = idealLastKey; | ||
578 | MDB_val currentKey; | ||
579 | MDB_val data; | ||
580 | |||
581 | // Find the first key in the range | ||
582 | int rc = mdb_cursor_get(cursor, &firstKey, &data, MDB_SET_RANGE); | ||
583 | |||
584 | if (rc != MDB_SUCCESS) { | ||
585 | // Nothing is greater or equal than the lower bound, meaning no result | ||
586 | mdb_cursor_close(cursor); | ||
587 | return 0; | ||
588 | } | ||
589 | |||
590 | currentKey = firstKey; | ||
591 | |||
592 | // If already bigger than the upper bound | ||
593 | if (mdb_cmp(d->transaction, d->dbi, ¤tKey, &idealLastKey) > 0) { | ||
594 | mdb_cursor_close(cursor); | ||
595 | return 0; | ||
596 | } | ||
597 | |||
598 | do { | ||
599 | const auto currentBAKey = QByteArray::fromRawData((char *)currentKey.mv_data, currentKey.mv_size); | ||
600 | const auto currentBAValue = QByteArray::fromRawData((char *)data.mv_data, data.mv_size); | ||
601 | resultHandler(currentBAKey, currentBAValue); | ||
602 | } while (mdb_cursor_get(cursor, ¤tKey, &data, MDB_NEXT) == MDB_SUCCESS && | ||
603 | mdb_cmp(d->transaction, d->dbi, ¤tKey, &idealLastKey) <= 0); | ||
604 | |||
605 | mdb_cursor_close(cursor); | ||
606 | } | ||
607 | |||
554 | qint64 DataStore::NamedDatabase::getSize() | 608 | qint64 DataStore::NamedDatabase::getSize() |
555 | { | 609 | { |
556 | if (!d || !d->transaction) { | 610 | if (!d || !d->transaction) { |