Numeric IDs inside the database are generated randomly instead of sequentially.
If some external process is synchronising databases between systems, this will avoid conflicts when objects (domains, keys, etc.) get added.
+.. _settings-lmdb-map-size:
+
+``lmdb-random-ids``
+^^^^^^^^^^^^^^^^^^^
+
+ .. versionadded:: 4.7.0
+
+Size, in megabytes, of each LMDB database.
+This number can be increased later, but never decreased.
+Defaults to 100 on 32 bit systems, and 16000 on 64 bit systems.
+
LMDB Structure
--------------
// Database names are keys in the unnamed database, and may be read but not written.
}
-MDBEnv::MDBEnv(const char* fname, int flags, int mode)
+MDBEnv::MDBEnv(const char* fname, int flags, int mode, uint64_t mapsizeMB)
{
mdb_env_create(&d_env);
- uint64_t mapsizeMB = (sizeof(long)==4) ? 100 : 16000;
- // on 32 bit platforms, there is just no room for more
if(mdb_env_set_mapsize(d_env, mapsizeMB * 1048576))
throw std::runtime_error("setting map size");
/*
}
-std::shared_ptr<MDBEnv> getMDBEnv(const char* fname, int flags, int mode)
+std::shared_ptr<MDBEnv> getMDBEnv(const char* fname, int flags, int mode, uint64_t mapsizeMB)
{
struct Value
{
throw std::runtime_error("Unable to stat prospective mdb database: "+string(strerror(errno)));
else {
std::lock_guard<std::mutex> l(mut);
- auto fresh = std::make_shared<MDBEnv>(fname, flags, mode);
+ auto fresh = std::make_shared<MDBEnv>(fname, flags, mode, mapsizeMB);
if(stat(fname, &statbuf))
throw std::runtime_error("Unable to stat prospective mdb database: "+string(strerror(errno)));
auto key = std::tie(statbuf.st_dev, statbuf.st_ino);
}
}
- auto fresh = std::make_shared<MDBEnv>(fname, flags, mode);
+ auto fresh = std::make_shared<MDBEnv>(fname, flags, mode, mapsizeMB);
s_envs[key] = {fresh, flags};
return fresh;
class MDBEnv
{
public:
- MDBEnv(const char* fname, int flags, int mode);
+ MDBEnv(const char* fname, int flags, int mode, uint64_t mapsizeMB);
~MDBEnv()
{
std::map<std::thread::id, int> d_ROtransactionsOut;
};
-std::shared_ptr<MDBEnv> getMDBEnv(const char* fname, int flags, int mode);
+std::shared_ptr<MDBEnv> getMDBEnv(const char* fname, int flags, int mode, uint64_t mapsizeMB=(sizeof(void *)==4) ? 100 : 16000);
else
throw std::runtime_error("Unknown sync mode " + syncMode + " requested for LMDB backend");
- d_tdomains = std::make_shared<tdomains_t>(getMDBEnv(getArg("filename").c_str(), MDB_NOSUBDIR | d_asyncFlag, 0600), "domains");
+ uint64_t mapSize = 0;
+ try {
+ mapSize = std::stoll(getArg("map-size"));
+ }
+ catch (const std::exception& e) {
+ throw std::runtime_error(std::string("Unable to parse the 'map-size' LMDB value: ") + e.what());
+ }
+ d_tdomains = std::make_shared<tdomains_t>(getMDBEnv(getArg("filename").c_str(), MDB_NOSUBDIR | d_asyncFlag, 0600, mapSize), "domains");
d_tmeta = std::make_shared<tmeta_t>(d_tdomains->getEnv(), "metadata");
d_tkdb = std::make_shared<tkdb_t>(d_tdomains->getEnv(), "keydata");
d_ttsig = std::make_shared<ttsig_t>(d_tdomains->getEnv(), "tsig");
declare(suffix, "filename", "Filename for lmdb", "./pdns.lmdb");
declare(suffix, "sync-mode", "Synchronisation mode: nosync, nometasync, mapasync, sync", "mapasync");
// there just is no room for more on 32 bit
- declare(suffix, "shards", "Records database will be split into this number of shards", (sizeof(long) == 4) ? "2" : "64");
+ declare(suffix, "shards", "Records database will be split into this number of shards", (sizeof(void*) == 4) ? "2" : "64");
declare(suffix, "schema-version", "Maximum allowed schema version to run on this DB. If a lower version is found, auto update is performed", std::to_string(SCHEMAVERSION));
declare(suffix, "random-ids", "Numeric IDs inside the database are generated randomly instead of sequentially", "no");
+ declare(suffix, "map-size", "LMDB map size in megabytes", (sizeof(void*) == 4) ? "100" : "16000");
}
DNSBackend* make(const string& suffix = "") override
{
class LMDBKVStore: public KeyValueStore
{
public:
- LMDBKVStore(const std::string& fname, const std::string& dbName, bool noLock=false): d_env(fname.c_str(), noLock ? MDB_NOSUBDIR|MDB_RDONLY|MDB_NOLOCK : MDB_NOSUBDIR|MDB_RDONLY, 0600), d_dbi(d_env.openDB(dbName, 0)), d_fname(fname), d_dbName(dbName)
+ LMDBKVStore(const std::string& fname, const std::string& dbName, bool noLock=false): d_env(fname.c_str(), noLock ? MDB_NOSUBDIR|MDB_RDONLY|MDB_NOLOCK : MDB_NOSUBDIR|MDB_RDONLY, 0600, 0), d_dbi(d_env.openDB(dbName, 0)), d_fname(fname), d_dbName(dbName)
{
}
string dbPath("/tmp/test_lmdb.XXXXXX");
{
- MDBEnv env(dbPath.c_str(), MDB_NOSUBDIR, 0600);
+ MDBEnv env(dbPath.c_str(), MDB_NOSUBDIR, 0600, 50);
auto transaction = env.getRWTransaction();
auto dbi = transaction->openDB("db-name", MDB_CREATE);
transaction->put(dbi, MDBInVal(std::string(reinterpret_cast<const char*>(&rem.sin4.sin_addr.s_addr), sizeof(rem.sin4.sin_addr.s_addr))), MDBInVal("this is the value for the remote addr"));
}
{
- MDBEnv env(dbPath.c_str(), MDB_NOSUBDIR, 0600);
+ MDBEnv env(dbPath.c_str(), MDB_NOSUBDIR, 0600, 50);
auto transaction = env.getRWTransaction();
auto dbi = transaction->openDB("range-db-name", MDB_CREATE);
/* range-based lookups */