]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/statbag.hh
rec: Don't account chained queries more than once
[thirdparty/pdns.git] / pdns / statbag.hh
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 #ifndef STATBAG_HH
23 #define STATBAG_HH
24 #include <pthread.h>
25 #include <map>
26 #include <functional>
27 #include <string>
28 #include <vector>
29 #include "lock.hh"
30 #include "namespaces.hh"
31 #include "iputils.hh"
32 #include <boost/circular_buffer.hpp>
33
34
35
36 template<typename T, typename Comp=std::less<T> >
37 class StatRing
38 {
39 public:
40 StatRing(unsigned int size=10000);
41 void account(const T &item);
42
43 unsigned int getSize();
44 void resize(unsigned int newsize);
45 void reset();
46 void setHelp(const string &str);
47 string getHelp();
48
49 vector<pair<T, unsigned int> > get() const;
50 private:
51 static bool popisort(const pair<T,int> &a, const pair<T,int> &b)
52 {
53 return (a.second > b.second);
54 }
55
56 boost::circular_buffer<T> d_items;
57 mutable pthread_mutex_t d_lock;
58 string d_help;
59 };
60
61
62 //! use this to gather and query statistics
63 class StatBag
64 {
65 map<string, AtomicCounter *> d_stats;
66 map<string, string> d_keyDescrips;
67 map<string,StatRing<string> >d_rings;
68 map<string,StatRing<SComboAddress> >d_comborings;
69 typedef boost::function<uint64_t(const std::string&)> func_t;
70 typedef map<string, func_t> funcstats_t;
71 funcstats_t d_funcstats;
72 bool d_doRings;
73
74 public:
75 StatBag(); //!< Naked constructor. You need to declare keys before this class becomes useful
76 ~StatBag();
77 void declare(const string &key, const string &descrip=""); //!< Before you can store or access a key, you need to declare it
78 void declare(const string &key, const string &descrip, func_t func); //!< Before you can store or access a key, you need to declare it
79
80 void declareRing(const string &name, const string &title, unsigned int size=10000);
81 void declareComboRing(const string &name, const string &help, unsigned int size=10000);
82 vector<pair<string, unsigned int> >getRing(const string &name);
83 string getRingTitle(const string &name);
84 void ringAccount(const char* name, const string &item)
85 {
86 if(d_doRings) {
87 if(!d_rings.count(name))
88 throw runtime_error("Attempting to account to non-existent ring '"+std::string(name)+"'");
89
90 d_rings[name].account(item);
91 }
92 }
93 void ringAccount(const char* name, const ComboAddress &item)
94 {
95 if(d_doRings) {
96 if(!d_comborings.count(name))
97 throw runtime_error("Attempting to account to non-existent comboring '"+std::string(name)+"'");
98 d_comborings[name].account(item);
99 }
100 }
101
102 void doRings()
103 {
104 d_doRings=true;
105 }
106
107 vector<string>listRings();
108 bool ringExists(const string &name);
109 void resetRing(const string &name);
110 void resizeRing(const string &name, unsigned int newsize);
111 unsigned int getRingSize(const string &name);
112
113 string directory(); //!< Returns a list of all data stored
114 vector<string> getEntries(); //!< returns a vector with datums (items)
115 string getDescrip(const string &item); //!< Returns the description of this datum/item
116 void exists(const string &key); //!< call this function to throw an exception in case a key does not exist
117 inline void deposit(const string &key, int value); //!< increment the statistics behind this key by value amount
118 inline void inc(const string &key); //!< increase this key's value by one
119 void set(const string &key, unsigned long value); //!< set this key's value
120 unsigned long read(const string &key); //!< read the value behind this key
121 unsigned long readZero(const string &key); //!< read the value behind this key, and zero it afterwards
122 AtomicCounter *getPointer(const string &key); //!< get a direct pointer to the value behind a key. Use this for high performance increments
123 string getValueStr(const string &key); //!< read a value behind a key, and return it as a string
124 string getValueStrZero(const string &key); //!< read a value behind a key, and return it as a string, and zero afterwards
125 };
126
127 inline void StatBag::deposit(const string &key, int value)
128 {
129 exists(key);
130
131 *d_stats[key]+=value;
132 }
133
134 inline void StatBag::inc(const string &key)
135 {
136 deposit(key,1);
137 }
138
139
140 #endif /* STATBAG_HH */