lwr->d_rcode = 0;
lwr->d_pingCorrect = false;
lwr->d_haveEDNS = false;
-
int ret;
DTime dt;
class LWResult
{
public:
+ LWResult() : d_usec(0) {}
typedef vector<DNSResourceRecord> res_t;
vector<DNSResourceRecord> d_result;
if(!g_quiet) {
L<<Logger::Error<<t_id<<" ["<<MT->getTid()<<"/"<<MT->numProcesses()<<"] answer to "<<(dc->d_mdp.d_header.rd?"":"non-rd ")<<"question '"<<dc->d_mdp.d_qname<<"|"<<DNSRecordContent::NumberToType(dc->d_mdp.d_qtype);
L<<"': "<<ntohs(pw.getHeader()->ancount)<<" answers, "<<ntohs(pw.getHeader()->arcount)<<" additional, took "<<sr.d_outqueries<<" packets, "<<
- sr.d_throttledqueries<<" throttled, "<<sr.d_timeouts<<" timeouts, "<<sr.d_tcpoutqueries<<" tcp connections, rcode="<<res<<endl;
+ sr.d_totUsec/1000.0<<" ms, "<<
+ sr.d_throttledqueries<<" throttled, "<<sr.d_timeouts<<" timeouts, "<<sr.d_tcpoutqueries<<" tcp connections, rcode="<<res<<endl;
}
sr.d_outqueries ? t_RC->cacheMisses++ : t_RC->cacheHits++;
SyncRes::s_serverdownthrottletime=::arg().asNum("server-down-throttle-time");
SyncRes::s_serverID=::arg()["server-id"];
SyncRes::s_maxqperq=::arg().asNum("max-qperq");
+ SyncRes::s_maxtotusec=1000*::arg().asNum("max-total-msec");
if(SyncRes::s_serverID.empty()) {
char tmp[128];
gethostname(tmp, sizeof(tmp)-1);
::arg().set("udp-truncation-threshold", "Maximum UDP response size before we truncate")="1680";
::arg().set("minimum-ttl-override", "Set under adverse conditions, a minimum TTL")="0";
::arg().set("max-qperq", "Maximum outgoing queries per query")="50";
+ ::arg().set("max-total-msec", "Maximum total wall-clock time per query in milliseconds, 0 for unlimited")="5000";
::arg().set("include-dir","Include *.conf files from this directory")="";
::arg().set("security-poll-suffix","Domain name from which to query security update notifications")="secpoll.powerdns.com.";
bool SyncRes::s_doIPv6;
bool SyncRes::s_nopacketcache;
unsigned int SyncRes::s_maxqperq;
+unsigned int SyncRes::s_maxtotusec;
string SyncRes::s_serverID;
SyncRes::LogMode SyncRes::s_lm;
bool SyncRes::s_noEDNS;
SyncRes::SyncRes(const struct timeval& now) : d_outqueries(0), d_tcpoutqueries(0), d_throttledqueries(0), d_timeouts(0), d_unreachables(0),
- d_now(now),
+ d_totUsec(0), d_now(now),
d_cacheonly(false), d_nocache(false), d_doEDNS0(false), d_lm(s_lm)
{
s_tcpoutqueries++; d_tcpoutqueries++;
}
+ if(s_maxtotusec && d_totUsec > s_maxtotusec)
+ throw ImmediateServFailException("Too much time waiting for "+qname+"|"+qtype.getName()+", timeouts: "+boost::lexical_cast<string>(d_timeouts) +", throttles: "+boost::lexical_cast<string>(d_throttledqueries) + ", "+lexical_cast<string>(d_totUsec/1000)+"msec");
+
if(d_pdl && d_pdl->preoutquery(*remoteIP, d_requestor, qname, qtype, lwr.d_result, resolveret)) {
LOG(prefix<<qname<<": query handled by Lua"<<endl);
}
if(resolveret==-3)
throw ImmediateServFailException("Query killed by policy");
-
+ d_totUsec += lwr.d_usec;
if(resolveret != 1) {
if(resolveret==0) {
LOG(prefix<<qname<<": timeout resolving after "<<lwr.d_usec/1000.0<<"msec "<< (doTCP ? "over TCP" : "")<<endl);
static unsigned int s_minimumTTL;
static bool s_doIPv6;
static unsigned int s_maxqperq;
+ static unsigned int s_maxtotusec;
unsigned int d_outqueries;
unsigned int d_tcpoutqueries;
unsigned int d_throttledqueries;
unsigned int d_timeouts;
unsigned int d_unreachables;
+ unsigned int d_totUsec;
ComboAddress d_requestor;
- // typedef map<string,NegCacheEntry> negcache_t;
typedef multi_index_container <
NegCacheEntry,