]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/statbag.cc
Merge pull request #8141 from rgacogne/dnsdist-ocsp
[thirdparty/pdns.git] / pdns / statbag.cc
1 /*
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 */
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include "utility.hh"
26 #include "statbag.hh"
27 #include "pdnsexception.hh"
28 #include <iostream>
29 #include <sstream>
30 #include <algorithm>
31 #include "arguments.hh"
32 #include "lock.hh"
33 #include "iputils.hh"
34
35
36 #include "namespaces.hh"
37
38 StatBag::StatBag()
39 {
40 d_doRings=false;
41 }
42
43 void StatBag::exists(const string &key)
44 {
45 if(!d_keyDescrips.count(key))
46 {
47 throw PDNSException("Trying to deposit into unknown StatBag key '"+key+"'");
48 }
49 }
50
51 string StatBag::directory()
52 {
53 string dir;
54 ostringstream o;
55
56 for(const auto& i: d_stats) {
57 if (d_blacklist.find(i.first) != d_blacklist.end())
58 continue;
59 o<<i.first<<"="<<*(i.second)<<",";
60 }
61
62
63 for(const funcstats_t::value_type& val : d_funcstats) {
64 if (d_blacklist.find(val.first) != d_blacklist.end())
65 continue;
66 o << val.first<<"="<<val.second(val.first)<<",";
67 }
68 dir=o.str();
69 return dir;
70 }
71
72
73 vector<string>StatBag::getEntries()
74 {
75 vector<string> ret;
76
77 for(const auto& i: d_stats) {
78 if (d_blacklist.find(i.first) != d_blacklist.end())
79 continue;
80 ret.push_back(i.first);
81 }
82
83 for(const funcstats_t::value_type& val : d_funcstats) {
84 if (d_blacklist.find(val.first) != d_blacklist.end())
85 continue;
86 ret.push_back(val.first);
87 }
88
89
90 return ret;
91
92 }
93
94 string StatBag::getDescrip(const string &item)
95 {
96 exists(item);
97 return d_keyDescrips[item];
98 }
99
100 void StatBag::declare(const string &key, const string &descrip)
101 {
102 AtomicCounter *i=new AtomicCounter(0);
103 d_stats[key]=i;
104 d_keyDescrips[key]=descrip;
105 }
106
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 }
113
114
115 void StatBag::set(const string &key, unsigned long value)
116 {
117 exists(key);
118 d_stats[key]->store(value);
119 }
120
121 unsigned long StatBag::read(const string &key)
122 {
123 exists(key);
124 funcstats_t::const_iterator iter = d_funcstats.find(key);
125 if(iter != d_funcstats.end())
126 return iter->second(iter->first);
127 return *d_stats[key];
128 }
129
130 unsigned long StatBag::readZero(const string &key)
131 {
132 exists(key);
133 unsigned long tmp=*d_stats[key];
134 d_stats[key]=0;
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
153 AtomicCounter *StatBag::getPointer(const string &key)
154 {
155 exists(key);
156 return d_stats[key];
157 }
158
159 StatBag::~StatBag()
160 {
161 for(const auto& i: d_stats) {
162 delete i.second;
163 }
164
165 }
166
167 template<typename T, typename Comp>
168 StatRing<T,Comp>::StatRing(unsigned int size)
169 {
170 d_items.set_capacity(size);
171 pthread_mutex_init(&d_lock, 0);
172 }
173
174 template<typename T, typename Comp>
175 void StatRing<T,Comp>::account(const T& t)
176 {
177 Lock l(&d_lock);
178 d_items.push_back(t);
179 }
180
181 template<typename T, typename Comp>
182 unsigned int StatRing<T,Comp>::getSize()
183 {
184 Lock l(&d_lock);
185 return d_items.capacity();
186 }
187
188 template<typename T, typename Comp>
189 void StatRing<T,Comp>::resize(unsigned int newsize)
190 {
191 Lock l(&d_lock);
192 d_items.set_capacity(newsize);
193 }
194
195
196 template<typename T, typename Comp>
197 void StatRing<T,Comp>::setHelp(const string &str)
198 {
199 d_help=str;
200 }
201
202 template<typename T, typename Comp>
203 string StatRing<T,Comp>::getHelp()
204 {
205 return d_help;
206 }
207
208
209 template<typename T, typename Comp>
210 vector<pair<T, unsigned int> >StatRing<T,Comp>::get() const
211 {
212 Lock l(&d_lock);
213 map<T,unsigned int, Comp> res;
214 for(typename boost::circular_buffer<T>::const_iterator i=d_items.begin();i!=d_items.end();++i) {
215 res[*i]++;
216 }
217
218 vector<pair<T ,unsigned int> > tmp;
219 for(typename map<T, unsigned int>::const_iterator i=res.begin();i!=res.end();++i)
220 tmp.push_back(*i);
221
222 sort(tmp.begin(),tmp.end(),popisort);
223
224 return tmp;
225 }
226
227 void StatBag::declareRing(const string &name, const string &help, unsigned int size)
228 {
229 d_rings[name]=StatRing<string, CIStringCompare>(size);
230 d_rings[name].setHelp(help);
231 }
232
233 void StatBag::declareComboRing(const string &name, const string &help, unsigned int size)
234 {
235 d_comborings[name]=StatRing<SComboAddress>(size);
236 d_comborings[name].setHelp(help);
237 }
238
239 void StatBag::declareDNSNameQTypeRing(const string &name, const string &help, unsigned int size)
240 {
241 d_dnsnameqtyperings[name] = StatRing<std::tuple<DNSName, QType> >(size);
242 d_dnsnameqtyperings[name].setHelp(help);
243 }
244
245
246 vector<pair<string, unsigned int> > StatBag::getRing(const string &name)
247 {
248 if(d_rings.count(name)) {
249 return d_rings[name].get();
250 }
251 vector<pair<string, unsigned int> > ret;
252
253 if (d_comborings.count(name)) {
254 typedef pair<SComboAddress, unsigned int> stor_t;
255 vector<stor_t> raw =d_comborings[name].get();
256 for(const stor_t& stor : raw) {
257 ret.push_back(make_pair(stor.first.ca.toString(), stor.second));
258 }
259 } else if(d_dnsnameqtyperings.count(name)) {
260 auto raw = d_dnsnameqtyperings[name].get();
261 for (auto const &e : raw) {
262 ret.push_back(make_pair(std::get<0>(e.first).toLogString() + "/" + std::get<1>(e.first).getName(), e.second));
263 }
264 }
265 return ret;
266 }
267
268 template<typename T, typename Comp>
269 void StatRing<T,Comp>::reset()
270 {
271 Lock l(&d_lock);
272 d_items.clear();
273 }
274
275 void StatBag::resetRing(const string &name)
276 {
277 if(d_rings.count(name))
278 d_rings[name].reset();
279 if(d_comborings.count(name))
280 d_comborings[name].reset();
281 if(d_dnsnameqtyperings.count(name))
282 d_dnsnameqtyperings[name].reset();
283 }
284
285 void StatBag::resizeRing(const string &name, unsigned int newsize)
286 {
287 if(d_rings.count(name))
288 d_rings[name].resize(newsize);
289 if(d_comborings.count(name))
290 d_comborings[name].resize(newsize);
291 if(d_dnsnameqtyperings.count(name))
292 return d_dnsnameqtyperings[name].resize(newsize);
293 }
294
295
296 unsigned int StatBag::getRingSize(const string &name)
297 {
298 if(d_rings.count(name))
299 return d_rings[name].getSize();
300 if(d_comborings.count(name))
301 return d_comborings[name].getSize();
302 if(d_dnsnameqtyperings.count(name))
303 return d_dnsnameqtyperings[name].getSize();
304 return 0;
305 }
306
307 string StatBag::getRingTitle(const string &name)
308 {
309 if(d_rings.count(name))
310 return d_rings[name].getHelp();
311 if(d_comborings.count(name))
312 return d_comborings[name].getHelp();
313 if(d_dnsnameqtyperings.count(name))
314 return d_dnsnameqtyperings[name].getHelp();
315 return "";
316 }
317
318 vector<string>StatBag::listRings()
319 {
320 vector<string> ret;
321 for(auto i=d_rings.begin();i!=d_rings.end();++i)
322 ret.push_back(i->first);
323 for(auto i=d_comborings.begin();i!=d_comborings.end();++i)
324 ret.push_back(i->first);
325 for(const auto &i : d_dnsnameqtyperings)
326 ret.push_back(i.first);
327
328 return ret;
329 }
330
331 bool StatBag::ringExists(const string &name)
332 {
333 return d_rings.count(name) || d_comborings.count(name) || d_dnsnameqtyperings.count(name);
334 }
335
336 void StatBag::blacklist(const string& str) {
337 d_blacklist.insert(str);
338 }
339
340 template class StatRing<std::string, CIStringCompare>;
341 template class StatRing<SComboAddress>;
342 template class StatRing<std::tuple<DNSName, QType> >;