Browse Source

[1198] Extracted search for delegation point into a separate method.

Stephen Morris 13 years ago
parent
commit
2e12dd60da
2 changed files with 129 additions and 23 deletions
  1. 65 23
      src/lib/datasrc/database.cc
  2. 64 0
      src/lib/datasrc/database.h

+ 65 - 23
src/lib/datasrc/database.cc

@@ -14,6 +14,7 @@
 
 #include <string>
 #include <vector>
+#include <iostream>
 
 #include <datasrc/database.h>
 #include <datasrc/data_source.h>
@@ -389,55 +390,55 @@ DatabaseClient::Finder::findNSECCover(const Name& name) {
     return (RRsetPtr());
 }
 
-ZoneFinder::FindResult
-DatabaseClient::Finder::find(const isc::dns::Name& name,
-                             const isc::dns::RRType& type,
-                             isc::dns::RRsetList*,
-                             const FindOptions options)
-{
-    // This variable is used to determine the difference between
-    // NXDOMAIN and NXRRSET
-    bool records_found = false;
-    bool glue_ok((options & FIND_GLUE_OK) != 0);
-    const bool dnssec_data((options & FIND_DNSSEC) != 0);
-    bool get_cover(false);
+DatabaseClient::Finder::DelegationSearchResult
+DatabaseClient::Finder::findDelegationPoint(const isc::dns::Name& name,
+                                            const FindOptions options) {
+    // Result of search
     isc::dns::RRsetPtr result_rrset;
     ZoneFinder::Result result_status = SUCCESS;
-    FoundRRsets found;
-    logger.debug(DBG_TRACE_DETAILED, DATASRC_DATABASE_FIND_RECORDS)
-        .arg(accessor_->getDBName()).arg(name).arg(type);
+
     // In case we are in GLUE_OK mode and start matching wildcards,
     // we can't do it under NS, so we store it here to check
     isc::dns::RRsetPtr first_ns;
 
+    // Are we searching for glue?
+    bool glue_ok((options & FIND_GLUE_OK) != 0);
+
     // First, do we have any kind of delegation (NS/DNAME) here?
     const Name origin(getOrigin());
     const size_t origin_label_count(origin.getLabelCount());
+
     // Number of labels in the last known non-empty domain
     size_t last_known(origin_label_count);
     const size_t current_label_count(name.getLabelCount());
+
     // This is how many labels we remove to get origin
     const size_t remove_labels(current_label_count - origin_label_count);
 
-    // Now go trough all superdomains from origin down
-    for (int i(remove_labels); i > 0; --i) {
+    // Go through all superdomains from the origin down searching for nodes
+    // that indicate a delegation (NS or DNAME).
+    for (int i = remove_labels; i > 0; --i) {
         Name superdomain(name.split(i));
+
+        // Note if this is the origin.
+        bool not_origin = (i != remove_labels);
+
         // Look if there's NS or DNAME (but ignore the NS in origin)
-        found = getRRsets(superdomain.toText(), DELEGATION_TYPES(),
-                          i != remove_labels);
+        FoundRRsets found = getRRsets(superdomain.toText(), DELEGATION_TYPES(),
+                                      not_origin);
         if (found.first) {
             // It contains some RRs, so it exists.
             last_known = superdomain.getLabelCount();
 
             const FoundIterator nsi(found.second.find(RRType::NS()));
             const FoundIterator dni(found.second.find(RRType::DNAME()));
+
             // In case we are in GLUE_OK mode, we want to store the
             // highest encountered NS (but not apex)
-            if (glue_ok && !first_ns && i != remove_labels &&
-                nsi != found.second.end()) {
+            if (glue_ok && !first_ns && not_origin && nsi != found.second.end()) {
                 first_ns = nsi->second;
-            } else if (!glue_ok && i != remove_labels &&
-                       nsi != found.second.end()) {
+
+            } else if (!glue_ok && not_origin && nsi != found.second.end()) {
                 // Do a NS delegation, but ignore NS in glue_ok mode. Ignore
                 // delegation in apex
                 LOG_DEBUG(logger, DBG_TRACE_DETAILED,
@@ -447,6 +448,7 @@ DatabaseClient::Finder::find(const isc::dns::Name& name,
                 result_status = DELEGATION;
                 // No need to go lower, found
                 break;
+
             } else if (dni != found.second.end()) {
                 // Very similar with DNAME
                 LOG_DEBUG(logger, DBG_TRACE_DETAILED,
@@ -463,6 +465,46 @@ DatabaseClient::Finder::find(const isc::dns::Name& name,
             }
         }
     }
+    return (DelegationSearchResult(result_status, result_rrset, first_ns,
+                                   last_known));
+}
+
+ZoneFinder::FindResult
+DatabaseClient::Finder::find(const isc::dns::Name& name,
+                             const isc::dns::RRType& type,
+                             isc::dns::RRsetList*,
+                             const FindOptions options)
+{
+    // This variable is used to determine the difference between
+    // NXDOMAIN and NXRRSET
+    bool records_found = false;
+    bool glue_ok((options & FIND_GLUE_OK) != 0);
+    const bool dnssec_data((options & FIND_DNSSEC) != 0);
+    bool get_cover(false);
+    isc::dns::RRsetPtr result_rrset;
+    ZoneFinder::Result result_status = SUCCESS;
+    FoundRRsets found;
+    logger.debug(DBG_TRACE_DETAILED, DATASRC_DATABASE_FIND_RECORDS)
+        .arg(accessor_->getDBName()).arg(name).arg(type);
+
+    // First, do we have any kind of delegation (NS/DNAME) here?
+    const Name origin(getOrigin());
+    // Number of labels in the last known non-empty domain
+    const size_t current_label_count(name.getLabelCount());
+    // This is how many labels we remove to get origin
+    //const size_t remove_labels(current_label_count - origin_label_count);
+
+    // First stage: go throught all superdomains from the origin down,
+    // searching for nodes that indicate a delegation (NS or DNAME).
+
+    DelegationSearchResult dresult = findDelegationPoint(name, options);
+    result_status = dresult.code;
+    result_rrset = dresult.rrset;
+
+    // In case we are in GLUE_OK mode and start matching wildcards,
+    // we can't do it under NS, so we store it here to check
+    isc::dns::RRsetPtr first_ns = dresult.first_ns;
+    size_t last_known = dresult.last_known;
 
     if (!result_rrset) { // Only if we didn't find a redirect already
         // Try getting the final result and extract it

+ 64 - 0
src/lib/datasrc/database.h

@@ -18,6 +18,7 @@
 #include <string>
 
 #include <boost/scoped_ptr.hpp>
+#include <boost/tuple/tuple.hpp>
 
 #include <dns/rrclass.h>
 #include <dns/rrclass.h>
@@ -814,6 +815,40 @@ public:
         const DatabaseAccessor& getAccessor() const {
             return (*accessor_);
         }
+        
+        /// \brief Search result of \c findDelegationPoint().
+        ///
+        /// This is a tuple combining the result of the search - a status code
+        /// and a pointer to the RRset found - together with additional
+        /// information needed for subsequent processing, an indication of
+        /// the first NS RRset found in the search and the number of labels
+        /// in the last non-empty domain encountered in the search.  It is
+        /// used by \c findDelegationPoint().
+        ///
+        /// The last two items are located naturally in the search and although
+        /// not strictly part of the result, they are passed back to avoid
+        /// another (duplicate) search later in the processing.
+        ///
+        /// Note that the code and rrset elements are the same as that in
+        /// the \c ZoneFinder::FindResult struct: this structure could be
+        /// derived from that one, but as it is used just once in the code and
+        /// will never be treated as a \c FindResult, the obscurity involved in
+        /// deriving it from a parent class was deemed not worthwhile.
+        struct DelegationSearchResult {
+            DelegationSearchResult(const ZoneFinder::Result param_code,
+                                   const isc::dns::RRsetPtr param_rrset,
+                                   const isc::dns::RRsetPtr param_ns,
+                                   size_t param_last_known) :
+                                   code(param_code), rrset(param_rrset),
+                                   first_ns(param_ns),
+                                   last_known(param_last_known)
+            {}
+            const ZoneFinder::Result code;      ///< Result code
+            const isc::dns::RRsetPtr rrset;     ///< Pointer to RRset found
+            const isc::dns::RRsetPtr first_ns;  ///< Pointer to first NS found
+            const size_t last_known; ///< No. labels in last non-empty domain
+        };
+
     private:
         boost::shared_ptr<DatabaseAccessor> accessor_;
         const int zone_id_;
@@ -824,6 +859,7 @@ public:
             FoundRRsets;
         /// \brief Just shortcut for set of types
         typedef std::set<dns::RRType> WantedTypes;
+
         /**
          * \brief Searches database for RRsets of one domain.
          *
@@ -854,6 +890,34 @@ public:
         FoundRRsets getRRsets(const std::string& name,
                               const WantedTypes& types, bool check_ns,
                               const std::string* construct_name = NULL);
+
+        /**
+         * \brief Find delegation point
+         *
+         * Given a name, searches through the superdomains from the origin
+         * down, searching for a point that indicates a delegation (i.e. an
+         * NS record or a DNAME).
+         *
+         * \param name The name to find
+         * \param type The RRType to find
+         * \param target Unused at this moment
+         * \param options Options about how to search. See
+         *        ZoneFinder::FindOptions.
+         *
+         * \return Tuple holding the result of the search - the RRset of the
+         *         delegation point and the type of the point (DELEGATION or
+         *         DNAME) - and associated information.  This latter item
+         *         comprises two pieces of data: a pointer to the highest
+         *         encountered NS, and the number of labels in the last known
+         *         non-empty domain.  The associated information is found as
+         *         a natural part of the search for the delegation point and
+         *         is used later in the find() processing; it is passed back
+         *         to avoid the need to perform a second search toi obtain it.
+         */
+        DelegationSearchResult
+        findDelegationPoint(const isc::dns::Name& name,
+                            const FindOptions options = FIND_DEFAULT);
+
         /**
          * \brief Checks if something lives below this domain.
          *