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)
#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;
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;
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";
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
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();
}
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);
+ }
}
}
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;
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)
{
#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
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:
// 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
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;