memory_datasrc.cc 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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. #include <map>
  15. #include <cassert>
  16. #include <boost/shared_ptr.hpp>
  17. #include <dns/name.h>
  18. #include <dns/rrclass.h>
  19. #include <datasrc/memory_datasrc.h>
  20. #include <datasrc/rbtree.h>
  21. using namespace std;
  22. using namespace isc::dns;
  23. namespace isc {
  24. namespace datasrc {
  25. // Private data and hidden methods of MemoryZone
  26. struct MemoryZone::MemoryZoneImpl {
  27. // Constructor
  28. MemoryZoneImpl(const RRClass& zone_class, const Name& origin) :
  29. zone_class_(zone_class), origin_(origin)
  30. {}
  31. // Information about the zone
  32. RRClass zone_class_;
  33. Name origin_;
  34. // Some type aliases
  35. /*
  36. * Each domain consists of some RRsets. They will be looked up by the
  37. * RRType.
  38. *
  39. * The use of map is questionable with regard to performance - there'll
  40. * be usually only few RRsets in the domain, so the log n benefit isn't
  41. * much and a vector/array might be faster due to its simplicity and
  42. * continuous memory location. But this is unlikely to be a performance
  43. * critical place and map has better interface for the lookups, so we use
  44. * that.
  45. */
  46. typedef map<RRType, ConstRRsetPtr> Domain;
  47. typedef Domain::value_type DomainPair;
  48. typedef boost::shared_ptr<Domain> DomainPtr;
  49. // The tree stores domains
  50. typedef RBTree<Domain> DomainTree;
  51. typedef RBNode<Domain> DomainNode;
  52. // The actual zone data
  53. DomainTree domains_;
  54. /*
  55. * Implementation of longer methods. We put them here, because the
  56. * access is without the impl_-> and it will get inlined anyway.
  57. */
  58. // Implementation of MemoryZone::add
  59. result::Result add(const ConstRRsetPtr& rrset) {
  60. // Sanitize input
  61. if (!rrset) {
  62. isc_throw(NullRRset, "The rrset provided is NULL");
  63. }
  64. Name name(rrset->getName());
  65. NameComparisonResult compare(origin_.compare(name));
  66. if (compare.getRelation() != NameComparisonResult::SUPERDOMAIN &&
  67. compare.getRelation() != NameComparisonResult::EQUAL)
  68. {
  69. isc_throw(OutOfZone, "The name " << name <<
  70. " is not contained in zone " << origin_);
  71. }
  72. // Get the node
  73. DomainNode* node;
  74. switch (domains_.insert(name, &node)) {
  75. // Just check it returns reasonable results
  76. case DomainTree::SUCCEED:
  77. case DomainTree::ALREADYEXIST:
  78. break;
  79. // Something odd got out
  80. default:
  81. assert(0);
  82. }
  83. assert(node);
  84. // Now get the domain
  85. DomainPtr domain;
  86. // It didn't exist yet, create it
  87. if (node->isEmpty()) {
  88. domain.reset(new Domain);
  89. node->setData(domain);
  90. } else { // Get existing one
  91. domain = node->getData();
  92. }
  93. // Try inserting the rrset there
  94. if (domain->insert(DomainPair(rrset->getType(), rrset)).second) {
  95. // Ok, we just put it in
  96. return (result::SUCCESS);
  97. } else {
  98. // The RRSet of given type was already there
  99. return (result::EXIST);
  100. }
  101. }
  102. // Implementation of MemoryZone::find
  103. FindResult find(const Name& name, RRType type) const {
  104. // Get the node
  105. DomainNode* node;
  106. switch (domains_.find(name, &node)) {
  107. case DomainTree::PARTIALMATCH:
  108. // Pretend it was not found for now
  109. // TODO: Implement real delegation. Currently, not having
  110. // the the domain can cause a partialmatch as well, so
  111. // better check.
  112. case DomainTree::NOTFOUND:
  113. return (FindResult(NXDOMAIN, ConstRRsetPtr()));
  114. case DomainTree::EXACTMATCH: // This one is OK, handle it
  115. break;
  116. default:
  117. assert(0);
  118. }
  119. assert(node);
  120. assert(!node->isEmpty());
  121. Domain::const_iterator found(node->getData()->find(type));
  122. if (found != node->getData()->end()) {
  123. // Good, it is here
  124. return (FindResult(SUCCESS, found->second));
  125. } else {
  126. /*
  127. * TODO Look for CNAME and DNAME (it should be OK to do so when
  128. * the value is not found, as CNAME/DNAME domain should be
  129. * empty otherwise.)
  130. */
  131. return (FindResult(NXRRSET, ConstRRsetPtr()));
  132. }
  133. }
  134. };
  135. MemoryZone::MemoryZone(const RRClass& zone_class, const Name& origin) :
  136. impl_(new MemoryZoneImpl(zone_class, origin))
  137. {
  138. }
  139. MemoryZone::~MemoryZone() {
  140. delete impl_;
  141. }
  142. const Name&
  143. MemoryZone::getOrigin() const {
  144. return (impl_->origin_);
  145. }
  146. const RRClass&
  147. MemoryZone::getClass() const {
  148. return (impl_->zone_class_);
  149. }
  150. Zone::FindResult
  151. MemoryZone::find(const Name& name, const RRType& type) const {
  152. return (impl_->find(name, type));
  153. }
  154. result::Result
  155. MemoryZone::add(const ConstRRsetPtr& rrset) {
  156. return (impl_->add(rrset));
  157. }
  158. /// Implementation details for \c MemoryDataSrc hidden from the public
  159. /// interface.
  160. ///
  161. /// For now, \c MemoryDataSrc only contains a \c ZoneTable object, which
  162. /// consists of (pointers to) \c MemoryZone objects, we may add more
  163. /// member variables later for new features.
  164. struct MemoryDataSrc::MemoryDataSrcImpl {
  165. ZoneTable zone_table;
  166. };
  167. MemoryDataSrc::MemoryDataSrc() : impl_(new MemoryDataSrcImpl)
  168. {}
  169. MemoryDataSrc::~MemoryDataSrc() {
  170. delete impl_;
  171. }
  172. result::Result
  173. MemoryDataSrc::addZone(ZonePtr zone) {
  174. if (!zone) {
  175. isc_throw(InvalidParameter,
  176. "Null pointer is passed to MemoryDataSrc::addZone()");
  177. }
  178. return (impl_->zone_table.addZone(zone));
  179. }
  180. MemoryDataSrc::FindResult
  181. MemoryDataSrc::findZone(const isc::dns::Name& name) const {
  182. return (FindResult(impl_->zone_table.findZone(name).code,
  183. impl_->zone_table.findZone(name).zone));
  184. }
  185. } // end of namespace datasrc
  186. } // end of namespace dns