From: Remi Gacogne Date: Fri, 22 Jun 2018 07:49:37 +0000 (+0200) Subject: dnsdist: Add the ability to dump a summary of the cache content X-Git-Tag: dnsdist-1.3.1~14^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f037144cc2520de845c2b07c6480b696eb787ac7;p=pdns dnsdist: Add the ability to dump a summary of the cache content --- diff --git a/pdns/dnsdist-cache.cc b/pdns/dnsdist-cache.cc index 50703e28c..6435ae322 100644 --- a/pdns/dnsdist-cache.cc +++ b/pdns/dnsdist-cache.cc @@ -160,6 +160,7 @@ bool DNSDistPacketCache::get(const DNSQuestion& dq, uint16_t consumed, uint16_t { std::string dnsQName(dq.qname->toDNSString()); uint32_t key = getKey(dnsQName, consumed, (const unsigned char*)dq.dh, dq.len, dq.tcp); + if (keyOut) *keyOut = key; @@ -383,3 +384,35 @@ uint64_t DNSDistPacketCache::getEntriesCount() { return getSize(); } + +uint64_t DNSDistPacketCache::dump(int fd) +{ + FILE * fp = fdopen(dup(fd), "w"); + if (fp == nullptr) { + return 0; + } + + fprintf(fp, "; dnsdist's packet cache dump follows\n;\n"); + + uint64_t count = 0; + time_t now = time(nullptr); + for (uint32_t shardIndex = 0; shardIndex < d_shardCount; shardIndex++) { + ReadLock w(&d_shards.at(shardIndex).d_lock); + auto& map = d_shards[shardIndex].d_map; + + for(const auto entry : map) { + const CacheValue& value = entry.second; + count++; + + try { + fprintf(fp, "%s %" PRId64 " %s ; key %" PRIu32 ", length %" PRIu16 ", tcp %d, added %" PRIu64 "\n", value.qname.toString().c_str(), static_cast(value.validity - now), QType(value.qtype).getName().c_str(), entry.first, value.len, value.tcp, value.added); + } + catch(...) { + fprintf(fp, "; error printing '%s'\n", value.qname.empty() ? "EMPTY" : value.qname.toString().c_str()); + } + } + } + + fclose(fp); + return count; +} diff --git a/pdns/dnsdist-cache.hh b/pdns/dnsdist-cache.hh index daeabc6f6..1c4d54edc 100644 --- a/pdns/dnsdist-cache.hh +++ b/pdns/dnsdist-cache.hh @@ -50,6 +50,7 @@ public: uint64_t getMaxEntries() const { return d_maxEntries; } uint64_t getTTLTooShorts() const { return d_ttlTooShorts; } uint64_t getEntriesCount(); + uint64_t dump(int fd); static uint32_t getMinTTL(const char* packet, uint16_t length); diff --git a/pdns/dnsdist-lua-bindings.cc b/pdns/dnsdist-lua-bindings.cc index f5229184b..5221d6e5c 100644 --- a/pdns/dnsdist-lua-bindings.cc +++ b/pdns/dnsdist-lua-bindings.cc @@ -19,6 +19,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include +#include +#include + #include "dnsdist.hh" #include "dnsdist-lua.hh" #include "dnsdist-protobuf.hh" @@ -240,6 +244,29 @@ void setupLuaBindings(bool client) g_outputBuffer+="TTL Too Shorts: " + std::to_string(cache->getTTLTooShorts()) + "\n"; } }); + g_lua.registerFunction::*)(const std::string& fname)>("dump", [](const std::shared_ptr cache, const std::string& fname) { + if (cache) { + + int fd = open(fname.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0660); + if (fd < 0) { + g_outputBuffer = "Error opening dump file for writing: " + string(strerror(errno)) + "\n"; + return; + } + + uint64_t records = 0; + try { + records = cache->dump(fd); + } + catch (const std::exception& e) { + close(fd); + throw; + } + + close(fd); + + g_outputBuffer += "Dumped " + std::to_string(records) + " records\n"; + } + }); /* ProtobufMessage */ g_lua.registerFunction("setTag", [](DNSDistProtoBufMessage& message, const std::string& strValue) { diff --git a/pdns/dnsdistdist/docs/reference/config.rst b/pdns/dnsdistdist/docs/reference/config.rst index 5d12abd5b..8f92380be 100644 --- a/pdns/dnsdistdist/docs/reference/config.rst +++ b/pdns/dnsdistdist/docs/reference/config.rst @@ -526,6 +526,14 @@ See :doc:`../guides/cache` for a how to. Represents a cache that can be part of :class:`ServerPool`. + .. method:: PacketCache:dump(fname) + + .. versionadded:: 1.3.1 + + Dump a summary of the cache entries to a file. + + :param str fname: The path to a file where the cache summary should be dumped. Note that if the target file already exists, it will not be overwritten. + .. method:: PacketCache:expunge(n) Remove entries from the cache, leaving at most ``n`` entries