]> granicus.if.org Git - pdns/commitdiff
dnsdist: Add an optional `seconds` parameter to `statNodeRespRing()`
authorRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 16 Dec 2016 15:51:12 +0000 (16:51 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 13 Jan 2017 14:43:10 +0000 (15:43 +0100)
By default `statNodeRespRing()` applies the visitor function to every
entry in the response rings. When passed a non-zero `seconds` parameter,
it will only apply it to entries added in the last `seconds` seconds.

pdns/dnsdist-lua2.cc
regression-tests.dnsdist/test_Advanced.py

index 2a2e5bb125fcf52b882da23e0427ef119dffd5e8..24797e6ea2bd29639a38900ca3caccf470883d9f 100644 (file)
@@ -84,12 +84,25 @@ map<ComboAddress,int> filterScore(const map<ComboAddress, unsigned int,ComboAddr
 
 typedef std::function<void(const StatNode&, const StatNode::Stat&, const StatNode::Stat&)> statvisitor_t;
 
-void statNodeRespRing(statvisitor_t visitor)
+static void statNodeRespRing(statvisitor_t visitor, unsigned int seconds)
 {
+  struct timespec cutoff, now;
+  gettime(&now);
+  if (seconds) {
+    cutoff = now;
+    cutoff.tv_sec -= seconds;
+  }
+
   std::lock_guard<std::mutex> lock(g_rings.respMutex);
   
   StatNode root;
   for(const auto& c : g_rings.respRing) {
+    if (now < c.when)
+      continue;
+
+    if (seconds && c.when < cutoff)
+      continue;
+
     root.submit(c.name, c.dh.rcode, c.requestor);
   }
   StatNode::Stat node;
@@ -355,7 +368,9 @@ void moreLua(bool client)
   g_lua.registerMember("nxdomains", &StatNode::Stat::nxdomains);
   g_lua.registerMember("queries", &StatNode::Stat::queries);
 
-  g_lua.writeFunction("statNodeRespRing", statNodeRespRing);
+  g_lua.writeFunction("statNodeRespRing", [](statvisitor_t visitor, boost::optional<unsigned int> seconds) {
+      statNodeRespRing(visitor, seconds ? *seconds : 0);
+    });
 
   g_lua.writeFunction("getTopBandwidth", [](unsigned int top) {
       setLuaNoSideEffect();
index c0ae43d81dfd34673de3414eaedc09c1fe4fbb98..eb35ed0a37d5b8b634d227c6534da56b538388be 100644 (file)
@@ -1,6 +1,8 @@
 #!/usr/bin/env python
+import base64
 from datetime import datetime, timedelta
 import os
+import string
 import time
 import dns
 from dnsdisttests import DNSDistTest
@@ -1243,3 +1245,88 @@ class TestAdvancedLuaDO(DNSDistTest):
         self.assertTrue(receivedResponse)
         doResponse.id = receivedResponse.id
         self.assertEquals(receivedResponse, doResponse)
+
+class TestStatNodeRespRingSince(DNSDistTest):
+
+    _consoleKey = DNSDistTest.generateConsoleKey()
+    _consoleKeyB64 = base64.b64encode(_consoleKey)
+    _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort']
+    _config_template = """
+    setKey("%s")
+    controlSocket("127.0.0.1:%s")
+    s1 = newServer{address="127.0.0.1:%s"}
+    s1:setUp()
+    function visitor(node, self, childstat)
+        table.insert(nodesSeen, node.fullname)
+    end
+    """
+
+    def testStatNodeRespRingSince(self):
+        """
+        Advanced: StatNodeRespRing with optional since parameter
+
+        """
+        name = 'statnodesince.advanced.tests.powerdns.com.'
+        query = dns.message.make_query(name, 'A', 'IN')
+        response = dns.message.make_response(query)
+        rrset = dns.rrset.from_text(name,
+                                    1,
+                                    dns.rdataclass.IN,
+                                    dns.rdatatype.A,
+                                    '127.0.0.1')
+        response.answer.append(rrset)
+
+        (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
+        self.assertTrue(receivedQuery)
+        self.assertTrue(receivedResponse)
+        receivedQuery.id = query.id
+        self.assertEquals(query, receivedQuery)
+        self.assertEquals(response, receivedResponse)
+
+        self.sendConsoleCommand("nodesSeen = {}")
+        self.sendConsoleCommand("statNodeRespRing(visitor)")
+        nodes = self.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str")
+        nodes = string.strip(nodes, "\n")
+        self.assertEquals(nodes, """statnodesince.advanced.tests.powerdns.com.
+advanced.tests.powerdns.com.
+tests.powerdns.com.
+powerdns.com.
+com.""")
+
+        self.sendConsoleCommand("nodesSeen = {}")
+        self.sendConsoleCommand("statNodeRespRing(visitor, 0)")
+        nodes = self.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str")
+        nodes = string.strip(nodes, "\n")
+        self.assertEquals(nodes, """statnodesince.advanced.tests.powerdns.com.
+advanced.tests.powerdns.com.
+tests.powerdns.com.
+powerdns.com.
+com.""")
+
+        time.sleep(5)
+
+        self.sendConsoleCommand("nodesSeen = {}")
+        self.sendConsoleCommand("statNodeRespRing(visitor)")
+        nodes = self.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str")
+        nodes = string.strip(nodes, "\n")
+        self.assertEquals(nodes, """statnodesince.advanced.tests.powerdns.com.
+advanced.tests.powerdns.com.
+tests.powerdns.com.
+powerdns.com.
+com.""")
+
+        self.sendConsoleCommand("nodesSeen = {}")
+        self.sendConsoleCommand("statNodeRespRing(visitor, 5)")
+        nodes = self.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str")
+        nodes = string.strip(nodes, "\n")
+        self.assertEquals(nodes, """""")
+
+        self.sendConsoleCommand("nodesSeen = {}")
+        self.sendConsoleCommand("statNodeRespRing(visitor, 10)")
+        nodes = self.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str")
+        nodes = string.strip(nodes, "\n")
+        self.assertEquals(nodes, """statnodesince.advanced.tests.powerdns.com.
+advanced.tests.powerdns.com.
+tests.powerdns.com.
+powerdns.com.
+com.""")