summaryrefslogtreecommitdiffstats
path: root/common/storage_lmdb.cpp
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2016-05-30 23:15:23 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2016-05-30 23:15:23 +0200
commit8588cd99ee9f3ba92a7167be3752fe511200131b (patch)
tree5ecad52cc4a49ebe31d5d410a1eb396e74ca3f9e /common/storage_lmdb.cpp
parentfe1940830d7cc2e9c652ec9a13ca7f3790ff4079 (diff)
downloadsink-8588cd99ee9f3ba92a7167be3752fe511200131b.tar.gz
sink-8588cd99ee9f3ba92a7167be3752fe511200131b.zip
Detect and recover from invalid database environment.
Sometimes wrong databases are returned for the name, probably related to threading/incorrect usage of lmdb. For the time being we recover from that by detecting it and retrying.
Diffstat (limited to 'common/storage_lmdb.cpp')
-rw-r--r--common/storage_lmdb.cpp44
1 files changed, 43 insertions, 1 deletions
diff --git a/common/storage_lmdb.cpp b/common/storage_lmdb.cpp
index cc8b28d..ae4bfba 100644
--- a/common/storage_lmdb.cpp
+++ b/common/storage_lmdb.cpp
@@ -437,6 +437,43 @@ void Storage::Transaction::abort()
437 d->transaction = nullptr; 437 d->transaction = nullptr;
438} 438}
439 439
440//Ensure that we opened the correct database by comparing the expected identifier with the one
441//we write to the database on first open.
442static bool ensureCorrectDb(Storage::NamedDatabase &database, const QByteArray &db, bool readOnly)
443{
444 bool openedTheWrongDatabase = false;
445 auto count = database.scan("__internal_dbname", [db, &openedTheWrongDatabase](const QByteArray &key, const QByteArray &value) ->bool {
446 if (value != db) {
447 Warning() << "Opened the wrong database, got " << value << " instead of " << db;
448 openedTheWrongDatabase = true;
449 }
450 return false;
451 },
452 [](const Storage::Error &error) -> bool{
453 return false;
454 }, false);
455 //This is the first time we open this database in a write transaction, write the db name
456 if (!count) {
457 if (!readOnly) {
458 database.write("__internal_dbname", db);
459 }
460 }
461 return !openedTheWrongDatabase;
462}
463
464bool Storage::Transaction::validateNamedDatabases()
465{
466 auto databases = getDatabaseNames();
467 for (const auto &dbName : databases) {
468 auto db = openDatabase(dbName);
469 if (!db) {
470 Warning() << "Failed to open the database: " << dbName;
471 return false;
472 }
473 }
474 return true;
475}
476
440Storage::NamedDatabase Storage::Transaction::openDatabase(const QByteArray &db, const std::function<void(const Storage::Error &error)> &errorHandler, bool allowDuplicates) const 477Storage::NamedDatabase Storage::Transaction::openDatabase(const QByteArray &db, const std::function<void(const Storage::Error &error)> &errorHandler, bool allowDuplicates) const
441{ 478{
442 if (!d) { 479 if (!d) {
@@ -450,7 +487,12 @@ Storage::NamedDatabase Storage::Transaction::openDatabase(const QByteArray &db,
450 delete p; 487 delete p;
451 return Storage::NamedDatabase(); 488 return Storage::NamedDatabase();
452 } 489 }
453 return Storage::NamedDatabase(p); 490 auto database = Storage::NamedDatabase(p);
491 if (!ensureCorrectDb(database, db, d->requestedRead)) {
492 Warning() << "Failed to open the database";
493 return Storage::NamedDatabase();
494 }
495 return database;
454} 496}
455 497
456QList<QByteArray> Storage::Transaction::getDatabaseNames() const 498QList<QByteArray> Storage::Transaction::getDatabaseNames() const