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.cpp100
1 files changed, 51 insertions, 49 deletions
diff --git a/common/storage_lmdb.cpp b/common/storage_lmdb.cpp
index 6f11af3..e418472 100644
--- a/common/storage_lmdb.cpp
+++ b/common/storage_lmdb.cpp
@@ -39,6 +39,7 @@ SINK_DEBUG_AREA("storage")
39// SINK_DEBUG_COMPONENT(d->storageRoot.toLatin1() + '/' + d->name.toLatin1()) 39// SINK_DEBUG_COMPONENT(d->storageRoot.toLatin1() + '/' + d->name.toLatin1())
40 40
41namespace Sink { 41namespace Sink {
42namespace Storage {
42 43
43QMutex sMutex; 44QMutex sMutex;
44QHash<QString, MDB_env *> sEnvironments; 45QHash<QString, MDB_env *> sEnvironments;
@@ -47,17 +48,17 @@ int getErrorCode(int e)
47{ 48{
48 switch (e) { 49 switch (e) {
49 case MDB_NOTFOUND: 50 case MDB_NOTFOUND:
50 return Storage::ErrorCodes::NotFound; 51 return DataStore::ErrorCodes::NotFound;
51 default: 52 default:
52 break; 53 break;
53 } 54 }
54 return -1; 55 return -1;
55} 56}
56 57
57class Storage::NamedDatabase::Private 58class DataStore::NamedDatabase::Private
58{ 59{
59public: 60public:
60 Private(const QByteArray &_db, bool _allowDuplicates, const std::function<void(const Storage::Error &error)> &_defaultErrorHandler, const QString &_name, MDB_txn *_txn) 61 Private(const QByteArray &_db, bool _allowDuplicates, const std::function<void(const DataStore::Error &error)> &_defaultErrorHandler, const QString &_name, MDB_txn *_txn)
61 : db(_db), transaction(_txn), allowDuplicates(_allowDuplicates), defaultErrorHandler(_defaultErrorHandler), name(_name) 62 : db(_db), transaction(_txn), allowDuplicates(_allowDuplicates), defaultErrorHandler(_defaultErrorHandler), name(_name)
62 { 63 {
63 } 64 }
@@ -70,10 +71,10 @@ public:
70 MDB_txn *transaction; 71 MDB_txn *transaction;
71 MDB_dbi dbi; 72 MDB_dbi dbi;
72 bool allowDuplicates; 73 bool allowDuplicates;
73 std::function<void(const Storage::Error &error)> defaultErrorHandler; 74 std::function<void(const DataStore::Error &error)> defaultErrorHandler;
74 QString name; 75 QString name;
75 76
76 bool openDatabase(bool readOnly, std::function<void(const Storage::Error &error)> errorHandler) 77 bool openDatabase(bool readOnly, std::function<void(const DataStore::Error &error)> errorHandler)
77 { 78 {
78 unsigned int flags = 0; 79 unsigned int flags = 0;
79 if (!readOnly) { 80 if (!readOnly) {
@@ -97,20 +98,20 @@ public:
97 } 98 }
98}; 99};
99 100
100Storage::NamedDatabase::NamedDatabase() : d(nullptr) 101DataStore::NamedDatabase::NamedDatabase() : d(nullptr)
101{ 102{
102} 103}
103 104
104Storage::NamedDatabase::NamedDatabase(NamedDatabase::Private *prv) : d(prv) 105DataStore::NamedDatabase::NamedDatabase(NamedDatabase::Private *prv) : d(prv)
105{ 106{
106} 107}
107 108
108Storage::NamedDatabase::NamedDatabase(NamedDatabase &&other) : d(nullptr) 109DataStore::NamedDatabase::NamedDatabase(NamedDatabase &&other) : d(nullptr)
109{ 110{
110 *this = std::move(other); 111 *this = std::move(other);
111} 112}
112 113
113Storage::NamedDatabase &Storage::NamedDatabase::operator=(Storage::NamedDatabase &&other) 114DataStore::NamedDatabase &DataStore::NamedDatabase::operator=(DataStore::NamedDatabase &&other)
114{ 115{
115 if (&other != this) { 116 if (&other != this) {
116 delete d; 117 delete d;
@@ -120,12 +121,12 @@ Storage::NamedDatabase &Storage::NamedDatabase::operator=(Storage::NamedDatabase
120 return *this; 121 return *this;
121} 122}
122 123
123Storage::NamedDatabase::~NamedDatabase() 124DataStore::NamedDatabase::~NamedDatabase()
124{ 125{
125 delete d; 126 delete d;
126} 127}
127 128
128bool Storage::NamedDatabase::write(const QByteArray &sKey, const QByteArray &sValue, const std::function<void(const Storage::Error &error)> &errorHandler) 129bool DataStore::NamedDatabase::write(const QByteArray &sKey, const QByteArray &sValue, const std::function<void(const DataStore::Error &error)> &errorHandler)
129{ 130{
130 if (!d || !d->transaction) { 131 if (!d || !d->transaction) {
131 Error error("", ErrorCodes::GenericError, "Not open"); 132 Error error("", ErrorCodes::GenericError, "Not open");
@@ -161,12 +162,12 @@ bool Storage::NamedDatabase::write(const QByteArray &sKey, const QByteArray &sVa
161 return !rc; 162 return !rc;
162} 163}
163 164
164void Storage::NamedDatabase::remove(const QByteArray &k, const std::function<void(const Storage::Error &error)> &errorHandler) 165void DataStore::NamedDatabase::remove(const QByteArray &k, const std::function<void(const DataStore::Error &error)> &errorHandler)
165{ 166{
166 remove(k, QByteArray(), errorHandler); 167 remove(k, QByteArray(), errorHandler);
167} 168}
168 169
169void Storage::NamedDatabase::remove(const QByteArray &k, const QByteArray &value, const std::function<void(const Storage::Error &error)> &errorHandler) 170void DataStore::NamedDatabase::remove(const QByteArray &k, const QByteArray &value, const std::function<void(const DataStore::Error &error)> &errorHandler)
170{ 171{
171 if (!d || !d->transaction) { 172 if (!d || !d->transaction) {
172 if (d) { 173 if (d) {
@@ -195,8 +196,8 @@ void Storage::NamedDatabase::remove(const QByteArray &k, const QByteArray &value
195 } 196 }
196} 197}
197 198
198int Storage::NamedDatabase::scan(const QByteArray &k, const std::function<bool(const QByteArray &key, const QByteArray &value)> &resultHandler, 199int DataStore::NamedDatabase::scan(const QByteArray &k, const std::function<bool(const QByteArray &key, const QByteArray &value)> &resultHandler,
199 const std::function<void(const Storage::Error &error)> &errorHandler, bool findSubstringKeys, bool skipInternalKeys) const 200 const std::function<void(const DataStore::Error &error)> &errorHandler, bool findSubstringKeys, bool skipInternalKeys) const
200{ 201{
201 if (!d || !d->transaction) { 202 if (!d || !d->transaction) {
202 // Not an error. We rely on this to read nothing from non-existing databases. 203 // Not an error. We rely on this to read nothing from non-existing databases.
@@ -278,8 +279,8 @@ int Storage::NamedDatabase::scan(const QByteArray &k, const std::function<bool(c
278 return numberOfRetrievedValues; 279 return numberOfRetrievedValues;
279} 280}
280 281
281void Storage::NamedDatabase::findLatest(const QByteArray &k, const std::function<void(const QByteArray &key, const QByteArray &value)> &resultHandler, 282void DataStore::NamedDatabase::findLatest(const QByteArray &k, const std::function<void(const QByteArray &key, const QByteArray &value)> &resultHandler,
282 const std::function<void(const Storage::Error &error)> &errorHandler) const 283 const std::function<void(const DataStore::Error &error)> &errorHandler) const
283{ 284{
284 if (!d || !d->transaction) { 285 if (!d || !d->transaction) {
285 // Not an error. We rely on this to read nothing from non-existing databases. 286 // Not an error. We rely on this to read nothing from non-existing databases.
@@ -346,7 +347,7 @@ void Storage::NamedDatabase::findLatest(const QByteArray &k, const std::function
346 return; 347 return;
347} 348}
348 349
349qint64 Storage::NamedDatabase::getSize() 350qint64 DataStore::NamedDatabase::getSize()
350{ 351{
351 if (!d || !d->transaction) { 352 if (!d || !d->transaction) {
352 return -1; 353 return -1;
@@ -368,10 +369,10 @@ qint64 Storage::NamedDatabase::getSize()
368} 369}
369 370
370 371
371class Storage::Transaction::Private 372class DataStore::Transaction::Private
372{ 373{
373public: 374public:
374 Private(bool _requestRead, const std::function<void(const Storage::Error &error)> &_defaultErrorHandler, const QString &_name, MDB_env *_env) 375 Private(bool _requestRead, const std::function<void(const DataStore::Error &error)> &_defaultErrorHandler, const QString &_name, MDB_env *_env)
375 : env(_env), transaction(nullptr), requestedRead(_requestRead), defaultErrorHandler(_defaultErrorHandler), name(_name), implicitCommit(false), error(false), modificationCounter(0) 376 : env(_env), transaction(nullptr), requestedRead(_requestRead), defaultErrorHandler(_defaultErrorHandler), name(_name), implicitCommit(false), error(false), modificationCounter(0)
376 { 377 {
377 } 378 }
@@ -383,7 +384,7 @@ public:
383 MDB_txn *transaction; 384 MDB_txn *transaction;
384 MDB_dbi dbi; 385 MDB_dbi dbi;
385 bool requestedRead; 386 bool requestedRead;
386 std::function<void(const Storage::Error &error)> defaultErrorHandler; 387 std::function<void(const DataStore::Error &error)> defaultErrorHandler;
387 QString name; 388 QString name;
388 bool implicitCommit; 389 bool implicitCommit;
389 bool error; 390 bool error;
@@ -406,21 +407,21 @@ public:
406 } 407 }
407}; 408};
408 409
409Storage::Transaction::Transaction() : d(nullptr) 410DataStore::Transaction::Transaction() : d(nullptr)
410{ 411{
411} 412}
412 413
413Storage::Transaction::Transaction(Transaction::Private *prv) : d(prv) 414DataStore::Transaction::Transaction(Transaction::Private *prv) : d(prv)
414{ 415{
415 d->startTransaction(); 416 d->startTransaction();
416} 417}
417 418
418Storage::Transaction::Transaction(Transaction &&other) : d(nullptr) 419DataStore::Transaction::Transaction(Transaction &&other) : d(nullptr)
419{ 420{
420 *this = std::move(other); 421 *this = std::move(other);
421} 422}
422 423
423Storage::Transaction &Storage::Transaction::operator=(Storage::Transaction &&other) 424DataStore::Transaction &DataStore::Transaction::operator=(DataStore::Transaction &&other)
424{ 425{
425 if (&other != this) { 426 if (&other != this) {
426 delete d; 427 delete d;
@@ -430,7 +431,7 @@ Storage::Transaction &Storage::Transaction::operator=(Storage::Transaction &&oth
430 return *this; 431 return *this;
431} 432}
432 433
433Storage::Transaction::~Transaction() 434DataStore::Transaction::~Transaction()
434{ 435{
435 if (d && d->transaction) { 436 if (d && d->transaction) {
436 if (d->implicitCommit && !d->error) { 437 if (d->implicitCommit && !d->error) {
@@ -443,12 +444,12 @@ Storage::Transaction::~Transaction()
443 delete d; 444 delete d;
444} 445}
445 446
446Storage::Transaction::operator bool() const 447DataStore::Transaction::operator bool() const
447{ 448{
448 return (d && d->transaction); 449 return (d && d->transaction);
449} 450}
450 451
451bool Storage::Transaction::commit(const std::function<void(const Storage::Error &error)> &errorHandler) 452bool DataStore::Transaction::commit(const std::function<void(const DataStore::Error &error)> &errorHandler)
452{ 453{
453 if (!d || !d->transaction) { 454 if (!d || !d->transaction) {
454 return false; 455 return false;
@@ -467,7 +468,7 @@ bool Storage::Transaction::commit(const std::function<void(const Storage::Error
467 return !rc; 468 return !rc;
468} 469}
469 470
470void Storage::Transaction::abort() 471void DataStore::Transaction::abort()
471{ 472{
472 if (!d || !d->transaction) { 473 if (!d || !d->transaction) {
473 return; 474 return;
@@ -481,7 +482,7 @@ void Storage::Transaction::abort()
481 482
482//Ensure that we opened the correct database by comparing the expected identifier with the one 483//Ensure that we opened the correct database by comparing the expected identifier with the one
483//we write to the database on first open. 484//we write to the database on first open.
484static bool ensureCorrectDb(Storage::NamedDatabase &database, const QByteArray &db, bool readOnly) 485static bool ensureCorrectDb(DataStore::NamedDatabase &database, const QByteArray &db, bool readOnly)
485{ 486{
486 bool openedTheWrongDatabase = false; 487 bool openedTheWrongDatabase = false;
487 auto count = database.scan("__internal_dbname", [db, &openedTheWrongDatabase](const QByteArray &key, const QByteArray &value) ->bool { 488 auto count = database.scan("__internal_dbname", [db, &openedTheWrongDatabase](const QByteArray &key, const QByteArray &value) ->bool {
@@ -491,7 +492,7 @@ static bool ensureCorrectDb(Storage::NamedDatabase &database, const QByteArray &
491 } 492 }
492 return false; 493 return false;
493 }, 494 },
494 [](const Storage::Error &error) -> bool{ 495 [](const DataStore::Error &error) -> bool{
495 return false; 496 return false;
496 }, false); 497 }, false);
497 //This is the first time we open this database in a write transaction, write the db name 498 //This is the first time we open this database in a write transaction, write the db name
@@ -503,7 +504,7 @@ static bool ensureCorrectDb(Storage::NamedDatabase &database, const QByteArray &
503 return !openedTheWrongDatabase; 504 return !openedTheWrongDatabase;
504} 505}
505 506
506bool Storage::Transaction::validateNamedDatabases() 507bool DataStore::Transaction::validateNamedDatabases()
507{ 508{
508 auto databases = getDatabaseNames(); 509 auto databases = getDatabaseNames();
509 for (const auto &dbName : databases) { 510 for (const auto &dbName : databases) {
@@ -516,28 +517,28 @@ bool Storage::Transaction::validateNamedDatabases()
516 return true; 517 return true;
517} 518}
518 519
519Storage::NamedDatabase Storage::Transaction::openDatabase(const QByteArray &db, const std::function<void(const Storage::Error &error)> &errorHandler, bool allowDuplicates) const 520DataStore::NamedDatabase DataStore::Transaction::openDatabase(const QByteArray &db, const std::function<void(const DataStore::Error &error)> &errorHandler, bool allowDuplicates) const
520{ 521{
521 if (!d) { 522 if (!d) {
522 return Storage::NamedDatabase(); 523 return DataStore::NamedDatabase();
523 } 524 }
524 Q_ASSERT(d->transaction); 525 Q_ASSERT(d->transaction);
525 // We don't now if anything changed 526 // We don't now if anything changed
526 d->implicitCommit = true; 527 d->implicitCommit = true;
527 auto p = new Storage::NamedDatabase::Private(db, allowDuplicates, d->defaultErrorHandler, d->name, d->transaction); 528 auto p = new DataStore::NamedDatabase::Private(db, allowDuplicates, d->defaultErrorHandler, d->name, d->transaction);
528 if (!p->openDatabase(d->requestedRead, errorHandler)) { 529 if (!p->openDatabase(d->requestedRead, errorHandler)) {
529 delete p; 530 delete p;
530 return Storage::NamedDatabase(); 531 return DataStore::NamedDatabase();
531 } 532 }
532 auto database = Storage::NamedDatabase(p); 533 auto database = DataStore::NamedDatabase(p);
533 if (!ensureCorrectDb(database, db, d->requestedRead)) { 534 if (!ensureCorrectDb(database, db, d->requestedRead)) {
534 SinkWarning() << "Failed to open the database" << db; 535 SinkWarning() << "Failed to open the database" << db;
535 return Storage::NamedDatabase(); 536 return DataStore::NamedDatabase();
536 } 537 }
537 return database; 538 return database;
538} 539}
539 540
540QList<QByteArray> Storage::Transaction::getDatabaseNames() const 541QList<QByteArray> DataStore::Transaction::getDatabaseNames() const
541{ 542{
542 if (!d) { 543 if (!d) {
543 SinkWarning() << "Invalid transaction"; 544 SinkWarning() << "Invalid transaction";
@@ -574,7 +575,7 @@ QList<QByteArray> Storage::Transaction::getDatabaseNames() const
574} 575}
575 576
576 577
577class Storage::Private 578class DataStore::Private
578{ 579{
579public: 580public:
580 Private(const QString &s, const QString &n, AccessMode m); 581 Private(const QString &s, const QString &n, AccessMode m);
@@ -587,7 +588,7 @@ public:
587 AccessMode mode; 588 AccessMode mode;
588}; 589};
589 590
590Storage::Private::Private(const QString &s, const QString &n, AccessMode m) : storageRoot(s), name(n), env(0), mode(m) 591DataStore::Private::Private(const QString &s, const QString &n, AccessMode m) : storageRoot(s), name(n), env(0), mode(m)
591{ 592{
592 const QString fullPath(storageRoot + '/' + name); 593 const QString fullPath(storageRoot + '/' + name);
593 QFileInfo dirInfo(fullPath); 594 QFileInfo dirInfo(fullPath);
@@ -639,27 +640,27 @@ Storage::Private::Private(const QString &s, const QString &n, AccessMode m) : st
639 } 640 }
640} 641}
641 642
642Storage::Private::~Private() 643DataStore::Private::~Private()
643{ 644{
644 //We never close the environment (unless we remove the db), since we should only open the environment once per process (as per lmdb docs) 645 //We never close the environment (unless we remove the db), since we should only open the environment once per process (as per lmdb docs)
645 //and create storage instance from all over the place. Thus, we're not closing it here on purpose. 646 //and create storage instance from all over the place. Thus, we're not closing it here on purpose.
646} 647}
647 648
648Storage::Storage(const QString &storageRoot, const QString &name, AccessMode mode) : d(new Private(storageRoot, name, mode)) 649DataStore::DataStore(const QString &storageRoot, const QString &name, AccessMode mode) : d(new Private(storageRoot, name, mode))
649{ 650{
650} 651}
651 652
652Storage::~Storage() 653DataStore::~DataStore()
653{ 654{
654 delete d; 655 delete d;
655} 656}
656 657
657bool Storage::exists() const 658bool DataStore::exists() const
658{ 659{
659 return (d->env != 0); 660 return (d->env != 0);
660} 661}
661 662
662Storage::Transaction Storage::createTransaction(AccessMode type, const std::function<void(const Storage::Error &error)> &errorHandlerArg) 663DataStore::Transaction DataStore::createTransaction(AccessMode type, const std::function<void(const DataStore::Error &error)> &errorHandlerArg)
663{ 664{
664 auto errorHandler = errorHandlerArg ? errorHandlerArg : defaultErrorHandler(); 665 auto errorHandler = errorHandlerArg ? errorHandlerArg : defaultErrorHandler();
665 if (!d->env) { 666 if (!d->env) {
@@ -677,7 +678,7 @@ Storage::Transaction Storage::createTransaction(AccessMode type, const std::func
677 return Transaction(new Transaction::Private(requestedRead, defaultErrorHandler(), d->name, d->env)); 678 return Transaction(new Transaction::Private(requestedRead, defaultErrorHandler(), d->name, d->env));
678} 679}
679 680
680qint64 Storage::diskUsage() const 681qint64 DataStore::diskUsage() const
681{ 682{
682 QFileInfo info(d->storageRoot + '/' + d->name + "/data.mdb"); 683 QFileInfo info(d->storageRoot + '/' + d->name + "/data.mdb");
683 if (!info.exists()) { 684 if (!info.exists()) {
@@ -686,7 +687,7 @@ qint64 Storage::diskUsage() const
686 return info.size(); 687 return info.size();
687} 688}
688 689
689void Storage::removeFromDisk() const 690void DataStore::removeFromDisk() const
690{ 691{
691 const QString fullPath(d->storageRoot + '/' + d->name); 692 const QString fullPath(d->storageRoot + '/' + d->name);
692 QMutexLocker locker(&sMutex); 693 QMutexLocker locker(&sMutex);
@@ -701,7 +702,7 @@ void Storage::removeFromDisk() const
701 } 702 }
702} 703}
703 704
704void Storage::clearEnv() 705void DataStore::clearEnv()
705{ 706{
706 for (auto env : sEnvironments) { 707 for (auto env : sEnvironments) {
707 mdb_env_close(env); 708 mdb_env_close(env);
@@ -709,4 +710,5 @@ void Storage::clearEnv()
709 sEnvironments.clear(); 710 sEnvironments.clear();
710} 711}
711 712
713}
712} // namespace Sink 714} // namespace Sink