From: Remi Gacogne Date: Tue, 4 Apr 2017 17:02:25 +0000 (+0200) Subject: rec: Cleanup the StaticStorage object, renamed to ThreadLocalStorage X-Git-Tag: rec-4.1.0-alpha1~107^2~3 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a712cb5662be45bc70136c2827dc21e5629ff344;p=pdns rec: Cleanup the StaticStorage object, renamed to ThreadLocalStorage --- diff --git a/pdns/pdns_recursor.cc b/pdns/pdns_recursor.cc index 44b6fdc1e..90d30ea35 100644 --- a/pdns/pdns_recursor.cc +++ b/pdns/pdns_recursor.cc @@ -1424,7 +1424,7 @@ static void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var) if(t_pdl && t_pdl->d_gettag) { try { - dc->d_tag = t_pdl->gettag(conn->d_remote, dc->d_ednssubnet.source, dest, qname, qtype, &dc->d_policyTags, dc->d_data, ednsOptionsn true, requestorId); + dc->d_tag = t_pdl->gettag(conn->d_remote, dc->d_ednssubnet.source, dest, qname, qtype, &dc->d_policyTags, dc->d_data, ednsOptions, true, requestorId); } catch(std::exception& e) { if(g_logCommonErrors) @@ -2060,15 +2060,11 @@ static void houseKeeping(void *) t_RC->doPrune(); // this function is local to a thread, so fine anyhow t_packetCache->doPruneTo(::arg().asNum("max-packetcache-entries") / g_numWorkerThreads); - t_sstorage->negcache.prune(::arg().asNum("max-cache-entries") / (g_numWorkerThreads * 10)); + SyncRes::pruneNegCache(::arg().asNum("max-cache-entries") / (g_numWorkerThreads * 10)); if(!((cleanCounter++)%40)) { // this is a full scan! time_t limit=now.tv_sec-300; - for(SyncRes::nsspeeds_t::iterator i = t_sstorage->nsSpeeds.begin() ; i!= t_sstorage->nsSpeeds.end(); ) - if(i->second.stale(limit)) - i = t_sstorage->nsSpeeds.erase(i); - else - ++i; + SyncRes::pruneNSSpeeds(limit); } last_prune=time(0); } @@ -2948,7 +2944,7 @@ try { t_id=(int) (long) ptr; SyncRes tmp(g_now); // make sure it allocates tsstorage before we do anything, like primeHints or so.. - t_sstorage->domainmap = g_initialDomainMap; + SyncRes::setDomainMap(g_initialDomainMap); t_allowFrom = g_initialAllowFrom; t_udpclientsocks = std::unique_ptr(new UDPClientSocks()); t_tcpClientCounts = std::unique_ptr(new tcpClientCounts_t()); diff --git a/pdns/rec_channel_rec.cc b/pdns/rec_channel_rec.cc index c9f37df01..ce3a0d452 100644 --- a/pdns/rec_channel_rec.cc +++ b/pdns/rec_channel_rec.cc @@ -191,7 +191,7 @@ static uint64_t dumpNegCache(NegCache& negcache, int fd) static uint64_t* pleaseDump(int fd) { - return new uint64_t(t_RC->doDump(fd) + dumpNegCache(t_sstorage->negcache, fd) + t_packetCache->doDump(fd)); + return new uint64_t(t_RC->doDump(fd) + dumpNegCache(SyncRes::t_sstorage.negcache, fd) + t_packetCache->doDump(fd)); } static uint64_t* pleaseDumpNSSpeeds(int fd) @@ -274,7 +274,7 @@ uint64_t* pleaseWipePacketCache(const DNSName& canon, bool subtree) uint64_t* pleaseWipeAndCountNegCache(const DNSName& canon, bool subtree) { - uint64_t ret = t_sstorage->negcache.wipe(canon, subtree); + uint64_t ret = SyncRes::wipeNegCache(canon, subtree); return new uint64_t(ret); } @@ -621,7 +621,7 @@ static string doCurrentQueries() uint64_t* pleaseGetThrottleSize() { - return new uint64_t(t_sstorage ? t_sstorage->throttle.size() : 0); + return new uint64_t(SyncRes::getThrottledServersSize()); } static uint64_t getThrottleSize() @@ -631,7 +631,7 @@ static uint64_t getThrottleSize() uint64_t* pleaseGetNegCacheSize() { - uint64_t tmp=(t_sstorage ? t_sstorage->negcache.size() : 0); + uint64_t tmp=(SyncRes::getNegCacheSize()); return new uint64_t(tmp); } @@ -642,7 +642,7 @@ uint64_t getNegCacheSize() uint64_t* pleaseGetFailedHostsSize() { - uint64_t tmp=(t_sstorage ? t_sstorage->fails.size() : 0); + uint64_t tmp=(SyncRes::getThrottledServersSize()); return new uint64_t(tmp); } uint64_t getFailedHostsSize() @@ -652,7 +652,7 @@ uint64_t getFailedHostsSize() uint64_t* pleaseGetNsSpeedsSize() { - return new uint64_t(t_sstorage ? t_sstorage->nsSpeeds.size() : 0); + return new uint64_t(SyncRes::getNSSpeedsSize()); } uint64_t getNsSpeedsSize() diff --git a/pdns/recursordist/test-syncres_cc.cc b/pdns/recursordist/test-syncres_cc.cc index b446e02a7..9072f63c5 100644 --- a/pdns/recursordist/test-syncres_cc.cc +++ b/pdns/recursordist/test-syncres_cc.cc @@ -127,6 +127,11 @@ static void init(bool debug=false) SyncRes::clearDelegationOnly(); SyncRes::clearDontQuery(); + SyncRes::clearNSSpeeds(); + SyncRes::clearEDNSStatuses(); + SyncRes::clearThrottle(); + SyncRes::clearFailedServers(); + auto luaconfsCopy = g_luaconfs.getCopy(); luaconfsCopy.dfe.clear(); g_luaconfs.setState(luaconfsCopy); @@ -149,13 +154,8 @@ static void initSR(std::unique_ptr& sr, bool edns0, bool dnssec, SyncRe sr->setDoEDNS0(edns0); sr->setDoDNSSEC(dnssec); sr->setLogMode(lm); - t_sstorage->domainmap = std::make_shared(); - t_sstorage->negcache.clear(); - t_sstorage->nsSpeeds.clear(); - t_sstorage->ednsstatus.clear(); - t_sstorage->throttle.clear(); - t_sstorage->fails.clear(); - t_sstorage->dnssecmap.clear(); + SyncRes::setDomainMap(std::make_shared()); + SyncRes::clearNegCache(); } static void setLWResult(LWResult* res, int rcode, bool aa=false, bool tc=false, bool edns=false) @@ -299,7 +299,7 @@ BOOST_AUTO_TEST_CASE(test_root_not_primed_and_no_response) { BOOST_CHECK(downServers.size() > 0); /* we explicitly refuse to mark the root servers down */ for (const auto& server : downServers) { - BOOST_CHECK_EQUAL(t_sstorage->fails.value(server), 0); + BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server), 0); } } @@ -341,8 +341,8 @@ BOOST_AUTO_TEST_CASE(test_edns_formerr_fallback) { BOOST_CHECK_EQUAL(ret.size(), 1); BOOST_CHECK_EQUAL(queriesWithEDNS, 1); BOOST_CHECK_EQUAL(queriesWithoutEDNS, 1); - BOOST_CHECK_EQUAL(t_sstorage->ednsstatus.size(), 1); - BOOST_CHECK_EQUAL(t_sstorage->ednsstatus[noEDNSServer].mode, SyncRes::EDNSStatus::NOEDNS); + BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), 1); + BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(noEDNSServer), SyncRes::EDNSStatus::NOEDNS); } BOOST_AUTO_TEST_CASE(test_edns_notimp_fallback) { @@ -451,8 +451,8 @@ BOOST_AUTO_TEST_CASE(test_all_nss_down) { BOOST_CHECK_EQUAL(downServers.size(), 4); for (const auto& server : downServers) { - BOOST_CHECK_EQUAL(t_sstorage->fails.value(server), 1); - BOOST_CHECK(t_sstorage->throttle.shouldThrottle(time(nullptr), boost::make_tuple(server, target, QType::A))); + BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server), 1); + BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server, target, QType::A)); } } @@ -499,8 +499,9 @@ BOOST_AUTO_TEST_CASE(test_all_nss_network_error) { BOOST_CHECK_EQUAL(downServers.size(), 4); for (const auto& server : downServers) { - BOOST_CHECK_EQUAL(t_sstorage->fails.value(server), 1); - BOOST_CHECK(t_sstorage->throttle.shouldThrottle(time(nullptr), boost::make_tuple(server, target, QType::A))); + BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server), 1); + BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server, target, QType::A)); +; } } @@ -555,8 +556,8 @@ BOOST_AUTO_TEST_CASE(test_os_limit_errors) { /* Error is reported as "OS limit error" (-2) so the servers should _NOT_ be marked down */ for (const auto& server : downServers) { - BOOST_CHECK_EQUAL(t_sstorage->fails.value(server), 0); - BOOST_CHECK(!t_sstorage->throttle.shouldThrottle(time(nullptr), boost::make_tuple(server, target, QType::A))); + BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server), 0); + BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), server, target, QType::A)); } } @@ -1109,7 +1110,7 @@ BOOST_AUTO_TEST_CASE(test_throttled_server) { }); /* mark ns as down */ - t_sstorage->throttle.throttle(time(nullptr), boost::make_tuple(ns, "", 0), SyncRes::s_serverdownthrottletime, 10000); + SyncRes::doThrottle(time(nullptr), ns, SyncRes::s_serverdownthrottletime, 10000); vector ret; int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); @@ -1130,14 +1131,14 @@ BOOST_AUTO_TEST_CASE(test_throttled_server_count) { const size_t blocks = 10; /* mark ns as down for 'blocks' queries */ - t_sstorage->throttle.throttle(time(nullptr), boost::make_tuple(ns, "", 0), SyncRes::s_serverdownthrottletime, blocks); + SyncRes::doThrottle(time(nullptr), ns, SyncRes::s_serverdownthrottletime, blocks); for (size_t idx = 0; idx < blocks; idx++) { - BOOST_CHECK(t_sstorage->throttle.shouldThrottle(time(nullptr), boost::make_tuple(ns, "", 0))); + BOOST_CHECK(SyncRes::isThrottled(time(nullptr), ns)); } /* we have been throttled 'blocks' times, we should not be throttled anymore */ - BOOST_CHECK(!t_sstorage->throttle.shouldThrottle(time(nullptr), boost::make_tuple(ns, "", 0))); + BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), ns)); } BOOST_AUTO_TEST_CASE(test_throttled_server_time) { @@ -1151,13 +1152,14 @@ BOOST_AUTO_TEST_CASE(test_throttled_server_time) { const size_t seconds = 1; /* mark ns as down for 'seconds' seconds */ - t_sstorage->throttle.throttle(time(nullptr), boost::make_tuple(ns, "", 0), seconds, 10000); - BOOST_CHECK(t_sstorage->throttle.shouldThrottle(time(nullptr), boost::make_tuple(ns, "", 0))); + SyncRes::doThrottle(time(nullptr), ns, seconds, 10000); + + BOOST_CHECK(SyncRes::isThrottled(time(nullptr), ns)); sleep(seconds + 1); /* we should not be throttled anymore */ - BOOST_CHECK(!t_sstorage->throttle.shouldThrottle(time(nullptr), boost::make_tuple(ns, "", 0))); + BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), ns)); } BOOST_AUTO_TEST_CASE(test_dont_query_server) { @@ -1248,14 +1250,14 @@ BOOST_AUTO_TEST_CASE(test_root_nx_trust) { BOOST_CHECK_EQUAL(res, RCode::NXDomain); BOOST_CHECK_EQUAL(ret.size(), 1); /* one for target1 and one for the entire TLD */ - BOOST_CHECK_EQUAL(t_sstorage->negcache.size(), 2); + BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2); ret.clear(); res = sr->beginResolve(target2, QType(QType::A), QClass::IN, ret); BOOST_CHECK_EQUAL(res, RCode::NXDomain); BOOST_CHECK_EQUAL(ret.size(), 1); /* one for target1 and one for the entire TLD */ - BOOST_CHECK_EQUAL(t_sstorage->negcache.size(), 2); + BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2); /* we should have sent only one query */ BOOST_CHECK_EQUAL(queriesCount, 1); @@ -1311,7 +1313,7 @@ BOOST_AUTO_TEST_CASE(test_root_nx_trust_specific) { /* even with root-nx-trust on and a NX answer from the root, we should not have cached the entire TLD this time. */ - BOOST_CHECK_EQUAL(t_sstorage->negcache.size(), 1); + BOOST_CHECK_EQUAL(SyncRes::t_sstorage.negcache.size(), 1); ret.clear(); res = sr->beginResolve(target2, QType(QType::A), QClass::IN, ret); @@ -1321,7 +1323,7 @@ BOOST_AUTO_TEST_CASE(test_root_nx_trust_specific) { BOOST_CHECK_EQUAL(ret[0].d_name, target2); BOOST_CHECK(getRR(ret[0])->getCA() == ComboAddress("192.0.2.2")); - BOOST_CHECK_EQUAL(t_sstorage->negcache.size(), 1); + BOOST_CHECK_EQUAL(SyncRes::t_sstorage.negcache.size(), 1); BOOST_CHECK_EQUAL(queriesCount, 3); } @@ -1373,14 +1375,14 @@ BOOST_AUTO_TEST_CASE(test_root_nx_dont_trust) { BOOST_CHECK_EQUAL(res, RCode::NXDomain); BOOST_CHECK_EQUAL(ret.size(), 1); /* one for target1 */ - BOOST_CHECK_EQUAL(t_sstorage->negcache.size(), 1); + BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1); ret.clear(); res = sr->beginResolve(target2, QType(QType::A), QClass::IN, ret); BOOST_CHECK_EQUAL(res, 0); BOOST_CHECK_EQUAL(ret.size(), 1); /* one for target1 */ - BOOST_CHECK_EQUAL(t_sstorage->negcache.size(), 1); + BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1); /* we should have sent three queries */ BOOST_CHECK_EQUAL(queriesCount, 3); @@ -1439,7 +1441,7 @@ BOOST_AUTO_TEST_CASE(test_skip_negcache_for_variable_response) { BOOST_CHECK_EQUAL(res, RCode::NXDomain); BOOST_CHECK_EQUAL(ret.size(), 2); /* no negative cache entry because the response was variable */ - BOOST_CHECK_EQUAL(t_sstorage->negcache.size(), 0); + BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 0); } BOOST_AUTO_TEST_CASE(test_ns_speed) { @@ -1497,12 +1499,12 @@ BOOST_AUTO_TEST_CASE(test_ns_speed) { /* make pdns-public-ns2.powerdns.com. the fastest NS, with its IPv6 address faster than the IPV4 one, then pdns-public-ns1.powerdns.com. on IPv4 */ - t_sstorage->nsSpeeds[DNSName("pdns-public-ns1.powerdns.com.")].submit(ComboAddress("192.0.2.1:53"), 100, &now); - t_sstorage->nsSpeeds[DNSName("pdns-public-ns1.powerdns.com.")].submit(ComboAddress("[2001:DB8::1]:53"), 10000, &now); - t_sstorage->nsSpeeds[DNSName("pdns-public-ns2.powerdns.com.")].submit(ComboAddress("192.0.2.2:53"), 10, &now); - t_sstorage->nsSpeeds[DNSName("pdns-public-ns2.powerdns.com.")].submit(ComboAddress("[2001:DB8::2]:53"), 1, &now); - t_sstorage->nsSpeeds[DNSName("pdns-public-ns3.powerdns.com.")].submit(ComboAddress("192.0.2.3:53"), 10000, &now); - t_sstorage->nsSpeeds[DNSName("pdns-public-ns3.powerdns.com.")].submit(ComboAddress("[2001:DB8::3]:53"), 10000, &now); + SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("192.0.2.1:53"), 100, &now); + SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("[2001:DB8::1]:53"), 10000, &now); + SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("192.0.2.2:53"), 10, &now); + SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("[2001:DB8::2]:53"), 1, &now); + SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("192.0.2.3:53"), 10000, &now); + SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("[2001:DB8::3]:53"), 10000, &now); vector ret; int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); @@ -2288,7 +2290,7 @@ BOOST_AUTO_TEST_CASE(test_forward_zone_nord) { SyncRes::AuthDomain ad; ad.d_rdForward = false; ad.d_servers.push_back(forwardedNS); - (*t_sstorage->domainmap)[target] = ad; + (*SyncRes::t_sstorage.domainmap)[target] = ad; sr->setAsyncCallback([forwardedNS](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional& srcmask, boost::optional context, std::shared_ptr outgoingLogger, LWResult* res) { @@ -2324,7 +2326,7 @@ BOOST_AUTO_TEST_CASE(test_forward_zone_rd) { SyncRes::AuthDomain ad; ad.d_rdForward = false; ad.d_servers.push_back(forwardedNS); - (*t_sstorage->domainmap)[target] = ad; + (*SyncRes::t_sstorage.domainmap)[target] = ad; sr->setAsyncCallback([forwardedNS](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional& srcmask, boost::optional context, std::shared_ptr outgoingLogger, LWResult* res) { @@ -2357,7 +2359,7 @@ BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_nord) { SyncRes::AuthDomain ad; ad.d_rdForward = true; ad.d_servers.push_back(forwardedNS); - (*t_sstorage->domainmap)[target] = ad; + (*SyncRes::t_sstorage.domainmap)[target] = ad; sr->setAsyncCallback([forwardedNS](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional& srcmask, boost::optional context, std::shared_ptr outgoingLogger, LWResult* res) { @@ -2393,7 +2395,7 @@ BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd) { SyncRes::AuthDomain ad; ad.d_rdForward = true; ad.d_servers.push_back(forwardedNS); - (*t_sstorage->domainmap)[target] = ad; + (*SyncRes::t_sstorage.domainmap)[target] = ad; sr->setAsyncCallback([forwardedNS](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional& srcmask, boost::optional context, std::shared_ptr outgoingLogger, LWResult* res) { @@ -2442,7 +2444,7 @@ BOOST_AUTO_TEST_CASE(test_auth_zone_delegation_oob) { dr.d_content = std::make_shared(nsAddr); ad.d_records.insert(dr); - (*t_sstorage->domainmap)[authZone] = ad; + (*SyncRes::t_sstorage.domainmap)[authZone] = ad; sr->setAsyncCallback([&queriesCount,nsAddr,target,targetAddr](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional& srcmask, boost::optional context, std::shared_ptr outgoingLogger, LWResult* res) { queriesCount++; diff --git a/pdns/reczones.cc b/pdns/reczones.cc index f7fa10c40..cd7ac7996 100644 --- a/pdns/reczones.cc +++ b/pdns/reczones.cc @@ -229,26 +229,28 @@ void convertServersForAD(const std::string& input, SyncRes::AuthDomain& ad, cons void* pleaseWipeNegCache() { - t_sstorage->negcache.clear(); + SyncRes::clearNegCache(); return 0; } void* pleaseUseNewSDomainsMap(std::shared_ptr newmap) { - t_sstorage->domainmap = newmap; + SyncRes::setDomainMap(newmap); return 0; } string reloadAuthAndForwards() { - std::shared_ptr original=t_sstorage->domainmap; + std::shared_ptr original=SyncRes::getDomainMap(); try { L<domainmap) { - for(const auto& j : i.second.d_records) - broadcastAccFunction(boost::bind(pleaseWipeCache, j.d_name, false)); + + if (original) { + for(const auto& i : *original) { + for(const auto& j : i.second.d_records) + broadcastAccFunction(boost::bind(pleaseWipeCache, j.d_name, false)); + } } string configname=::arg()["config-dir"]+"/recursor.conf"; diff --git a/pdns/syncres.cc b/pdns/syncres.cc index 03b8fa701..3e1746741 100644 --- a/pdns/syncres.cc +++ b/pdns/syncres.cc @@ -49,7 +49,7 @@ #include "ednssubnet.hh" #include "cachecleaner.hh" #include "rec-lua-conf.hh" -thread_local std::unique_ptr t_sstorage; +thread_local SyncRes::ThreadLocalStorage SyncRes::t_sstorage; unsigned int SyncRes::s_maxnegttl; unsigned int SyncRes::s_maxcachettl; @@ -121,9 +121,6 @@ SyncRes::SyncRes(const struct timeval& now) : d_outqueries(0), d_tcpoutqueries( d_cacheonly(false), d_nocache(false), d_doDNSSEC(false), d_doEDNS0(false), d_lm(s_lm) { - if(!t_sstorage) { - t_sstorage = std::unique_ptr(new StaticStorage()); - } } /** everything begins here - this is the entry point just after receiving a packet */ @@ -230,7 +227,7 @@ bool SyncRes::doOOBResolve(const DNSName &qname, const QType &qtype, vectordomainmap->end()) { + if(iter==t_sstorage.domainmap->end()) { LOG(prefix<ednsstatus) { + for(const auto& eds : t_sstorage.ednsstatus) { fprintf(fp, "%s\t%d\t%s", eds.first.toString().c_str(), (int)eds.second.mode, ctime(&eds.second.modeSetAt)); } @@ -347,7 +344,7 @@ uint64_t SyncRes::doDumpNSSpeeds(int fd) fprintf(fp, "; nsspeed dump from thread follows\n;\n"); uint64_t count=0; - for(const auto& i : t_sstorage->nsSpeeds) + for(const auto& i : t_sstorage.nsSpeeds) { count++; fprintf(fp, "%s -> ", i.first.toString().c_str()); @@ -406,7 +403,7 @@ int SyncRes::asyncresolveWrapper(const ComboAddress& ip, bool ednsMANDATORY, con */ SyncRes::EDNSStatus* ednsstatus; - ednsstatus = &t_sstorage->ednsstatus[ip]; // does this include port? YES + ednsstatus = &t_sstorage.ednsstatus[ip]; // does this include port? YES if(ednsstatus->modeSetAt && ednsstatus->modeSetAt + 3600 < d_now.tv_sec) { *ednsstatus=SyncRes::EDNSStatus(); @@ -503,7 +500,7 @@ int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vectordomainmap->end()) { + if(iter != t_sstorage.domainmap->end()) { const vector& servers = iter->second.d_servers; if(servers.empty()) { ret.clear(); @@ -635,9 +632,9 @@ vector SyncRes::getAddrs(const DNSName &qname, unsigned int depth, random_shuffle(ret.begin(), ret.end(), dns_random); // move 'best' address for this nameserver name up front - nsspeeds_t::iterator best = t_sstorage->nsSpeeds.find(qname); + nsspeeds_t::iterator best = t_sstorage.nsSpeeds.find(qname); - if(best != t_sstorage->nsSpeeds.end()) + if(best != t_sstorage.nsSpeeds.end()) for(ret_t::iterator i=ret.begin(); i != ret.end(); ++i) { if(*i==best->second.d_best) { // got the fastest one if(i!=ret.begin()) { @@ -732,8 +729,8 @@ SyncRes::domainmap_t::const_iterator SyncRes::getBestAuthZone(DNSName* qname) co { SyncRes::domainmap_t::const_iterator ret; do { - ret=t_sstorage->domainmap->find(*qname); - if(ret!=t_sstorage->domainmap->end()) + ret=t_sstorage.domainmap->find(*qname); + if(ret!=t_sstorage.domainmap->end()) break; }while(qname->chopOff()); return ret; @@ -746,7 +743,7 @@ DNSName SyncRes::getBestNSNamesFromCache(const DNSName &qname, const QType& qtyp DNSName authdomain(qname); domainmap_t::const_iterator iter=getBestAuthZone(&authdomain); - if(iter!=t_sstorage->domainmap->end()) { + if(iter!=t_sstorage.domainmap->end()) { if( iter->second.d_servers.empty() ) // this gets picked up in doResolveAt, the empty DNSName, combined with the // empty vector means 'we are auth for this zone' @@ -858,7 +855,7 @@ bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vectordomainmap->end()) { + if(iter != t_sstorage.domainmap->end()) { wasForwardedOrAuth = true; const vector& servers = iter->second.d_servers; if(servers.empty()) { @@ -868,7 +865,7 @@ bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vectornegcache.getRootNXTrust(qname, d_now, ne) && + t_sstorage.negcache.getRootNXTrust(qname, d_now, ne) && ne.d_auth.isRoot() && !(wasForwardedOrAuth && !authname.isRoot())) { // when forwarding, the root may only neg-cache if it was forwarded to. sttl = ne.d_ttd - d_now.tv_sec; @@ -876,7 +873,7 @@ bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vectornegcache.get(qname, qtype, d_now, ne) && + else if (t_sstorage.negcache.get(qname, qtype, d_now, ne) && !(wasForwardedOrAuth && ne.d_auth != authname)) { // Only the authname nameserver can neg cache entries res = 0; sttl = ne.d_ttd - d_now.tv_sec; @@ -975,7 +972,7 @@ inline vector SyncRes::shuffleInSpeedOrder(NsSet &tnameservers, const s for(const auto& val: rnameservers) { double speed; - speed=t_sstorage->nsSpeeds[val].get(&d_now); + speed=t_sstorage.nsSpeeds[val].get(&d_now); speeds[val]=speed; } random_shuffle(rnameservers.begin(),rnameservers.end(), dns_random); @@ -1115,12 +1112,12 @@ vector SyncRes::retrieveAddressesForNS(const std::string& prefix, bool SyncRes::throttledOrBlocked(const std::string& prefix, const ComboAddress& remoteIP, const DNSName& qname, const QType& qtype, bool pierceDontQuery) { - if(t_sstorage->throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, "", 0))) { + if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, "", 0))) { LOG(prefix<throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()))) { + else if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()))) { LOG(prefix<domainmap->empty()) { + if (!t_sstorage.domainmap->empty()) { // Check if we are authoritative for a zone in this answer DNSName tmp_qname(rec.d_name); auto auth_domain_iter=getBestAuthZone(&tmp_qname); - if(auth_domain_iter!=t_sstorage->domainmap->end() && + if(auth_domain_iter!=t_sstorage.domainmap->end() && auth.countLabels() <= auth_domain_iter->first.countLabels()) { if (auth_domain_iter->first != auth) { LOG("NO! - we are authoritative for the zone "<first<negcache.add(ne); + t_sstorage.negcache.add(ne); if(s_rootNXTrust && ne.d_auth.isRoot() && auth.isRoot()) { ne.d_name = ne.d_name.getLastLabel(); - t_sstorage->negcache.add(ne); + t_sstorage.negcache.add(ne); } } @@ -1335,7 +1332,7 @@ bool SyncRes::processRecords(const std::string& prefix, const DNSName& qname, co ne.d_qtype = qtype; harvestNXRecords(lwr.d_records, ne); if(qtype.getCode()) { // prevents us from blacking out a whole domain - t_sstorage->negcache.add(ne); + t_sstorage.negcache.add(ne); } } negindic=true; @@ -1488,16 +1485,16 @@ int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, con } if(resolveret!=-2) { // don't account for resource limits, they are our own fault - t_sstorage->nsSpeeds[*tns].submit(*remoteIP, 1000000, &d_now); // 1 sec + t_sstorage.nsSpeeds[*tns].submit(*remoteIP, 1000000, &d_now); // 1 sec // code below makes sure we don't filter COM or the root - if (s_serverdownmaxfails > 0 && (auth != g_rootdnsname) && t_sstorage->fails.incr(*remoteIP) >= s_serverdownmaxfails) { + if (s_serverdownmaxfails > 0 && (auth != g_rootdnsname) && t_sstorage.fails.incr(*remoteIP) >= s_serverdownmaxfails) { LOG(prefix<toString() <<". Going full throttle for "<< s_serverdownthrottletime <<" seconds" <throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, "", 0), s_serverdownthrottletime, 10000); // mark server as down + t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, "", 0), s_serverdownthrottletime, 10000); // mark server as down } else if(resolveret==-1) - t_sstorage->throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100); // unreachable, 1 minute or 100 queries + t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100); // unreachable, 1 minute or 100 queries else - t_sstorage->throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 10, 5); // timeout + t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 10, 5); // timeout } continue; } @@ -1506,17 +1503,17 @@ int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, con if(lwr.d_rcode==RCode::ServFail || lwr.d_rcode==RCode::Refused) { LOG(prefix<toString()<<") returned a "<< (lwr.d_rcode==RCode::ServFail ? "ServFail" : "Refused") << ", trying sibling IP or NS"<throttle.throttle(d_now.tv_sec,boost::make_tuple(*remoteIP, qname, qtype.getCode()),60,3); // servfail or refused + t_sstorage.throttle.throttle(d_now.tv_sec,boost::make_tuple(*remoteIP, qname, qtype.getCode()),60,3); // servfail or refused continue; } if(s_serverdownmaxfails > 0) - t_sstorage->fails.clear(*remoteIP); + t_sstorage.fails.clear(*remoteIP); break; // this IP address worked! wasLame:; // well, it didn't LOG(prefix<toString() <<") is lame for '"<throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100); // lame + t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100); // lame } } @@ -1540,7 +1537,7 @@ int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, con */ // cout<<"msec: "<nsSpeeds[*tns].submit(*remoteIP, lwr.d_usec, &d_now); + t_sstorage.nsSpeeds[*tns].submit(*remoteIP, lwr.d_usec, &d_now); } if(s_minimumTTL) { @@ -1599,8 +1596,8 @@ int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, con else if(realreferral) { LOG(prefix<dnssecmap[newauth]=true; - /* for(const auto& e : t_sstorage->dnssecmap) + //s_dnssecmap[newauth]=true; + /* for(const auto& e : s_dnssecmap) cout<& srcmask, boost::optional context, std::shared_ptr outgoingLogger, LWResult *lwr)> asyncresolve_t; + struct EDNSStatus + { + EDNSStatus() : mode(UNKNOWN), modeSetAt(0) {} + enum EDNSMode { UNKNOWN=0, EDNSOK=1, EDNSIGNORANT=2, NOEDNS=3 } mode; + time_t modeSetAt; + }; + + //! This represents a number of decaying Ewmas, used to store performance per nameserver-name. + /** Modelled to work mostly like the underlying DecayingEwma. After you've called get, + d_best is filled out with the best address for this collection */ + struct DecayingEwmaCollection + { + void submit(const ComboAddress& remote, int usecs, const struct timeval* now) + { + collection_t::iterator pos; + for(pos=d_collection.begin(); pos != d_collection.end(); ++pos) + if(pos->first==remote) + break; + if(pos!=d_collection.end()) { + pos->second.submit(usecs, now); + } + else { + DecayingEwma de; + de.submit(usecs, now); + d_collection.push_back(make_pair(remote, de)); + } + } + + double get(const struct timeval* now) + { + if(d_collection.empty()) + return 0; + double ret=std::numeric_limits::max(); + double tmp; + for(collection_t::iterator pos=d_collection.begin(); pos != d_collection.end(); ++pos) { + if((tmp=pos->second.get(now)) < ret) { + ret=tmp; + d_best=pos->first; + } + } + + return ret; + } + + bool stale(time_t limit) const + { + for(collection_t::const_iterator pos=d_collection.begin(); pos != d_collection.end(); ++pos) + if(!pos->second.stale(limit)) + return false; + return true; + } + + typedef vector > collection_t; + collection_t d_collection; + ComboAddress d_best; + }; + + typedef map nsspeeds_t; + typedef map ednsstatus_t; + + struct AuthDomain + { + vector d_servers; + bool d_rdForward; + typedef multi_index_container < + DNSRecord, + indexed_by < + ordered_non_unique< + composite_key< DNSRecord, + member, + member + >, + composite_key_compare, std::less > + > + > + > records_t; + records_t d_records; + }; + + typedef map domainmap_t; + typedef Throttle > throttle_t; + typedef Counters fails_t; + + struct ThreadLocalStorage { + NegCache negcache; + nsspeeds_t nsSpeeds; + throttle_t throttle; + ednsstatus_t ednsstatus; + fails_t fails; + std::shared_ptr domainmap; + }; + static void setDefaultLogMode(LogMode lm) { s_lm = lm; @@ -329,6 +410,107 @@ public: { s_ednsdomains = SuffixMatchNode(); } + static void pruneNSSpeeds(time_t limit) + { + for(auto i = t_sstorage.nsSpeeds.begin(), end = t_sstorage.nsSpeeds.end(); i != end; ) { + if(i->second.stale(limit)) { + i = t_sstorage.nsSpeeds.erase(i); + } + else { + ++i; + } + } + } + static uint64_t getNSSpeedsSize() + { + return t_sstorage.nsSpeeds.size(); + } + static void submitNSSpeed(const DNSName& server, const ComboAddress& ca, uint32_t usec, const struct timeval* now) + { + t_sstorage.nsSpeeds[server].submit(ca, usec, now); + } + static void clearNSSpeeds() + { + t_sstorage.nsSpeeds.clear(); + } + static EDNSStatus::EDNSMode getEDNSStatus(const ComboAddress& server) + { + const auto& it = t_sstorage.ednsstatus.find(server); + if (it == t_sstorage.ednsstatus.end()) + return EDNSStatus::UNKNOWN; + + return it->second.mode; + } + static uint64_t getEDNSStatusesSize() + { + return t_sstorage.ednsstatus.size(); + } + static void clearEDNSStatuses() + { + t_sstorage.ednsstatus.clear(); + } + static uint64_t getThrottledServersSize() + { + return t_sstorage.throttle.size(); + } + static void clearThrottle() + { + t_sstorage.throttle.clear(); + } + static bool isThrottled(time_t now, const ComboAddress& server, const DNSName& target, uint16_t qtype) + { + return t_sstorage.throttle.shouldThrottle(now, boost::make_tuple(server, target, qtype)); + } + static bool isThrottled(time_t now, const ComboAddress& server) + { + return t_sstorage.throttle.shouldThrottle(now, boost::make_tuple(server, "", 0)); + } + static void doThrottle(time_t now, const ComboAddress& server, time_t duration, unsigned int tries) + { + t_sstorage.throttle.throttle(now, boost::make_tuple(server, "", 0), duration, tries); + } + static uint64_t getFailedServersSize() + { + return t_sstorage.fails.size(); + } + static void clearFailedServers() + { + t_sstorage.fails.clear(); + } + static unsigned long getServerFailsCount(const ComboAddress& server) + { + return t_sstorage.fails.value(server); + } + + static void clearNegCache() + { + t_sstorage.negcache.clear(); + } + + static uint64_t getNegCacheSize() + { + return t_sstorage.negcache.size(); + } + + static void pruneNegCache(unsigned int maxEntries) + { + t_sstorage.negcache.prune(maxEntries); + } + + static uint64_t wipeNegCache(const DNSName& name, bool subtree = false) + { + return t_sstorage.negcache.wipe(name, subtree); + } + + static void setDomainMap(std::shared_ptr newMap) + { + t_sstorage.domainmap = newMap; + } + + static const std::shared_ptr getDomainMap() + { + return t_sstorage.domainmap; + } explicit SyncRes(const struct timeval& now); @@ -430,6 +612,8 @@ public: d_asyncResolve = func; } + static thread_local ThreadLocalStorage t_sstorage; + static std::atomic s_queries; static std::atomic s_outgoingtimeouts; static std::atomic s_outgoing4timeouts; @@ -441,103 +625,6 @@ public: static std::atomic s_nodelegated; static std::atomic s_unreachables; - std::unordered_map d_discardedPolicies; - DNSFilterEngine::Policy d_appliedPolicy; - 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; - - //! This represents a number of decaying Ewmas, used to store performance per nameserver-name. - /** Modelled to work mostly like the underlying DecayingEwma. After you've called get, - d_best is filled out with the best address for this collection */ - struct DecayingEwmaCollection - { - void submit(const ComboAddress& remote, int usecs, struct timeval* now) - { - collection_t::iterator pos; - for(pos=d_collection.begin(); pos != d_collection.end(); ++pos) - if(pos->first==remote) - break; - if(pos!=d_collection.end()) { - pos->second.submit(usecs, now); - } - else { - DecayingEwma de; - de.submit(usecs, now); - d_collection.push_back(make_pair(remote, de)); - } - } - - double get(struct timeval* now) - { - if(d_collection.empty()) - return 0; - double ret=std::numeric_limits::max(); - double tmp; - for(collection_t::iterator pos=d_collection.begin(); pos != d_collection.end(); ++pos) { - if((tmp=pos->second.get(now)) < ret) { - ret=tmp; - d_best=pos->first; - } - } - - return ret; - } - - bool stale(time_t limit) const - { - for(collection_t::const_iterator pos=d_collection.begin(); pos != d_collection.end(); ++pos) - if(!pos->second.stale(limit)) - return false; - return true; - } - - typedef vector > collection_t; - collection_t d_collection; - ComboAddress d_best; - }; - - typedef map nsspeeds_t; - - struct EDNSStatus - { - EDNSStatus() : mode(UNKNOWN), modeSetAt(0) {} - enum EDNSMode { UNKNOWN=0, EDNSOK=1, EDNSIGNORANT=2, NOEDNS=3 } mode; - time_t modeSetAt; - }; - - typedef map ednsstatus_t; - - struct AuthDomain - { - vector d_servers; - bool d_rdForward; - typedef multi_index_container < - DNSRecord, - indexed_by < - ordered_non_unique< - composite_key< DNSRecord, - member, - member - >, - composite_key_compare, std::less > - > - > - > records_t; - records_t d_records; - }; - - - typedef map domainmap_t; - - typedef Throttle > throttle_t; - - typedef Counters fails_t; - static string s_serverID; static unsigned int s_minimumTTL; static unsigned int s_maxqperq; @@ -557,17 +644,18 @@ public: static bool s_rootNXTrust; static bool s_nopacketcache; - struct StaticStorage { - nsspeeds_t nsSpeeds; - ednsstatus_t ednsstatus; - throttle_t throttle; - fails_t fails; - std::shared_ptr domainmap; - map dnssecmap; - NegCache negcache; - }; + std::unordered_map d_discardedPolicies; + DNSFilterEngine::Policy d_appliedPolicy; + 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; private: + static std::unordered_set s_delegationOnly; static NetmaskGroup s_ednssubnets; static SuffixMatchNode s_ednsdomains; @@ -642,7 +730,6 @@ private: LogMode d_lm; }; -extern thread_local std::unique_ptr t_sstorage; class Socket; /* external functions, opaque to us */ diff --git a/pdns/ws-recursor.cc b/pdns/ws-recursor.cc index 7b284fd89..92d5494c4 100644 --- a/pdns/ws-recursor.cc +++ b/pdns/ws-recursor.cc @@ -116,8 +116,8 @@ static void apiServerConfigAllowFrom(HttpRequest* req, HttpResponse* resp) static void fillZone(const DNSName& zonename, HttpResponse* resp) { - auto iter = t_sstorage->domainmap->find(zonename); - if (iter == t_sstorage->domainmap->end()) + auto iter = SyncRes::t_sstorage.domainmap->find(zonename); + if (iter == SyncRes::t_sstorage.domainmap->end()) throw ApiException("Could not find domain '"+zonename.toString()+"'"); const SyncRes::AuthDomain& zone = iter->second; @@ -251,8 +251,8 @@ static void apiServerZones(HttpRequest* req, HttpResponse* resp) DNSName zonename = apiNameToDNSName(stringFromJson(document, "name")); - auto iter = t_sstorage->domainmap->find(zonename); - if (iter != t_sstorage->domainmap->end()) + auto iter = SyncRes::t_sstorage.domainmap->find(zonename); + if (iter != SyncRes::t_sstorage.domainmap->end()) throw ApiException("Zone already exists"); doCreateZone(document); @@ -266,7 +266,7 @@ static void apiServerZones(HttpRequest* req, HttpResponse* resp) throw HttpMethodNotAllowedException(); Json::array doc; - for(const SyncRes::domainmap_t::value_type& val : *t_sstorage->domainmap) { + for(const SyncRes::domainmap_t::value_type& val : *SyncRes::t_sstorage.domainmap) { const SyncRes::AuthDomain& zone = val.second; Json::array servers; for(const ComboAddress& server : zone.d_servers) { @@ -290,8 +290,8 @@ static void apiServerZoneDetail(HttpRequest* req, HttpResponse* resp) { DNSName zonename = apiZoneIdToName(req->parameters["id"]); - SyncRes::domainmap_t::const_iterator iter = t_sstorage->domainmap->find(zonename); - if (iter == t_sstorage->domainmap->end()) + SyncRes::domainmap_t::const_iterator iter = SyncRes::t_sstorage.domainmap->find(zonename); + if (iter == SyncRes::t_sstorage.domainmap->end()) throw ApiException("Could not find domain '"+zonename.toString()+"'"); if(req->method == "PUT" && !::arg().mustDo("api-readonly")) { @@ -328,7 +328,7 @@ static void apiServerSearchData(HttpRequest* req, HttpResponse* resp) { throw ApiException("Query q can't be blank"); Json::array doc; - for(const SyncRes::domainmap_t::value_type& val : *t_sstorage->domainmap) { + for(const SyncRes::domainmap_t::value_type& val : *SyncRes::t_sstorage.domainmap) { string zoneId = apiZoneNameToId(val.first); string zoneName = val.first.toString(); if (pdns_ci_find(zoneName, q) != string::npos) {