resolver_cache.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  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. /// \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. class ResolverClassCache {
  72. public:
  73. /// \brief Default Constructor.
  74. ///
  75. /// Only support for class "IN", and message cache size is
  76. /// MESSAGE_CACHE_DEFAULT_SIZE, rrset cache size is
  77. /// RRSET_CACHE_DEFAULT_SIZE
  78. ResolverClassCache(const isc::dns::RRClass& cache_class);
  79. /// \brief Construct Function.
  80. /// \param caches_size cache size information for each
  81. /// messages/rrsets of different classes.
  82. ResolverClassCache(CacheSizeInfo cache_info);
  83. /// \name Lookup Interfaces
  84. //@{
  85. /// \brief Look up message in cache.
  86. ///
  87. /// \param qname The query name to look up
  88. /// \param qtype The query type to look up
  89. /// \param response the query message (must be in RENDER mode)
  90. /// which has question section already (exception
  91. /// MessageNoQeustionSection will be thrown if it has
  92. /// no question section). If the message can be found
  93. /// in cache, rrsets for the message will be added to
  94. /// different sections(answer, authority, additional).
  95. /// \return return true if the message can be found, or else,
  96. /// return false.
  97. bool lookup(const isc::dns::Name& qname,
  98. const isc::dns::RRType& qtype,
  99. isc::dns::Message& response) const;
  100. /// \brief Look up rrset in cache.
  101. ///
  102. /// \param qname The query name to look up
  103. /// \param qtype The query type to look up
  104. ///
  105. /// \return return the shared_ptr of rrset if it can be found,
  106. /// or else, return NULL. When looking up, local zone
  107. /// data will be searched first, if not found, then
  108. /// search in rrset cache.
  109. ///
  110. /// \overload
  111. ///
  112. isc::dns::RRsetPtr lookup(const isc::dns::Name& qname,
  113. const isc::dns::RRType& qtype) const;
  114. /// \brief Update the message in the cache with the new one.
  115. ///
  116. /// \param msg The message to update
  117. ///
  118. /// \return return true if the message is updated successfully,
  119. /// or else, return false.
  120. ///
  121. /// \note the function doesn't do any message validation check,
  122. /// the user should make sure the message is valid, and of
  123. /// the right class
  124. bool update(const isc::dns::Message& msg);
  125. /// \brief Update the rrset in the cache with the new one.
  126. ///
  127. /// local zone data and rrset cache will be updated together.
  128. /// If the rrset doesn't exist in both of them, then the rrset
  129. /// will be added into both of them.
  130. ///
  131. /// \param rrset_ptr The RRset to update
  132. ///
  133. /// \return return false, if the class of the parameter rrset is
  134. /// allowed to be cached.
  135. ///
  136. /// \overload
  137. ///
  138. /// \note The class of the RRset must have been checked. It is not
  139. /// here.
  140. bool update(const isc::dns::ConstRRsetPtr rrset_ptr);
  141. /// \brief Get the RRClass this cache is for
  142. ///
  143. /// \return The RRClass of this cache
  144. const isc::dns::RRClass& getClass() const;
  145. private:
  146. /// \brief Update rrset cache.
  147. ///
  148. /// \param rrset_ptr The rrset to update with
  149. /// \param rrset_cache_ptr the rrset cache to update
  150. ///
  151. /// \return return true if the rrset is updated in the rrset cache,
  152. /// or else return false if failed.
  153. /// \param rrset_cache_ptr The rrset cache need to be updated.
  154. bool updateRRsetCache(const isc::dns::ConstRRsetPtr rrset_ptr,
  155. RRsetCachePtr rrset_cache_ptr);
  156. /// \brief Class this cache is for.
  157. const isc::dns::RRClass cache_class_;
  158. /// \brief map of message caches for configured classes(each message
  159. /// cache is class-specific)
  160. MessageCachePtr messages_cache_;
  161. /// \name rrset caches
  162. //@{
  163. /// \brief Local Zone data cache
  164. /// Cache for rrsets in local zones, rrsets
  165. /// in it never expire.
  166. LocalZoneDataPtr local_zone_data_;
  167. /// \brief cache the rrsets parsed from the received message.
  168. RRsetCachePtr rrsets_cache_;
  169. //@}
  170. };
  171. class ResolverCache {
  172. public:
  173. /// \brief Default Constructor.
  174. ///
  175. /// Right now, only support for class "IN", and message cache size is
  176. /// MESSAGE_CACHE_DEFAULT_SIZE, rrset cache size is
  177. /// RRSET_CACHE_DEFAULT_SIZE
  178. ResolverCache();
  179. /// \brief Construct Function.
  180. /// \param caches_size cache size information for each
  181. /// messages/rrsets of different classes.
  182. ResolverCache(std::vector<CacheSizeInfo> caches_size);
  183. /// \brief Destructor
  184. ~ResolverCache();
  185. /// \name Lookup Interfaces
  186. //@{
  187. /// \brief Look up message in cache.
  188. ///
  189. /// \param qname The query name to look up
  190. /// \param qtype The query type to look up
  191. /// \param qclass The query class to look up
  192. /// \param response the query message (must be in RENDER mode)
  193. /// which has question section already (exception
  194. /// MessageNoQeustionSection will be thrown if it has
  195. /// no question section). If the message can be found
  196. /// in cache, rrsets for the message will be added to
  197. /// different sections(answer, authority, additional).
  198. /// \return return true if the message can be found, or else,
  199. /// return false.
  200. bool lookup(const isc::dns::Name& qname,
  201. const isc::dns::RRType& qtype,
  202. const isc::dns::RRClass& qclass,
  203. isc::dns::Message& response) const;
  204. /// \brief Look up rrset in cache.
  205. ///
  206. /// \param qname The query name to look up
  207. /// \param qtype The query type to look up
  208. /// \param qclass The query class to look up
  209. ///
  210. /// \return return the shared_ptr of rrset if it can be found,
  211. /// or else, return NULL. When looking up, local zone
  212. /// data will be searched first, if not found, then
  213. /// search in rrset cache.
  214. ///
  215. /// \overload
  216. ///
  217. isc::dns::RRsetPtr lookup(const isc::dns::Name& qname,
  218. const isc::dns::RRType& qtype,
  219. const isc::dns::RRClass& qclass) const;
  220. /// \brief Look up closest rrset in cache.
  221. ///
  222. /// \param qname The query name to look up
  223. /// \param qtype The query type to look up
  224. /// \param qclass The query class to look up
  225. ///
  226. /// \return return the shared_ptr of rrset if it can be found in
  227. /// cache, or else return NULL.
  228. ///
  229. /// Currently the implementation is: search exact rrset
  230. /// label by lable, If the rrset can't be found, remove the last
  231. /// label, then search again. The efficiency may be very low when
  232. /// the name of rrset is very long but it's closest rrset's name
  233. /// is very short.
  234. /// If a good perfermance is needed when looking up the closest rrset,
  235. /// rrset cache structure(HashTable) should be redesigned. By using
  236. /// HashTable, it can only garantee the performance for looking
  237. /// up exact rrset.
  238. /// So here there is another question, which rrset looking up interface
  239. /// is used frequently? Exact or closest looking up.
  240. isc::dns::RRsetPtr lookupClosestRRset(const isc::dns::Name& qname,
  241. const isc::dns::RRType& qtype,
  242. const isc::dns::RRClass& qclass) const;
  243. //@}
  244. /// \brief Update the message in the cache with the new one.
  245. ///
  246. /// \param msg The message to update
  247. ///
  248. /// \return return true if the message is updated successfully,
  249. /// or else, return false.
  250. ///
  251. /// \note the function doesn't do any message validation check,
  252. /// the user should make sure the message is valid.
  253. bool update(const isc::dns::Message& msg);
  254. /// \brief Update the rrset in the cache with the new one.
  255. ///
  256. /// local zone data and rrset cache will be updated together.
  257. /// If the rrset doesn't exist in both of them, then the rrset
  258. /// will be added into both of them.
  259. ///
  260. /// \param rrset_ptr The RRset to update
  261. ///
  262. /// \return return false, if the class of the parameter rrset is
  263. /// allowed to be cached.
  264. ///
  265. /// \overload
  266. ///
  267. bool update(const isc::dns::ConstRRsetPtr rrset_ptr);
  268. /// \name Cache Serialization
  269. //@{
  270. /// \brief Dump the cache content to one file.
  271. ///
  272. /// \param file_name file to write to
  273. ///
  274. /// \todo It should can be dumped to one configured database.
  275. void dump(const std::string& file_name);
  276. /// \brief Load the cache from one file.
  277. ///
  278. /// \param file to load from
  279. ///
  280. /// \todo It should can be loaded from one configured database.
  281. void load(const std::string& file_name);
  282. //@}
  283. private:
  284. /// \brief Returns the class-specific subcache
  285. ///
  286. /// \param cache_class the class to get the subcache for
  287. /// \return The subcache, or NULL if there is no cache for this class
  288. ResolverClassCache* getClassCache(const isc::dns::RRClass& cache_class) const;
  289. /// The class-specific caches.
  290. /// TODO: I think we can optimize for IN, and always have that
  291. /// one directly available, use the vector for the rest?
  292. std::vector<ResolverClassCache*> class_caches_;
  293. };
  294. } // namespace cache
  295. } // namespace isc
  296. #endif // __RESOLVER_CACHE_H