From: Remi Gacogne Date: Mon, 18 Apr 2016 14:13:51 +0000 (+0200) Subject: dnsdist: Make `topBandwidth()` behave like other top* functions X-Git-Tag: dnsdist-1.0.0~2^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7fc0093781f4c98dec8d5ba32731bee251f1ac24;p=pdns dnsdist: Make `topBandwidth()` behave like other top* functions Fixes #3521. --- diff --git a/pdns/dnsdist-lua2.cc b/pdns/dnsdist-lua2.cc index 18be93099..2b5f42043 100644 --- a/pdns/dnsdist-lua2.cc +++ b/pdns/dnsdist-lua2.cc @@ -221,15 +221,11 @@ void moreLua(bool client) }); - g_lua.writeFunction("topBandwidth", [](boost::optional top_) { + g_lua.writeFunction("getTopBandwidth", [](unsigned int top) { setLuaNoSideEffect(); - auto top = top_.get_value_or(10); - auto res = g_rings.getTopBandwidth(top); - boost::format fmt("%7d %s\n"); - for(const auto& l : res) { - g_outputBuffer += (fmt % l.first % l.second.toString()).str(); - } + return g_rings.getTopBandwidth(top); }); + g_lua.executeCode(R"(function topBandwidth(top) top = top or 10; for k,v in ipairs(getTopBandwidth(top)) do show(string.format("%4d %-40s %4d %4.1f%%",k,v[1],v[2],v[3])) end end)"); g_lua.writeFunction("delta", []() { setLuaNoSideEffect(); diff --git a/pdns/dnsdist-rings.cc b/pdns/dnsdist-rings.cc index 787260a66..0ae0ea124 100644 --- a/pdns/dnsdist-rings.cc +++ b/pdns/dnsdist-rings.cc @@ -4,36 +4,53 @@ unsigned int Rings::numDistinctRequestors() { std::set s; - WriteLock wl(&queryLock); + ReadLock rl(&queryLock); for(const auto& q : queryRing) s.insert(q.requestor); return s.size(); } -vector > Rings::getTopBandwidth(unsigned int numentries) +std::unordered_map>> Rings::getTopBandwidth(unsigned int numentries) { map counts; + uint64_t total=0; { - WriteLock wl(&queryLock); - for(const auto& q : queryRing) + ReadLock rl(&queryLock); + for(const auto& q : queryRing) { counts[q.requestor]+=q.size; + total+=q.size; + } } { std::lock_guard lock(respMutex); - for(const auto& r : respRing) + for(const auto& r : respRing) { counts[r.requestor]+=r.size; + total+=r.size; + } } typedef vector> ret_t; - ret_t ret; + ret_t rcounts; + rcounts.reserve(counts.size()); for(const auto& p : counts) - ret.push_back({p.second, p.first}); - numentries = ret.size() < numentries ? ret.size() : numentries; - partial_sort(ret.begin(), ret.begin()+numentries, ret.end(), [](const ret_t::value_type&a, const ret_t::value_type&b) + rcounts.push_back({p.second, p.first}); + numentries = rcounts.size() < numentries ? rcounts.size() : numentries; + partial_sort(rcounts.begin(), rcounts.begin()+numentries, rcounts.end(), [](const ret_t::value_type&a, const ret_t::value_type&b) { - return(b.second < a.second); + return(b.first < a.first); }); - ret.resize(numentries); + std::unordered_map>> ret; + uint64_t rest = 0; + unsigned int count = 1; + for(const auto& rc : rcounts) { + if(count==numentries+1) { + rest+=rc.first; + } + else { + ret.insert({count++, {rc.second.toString(), rc.first, 100.0*rc.first/total}}); + } + } + ret.insert({count, {"Rest", rest, total > 0 ? 100.0*rest/total : 100.0}}); return ret; } diff --git a/pdns/dnsdist.hh b/pdns/dnsdist.hh index 224f750f8..a7893b38e 100644 --- a/pdns/dnsdist.hh +++ b/pdns/dnsdist.hh @@ -260,7 +260,7 @@ struct Rings { std::mutex respMutex; pthread_rwlock_t queryLock; - vector > getTopBandwidth(unsigned int numentries); + std::unordered_map > > getTopBandwidth(unsigned int numentries); unsigned int numDistinctRequestors(); };