Changeset 1374
- Timestamp:
- 07/28/09 22:33:20 (4 years ago)
- Location:
- trunk/pdns/pdns
- Files:
-
- 2 modified
-
recursor_cache.cc (modified) (18 diffs)
-
recursor_cache.hh (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/pdns/pdns/recursor_cache.cc
r1265 r1374 6 6 #include "arguments.hh" 7 7 #include "syncres.hh" 8 #include "lock.hh" 9 #include "recursor_cache.hh" 8 10 9 11 using namespace std; … … 12 14 #include "config.h" 13 15 14 #ifdef GCC_SKIP_LOCKING 15 #include <bits/atomicity.h> 16 // This code is ugly but does speedup the recursor tremendously on multi-processor systems, and even has a large effect (20, 30%) on uniprocessor 17 namespace __gnu_cxx 18 { 19 _Atomic_word 20 __attribute__ ((__unused__)) 21 __exchange_and_add(volatile _Atomic_word* __mem, int __val) 22 { 23 register _Atomic_word __result=*__mem; 24 *__mem+=__val; 25 return __result; 26 } 27 28 void 29 __attribute__ ((__unused__)) 30 __atomic_add(volatile _Atomic_word* __mem, int __val) 31 { 32 *__mem+=__val; 33 } 34 } 35 #endif 36 16 pthread_rwlock_t MemRecursorCache::s_rwlock; 37 17 38 18 DNSResourceRecord String2DNSRR(const string& qname, const QType& qt, const string& serial, uint32_t ttd) … … 83 63 } 84 64 65 // returns the RDATA for rr - might be compressed! 85 66 string DNSRR2String(const DNSResourceRecord& rr) 86 67 { … … 126 107 int MemRecursorCache::getDirect(time_t now, const char* qname, const QType& qt, uint32_t ttd[10], char* data[10], uint16_t len[10]) 127 108 { 109 ReadLock rl(&s_rwlock); 110 128 111 if(!d_cachecachevalid || Utility::strcasecmp(d_cachedqname.c_str(), qname)) { 129 112 // cerr<<"had cache cache miss for '"<<qname<<"'"<<endl; … … 187 170 int MemRecursorCache::get(time_t now, const string &qname, const QType& qt, set<DNSResourceRecord>* res) 188 171 { 172 WriteLock wl(&s_rwlock); 189 173 unsigned int ttd=0; 190 174 … … 215 199 216 200 for(vector<StoredRecord>::const_iterator k=i->d_records.begin(); k != i->d_records.end(); ++k) { 217 if(k->d_ttd < 1000000000 || k->d_ttd > (uint32_t) now) { 201 if(k->d_ttd < 1000000000 || k->d_ttd > (uint32_t) now) { // FIXME what does the 100000000 number mean? 218 202 ttd=k->d_ttd; 219 203 if(res) { … … 238 222 return -1; 239 223 } 224 225 240 226 241 227 bool MemRecursorCache::attemptToRefreshNSTTL(const QType& qt, const set<DNSResourceRecord>& content, const CacheEntry& stored) 242 228 { 229 // WriteLock wl(&s_rwlock); (holds the lock already) 243 230 if(!stored.d_auth) { 244 231 // cerr<<"feel free to scribble non-auth data!"<<endl; … … 272 259 void MemRecursorCache::replace(time_t now, const string &qname, const QType& qt, const set<DNSResourceRecord>& content, bool auth) 273 260 { 261 WriteLock wl(&s_rwlock); 274 262 d_cachecachevalid=false; 275 263 tuple<string, uint16_t> key=make_tuple(qname, qt.getCode()); 276 264 cache_t::iterator stored=d_cache.find(key); 277 278 // cerr<<"storing "<< qname+"|"+qt.getName()<<" -> '"<<content.begin()->content<<"'\n";279 265 280 266 bool isNew=false; … … 283 269 isNew=true; 284 270 } 285 286 271 pair<vector<StoredRecord>::iterator, vector<StoredRecord>::iterator> range; 287 272 … … 289 274 CacheEntry ce=*stored; 290 275 291 if(qt.getCode()==QType::SOA || qt.getCode()==QType::CNAME) // you can only have one (1) each of these 276 // cerr<<"storing "<< qname+"|"+qt.getName()<<" -> '"<<content.begin()->content<<"', isnew="<<isNew<<", auth="<<auth<<", ce.auth="<<ce.d_auth<<"\n"; 277 278 if(qt.getCode()==QType::SOA || qt.getCode()==QType::CNAME) { // you can only have one (1) each of these 279 // cerr<<"\tCleaning out existing store because of SOA and CNAME\n"; 292 280 ce.d_records.clear(); 293 294 if(auth && !attemptToRefreshNSTTL(qt, content, ce) ) {295 ce.d_records.clear(); // clear non-auth data296 ce.d_auth = true;297 isNew=true; // data should be sorted again298 281 } 299 282 … … 304 287 break; 305 288 if(j != ce.d_records.end()) { // we still have valid data, ignore unauth data 289 // cerr<<"\tStill hold valid auth data, and the new data is unauth, return\n"; 306 290 return; 307 291 } … … 310 294 } 311 295 } 312 296 #if 0 297 if(auth && !attemptToRefreshNSTTL(qt, content, ce) ) { 298 cerr<<"\tGot auth data, and it was not refresh attempt of an NS record, nuking storage"<<endl; 299 ce.d_records.clear(); // clear non-auth data 300 ce.d_auth = true; 301 isNew=true; // data should be sorted again 302 } 303 #endif 304 // cerr<<"\tHave "<<content.size()<<" records to store\n"; 313 305 for(set<DNSResourceRecord>::const_iterator i=content.begin(); i != content.end(); ++i) { 314 306 dr.d_ttd=i->ttl; … … 319 311 else { 320 312 range=equal_range(ce.d_records.begin(), ce.d_records.end(), dr); 321 313 314 if(range.first != range.second && (range.first != ce.d_records.begin() || range.second != ce.d_records.end())) { 315 // cerr<<"\t\tIncomplete match! Must nuke"<<endl; 316 ce.d_records.clear(); 317 range.first = range.second = ce.d_records.begin(); 318 } 319 322 320 if(range.first != range.second) { 321 // cerr<<"\t\tMay need to modify TTL of stored record\n"; 323 322 for(vector<StoredRecord>::iterator j=range.first ; j!=range.second; ++j) { 324 323 /* see http://mailman.powerdns.com/pipermail/pdns-users/2006-May/003413.html */ 325 if(j->d_ttd > (unsigned int) now && i->ttl > j->d_ttd && qt.getCode()==QType::NS && auth) // don't allow auth servers to *raise* TTL of an NS record 324 if(j->d_ttd > (unsigned int) now && i->ttl > j->d_ttd && qt.getCode()==QType::NS && auth) { // don't allow auth servers to *raise* TTL of an NS recor 325 // cerr<<"\t\tNot doing so, trying to raise TTL NS\n"; 326 326 continue; 327 if(i->ttl > j->d_ttd || (auth && d_followRFC2181) ) // authoritative packets can override the TTL to be lower 327 } 328 if(i->ttl > j->d_ttd || (auth && d_followRFC2181) ) { // authoritative packets can override the TTL to be lower 329 // cerr<<"\t\tUpdating the ttl, diff="<<j->d_ttd - i->ttl<<endl;; 328 330 j->d_ttd=i->ttl; 331 } 332 else { 333 // cerr<<"\t\tNOT updating the ttl, old= " <<j->d_ttd - now <<", new: "<<i->ttl - now <<endl; 334 } 329 335 } 330 336 } 331 337 else { 338 // cerr<<"\t\tThere was no exact copy of this record, so adding & sorting\n"; 332 339 ce.d_records.push_back(dr); 333 340 sort(ce.d_records.begin(), ce.d_records.end()); … … 337 344 338 345 if(isNew) { 346 // cerr<<"\tSorting (because of isNew)\n"; 339 347 sort(ce.d_records.begin(), ce.d_records.end()); 340 348 } … … 348 356 int MemRecursorCache::doWipeCache(const string& name, uint16_t qtype) 349 357 { 358 WriteLock wl(&s_rwlock); 350 359 int count=0; 351 360 d_cachecachevalid=false; … … 365 374 bool MemRecursorCache::doAgeCache(time_t now, const string& name, uint16_t qtype, int32_t newTTL) 366 375 { 376 WriteLock wl(&s_rwlock); 367 377 cache_t::iterator iter = d_cache.find(tie(name, qtype)); 368 378 if(iter == d_cache.end()) … … 393 403 void MemRecursorCache::doDumpAndClose(int fd) 394 404 { 405 WriteLock wl(&s_rwlock); 395 406 FILE* fp=fdopen(fd, "w"); 396 407 if(!fp) { … … 424 435 void MemRecursorCache::doPrune(void) 425 436 { 437 WriteLock wl(&s_rwlock); 426 438 uint32_t now=(uint32_t)time(0); 427 439 d_cachecachevalid=false; -
trunk/pdns/pdns/recursor_cache.hh
r1265 r1374 7 7 #include "misc.hh" 8 8 #include <iostream> 9 9 10 #include <boost/utility.hpp> 10 11 #undef L … … 29 30 public: 30 31 MemRecursorCache() : d_followRFC2181(false), d_cachecachevalid(false) 31 {} 32 { 33 pthread_rwlock_init(&s_rwlock, 0); 34 // cerr<<"ce: "<<sizeof(CacheEntry)<<", sr: "<<sizeof(struct StoredRecord)<<endl; 35 } 32 36 unsigned int size(); 33 37 unsigned int bytes(); … … 63 67 }; 64 68 65 struct predicate66 {67 predicate(uint32_t limit) : d_limit(limit)68 {69 }70 71 bool operator()(const StoredRecord& sr) const72 {73 return sr.d_ttd <= d_limit;74 }75 uint32_t d_limit;76 };77 78 // typedef __gnu_cxx::hash_map<string, vector<StoredRecord> > cache_t;79 69 struct CacheEntry 80 70 { 81 string d_qname;82 uint16_t d_qtype;83 bool d_auth;84 85 71 CacheEntry(const tuple<string, uint16_t>& key, const vector<StoredRecord>& records, bool auth) : 86 72 d_qname(key.get<0>()), d_qtype(key.get<1>()), d_auth(auth), d_records(records) … … 88 74 89 75 typedef vector<StoredRecord> records_t; 90 records_t d_records; 76 91 77 uint32_t getTTD() const 92 78 { … … 99 85 return earliest; 100 86 } 87 88 string d_qname; 89 uint16_t d_qtype; 90 bool d_auth; 91 records_t d_records; 101 92 }; 102 93 … … 122 113 bool attemptToRefreshNSTTL(const QType& qt, const set<DNSResourceRecord>& content, const CacheEntry& stored); 123 114 115 static pthread_rwlock_t s_rwlock; 116 124 117 }; 125 118 string DNSRR2String(const DNSResourceRecord& rr);