]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/statbag.cc
Initial revision
[thirdparty/pdns.git] / pdns / statbag.cc
CommitLineData
12c86877
BH
1/*
2 PowerDNS Versatile Database Driven Nameserver
3 Copyright (C) 2002 PowerDNS.COM BV
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18*/
19\r
20#include "utility.hh"\r
21#include "statbag.hh"
22#include "ahuexception.hh"
23#include <iostream>
24#include <sstream>
25#include <algorithm>
26#include "arguments.hh"
27#include "lock.hh"
28
29using namespace std;
30
31StatBag::StatBag()
32{
33 d_doRings=false;
34 pthread_mutex_init(&d_lock,0);
35}
36
37
38
39/** this NEEDS TO HAVE THE LOCK held already! */
40void StatBag::exists(const string &key)
41{
42 if(!d_stats.count(key))
43 {
44 unlock(); // it's the details that count
45 throw AhuException("Trying to deposit into unknown StatBag key '"+key+"'");
46 }
47}
48
49string StatBag::directory()
50{
51 string dir;
52 ostringstream o;
53 lock();
54 for(map<string,int *>::const_iterator i=d_stats.begin();
55 i!=d_stats.end();
56 i++)
57 {
58 o<<i->first<<"="<<*(i->second)<<",";
59 }
60 unlock();
61 dir=o.str();
62 return dir;
63}
64
65
66vector<string>StatBag::getEntries()
67{
68 vector<string> ret;
69 lock();
70 for(map<string,int *>::const_iterator i=d_stats.begin();
71 i!=d_stats.end();
72 i++)
73 ret.push_back(i->first);
74
75 unlock();
76 return ret;
77
78}
79
80string StatBag::getDescrip(const string &item)
81{
82 lock();
83 string tmp=d_keyDescrips[item];
84 unlock();
85 return tmp;
86}
87
88void StatBag::declare(const string &key, const string &descrip)
89{
90 lock();
91 int *i=new int(0);
92 d_stats[key]=i;
93 d_keyDescrips[key]=descrip;
94 unlock();
95}
96
97
98
99void StatBag::set(const string &key, int value)
100{
101 lock();
102 exists(key);
103 *d_stats[key]=value;
104
105 unlock();
106}
107
108int StatBag::read(const string &key)
109{
110 lock();
111
112 if(!d_stats.count(key))
113 {
114 unlock();
115 return 0;
116 }
117
118 int tmp=*d_stats[key];
119
120 unlock();
121 return tmp;
122
123}
124
125int StatBag::readZero(const string &key)
126{
127 lock();
128
129
130 if(!d_stats.count(key))
131 {
132 unlock();
133 return 0;
134 }
135
136
137 int tmp=*d_stats[key];
138 d_stats[key]=0;
139
140 unlock();
141
142 return tmp;
143}
144
145
146string StatBag::getValueStr(const string &key)
147{
148 ostringstream o;
149 o<<read(key);
150 return o.str();
151}
152
153string StatBag::getValueStrZero(const string &key)
154{
155 ostringstream o;
156 o<<readZero(key);
157 return o.str();
158}
159
160int *StatBag::getPointer(const string &key)
161{
162 exists(key);
163 return d_stats[key];
164}
165
166StatBag::~StatBag()
167{
168 for(map<string,int *>::const_iterator i=d_stats.begin();
169 i!=d_stats.end();
170 i++)
171 {
172 delete i->second;
173 }
174
175}
176
177StatRing::StatRing(int size)
178{
179 d_size=size;
180 d_items.resize(d_size);
181 d_lock=0;
182 d_pos=0;
183 d_lock=new pthread_mutex_t;
184 pthread_mutex_init(d_lock, 0);
185}
186
187void StatRing::resize(int newsize)
188{
189 if(d_size==newsize)
190 return;
191 Lock l(d_lock);
192
193 if(newsize>d_size) {
194 d_size=newsize;
195 d_items.resize(d_size);
196 return;
197 }
198
199 // this is the hard part, shrink
200 int startpos=d_pos-newsize;
201 int rpos;
202 vector<string>newring;
203 for(int i=startpos;i<d_pos;++i) {
204 rpos=i>=0 ? i : i+d_size;
205
206 newring.push_back(d_items[rpos%d_size]);
207 }
208 d_items=newring;
209 d_size=newsize;
210 d_pos=d_size-1;
211
212}
213StatRing::~StatRing()
214{
215 // do not clean up d_lock, it is shared
216}
217
218void StatRing::setHelp(const string &str)
219{
220 d_help=str;
221}
222
223string StatRing::getHelp()
224{
225 return d_help;
226}
227
228static bool popisort(const pair<string,int> &a, const pair<string,int> &b)
229{
230 return (a.second > b.second);
231}
232
233vector<pair<string,int> >StatRing::get() const
234{
235 Lock l(d_lock);
236 map<string,int> res;
237 for(vector<string>::const_iterator i=d_items.begin();i!=d_items.end();++i) {
238 if(!i->empty())
239 res[*i]++;
240 }
241
242 vector<pair<string,int> > tmp;
243 for(map<string,int>::const_iterator i=res.begin();i!=res.end();++i)
244 tmp.push_back(*i);
245
246 sort(tmp.begin(),tmp.end(),popisort);
247
248 return tmp;
249}
250
251void StatBag::declareRing(const string &name, const string &help, unsigned int size)
252{
253 d_rings[name]=StatRing(size);
254 d_rings[name].setHelp(help);
255}
256
257vector<pair<string,int> > StatBag::getRing(const string &name)
258{
259 return d_rings[name].get();
260}
261
262void StatRing::reset()
263{
264 Lock l(d_lock);
265 for(vector<string>::iterator i=d_items.begin();i!=d_items.end();++i) {
266 if(!i->empty())
267 *i="";
268 }
269}
270
271void StatBag::resetRing(const string &name)
272{
273 d_rings[name].reset();
274}
275
276void StatBag::resizeRing(const string &name, int newsize)
277{
278 d_rings[name].resize(newsize);
279}
280
281
282int StatBag::getRingSize(const string &name)
283{
284 return d_rings[name].getSize();
285}
286
287
288string StatBag::getRingTitle(const string &name)
289{
290 return d_rings[name].getHelp();
291}
292
293vector<string>StatBag::listRings()
294{
295 vector<string> ret;
296 for(map<string,StatRing>::const_iterator i=d_rings.begin();i!=d_rings.end();++i)
297 ret.push_back(i->first);
298 return ret;
299}
300
301