| 1 | /* |
|---|
| 2 | PowerDNS Versatile Database Driven Nameserver |
|---|
| 3 | Copyright (C) 2002 - 2008 PowerDNS.COM BV |
|---|
| 4 | |
|---|
| 5 | This program is free software; you can redistribute it and/or modify |
|---|
| 6 | it under the terms of the GNU General Public License version 2 |
|---|
| 7 | as published by the Free Software Foundation |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | This program is distributed in the hope that it will be useful, |
|---|
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 13 | GNU General Public License for more details. |
|---|
| 14 | |
|---|
| 15 | You should have received a copy of the GNU General Public License |
|---|
| 16 | along with this program; if not, write to the Free Software |
|---|
| 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|---|
| 18 | */ |
|---|
| 19 | #ifndef PACKETCACHE_HH |
|---|
| 20 | #define PACKETCACHE_HH |
|---|
| 21 | |
|---|
| 22 | #include <string> |
|---|
| 23 | #include <utility> |
|---|
| 24 | #include <map> |
|---|
| 25 | #include <map> |
|---|
| 26 | #include "dns.hh" |
|---|
| 27 | #include <boost/version.hpp> |
|---|
| 28 | using namespace std; |
|---|
| 29 | using namespace ::boost::multi_index; |
|---|
| 30 | |
|---|
| 31 | using namespace boost; |
|---|
| 32 | #include "dnspacket.hh" |
|---|
| 33 | #include "lock.hh" |
|---|
| 34 | #include "statbag.hh" |
|---|
| 35 | |
|---|
| 36 | /** This class performs 'whole packet caching'. Feed it a question packet and it will |
|---|
| 37 | try to find an answer. If you have an answer, insert it to have it cached for later use. |
|---|
| 38 | Take care not to replace existing cache entries. While this works, it is wasteful. Only |
|---|
| 39 | insert packets that where not found by get() |
|---|
| 40 | |
|---|
| 41 | Locking! |
|---|
| 42 | |
|---|
| 43 | The cache itself is protected by a read/write lock. Because deleting is a two step process, which |
|---|
| 44 | first marks and then sweeps, a second lock is present to prevent simultaneous inserts and deletes. |
|---|
| 45 | */ |
|---|
| 46 | |
|---|
| 47 | struct CIBackwardsStringCompare: public binary_function<string, string, bool> |
|---|
| 48 | { |
|---|
| 49 | bool operator()(const string& str_a, const string& str_b) const |
|---|
| 50 | { |
|---|
| 51 | string::const_reverse_iterator ra, rb; |
|---|
| 52 | char a=0, b=0; |
|---|
| 53 | for(ra = str_a.rbegin(), rb = str_b.rbegin(); |
|---|
| 54 | ra < str_a.rend() && rb < str_b.rend() && (a=dns_tolower(*ra)) == (b=dns_tolower(*rb)); |
|---|
| 55 | ra++, rb++); |
|---|
| 56 | |
|---|
| 57 | if (ra < str_a.rend() && rb==str_b.rend()) { a=*(ra++); b=0; } |
|---|
| 58 | if (rb < str_b.rend() && ra==str_a.rend()) { b=*(rb++); a=0; } |
|---|
| 59 | |
|---|
| 60 | return a < b; |
|---|
| 61 | } |
|---|
| 62 | }; |
|---|
| 63 | |
|---|
| 64 | |
|---|
| 65 | class PacketCache |
|---|
| 66 | { |
|---|
| 67 | public: |
|---|
| 68 | PacketCache(); |
|---|
| 69 | enum CacheEntryType { PACKETCACHE, QUERYCACHE, NEGCACHE}; |
|---|
| 70 | |
|---|
| 71 | void insert(DNSPacket *q, DNSPacket *r); //!< We copy the contents of *p into our cache. Do not needlessly call this to insert questions already in the cache as it wastes resources |
|---|
| 72 | |
|---|
| 73 | void insert(const string &qname, const QType& qtype, CacheEntryType cet, const string& value, unsigned int ttl, int zoneID=-1, bool meritsRecursion=false); |
|---|
| 74 | |
|---|
| 75 | int get(DNSPacket *p, DNSPacket *q); //!< We return a dynamically allocated copy out of our cache. You need to delete it. You also need to spoof in the right ID with the DNSPacket.spoofID() method. |
|---|
| 76 | bool getEntry(const string &content, const QType& qtype, CacheEntryType cet, string& entry, int zoneID=-1, bool meritsRecursion=false); |
|---|
| 77 | |
|---|
| 78 | int size(); //!< number of entries in the cache |
|---|
| 79 | void cleanup(); //!< force the cache to preen itself from expired packets |
|---|
| 80 | int purge(const vector<string>&matches= vector<string>()); |
|---|
| 81 | |
|---|
| 82 | map<char,int> getCounts(); |
|---|
| 83 | private: |
|---|
| 84 | struct CacheEntry |
|---|
| 85 | { |
|---|
| 86 | CacheEntry() { qtype = ctype = 0; zoneID = -1; meritsRecursion=false;} |
|---|
| 87 | |
|---|
| 88 | string qname; |
|---|
| 89 | uint16_t qtype; |
|---|
| 90 | uint16_t ctype; |
|---|
| 91 | int zoneID; |
|---|
| 92 | time_t ttd; |
|---|
| 93 | bool meritsRecursion; |
|---|
| 94 | string value; |
|---|
| 95 | }; |
|---|
| 96 | |
|---|
| 97 | void getTTLS(); |
|---|
| 98 | |
|---|
| 99 | typedef multi_index_container< |
|---|
| 100 | CacheEntry, |
|---|
| 101 | indexed_by < |
|---|
| 102 | ordered_unique< |
|---|
| 103 | composite_key< |
|---|
| 104 | CacheEntry, |
|---|
| 105 | member<CacheEntry,string,&CacheEntry::qname>, |
|---|
| 106 | member<CacheEntry,uint16_t,&CacheEntry::qtype>, |
|---|
| 107 | member<CacheEntry,uint16_t, &CacheEntry::ctype>, |
|---|
| 108 | member<CacheEntry,int, &CacheEntry::zoneID>, |
|---|
| 109 | member<CacheEntry,bool, &CacheEntry::meritsRecursion> |
|---|
| 110 | >, |
|---|
| 111 | composite_key_compare<CIBackwardsStringCompare, std::less<uint16_t>, std::less<uint16_t>, std::less<int>, std::less<bool> > |
|---|
| 112 | >, |
|---|
| 113 | sequenced<> |
|---|
| 114 | > |
|---|
| 115 | > cmap_t; |
|---|
| 116 | |
|---|
| 117 | |
|---|
| 118 | cmap_t d_map; |
|---|
| 119 | |
|---|
| 120 | pthread_rwlock_t d_mut; |
|---|
| 121 | |
|---|
| 122 | int d_hit; |
|---|
| 123 | int d_miss; |
|---|
| 124 | int d_ttl; |
|---|
| 125 | int d_recursivettl; |
|---|
| 126 | bool d_doRecursion; |
|---|
| 127 | int *statnumhit; |
|---|
| 128 | int *statnummiss; |
|---|
| 129 | int *statnumentries; |
|---|
| 130 | }; |
|---|
| 131 | |
|---|
| 132 | |
|---|
| 133 | |
|---|
| 134 | #endif /* PACKETCACHE_HH */ |
|---|
| 135 | |
|---|