summaryrefslogtreecommitdiffstats
path: root/statnode.cc
blob: e4c8f9edb50f669f79d6d6b25cf2cb2c77eac3cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include "statnode.hh"

StatNode::Stat StatNode::print(unsigned int depth, Stat newstat, bool silent) const
{
  if(!silent) {
    cout<<string(depth, ' ');
    cout<<name<<": "<<endl;
  }
  Stat childstat;
  childstat.queries += s.queries;
  childstat.noerrors += s.noerrors;
  childstat.nxdomains += s.nxdomains;
  childstat.servfails += s.servfails;
  childstat.drops += s.drops;
  childstat.bytes += s.bytes;

  if(children.size()>1024 && !silent) {
    cout<<string(depth, ' ')<<name<<": too many to print"<<endl;
  }
  for(const children_t::value_type& child :  children) {
    childstat=child.second.print(depth+8, childstat, silent || children.size()>1024);
  }
  if(!silent || children.size()>1)
    cout<<string(depth, ' ')<<childstat.queries<<" queries, " << 
      childstat.noerrors<<" noerrors, "<< 
      childstat.nxdomains<<" nxdomains, "<< 
      childstat.servfails<<" servfails, "<< 
      childstat.drops<<" drops, "<<
      childstat.bytes<<" bytes"<<endl;

  newstat+=childstat;

  return newstat;
}


void StatNode::visit(visitor_t visitor, Stat &newstat, unsigned int depth) const
{
  Stat childstat(s);

  for (const auto& child : children) {
    child.second.visit(visitor, childstat, depth+8);
  }

  visitor(this, s, childstat);

  newstat += childstat;
}


void StatNode::submit(const DNSName& domain, int rcode, unsigned int bytes, boost::optional<const ComboAddress&> remote)
{
  //  cerr<<"FIRST submit called on '"<<domain<<"'"<<endl;
  std::vector<string> tmp = domain.getRawLabels();
  if (tmp.empty()) {
    return;
  }

  auto last = tmp.end() - 1;
  children[*last].submit(last, tmp.begin(), "", rcode, bytes, remote, 1);
}

/* www.powerdns.com. -> 
   .                 <- fullnames
   com.
   powerdns.com
   www.powerdns.com. 
*/

void StatNode::submit(std::vector<string>::const_iterator end, std::vector<string>::const_iterator begin, const std::string& domain, int rcode, unsigned int bytes, boost::optional<const ComboAddress&> remote, unsigned int count)
{
  //  cerr<<"Submit called for domain='"<<domain<<"': ";
  //  for(const std::string& n :  labels) 
  //    cerr<<n<<".";
  //  cerr<<endl;
  if (name.empty()) {

    name=*end;
    //    cerr<<"Set short name to '"<<name<<"'"<<endl;
  }
  else {
    //    cerr<<"Short name was already set to '"<<name<<"'"<<endl;
  }

  if (end == begin) {
    if (fullname.empty()) {
      size_t needed = name.size() + 1 + domain.size();
      if (fullname.capacity() < needed) {
        fullname.reserve(needed);
      }
      fullname = name;
      fullname.append(".");
      fullname.append(domain);
      labelsCount = count;
    }
    //    cerr<<"Hit the end, set our fullname to '"<<fullname<<"'"<<endl<<endl;
    s.queries++;
    s.bytes += bytes;
    if(rcode<0)
      s.drops++;
    else if(rcode==0)
      s.noerrors++;
    else if(rcode==2)
      s.servfails++;
    else if(rcode==3)
      s.nxdomains++;

    if (remote) {
      s.remotes[*remote]++;
    }
  }
  else {
    if (fullname.empty()) {
      size_t needed = name.size() + 1 + domain.size();
      if (fullname.capacity() < needed) {
        fullname.reserve(needed);
      }
      fullname = name;
      fullname.append(".");
      fullname.append(domain);
      labelsCount = count;
    }
    //    cerr<<"Not yet end, set our fullname to '"<<fullname<<"', recursing"<<endl;
    --end;
    children[*end].submit(end, begin, fullname, rcode, bytes, remote, count+1);
  }
}