]>
Commit | Line | Data |
---|---|---|
12c86877 | 1 | /* |
6edbf68a PL |
2 | * This file is part of PowerDNS or dnsdist. |
3 | * Copyright -- PowerDNS.COM B.V. and its contributors | |
4 | * | |
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. | |
8 | * | |
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. | |
12 | * | |
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. | |
17 | * | |
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. | |
21 | */ | |
870a0fe4 AT |
22 | #ifdef HAVE_CONFIG_H |
23 | #include "config.h" | |
24 | #endif | |
896e5153 | 25 | #include "utility.hh" |
12c86877 | 26 | #include "statbag.hh" |
5c409fa2 | 27 | #include "pdnsexception.hh" |
12c86877 BH |
28 | #include <iostream> |
29 | #include <sstream> | |
30 | #include <algorithm> | |
31 | #include "arguments.hh" | |
32 | #include "lock.hh" | |
4eb26e0f | 33 | #include "iputils.hh" |
fa8fd4d2 | 34 | |
12c86877 | 35 | |
10f4eea8 | 36 | #include "namespaces.hh" |
12c86877 BH |
37 | |
38 | StatBag::StatBag() | |
39 | { | |
40 | d_doRings=false; | |
12c86877 BH |
41 | } |
42 | ||
12c86877 BH |
43 | void StatBag::exists(const string &key) |
44 | { | |
e903706d | 45 | if(!d_keyDescrips.count(key)) |
12c86877 | 46 | { |
3f81d239 | 47 | throw PDNSException("Trying to deposit into unknown StatBag key '"+key+"'"); |
12c86877 BH |
48 | } |
49 | } | |
50 | ||
f3245c8c | 51 | string StatBag::directory() |
12c86877 BH |
52 | { |
53 | string dir; | |
54 | ostringstream o; | |
1566533a | 55 | |
cb167afd | 56 | for(const auto& i: d_stats) { |
f3245c8c | 57 | if (d_blacklist.find(i.first) != d_blacklist.end()) |
28c3cc11 | 58 | continue; |
cb167afd CHB |
59 | o<<i.first<<"="<<*(i.second)<<","; |
60 | } | |
1566533a | 61 | |
e903706d | 62 | |
ef7cd021 | 63 | for(const funcstats_t::value_type& val : d_funcstats) { |
f3245c8c | 64 | if (d_blacklist.find(val.first) != d_blacklist.end()) |
28c3cc11 | 65 | continue; |
e903706d | 66 | o << val.first<<"="<<val.second(val.first)<<","; |
67 | } | |
12c86877 BH |
68 | dir=o.str(); |
69 | return dir; | |
70 | } | |
71 | ||
72 | ||
73 | vector<string>StatBag::getEntries() | |
74 | { | |
75 | vector<string> ret; | |
1566533a | 76 | |
cb167afd | 77 | for(const auto& i: d_stats) { |
f3245c8c OM |
78 | if (d_blacklist.find(i.first) != d_blacklist.end()) |
79 | continue; | |
80 | ret.push_back(i.first); | |
cb167afd | 81 | } |
12c86877 | 82 | |
ef7cd021 | 83 | for(const funcstats_t::value_type& val : d_funcstats) { |
f3245c8c OM |
84 | if (d_blacklist.find(val.first) != d_blacklist.end()) |
85 | continue; | |
e903706d | 86 | ret.push_back(val.first); |
87 | } | |
88 | ||
1566533a | 89 | |
12c86877 BH |
90 | return ret; |
91 | ||
92 | } | |
93 | ||
94 | string StatBag::getDescrip(const string &item) | |
95 | { | |
1566533a | 96 | exists(item); |
97 | return d_keyDescrips[item]; | |
12c86877 BH |
98 | } |
99 | ||
100 | void StatBag::declare(const string &key, const string &descrip) | |
101 | { | |
c2826d2e RG |
102 | auto i=make_unique<AtomicCounter>(0); |
103 | d_stats[key]=std::move(i); | |
12c86877 | 104 | d_keyDescrips[key]=descrip; |
12c86877 BH |
105 | } |
106 | ||
e903706d | 107 | void StatBag::declare(const string &key, const string &descrip, StatBag::func_t func) |
108 | { | |
109 | ||
110 | d_funcstats[key]=func; | |
111 | d_keyDescrips[key]=descrip; | |
112 | } | |
12c86877 BH |
113 | |
114 | ||
ac0995bb | 115 | void StatBag::set(const string &key, unsigned long value) |
12c86877 | 116 | { |
12c86877 | 117 | exists(key); |
ac0995bb | 118 | d_stats[key]->store(value); |
12c86877 BH |
119 | } |
120 | ||
ac0995bb | 121 | unsigned long StatBag::read(const string &key) |
12c86877 | 122 | { |
1566533a | 123 | exists(key); |
3b433571 | 124 | funcstats_t::const_iterator iter = d_funcstats.find(key); |
125 | if(iter != d_funcstats.end()) | |
126 | return iter->second(iter->first); | |
1566533a | 127 | return *d_stats[key]; |
12c86877 BH |
128 | } |
129 | ||
ac0995bb | 130 | unsigned long StatBag::readZero(const string &key) |
12c86877 | 131 | { |
1566533a | 132 | exists(key); |
ac0995bb | 133 | unsigned long tmp=*d_stats[key]; |
12c86877 | 134 | d_stats[key]=0; |
12c86877 BH |
135 | return tmp; |
136 | } | |
137 | ||
138 | ||
139 | string StatBag::getValueStr(const string &key) | |
140 | { | |
141 | ostringstream o; | |
142 | o<<read(key); | |
143 | return o.str(); | |
144 | } | |
145 | ||
146 | string StatBag::getValueStrZero(const string &key) | |
147 | { | |
148 | ostringstream o; | |
149 | o<<readZero(key); | |
150 | return o.str(); | |
151 | } | |
152 | ||
1566533a | 153 | AtomicCounter *StatBag::getPointer(const string &key) |
12c86877 BH |
154 | { |
155 | exists(key); | |
c2826d2e | 156 | return d_stats[key].get(); |
12c86877 BH |
157 | } |
158 | ||
159 | StatBag::~StatBag() | |
160 | { | |
12c86877 BH |
161 | } |
162 | ||
4eb26e0f | 163 | template<typename T, typename Comp> |
164 | StatRing<T,Comp>::StatRing(unsigned int size) | |
12c86877 | 165 | { |
4eb26e0f | 166 | d_items.set_capacity(size); |
12c86877 BH |
167 | } |
168 | ||
f979b818 OM |
169 | template<typename T, typename Comp> |
170 | StatRing<T,Comp>::StatRing(const StatRing<T,Comp> &arg) | |
171 | { | |
172 | std::lock_guard<std::mutex> thislock(d_lock); | |
173 | std::lock_guard<std::mutex> arglock(arg.d_lock); | |
174 | ||
175 | d_items = arg.d_items; | |
176 | d_help = arg.d_help; | |
177 | } | |
178 | ||
4eb26e0f | 179 | template<typename T, typename Comp> |
180 | void StatRing<T,Comp>::account(const T& t) | |
12c86877 | 181 | { |
92b91988 | 182 | std::lock_guard<std::mutex> l(d_lock); |
4eb26e0f | 183 | d_items.push_back(t); |
184 | } | |
12c86877 | 185 | |
4eb26e0f | 186 | template<typename T, typename Comp> |
74e38357 | 187 | uint64_t StatRing<T,Comp>::getSize() const |
4eb26e0f | 188 | { |
92b91988 | 189 | std::lock_guard<std::mutex> l(d_lock); |
4eb26e0f | 190 | return d_items.capacity(); |
12c86877 | 191 | } |
975bee12 | 192 | |
74e38357 RG |
193 | template<typename T, typename Comp> |
194 | uint64_t StatRing<T,Comp>::getEntriesCount() const | |
195 | { | |
196 | std::lock_guard<std::mutex> l(d_lock); | |
197 | return d_items.size(); | |
198 | } | |
199 | ||
4eb26e0f | 200 | template<typename T, typename Comp> |
201 | void StatRing<T,Comp>::resize(unsigned int newsize) | |
12c86877 | 202 | { |
92b91988 | 203 | std::lock_guard<std::mutex> l(d_lock); |
4eb26e0f | 204 | d_items.set_capacity(newsize); |
12c86877 BH |
205 | } |
206 | ||
4eb26e0f | 207 | template<typename T, typename Comp> |
208 | void StatRing<T,Comp>::setHelp(const string &str) | |
12c86877 BH |
209 | { |
210 | d_help=str; | |
211 | } | |
212 | ||
4eb26e0f | 213 | template<typename T, typename Comp> |
214 | string StatRing<T,Comp>::getHelp() | |
12c86877 BH |
215 | { |
216 | return d_help; | |
217 | } | |
218 | ||
12c86877 | 219 | |
4eb26e0f | 220 | template<typename T, typename Comp> |
221 | vector<pair<T, unsigned int> >StatRing<T,Comp>::get() const | |
12c86877 | 222 | { |
92b91988 | 223 | std::lock_guard<std::mutex> l(d_lock); |
4eb26e0f | 224 | map<T,unsigned int, Comp> res; |
225 | for(typename boost::circular_buffer<T>::const_iterator i=d_items.begin();i!=d_items.end();++i) { | |
226 | res[*i]++; | |
12c86877 BH |
227 | } |
228 | ||
4eb26e0f | 229 | vector<pair<T ,unsigned int> > tmp; |
230 | for(typename map<T, unsigned int>::const_iterator i=res.begin();i!=res.end();++i) | |
12c86877 BH |
231 | tmp.push_back(*i); |
232 | ||
233 | sort(tmp.begin(),tmp.end(),popisort); | |
234 | ||
235 | return tmp; | |
236 | } | |
237 | ||
74e38357 RG |
238 | void StatBag::registerRingStats(const string& name) |
239 | { | |
240 | declare("ring-" + name + "-size", "Number of entries in the " + name + " ring", [this,name](const std::string&) { return static_cast<uint64_t>(getRingEntriesCount(name)); }); | |
241 | declare("ring-" + name + "-capacity", "Maximum number of entries in the " + name + " ring", [this,name](const std::string&) { return static_cast<uint64_t>(getRingSize(name)); }); | |
242 | } | |
243 | ||
12c86877 BH |
244 | void StatBag::declareRing(const string &name, const string &help, unsigned int size) |
245 | { | |
92b91988 | 246 | d_rings.emplace(name, size); |
12c86877 | 247 | d_rings[name].setHelp(help); |
74e38357 | 248 | registerRingStats(name); |
12c86877 BH |
249 | } |
250 | ||
4eb26e0f | 251 | void StatBag::declareComboRing(const string &name, const string &help, unsigned int size) |
12c86877 | 252 | { |
ef2ea4bf JS |
253 | d_comboRings.emplace(name, size); |
254 | d_comboRings[name].setHelp(help); | |
74e38357 | 255 | registerRingStats(name); |
12c86877 BH |
256 | } |
257 | ||
f2b2f3ad PL |
258 | void StatBag::declareDNSNameQTypeRing(const string &name, const string &help, unsigned int size) |
259 | { | |
92b91988 | 260 | d_dnsnameqtyperings.emplace(name, size); |
f2b2f3ad | 261 | d_dnsnameqtyperings[name].setHelp(help); |
74e38357 | 262 | registerRingStats(name); |
f2b2f3ad PL |
263 | } |
264 | ||
4eb26e0f | 265 | vector<pair<string, unsigned int> > StatBag::getRing(const string &name) |
12c86877 | 266 | { |
f2b2f3ad | 267 | if(d_rings.count(name)) { |
4eb26e0f | 268 | return d_rings[name].get(); |
f2b2f3ad PL |
269 | } |
270 | vector<pair<string, unsigned int> > ret; | |
271 | ||
ef2ea4bf | 272 | if (d_comboRings.count(name)) { |
662d5441 | 273 | typedef pair<SComboAddress, unsigned int> stor_t; |
ef2ea4bf | 274 | vector<stor_t> raw =d_comboRings[name].get(); |
ef7cd021 | 275 | for(const stor_t& stor : raw) { |
662d5441 | 276 | ret.push_back(make_pair(stor.first.ca.toString(), stor.second)); |
4eb26e0f | 277 | } |
f2b2f3ad PL |
278 | } else if(d_dnsnameqtyperings.count(name)) { |
279 | auto raw = d_dnsnameqtyperings[name].get(); | |
280 | for (auto const &e : raw) { | |
281 | ret.push_back(make_pair(std::get<0>(e.first).toLogString() + "/" + std::get<1>(e.first).getName(), e.second)); | |
282 | } | |
12c86877 | 283 | } |
f2b2f3ad | 284 | return ret; |
4eb26e0f | 285 | } |
286 | ||
287 | template<typename T, typename Comp> | |
288 | void StatRing<T,Comp>::reset() | |
289 | { | |
92b91988 | 290 | std::lock_guard<std::mutex> l(d_lock); |
4eb26e0f | 291 | d_items.clear(); |
12c86877 BH |
292 | } |
293 | ||
294 | void StatBag::resetRing(const string &name) | |
295 | { | |
4eb26e0f | 296 | if(d_rings.count(name)) |
297 | d_rings[name].reset(); | |
ef2ea4bf JS |
298 | if(d_comboRings.count(name)) |
299 | d_comboRings[name].reset(); | |
f2b2f3ad PL |
300 | if(d_dnsnameqtyperings.count(name)) |
301 | d_dnsnameqtyperings[name].reset(); | |
12c86877 BH |
302 | } |
303 | ||
bb3c3f50 | 304 | void StatBag::resizeRing(const string &name, unsigned int newsize) |
12c86877 | 305 | { |
4eb26e0f | 306 | if(d_rings.count(name)) |
307 | d_rings[name].resize(newsize); | |
ef2ea4bf JS |
308 | if(d_comboRings.count(name)) |
309 | d_comboRings[name].resize(newsize); | |
f2b2f3ad PL |
310 | if(d_dnsnameqtyperings.count(name)) |
311 | return d_dnsnameqtyperings[name].resize(newsize); | |
12c86877 BH |
312 | } |
313 | ||
314 | ||
74e38357 | 315 | uint64_t StatBag::getRingSize(const string &name) |
12c86877 | 316 | { |
4eb26e0f | 317 | if(d_rings.count(name)) |
318 | return d_rings[name].getSize(); | |
ef2ea4bf JS |
319 | if(d_comboRings.count(name)) |
320 | return d_comboRings[name].getSize(); | |
f2b2f3ad PL |
321 | if(d_dnsnameqtyperings.count(name)) |
322 | return d_dnsnameqtyperings[name].getSize(); | |
323 | return 0; | |
12c86877 BH |
324 | } |
325 | ||
74e38357 RG |
326 | uint64_t StatBag::getRingEntriesCount(const string &name) |
327 | { | |
328 | if(d_rings.count(name)) | |
329 | return d_rings[name].getEntriesCount(); | |
ef2ea4bf JS |
330 | if(d_comboRings.count(name)) |
331 | return d_comboRings[name].getEntriesCount(); | |
74e38357 RG |
332 | if(d_dnsnameqtyperings.count(name)) |
333 | return d_dnsnameqtyperings[name].getEntriesCount(); | |
334 | return 0; | |
335 | } | |
336 | ||
12c86877 BH |
337 | string StatBag::getRingTitle(const string &name) |
338 | { | |
4eb26e0f | 339 | if(d_rings.count(name)) |
340 | return d_rings[name].getHelp(); | |
ef2ea4bf JS |
341 | if(d_comboRings.count(name)) |
342 | return d_comboRings[name].getHelp(); | |
f2b2f3ad PL |
343 | if(d_dnsnameqtyperings.count(name)) |
344 | return d_dnsnameqtyperings[name].getHelp(); | |
345 | return ""; | |
12c86877 BH |
346 | } |
347 | ||
348 | vector<string>StatBag::listRings() | |
349 | { | |
350 | vector<string> ret; | |
fadd04cc | 351 | for(auto i=d_rings.begin();i!=d_rings.end();++i) |
4eb26e0f | 352 | ret.push_back(i->first); |
ef2ea4bf | 353 | for(auto i=d_comboRings.begin();i!=d_comboRings.end();++i) |
12c86877 | 354 | ret.push_back(i->first); |
f2b2f3ad PL |
355 | for(const auto &i : d_dnsnameqtyperings) |
356 | ret.push_back(i.first); | |
4eb26e0f | 357 | |
12c86877 BH |
358 | return ret; |
359 | } | |
360 | ||
ef1439ff KM |
361 | bool StatBag::ringExists(const string &name) |
362 | { | |
ef2ea4bf | 363 | return d_rings.count(name) || d_comboRings.count(name) || d_dnsnameqtyperings.count(name); |
ef1439ff | 364 | } |
4eb26e0f | 365 | |
f3245c8c OM |
366 | void StatBag::blacklist(const string& str) { |
367 | d_blacklist.insert(str); | |
368 | } | |
369 | ||
fadd04cc | 370 | template class StatRing<std::string, CIStringCompare>; |
662d5441 | 371 | template class StatRing<SComboAddress>; |
f2b2f3ad | 372 | template class StatRing<std::tuple<DNSName, QType> >; |