diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2015-09-11 09:31:24 +0200 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2015-09-11 09:31:24 +0200 |
commit | 50f737b8549fb1b380c753d36be3fafe0ec4a768 (patch) | |
tree | 63dc679d19382bba8e9100d20822d0c502e3dcc7 /common | |
parent | 2554645a86359ec4cf805c8dee0e347b802776e0 (diff) | |
download | sink-50f737b8549fb1b380c753d36be3fafe0ec4a768.tar.gz sink-50f737b8549fb1b380c753d36be3fafe0ec4a768.zip |
Storage: substring search and findLatest
Diffstat (limited to 'common')
-rw-r--r-- | common/storage.h | 11 | ||||
-rw-r--r-- | common/storage_common.cpp | 11 | ||||
-rw-r--r-- | common/storage_lmdb.cpp | 47 |
3 files changed, 58 insertions, 11 deletions
diff --git a/common/storage.h b/common/storage.h index d186b2e..98b12ed 100644 --- a/common/storage.h +++ b/common/storage.h | |||
@@ -76,9 +76,13 @@ public: | |||
76 | * | 76 | * |
77 | * @return The number of values retrieved. | 77 | * @return The number of values retrieved. |
78 | */ | 78 | */ |
79 | int scan(const QByteArray &k, | 79 | int scan(const QByteArray &key, |
80 | const std::function<bool(const QByteArray &key, const QByteArray &value)> &resultHandler, | 80 | const std::function<bool(const QByteArray &key, const QByteArray &value)> &resultHandler, |
81 | const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()) const; | 81 | const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>(), bool findSubstringKeys = false) const; |
82 | |||
83 | void findLatest(const QByteArray &uid, | ||
84 | const std::function<void(const QByteArray &key, const QByteArray &value)> &resultHandler, | ||
85 | const std::function<void(const Storage::Error &error)> &errorHandler = std::function<void(const Storage::Error &error)>()) const; | ||
82 | 86 | ||
83 | NamedDatabase(NamedDatabase&& other) : d(other.d) | 87 | NamedDatabase(NamedDatabase&& other) : d(other.d) |
84 | { | 88 | { |
@@ -170,6 +174,9 @@ public: | |||
170 | static bool isInternalKey(void *key, int keySize); | 174 | static bool isInternalKey(void *key, int keySize); |
171 | static bool isInternalKey(const QByteArray &key); | 175 | static bool isInternalKey(const QByteArray &key); |
172 | 176 | ||
177 | static QByteArray assembleKey(const QByteArray &key, qint64 revision); | ||
178 | static QByteArray uidFromKey(const QByteArray &key); | ||
179 | |||
173 | private: | 180 | private: |
174 | std::function<void(const Storage::Error &error)> mErrorHandler; | 181 | std::function<void(const Storage::Error &error)> mErrorHandler; |
175 | 182 | ||
diff --git a/common/storage_common.cpp b/common/storage_common.cpp index f22150a..28fb4c2 100644 --- a/common/storage_common.cpp +++ b/common/storage_common.cpp | |||
@@ -93,4 +93,15 @@ bool Storage::isInternalKey(const QByteArray &key) | |||
93 | return key.startsWith(s_internalPrefix); | 93 | return key.startsWith(s_internalPrefix); |
94 | } | 94 | } |
95 | 95 | ||
96 | QByteArray Storage::assembleKey(const QByteArray &key, qint64 revision) | ||
97 | { | ||
98 | Q_ASSERT(key.size() == 38); | ||
99 | return key + QByteArray::number(revision); | ||
100 | } | ||
101 | |||
102 | QByteArray Storage::uidFromKey(const QByteArray &key) | ||
103 | { | ||
104 | return key.mid(0, 38); | ||
105 | } | ||
106 | |||
96 | } // namespace Akonadi2 | 107 | } // namespace Akonadi2 |
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 | ||
170 | int Storage::NamedDatabase::scan(const QByteArray &k, | 170 | int 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 | } |
241 | void 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 | ||