This setting is also available in version 4.9.9.
**Warning**: Running with this flag disabled will cause spurious notifications
-to be sent upon startup.
+to be sent upon startup, unless a ``flush'' command is sent using
+:doc:`pdns_control <../manpages/pdns_control.1>` before stopping the
+PowerDNS Authoritative Server.
``lmdb-lightning-stream``
^^^^^^^^^^^^^^^^^^^^^^^^^
Restart the nameserver so it reloads its configuration. Only works
when the server is running in guardian mode.
+flush
+^^^^^
+
+Flush all backend data to stable storage.
+There is usually no such data during regular operation, unless the LMDB backend
+is used with :ref:`setting-lmdb-write-notification-update` set to ``no``.
+
list
^^^^
}
// Serial number cache
+
+// Retrieve the serial number entry for the given domain, if any
bool LMDBBackend::SerialCache::get(domainid_t domainid, uint32_t& serial) const
{
if (auto iter = d_serials.find(domainid); iter != d_serials.end()) {
return false;
}
+// Remove the serial number entry for the given domain
void LMDBBackend::SerialCache::remove(domainid_t domainid)
{
if (auto iter = d_serials.find(domainid); iter != d_serials.end()) {
}
}
+// Create or update the serial number entry for the given domain
void LMDBBackend::SerialCache::update(domainid_t domainid, uint32_t serial)
{
d_serials.insert_or_assign(domainid, serial);
}
+// Return the contents of the first element and remove it
+bool LMDBBackend::SerialCache::pop(domainid_t& domainid, uint32_t& serial)
+{
+ auto iter = d_serials.begin();
+ if (iter == d_serials.end()) {
+ return false;
+ }
+ domainid = iter->first;
+ serial = iter->second;
+ (void)d_serials.erase(iter);
+ return true;
+}
+
SharedLockGuarded<LMDBBackend::SerialCache> LMDBBackend::s_notified_serial;
LMDBBackend::LMDBBackend(const std::string& suffix)
LMDBBackend::deleteDomainRecords(*d_rwtxn, order(domain_id), QType::NSEC3);
}
+void LMDBBackend::flush()
+{
+ if (d_write_notification_update) {
+ return; // no data needs to be synchronized
+ }
+
+ // We flush in chunks of 10 domains, in order not to keep the serial number
+ // cache locked for too long.
+ while (true) {
+ unsigned int done = 0;
+ auto container = s_notified_serial.write_lock();
+ for (; done < 10; ++done) {
+ domainid_t domid{};
+ uint32_t serial{};
+ if (!container->pop(domid, serial)) {
+ break;
+ }
+ DomainInfo info;
+ if (findDomain(domid, info)) {
+ info.notified_serial = serial;
+ auto txn = d_tdomains->getRWTransaction();
+ txn.put(info, info.id);
+ txn.commit();
+ }
+ else {
+ // Domain has been removed. This should not happen because deletion
+ // is supposed to take care of removing the entry here too.
+ // Is it worth logging something here?
+ }
+ }
+ if (done == 0) {
+ break; // no more work to do!
+ }
+ }
+}
+
class LMDBFactory : public BackendFactory
{
public:
bool updateEmptyNonTerminals(domainid_t domain_id, set<DNSName>& insert, set<DNSName>& erase, bool remove) override;
+ void flush() override;
+
// other
string directBackendCmd(const string& query) override;
bool get(domainid_t domainid, uint32_t& serial) const;
void remove(domainid_t domainid);
void update(domainid_t domainid, uint32_t serial);
+ bool pop(domainid_t& domainid, uint32_t& serial);
private:
std::unordered_map<domainid_t, uint32_t> d_serials;
DynListener::registerExitFunc("QUIT", &DLRQuitHandler);
DynListener::registerFunc("CCOUNTS", &DLCCHandler, "get cache statistics");
DynListener::registerFunc("CURRENT-CONFIG", &DLCurrentConfigHandler, "retrieve the current configuration", "[diff]");
+ DynListener::registerFunc("FLUSH", &DLFlushHandler, "flush backend data");
DynListener::registerFunc("LIST-ZONES", &DLListZones, "show list of zones", "[primary|secondary|native|consumer|producer]");
DynListener::registerFunc("NOTIFY", &DLNotifyHandler, "queue a notification", "<zone>");
DynListener::registerFunc("NOTIFY-HOST", &DLNotifyHostHandler, "notify host for specific zone", "<zone> <host>");
return get(rec);
}
+ virtual void flush()
+ {
+ }
+
protected:
bool mustDo(const string& key);
const string& getArg(const string& key);
return ret.str();
}
+string DLFlushHandler(const vector<string>& /*parts*/, Utility::pid_t /*ppid*/)
+{
+ UeberBackend B; // NOLINT(readability-identifier-length)
+ B.flush();
+ g_log<<Logger::Error<<"Backend flush was requested"<<endl;
+ return "Ok";
+}
+
#ifdef HAVE_P11KIT1
extern bool PKCS11ModuleSlotLogin(const std::string& module, const string& tokenId, const std::string& pin);
#endif
void setStatus(const string &str);
string DLCCHandler(const vector<string>&parts, Utility::pid_t ppid);
string DLCurrentConfigHandler(const vector<string>&parts, Utility::pid_t ppid);
+string DLFlushHandler(const vector<string>&parts, Utility::pid_t ppid);
string DLListZones(const vector<string>&parts, Utility::pid_t ppid);
string DLNotifyHandler(const vector<string>&parts, Utility::pid_t ppid);
string DLNotifyHostHandler(const vector<string>&parts, Utility::pid_t ppid);
return capabilities;
}
+void UeberBackend::flush()
+{
+ for (auto& backend : backends) {
+ backend->flush();
+ }
+}
+
AtomicCounter UeberBackend::handle::instances(0);
UeberBackend::handle::handle()
unsigned int getCapabilities();
+ void flush();
+
private:
handle d_handle;
vector<DNSZoneRecord> d_answers;