cache.h 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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 __CACHE_H
  15. #define __CACHE_H
  16. #include <time.h>
  17. #include <boost/shared_ptr.hpp>
  18. #include <dns/rrset.h>
  19. namespace isc {
  20. namespace dns {
  21. class Name;
  22. class RRClass;
  23. class RRType;
  24. }
  25. namespace datasrc {
  26. class CacheNode;
  27. typedef boost::shared_ptr<CacheNode> CacheNodePtr;
  28. typedef boost::shared_ptr<const CacheNode> ConstCacheNodePtr;
  29. class HotCacheImpl;
  30. /// \brief A \c HotCache is a hot-spot cache for one or more data sources.
  31. ///
  32. /// A \c HotCache must be instantiated prior to creating a \c Query.
  33. /// The same instance should be passed to the constructor for all queries,
  34. /// so that all of them will be using the same cache.
  35. ///
  36. /// The cache may contain positive or negative entries, indicating
  37. /// whether the data does or does not exist in the underlying data
  38. /// source. Entries have a fixed and limited lifespan (currently
  39. /// set to 30 seconds, see LIFESPAN_ below). If a cache entry is
  40. /// found which has exceeded its lifespan, it will not be returned
  41. /// to the caller--exactly as if it had not been found.
  42. ///
  43. /// The current 30 second cache entry lifespan is experimental. A longer
  44. /// lifespan would improve performance somewhat; however, longer-lived
  45. /// cache entries are more likely to be incorrect in the event that
  46. /// the underlying data source had been updated. Depending on the
  47. /// frequency of queries and the frequency of updates, longer or
  48. /// shorter lifespans may be desirable -- it's even possible
  49. /// we may want the lifespan to be set differently depending on
  50. /// the zone or the data source (i.e., with an infinite lifespan
  51. /// for cached data from a static data source). Additional benchmarking
  52. /// and analysis will be needed for this.
  53. ///
  54. /// The cache may be configured with a number of available slots for
  55. /// for entries. When set to a nonzero value, no more than that number
  56. /// of entries can exist in the cache. If more entries are inserted,
  57. /// old entries will be dropped in "least recently used" order. If
  58. /// set to zero, the cache size is unlimited. The current default is
  59. /// based on one thousand queries per second, times the number of seconds
  60. /// in the cache lifespan: 30,000 slots.
  61. ///
  62. /// Notes to developers: The current implementation of HotCache uses
  63. /// a std::map (keyed by isc::dns::Question) to locate nodes, so access
  64. /// will generally be in O(log n) time. (XXX: This might be faster if a
  65. /// hash table were used instead.)
  66. ///
  67. /// A linked list is also maintained to keep track of recent accesses
  68. /// to cache entries; each time an entry is accessed, it is moved to the
  69. /// head of the list; when entries need to be removed, they are taken
  70. /// from the tail of the list. This operation is not locked. BIND 10
  71. /// does not currently use threads, but if it ever does (or if libdatasrc
  72. /// is ever used by a threaded application), this will need to be
  73. /// revisited.
  74. class HotCache {
  75. private:
  76. /// \name Static definitions
  77. //@{
  78. /// \brief Default validity period for cache entries
  79. static const int LIFESPAN_ = 30;
  80. /// \brief Default number of slots in cache
  81. static const int SLOTS_ = 1000 * LIFESPAN_;
  82. //@}
  83. /// \name Constructors, Assignment Operator and Destructor.
  84. ///
  85. /// Note: The copy constructor and the assignment operator are intentionally
  86. /// defined as private.
  87. //@{
  88. HotCache(const HotCache& source);
  89. HotCache& operator=(const HotCache& source);
  90. public:
  91. /// \brief Constructor for HotCache
  92. ///
  93. /// \param slots The number of slots available in the cache.
  94. HotCache(const int slots = SLOTS_);
  95. /// \brief Destructor for HotCache
  96. ~HotCache();
  97. //@}
  98. /// \name Cache Manipulation Methods
  99. //@{
  100. /// \brief Enter a positive cache entry.
  101. ///
  102. /// If an entry already exists in the cache which matches the
  103. /// name/class/type of the RRset being cached, then the old entry
  104. /// is removed before the the new one is inserted. (XXX: This is
  105. /// currently slightly inefficient; it would be quicker to keep the
  106. /// existing node and simply update the rrset, flags, and lifespan.)
  107. ///
  108. /// \param rrset The \c RRset to cache.
  109. /// \param flags The query response flags returned from the low-level
  110. /// data source when this \c RRset was looked up.
  111. /// \param lifespan How long the cache node is to be considered valid;
  112. /// defaulting to 30 seconds.
  113. void addPositive(isc::dns::RRsetPtr rrset,
  114. uint32_t flags,
  115. time_t lifespan = LIFESPAN_);
  116. /// \brief Enter a negative cache entry.
  117. ///
  118. /// In the case of a negative cache entry there is no \c RRset to
  119. /// cache, so instead a null \c RRsetPtr will be stored. Since the
  120. /// name, class, and type cannot be retrieved from an \c RRset, they
  121. /// must be specified in the parameters.
  122. ///
  123. /// If an entry already exists in the cache which matches the
  124. /// specified name/class/type, then the old entry is removed
  125. /// before the the new one is inserted. (XXX: As noted in the comments
  126. /// for addPositive(), this is currently slightly inefficient.)
  127. ///
  128. /// \param name Query name
  129. /// \param rrclass Query class
  130. /// \param rrtype Query type
  131. /// \param flags Query response flags returned from the low-level
  132. /// data source, indicating why this lookup failed (name not found,
  133. /// type not found, etc).
  134. /// \param lifespan How long the cache node is to be considered valid;
  135. /// defaulting to 30 seconds.
  136. ///
  137. /// Note: 'rrclass' and 'rrtype' must refer to a specific class and
  138. /// type; it is not meaningful to cache type or class ANY. Currently,
  139. /// this condition is silently ignored.
  140. void addNegative(const isc::dns::Name& name,
  141. const isc::dns::RRClass& rrclass,
  142. const isc::dns::RRType& rrtype,
  143. uint32_t flags,
  144. time_t lifespan = LIFESPAN_);
  145. /// \brief Retrieve (and promote) a record from the cache
  146. ///
  147. /// Retrieves a record from the cache matching the given
  148. /// query-tuple. Returns true if one is found. If it is a
  149. /// positive cache entry, then 'rrset' is set to the cached
  150. /// RRset. For both positive and negative cache entries, 'flags'
  151. /// is set to the query response flags. The cache entry is
  152. /// then promoted to the head of the LRU queue. (NOTE: Because
  153. /// of this, "retrieve" cannot be implemented as a const method.)
  154. ///
  155. /// \param qname The query name
  156. /// \param qclass The query class
  157. /// \param qtype The query type
  158. /// \param rrset Returns the RRset found, if any, to the caller
  159. /// \param flags Returns the flags, if any, to the caller
  160. ///
  161. /// \return \c bool, true if data was found in the cache, false if not.
  162. bool retrieve(const isc::dns::Name& qname,
  163. const isc::dns::RRClass& qclass,
  164. const isc::dns::RRType& qtype,
  165. isc::dns::RRsetPtr& rrset,
  166. uint32_t& flags);
  167. //@}
  168. /// \name Getter and Setter Methods
  169. //@{
  170. /// \brief Sets the number of slots in the cache.
  171. ///
  172. /// If slots is set to zero, the cache can grow without any imposed
  173. /// limit. If slots is to set a lower number than the cache currently
  174. /// contains, then the least recently used records will be purged from
  175. /// the cache until the total number of items in the cache equals slots.
  176. void setSlots(int slots);
  177. /// \brief Returns the number of slots in the cache.
  178. int getSlots() const;
  179. /// \brief Enable or disable the cache
  180. void setEnabled(bool e);
  181. /// \brief Indicate whether the cache is enabled
  182. bool getEnabled() const;
  183. /// \brief Returns the number of nodes currently stored in the cache.
  184. ///
  185. /// Note that this doesn't indicate how many nodes are still valid;
  186. /// some may have expired.
  187. int getCount() const;
  188. //@}
  189. private:
  190. /// \brief Hidden implementation details
  191. HotCacheImpl* impl_;
  192. };
  193. }
  194. }
  195. #endif
  196. // Local Variables:
  197. // mode: c++
  198. // End: