zone_table.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. // Copyright (C) 2012 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 DATASRC_MEMORY_ZONE_TABLE_H
  15. #define DATASRC_MEMORY_ZONE_TABLE_H 1
  16. #include <util/memory_segment.h>
  17. #include <dns/rrclass.h>
  18. #include <datasrc/result.h>
  19. #include <datasrc/memory/domaintree.h>
  20. #include <boost/noncopyable.hpp>
  21. #include <boost/interprocess/offset_ptr.hpp>
  22. namespace isc {
  23. namespace dns {
  24. class Name;
  25. class RRClass;
  26. }
  27. namespace datasrc {
  28. namespace memory {
  29. // forward declaration: in this header it's mostly an opaque type.
  30. class ZoneData;
  31. /// \brief A conceptual table of authoritative zones.
  32. ///
  33. /// This class is actually a simple wrapper for a \c DomainTree whose data is
  34. /// of \c ZoneData, and provides allocator, deallocator, and some basic
  35. /// manipulation methods.
  36. ///
  37. /// A single \c ZoneData object is intended to be used for a single specific
  38. /// RR class, and provides a mapping from a name to a \c ZoneData (using the
  39. /// best matching search semantics). The \c ZoneData class itself does not
  40. /// maintain the information of the RR class; the user of this class is
  41. /// responsible for associating a specific RR class to a corresponding
  42. /// \c ZoneData object.
  43. ///
  44. /// This class is designed so an instance can be stored in a shared memory
  45. /// region. So it only contains straightforward data (e.g., it doesn't hold
  46. /// a pointer to an object of some base class that contains virtual methods),
  47. /// and some pointers (either as a direct or indirect member variable) are
  48. /// represented as offset pointers. For the same reason this class should
  49. /// never has virtual methods (and as a result, should never be inherited
  50. /// in practice). When this class is extended these properties must be
  51. /// retained.
  52. ///
  53. /// This class is intended to be used as a backend for the \c MemoryDataSrc
  54. /// class, and is not intended to be used for other general purposes.
  55. class ZoneTable : boost::noncopyable {
  56. private:
  57. // The deleter for the zone data stored in the table.
  58. struct ZoneDataDeleter {
  59. ZoneDataDeleter() {}
  60. void operator()(util::MemorySegment& mem_sgmt,
  61. ZoneData* zone_data) const;
  62. };
  63. // Type aliases to make it shorter
  64. typedef DomainTree<ZoneData> ZoneTableTree;
  65. typedef DomainTreeNode<ZoneData> ZoneTableNode;
  66. public:
  67. /// \brief Result data of addZone() method.
  68. struct AddResult {
  69. AddResult(result::Result param_code, ZoneData* param_zone_data) :
  70. code(param_code), zone_data(param_zone_data)
  71. {}
  72. const result::Result code;
  73. ZoneData* const zone_data;
  74. };
  75. /// \brief Result data of findZone() method.
  76. ///
  77. /// See \c findZone() about the semantics of the members.
  78. struct FindResult {
  79. FindResult(result::Result param_code,
  80. const ZoneData* param_zone_data,
  81. result::ResultFlags param_flags = result::FLAGS_DEFAULT) :
  82. code(param_code), flags(param_flags), zone_data(param_zone_data)
  83. {}
  84. const result::Result code;
  85. const result::ResultFlags flags;
  86. const ZoneData* const zone_data;
  87. };
  88. private:
  89. /// Constructor.
  90. ///
  91. /// An object of this class is always expected to be created by the
  92. /// allocator (\c create()), so the constructor is hidden as private.
  93. ///
  94. /// This constructor never throws.
  95. ZoneTable(const dns::RRClass& rrclass, ZoneTableTree* zones,
  96. ZoneData* null_zone_data) :
  97. rrclass_(rrclass),
  98. zone_count_(0),
  99. zones_(zones),
  100. null_zone_data_(null_zone_data)
  101. {}
  102. public:
  103. /// \brief Allocate and construct \c ZoneTable
  104. ///
  105. /// This static method allocates memory for a new \c ZoneTable object
  106. /// from the given memory segment, constructs the object, and returns
  107. /// a pointer to it.
  108. ///
  109. /// This method ensures there'll be no memory leak on exception.
  110. /// But addresses allocated from \c mem_sgmt could be relocated if
  111. /// \c util::MemorySegmentGrown is thrown; the caller or its upper layer
  112. /// must be aware of that possibility and update any such addresses
  113. /// accordingly. On successful return, this method ensures there's no
  114. /// address relocation.
  115. ///
  116. /// \throw util::MemorySegmentGrown The memory segment has grown, possibly
  117. /// relocating data.
  118. /// \throw std::bad_alloc Memory allocation fails.
  119. ///
  120. /// \param mem_sgmt A \c MemorySegment from which memory for the new
  121. /// \c ZoneTable is allocated.
  122. /// \param zone_class The RR class of the zone. It must be the RR class
  123. /// that is supposed to be associated to the zone table.
  124. static ZoneTable* create(util::MemorySegment& mem_sgmt,
  125. const dns::RRClass& zone_class);
  126. /// \brief Destruct and deallocate \c ZoneTable
  127. ///
  128. /// This method releases all internal resources including all zone data
  129. /// created via \c addZone() calls.
  130. ///
  131. /// \throw none
  132. ///
  133. /// \param mem_sgmt The \c MemorySegment that allocated memory for
  134. /// \c ztable and used for prior calls to \c addZone().
  135. /// \param zone_class The RR class of the zone. It must be the RR class
  136. /// that is supposed to be associated to the zone table.
  137. /// \param ztable A non NULL pointer to a valid \c ZoneTable object
  138. /// that was originally created by the \c create() method (the behavior
  139. /// is undefined if this condition isn't met).
  140. static void destroy(util::MemorySegment& mem_sgmt, ZoneTable* ztable);
  141. /// \brief Return the number of zones contained in the zone table.
  142. ///
  143. /// \throw None.
  144. size_t getZoneCount() const { return (zone_count_); }
  145. /// \brief Add a new zone to the \c ZoneTable.
  146. ///
  147. /// This method adds a given zone data to the internal table.
  148. ///
  149. /// This method ensures there'll be no memory leak on exception.
  150. /// But addresses allocated from \c mem_sgmt could be relocated if
  151. /// \c util::MemorySegmentGrown is thrown; the caller or its upper layer
  152. /// must be aware of that possibility and update any such addresses
  153. /// accordingly. On successful return, this method ensures there's no
  154. /// address relocation.
  155. ///
  156. /// \throw InvalidParameter content is NULL or empty.
  157. /// \throw util::MemorySegmentGrown The memory segment has grown, possibly
  158. /// relocating data.
  159. /// \throw std::bad_alloc Internal resource allocation fails.
  160. ///
  161. /// \param mem_sgmt The \c MemorySegment to allocate zone data to be
  162. /// created. It must be the same segment that was used to create
  163. /// the zone table at the time of create().
  164. /// \param zone_name The name of the zone to be added.
  165. /// \param zone_class The RR class of the zone. It must be the RR class
  166. /// that is supposed to be associated to the zone table.
  167. /// \param content This one should hold the zone content (the ZoneData).
  168. /// The ownership is passed onto the zone table. Must not be null or
  169. /// empty. Must correspond to the name and class and must be allocated
  170. /// from mem_sgmt.
  171. /// \return \c result::SUCCESS If the zone is successfully
  172. /// added to the zone table.
  173. /// \return \c result::EXIST The zone table already contained
  174. /// zone of the same origin. The old data is replaced and returned
  175. /// inside the result unless it's empty; if the zone was previously
  176. /// added by \c addEmptyZone(), the data returned is NULL.
  177. AddResult addZone(util::MemorySegment& mem_sgmt,
  178. dns::RRClass zone_class,
  179. const dns::Name& zone_name,
  180. ZoneData* content);
  181. /// \brief Add an empty zone to the \c ZoneTable.
  182. ///
  183. /// This method is similar to \c addZone(), but adds a conceptual "empty"
  184. /// zone of the given zone name to the table. The added empty zone
  185. /// affects subsequent calls to \c addZone() (and \c addEmptyZone() itself)
  186. /// and \c findZone() as described for these methods.
  187. ///
  188. /// The intended meaning of an empty zone in the table is that the zone
  189. /// is somehow broken, such as configured to be loaded but loading failed.
  190. /// But this class is not aware of such interpretation; it's up to the
  191. /// user of the class how to use the concept of empty zones.
  192. ///
  193. /// It returns an \c AddResult object as described for \c addZone().
  194. ///
  195. /// The same notes on exception safety as that for \c addZone() applies.
  196. ///
  197. /// \param mem_sgmt Same as addZone().
  198. /// \param zone_name Same as addZone().
  199. AddResult addEmptyZone(util::MemorySegment& mem_sgmt,
  200. const dns::Name& zone_name);
  201. /// \brief Find a zone that best matches the given name in the
  202. /// \c ZoneTable.
  203. ///
  204. /// It searches the internal storage for a zone that gives the
  205. /// longest match against \c name, and returns the result in the
  206. /// form of a \c FindResult object as follows:
  207. /// - \c code: The result code of the operation.
  208. /// - \c result::SUCCESS: A zone that gives an exact match
  209. /// is found
  210. /// - \c result::PARTIALMATCH: A zone whose origin is a
  211. /// super domain of \c name is found (but there is no exact match)
  212. /// - \c result::NOTFOUND: For all other cases.
  213. /// - \c flags If the zone is empty (added by \c addEmptyZone()),
  214. /// result::ZONE_EMPTY is set.
  215. /// - \c zone_data: corresponding zone data of the found zone if found and
  216. /// non empty; NULL if no matching zone is found or the found zone is
  217. /// empty.
  218. ///
  219. /// \throw none
  220. ///
  221. /// \param name A domain name for which the search is performed.
  222. /// \return A \c FindResult object enclosing the search result (see above).
  223. FindResult findZone(const isc::dns::Name& name) const;
  224. private:
  225. const dns::RRClass rrclass_;
  226. size_t zone_count_;
  227. boost::interprocess::offset_ptr<ZoneTableTree> zones_;
  228. // this is a shared placeholder for broken zones
  229. boost::interprocess::offset_ptr<ZoneData> null_zone_data_;
  230. // Common routine for addZone and addEmptyZone. This method can throw
  231. // util::MemorySegmentGrown, in which case addresses from mem_sgmt
  232. // can be relocated. The caller is responsible for destroying content
  233. // on exception, if it needs to be destroyed. On successful return it
  234. // ensures there's been no address relocation.
  235. AddResult addZoneInternal(util::MemorySegment& mem_sgmt,
  236. const dns::Name& zone_name,
  237. ZoneData* content);
  238. };
  239. }
  240. }
  241. }
  242. #endif // DATASRC_MEMORY_ZONE_TABLE_H
  243. // Local Variables:
  244. // mode: c++
  245. // End: