const auto& idx = content->d_map.get<NegCacheEntry>();
auto range = idx.equal_range(qname);
- auto ni = range.first;
- while (ni != range.second) {
+ for (auto ni = range.first; ni != range.second; ++ni) {
// We have an entry
if ((!typeMustMatch && ni->d_qtype == QType::ENT) || ni->d_qtype == qtype) {
// We match the QType or the whole name is denied
auto firstIndexIterator = content->d_map.project<CompositeKey>(ni);
- if (!refresh && (serveStale || ni->d_servedStale > 0) && ni->d_ttd <= now.tv_sec && ni->d_servedStale < s_maxServedStaleExtensions) {
+ // this checks ttd, but also takes into account serve-stale
+ if (!ni->isEntryUsable(now.tv_sec, serveStale)) {
+ // Outdated
+ moveCacheItemToFront<SequenceTag>(content->d_map, firstIndexIterator);
+ continue;
+ }
+ // If we are serving this record stale (or *should*) and the ttd has passed increase ttd to
+ // the future and remember that we did. Also push a refresh task.
+ if ((serveStale || ni->d_servedStale > 0) && ni->d_ttd <= now.tv_sec && ni->d_servedStale < s_maxServedStaleExtensions) {
updateStaleEntry(now.tv_sec, firstIndexIterator, qtype);
}
- if (now.tv_sec < ni->d_ttd && !(refresh && ni->d_servedStale > 0)) {
+ if (now.tv_sec < ni->d_ttd) {
// Not expired
ne = *ni;
moveCacheItemToBack<SequenceTag>(content->d_map, firstIndexIterator);
- return true;
+ return !refresh; // when refreshing, we consider everything outdated
}
- // expired
- moveCacheItemToFront<SequenceTag>(content->d_map, firstIndexIterator);
}
- ++ni;
}
return false;
}
return d_ttd < now;
}
};
+
+ bool isEntryUsable(time_t now, bool serveStale) const
+ {
+ // When serving stale, we consider expired records
+ return d_ttd > now || serveStale || d_servedStale != 0;
+ }
};
void add(const NegCacheEntry& ne);