BIND 10 trac1750, updated. 85885d88d2647bb4bac08c0f25f485659a4e9320 [1750] Implement the shortcut in in-memory

BIND 10 source code commits bind10-changes at lists.isc.org
Fri Mar 9 12:49:58 UTC 2012


The branch, trac1750 has been updated
       via  85885d88d2647bb4bac08c0f25f485659a4e9320 (commit)
       via  4ae03bf2883251fb06740ec7dcc301d61e3ef533 (commit)
      from  6e7eee31fa6b4884490778ce4148eb346fa4bf28 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 85885d88d2647bb4bac08c0f25f485659a4e9320
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Fri Mar 9 13:43:03 2012 +0100

    [1750] Implement the shortcut in in-memory
    
    It simply takes the origin node if the FIND_AT_ORIGIN flag is present,
    not examining the qname.

commit 4ae03bf2883251fb06740ec7dcc301d61e3ef533
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Fri Mar 9 13:41:54 2012 +0100

    [1750] Add the FIND_AT_ORIGIN flag
    
    Not used yet, just documented.

-----------------------------------------------------------------------

Summary of changes:
 src/lib/datasrc/memory_datasrc.cc                |  225 ++++++++++++----------
 src/lib/datasrc/tests/memory_datasrc_unittest.cc |   35 ++++
 src/lib/datasrc/zone.h                           |    9 +-
 3 files changed, 162 insertions(+), 107 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/lib/datasrc/memory_datasrc.cc b/src/lib/datasrc/memory_datasrc.cc
index 33ab82f..fad64f0 100644
--- a/src/lib/datasrc/memory_datasrc.cc
+++ b/src/lib/datasrc/memory_datasrc.cc
@@ -677,121 +677,134 @@ struct InMemoryZoneFinder::InMemoryZoneFinderImpl {
         FindState state(options);
         RBTreeNodeChain<Domain> node_path;
         bool rename(false);
-        switch (zone_data_->domains_.find(name, &node, node_path, cutCallback,
-                                          &state)) {
-            case DomainTree::PARTIALMATCH:
-                /*
-                 * In fact, we could use a single variable instead of
-                 * dname_node_ and zonecut_node_. But then we would need
-                 * to distinquish these two cases by something else and
-                 * it seemed little more confusing to me when I wrote it.
-                 *
-                 * Usually at most one of them will be something else than
-                 * NULL (it might happen both are NULL, in which case we
-                 * consider it NOT FOUND). There's one corner case when
-                 * both might be something else than NULL and it is in case
-                 * there's a DNAME under a zone cut and we search in
-                 * glue OK mode ‒ in that case we don't stop on the domain
-                 * with NS and ignore it for the answer, but it gets set
-                 * anyway. Then we find the DNAME and we need to act by it,
-                 * therefore we first check for DNAME and then for NS. In
-                 * all other cases it doesn't matter, as at least one of them
-                 * is NULL.
-                 */
-                if (state.dname_node_ != NULL) {
-                    LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_DNAME_FOUND).
-                        arg(state.rrset_->getName());
-                    // We were traversing a DNAME node (and wanted to go
-                    // lower below it), so return the DNAME
-                    return (createFindResult(DNAME,
-                                             prepareRRset(name, state.rrset_,
-                                                          false, options)));
-                }
-                if (state.zonecut_node_ != NULL) {
-                    LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_DELEG_FOUND).
-                        arg(state.rrset_->getName());
-                    return (createFindResult(DELEGATION,
-                                             prepareRRset(name, state.rrset_,
-                                                          false, options)));
-                }
-
-                // If the RBTree search stopped at a node for a super domain
-                // of the search name, it means the search name exists in
-                // the zone but is empty.  Treat it as NXRRSET.
-                if (node_path.getLastComparisonResult().getRelation() ==
-                    NameComparisonResult::SUPERDOMAIN) {
-                    LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_SUPER_STOP).
-                        arg(name);
-                    return (createFindResult(NXRRSET, ConstRRsetPtr()));
-                }
-
-                /*
-                 * No redirection anywhere. Let's try if it is a wildcard.
-                 *
-                 * The wildcard is checked after the empty non-terminal domain
-                 * case above, because if that one triggers, it means we should
-                 * not match according to 4.3.3 of RFC 1034 (the query name
-                 * is known to exist).
-                 */
-                if (node->getFlag(DOMAINFLAG_WILD)) {
-                    /* Should we cancel this match?
-                     *
-                     * If we compare with some node and get a common ancestor,
-                     * it might mean we are comparing with a non-wildcard node.
-                     * In that case, we check which part is common. If we have
-                     * something in common that lives below the node we got
-                     * (the one above *), then we should cancel the match
-                     * according to section 4.3.3 of RFC 1034 (as the name
-                     * between the wildcard domain and the query name is known
-                     * to exist).
-                     *
-                     * Because the way the tree stores relative names, we will
-                     * have exactly one common label (the ".") in case we have
-                     * nothing common under the node we got and we will get
-                     * more common labels otherwise (yes, this relies on the
-                     * internal RBTree structure, which leaks out through this
-                     * little bit).
+        if (options & FIND_AT_ORIGIN) {
+            // In case it talks about origin, just give it the origin and don't
+            // search
+            node = zone_data_->origin_data_;
+        } else {
+            switch (zone_data_->domains_.find(name, &node, node_path,
+                                              cutCallback, &state)) {
+                case DomainTree::PARTIALMATCH:
+                    /*
+                     * In fact, we could use a single variable instead of
+                     * dname_node_ and zonecut_node_. But then we would need to
+                     * distinquish these two cases by something else and it
+                     * seemed little more confusing to me when I wrote it.
                      *
-                     * If the empty non-terminal node actually exists in the
-                     * tree, then this cancellation is not needed, because we
-                     * will not get here at all.
+                     * Usually at most one of them will be something else than
+                     * NULL (it might happen both are NULL, in which case we
+                     * consider it NOT FOUND). There's one corner case when
+                     * both might be something else than NULL and it is in case
+                     * there's a DNAME under a zone cut and we search in glue
+                     * OK mode ‒ in that case we don't stop on the domain with
+                     * NS and ignore it for the answer, but it gets set anyway.
+                     * Then we find the DNAME and we need to act by it,
+                     * therefore we first check for DNAME and then for NS. In
+                     * all other cases it doesn't matter, as at least one of
+                     * them is NULL.
                      */
+                    if (state.dname_node_ != NULL) {
+                        LOG_DEBUG(logger, DBG_TRACE_DATA,
+                                  DATASRC_MEM_DNAME_FOUND).
+                            arg(state.rrset_->getName());
+                        // We were traversing a DNAME node (and wanted to go
+                        // lower below it), so return the DNAME
+                        return (createFindResult(DNAME,
+                                                 prepareRRset(name,
+                                                              state.rrset_,
+                                                              false,
+                                                              options)));
+                    }
+                    if (state.zonecut_node_ != NULL) {
+                        LOG_DEBUG(logger, DBG_TRACE_DATA,
+                                  DATASRC_MEM_DELEG_FOUND).
+                            arg(state.rrset_->getName());
+                        return (createFindResult(DELEGATION,
+                                                 prepareRRset(name,
+                                                              state.rrset_,
+                                                              false,
+                                                              options)));
+                    }
+
+                    // If the RBTree search stopped at a node for a super
+                    // domain of the search name, it means the search name
+                    // exists in the zone but is empty.  Treat it as NXRRSET.
                     if (node_path.getLastComparisonResult().getRelation() ==
-                        NameComparisonResult::COMMONANCESTOR && node_path.
-                        getLastComparisonResult().getCommonLabels() > 1) {
+                        NameComparisonResult::SUPERDOMAIN) {
                         LOG_DEBUG(logger, DBG_TRACE_DATA,
-                                     DATASRC_MEM_WILDCARD_CANCEL).arg(name);
-                        return (createFindResult(NXDOMAIN, ConstRRsetPtr(),
-                                                 false));
+                                  DATASRC_MEM_SUPER_STOP).arg(name);
+                        return (createFindResult(NXRRSET, ConstRRsetPtr()));
                     }
