]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnsdist-rings.cc
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include "dnsdist-rings.hh"
27 void Rings::setCapacity(size_t newCapacity
, size_t numberOfShards
)
30 throw std::runtime_error("Rings::setCapacity() should not be called once the rings have been initialized");
32 d_capacity
= newCapacity
;
33 d_numberOfShards
= numberOfShards
;
38 if (d_initialized
.exchange(true)) {
39 throw std::runtime_error("Rings::init() should only be called once");
42 if (d_numberOfShards
<= 1) {
46 d_shards
.resize(d_numberOfShards
);
48 /* resize all the rings */
49 for (auto& shard
: d_shards
) {
50 shard
= std::make_unique
<Shard
>();
51 shard
->queryRing
.lock()->set_capacity(d_capacity
/ d_numberOfShards
);
52 shard
->respRing
.lock()->set_capacity(d_capacity
/ d_numberOfShards
);
55 /* we just recreated the shards so they are now empty */
57 d_nbResponseEntries
= 0;
60 void Rings::setNumberOfLockRetries(size_t retries
)
62 if (d_numberOfShards
<= 1) {
65 d_nbLockTries
= retries
;
69 size_t Rings::numDistinctRequestors()
71 std::set
<ComboAddress
, ComboAddress::addressOnlyLessThan
> s
;
72 for (const auto& shard
: d_shards
) {
73 auto rl
= shard
->queryRing
.lock();
74 for (const auto& q
: *rl
) {
75 s
.insert(q
.requestor
);
81 std::unordered_map
<int, vector
<boost::variant
<string
,double>>> Rings::getTopBandwidth(unsigned int numentries
)
83 map
<ComboAddress
, unsigned int, ComboAddress::addressOnlyLessThan
> counts
;
85 for (const auto& shard
: d_shards
) {
87 auto rl
= shard
->queryRing
.lock();
88 for(const auto& q
: *rl
) {
89 counts
[q
.requestor
] += q
.size
;
94 auto rl
= shard
->respRing
.lock();
95 for(const auto& r
: *rl
) {
96 counts
[r
.requestor
] += r
.size
;
102 typedef vector
<pair
<unsigned int, ComboAddress
>> ret_t
;
104 rcounts
.reserve(counts
.size());
105 for(const auto& p
: counts
)
106 rcounts
.push_back({p
.second
, p
.first
});
107 numentries
= rcounts
.size() < numentries
? rcounts
.size() : numentries
;
108 partial_sort(rcounts
.begin(), rcounts
.begin()+numentries
, rcounts
.end(), [](const ret_t::value_type
&a
, const ret_t::value_type
&b
)
110 return(b
.first
< a
.first
);
112 std::unordered_map
<int, vector
<boost::variant
<string
,double>>> ret
;
114 unsigned int count
= 1;
115 for(const auto& rc
: rcounts
) {
116 if(count
==numentries
+1) {
120 ret
.insert({count
++, {rc
.second
.toString(), rc
.first
, 100.0*rc
.first
/total
}});
125 ret
.insert({count
, {"Rest", rest
, 100.0*rest
/total
}});
128 ret
.insert({count
, {"Rest", rest
, 100.0 }});
134 size_t Rings::loadFromFile(const std::string
& filepath
, const struct timespec
& now
)
136 ifstream
ifs(filepath
);
138 throw std::runtime_error("unable to open the file at " + filepath
);
144 memset(&dh
, 0, sizeof(dh
));
146 while (std::getline(ifs
, line
)) {
147 boost::trim_right_if(line
, boost::is_any_of(" \r\n\x1a"));
148 boost::trim_left(line
);
149 bool isResponse
= false;
150 vector
<string
> parts
;
151 stringtok(parts
, line
, " \t,");
153 if (parts
.size() == 8) {
155 else if (parts
.size() >= 11 && parts
.size() <= 13) {
159 cerr
<<"skipping line with "<<parts
.size()<<"parts: "<<line
<<endl
;
164 vector
<string
> timeStr
;
165 stringtok(timeStr
, parts
.at(idx
++), ".");
166 if (timeStr
.size() != 2) {
167 cerr
<<"skipping invalid time "<<parts
.at(0)<<endl
;
171 struct timespec when
;
173 when
.tv_sec
= now
.tv_sec
+ std::stoi(timeStr
.at(0));
174 when
.tv_nsec
= now
.tv_nsec
+ std::stoi(timeStr
.at(1)) * 100 * 1000 * 1000;
176 catch (const std::exception
& e
) {
177 cerr
<<"error parsing time "<<parts
.at(idx
-1)<<" from line "<<line
<<endl
;
181 ComboAddress
from(parts
.at(idx
++));
183 dnsdist::Protocol
protocol(parts
.at(idx
++));
185 to
= ComboAddress(parts
.at(idx
++));
189 DNSName
qname(parts
.at(idx
++));
190 QType
qtype(QType::chartocode(parts
.at(idx
++).c_str()));
193 insertResponse(when
, from
, qname
, qtype
.getCode(), 0, 0, dh
, to
, protocol
);
196 insertQuery(when
, from
, qname
, qtype
.getCode(), 0, dh
, protocol
);