]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
implement fast wiping of "ds9a.nl" and "blah.ds9a.nl" using inverted ordering
authorBert Hubert <bert.hubert@netherlabs.nl>
Sun, 22 Jun 2008 22:17:20 +0000 (22:17 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Sun, 22 Jun 2008 22:17:20 +0000 (22:17 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@1220 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/packetcache.cc
pdns/packetcache.hh

index 9ff3be61d069efe73fe1d8597e489375faaeb623..337109fc3ec3ec6fc6dda0bde04036a1dc128a29 100644 (file)
@@ -21,6 +21,7 @@
 #include "arguments.hh"
 #include "statbag.hh"
 #include <map>
+#include <boost/algorithm/string.hpp>
 
 extern StatBag S;
 
@@ -129,7 +130,7 @@ void PacketCache::insert(const string &qname, const QType& qtype, CacheEntryType
   if(!ttl)
     return;
   
-  //  cerr<<"Inserting, cet: "<<(int)cet<<endl;
+  //  cerr<<"Inserting qname '"<<qname<<"', cet: "<<(int)cet<<", value: '"<< (cet ? value : "PACKET") <<"', qtype: "<<qtype.getName()<<endl;
 
   CacheEntry val;
   val.ttd=time(0)+ttl;
@@ -157,7 +158,7 @@ void PacketCache::insert(const string &qname, const QType& qtype, CacheEntryType
 int PacketCache::purge(const string &match)
 {
   WriteLock l(&d_mut);
-  int delcount;
+  int delcount=0;
 
   if(match.empty()) {
     delcount = d_map.size();
@@ -170,13 +171,71 @@ int PacketCache::purge(const string &match)
      pertains 'www.powerdns.com' but we also want to be able to delete everything
      in the powerdns.com zone, so: 'powerdns.com' and '*.powerdns.com'.
 
-     However, we do NOT want to delete 'usepowerdns.com!'
-  */
+     However, we do NOT want to delete 'usepowerdns.com!, nor 'powerdnsiscool.com'
+
+     So, at first shot, store in reverse label order:
+
+     'be.someotherdomain'
+     'com.powerdns'
+     'com.powerdns.images'
+     'com.powerdns.www'
+     'com.powerdnsiscool'
+     'com.usepowerdns.www'
+
+     If we get a request to remove 'everything above powerdns.com', we do a search for 'com.powerdns' which is guaranteed to come first (it is shortest!)
+     Then we delete everything that is either equal to 'com.powerdns' or begins with 'com.powerdns.' This trailing dot saves us 
+     from deleting 'com.powerdnsiscool'.
+
+     We can stop the process once we reach something that doesn't match.
+
+     Ok - fine so far, except it doesn't work! Let's say there *is* no 'com.powerdns' in cache!
+
+     In that case our request doesn't find anything.. now what.
+     lower_bound to the rescue! It finds the place where 'com.powerdns' *would* be.
+     
+     Ok - next step, can we get away with simply reversing the string?
+
+     'moc.sndrewop'
+     'moc.sndrewop.segami'
+     'moc.sndrewop.www'
+     'moc.loocsidnsrewop'
+     'moc.dnsrewopesu.www'
 
-  delcount=d_map.count(tie(match));
-  pair<cmap_t::iterator, cmap_t::iterator> range = d_map.equal_range(tie(match));
-  d_map.erase(range.first, range.second);
+     Ok - next step, can we get away with only reversing the comparison?
 
+     'powerdns.com'
+     'images.powerdns.com'
+     '   www.powerdns.com'
+     'powerdnsiscool.com'
+     'www.userpowerdns.com'
+
+  */
+  if(ends_with(match, "$")) {
+    string suffix(match);
+    suffix.resize(suffix.size()-1);
+
+    //    cerr<<"Begin dump!"<<endl;
+    cmap_t::const_iterator iter = d_map.lower_bound(tie(suffix));
+    cmap_t::const_iterator start=iter;
+    string dotsuffix = "."+suffix;
+
+    for(; iter != d_map.end(); ++iter) {
+      if(!iequals(iter->qname, suffix) && !iends_with(iter->qname, dotsuffix)) {
+       //      cerr<<"Stopping!"<<endl;
+       break;
+      }
+      //      cerr<<"Will erase '"<<iter->qname<<"'\n";
+
+      delcount++;
+    }
+    //    cerr<<"End dump!"<<endl;
+    d_map.erase(start, iter);
+  }
+  else {
+    delcount=d_map.count(tie(match));
+    pair<cmap_t::iterator, cmap_t::iterator> range = d_map.equal_range(tie(match));
+    d_map.erase(range.first, range.second);
+  }
   *statnumentries=d_map.size();
   return delcount;
 }
index d250efb8591a128a4625e4d3d138d06e2bd0ecbf..2a1412cbaed32622f5ca3e7e6eda713ac37e91de 100644 (file)
@@ -49,6 +49,31 @@ using namespace boost;
     first marks and then sweeps, a second lock is present to prevent simultaneous inserts and deletes.
 */
 
+struct CIBackwardsStringCompare: public binary_function<string, string, bool>  
+{
+  bool operator()(const string& a, const string& b) const
+  {
+    const unsigned char *p1 = (const unsigned char *) a.c_str() + a.length();
+    const unsigned char *p2 = (const unsigned char *) b.c_str() + b.length();
+    int result;
+    
+    if (p1 == p2) {
+      return 0;
+    }
+    
+    while ((result = dns_tolower (*p1--) - dns_tolower (*p2--)) == 0)
+      if (p1 == (unsigned char*)a.c_str() || p2 == (unsigned char*) b.c_str())
+       break;
+    
+    if(result==0) { // one of our strings ended, the shortest one is smaller then
+      return a.length() < b.length();
+    }
+
+    return result < 0;
+  }
+};
+
+
 class PacketCache
 {
 public:
@@ -96,7 +121,7 @@ private:
                        member<CacheEntry,int, &CacheEntry::zoneID>,
                        member<CacheEntry,bool, &CacheEntry::meritsRecursion>
                       >,
-                 composite_key_compare<CIStringCompare, std::less<uint16_t>, std::less<uint16_t>, std::less<int>, std::less<bool> >
+                 composite_key_compare<CIBackwardsStringCompare, std::less<uint16_t>, std::less<uint16_t>, std::less<int>, std::less<bool> >
                 >,
                sequenced<>
                >