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

« back to all changes in this revision

Viewing changes to pdns/recursor_cache.cc

  • Committer: Bazaar Package Importer
  • Author(s): Debian PowerDNS Maintainers
  • Date: 2006-05-06 10:40:44 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20060506104044-v9hczzfl7dcri6qt
Tags: 2.9.20-3
Disable the recursor, this is in a separate package now.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
#include <iostream>
4
4
#include <boost/shared_ptr.hpp>
5
5
#include "dnsrecords.hh"
 
6
 
6
7
using namespace std;
7
8
using namespace boost;
8
9
 
 
10
#include "config.h"
 
11
#ifdef GCC_SKIP_LOCKING
 
12
#include <bits/atomicity.h>
 
13
// This code is ugly but does speedup the recursor tremendously on multi-processor systems, and even has a large effect (20, 30%) on uniprocessor 
 
14
namespace __gnu_cxx
 
15
{
 
16
  _Atomic_word
 
17
  __attribute__ ((__unused__))
 
18
  __exchange_and_add(volatile _Atomic_word* __mem, int __val)
 
19
  {
 
20
    register _Atomic_word __result=*__mem;
 
21
    *__mem+=__val;
 
22
    return __result;
 
23
  }
 
24
 
 
25
  void
 
26
  __attribute__ ((__unused__))
 
27
  __atomic_add(volatile _Atomic_word* __mem, int __val)
 
28
  {
 
29
    *__mem+=__val;
 
30
  }
 
31
}
 
32
#endif
 
33
 
9
34
DNSResourceRecord String2DNSRR(const string& qname, const QType& qt, const string& serial, uint32_t ttd)
10
35
{
11
36
  shared_ptr<DNSRecordContent> regen=DNSRecordContent::unserialize(qname,qt.getCode(), serial);
15
40
  rr.content=regen->getZoneRepresentation();
16
41
  rr.qtype=regen->d_qtype;
17
42
  //  cerr<<"Returning: '"<<rr.qname<<"' "<<rr.qtype.getName()<<"  "<<rr.ttl<<"  '"<<rr.content<<"'\n";
 
43
  rr.content.reserve(0);
 
44
  rr.qname.reserve(0);
18
45
  return rr;
19
46
}
20
47
 
31
58
 
32
59
unsigned int MemRecursorCache::size()
33
60
{
34
 
  return d_cache.size();
35
 
}
 
61
  unsigned int ret=0;
 
62
  for(cache_t::const_iterator i=d_cache.begin(); i!=d_cache.end(); ++i) {
 
63
    ret+=i->d_name.size();
 
64
  }
 
65
  return ret;
 
66
}
 
67
 
 
68
unsigned int MemRecursorCache::bytes()
 
69
{
 
70
  unsigned int ret=0;
 
71
 
 
72
  for(cache_t::const_iterator i=d_cache.begin(); i!=d_cache.end(); ++i) {
 
73
    ret+=i->d_name.length();
 
74
    for(vector<StoredRecord>::const_iterator j=i->d_records.begin(); j!= i->d_records.end(); ++j)
 
75
      ret+=j->size();
 
76
  }
 
77
  return ret;
 
78
}
 
79
 
36
80
 
