diff options
Diffstat (limited to 'common/storage_lmdb.cpp')
-rw-r--r-- | common/storage_lmdb.cpp | 86 |
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 | ||
65 | static 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 | |||
65 | class DataStore::NamedDatabase::Private | 103 | class DataStore::NamedDatabase::Private |
66 | { | 104 | { |
67 | public: | 105 | public: |
@@ -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 | ||