summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorRémi Nicole <nicole@kolabsystems.com>2018-05-24 12:10:24 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2018-05-24 12:17:15 +0200
commit0456cef80e909e545897ac9eb107fd832d4dfde8 (patch)
tree5878f19df4089c166637380850a6bc101fa20a82 /common
parent7e910179f1349d1245211933d95cda2dc13cd617 (diff)
downloadsink-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')
-rw-r--r--common/storage.h9
-rw-r--r--common/storage_lmdb.cpp54
2 files changed, 63 insertions, 0 deletions
diff --git a/common/storage.h b/common/storage.h
index bb8c1fa..a8c486c 100644
--- a/common/storage.h
+++ b/common/storage.h
@@ -109,6 +109,15 @@ public:
109 const std::function<void(const DataStore::Error &error)> &errorHandler = std::function<void(const DataStore::Error &error)>()) const; 109 const std::function<void(const DataStore::Error &error)> &errorHandler = std::function<void(const DataStore::Error &error)>()) const;
110 110
111 /** 111 /**
112 * Finds all the keys and values whose keys are in a given range
113 * (inclusive).
114 */
115 int findAllInRange(const QByteArray &lowerBound, const QByteArray &upperBound,
116 const std::function<void(const QByteArray &key, const QByteArray &value)> &resultHandler,
117 const std::function<void(const DataStore::Error &error)> &errorHandler =
118 std::function<void(const DataStore::Error &error)>()) const;
119
120 /**
112 * Returns true if the database contains the substring key. 121 * Returns true if the database contains the substring key.
113 */ 122 */
114 bool contains(const QByteArray &uid); 123 bool contains(const QByteArray &uid);
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
554int 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, &currentKey, &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, &currentKey, &data, MDB_NEXT) == MDB_SUCCESS &&
603 mdb_cmp(d->transaction, d->dbi, &currentKey, &idealLastKey) <= 0);
604
605 mdb_cursor_close(cursor);
606}
607
554qint64 DataStore::NamedDatabase::getSize() 608qint64 DataStore::NamedDatabase::getSize()
555{ 609{
556 if (!d || !d->transaction) { 610 if (!d || !d->transaction) {