37
81
int MemRecursorCache::get(time_t now, const string &qname, const QType& qt, set<DNSResourceRecord>* res)
38
82
{
39
83
  unsigned int ttd=0;
40
 
  cache_t::const_iterator j=d_cache.find(toLowerCanonic(qname)+"|"+qt.getName());
 
84
  uint16_t code=qt.getCode();
 
85
  string key(toLowerCanonic(qname)); key.append(1,'|'); key.append((char*)&code, ((char*)&code)+2);
 
86
  cache_t::const_iterator j=d_cache.find(key);
41
87
  //  cerr<<"looking up "<< toLowerCanonic(qname)+"|"+qt.getName() << endl;
42
88
  if(res)
43
89
    res->clear();
44
90
 
45
 
  if(j!=d_cache.end() && j->first==toLowerCanonic(qname)+"|"+qt.getName() && j->second.begin()->d_ttd>(unsigned int)now) {
 
91
  if(j!=d_cache.end() && j->d_records.begin()->d_ttd>(unsigned int)now) {
46
92
    if(res) {
47
 
      for(set<StoredRecord>::const_iterator k=j->second.begin(); k != j->second.end(); ++k) {
 
93
      for(vector<StoredRecord>::const_iterator k=j->d_records.begin(); k != j->d_records.end(); ++k) {
48
94
        DNSResourceRecord rr=String2DNSRR(qname, qt,  k->d_string, ttd=k->d_ttd); 
49
95
        //      cerr<<"Returning '"<<rr.content<<"'\n";
50
96
        res->insert(rr);
57
103
  
58
104
  return -1;
59
105
}
60
 
  
 
106
 
 
107
/* the code below is rather tricky - it basically replaces the stuff cached for qname by content, but it is special
 
108
   cased for when inserting identical records with only differing ttls, in which case the entry is not
 
109
   touched, but only given a new ttd */
61
110
void MemRecursorCache::replace(const string &qname, const QType& qt,  const set<DNSResourceRecord>& content)
62
111
{
63
 
  set<StoredRecord>& stored=d_cache[toLowerCanonic(qname)+"|"+qt.getName()];
64
 
  stored.clear();
 
112
  int code=qt.getCode();
 
113
  string key(toLowerCanonic(qname)); key.append(1,'|'); key.append((char*)&code, ((char*)&code)+2);
 
114
  cache_t::iterator stored=d_cache.find(key);
 
115
  
 
116
  bool isNew=false;
 
117
  if(stored == d_cache.end()) {
 
118
    stored=d_cache.insert(CacheEntry(key,vector<StoredRecord>())).first;
 
119
    isNew=true;
 
120
  }
 
121
 
 
122
  pair<vector<StoredRecord>::iterator, vector<StoredRecord>::iterator> range;
 
123
 
 
124
  StoredRecord dr;
 
125
  CacheEntry ce=*stored;
 
126
 
65
127
  for(set<DNSResourceRecord>::const_iterator i=content.begin(); i != content.end(); ++i) {
66
 
    StoredRecord dr;
67
128
    dr.d_ttd=i->ttl;
68
129
    dr.d_string=DNSRR2String(*i);
69
 
    stored.insert(dr);
70
 
    //cerr<<"Storing: "<< toLowerCanonic(qname)+"|"+qt.getName() << " <=> '"<<i->content<<"', ttd="<<i->ttl<<endl;
71
 
  }
72
 
}
73
 
  
74
 
void MemRecursorCache::doPrune(void)
75
 
{
76
 
  unsigned int names=0, records=0;
77
 
  time_t now=time(0);
78
 
  for(cache_t::iterator j=d_cache.begin();j!=d_cache.end();){
79
 
    for(set<StoredRecord>::iterator k=j->second.begin();k!=j->second.end();) 
80
 
      if((unsigned int)k->d_ttd < (unsigned int) now) {
81
 
        k->d_string.prune();
82
 
        j->second.erase(k++);
83
 
        records++;
84
 
      }
85
 
      else
86
 
        ++k;
87
130
    
88
 
    if(j->second.empty()) { // everything is gone
89
 
      d_cache.erase(j++);
90
 
      names++;
 
131
    if(isNew) 
 
132
      ce.d_records.push_back(dr);
 
133
    else {
 
134
      range=equal_range(ce.d_records.begin(), ce.d_records.end(), dr);
91
135
      
 
136
      if(range.first != range.second) {
 
137
        for(vector<StoredRecord>::iterator j=range.first ; j!=range.second; ++j)
 
138
          j->d_ttd=i->ttl;
 
139
      }
 
140
      else {
 
141
        ce.d_records.push_back(dr);
 
142
        sort(ce.d_records.begin(), ce.d_records.end());
 
143
      }
 
144
    }
 
145
  }
 
146
  if(isNew) {
 
147
    sort(ce.d_records.begin(), ce.d_records.end());
 
148
  }
 
149
 
 
150
  if(ce.d_records.capacity() != ce.d_records.size())
 
151
    vector<StoredRecord>(ce.d_records).swap(ce.d_records);
 
152
 
 
153
  d_cache.replace(stored, ce);
 
154
}
 
155
 
 
156
 
 
157
 
 
158
void MemRecursorCache::doPrune(void)
 
159
{
 
160
  unsigned int names=0;
 
161
  uint32_t now=(uint32_t)time(0);
 
162
 
 
163
//  cout<<"Going to prune!\n";
 
164
 
 
165
  typedef cache_t::nth_index<1>::type cache_by_ttd_t;
 
166
  cache_by_ttd_t& ttdindex=d_cache.get<1>();
 
167
 
 
168
  uint32_t looked(0), quickZonk(0), fullZonk(0), partialZonk(0), noZonk(0);
 
169
  DTime dt;
 
170
  dt.set(); 
 
171
  cache_by_ttd_t::iterator j;
 
172
  for(j=ttdindex.begin();j!=ttdindex.end();){
 
173
    if(j->getTTD() > now) {
 
174
//      cout<<"Done pruning, this record ("<<j->d_name<<") only needs to get killed in "<< j->getTTD() - now <<" seconds, rest will be later\n";
 
175
      break;
 
176
    }
 
177
    else 
 
178
        ;
 
179
//      cout<<"Looking at '"<<j->d_name<<"', "<<now - j->getTTD()<<" seconds overdue!\n";
 
180
    looked++;
 
181
    if(j->d_records.size()==1) {
 
182
//      ttdindex.erase(j++);
 
183
      j++;
 
184
      quickZonk++;
 
185
      continue;
 
186
    }
 
187
    predicate p(now);
 
188
    CacheEntry ce=*j;
 
189
 
 
190
    size_t before=ce.d_records.size();
 
191
    ce.d_records.erase(remove_if(ce.d_records.begin(), ce.d_records.end(), p), ce.d_records.end());
 
192
 
 
193
    if(ce.d_records.empty()) { // everything is gone
 
194
//      cout<<"Zonked it entirely!\n";
 
195
//      ttdindex.erase(j++);
 
196
      j++;
 
197
      fullZonk++;
92
198
    }
93
199
    else {
94
 
      ++j;
 
200
      if(ce.d_records.size()!=before) {
 
201
//      cout<<"Zonked partially, putting back, new TTD: "<< ce.getTTD() - now<<endl;;
 
202
        cache_by_ttd_t::iterator here=j++;
 
203
        ttdindex.replace(here, ce);
 
204
        partialZonk++;
 
205
      }
 
206
      else {
 
207
        ++j;
 
208
        noZonk++;
 
209
        break;
 
210
      }
95
211
    }
96
212
  }
 
213
  
 
214
//  cout<<"Walk took "<< dt.udiff()<<"usec\n";
 
215
  dt.set();
 
216
  ttdindex.erase(ttdindex.begin(), j);
 
217
  //  cout<<"Erase took "<< dt.udiff()<<" usec, looked: "<<looked<<", quick: "<<quickZonk<<", full: ";
 
218
  //  cout<<fullZonk<<", partial: "<<partialZonk<<", no: "<<noZonk<<"\n";
 
219
  //  cache_t(d_cache).swap(d_cache);
97
220
}
98
221