/*
PowerDNS Versatile Database Driven Nameserver
- Copyright (C) 2002 - 2005 PowerDNS.COM BV
+ Copyright (C) 2002 - 2006 PowerDNS.COM BV
This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
#include "zoneparser-tng.hh"
#include "rec_channel.hh"
-// using namespace boost;
+using namespace boost;
#ifdef __FreeBSD__ // see cvstrac ticket #26
#include <pthread.h>
dt.setTimeval(now);
RC.doPrune();
int pruned=0;
- for(SyncRes::negcache_t::iterator i = SyncRes::s_negcache.begin(); i != SyncRes::s_negcache.end();)
- if(i->second.ttd < now.tv_sec) {
- SyncRes::s_negcache.erase(i++);
- pruned++;
- }
- else
- ++i;
+
+ typedef SyncRes::negcache_t::nth_index<1>::type negcache_by_ttd_index_t;
+ negcache_by_ttd_index_t& ttdindex=boost::multi_index::get<1>(SyncRes::s_negcache);
+
+ negcache_by_ttd_index_t::iterator i=ttdindex.lower_bound(now.tv_sec);
+ ttdindex.erase(ttdindex.begin(), i);
time_t limit=now.tv_sec-300;
for(SyncRes::nsspeeds_t::iterator i = SyncRes::s_nsSpeeds.begin() ; i!= SyncRes::s_nsSpeeds.end(); )
addGetStat("cache-hits", &RC.cacheHits);
addGetStat("cache-misses", &RC.cacheMisses);
- addGetStat("cache-entries", bind(&MemRecursorCache::size, ref(RC)));
+ addGetStat("cache-entries", boost::bind(&MemRecursorCache::size, ref(RC)));
addGetStat("servfail-answers", &g_stats.servFails);
addGetStat("nxdomain-answers", &g_stats.nxDomains);
addGetStat("noerror-answers", &g_stats.noErrors);
addGetStat("qa-latency", &g_stats.avgLatencyUsec);
addGetStat("all-questions", &qcounter);
- addGetStat("negcache-entries", bind(&SyncRes::negcache_t::size, ref(SyncRes::s_negcache)));
- addGetStat("throttle-entries", bind(&SyncRes::throttle_t::size, ref(SyncRes::s_throttle)));
- addGetStat("nsspeeds-entries", bind(&SyncRes::nsspeeds_t::size, ref(SyncRes::s_nsSpeeds)));
+ addGetStat("negcache-entries", boost::bind(&SyncRes::negcache_t::size, ref(SyncRes::s_negcache)));
+ addGetStat("throttle-entries", boost::bind(&SyncRes::throttle_t::size, ref(SyncRes::s_throttle)));
+ addGetStat("nsspeeds-entries", boost::bind(&SyncRes::nsspeeds_t::size, ref(SyncRes::s_nsSpeeds)));
- addGetStat("concurrent-queries", bind(&MTasker<PacketID,string>::numProcesses, ref(MT)));
+ addGetStat("concurrent-queries", boost::bind(&MTasker<PacketID,string>::numProcesses, ref(MT)));
addGetStat("outgoing-timeouts", &SyncRes::s_outgoingtimeouts);
addGetStat("tcp-outqueries", &SyncRes::s_tcpoutqueries);
addGetStat("all-outqueries", &SyncRes::s_outqueries);
QType sqt(qtype);
uint32_t sttl=0;
- if(s_negcache.count(toLower(qname))) {
+ negcache_t::iterator ni=s_negcache.find(toLower(qname));
+ if(ni!=s_negcache.end()) {
+ cerr<<"found something\n";
res=0;
- negcache_t::const_iterator ni=s_negcache.find(toLower(qname));
- if(d_now.tv_sec < ni->second.ttd) {
- sttl=ni->second.ttd - d_now.tv_sec;
+ if((uint32_t)d_now.tv_sec < ni->d_ttd) {
+ sttl=ni->d_ttd - d_now.tv_sec;
LOG<<prefix<<qname<<": Entire record '"<<toLower(qname)<<"', is negatively cached for another "<<sttl<<" seconds"<<endl;
res=RCode::NXDomain;
giveNegative=true;
- sqname=ni->second.name;
+ sqname=ni->d_qname;
sqt="SOA";
}
else {
LOG<<prefix<<qname<<": Entire record '"<<toLower(qname)<<"' was negatively cached, but entry expired"<<endl;
- s_negcache.erase(toLower(qname));
+ s_negcache.erase(ni);
}
}
LOG<<prefix<<qname<<": Looking for direct cache hit of '"<<tuple<<"', negative cached: "<<s_negcache.count(tuple)<<endl;
res=0;
- negcache_t::const_iterator ni=s_negcache.find(tuple);
+ ni=s_negcache.find(tuple);
if(ni!=s_negcache.end()) {
- if(d_now.tv_sec < ni->second.ttd) {
- sttl=ni->second.ttd - d_now.tv_sec;
+ if((uint32_t)d_now.tv_sec < ni->d_ttd) {
+ sttl=ni->d_ttd - d_now.tv_sec;
LOG<<prefix<<qname<<": "<<qtype.getName()<<" is negatively cached for another "<<sttl<<" seconds"<<endl;
res=RCode::NoError; // only this record doesn't exist
giveNegative=true;
- sqname=ni->second.name;
+ sqname=ni->d_qname;
sqt="SOA";
}
else {
LOG<<prefix<<qname<<": "<<qtype.getName()<<" was negatively cached, but entry expired"<<endl;
- s_negcache.erase(toLower(tuple));
+ s_negcache.erase(ni);
}
}
}
ret.push_back(*i);
NegCacheEntry ne;
- ne.name=i->qname;
- ne.ttd=d_now.tv_sec + i->ttl;
- s_negcache[toLower(qname)]=ne;
+
+ ne.d_qname=i->qname;
+ ne.d_ttd=d_now.tv_sec + min(i->ttl, 3600U); // controversial
+ ne.d_name=toLower(qname);
+ s_negcache.insert(ne);
negindic=true;
}
else if(i->d_place==DNSResourceRecord::ANSWER && i->qname==qname && i->qtype.getCode()==QType::CNAME && (!(qtype==QType(QType::CNAME)))) {
ret.push_back(*i);
NegCacheEntry ne;
- ne.name=i->qname;
- ne.ttd=d_now.tv_sec + i->ttl;
- s_negcache[toLower(qname)+"|"+qtype.getName()]=ne;
+ ne.d_qname=i->qname;
+ ne.d_ttd=d_now.tv_sec + min(3600U,i->ttl);
+ ne.d_name=toLower(qname)+"|"+qtype.getName();
+ s_negcache.insert(ne);
negindic=true;
}
}
struct NegCacheEntry
{
- string name;
- time_t ttd;
+ string d_qname;
+ string d_name;
+ uint32_t d_ttd;
};
unsigned int d_tcpoutqueries;
unsigned int d_throttledqueries;
unsigned int d_timeouts;
- typedef map<string,NegCacheEntry> negcache_t;
+ // typedef map<string,NegCacheEntry> negcache_t;
+
+ typedef multi_index_container <
+ NegCacheEntry,
+ indexed_by <
+ ordered_unique<
+ member<NegCacheEntry, string, &NegCacheEntry::d_name>
+ >,
+ ordered_non_unique<
+ member<NegCacheEntry, uint32_t, &NegCacheEntry::d_ttd>
+ >
+ >
+ >negcache_t;
static negcache_t s_negcache;
typedef map<string,DecayingEwma> nsspeeds_t;