]> granicus.if.org Git - pdns/commitdiff
move cache to composite_keys, doing away the nasty string-concatenation based keys
authorBert Hubert <bert.hubert@netherlabs.nl>
Sat, 25 Mar 2006 21:01:35 +0000 (21:01 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Sat, 25 Mar 2006 21:01:35 +0000 (21:01 +0000)
implement cache wiping via rec_control
implement cache dumping

git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@623 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/dnsrecords.cc
pdns/rec_channel_rec.cc
pdns/recursor_cache.cc
pdns/recursor_cache.hh

index 4528b30e78c953c289ea8ef7cf1c4fc3c6018196..2f9021ceccf46e3e7ec587692075fc29ece44048 100644 (file)
 
 boilerplate_conv(A, ns_t_a, conv.xfrIP(d_ip));
 
+uint32_t ARecordContent::getIP() const
+{
+  return d_ip;
+}
+
 void ARecordContent::doRecordCheck(const DNSRecord& dr)
 {  
   if(dr.d_clen!=4)
index 88f6c550bf9d3e28452dec7e6344e0160f8cc7de..a23c409dcd1be6657f1a2c7116f02953d2fb1649 100644 (file)
@@ -8,6 +8,9 @@
 #include <boost/function.hpp>
 #include <boost/optional.hpp>
 #include <boost/tuple/tuple.hpp>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 
 using namespace std;
 using namespace boost;
@@ -61,6 +64,34 @@ string doGet(T begin, T end)
   return ret;
 }
 
+template<typename T>
+string doDumpCache(T begin, T end)
+{
+  T i=begin;
+  string fname;
+
+  if(i!=end) 
+    fname=*i;
+
+  int fd=open(fname.c_str(), O_CREAT | O_EXCL | O_WRONLY | O_LARGEFILE, 0660);
+  if(fd < 0) 
+    return "Error opening dump file for writing: "+string(strerror(errno))+"\n";
+
+  RC.doDumpAndClose(fd); 
+
+  return "done\n";
+}
+
+template<typename T>
+string doWipeCache(T begin, T end)
+{
+  for(T i=begin; i != end; ++i)
+    RC.doWipeCache(*i);
+
+  return "done\n";
+}
+
+
 uint32_t getQueryRate()
 {
   struct timeval now;
@@ -116,14 +147,20 @@ string RecursorControlParser::getAnswer(const string& question)
   if(words.empty())
     return "invalid command";
 
-  string& cmd=words[0];
+  string cmd=toLower(words[0]);
   vector<string>::const_iterator begin=words.begin()+1, end=words.end();
 
-  if(words[0]=="GET") 
+  if(words[0]=="get") 
     return doGet(begin, end);
 
-  if(words[0]=="QUIT") 
+  if(words[0]=="quit") 
     exit(1);
+
+  if(words[0]=="dump-cache") 
+    return doDumpCache(begin, end);
+
+  if(words[0]=="wipe-cache") 
+    return doWipeCache(begin, end);
   
   return "Unknown command '"+cmd+"'\n";
 
index 34ea25b94fe5b83fb65d13700657dea1daa13da5..7483e10c6cc4a76f8941b7f1be514c69358931c1 100644 (file)
@@ -8,6 +8,7 @@ using namespace std;
 using namespace boost;
 
 #include "config.h"
+
 #ifdef GCC_SKIP_LOCKING
 #include <bits/atomicity.h>
 // This code is ugly but does speedup the recursor tremendously on multi-processor systems, and even has a large effect (20, 30%) on uniprocessor 
@@ -66,7 +67,7 @@ unsigned int MemRecursorCache::bytes()
   unsigned int ret=0;
 
   for(cache_t::const_iterator i=d_cache.begin(); i!=d_cache.end(); ++i) {
-    ret+=i->d_name.length();
+    ret+=i->d_qname.length();
     for(vector<StoredRecord>::const_iterator j=i->d_records.begin(); j!= i->d_records.end(); ++j)
       ret+=j->size();
   }
@@ -77,18 +78,21 @@ unsigned int MemRecursorCache::bytes()
 int MemRecursorCache::get(time_t now, const string &qname, const QType& qt, set<DNSResourceRecord>* res)
 {
   unsigned int ttd=0;
-  uint16_t code=qt.getCode();
-  string key(toLowerCanonic(qname)); key.append(1,'|'); key.append((char*)&code, ((char*)&code)+2);
+  tuple<string, uint16_t> key=make_tuple(toLowerCanonic(qname), qt.getCode());
+
   cache_t::const_iterator j=d_cache.find(key);
+
   //  cerr<<"looking up "<< toLowerCanonic(qname)+"|"+qt.getName() << " ("<<key<<", "<<code<<")\n";
   if(res)
     res->clear();
 
-  if(j!=d_cache.end() && j->d_records.begin()->d_ttd>(unsigned int)now) {
+  if(j!=d_cache.end()) { 
     if(res) {
       for(vector<StoredRecord>::const_iterator k=j->d_records.begin(); k != j->d_records.end(); ++k) {
-       DNSResourceRecord rr=String2DNSRR(qname, qt,  k->d_string, ttd=k->d_ttd); 
-       res->insert(rr);
+       if(k->d_ttd > (uint32_t) now) {
+         DNSResourceRecord rr=String2DNSRR(qname, qt,  k->d_string, ttd=k->d_ttd); 
+         res->insert(rr);
+       }
       }
     }
 
@@ -104,8 +108,7 @@ int MemRecursorCache::get(time_t now, const string &qname, const QType& qt, set<
    touched, but only given a new ttd */
 void MemRecursorCache::replace(const string &qname, const QType& qt,  const set<DNSResourceRecord>& content)
 {
-  uint16_t code=qt.getCode();
-  string key(toLowerCanonic(qname)); key.append(1,'|'); key.append((char*)&code, ((char*)&code)+2);
+  tuple<string, uint16_t> key=make_tuple(toLowerCanonic(qname), qt.getCode());
   cache_t::iterator stored=d_cache.find(key);
   
   bool isNew=false;
@@ -148,7 +151,28 @@ void MemRecursorCache::replace(const string &qname, const QType& qt,  const set<
   d_cache.replace(stored, ce);
 }
 
+void MemRecursorCache::doWipeCache(const string& name)
+{
+  pair<cache_t::iterator, cache_t::iterator> range=d_cache.equal_range(tie(name));
+  d_cache.erase(range.first, range.second);
+}
 
+void MemRecursorCache::doDumpAndClose(int fd)
+{
+  FILE* fp=fdopen(fd, "w");
+  if(!fp) {
+    close(fd);
+    return;
+  }
+  time_t now=time(0);
+  for(cache_t::const_iterator i=d_cache.begin(); i!=d_cache.end(); ++i) {
+    for(vector<StoredRecord>::const_iterator j=i->d_records.begin(); j != i->d_records.end(); ++j) {
+      DNSResourceRecord rr=String2DNSRR(i->d_qname, QType(i->d_qtype), j->d_string, j->d_ttd - now);
+      fprintf(fp, "%s. %d IN %s %s\n", rr.qname.c_str(), rr.ttl, rr.qtype.getName().c_str(), rr.content.c_str());
+    }
+  }
+  fclose(fp);
+}
 
 void MemRecursorCache::doPrune(void)
 {
index 0095aded3e680bd50075250085e897d1cd0a8d4e..4d63fef9ff522e86c7a32ffe3cd6ab26e9a09b6e 100644 (file)
@@ -9,7 +9,7 @@
 #undef L
 #include <boost/multi_index_container.hpp>
 #include <boost/multi_index/ordered_index.hpp>
-
+#include <boost/tuple/tuple_comparison.hpp>
 #include <boost/multi_index/key_extractors.hpp>
 #include <boost/version.hpp>
 #if BOOST_VERSION >= 103300
@@ -29,6 +29,8 @@ public:
   int get(time_t, const string &qname, const QType& qt, set<DNSResourceRecord>* res);
   void replace(const string &qname, const QType& qt,  const set<DNSResourceRecord>& content);
   void doPrune(void);
+  void doDumpAndClose(int fd);
+  void doWipeCache(const string& name);
   uint64_t cacheHits, cacheMisses;
 
 private:
@@ -66,10 +68,13 @@ private:
   //   typedef __gnu_cxx::hash_map<string, vector<StoredRecord> > cache_t;
   struct CacheEntry
   {
-    CacheEntry(){}
-    CacheEntry(const string& name, const vector<StoredRecord>& records) : d_name(name), d_records(records)
+    string d_qname;
+    uint16_t d_qtype;
+
+    CacheEntry(const tuple<string, uint16_t>& key, const vector<StoredRecord>& records) : 
+      d_qname(key.get<0>()), d_qtype(key.get<1>()), d_records(records)
     {}
-    string d_name;
+
     typedef vector<StoredRecord> records_t;
     records_t d_records;
     uint32_t getTTD() const
@@ -88,11 +93,13 @@ private:
   typedef multi_index_container<
     CacheEntry,
     indexed_by <
-#if BOOST_VERSION >= 103300
-                hashed_unique<member<CacheEntry,string,&CacheEntry::d_name> >,
-#else
-                ordered_unique<member<CacheEntry,string,&CacheEntry::d_name> >,
-#endif
+                ordered_unique<
+                      composite_key< 
+                        CacheEntry,
+                        member<CacheEntry,string,&CacheEntry::d_qname>,
+                        member<CacheEntry,uint16_t,&CacheEntry::d_qtype>
+                      >
+                >,
                 ordered_non_unique<const_mem_fun<CacheEntry,uint32_t,&CacheEntry::getTTD> >
                >
   > cache_t;