-                    const Name wildcard(Name("*").concatenate(
-                        node_path.getAbsoluteName()));
-                    DomainTree::Result result =
-                        zone_data_->domains_.find(wildcard, &node);
-                    /*
-                     * Otherwise, why would the DOMAINFLAG_WILD be there if
-                     * there was no wildcard under it?
-                     */
-                    assert(result == DomainTree::EXACTMATCH);
+
                     /*
-                     * We have the wildcard node now. Jump below the switch,
-                     * where handling of the common (exact-match) case is.
+                     * No redirection anywhere. Let's try if it is a wildcard.
                      *
-                     * However, rename it to the searched name.
+                     * The wildcard is checked after the empty non-terminal
+                     * domain case above, because if that one triggers, it
+                     * means we should not match according to 4.3.3 of RFC 1034
+                     * (the query name is known to exist).
                      */
-                    rename = true;
-                    break;
-                }
+                    if (node->getFlag(DOMAINFLAG_WILD)) {
+                        /* Should we cancel this match?
+                         *
+                         * If we compare with some node and get a common
+                         * ancestor, it might mean we are comparing with a
+                         * non-wildcard node.  In that case, we check which
+                         * part is common. If we have something in common that
+                         * lives below the node we got (the one above *), then
+                         * we should cancel the match according to section
+                         * 4.3.3 of RFC 1034 (as the name between the wildcard
+                         * domain and the query name is known to exist).
+                         *
+                         * Because the way the tree stores relative names, we
+                         * will have exactly one common label (the ".") in case
+                         * we have nothing common under the node we got and we
+                         * will get more common labels otherwise (yes, this
+                         * relies on the internal RBTree structure, which leaks
+                         * out through this little bit).
+                         *
+                         * If the empty non-terminal node actually exists in
+                         * the tree, then this cancellation is not needed,
+                         * because we will not get here at all.
+                         */
+                        if (node_path.getLastComparisonResult().getRelation() ==
+                            NameComparisonResult::COMMONANCESTOR && node_path.
+                            getLastComparisonResult().getCommonLabels() > 1) {
+                            LOG_DEBUG(logger, DBG_TRACE_DATA,
+                                      DATASRC_MEM_WILDCARD_CANCEL).arg(name);
+                            return (createFindResult(NXDOMAIN, ConstRRsetPtr(),
+                                                     false));
+                        }
+                        const Name wildcard(Name("*").concatenate(
+                            node_path.getAbsoluteName()));
+                        DomainTree::Result result =
+                            zone_data_->domains_.find(wildcard, &node);
+                        /*
+                         * Otherwise, why would the DOMAINFLAG_WILD be there if
+                         * there was no wildcard under it?
+                         */
+                        assert(result == DomainTree::EXACTMATCH);
+                        /*
+                         * We have the wildcard node now. Jump below the switch,
+                         * where handling of the common (exact-match) case is.
+                         *
+                         * However, rename it to the searched name.
+                         */
+                        rename = true;
+                        break;
+                    }
 
