cache.h 8.7 KB

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