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