From 03b0091753ce38ad0251097fa59550ddc4befaf4 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Tue, 20 Mar 2018 10:36:19 +0100 Subject: [PATCH] dnsdist: Move the rings declaration to a separate header file --- pdns/dnsdist-dynblocks.hh | 25 +++-- pdns/dnsdist-lua-inspection.cc | 1 + pdns/dnsdist-lua.cc | 1 + pdns/dnsdist-rings.cc | 4 +- pdns/dnsdist-rings.hh | 160 ++++++++++++++++++++++++++++++ pdns/dnsdist-tcp.cc | 2 + pdns/dnsdist.cc | 1 + pdns/dnsdist.hh | 128 ------------------------ pdns/dnsdistdist/Makefile.am | 2 +- pdns/dnsdistdist/dnsdist-rings.hh | 1 + 10 files changed, 184 insertions(+), 141 deletions(-) create mode 100644 pdns/dnsdist-rings.hh create mode 120000 pdns/dnsdistdist/dnsdist-rings.hh diff --git a/pdns/dnsdist-dynblocks.hh b/pdns/dnsdist-dynblocks.hh index 3613b2e98..5b70b4240 100644 --- a/pdns/dnsdist-dynblocks.hh +++ b/pdns/dnsdist-dynblocks.hh @@ -22,6 +22,7 @@ #pragma once #include "dolog.hh" +#include "dnsdist-rings.hh" class DynBlockRulesGroup { @@ -123,12 +124,16 @@ public: size_t entriesCount = 0; if (hasQueryRules()) { - ReadLock rl(&g_rings.queryLock); - entriesCount += g_rings.queryRing.size(); + for (const auto& shard : g_rings.d_shards) { + std::lock_guard rl(shard->queryLock); + entriesCount += shard->queryRing.size(); + } } if (hasResponseRules()) { - std::lock_guard lock(g_rings.respMutex); - entriesCount += g_rings.respRing.size(); + for (const auto& shard : g_rings.d_shards) { + std::lock_guard rl(shard->respLock); + entriesCount += shard->respRing.size(); + } } counts.reserve(entriesCount); @@ -263,9 +268,9 @@ private: rule.second.d_cutOff.tv_sec -= rule.second.d_seconds; } - { - ReadLock rl(&g_rings.queryLock); - for(const auto& c : g_rings.queryRing) { + for (const auto& shard : g_rings.d_shards) { + std::lock_guard rl(shard->queryLock); + for(const auto& c : shard->queryRing) { if (now < c.when) { continue; } @@ -302,9 +307,9 @@ private: rule.second.d_cutOff.tv_sec -= rule.second.d_seconds; } - { - std::lock_guard lock(g_rings.respMutex); - for(const auto& c : g_rings.respRing) { + for (const auto& shard : g_rings.d_shards) { + std::lock_guard rl(shard->respLock); + for(const auto& c : shard->respRing) { if (now < c.when) { continue; } diff --git a/pdns/dnsdist-lua-inspection.cc b/pdns/dnsdist-lua-inspection.cc index 74aeff321..ad58203ed 100644 --- a/pdns/dnsdist-lua-inspection.cc +++ b/pdns/dnsdist-lua-inspection.cc @@ -22,6 +22,7 @@ #include "dnsdist.hh" #include "dnsdist-lua.hh" #include "dnsdist-dynblocks.hh" +#include "dnsdist-rings.hh" #include "statnode.hh" diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index 0198ef216..5e4356cf8 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -31,6 +31,7 @@ #include "dnsdist.hh" #include "dnsdist-console.hh" #include "dnsdist-lua.hh" +#include "dnsdist-rings.hh" #include "base64.hh" #include "dnswriter.hh" diff --git a/pdns/dnsdist-rings.cc b/pdns/dnsdist-rings.cc index 4288cd05c..8f8ab0ddb 100644 --- a/pdns/dnsdist-rings.cc +++ b/pdns/dnsdist-rings.cc @@ -19,8 +19,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "dnsdist.hh" -#include "lock.hh" + +#include "dnsdist-rings.hh" size_t Rings::numDistinctRequestors() { diff --git a/pdns/dnsdist-rings.hh b/pdns/dnsdist-rings.hh new file mode 100644 index 000000000..71e295ddd --- /dev/null +++ b/pdns/dnsdist-rings.hh @@ -0,0 +1,160 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once + +#include +#include +#include + +#include +#include + +#include "dnsname.hh" +#include "iputils.hh" + + +struct Rings { + struct Query + { + struct timespec when; + ComboAddress requestor; + DNSName name; + uint16_t size; + uint16_t qtype; + struct dnsheader dh; + }; + struct Response + { + struct timespec when; + ComboAddress requestor; + DNSName name; + uint16_t qtype; + unsigned int usec; + unsigned int size; + struct dnsheader dh; + ComboAddress ds; // who handled it + }; + + struct Shard + { + boost::circular_buffer queryRing; + boost::circular_buffer respRing; + std::mutex queryLock; + std::mutex respLock; + }; + + Rings(size_t capacity=10000, size_t numberOfShards=1, size_t nbLockTries=5): d_numberOfShards(numberOfShards), d_nbLockTries(nbLockTries) + { + setCapacity(capacity, numberOfShards); + if (numberOfShards <= 1) { + d_nbLockTries = 0; + } + } + std::unordered_map > > getTopBandwidth(unsigned int numentries); + size_t numDistinctRequestors(); + void setCapacity(size_t newCapacity, size_t numberOfShards) + { + if (numberOfShards < d_numberOfShards) { + throw std::runtime_error("Decreasing the number of shards in the query and response rings is not supported"); + } + + d_shards.resize(numberOfShards); + d_numberOfShards = numberOfShards; + + /* resize all the rings */ + for (size_t idx = 0; idx < numberOfShards; idx++) { + d_shards[idx] = std::unique_ptr(new Shard()); + { + std::lock_guard wl(d_shards[idx]->queryLock); + d_shards[idx]->queryRing.set_capacity(newCapacity / numberOfShards); + } + { + std::lock_guard wl(d_shards[idx]->respLock); + d_shards[idx]->respRing.set_capacity(newCapacity / numberOfShards); + } + } + } + + void setNumberOfLockRetries(size_t retries) + { + if (d_numberOfShards <= 1) { + d_nbLockTries = 0; + } else { + d_nbLockTries = retries; + } + } + + size_t getNumberOfShards() const + { + return d_numberOfShards; + } + + void insertQuery(const struct timespec& when, const ComboAddress& requestor, const DNSName& name, uint16_t qtype, uint16_t size, const struct dnsheader& dh) + { + for (size_t idx = 0; idx < d_nbLockTries; idx++) { + auto shardId = getShardId(); + std::unique_lock wl(d_shards[shardId]->queryLock, std::try_to_lock); + if (wl.owns_lock()) { + d_shards[shardId]->queryRing.push_back({when, requestor, name, size, qtype, dh}); + return; + } + } + + /* out of luck, let's just wait */ + auto shardId = getShardId(); + std::lock_guard wl(d_shards[shardId]->queryLock); + d_shards[shardId]->queryRing.push_back({when, requestor, name, size, qtype, dh}); + } + + void insertResponse(const struct timespec& when, const ComboAddress& requestor, const DNSName& name, uint16_t qtype, unsigned int usec, unsigned int size, const struct dnsheader& dh, const ComboAddress& backend) + { + for (size_t idx = 0; idx < d_nbLockTries; idx++) { + auto shardId = getShardId(); + std::unique_lock wl(d_shards[shardId]->respLock, std::try_to_lock); + if (wl.owns_lock()) { + d_shards[shardId]->respRing.push_back({when, requestor, name, qtype, usec, size, dh, backend}); + return; + } + } + + /* out of luck, let's just wait */ + auto shardId = getShardId(); + std::lock_guard wl(d_shards[shardId]->respLock); + d_shards[shardId]->respRing.push_back({when, requestor, name, qtype, usec, size, dh, backend}); + } + + std::vector > d_shards; + +private: + size_t getShardId() + { + return (d_currentShardId++ % d_numberOfShards); + } + + std::atomic d_currentShardId; + + size_t d_numberOfShards; + size_t d_nbLockTries = 5; + +}; + +extern Rings g_rings; diff --git a/pdns/dnsdist-tcp.cc b/pdns/dnsdist-tcp.cc index b81638477..b94fb6b98 100644 --- a/pdns/dnsdist-tcp.cc +++ b/pdns/dnsdist-tcp.cc @@ -21,6 +21,8 @@ */ #include "dnsdist.hh" #include "dnsdist-ecs.hh" +#include "dnsdist-rings.hh" + #include "dnsparser.hh" #include "ednsoptions.hh" #include "dolog.hh" diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index 0381723c5..e3d1a7299 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -46,6 +46,7 @@ #include "dnsdist-console.hh" #include "dnsdist-ecs.hh" #include "dnsdist-lua.hh" +#include "dnsdist-rings.hh" #include "base64.hh" #include "delaypipe.hh" diff --git a/pdns/dnsdist.hh b/pdns/dnsdist.hh index a956eeb23..601d79109 100644 --- a/pdns/dnsdist.hh +++ b/pdns/dnsdist.hh @@ -28,7 +28,6 @@ #include "iputils.hh" #include "dnsname.hh" #include -#include #include #include #include @@ -375,133 +374,6 @@ struct IDState bool destHarvested{false}; // if true, origDest holds the original dest addr, otherwise the listening addr }; -struct Rings { - struct Query - { - struct timespec when; - ComboAddress requestor; - DNSName name; - uint16_t size; - uint16_t qtype; - struct dnsheader dh; - }; - struct Response - { - struct timespec when; - ComboAddress requestor; - DNSName name; - uint16_t qtype; - unsigned int usec; - unsigned int size; - struct dnsheader dh; - ComboAddress ds; // who handled it - }; - - struct Shard - { - boost::circular_buffer queryRing; - boost::circular_buffer respRing; - std::mutex queryLock; - std::mutex respLock; - }; - - Rings(size_t capacity=10000, size_t numberOfShards=1, size_t nbLockTries=5): d_numberOfShards(numberOfShards), d_nbLockTries(nbLockTries) - { - setCapacity(capacity, numberOfShards); - if (numberOfShards <= 1) { - d_nbLockTries = 0; - } - } - std::unordered_map > > getTopBandwidth(unsigned int numentries); - size_t numDistinctRequestors(); - void setCapacity(size_t newCapacity, size_t numberOfShards) - { - if (numberOfShards < d_numberOfShards) { - throw std::runtime_error("Decreasing the number of shards in the query and response rings is not supported"); - } - - d_shards.resize(numberOfShards); - d_numberOfShards = numberOfShards; - - /* resize all the rings */ - for (size_t idx = 0; idx < numberOfShards; idx++) { - d_shards[idx] = std::unique_ptr(new Shard()); - { - std::lock_guard wl(d_shards[idx]->queryLock); - d_shards[idx]->queryRing.set_capacity(newCapacity / numberOfShards); - } - { - std::lock_guard wl(d_shards[idx]->respLock); - d_shards[idx]->respRing.set_capacity(newCapacity / numberOfShards); - } - } - } - - void setNumberOfLockRetries(size_t retries) - { - if (d_numberOfShards <= 1) { - d_nbLockTries = 0; - } else { - d_nbLockTries = retries; - } - } - - size_t getNumberOfShards() const - { - return d_numberOfShards; - } - - void insertQuery(const struct timespec& when, const ComboAddress& requestor, const DNSName& name, uint16_t qtype, uint16_t size, const struct dnsheader& dh) - { - for (size_t idx = 0; idx < d_nbLockTries; idx++) { - auto shardId = getShardId(); - std::unique_lock wl(d_shards[shardId]->queryLock, std::try_to_lock); - if (wl.owns_lock()) { - d_shards[shardId]->queryRing.push_back({when, requestor, name, size, qtype, dh}); - return; - } - } - - /* out of luck, let's just wait */ - auto shardId = getShardId(); - std::lock_guard wl(d_shards[shardId]->queryLock); - d_shards[shardId]->queryRing.push_back({when, requestor, name, size, qtype, dh}); - } - - void insertResponse(const struct timespec& when, const ComboAddress& requestor, const DNSName& name, uint16_t qtype, unsigned int usec, unsigned int size, const struct dnsheader& dh, const ComboAddress& backend) - { - for (size_t idx = 0; idx < d_nbLockTries; idx++) { - auto shardId = getShardId(); - std::unique_lock wl(d_shards[shardId]->respLock, std::try_to_lock); - if (wl.owns_lock()) { - d_shards[shardId]->respRing.push_back({when, requestor, name, qtype, usec, size, dh, backend}); - return; - } - } - - /* out of luck, let's just wait */ - auto shardId = getShardId(); - std::lock_guard wl(d_shards[shardId]->respLock); - d_shards[shardId]->respRing.push_back({when, requestor, name, qtype, usec, size, dh, backend}); - } - - std::vector > d_shards; - -private: - size_t getShardId() - { - return (d_currentShardId++ % d_numberOfShards); - } - - std::atomic d_currentShardId; - - size_t d_numberOfShards; - size_t d_nbLockTries = 5; - -}; - -extern Rings g_rings; - typedef std::unordered_map QueryCountRecords; typedef std::function(DNSQuestion dq)> QueryCountFilter; struct QueryCount { diff --git a/pdns/dnsdistdist/Makefile.am b/pdns/dnsdistdist/Makefile.am index 3089bed9a..be6bd927b 100644 --- a/pdns/dnsdistdist/Makefile.am +++ b/pdns/dnsdistdist/Makefile.am @@ -98,7 +98,7 @@ dnsdist_SOURCES = \ dnsdist-lua-rules.cc \ dnsdist-lua-vars.cc \ dnsdist-protobuf.cc dnsdist-protobuf.hh \ - dnsdist-rings.cc \ + dnsdist-rings.cc dnsdist-rings.hh \ dnsdist-snmp.cc dnsdist-snmp.hh \ dnsdist-tcp.cc \ dnsdist-web.cc \ diff --git a/pdns/dnsdistdist/dnsdist-rings.hh b/pdns/dnsdistdist/dnsdist-rings.hh new file mode 120000 index 000000000..4c33d6dbb --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-rings.hh @@ -0,0 +1 @@ +../dnsdist-rings.hh \ No newline at end of file -- 2.40.0