From 2b94bb415eb33d909e064cadea06a7c2fcea7380 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Wed, 10 Feb 2016 09:02:17 +0100 Subject: [PATCH] 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. --- pdns/recpacketcache.cc | 7 +++++++ pdns/recursor_cache.cc | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+) 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); } -- 2.47.2