]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/cachecleaner.hh
wip
[thirdparty/pdns.git] / pdns / cachecleaner.hh
index 732631d00194c1d82b4994e52b18bde3ceacf5c2..9d57ede00981097b133f98b3adcdfba59eeeed82 100644 (file)
@@ -21,6 +21,7 @@
  */
 #pragma once
 
+#include <mutex>
 #include "lock.hh"
 
 // this function can clean any cache that has a getTTD() method on its entries, a preRemoval() method and a 'sequence' index as its second index
@@ -56,7 +57,7 @@ template <typename S, typename C, typename T> void pruneCollection(C& container,
   for(; iter != sidx.end() && tried < lookAt ; ++tried) {
     if(iter->getTTD() < now) {
       container.preRemoval(*iter);
-      sidx.erase(iter++);
+      iter = sidx.erase(iter);
       erased++;
     }
     else
@@ -132,7 +133,7 @@ template <typename S, typename T> uint64_t pruneLockedCollectionsVector(vector<T
     auto& sidx = boost::multi_index::get<S>(mc.d_map);
     uint64_t erased = 0, lookedAt = 0;
     for(auto i = sidx.begin(); i != sidx.end(); lookedAt++) {
-      if(i->ttd < now) {
+      if (i->getTTD() < now) {
         i = sidx.erase(i);
         erased++;
       } else {
@@ -151,6 +152,69 @@ template <typename S, typename T> uint64_t pruneLockedCollectionsVector(vector<T
   return totErased;
 }
 
+template <typename S, typename C, typename T> uint64_t pruneMutexCollectionsVector(C& container, vector<T>& maps, uint64_t maxCached, uint64_t cacheSize)
+{
+  time_t now = time(nullptr);
+  uint64_t totErased = 0;
+  uint64_t toTrim = 0;
+  uint64_t lookAt = 0;
+
+  // two modes - if toTrim is 0, just look through 10%  of the cache and nuke everything that is expired
+  // otherwise, scan first 5*toTrim records, and stop once we've nuked enough
+  if (cacheSize > maxCached) {
+    toTrim = cacheSize - maxCached;
+    lookAt = 5 * toTrim;
+  } else {
+    lookAt = cacheSize / 10;
+  }
+  
+  for (auto& mc : maps) {
+    const std::lock_guard<std::mutex> lock(mc.mutex);
+    auto& sidx = boost::multi_index::get<S>(mc.d_map);
+    uint64_t erased = 0, lookedAt = 0;
+    for (auto i = sidx.begin(); i != sidx.end(); lookedAt++) {
+      if (i->getTTD() < now) {
+        container.preRemoval(*i);
+        i = sidx.erase(i);
+        erased++;
+      } else {
+        ++i;
+      }
+
+      if (toTrim && erased >= toTrim / maps.size())
+        break;
+
+      if (lookedAt > lookAt / maps.size())
+        break;
+    }
+    totErased += erased;
+    if (toTrim && totErased >= toTrim)
+      break;
+  }
+
+  if (totErased >= toTrim) { // done
+    return totErased;
+  }
+
+  toTrim -= totErased;
+
+  // XXXX kinda desperate method
+  while (toTrim > 0) {
+    for (auto& mc : maps) {
+      const std::lock_guard<std::mutex> lock(mc.mutex);
+      auto& sidx = boost::multi_index::get<S>(mc.d_map);
+      auto i = sidx.begin();
+      container.preRemoval(*i);
+      i = sidx.erase(i);
+      totErased++;
+      toTrim--;
+      if (toTrim == 0)
+        break;
+    }
+  }
+  return totErased;
+}
+
 template <typename T> uint64_t purgeLockedCollectionsVector(vector<T>& maps)
 {
   uint64_t delcount=0;