]> granicus.if.org Git - pdns/commitdiff
dnsdist: Add the ability to dump a summary of the cache content
authorRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 22 Jun 2018 07:49:37 +0000 (09:49 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 22 Jun 2018 07:49:37 +0000 (09:49 +0200)
pdns/dnsdist-cache.cc
pdns/dnsdist-cache.hh
pdns/dnsdist-lua-bindings.cc
pdns/dnsdistdist/docs/reference/config.rst

index 50703e28c8f3984063cc571196345db55ca1bdde..6435ae322f0b990af2d80a9cabe22c3f1f77a7fd 100644 (file)
@@ -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<int64_t>(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;
+}
index daeabc6f61fd0e2547050b907603b565979d647d..1c4d54edca9151d7ba885832f4a80c3aac505679 100644 (file)
@@ -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);
 
index f5229184b227dfd76e81b8a07789d2d7dcf891ca..5221d6e5cc4ea2693b220a0697f43eb2c601fc43 100644 (file)
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
 #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<void(std::shared_ptr<DNSDistPacketCache>::*)(const std::string& fname)>("dump", [](const std::shared_ptr<DNSDistPacketCache> 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<void(DNSDistProtoBufMessage::*)(std::string)>("setTag", [](DNSDistProtoBufMessage& message, const std::string& strValue) {
index 5d12abd5b882589773901850aae5873750b405da..8f92380bec26d28e97b1a25823a17e94b9eb288b 100644 (file)
@@ -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