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.cpp86
1 files changed, 54 insertions, 32 deletions
diff --git a/common/storage_lmdb.cpp b/common/storage_lmdb.cpp
index ed385ad..08eea37 100644
--- a/common/storage_lmdb.cpp
+++ b/common/storage_lmdb.cpp
@@ -62,6 +62,44 @@ int getErrorCode(int e)
62 return -1; 62 return -1;
63} 63}
64 64
65static QList<QByteArray> getDatabaseNames(MDB_txn *transaction)
66{
67 if (!transaction) {
68 SinkWarning() << "Invalid transaction";
69 return QList<QByteArray>();
70 }
71 int rc;
72 QList<QByteArray> list;
73 MDB_dbi dbi;
74 if ((rc = mdb_dbi_open(transaction, nullptr, 0, &dbi) == 0)) {
75 MDB_val key;
76 MDB_val data;
77 MDB_cursor *cursor;
78
79 mdb_cursor_open(transaction, dbi, &cursor);
80 if ((rc = mdb_cursor_get(cursor, &key, &data, MDB_FIRST)) == 0) {
81 list << QByteArray::fromRawData((char *)key.mv_data, key.mv_size);
82 while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
83 list << QByteArray::fromRawData((char *)key.mv_data, key.mv_size);
84 }
85 } else {
86 //Normal if we don't have any databases yet
87 if (rc == MDB_NOTFOUND) {
88 rc = 0;
89 }
90 if (rc) {
91 SinkWarning() << "Failed to get a value" << rc;
92 }
93 }
94 mdb_cursor_close(cursor);
95 } else {
96 SinkWarning() << "Failed to open db" << rc << QByteArray(mdb_strerror(rc));
97 }
98 return list;
99
100}
101
102
65class DataStore::NamedDatabase::Private 103class DataStore::NamedDatabase::Private
66{ 104{
67public: 105public:
@@ -93,6 +131,18 @@ public:
93 const auto dbiName = name + db; 131 const auto dbiName = name + db;
94 if (sDbis.contains(dbiName)) { 132 if (sDbis.contains(dbiName)) {
95 dbi = sDbis.value(dbiName); 133 dbi = sDbis.value(dbiName);
134 //sDbis can contain dbi's that are not available to this transaction.
135 //We use mdb_dbi_flags to check if the dbi is valid for this transaction.
136 uint f;
137 if (mdb_dbi_flags(transaction, dbi, &f) == EINVAL) {
138 //In readonly mode we can just ignore this. In read-write we would have tried to concurrently create a db.
139 if (!readOnly) {
140 SinkWarning() << "Tried to create database in second transaction: " << dbiName;
141 }
142 dbi = 0;
143 transaction = 0;
144 return false;
145 }
96 } else { 146 } else {
97 MDB_dbi flagtableDbi; 147 MDB_dbi flagtableDbi;
98 if (const int rc = mdb_dbi_open(transaction, "__flagtable", readOnly ? 0 : MDB_CREATE, &flagtableDbi)) { 148 if (const int rc = mdb_dbi_open(transaction, "__flagtable", readOnly ? 0 : MDB_CREATE, &flagtableDbi)) {
@@ -279,7 +329,8 @@ int DataStore::NamedDatabase::scan(const QByteArray &k, const std::function<bool
279 329
280 rc = mdb_cursor_open(d->transaction, d->dbi, &cursor); 330 rc = mdb_cursor_open(d->transaction, d->dbi, &cursor);
281 if (rc) { 331 if (rc) {
282 Error error(d->name.toLatin1() + d->db, getErrorCode(rc), QByteArray("Error during mdb_cursor open: ") + QByteArray(mdb_strerror(rc))); 332 //Invalid arguments can mean that the transaction doesn't contain the db dbi
333 Error error(d->name.toLatin1() + d->db, getErrorCode(rc), QByteArray("Error during mdb_cursor_open: ") + QByteArray(mdb_strerror(rc)) + ". Key: " + k);
283 errorHandler ? errorHandler(error) : d->defaultErrorHandler(error); 334 errorHandler ? errorHandler(error) : d->defaultErrorHandler(error);
284 return 0; 335 return 0;
285 } 336 }
@@ -447,7 +498,6 @@ public:
447 498
448 MDB_env *env; 499 MDB_env *env;
449 MDB_txn *transaction; 500 MDB_txn *transaction;
450 MDB_dbi dbi;
451 bool requestedRead; 501 bool requestedRead;
452 std::function<void(const DataStore::Error &error)> defaultErrorHandler; 502 std::function<void(const DataStore::Error &error)> defaultErrorHandler;
453 QString name; 503 QString name;
@@ -578,8 +628,7 @@ static bool ensureCorrectDb(DataStore::NamedDatabase &database, const QByteArray
578 } 628 }
579 return false; 629 return false;
580 }, 630 },
581 [](const DataStore::Error &error) -> bool{ 631 [&](const DataStore::Error &) {
582 return false;
583 }, false); 632 }, false);
584 //This is the first time we open this database in a write transaction, write the db name 633 //This is the first time we open this database in a write transaction, write the db name
585 if (!count) { 634 if (!count) {
@@ -637,35 +686,8 @@ QList<QByteArray> DataStore::Transaction::getDatabaseNames() const
637 SinkWarning() << "Invalid transaction"; 686 SinkWarning() << "Invalid transaction";
638 return QList<QByteArray>(); 687 return QList<QByteArray>();
639 } 688 }
689 return Sink::Storage::getDatabaseNames(d->transaction);
640 690
641 int rc;
642 QList<QByteArray> list;
643 Q_ASSERT(d->transaction);
644 if ((rc = mdb_dbi_open(d->transaction, nullptr, 0, &d->dbi) == 0)) {
645 MDB_val key;
646 MDB_val data;
647 MDB_cursor *cursor;
648
649 mdb_cursor_open(d->transaction, d->dbi, &cursor);
650 if ((rc = mdb_cursor_get(cursor, &key, &data, MDB_FIRST)) == 0) {
651 list << QByteArray::fromRawData((char *)key.mv_data, key.mv_size);
652 while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
653 list << QByteArray::fromRawData((char *)key.mv_data, key.mv_size);
654 }
655 } else {
656 //Normal if we don't have any databases yet
657 if (rc == MDB_NOTFOUND) {
658 rc = 0;
659 }
660 if (rc) {
661 SinkWarning() << "Failed to get a value" << rc;
662 }
663 }
664 mdb_cursor_close(cursor);
665 } else {
666 SinkWarning() << "Failed to open db" << rc << QByteArray(mdb_strerror(rc));
667 }
668 return list;
669} 691}
670 692
671 693