CacheEntry val;
val.created=time(0);
val.ttd=val.created+ttl;
- val.qname=qname;
+ val.qname=pcReverse(qname);
val.qtype=qtype.getCode();
val.value=value;
val.ctype=cet;
WriteLock l(&d_mut);
int delcount=0;
- /* ok, the suffix delete plan. We want to be able to delete everything that
- 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!, 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'
-
- 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);
+ string prefix(match);
+ prefix.resize(prefix.size()-1);
+
+ string zone = pcReverse(prefix);
- cmap_t::const_iterator iter = d_map.lower_bound(tie(suffix));
+ cmap_t::const_iterator iter = d_map.lower_bound(tie(zone));
cmap_t::const_iterator start=iter;
- string dotsuffix = "."+suffix;
for(; iter != d_map.end(); ++iter) {
- if(!pdns_iequals(iter->qname, suffix) && !iends_with(iter->qname, dotsuffix)) {
- // cerr<<"Stopping!"<<endl;
+ if(!iter->qname.compare(0, zone.size(), zone)) {
break;
}
delcount++;
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));
+ string qname = pcReverse(match);
+
+ delcount=d_map.count(tie(qname));
+ pair<cmap_t::iterator, cmap_t::iterator> range = d_map.equal_range(tie(qname));
d_map.erase(range.first, range.second);
}
*d_statnumentries=d_map.size();
{
uint16_t qt = qtype.getCode();
//cerr<<"Lookup for maxReplyLen: "<<maxReplyLen<<endl;
- cmap_t::const_iterator i=d_map.find(tie(qname, qt, cet, zoneID, meritsRecursion, maxReplyLen, dnssecOK, hasEDNS, *age));
+ string pcqname = pcReverse(qname);
+ cmap_t::const_iterator i=d_map.find(tie(pcqname, qt, cet, zoneID, meritsRecursion, maxReplyLen, dnssecOK, hasEDNS, *age));
time_t now=time(0);
bool ret=(i!=d_map.end() && i->ttd > now);
if(ret) {
return ret;
}
+
+string PacketCache::pcReverse(const string &content)
+{
+ string tmp = string(content.rbegin(), content.rend());
+ return toLower(boost::replace_all_copy(tmp, ".", " "))+" ";
+}
+
+
map<char,int> PacketCache::getCounts()
{
ReadLock l(&d_mut);
first marks and then sweeps, a second lock is present to prevent simultaneous inserts and deletes.
*/
-struct CIBackwardsStringCompare: public std::binary_function<string, string, bool>
-{
- bool operator()(const string& str_a, const string& str_b) const
- {
- string::const_reverse_iterator ra, rb;
- char a=0, b=0;
- for(ra = str_a.rbegin(), rb = str_b.rbegin();
- ra < str_a.rend() && rb < str_b.rend() && (a=dns_tolower(*ra)) == (b=dns_tolower(*rb));
- ra++, rb++);
-
- if (ra < str_a.rend() && rb==str_b.rend()) { a=*(ra++); b=0; return false; } // we are at the beginning of b -> b smaller
- if (rb < str_b.rend() && ra==str_a.rend()) { b=*(rb++); a=0; return true; } // we are at the beginning of a -> a smaller
- // if BOTH are at their ends, a and b will be equal, and we should return false, which we will
- return a < b;
- }
-};
-
-
class PacketCache : public boost::noncopyable
{
public:
private:
bool getEntryLocked(const string &content, const QType& qtype, CacheEntryType cet, string& entry, int zoneID=-1,
bool meritsRecursion=false, unsigned int maxReplyLen=512, bool dnssecOk=false, bool hasEDNS=false, unsigned int *age=0);
+ string pcReverse(const string &content);
struct CacheEntry
{
CacheEntry() { qtype = ctype = 0; zoneID = -1; meritsRecursion=false; dnssecOk=false; hasEDNS=false;}
member<CacheEntry,bool, &CacheEntry::dnssecOk>,
member<CacheEntry,bool, &CacheEntry::hasEDNS>
>,
- composite_key_compare<CIBackwardsStringCompare, std::less<uint16_t>, std::less<uint16_t>, std::less<int>, std::less<bool>,
+ composite_key_compare<std::less<string>, std::less<uint16_t>, std::less<uint16_t>, std::less<int>, std::less<bool>,
std::less<unsigned int>, std::less<bool>, std::less<bool> >
>,
sequenced<>