}
uint64_t maps_size = maps.size();
- if (maps_size == 0)
- return 0;
+ if (maps_size == 0) {
+ return 0;
+ }
- for (auto& lockGuardedMap : maps) {
- auto mc = C::lock(lockGuardedMap);
+ for (auto& content : maps) {
+ auto mc = C::lock(content.d_content);
mc->invalidate();
auto& sidx = boost::multi_index::get<S>(mc->d_map);
uint64_t erased = 0, lookedAt = 0;
container.preRemoval(*mc, *i);
i = sidx.erase(i);
erased++;
- mc->d_entriesCount--;
+ --content.d_entriesCount;
} else {
++i;
}
while (true) {
size_t pershard = toTrim / maps_size + 1;
- for (auto& lockGuardedMap : maps) {
- auto mc = C::lock(lockGuardedMap);
+ for (auto& content : maps) {
+ auto mc = C::lock(content.d_content);
mc->invalidate();
auto& sidx = boost::multi_index::get<S>(mc->d_map);
size_t removed = 0;
for (auto i = sidx.begin(); i != sidx.end() && removed < pershard; removed++) {
container.preRemoval(*mc, *i);
i = sidx.erase(i);
- mc->d_entriesCount--;
+ --content.d_entriesCount;
totErased++;
toTrim--;
if (toTrim == 0) {
{
}
-size_t MemRecursorCache::size()
+size_t MemRecursorCache::size() const
{
size_t count = 0;
- for (auto& lockGuardedMap : d_maps) {
- auto map = lock(lockGuardedMap);
- count += map->d_entriesCount;
+ for (const auto& map : d_maps) {
+ count += map.d_entriesCount;
}
return count;
}
pair<uint64_t,uint64_t> MemRecursorCache::stats()
{
uint64_t c = 0, a = 0;
- for (auto& lockGuardedMap : d_maps) {
- auto map = lock(lockGuardedMap);
- c += map->d_contended_count;
- a += map->d_acquired_count;
+ for (auto& mc : d_maps) {
+ auto content = lock(mc.d_content);
+ c += content->d_contended_count;
+ a += content->d_acquired_count;
}
return pair<uint64_t,uint64_t>(c, a);
}
{
// XXX!
size_t count = 0;
- for (auto& map : d_maps) {
- auto m = lock(map);
- count += m->d_ecsIndex.size();
+ for (auto& mc : d_maps) {
+ auto content = lock(mc.d_content);
+ count += content->d_ecsIndex.size();
}
return count;
}
size_t MemRecursorCache::bytes()
{
size_t ret = 0;
- for (auto& map : d_maps) {
- auto m = lock(map);
+ for (auto& mc : d_maps) {
+ auto m = lock(mc.d_content);
for (const auto& i : m->d_map) {
ret += sizeof(struct CacheEntry);
ret += i.d_qname.toString().length();
}
}
-time_t MemRecursorCache::handleHit(MapCombo& map, MemRecursorCache::OrderedTagIterator_t& entry, const DNSName& qname, uint32_t& origTTL, vector<DNSRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, boost::optional<vState>& state, bool* wasAuth, DNSName* fromAuthZone)
+time_t MemRecursorCache::handleHit(MapCombo::LockedContent& content, MemRecursorCache::OrderedTagIterator_t& entry, const DNSName& qname, uint32_t& origTTL, vector<DNSRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, boost::optional<vState>& state, bool* wasAuth, DNSName* fromAuthZone)
{
- // MUTEX SHOULD BE ACQUIRED
+ // MUTEX SHOULD BE ACQUIRED (as indicated by the reference to the content which is protected by a lock)
time_t ttd = entry->d_ttd;
origTTL = entry->d_orig_ttl;
*fromAuthZone = entry->d_authZone;
}
- moveCacheItemToBack<SequencedTag>(map.d_map, entry);
+ moveCacheItemToBack<SequencedTag>(content.d_map, entry);
return ttd;
}
-MemRecursorCache::cache_t::const_iterator MemRecursorCache::getEntryUsingECSIndex(MapCombo& map, time_t now, const DNSName &qname, const QType qtype, bool requireAuth, const ComboAddress& who)
+MemRecursorCache::cache_t::const_iterator MemRecursorCache::getEntryUsingECSIndex(MapCombo::LockedContent& map, time_t now, const DNSName &qname, const QType qtype, bool requireAuth, const ComboAddress& who)
{
- // MUTEX SHOULD BE ACQUIRED
+ // MUTEX SHOULD BE ACQUIRED (as indicated by the reference to the content which is protected by a lock)
auto ecsIndexKey = tie(qname, qtype);
auto ecsIndex = map.d_ecsIndex.find(ecsIndexKey);
if (ecsIndex != map.d_ecsIndex.end() && !ecsIndex->isEmpty()) {
return map.d_map.end();
}
-MemRecursorCache::Entries MemRecursorCache::getEntries(MapCombo& map, const DNSName &qname, const QType qt, const OptTag& rtag )
+MemRecursorCache::Entries MemRecursorCache::getEntries(MapCombo::LockedContent& map, const DNSName &qname, const QType qt, const OptTag& rtag )
{
// MUTEX SHOULD BE ACQUIRED
if (!map.d_cachecachevalid || map.d_cachedqname != qname || map.d_cachedrtag != rtag) {
*wasAuth = true;
}
- auto& lockGuardedMap = getMap(qname);
- auto map = lock(lockGuardedMap);
+ auto& mc = getMap(qname);
+ auto map = lock(mc.d_content);
/* If we don't have any netmask-specific entries at all, let's just skip this
to be able to use the nice d_cachecache hack. */
void MemRecursorCache::replace(time_t now, const DNSName &qname, const QType qt, const vector<DNSRecord>& content, const vector<shared_ptr<RRSIGRecordContent>>& signatures, const std::vector<std::shared_ptr<DNSRecord>>& authorityRecs, bool auth, const DNSName& authZone, boost::optional<Netmask> ednsmask, const OptTag& routingTag, vState state, boost::optional<ComboAddress> from)
{
- auto& lockGuardedMap = getMap(qname);
- auto map = lock(lockGuardedMap);
+ auto& mc = getMap(qname);
+ auto map = lock(mc.d_content);
map->d_cachecachevalid = false;
if (ednsmask) {
cache_t::iterator stored = map->d_map.find(key);
if (stored == map->d_map.end()) {
stored = map->d_map.insert(CacheEntry(key, auth)).first;
- map->d_entriesCount++;
+ ++mc.d_entriesCount;
isNew = true;
}
size_t count = 0;
if (!sub) {
- auto& lockGuardedMap = getMap(name);
- auto map = lock(lockGuardedMap);
+ auto& mc = getMap(name);
+ auto map = lock(mc.d_content);
map->d_cachecachevalid = false;
auto& idx = map->d_map.get<OrderedTag>();
auto range = idx.equal_range(name);
if (i->d_qtype == qtype || qtype == 0xffff) {
i = idx.erase(i);
count++;
- map->d_entriesCount--;
+ --mc.d_entriesCount;
} else {
++i;
}
}
}
else {
- for (auto& lockGuardedMap : d_maps) {
- auto map = lock(lockGuardedMap);
+ for (auto& mc : d_maps) {
+ auto map = lock(mc.d_content);
map->d_cachecachevalid = false;
auto& idx = map->d_map.get<OrderedTag>();
for (auto i = idx.lower_bound(name); i != idx.end(); ) {
if (i->d_qtype == qtype || qtype == 0xffff) {
count++;
i = idx.erase(i);
- map->d_entriesCount--;
+ --mc.d_entriesCount;
} else {
++i;
}
// Name should be doLimitTime or so
bool MemRecursorCache::doAgeCache(time_t now, const DNSName& name, const QType qtype, uint32_t newTTL)
{
- auto& lockGuardedMap = getMap(name);
- auto map = lock(lockGuardedMap);
+ auto& mc = getMap(name);
+ auto map = lock(mc.d_content);
cache_t::iterator iter = map->d_map.find(tie(name, qtype));
if (iter == map->d_map.end()) {
return false;
throw std::runtime_error("Trying to update the DNSSEC validation status of several (via ADDR) records for " + qname.toLogString());
}
- auto& lockGuardedMap = getMap(qname);
- auto map = lock(lockGuardedMap);
+ auto& mc = getMap(qname);
+ auto map = lock(mc.d_content);
bool updated = false;
if (!map->d_ecsIndex.empty() && !routingTag) {
fprintf(fp.get(), "; main record cache dump follows\n;\n");
uint64_t count = 0;
- for (auto& lockGuardedMap : d_maps) {
- auto map = lock(lockGuardedMap);
+ for (auto& mc : d_maps) {
+ auto map = lock(mc.d_content);
const auto& sidx = map->d_map.get<SequencedTag>();
time_t now = time(nullptr);
public:
MemRecursorCache(size_t mapsCount = 1024);
- size_t size();
+ size_t size() const;
size_t bytes();
pair<uint64_t,uint64_t> stats();
size_t ecsIndexSize();
> ecsIndex_t;
typedef std::pair<NameAndRTagOnlyHashedTagIterator_t, NameAndRTagOnlyHashedTagIterator_t> Entries;
-
+
struct MapCombo
{
MapCombo() {}
MapCombo(const MapCombo &) = delete;
MapCombo & operator=(const MapCombo &) = delete;
- cache_t d_map;
- ecsIndex_t d_ecsIndex;
- DNSName d_cachedqname;
- OptTag d_cachedrtag;
- Entries d_cachecache;
- bool d_cachecachevalid{false};
- std::atomic<uint64_t> d_entriesCount{0};
- uint64_t d_contended_count{0};
- uint64_t d_acquired_count{0};
-
- void invalidate()
+ struct LockedContent
{
- d_cachecachevalid = false;
- }
+ cache_t d_map;
+ ecsIndex_t d_ecsIndex;
+ DNSName d_cachedqname;
+ OptTag d_cachedrtag;
+ Entries d_cachecache;
+ uint64_t d_contended_count{0};
+ uint64_t d_acquired_count{0};
+ bool d_cachecachevalid{false};
+
+ void invalidate()
+ {
+ d_cachecachevalid = false;
+ }
+ };
+
+ LockGuarded<LockedContent> d_content;
+ std::atomic<uint64_t> d_entriesCount{0};
};
- vector<LockGuarded<MapCombo>> d_maps;
- LockGuarded<MapCombo>& getMap(const DNSName &qname)
+ vector<MapCombo> d_maps;
+ MapCombo& getMap(const DNSName &qname)
{
return d_maps.at(qname.hash() % d_maps.size());
}
static time_t fakeTTD(OrderedTagIterator_t& entry, const DNSName& qname, QType qtype, time_t ret, time_t now, uint32_t origTTL, bool refresh);
bool entryMatches(OrderedTagIterator_t& entry, QType qt, bool requireAuth, const ComboAddress& who);
- Entries getEntries(MapCombo& map, const DNSName &qname, const QType qt, const OptTag& rtag);
- cache_t::const_iterator getEntryUsingECSIndex(MapCombo& map, time_t now, const DNSName &qname, QType qtype, bool requireAuth, const ComboAddress& who);
+ Entries getEntries(MapCombo::LockedContent& content, const DNSName &qname, const QType qt, const OptTag& rtag);
+ cache_t::const_iterator getEntryUsingECSIndex(MapCombo::LockedContent& content, time_t now, const DNSName &qname, QType qtype, bool requireAuth, const ComboAddress& who);
- time_t handleHit(MapCombo& map, OrderedTagIterator_t& entry, const DNSName& qname, uint32_t& origTTL, vector<DNSRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, boost::optional<vState>& state, bool* wasAuth, DNSName* authZone);
+ time_t handleHit(MapCombo::LockedContent& content, OrderedTagIterator_t& entry, const DNSName& qname, uint32_t& origTTL, vector<DNSRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, boost::optional<vState>& state, bool* wasAuth, DNSName* authZone);
public:
- static LockGuardedTryHolder<MapCombo> lock(LockGuarded<MapCombo>& map)
+ static LockGuardedTryHolder<MapCombo::LockedContent> lock(LockGuarded<MapCombo::LockedContent>& content)
{
- auto locked = map.try_lock();
+ auto locked = content.try_lock();
if (!locked.owns_lock()) {
locked.lock();
- locked->d_contended_count++;
+ ++locked->d_contended_count;
}
++locked->d_acquired_count;
return locked;
}
- void preRemoval(MapCombo& map, const CacheEntry& entry)
+ void preRemoval(MapCombo::LockedContent& map, const CacheEntry& entry)
{
if (entry.d_netmask.empty()) {
return;
{
}
-size_t NegCache::size()
+size_t NegCache::size() const
{
size_t count = 0;
- for (auto& lockGuardedMap : d_maps) {
- auto map = lock(lockGuardedMap);
- count += map->d_entriesCount;
+ for (const auto& map : d_maps) {
+ count += map.d_entriesCount;
}
return count;
}
static const QType qtnull(0);
DNSName lastLabel = qname.getLastLabel();
- auto& lockGuardedMap = getMap(lastLabel);
- auto map = lock(lockGuardedMap);
+ auto& map = getMap(lastLabel);
+ auto content = lock(map.d_content);
- negcache_t::const_iterator ni = map->d_map.find(tie(lastLabel, qtnull));
+ negcache_t::const_iterator ni = content->d_map.find(tie(lastLabel, qtnull));
- while (ni != map->d_map.end() && ni->d_name == lastLabel && ni->d_auth.isRoot() && ni->d_qtype == qtnull) {
+ while (ni != content->d_map.end() && ni->d_name == lastLabel && ni->d_auth.isRoot() && ni->d_qtype == qtnull) {
// We have something
if (now.tv_sec < ni->d_ttd) {
ne = *ni;
- moveCacheItemToBack<SequenceTag>(map->d_map, ni);
+ moveCacheItemToBack<SequenceTag>(content->d_map, ni);
return true;
}
- moveCacheItemToFront<SequenceTag>(map->d_map, ni);
+ moveCacheItemToFront<SequenceTag>(content->d_map, ni);
++ni;
}
return false;
*/
bool NegCache::get(const DNSName& qname, const QType& qtype, const struct timeval& now, NegCacheEntry& ne, bool typeMustMatch)
{
- auto& lockGuardedMap = getMap(qname);
- auto map = lock(lockGuardedMap);
+ auto& map = getMap(qname);
+ auto content = lock(map.d_content);
- const auto& idx = map->d_map.get<NegCacheEntry>();
+ const auto& idx = content->d_map.get<NegCacheEntry>();
auto range = idx.equal_range(qname);
auto ni = range.first;
// We have an entry
if ((!typeMustMatch && ni->d_qtype.getCode() == 0) || ni->d_qtype == qtype) {
// We match the QType or the whole name is denied
- auto firstIndexIterator = map->d_map.project<CompositeKey>(ni);
+ auto firstIndexIterator = content->d_map.project<CompositeKey>(ni);
if (now.tv_sec < ni->d_ttd) {
// Not expired
ne = *ni;
- moveCacheItemToBack<SequenceTag>(map->d_map, firstIndexIterator);
+ moveCacheItemToBack<SequenceTag>(content->d_map, firstIndexIterator);
return true;
}
// expired
- moveCacheItemToFront<SequenceTag>(map->d_map, firstIndexIterator);
+ moveCacheItemToFront<SequenceTag>(content->d_map, firstIndexIterator);
}
++ni;
}
*/
void NegCache::add(const NegCacheEntry& ne)
{
- auto& lockGuardedMap = getMap(ne.d_name);
- auto map = lock(lockGuardedMap);
- bool inserted = lruReplacingInsert<SequenceTag>(map->d_map, ne);
+ bool inserted = false;
+ auto& map = getMap(ne.d_name);
+ auto content = lock(map.d_content);
+ inserted = lruReplacingInsert<SequenceTag>(content->d_map, ne);
if (inserted) {
- ++map->d_entriesCount;
+ ++map.d_entriesCount;
}
}
*/
void NegCache::updateValidationStatus(const DNSName& qname, const QType& qtype, const vState newState, boost::optional<time_t> capTTD)
{
- auto& lockGuardedMap = getMap(qname);
- auto map = lock(lockGuardedMap);
+ auto& mc = getMap(qname);
+ auto map = lock(mc.d_content);
auto range = map->d_map.equal_range(tie(qname, qtype));
if (range.first != range.second) {
*/
size_t NegCache::count(const DNSName& qname)
{
- auto& lockGuardedMap = getMap(qname);
- auto map = lock(lockGuardedMap);
- return map->d_map.count(tie(qname));
+ auto& map = getMap(qname);
+ auto content = lock(map.d_content);
+ return content->d_map.count(tie(qname));
}
/*!
*/
size_t NegCache::count(const DNSName& qname, const QType qtype)
{
- auto& lockGuardedMap = getMap(qname);
- auto map = lock(lockGuardedMap);
- return map->d_map.count(tie(qname, qtype));
+ auto& map = getMap(qname);
+ auto content = lock(map.d_content);
+ return content->d_map.count(tie(qname, qtype));
}
/*!
size_t ret = 0;
if (subtree) {
for (auto& map : d_maps) {
- auto m = lock(map);
+ auto m = lock(map.d_content);
for (auto i = m->d_map.lower_bound(tie(name)); i != m->d_map.end();) {
if (!i->d_name.isPartOf(name))
break;
i = m->d_map.erase(i);
ret++;
- --m->d_entriesCount;
+ --map.d_entriesCount;
}
}
return ret;
}
- auto& lockGuardedMap = getMap(name);
- auto map = lock(lockGuardedMap);
- auto range = map->d_map.equal_range(tie(name));
+ auto& map = getMap(name);
+ auto content = lock(map.d_content);
+ auto range = content->d_map.equal_range(tie(name));
auto i = range.first;
while (i != range.second) {
- i = map->d_map.erase(i);
+ i = content->d_map.erase(i);
ret++;
- --map->d_entriesCount;
+ --map.d_entriesCount;
}
return ret;
}
void NegCache::clear()
{
for (auto& map : d_maps) {
- auto m = lock(map);
+ auto m = lock(map.d_content);
m->d_map.clear();
- m->d_entriesCount = 0;
+ map.d_entriesCount = 0;
}
}
{
size_t ret = 0;
- for (auto& map : d_maps) {
- auto m = lock(map);
+ for (auto& mc : d_maps) {
+ auto m = lock(mc.d_content);
auto& sidx = m->d_map.get<SequenceTag>();
for (const NegCacheEntry& ne : sidx) {
ret++;
void clear();
size_t dumpToFile(FILE* fd, const struct timeval& now);
size_t wipe(const DNSName& name, bool subtree = false);
- size_t size();
+ size_t size() const;
private:
struct CompositeKey
MapCombo() {}
MapCombo(const MapCombo&) = delete;
MapCombo& operator=(const MapCombo&) = delete;
- negcache_t d_map;
+ struct LockedContent
+ {
+ negcache_t d_map;
+ uint64_t d_contended_count{0};
+ uint64_t d_acquired_count{0};
+ void invalidate() {}
+ };
+ LockGuarded<LockedContent> d_content;
std::atomic<uint64_t> d_entriesCount{0};
- uint64_t d_contended_count{0};
- uint64_t d_acquired_count{0};
- void invalidate() {}
};
- vector<LockGuarded<MapCombo>> d_maps;
+ vector<MapCombo> d_maps;
- LockGuarded<MapCombo>& getMap(const DNSName& qname)
+ MapCombo& getMap(const DNSName& qname)
{
return d_maps.at(qname.hash() % d_maps.size());
}
- const LockGuarded<MapCombo>& getMap(const DNSName& qname) const
+ const MapCombo& getMap(const DNSName& qname) const
{
return d_maps.at(qname.hash() % d_maps.size());
}
public:
- static LockGuardedTryHolder<MapCombo> lock(LockGuarded<MapCombo>& map)
+ static LockGuardedTryHolder<MapCombo::LockedContent> lock(LockGuarded<MapCombo::LockedContent>& content)
{
- auto locked = map.try_lock();
+ auto locked = content.try_lock();
if (!locked.owns_lock()) {
locked.lock();
- locked->d_contended_count++;
+ ++locked->d_contended_count;
}
++locked->d_acquired_count;
return locked;
}
- void preRemoval(MapCombo& map, const NegCacheEntry& entry)
+ void preRemoval(MapCombo::LockedContent& map, const NegCacheEntry& entry)
{
}
};