]>
Commit | Line | Data |
---|---|---|
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 | ||
29 | using namespace std; | |
30 | ||
31 | StatBag::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! */ | |
40 | void 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 | ||
49 | string 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 | ||
66 | vector<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 | ||
80 | string StatBag::getDescrip(const string &item) | |
81 | { | |
82 | lock(); | |
83 | string tmp=d_keyDescrips[item]; | |
84 | unlock(); | |
85 | return tmp; | |
86 | } | |
87 | ||
88 | void 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 | ||
99 | void StatBag::set(const string &key, int value) | |
100 | { | |
101 | lock(); | |
102 | exists(key); | |
103 | *d_stats[key]=value; | |
104 | ||
105 | unlock(); | |
106 | } | |
107 | ||
108 | int 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 | ||
125 | int 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 | ||
146 | string StatBag::getValueStr(const string &key) | |
147 | { | |
148 | ostringstream o; | |
149 | o<<read(key); | |
150 | return o.str(); | |
151 | } | |
152 | ||
153 | string StatBag::getValueStrZero(const string &key) | |
154 | { | |
155 | ostringstream o; | |
156 | o<<readZero(key); | |
157 | return o.str(); | |
158 | } | |
159 | ||
160 | int *StatBag::getPointer(const string &key) | |
161 | { | |
162 | exists(key); | |
163 | return d_stats[key]; | |
164 | } | |
165 | ||
166 | StatBag::~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 | ||
177 | StatRing::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 | ||
187 | void 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 | } | |
213 | StatRing::~StatRing() | |
214 | { | |
215 | // do not clean up d_lock, it is shared | |
216 | } | |
217 | ||
218 | void StatRing::setHelp(const string &str) | |
219 | { | |
220 | d_help=str; | |
221 | } | |
222 | ||
223 | string StatRing::getHelp() | |
224 | { | |
225 | return d_help; | |
226 | } | |
227 | ||
228 | static bool popisort(const pair<string,int> &a, const pair<string,int> &b) | |
229 | { | |
230 | return (a.second > b.second); | |
231 | } | |
232 | ||
233 | vector<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 | ||
251 | void 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 | ||
257 | vector<pair<string,int> > StatBag::getRing(const string &name) | |
258 | { | |
259 | return d_rings[name].get(); | |
260 | } | |
261 | ||
262 | void 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 | ||
271 | void StatBag::resetRing(const string &name) | |
272 | { | |
273 | d_rings[name].reset(); | |
274 | } | |
275 | ||
276 | void StatBag::resizeRing(const string &name, int newsize) | |
277 | { | |
278 | d_rings[name].resize(newsize); | |
279 | } | |
280 | ||
281 | ||
282 | int StatBag::getRingSize(const string &name) | |
283 | { | |
284 | return d_rings[name].getSize(); | |
285 | } | |
286 | ||
287 | ||
288 | string StatBag::getRingTitle(const string &name) | |
289 | { | |
290 | return d_rings[name].getHelp(); | |
291 | } | |
292 | ||
293 | vector<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 |