From: Remi Gacogne Date: Wed, 10 Feb 2016 08:02:17 +0000 (+0100) Subject: recursor: when replacing an expired entry, move it to the back X-Git-Tag: rec-3.7.4~5^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F3352%2Fhead;p=thirdparty%2Fpdns.git recursor: when replacing an expired entry, move it to the back If we did a lookup earlier and found the entry to be expired, we moved it to the front of the expunge queue. If we don't move it to the back, and the next cache purging operation occurs before a cache hit using this entry, it's very likely to get expunged. --- diff --git a/pdns/recpacketcache.cc b/pdns/recpacketcache.cc index c9e89d12b1..76534530ae 100644 --- a/pdns/recpacketcache.cc +++ b/pdns/recpacketcache.cc @@ -92,6 +92,13 @@ void RecursorPacketCache::insertResponsePacket(const std::string& responsePacket packetCache_t::iterator iter = d_packetCache.find(e); if(iter != d_packetCache.end()) { + if (iter->d_ttd <= now) { + /* entry had expired, a cache miss might have + moved it to the front, and we don't want to + get expunged just right now */ + moveCacheItemToBack(d_packetCache, iter); + } + iter->d_packet = responsePacket; iter->d_ttd = now + ttl; iter->d_creation = now; diff --git a/pdns/recursor_cache.cc b/pdns/recursor_cache.cc index dda3f42666..2c9cb2f850 100644 --- a/pdns/recursor_cache.cc +++ b/pdns/recursor_cache.cc @@ -191,10 +191,23 @@ void MemRecursorCache::replace(time_t now, const string &qname, const QType& qt, cache_t::iterator stored=d_cache.find(key); uint32_t maxTTD=UINT_MAX; + bool hadExpired=false; bool isNew=false; if(stored == d_cache.end()) { stored=d_cache.insert(CacheEntry(key,vector(), auth)).first; isNew=true; + } else { + vector::const_iterator j; + bool expired=true; + for(j = stored->d_records.begin() ; j != stored->d_records.end(); ++j) { + if (now < j->d_ttd) { + expired = false; + break; + } + } + if (expired) { + hadExpired = true; + } } pair::iterator, vector::iterator> range; @@ -290,6 +303,12 @@ void MemRecursorCache::replace(time_t now, const string &qname, const QType& qt, if(ce.d_records.capacity() != ce.d_records.size()) vector(ce.d_records).swap(ce.d_records); + if (hadExpired) { + /* previous entry had expired, a cache miss might have + moved it to the front, and we don't want to + get expunged just right now */ + moveCacheItemToBack(d_cache, stored); + } d_cache.replace(stored, ce); }