});
d_lw->registerFunction<void (DNSRecord::*)(const std::string&)>("changeContent", [](DNSRecord& dr, const std::string& newContent) { dr.setContent(shared_ptr<DNSRecordContent>(DNSRecordContent::make(dr.d_type, 1, newContent))); });
- // pdnsload
+ // pdnslog
+#ifdef RECURSOR
d_lw->writeFunction("pdnslog", [](const std::string& msg, boost::optional<int> loglevel, boost::optional<std::map<std::string, std::string>> values) {
auto log = g_slog->withName("lua");
if (values) {
}
}
log->info(static_cast<Logr::Priority>(loglevel.get_value_or(Logr::Warning)), msg);
+#else
+ d_lw->writeFunction("pdnslog", [](const std::string& msg, boost::optional<int> loglevel) {
+ g_log << (Logger::Urgency)loglevel.get_value_or(Logger::Warning) << msg<<endl;
+#endif
});
d_lw->writeFunction("pdnsrandom", [](boost::optional<uint32_t> maximum) {
:param str script: The pathname of the Lua script to run.
+.. note::
+ The :func:`putIntoRecordCache` and :func:`getRecordCacheRecords` functions are experimental, their functionality might change in upcoming releases.
+
.. function:: putIntoRecordCache(dump) -> int
.. versionadded:: 5.2.0
Some records might be skipped, for example when they are already present in the record cache or contain specific information not supported yet by this function.
If the :program:`Recursor` determines the version of the data is not compatible, it will skip loading and log an error.
-.. function:: getRecordCacheRecords(perShard, maxSize) ->str
+.. function:: getRecordCacheRecords(perShard, maxSize) -> str, int
.. versionadded:: 5.2.0
Get a record cache dump in proprietary format.
- :param int perShard: The maximum number of records to produce per shard.
+ :param int perShard: The maximum number of records to retrieve per shard.
:param int maxSize: The maximum size of the dump.
- :return: A string representing the records.
+ :return: A string representing the records and an integer specifying how many records were retrieved
This function will scan the most recently used records of each shard, picking at most ``perShard`` records per shard and adding them to the result.
If adding a record's data to the result would make the result size exceed ``maxSize``, the remainder of the current shard and further remaining shards are skipped.
The format of the string produced is proprietary.
The string contains meta information, so the :program:`Recursor` calling :func:`putIntoRecordCache` can check if the data format is compatible.
+
d_lw->writeFunction("getRecordCacheRecords", [](size_t perShard, size_t maxSize) {
std::string ret;
- g_recCache->getRecords(perShard, maxSize, ret);
- return ret;
+ auto number = g_recCache->getRecords(perShard, maxSize, ret);
+ return std::tuple<std::string, size_t>{ret, number};
});
d_lw->writeFunction("putIntoRecordCache", [](const string& data) {
});
d_lw->writeFunction("spawnThread", [](const string& scriptName) {
- auto log = g_slog->withName("lua")->withValues("name", Logging::Loggable(scriptName));
- log->info(Logr::Info, "Starting Lua thread");
+ auto log = g_slog->withName("lua")->withValues("script", Logging::Loggable(scriptName));
+ log->info(Logr::Info, "Starting Lua script in separate thread");
std::thread thread([=]() {
auto lua = std::make_shared<RecursorLua4>();
lua->loadFile(scriptName);
features.emplace_back("PR8001_devicename", true);
}
+void RecursorLua4::runStartStopFunction(const string& script, bool start, Logr::log_t log)
+{
+ const string func = start ? "on_recursor_start" : "on_recursor_stop";
+ auto mylog = log->withValues("script", Logging::Loggable(script), "function", Logging::Loggable(func));
+ loadFile(script);
+ auto call = d_lw->readVariable<boost::optional<std::function<void()>>>(func).get_value_or(nullptr);
+ if (call) {
+ mylog->info(Logr::Info, "Starting Lua function");
+ call();
+ mylog->info(Logr::Info, "Lua function done");
+ }
+ else {
+ mylog->info(Logr::Info, "No Lua function found");
+ }
+}
+
static void warnDrop(const RecursorLua4::DNSQuestion& dnsQuestion)
{
if (dnsQuestion.rcode == -2) {
bool policyHitEventFilter(const ComboAddress& remote, const DNSName& qname, const QType& qtype, bool tcp, DNSFilterEngine::Policy& policy, std::unordered_set<std::string>& tags, std::unordered_map<std::string, bool>& discardedPolicies) const;
+ void runStartStopFunction(const std::string& script, bool start, Logr::log_t log);
+
[[nodiscard]] bool needDQ() const
{
return (d_prerpz || d_preresolve || d_nxdomain || d_nodata || d_postresolve);
pdns::RateLimitedLog g_rateLimitedLogger;
-static void runCustomLua(Logr::log_t log);
+static void runStartStopLua(bool start, Logr::log_t log);
static std::map<unsigned int, std::set<int>> parseCPUMap(Logr::log_t log)
{
ret = tInfo.exitCode;
}
}
+ runStartStopLua(false, log);
}
return ret;
}
setupNODThread(log);
#endif /* NOD_ENABLED */
- runCustomLua(log);
-
+ runStartStopLua(true, log);
+
return RecThreadInfo::runThreads(log);
}
LockGuarded<pdns::rust::settings::rec::Recursorsettings> g_yamlStruct;
-static void runCustomLua(Logr::log_t log)
+static void runStartStopLua(bool start, Logr::log_t log)
{
auto settings = g_yamlStruct.lock();
- const auto& script = settings->recursor.lua_startup_script;
+ const auto& script = settings->recursor.lua_start_stop_script;
if (script.empty()) {
return;
}
- log->info(Logr::Info, "Starting Custom Lua", "script", Logging::Loggable(script));
- //std::thread thread([=]() {
- auto lua = std::make_shared<RecursorLua4>();
- lua->loadFile(std::string(script));
- log->info(Logr::Info, "Custom Lua done");
- //});
- //thread.detach();
+ auto lua = std::make_shared<RecursorLua4>();
+ lua->runStartStopFunction(std::string(script), start, log);
}
static void handleRuntimeDefaults(Logr::log_t log)
message.add_bool(PBCacheEntry::required_bool_tooBig, recordSet->d_tooBig);
}
-void MemRecursorCache::getRecords(size_t perShard, size_t maxSize, std::string& ret)
+size_t MemRecursorCache::getRecords(size_t perShard, size_t maxSize, std::string& ret)
{
auto log = g_slog->withName("recordcache")->withValues("perShard", Logging::Loggable(perShard), "maxSize", Logging::Loggable(maxSize));
log->info(Logr::Info, "Producing cache dump");
if (ret.size() > maxSize) {
message.rollback();
log->info(Logr::Info, "Produced cache dump (max size reached)", "size", Logging::Loggable(ret.size()), "count", Logging::Loggable(count));
- return;
+ return count;
}
++count;
++thisShardCount;
}
}
log->info(Logr::Info, "Produced cache dump", "size", Logging::Loggable(ret.size()), "count", Logging::Loggable(count));
- std::ofstream out("/tmp/pb");
- out.write(ret.data(), ret.size());
+ return count;
}
template <typename T>
[[nodiscard]] pair<uint64_t, uint64_t> stats();
[[nodiscard]] size_t ecsIndexSize();
- void getRecords(size_t howmany, size_t maxsize, std::string& ret);
+ size_t getRecords(size_t howmany, size_t maxsize, std::string& ret);
size_t putRecords(const std::string& pbuf);
using OptTag = boost::optional<std::string>;
'versionadded': '5.1.0',
},
{
- 'name' : 'lua_startup_script',
+ 'name' : 'lua_start_stop_script',
'section' : 'recursor',
'type' : LType.String,
'default' : '',
- 'help' : 'Custom Lua script to run on startup',
+ 'help' : 'Lua script containing functions to run on startup and shutdown',
'doc' : '''
-Run this Lua script on startup in a separate thread.
+Load this Lua script on startup and shutdown and run the Lua function ``on_recursor_start`` on startup and the Lua function ``on_recursor_stop`` on a ``nice`` shutdown (using ``rec_control quit-nicely`` of the :program:`Recursor` process.
''',
'skip-old' : 'No equivalent old-style setting',
'versionadded': '5.2.0',