]>
Commit | Line | Data |
---|---|---|
bf269e28 RG |
1 | /* |
2 | * This file is part of PowerDNS or dnsdist. | |
3 | * Copyright -- PowerDNS.COM B.V. and its contributors | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of version 2 of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * In addition, for the avoidance of any doubt, permission is granted to | |
10 | * link this program with OpenSSL and to (re)distribute the binaries | |
11 | * produced as the result of such linking. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
21 | */ | |
e8c59f2d | 22 | #pragma once |
bf269e28 RG |
23 | #include <string> |
24 | #include <map> | |
25 | #include "dns.hh" | |
26 | #include <boost/version.hpp> | |
27 | #include "namespaces.hh" | |
28 | using namespace ::boost::multi_index; | |
29 | ||
30 | #include <boost/multi_index/hashed_index.hpp> | |
31 | ||
32 | #include "dns.hh" | |
33 | #include "dnspacket.hh" | |
34 | #include "lock.hh" | |
35 | ||
36 | class AuthQueryCache : public boost::noncopyable | |
37 | { | |
38 | public: | |
39 | AuthQueryCache(size_t mapsCount=1024); | |
40 | ~AuthQueryCache(); | |
41 | ||
42 | void insert(const DNSName &qname, const QType& qtype, const vector<DNSZoneRecord>& content, uint32_t ttl, int zoneID); | |
43 | ||
44 | bool getEntry(const DNSName &qname, const QType& qtype, vector<DNSZoneRecord>& entry, int zoneID); | |
45 | ||
46 | size_t size() { return *d_statnumentries; } //!< number of entries in the cache | |
47 | void cleanup(); //!< force the cache to preen itself from expired querys | |
48 | uint64_t purge(); | |
49 | uint64_t purge(const std::string& match); // could be $ terminated. Is not a dnsname! | |
50 | uint64_t purgeExact(const DNSName& qname); // no wildcard matching here | |
51 | ||
52 | map<char,uint64_t> getCounts(); | |
53 | ||
54 | void setMaxEntries(uint64_t maxEntries) | |
55 | { | |
56 | d_maxEntries = maxEntries; | |
307994e7 RG |
57 | for (auto& shard : d_maps) { |
58 | shard.reserve(maxEntries / d_maps.size()); | |
59 | } | |
bf269e28 RG |
60 | } |
61 | private: | |
62 | ||
63 | struct CacheEntry | |
64 | { | |
65 | DNSName qname; | |
66 | mutable vector<DNSZoneRecord> drs; | |
67 | mutable time_t created{0}; | |
68 | mutable time_t ttd{0}; | |
69 | uint16_t qtype{0}; | |
70 | int zoneID{-1}; | |
71 | }; | |
72 | ||
73 | struct HashTag{}; | |
74 | struct NameTag{}; | |
94306029 | 75 | struct SequencedTag{}; |
bf269e28 RG |
76 | typedef multi_index_container< |
77 | CacheEntry, | |
78 | indexed_by < | |
79 | hashed_unique<tag<HashTag>, composite_key<CacheEntry, | |
80 | member<CacheEntry,DNSName,&CacheEntry::qname>, | |
81 | member<CacheEntry,uint16_t,&CacheEntry::qtype>, | |
82 | member<CacheEntry,int, &CacheEntry::zoneID> > > , | |
83 | ordered_non_unique<tag<NameTag>, member<CacheEntry,DNSName,&CacheEntry::qname>, CanonDNSNameCompare >, | |
d2814f81 RG |
84 | /* Note that this sequence holds 'least recently inserted or replaced', not least recently used. |
85 | Making it a LRU would require taking a write-lock when fetching from the cache, making the RW-lock inefficient compared to a mutex */ | |
94306029 | 86 | sequenced<tag<SequencedTag>> |
bf269e28 RG |
87 | > |
88 | > cmap_t; | |
89 | ||
90 | ||
91 | struct MapCombo | |
92 | { | |
040793d4 OM |
93 | MapCombo() { |
94 | pthread_rwlock_init(&d_mut, nullptr); | |
95 | } | |
96 | ~MapCombo() { | |
97 | pthread_rwlock_destroy(&d_mut); | |
98 | } | |
9c0ad051 OM |
99 | MapCombo(const MapCombo &) = delete; |
100 | MapCombo & operator=(const MapCombo &) = delete; | |
101 | ||
307994e7 RG |
102 | void reserve(size_t numberOfEntries); |
103 | ||
040793d4 | 104 | pthread_rwlock_t d_mut; |
bf269e28 RG |
105 | cmap_t d_map; |
106 | }; | |
107 | ||
108 | vector<MapCombo> d_maps; | |
109 | MapCombo& getMap(const DNSName& qname) | |
110 | { | |
111 | return d_maps[qname.hash() % d_maps.size()]; | |
112 | } | |
113 | ||
114 | bool getEntryLocked(cmap_t& map, const DNSName &content, uint16_t qtype, vector<DNSZoneRecord>& entry, int zoneID, time_t now); | |
115 | void cleanupIfNeeded(); | |
116 | ||
117 | AtomicCounter d_ops{0}; | |
118 | AtomicCounter *d_statnumhit; | |
119 | AtomicCounter *d_statnummiss; | |
120 | AtomicCounter *d_statnumentries; | |
121 | ||
122 | uint64_t d_maxEntries{0}; | |
123 | time_t d_lastclean; // doesn't need to be atomic | |
2010ac95 | 124 | unsigned long d_nextclean{4096}; |
bf269e28 RG |
125 | unsigned int d_cleaninterval{4096}; |
126 | bool d_cleanskipped{false}; | |
127 | ||
128 | static const unsigned int s_mincleaninterval=1000, s_maxcleaninterval=300000; | |
129 | }; |