Branch data Line data Source code
1 : : // Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
2 : : //
3 : : // Permission to use, copy, modify, and/or distribute this software for any
4 : : // purpose with or without fee is hereby granted, provided that the above
5 : : // copyright notice and this permission notice appear in all copies.
6 : : //
7 : : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
8 : : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9 : : // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
10 : : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11 : : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
12 : : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13 : : // PERFORMANCE OF THIS SOFTWARE.
14 : :
15 : : #ifndef __RESOLVER_CACHE_H
16 : : #define __RESOLVER_CACHE_H
17 : :
18 : : #include <map>
19 : : #include <string>
20 : : #include <boost/shared_ptr.hpp>
21 : : #include <dns/rrclass.h>
22 : : #include <dns/message.h>
23 : : #include <exceptions/exceptions.h>
24 : : #include "message_cache.h"
25 : : #include "rrset_cache.h"
26 : : #include "local_zone_data.h"
27 : :
28 : : namespace isc {
29 : : namespace cache {
30 : : class RRsetCache;
31 : :
32 : : //TODO a better proper default cache size
33 : : #define MESSAGE_CACHE_DEFAULT_SIZE 10000
34 : : #define RRSET_CACHE_DEFAULT_SIZE 20000
35 : : #define NEGATIVE_RRSET_CACHE_DEFAULT_SIZE 10000
36 : :
37 : : /// \brief Cache Size Information.
38 : : ///
39 : : /// Used to initialize the size of class-specific rrset/message cache.
40 : 0 : struct CacheSizeInfo
41 : : {
42 : : public:
43 : : /// \brief Constructor
44 : : ///
45 : : /// \param cls The RRClass code
46 : : /// \param msg_cache_size The size for the message cache
47 : : /// \param rst_cache_size The size for the RRset cache
48 : : CacheSizeInfo(const isc::dns::RRClass& cls,
49 : : uint32_t msg_cache_size,
50 : : uint32_t rst_cache_size):
51 : : cclass(cls),
52 : : message_cache_size(msg_cache_size),
53 : 13 : rrset_cache_size(rst_cache_size)
54 : : {}
55 : :
56 : : isc::dns::RRClass cclass; // class of the cache.
57 : : uint32_t message_cache_size; // the size for message cache.
58 : : uint32_t rrset_cache_size; // The size for rrset cache.
59 : : };
60 : :
61 : : /// \brief Message has no question section.
62 : : ///
63 : : /// Thrown if the given message has no question section when looking up
64 : : /// the message in cache.
65 : 1 : class MessageNoQuestionSection : public isc::Exception {
66 : : public:
67 : : MessageNoQuestionSection(const char*file, size_t line, const char*what) :
68 [ + - ]: 1 : isc::Exception(file, line, what)
69 : : {}
70 : : };
71 : :
72 : : /// \brief Class-specific Resolver Cache.
73 : : ///
74 : : /// The object of ResolverCache represents the cache of the resolver. It may hold
75 : : /// a list of message/rrset cache which are in different class.
76 : : ///
77 : : /// \note Public interaction with the cache should be through ResolverCache,
78 : : /// not directly with this one. (TODO: make this private/hidden/local to the .cc?)
79 : : ///
80 : : /// \todo The resolver cache class should provide the interfaces for
81 : : /// loading, dumping and resizing.
82 : 144 : class ResolverClassCache {
83 : : public:
84 : : /// \brief Default Constructor.
85 : : ///
86 : : /// Only support for class "IN", and message cache size is
87 : : /// MESSAGE_CACHE_DEFAULT_SIZE, rrset cache size is
88 : : /// RRSET_CACHE_DEFAULT_SIZE
89 : : ResolverClassCache(const isc::dns::RRClass& cache_class);
90 : :
91 : : /// \brief Construct Function.
92 : : /// \param cache_info Cache size information for each message/rrsets of
93 : : /// different classes.
94 : : ResolverClassCache(const CacheSizeInfo& cache_info);
95 : :
96 : : /// \name Lookup Interfaces
97 : : //@{
98 : : /// \brief Look up message in cache.
99 : : ///
100 : : /// \param qname The query name to look up
101 : : /// \param qtype The query type to look up
102 : : /// \param response the query message (must be in RENDER mode)
103 : : /// which has question section already (exception
104 : : /// MessageNoQeustionSection will be thrown if it has
105 : : /// no question section). If the message can be found
106 : : /// in cache, rrsets for the message will be added to
107 : : /// different sections(answer, authority, additional).
108 : : /// \return return true if the message can be found, or else,
109 : : /// return false.
110 : : bool lookup(const isc::dns::Name& qname,
111 : : const isc::dns::RRType& qtype,
112 : : isc::dns::Message& response) const;
113 : :
114 : : /// \brief Look up rrset in cache.
115 : : ///
116 : : /// \param qname The query name to look up
117 : : /// \param qtype The query type to look up
118 : : ///
119 : : /// \return return the shared_ptr of rrset if it can be found,
120 : : /// or else, return NULL. When looking up, local zone
121 : : /// data will be searched first, if not found, then
122 : : /// search in rrset cache.
123 : : ///
124 : : /// \overload
125 : : ///
126 : : isc::dns::RRsetPtr lookup(const isc::dns::Name& qname,
127 : : const isc::dns::RRType& qtype) const;
128 : :
129 : : /// \brief Update the message in the cache with the new one.
130 : : ///
131 : : /// \param msg The message to update
132 : : ///
133 : : /// \return return true if the message is updated successfully,
134 : : /// or else, return false.
135 : : ///
136 : : /// \note the function doesn't do any message validation check,
137 : : /// the user should make sure the message is valid, and of
138 : : /// the right class
139 : : /// TODO: Share the NXDOMAIN info between different type queries
140 : : /// current implementation can only cache for the type that
141 : : /// user quired, for example, if user query A record of
142 : : /// a.example. and the server replied with NXDOMAIN, this
143 : : /// should be cached for all the types queries of a.example.
144 : : bool update(const isc::dns::Message& msg);
145 : :
146 : : /// \brief Update the rrset in the cache with the new one.
147 : : ///
148 : : /// local zone data and rrset cache will be updated together.
149 : : /// If the rrset doesn't exist in both of them, then the rrset
150 : : /// will be added into both of them.
151 : : ///
152 : : /// \param rrset_ptr The RRset to update
153 : : ///
154 : : /// \return return false, if the class of the parameter rrset is
155 : : /// allowed to be cached.
156 : : ///
157 : : /// \overload
158 : : ///
159 : : /// \note The class of the RRset must have been checked. It is not
160 : : /// here.
161 : : bool update(const isc::dns::ConstRRsetPtr& rrset_ptr);
162 : :
163 : : /// \brief Get the RRClass this cache is for
164 : : ///
165 : : /// \return The RRClass of this cache
166 : : const isc::dns::RRClass& getClass() const;
167 : :
168 : : private:
169 : : /// \brief Update rrset cache.
170 : : ///
171 : : /// \param rrset_ptr The rrset to update with
172 : : /// \param rrset_cache_ptr the rrset cache to update
173 : : ///
174 : : /// \return return true if the rrset is updated in the rrset cache,
175 : : /// or else return false if failed.
176 : : /// \param rrset_cache_ptr The rrset cache need to be updated.
177 : : bool updateRRsetCache(const isc::dns::ConstRRsetPtr& rrset_ptr,
178 : : RRsetCachePtr rrset_cache_ptr);
179 : :
180 : : /// \brief Class this cache is for.
181 : : const isc::dns::RRClass cache_class_;
182 : :
183 : : /// \brief map of message caches for configured classes(each message
184 : : /// cache is class-specific)
185 : : MessageCachePtr messages_cache_;
186 : :
187 : : /// \name rrset caches
188 : : //@{
189 : : /// \brief Local Zone data cache
190 : : /// Cache for rrsets in local zones, rrsets
191 : : /// in it never expire.
192 : : LocalZoneDataPtr local_zone_data_;
193 : : //@}
194 : :
195 : : /// \brief cache the rrsets parsed from the received message.
196 : : RRsetCachePtr rrsets_cache_;
197 : :
198 : : /// \brief cache the SOA rrset parsed from the negative response message.
199 : : RRsetCachePtr negative_soa_cache_;
200 : : };
201 : :
202 : : class ResolverCache {
203 : : public:
204 : : /// \brief Default Constructor.
205 : : ///
206 : : /// Right now, only support for class "IN", and message cache size is
207 : : /// MESSAGE_CACHE_DEFAULT_SIZE, rrset cache size is
208 : : /// RRSET_CACHE_DEFAULT_SIZE
209 : : ResolverCache();
210 : :
211 : : /// \brief Construct Function.
212 : : /// \param caches_size cache size information for each
213 : : /// messages/rrsets of different classes.
214 : : ResolverCache(std::vector<CacheSizeInfo> caches_size);
215 : :
216 : : /// \brief Destructor
217 : : ~ResolverCache();
218 : :
219 : : /// \name Lookup Interfaces
220 : : //@{
221 : : /// \brief Look up message in cache.
222 : : ///
223 : : /// \param qname The query name to look up
224 : : /// \param qtype The query type to look up
225 : : /// \param qclass The query class to look up
226 : : /// \param response the query message (must be in RENDER mode)
227 : : /// which has question section already (exception
228 : : /// MessageNoQeustionSection will be thrown if it has
229 : : /// no question section). If the message can be found
230 : : /// in cache, rrsets for the message will be added to
231 : : /// different sections(answer, authority, additional).
232 : : /// \return return true if the message can be found, or else,
233 : : /// return false.
234 : : bool lookup(const isc::dns::Name& qname,
235 : : const isc::dns::RRType& qtype,
236 : : const isc::dns::RRClass& qclass,
237 : : isc::dns::Message& response) const;
238 : :
239 : : /// \brief Look up rrset in cache.
240 : : ///
241 : : /// \param qname The query name to look up
242 : : /// \param qtype The query type to look up
243 : : /// \param qclass The query class to look up
244 : : ///
245 : : /// \return return the shared_ptr of rrset if it can be found,
246 : : /// or else, return NULL. When looking up, local zone
247 : : /// data will be searched first, if not found, then
248 : : /// search in rrset cache.
249 : : ///
250 : : /// \overload
251 : : ///
252 : : isc::dns::RRsetPtr lookup(const isc::dns::Name& qname,
253 : : const isc::dns::RRType& qtype,
254 : : const isc::dns::RRClass& qclass) const;
255 : :
256 : : /// \brief Look up closest enclosing NS rrset in cache.
257 : : ///
258 : : /// \param qname The query name to look up
259 : : /// \param qclass The query class to look up
260 : : ///
261 : : /// \return return the shared_ptr of closest enclosing ns rrset
262 : : /// if it can be found in cache, or else return NULL.
263 : : ///
264 : : /// Currently the implementation is: search exact ns rrset
265 : : /// label by lable, If the ns rrset can't be found, remove the last
266 : : /// label, then search again. The efficiency may be very low when
267 : : /// the name is very long but it's closest rrset's name is very short.
268 : : ///
269 : : /// If a good perfermance is needed when looking up the closest
270 : : /// enclosing ns rrset, cache structure(HashTable) should be
271 : : /// redesigned. By using HashTable, it can only garantee the
272 : : /// performance for looking up exact rrset.
273 : : ///
274 : : /// So here there is another question, which rrset looking up interface
275 : : /// is used frequently? Exact or closest enclosing ns looking up.
276 : : isc::dns::RRsetPtr lookupDeepestNS(const isc::dns::Name& qname,
277 : : const isc::dns::RRClass& qclass) const;
278 : : //@}
279 : :
280 : : /// \brief Update the message in the cache with the new one.
281 : : ///
282 : : /// \param msg The message to update
283 : : ///
284 : : /// \return return true if the message is updated successfully,
285 : : /// or else, return false.
286 : : ///
287 : : /// \note the function doesn't do any message validation check,
288 : : /// the user should make sure the message is valid.
289 : : bool update(const isc::dns::Message& msg);
290 : :
291 : : /// \brief Update the rrset in the cache with the new one.
292 : : ///
293 : : /// local zone data and rrset cache will be updated together.
294 : : /// If the rrset doesn't exist in both of them, then the rrset
295 : : /// will be added into both of them.
296 : : ///
297 : : /// \param rrset_ptr The RRset to update
298 : : ///
299 : : /// \return return false, if the class of the parameter rrset is
300 : : /// allowed to be cached.
301 : : ///
302 : : /// \overload
303 : : ///
304 : : bool update(const isc::dns::ConstRRsetPtr& rrset_ptr);
305 : :
306 : : private:
307 : : /// \brief Returns the class-specific subcache
308 : : ///
309 : : /// \param cache_class the class to get the subcache for
310 : : /// \return The subcache, or NULL if there is no cache for this class
311 : : ResolverClassCache* getClassCache(const isc::dns::RRClass& cache_class) const;
312 : :
313 : : /// The class-specific caches.
314 : : /// TODO: I think we can optimize for IN, and always have that
315 : : /// one directly available, use the vector for the rest?
316 : : std::vector<ResolverClassCache*> class_caches_;
317 : : };
318 : :
319 : : } // namespace cache
320 : : } // namespace isc
321 : :
322 : : #endif // __RESOLVER_CACHE_H
323 : :
|