~ubuntu-branches/ubuntu/maverick/pdns/maverick-updates

« back to all changes in this revision

Viewing changes to pdns/rec_channel_rec.cc

  • Committer: Bazaar Package Importer
  • Author(s): Matthijs Mohlmann, Matthijs Mohlmann, Christoph Haas
  • Date: 2007-04-15 23:23:39 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070415232339-5x3scc8gx04e50um
Tags: 2.9.21-1
[ Matthijs Mohlmann ]
* New upstream release. (Closes: #420294)
* Remove meta pdns package.
* Added new sqlite3 backend package.
* Months and minutes where mixed up. (Closes: #406462)
* Case sensitivity in bind backend caused PowerDNS to not serve a certain
  zone. (Closes: #406461)
* Bind backend forgot about zones on a notify. (Closes: #398213)

[ Christoph Haas ]
* Documented incorporated backend bind. (Closes: #415471)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "utility.hh"
 
2
#include "rec_channel.hh"
 
3
#include <boost/lexical_cast.hpp>
 
4
#include <boost/bind.hpp>
 
5
#include <vector>
 
6
#include "misc.hh"
 
7
#include "recursor_cache.hh"
 
8
#include "syncres.hh"
 
9
#include <boost/function.hpp>
 
10
#include <boost/optional.hpp>
 
11
#include <boost/tuple/tuple.hpp>
 
12
#include <boost/format.hpp>
 
13
#include <sys/types.h>
 
14
#include <sys/stat.h>
 
15
#include <fcntl.h>
 
16
#include "logger.hh"
 
17
#include "dnsparser.hh"
 
18
#ifndef WIN32
 
19
#include <sys/resource.h>
 
20
#include <sys/time.h>
 
21
#endif
 
22
 
 
23
using namespace std;
 
24
using namespace boost;
 
25
map<string, const uint32_t*> d_get32bitpointers;
 
26
map<string, const uint64_t*> d_get64bitpointers;
 
27
map<string, function< uint32_t() > >  d_get32bitmembers;
 
28
 
 
29
void addGetStat(const string& name, const uint32_t* place)
 
30
{
 
31
  d_get32bitpointers[name]=place;
 
32
}
 
33
void addGetStat(const string& name, const uint64_t* place)
 
34
{
 
35
  d_get64bitpointers[name]=place;
 
36
}
 
37
void addGetStat(const string& name, function<uint32_t ()> f ) 
 
38
{
 
39
  d_get32bitmembers[name]=f;
 
40
}
 
41
 
 
42
optional<uint64_t> get(const string& name) 
 
43
{
 
44
  optional<uint64_t> ret;
 
45
 
 
46
  if(d_get32bitpointers.count(name))
 
47
    return *d_get32bitpointers.find(name)->second;
 
48
  if(d_get64bitpointers.count(name))
 
49
    return *d_get64bitpointers.find(name)->second;
 
50
  if(d_get32bitmembers.count(name))
 
51
    return d_get32bitmembers.find(name)->second();
 
52
 
 
53
  return ret;
 
54
}
 
55
 
 
56
 
 
57
template<typename T>
 
58
string doGet(T begin, T end)
 
59
{
 
60
  string ret;
 
61
 
 
62
  for(T i=begin; i != end; ++i) {
 
63
    optional<uint64_t> num=get(*i);
 
64
    if(num)
 
65
      ret+=lexical_cast<string>(*num)+"\n";
 
66
    else
 
67
      ret+="UNKNOWN\n";
 
68
  }
 
69
  return ret;
 
70
}
 
71
 
 
72
template<typename T>
 
73
string doDumpCache(T begin, T end)
 
74
{
 
75
  T i=begin;
 
76
  string fname;
 
77
 
 
78
  if(i!=end) 
 
79
    fname=*i;
 
80
 
 
81
  int fd=open(fname.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0660);
 
82
  if(fd < 0) 
 
83
    return "Error opening dump file for writing: "+string(strerror(errno))+"\n";
 
84
 
 
85
  RC.doDumpAndClose(fd); 
 
86
 
 
87
  return "done\n";
 
88
}
 
89
 
 
90
template<typename T>
 
91
string doWipeCache(T begin, T end)
 
92
{
 
93
  int count=0;
 
94
  for(T i=begin; i != end; ++i)
 
95
    count+=RC.doWipeCache(toCanonic("", *i));
 
96
 
 
97
  return "wiped "+lexical_cast<string>(count)+" records\n";
 
98
}
 
99
 
 
100
template<typename T>
 
101
string doSlashCache(T begin, T end)
 
102
{
 
103
  RC.doSlash(10);
 
104
 
 
105
  return "done\n";
 
106
}
 
107
 
 
108
#if 0  // broken!
 
109
uint32_t getQueryRate()
 
110
{
 
111
  struct timeval now;
 
112
  gettimeofday(&now, 0);
 
113
  optional<float> delay=g_stats.queryrate.get(now, 10);
 
114
  if(delay)
 
115
    return (uint32_t)(1000000/(*delay));
 
116
  else
 
117
    return 0;
 
118
}
 
119
#endif 
 
120
 
 
121
#ifndef WIN32
 
122
static uint64_t getSysTimeMsec()
 
123
{
 
124
  struct rusage ru;
 
125
  getrusage(RUSAGE_SELF, &ru);
 
126
  return (ru.ru_stime.tv_sec*1000ULL + ru.ru_stime.tv_usec/1000);
 
127
}
 
128
 
 
129
static uint64_t getUserTimeMsec()
 
130
{
 
131
  struct rusage ru;
 
132
  getrusage(RUSAGE_SELF, &ru);
 
133
  return (ru.ru_utime.tv_sec*1000ULL + ru.ru_utime.tv_usec/1000);
 
134
}
 
135
#endif
 
136
 
 
137
static uint64_t calculateUptime()
 
138
{
 
139
  return time(0) - g_stats.startupTime;
 
140
}
 
141
 
 
142
static string doCurrentQueries()
 
143
{
 
144
  ostringstream ostr;
 
145
 
 
146
  ostr << MT->d_waiters.size() <<" currently outstanding questions\n";
 
147
 
 
148
  boost::format fmt("%1% %|40t|%2% %|47t|%3% %|63t|%4% %|68t|%5%\n");
 
149
 
 
150
  ostr << (fmt % "qname" % "qtype" % "remote" % "tcp" % "chained");
 
151
  int n=0;
 
152
  for(MT_t::waiters_t::iterator mthread=MT->d_waiters.begin(); mthread!=MT->d_waiters.end() && n < 100; ++mthread, ++n) {
 
153
    const PacketID& pident = mthread->key;
 
154
    ostr << (fmt 
 
155
             % pident.domain % DNSRecordContent::NumberToType(pident.type) 
 
156
             % pident.remote.toString() % (pident.sock ? 'Y' : 'n')
 
157
             % (pident.fd == -1 ? 'Y' : 'n')
 
158
             );
 
159
  }
 
160
  ostr <<" - done\n";
 
161
  return ostr.str();
 
162
}
 
163
 
 
164
RecursorControlParser::RecursorControlParser()
 
165
{
 
166
  addGetStat("questions", &g_stats.qcounter);
 
167
  addGetStat("tcp-questions", &g_stats.tcpqcounter);
 
168
 
 
169
  addGetStat("cache-hits", &RC.cacheHits);
 
170
  addGetStat("cache-misses", &RC.cacheMisses);
 
171
 
 
172
  addGetStat("cache-entries", boost::bind(&MemRecursorCache::size, ref(RC)));
 
173
  addGetStat("servfail-answers", &g_stats.servFails);
 
174
  addGetStat("nxdomain-answers", &g_stats.nxDomains);
 
175
  addGetStat("noerror-answers", &g_stats.noErrors);
 
176
 
 
177
  addGetStat("unauthorized-udp", &g_stats.unauthorizedUDP);
 
178
  addGetStat("unauthorized-tcp", &g_stats.unauthorizedTCP);
 
179
  addGetStat("tcp-client-overflow", &g_stats.tcpClientOverflow);
 
180
 
 
181
  addGetStat("client-parse-errors", &g_stats.clientParseError);
 
182
  addGetStat("server-parse-errors", &g_stats.serverParseError);
 
183
 
 
184
  addGetStat("answers0-1", &g_stats.answers0_1);
 
185
  addGetStat("answers1-10", &g_stats.answers1_10);
 
186
  addGetStat("answers10-100", &g_stats.answers10_100);
 
187
  addGetStat("answers100-1000", &g_stats.answers100_1000);
 
188
  addGetStat("answers-slow", &g_stats.answersSlow);
 
189
 
 
190
  addGetStat("qa-latency", &g_stats.avgLatencyUsec);
 
191
  addGetStat("unexpected-packets", &g_stats.unexpectedCount);
 
192
  addGetStat("spoof-prevents", &g_stats.spoofCount);
 
193
 
 
194
  addGetStat("nsset-invalidations", &g_stats.nsSetInvalidations);
 
195
 
 
196
  addGetStat("resource-limits", &g_stats.resourceLimits);
 
197
  addGetStat("dlg-only-drops", &SyncRes::s_nodelegated);
 
198
  
 
199
  addGetStat("shunted-queries", &g_stats.shunted);
 
200
  addGetStat("noshunt-size", &g_stats.noShuntSize);
 
201
  addGetStat("noshunt-expired", &g_stats.noShuntExpired);
 
202
  addGetStat("noshunt-nomatch", &g_stats.noShuntNoMatch);
 
203
  addGetStat("noshunt-cname", &g_stats.noShuntCNAME);
 
204
  addGetStat("noshunt-wrong-question", &g_stats.noShuntWrongQuestion);
 
205
  addGetStat("noshunt-wrong-type", &g_stats.noShuntWrongType);
 
206
 
 
207
  addGetStat("negcache-entries", boost::bind(&SyncRes::negcache_t::size, ref(SyncRes::s_negcache)));
 
208
  addGetStat("throttle-entries", boost::bind(&SyncRes::throttle_t::size, ref(SyncRes::s_throttle)));
 
209
  addGetStat("nsspeeds-entries", boost::bind(&SyncRes::nsspeeds_t::size, ref(SyncRes::s_nsSpeeds)));
 
210
 
 
211
  addGetStat("concurrent-queries", boost::bind(&MTasker<PacketID,string>::numProcesses, ref(MT)));
 
212
  addGetStat("outgoing-timeouts", &SyncRes::s_outgoingtimeouts);
 
213
  addGetStat("tcp-outqueries", &SyncRes::s_tcpoutqueries);
 
214
  addGetStat("all-outqueries", &SyncRes::s_outqueries);
 
215
  addGetStat("ipv6-outqueries", &g_stats.ipv6queries);
 
216
  addGetStat("throttled-outqueries", &SyncRes::s_throttledqueries);
 
217
  addGetStat("throttled-out", &SyncRes::s_throttledqueries);
 
218
  addGetStat("unreachables", &SyncRes::s_unreachables);
 
219
  addGetStat("chain-resends", &g_stats.chainResends);
 
220
 
 
221
  addGetStat("uptime", calculateUptime);
 
222
 
 
223
#ifndef WIN32
 
224
  //  addGetStat("query-rate", getQueryRate);
 
225
  addGetStat("user-msec", getUserTimeMsec);
 
226
  addGetStat("sys-msec", getSysTimeMsec);
 
227
#endif
 
228
}
 
229
 
 
230
static void doExit()
 
231
{
 
232
  L<<Logger::Error<<"Exiting on user request"<<endl;
 
233
  extern RecursorControlChannel s_rcc;
 
234
  s_rcc.~RecursorControlChannel(); 
 
235
 
 
236
  extern string s_pidfname;
 
237
  if(!s_pidfname.empty()) 
 
238
    unlink(s_pidfname.c_str()); // we can at least try..
 
239
  _exit(1);
 
240
}
 
241
 
 
242
string doTopRemotes()
 
243
{
 
244
  typedef map<ComboAddress, int, ComboAddress::addressOnlyLessThan> counts_t;
 
245
  counts_t counts;
 
246
  
 
247
  unsigned int total=0;
 
248
  for(RecursorStats::remotes_t::const_iterator i=g_stats.remotes.begin(); i != g_stats.remotes.end(); ++i)
 
249
    if(i->sin4.sin_family) {
 
250
      total++;
 
251
      counts[*i]++;
 
252
    }
 
253
 
 
254
  typedef multimap<int, ComboAddress> rcounts_t;
 
255
  rcounts_t rcounts;
 
256
  
 
257
  for(counts_t::const_iterator i=counts.begin(); i != counts.end(); ++i)
 
258
    rcounts.insert(make_pair(-i->second, i->first));
 
259
 
 
260
  ostringstream ret;
 
261
  ret<<"Over last "<<total<<" queries:\n";
 
262
  format fmt("%.02f%%\t%s\n");
 
263
  int limit=0;
 
264
  if(total)
 
265
    for(rcounts_t::const_iterator i=rcounts.begin(); i != rcounts.end() && limit < 20; ++i, ++limit)
 
266
      ret<< fmt % (-100.0*i->first/total) % i->second.toString();
 
267
 
 
268
  return ret.str();
 
269
}
 
270
 
 
271
string RecursorControlParser::getAnswer(const string& question, RecursorControlParser::func_t** command)
 
272
{
 
273
  *command=nop;
 
274
  vector<string> words;
 
275
  stringtok(words, question);
 
276
 
 
277
  if(words.empty())
 
278
    return "invalid command\n";
 
279
 
 
280
  string cmd=toLower(words[0]);
 
281
  vector<string>::const_iterator begin=words.begin()+1, end=words.end();
 
282
 
 
283
  if(cmd=="get") 
 
284
    return doGet(begin, end);
 
285
 
 
286
  if(cmd=="quit") {
 
287
    *command=&doExit;
 
288
    return "bye\n";
 
289
  }
 
290
 
 
291
  if(cmd=="dump-cache") 
 
292
    return doDumpCache(begin, end);
 
293
 
 
294
  if(cmd=="slash-cache") 
 
295
    return doSlashCache(begin, end);
 
296
 
 
297
  if(cmd=="wipe-cache") 
 
298
    return doWipeCache(begin, end);
 
299
 
 
300
  if(cmd=="top-remotes")
 
301
    return doTopRemotes();
 
302
 
 
303
  if(cmd=="current-queries")
 
304
    return doCurrentQueries();
 
305
  
 
306
  if(cmd=="ping")
 
307
    return "pong\n";
 
308
 
 
309
  if(cmd=="reload-zones") {
 
310
    return reloadAuthAndForwards();
 
311
  }
 
312
 
 
313
  return "Unknown command '"+cmd+"'\n";
 
314
}