#endif /* #ifndef DNSDIST */
+std::atomic<unsigned int> MDBDbi::d_creationCount{0};
+
MDBDbi::MDBDbi(MDB_env* /* env */, MDB_txn* txn, const string_view dbname, int flags) : d_dbi(-1)
{
// A transaction that uses this function must finish (either commit or abort) before any other transaction in the process may use this function.
- int rc = mdb_dbi_open(txn, dbname.empty() ? 0 : &dbname[0], flags, &d_dbi);
- if(rc)
- throw std::runtime_error("Unable to open named database: " + MDBError(rc));
+ int ret = MDBDbi::mdb_dbi_open(txn, dbname.empty() ? nullptr : dbname.data(), flags, &d_dbi);
+ if (ret != 0) {
+ throw std::runtime_error("Unable to open named database: " + MDBError(ret));
+ }
// Database names are keys in the unnamed database, and may be read but not written.
}
+// This is a wrapper around the real mdb_dbi_open(), in order to track creation
+// of new files.
+int MDBDbi::mdb_dbi_open(MDB_txn* txn, const char* name, unsigned int flags, MDB_dbi* dbi)
+{
+ if ((flags & MDB_CREATE) != 0) {
+ flags &= ~MDB_CREATE;
+ int retval = ::mdb_dbi_open(txn, name, flags, dbi);
+ if (retval == MDB_NOTFOUND) {
+ flags |= MDB_CREATE;
+ retval = ::mdb_dbi_open(txn, name, flags, dbi);
+ if (retval == 0) {
+ d_creationCount++;
+ }
+ }
+ return retval;
+ }
+ return ::mdb_dbi_open(txn, name, flags, dbi);
+}
+
MDBEnv::MDBEnv(const char* fname, int flags, int mode, uint64_t mapsizeMB)
{
mdb_env_create(&d_env);
MDB_dbi dbi;
{
- int retCode = mdb_dbi_open(txn, "pdns", 0, &dbi);
+ int retCode = MDBDbi::mdb_dbi_open(txn, "pdns", 0, &dbi);
if (retCode != 0) {
if (retCode == MDB_NOTFOUND) {
// this means nothing has been inited yet
MDB_dbi shdbi = 0;
- const auto dbiOpenRc = mdb_dbi_open(shtxn, "records", 0, &shdbi);
+ const auto dbiOpenRc = MDBDbi::mdb_dbi_open(shtxn, "records", 0, &shdbi);
if (dbiOpenRc != 0) {
if (dbiOpenRc == MDB_NOTFOUND) {
mdb_txn_abort(shtxn);
MDB_dbi shdbi2 = 0;
- if (mdb_dbi_open(shtxn, "records_v5", MDB_CREATE, &shdbi2) != 0) {
+ if (MDBDbi::mdb_dbi_open(shtxn, "records_v5", MDB_CREATE, &shdbi2) != 0) {
mdb_dbi_close(shenv, shdbi);
mdb_txn_abort(shtxn);
mdb_env_close(shenv);
std::string tdbname = dbname + "_v5";
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index)
- if (mdb_dbi_open(txn, dbname.c_str(), 0, &fromtypeddbi[index]) != 0) {
+ if (MDBDbi::mdb_dbi_open(txn, dbname.c_str(), 0, &fromtypeddbi[index]) != 0) {
mdb_txn_abort(txn);
mdb_env_close(env);
- throw std::runtime_error("mdb_dbi_open typeddbi failed");
+ throw std::runtime_error("MDBDbi::mdb_dbi_open typeddbi failed");
}
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index)
- if (mdb_dbi_open(txn, tdbname.c_str(), MDB_CREATE, &totypeddbi[index]) != 0) {
+ if (MDBDbi::mdb_dbi_open(txn, tdbname.c_str(), MDB_CREATE, &totypeddbi[index]) != 0) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index)
mdb_dbi_close(env, fromtypeddbi[index]);
mdb_txn_abort(txn);
std::string tdbname = dbname + "_v5_0";
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index)
- if (mdb_dbi_open(txn, fdbname.c_str(), 0, &fromindexdbi[index]) != 0) {
+ if (MDBDbi::mdb_dbi_open(txn, fdbname.c_str(), 0, &fromindexdbi[index]) != 0) {
mdb_txn_abort(txn);
mdb_env_close(env);
throw std::runtime_error("mdb_dbi_open indexdbi failed");
}
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index)
- if (mdb_dbi_open(txn, tdbname.c_str(), MDB_CREATE, &toindexdbi[index]) != 0) {
+ if (MDBDbi::mdb_dbi_open(txn, tdbname.c_str(), MDB_CREATE, &toindexdbi[index]) != 0) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index)
mdb_dbi_close(env, fromindexdbi[index]);
mdb_txn_abort(txn);
MDB_dbi dbi = 0;
// finally, migrate the pdns db
- if (mdb_dbi_open(txn, "pdns", 0, &dbi) != 0) {
+ if (MDBDbi::mdb_dbi_open(txn, "pdns", 0, &dbi) != 0) {
mdb_txn_abort(txn);
mdb_env_close(env);
throw std::runtime_error("mdb_dbi_open pdns failed");
return "unknown lmdbbackend command\n";
}
+bool LMDBBackend::hasCreatedLocalFiles() const
+{
+ // Since the lmdb file creation counter is global, if multiple LMDB backends
+ // are used, they may end up all reporting having created files even if
+ // not all of them did.
+ // But since this information is for the sake of pdnsutil, this is not
+ // really a problem.
+ return MDBDbi::d_creationCount != 0;
+}
+
class LMDBFactory : public BackendFactory
{
public: