]>
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 | ||
51 | string StatBag::directory() | |
52 | { | |
53 | string dir; | |
54 | ostringstream o; | |
1566533a | 55 | |
cb167afd CHB |
56 | for(const auto& i: d_stats) { |
57 | o<<i.first<<"="<<*(i.second)<<","; | |
58 | } | |
1566533a | 59 | |
e903706d | 60 | |
ef7cd021 | 61 | for(const funcstats_t::value_type& val : d_funcstats) { |
e903706d | 62 | o << val.first<<"="<<val.second(val.first)<<","; |
63 | } | |
12c86877 BH |
64 | dir=o.str(); |
65 | return dir; | |
66 | } | |
67 | ||
68 | ||
69 | vector<string>StatBag::getEntries() | |
70 | { | |
71 | vector<string> ret; | |
1566533a | 72 | |
cb167afd CHB |
73 | for(const auto& i: d_stats) { |
74 | ret.push_back(i.first); | |
75 | } | |
12c86877 | 76 | |
ef7cd021 | 77 | for(const funcstats_t::value_type& val : d_funcstats) { |
e903706d | 78 | ret.push_back(val.first); |
79 | } | |
80 | ||
1566533a | 81 | |
12c86877 BH |
82 | return ret; |
83 | ||
84 | } | |
85 | ||
86 | string StatBag::getDescrip(const string &item) | |
87 | { | |
1566533a | 88 | exists(item); |
89 | return d_keyDescrips[item]; | |
12c86877 BH |
90 | } |
91 | ||
92 | void StatBag::declare(const string &key, const string &descrip) | |
93 | { | |
1566533a | 94 | AtomicCounter *i=new AtomicCounter(0); |
12c86877 BH |
95 | d_stats[key]=i; |
96 | d_keyDescrips[key]=descrip; | |
12c86877 BH |
97 | } |
98 | ||
e903706d | 99 | void StatBag::declare(const string &key, const string &descrip, StatBag::func_t func) |
100 | { | |
101 | ||
102 | d_funcstats[key]=func; | |
103 | d_keyDescrips[key]=descrip; | |
104 | } | |
12c86877 BH |
105 | |
106 | ||
ac0995bb | 107 | void StatBag::set(const string &key, unsigned long value) |
12c86877 | 108 | { |
12c86877 | 109 | exists(key); |
ac0995bb | 110 | d_stats[key]->store(value); |
12c86877 BH |
111 | } |
112 | ||
ac0995bb | 113 | unsigned long StatBag::read(const string &key) |
12c86877 | 114 | { |
1566533a | 115 | exists(key); |
3b433571 | 116 | funcstats_t::const_iterator iter = d_funcstats.find(key); |
117 | if(iter != d_funcstats.end()) | |
118 | return iter->second(iter->first); | |
1566533a | 119 | return *d_stats[key]; |
12c86877 BH |
120 | } |
121 | ||
ac0995bb | 122 | unsigned long StatBag::readZero(const string &key) |
12c86877 | 123 | { |
1566533a | 124 | exists(key); |
ac0995bb | 125 | unsigned long tmp=*d_stats[key]; |
12c86877 | 126 | d_stats[key]=0; |
12c86877 BH |
127 | return tmp; |
128 | } | |
129 | ||
130 | ||
131 | string StatBag::getValueStr(const string &key) | |
132 | { | |
133 | ostringstream o; | |
134 | o<<read(key); | |
135 | return o.str(); | |
136 | } | |
137 | ||
138 | string StatBag::getValueStrZero(const string &key) | |
139 | { | |
140 | ostringstream o; | |
141 | o<<readZero(key); | |
142 | return o.str(); | |
143 | } | |
144 | ||
1566533a | 145 | AtomicCounter *StatBag::getPointer(const string &key) |
12c86877 BH |
146 | { |
147 | exists(key); | |
148 | return d_stats[key]; | |
149 | } | |
150 | ||
151 | StatBag::~StatBag() | |
152 | { | |
cb167afd CHB |
153 | for(const auto& i: d_stats) { |
154 | delete i.second; | |
155 | } | |
12c86877 BH |
156 | |
157 | } | |
158 | ||
4eb26e0f | 159 | template<typename T, typename Comp> |
160 | StatRing<T,Comp>::StatRing(unsigned int size) | |
12c86877 | 161 | { |
4eb26e0f | 162 | d_items.set_capacity(size); |
163 | pthread_mutex_init(&d_lock, 0); | |
12c86877 BH |
164 | } |
165 | ||
4eb26e0f | 166 | template<typename T, typename Comp> |
167 | void StatRing<T,Comp>::account(const T& t) | |
12c86877 | 168 | { |
4eb26e0f | 169 | Lock l(&d_lock); |
170 | d_items.push_back(t); | |
171 | } | |
12c86877 | 172 | |
4eb26e0f | 173 | template<typename T, typename Comp> |
174 | unsigned int StatRing<T,Comp>::getSize() | |
175 | { | |
176 | Lock l(&d_lock); | |
177 | return d_items.capacity(); | |
12c86877 | 178 | } |
975bee12 | 179 | |
4eb26e0f | 180 | template<typename T, typename Comp> |
181 | void StatRing<T,Comp>::resize(unsigned int newsize) | |
12c86877 | 182 | { |
4eb26e0f | 183 | Lock l(&d_lock); |
184 | d_items.set_capacity(newsize); | |
12c86877 BH |
185 | } |
186 | ||
4eb26e0f | 187 | |
188 | template<typename T, typename Comp> | |
189 | void StatRing<T,Comp>::setHelp(const string &str) | |
12c86877 BH |
190 | { |
191 | d_help=str; | |
192 | } | |
193 | ||
4eb26e0f | 194 | template<typename T, typename Comp> |
195 | string StatRing<T,Comp>::getHelp() | |
12c86877 BH |
196 | { |
197 | return d_help; | |
198 | } | |
199 | ||
12c86877 | 200 | |
4eb26e0f | 201 | template<typename T, typename Comp> |
202 | vector<pair<T, unsigned int> >StatRing<T,Comp>::get() const | |
12c86877 | 203 | { |
4eb26e0f | 204 | Lock l(&d_lock); |
205 | map<T,unsigned int, Comp> res; | |
206 | for(typename boost::circular_buffer<T>::const_iterator i=d_items.begin();i!=d_items.end();++i) { | |
207 | res[*i]++; | |
12c86877 BH |
208 | } |
209 | ||
4eb26e0f | 210 | vector<pair<T ,unsigned int> > tmp; |
211 | for(typename map<T, unsigned int>::const_iterator i=res.begin();i!=res.end();++i) | |
12c86877 BH |
212 | tmp.push_back(*i); |
213 | ||
214 | sort(tmp.begin(),tmp.end(),popisort); | |
215 | ||
216 | return tmp; | |
217 | } | |
218 | ||
219 | void StatBag::declareRing(const string &name, const string &help, unsigned int size) | |
220 | { | |
fadd04cc | 221 | d_rings[name]=StatRing<string, CIStringCompare>(size); |
12c86877 BH |
222 | d_rings[name].setHelp(help); |
223 | } | |
224 | ||
4eb26e0f | 225 | void StatBag::declareComboRing(const string &name, const string &help, unsigned int size) |
12c86877 | 226 | { |
662d5441 | 227 | d_comborings[name]=StatRing<SComboAddress>(size); |
4eb26e0f | 228 | d_comborings[name].setHelp(help); |
12c86877 BH |
229 | } |
230 | ||
f2b2f3ad PL |
231 | void StatBag::declareDNSNameQTypeRing(const string &name, const string &help, unsigned int size) |
232 | { | |
233 | d_dnsnameqtyperings[name] = StatRing<std::tuple<DNSName, QType> >(size); | |
234 | d_dnsnameqtyperings[name].setHelp(help); | |
235 | } | |
236 | ||
4eb26e0f | 237 | |
238 | vector<pair<string, unsigned int> > StatBag::getRing(const string &name) | |
12c86877 | 239 | { |
f2b2f3ad | 240 | if(d_rings.count(name)) { |
4eb26e0f | 241 | return d_rings[name].get(); |
f2b2f3ad PL |
242 | } |
243 | vector<pair<string, unsigned int> > ret; | |
244 | ||
245 | if (d_comborings.count(name)) { | |
662d5441 | 246 | typedef pair<SComboAddress, unsigned int> stor_t; |
4eb26e0f | 247 | vector<stor_t> raw =d_comborings[name].get(); |
ef7cd021 | 248 | for(const stor_t& stor : raw) { |
662d5441 | 249 | ret.push_back(make_pair(stor.first.ca.toString(), stor.second)); |
4eb26e0f | 250 | } |
f2b2f3ad PL |
251 | } else if(d_dnsnameqtyperings.count(name)) { |
252 | auto raw = d_dnsnameqtyperings[name].get(); | |
253 | for (auto const &e : raw) { | |
254 | ret.push_back(make_pair(std::get<0>(e.first).toLogString() + "/" + std::get<1>(e.first).getName(), e.second)); | |
255 | } | |
12c86877 | 256 | } |
f2b2f3ad | 257 | return ret; |
4eb26e0f | 258 | } |
259 | ||
260 | template<typename T, typename Comp> | |
261 | void StatRing<T,Comp>::reset() | |
262 | { | |
263 | Lock l(&d_lock); | |
264 | d_items.clear(); | |
12c86877 BH |
265 | } |
266 | ||
267 | void StatBag::resetRing(const string &name) | |
268 | { | |
4eb26e0f | 269 | if(d_rings.count(name)) |
270 | d_rings[name].reset(); | |
f2b2f3ad | 271 | if(d_comborings.count(name)) |
4eb26e0f | 272 | d_comborings[name].reset(); |
f2b2f3ad PL |
273 | if(d_dnsnameqtyperings.count(name)) |
274 | d_dnsnameqtyperings[name].reset(); | |
12c86877 BH |
275 | } |
276 | ||
bb3c3f50 | 277 | void StatBag::resizeRing(const string &name, unsigned int newsize) |
12c86877 | 278 | { |
4eb26e0f | 279 | if(d_rings.count(name)) |
280 | d_rings[name].resize(newsize); | |
f2b2f3ad | 281 | if(d_comborings.count(name)) |
4eb26e0f | 282 | d_comborings[name].resize(newsize); |
f2b2f3ad PL |
283 | if(d_dnsnameqtyperings.count(name)) |
284 | return d_dnsnameqtyperings[name].resize(newsize); | |
12c86877 BH |
285 | } |
286 | ||
287 | ||
bb3c3f50 | 288 | unsigned int StatBag::getRingSize(const string &name) |
12c86877 | 289 | { |
4eb26e0f | 290 | if(d_rings.count(name)) |
291 | return d_rings[name].getSize(); | |
f2b2f3ad | 292 | if(d_comborings.count(name)) |
4eb26e0f | 293 | return d_comborings[name].getSize(); |
f2b2f3ad PL |
294 | if(d_dnsnameqtyperings.count(name)) |
295 | return d_dnsnameqtyperings[name].getSize(); | |
296 | return 0; | |
12c86877 BH |
297 | } |
298 | ||
12c86877 BH |
299 | string StatBag::getRingTitle(const string &name) |
300 | { | |
4eb26e0f | 301 | if(d_rings.count(name)) |
302 | return d_rings[name].getHelp(); | |
f2b2f3ad | 303 | if(d_comborings.count(name)) |
4eb26e0f | 304 | return d_comborings[name].getHelp(); |
f2b2f3ad PL |
305 | if(d_dnsnameqtyperings.count(name)) |
306 | return d_dnsnameqtyperings[name].getHelp(); | |
307 | return ""; | |
12c86877 BH |
308 | } |
309 | ||
310 | vector<string>StatBag::listRings() | |
311 | { | |
312 | vector<string> ret; | |
fadd04cc | 313 | for(auto i=d_rings.begin();i!=d_rings.end();++i) |
4eb26e0f | 314 | ret.push_back(i->first); |
fadd04cc | 315 | for(auto i=d_comborings.begin();i!=d_comborings.end();++i) |
12c86877 | 316 | ret.push_back(i->first); |
f2b2f3ad PL |
317 | for(const auto &i : d_dnsnameqtyperings) |
318 | ret.push_back(i.first); | |
4eb26e0f | 319 | |
12c86877 BH |
320 | return ret; |
321 | } | |
322 | ||
ef1439ff KM |
323 | bool StatBag::ringExists(const string &name) |
324 | { | |
f2b2f3ad | 325 | return d_rings.count(name) || d_comborings.count(name) || d_dnsnameqtyperings.count(name); |
ef1439ff | 326 | } |
4eb26e0f | 327 | |
fadd04cc | 328 | template class StatRing<std::string, CIStringCompare>; |
662d5441 | 329 | template class StatRing<SComboAddress>; |
f2b2f3ad | 330 | template class StatRing<std::tuple<DNSName, QType> >; |