resolver_cache.h 12 KB

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