resolver_cache.h 12 KB

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