Utility::srandom(time(0));
arg().set("soa-minimum-ttl","Don't change")="0";
arg().set("soa-serial-offset","Don't change")="0";
- arg().set("no-shuffle","Don't change")="ogg";
+ arg().set("no-shuffle","Don't change")="off";
arg().set("aaaa-additional-processing","turn on to do AAAA additional processing (slow)")="off";
arg().set("local-port","port to listen on")="53";
arg().set("local-address","single address to listen on")="0.0.0.0";
}
LOG<<prefix<<qname<<": Resolved '"+auth+"' NS "<<*tns<<" to "<<remoteIP<<", asking '"<<qname<<"|"<<qtype.getName()<<"'"<<endl;
- if(s_throttle.shouldThrottle(remoteIP+"|"+qname+"|"+qtype.getName())) {
+ if(s_throttle.shouldThrottle(d_now, remoteIP+"|"+qname+"|"+qtype.getName())) {
LOG<<prefix<<qname<<": query throttled "<<endl;
s_throttledqueries++;
d_throttledqueries++;
LOG<<prefix<<qname<<": error resolving (perhaps timeout?)"<<endl;
nsSpeeds[toLower(*tns)].submit(1000000); // 1 sec
d_timeouts++;
- s_throttle.throttle(remoteIP+"|"+qname+"|"+qtype.getName(),20,5);
+ s_throttle.throttle(d_now, remoteIP+"|"+qname+"|"+qtype.getName(),20,5);
continue;
}
d_now=time(0);
result=d_lwr.result();
if(d_lwr.d_rcode==RCode::ServFail) {
LOG<<prefix<<qname<<": "<<*tns<<" returned a ServFail, trying sibling NS"<<endl;
- s_throttle.throttle(remoteIP+"|"+qname+"|"+qtype.getName(),60,3);
+ s_throttle.throttle(d_now,remoteIP+"|"+qname+"|"+qtype.getName(),60,3);
continue;
}
LOG<<prefix<<qname<<": Got "<<result.size()<<" answers from "<<*tns<<" ("<<remoteIP<<"), rcode="<<d_lwr.d_rcode<<", in "<<d_lwr.d_usec/1000<<"ms"<<endl;
}
else {
LOG<<prefix<<qname<<": status=NS "<<*tns<<" is lame for '"<<auth<<"', trying sibling NS"<<endl;
- s_throttle.throttle(remoteIP+"|"+qname+"|"+qtype.getName(),60,0);
+ s_throttle.throttle(d_now, remoteIP+"|"+qname+"|"+qtype.getName(),60,0);
}
}
}
d_ttl=60;
d_last_clean=time(0);
}
- bool shouldThrottle(const Thing& t)
+ bool shouldThrottle(time_t now, const Thing& t)
{
- time_t now=time(0);
if(now > d_last_clean + 60 ) {
d_last_clean=now;
for(typename cont_t::iterator i=d_cont.begin();i!=d_cont.end();)
++i;
}
-
-
typename cont_t::iterator i=d_cont.find(t);
if(i==d_cont.end())
return false;
return true;
}
}
- void throttle(const Thing& t, unsigned int ttl=0, unsigned int tries=0)
+ void throttle(time_t now, const Thing& t, unsigned int ttl=0, unsigned int tries=0)
{
typename cont_t::iterator i=d_cont.find(t);
- entry e={ time_t(0)+(ttl ? ttl : d_ttl), tries ? tries : d_limit};
+ entry e={ now+(ttl ? ttl : d_ttl), tries ? tries : d_limit};
if(i==d_cont.end()) {
d_cont[t]=e;
};
-#if 0
-
-template<class Thing> class Throttle
-{
-public:
- Throttle()
- {
- d_limit=3;
- d_ttl=60;
- }
- bool shouldThrottle(const Thing& t)
- {
- time_t now=time(0);
- while(!d_dq.empty() && d_dq.back().ttd < now) // remove expired entries from the end
- d_dq.pop_back();
-
- for(typename cont_t::iterator i=d_dq.begin();i!=d_dq.end();++i)
- if(i->T==t && i->count-- < 0)
- return true;
- return false;
- }
-
- void throttle(const Thing& t, unsigned int ttl=0, unsigned int tries=0)
- {
- entry e;
- e.ttd=time(0)+ (ttl ? ttl : d_ttl) ;
- e.T=t;
- e.count=tries ? tries : d_limit;
- d_dq.push_front(e);
-
- }
-private:
- int d_limit;
- int d_ttl;
- struct entry
- {
- time_t ttd;
- Thing T;
- int count;
- };
- typedef deque<entry> cont_t;
- cont_t d_dq;
-};
-#endif
-
/** Class that implements a decaying EWMA.
This class keeps an exponentially weighted moving average which, additionally, decays over time.
The decaying is only done on get.