-                // fall through
-            case DomainTree::NOTFOUND:
-                LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_NOT_FOUND).
-                    arg(name);
-                return (createFindResult(NXDOMAIN, ConstRRsetPtr(), false));
-            case DomainTree::EXACTMATCH: // This one is OK, handle it
-                break;
-            default:
-                assert(0);
+                    // fall through
+                case DomainTree::NOTFOUND:
+                    LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_NOT_FOUND).
+                        arg(name);
+                    return (createFindResult(NXDOMAIN, ConstRRsetPtr(),
+                                             false));
+                case DomainTree::EXACTMATCH: // This one is OK, handle it
+                    break;
+                default:
+                    assert(0);
+            }
         }
         assert(node != NULL);
 
diff --git a/src/lib/datasrc/tests/memory_datasrc_unittest.cc b/src/lib/datasrc/tests/memory_datasrc_unittest.cc
index 9096a9e..e9bb212 100644
--- a/src/lib/datasrc/tests/memory_datasrc_unittest.cc
+++ b/src/lib/datasrc/tests/memory_datasrc_unittest.cc
@@ -2106,4 +2106,39 @@ TEST_F(InMemoryZoneFinderTest, loadAndFindNSEC3) {
     EXPECT_EQ(Name("q04jkcevqvmu85r014c7dkba38o0ji5r.example"),
               result3.next_proof->getName());
 }
+
+/**
+ * \brief Test searching at the origin.
+ *
+ * Check finding with FIND_AT_ORIGIN works ‒ returns the data under origin
+ * all the time.
+ */
+TEST_F(InMemoryZoneFinderTest, findAtOrigin) {
+    // Fill some data inside
+    // Now put all the data we have there. It should throw nothing
+    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
+    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_a_)));
+    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_aaaa_)));
+    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_a_)));
+
+    // No matter the qname, this should find the origin node.
+    findTest(origin_, RRType::NS(), ZoneFinder::SUCCESS, true, rr_ns_,
+             ZoneFinder::RESULT_DEFAULT, NULL, ZoneFinder::FIND_AT_ORIGIN);
+    findTest(rr_ns_a_->getName(), RRType::NS(), ZoneFinder::SUCCESS, true,
+             rr_ns_, ZoneFinder::RESULT_DEFAULT, NULL,
+             ZoneFinder::FIND_AT_ORIGIN);
+    EXPECT_NE(origin_, rr_ns_a_->getName());
+
+    // The findAll works the same
+    vector<ConstRRsetPtr> expected_rrsets;
+    expected_rrsets.push_back(rr_ns_);
+    expected_rrsets.push_back(rr_a_);
+    findAllTest(origin_, ZoneFinder::SUCCESS, expected_rrsets,
+                ZoneFinder::RESULT_DEFAULT, NULL, ConstRRsetPtr(),
+                ZoneFinder::FIND_AT_ORIGIN);
+    findAllTest(rr_ns_a_->getName(), ZoneFinder::SUCCESS, expected_rrsets,
+                ZoneFinder::RESULT_DEFAULT, NULL, ConstRRsetPtr(),
+                ZoneFinder::FIND_AT_ORIGIN);
+}
+
 }
diff --git a/src/lib/datasrc/zone.h b/src/lib/datasrc/zone.h
index 361a03a..46156ac 100644
--- a/src/lib/datasrc/zone.h
+++ b/src/lib/datasrc/zone.h
@@ -103,7 +103,14 @@ public:
                                 ///< (RRSIG, NSEC, etc.). The implementation
                                 ///< is allowed to include it even if it is
                                 ///< not set.
-        NO_WILDCARD = 4         ///< Do not try wildcard matching.
+        NO_WILDCARD = 4,        ///< Do not try wildcard matching.
+        FIND_AT_ORIGIN = 8      ///< Hint that the search is the origin.
+                                ///< Can be used for optimizations, but can
+                                ///< be safely ignored.
+                                ///< It is the caller's responsibility to
+                                ///< make sure the qname is actually the
+                                ///< origin, the behaviour is undefined
+                                ///< otherwise.
     };
 
 protected:



More information about the bind10-changes mailing list