Browse Source

[1608] build shortcut links to rbtnodes for additional records.

no observable change yet.
JINMEI Tatuya 13 years ago
parent
commit
08ac200f2f
2 changed files with 83 additions and 7 deletions
  1. 77 7
      src/lib/datasrc/memory_datasrc.cc
  2. 6 0
      src/lib/datasrc/rbnode_rrset.h

+ 77 - 7
src/lib/datasrc/memory_datasrc.cc

@@ -108,15 +108,23 @@ struct ZoneData {
 };
 }
 
-// RBNodeRRset details
 namespace internal {
 
+struct AdditionalNodeInfo {
+    AdditionalNodeInfo(DomainNode* node) : node_(node) {}
+    DomainNode* node_;
+};
+
+//
+// RBNodeRRset details
+//
 struct RBNodeRRsetImpl {
 public:
     RBNodeRRsetImpl(const ConstRRsetPtr& rrset) : rrset_(rrset)
     {}
 
     ConstRRsetPtr rrset_;     ///< Underlying RRset
+    scoped_ptr<vector<AdditionalNodeInfo> > additionals_;
 };
 
 RBNodeRRset::RBNodeRRset(const ConstRRsetPtr& rrset) :
@@ -239,6 +247,14 @@ RBNodeRRset::getUnderlyingRRset() const {
     return (impl_->rrset_);
 }
 
+void
+RBNodeRRset::addAdditionalNode(const AdditionalNodeInfo& additional) {
+    if (!impl_->additionals_) {
+        impl_->additionals_.reset(new vector<AdditionalNodeInfo>);
+    }
+    impl_->additionals_->push_back(additional);
+}
+
 } // end of internal
 
 class InMemoryZoneFinder::Context_ : public ZoneFinder::Context {
@@ -253,6 +269,13 @@ public:
              const vector<ConstRRsetPtr> &all_set) :
         ZoneFinder::Context(finder, options, result, all_set)
     {}
+
+protected:
+    virtual void getAdditionalImpl(const vector<RRType>& requested_types,
+                                   vector<ConstRRsetPtr>& result)
+    {
+        ZoneFinder::Context::getAdditionalImpl(requested_types, result);
+    }
 };
 
 // Private data and hidden methods of InMemoryZoneFinder
@@ -565,7 +588,9 @@ struct InMemoryZoneFinder::InMemoryZoneFinderImpl {
      * access is without the impl_-> and it will get inlined anyway.
      */
     // Implementation of InMemoryZoneFinder::add
-    result::Result add(const ConstRRsetPtr& rawrrset, ZoneData& zone_data) {
+    result::Result add(const ConstRRsetPtr& rawrrset, ZoneData& zone_data,
+                       vector<internal::RBNodeRRset*>* need_additionals)
+    {
         // Sanitize input.  This will cause an exception to be thrown
         // if the input RRset is empty.
         addValidation(rawrrset);
@@ -634,6 +659,12 @@ struct InMemoryZoneFinder::InMemoryZoneFinderImpl {
                 node->setFlag(DomainNode::FLAG_CALLBACK);
             }
 
+            if (need_additionals != NULL &&
+                (rrset->getType() == RRType::NS() ||
+                 rrset->getType() == RRType::MX())) {
+                need_additionals->push_back(rrset.get());
+            }
+
             // If we've added NSEC3PARAM at zone origin, set up NSEC3 specific
             // data or check consistency with already set up parameters.
             if (rrset->getType() == RRType::NSEC3PARAM() &&
@@ -662,8 +693,10 @@ struct InMemoryZoneFinder::InMemoryZoneFinderImpl {
      * Same as above, but it checks the return value and if it already exists,
      * it throws.
      */
-    void addFromLoad(const ConstRRsetPtr& set, ZoneData* zone_data) {
-        switch (add(set, *zone_data)) {
+    void addFromLoad(const ConstRRsetPtr& set, ZoneData* zone_data,
+                     vector<internal::RBNodeRRset*>* need_additionals)
+    {
+        switch (add(set, *zone_data, need_additionals)) {
         case result::EXIST:
             LOG_ERROR(logger, DATASRC_MEM_DUP_RRSET).
                 arg(set->getName()).arg(set->getType());
@@ -1133,20 +1166,57 @@ InMemoryZoneFinder::findNSEC3(const Name& name, bool recursive) {
 
 result::Result
 InMemoryZoneFinder::add(const ConstRRsetPtr& rrset) {
-    return (impl_->add(rrset, *impl_->zone_data_));
+    return (impl_->add(rrset, *impl_->zone_data_, NULL));
+}
+
+namespace {
+// This should eventually be more generalized.
+const Name&
+getAdditionalName(RRType rrtype, const rdata::Rdata& rdata) {
+    if (rrtype == RRType::NS()) {
+        const generic::NS& ns = dynamic_cast<const generic::NS&>(rdata);
+        return (ns.getNSName());
+    } else if (rrtype == RRType::MX()) {
+        const generic::MX& mx = dynamic_cast<const generic::MX&>(rdata);
+        return (mx.getMXName());
+    }
+    // In our usage this shouldn't happen.
+    assert(false);
 }
 
+void
+addAdditional(internal::RBNodeRRset* rrset, ZoneData* zone_data) {
+    RdataIteratorPtr rdata_iterator = rrset->getRdataIterator();
+    for (; !rdata_iterator->isLast(); rdata_iterator->next()) {
+        // TODO: zone cut consideration, empty node case
+        RBTreeNodeChain<Domain> node_path;
+        DomainNode* node = NULL;
+        DomainTree::Result result =
+            zone_data->domains_.find<void*>(
+                getAdditionalName(rrset->getType(),
+                                  rdata_iterator->getCurrent()),
+                &node, node_path, NULL, NULL);
+        if (result == DomainTree::EXACTMATCH) {
+            rrset->addAdditionalNode(node);
+        }
+    }
+}
+}
 
 void
 InMemoryZoneFinder::load(const string& filename) {
     LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_MEM_LOAD).arg(getOrigin()).
         arg(filename);
-    // Load it into temporary zone data
+    // Load it into temporary zone data.
+    vector<internal::RBNodeRRset*> need_additionals;
     scoped_ptr<ZoneData> tmp(new ZoneData(getOrigin()));
 
     masterLoad(filename.c_str(), getOrigin(), getClass(),
                boost::bind(&InMemoryZoneFinderImpl::addFromLoad, impl_,
-                           _1, tmp.get()));
+                           _1, tmp.get(), &need_additionals));
+
+    for_each(need_additionals.begin(), need_additionals.end(),
+             boost::bind(addAdditional, _1, tmp.get()));
 
     // If the zone is NSEC3-signed, check if it has NSEC3PARAM
     if (tmp->nsec3_data_) {

+ 6 - 0
src/lib/datasrc/rbnode_rrset.h

@@ -35,6 +35,8 @@ namespace internal {
 /// so that the In-memory data source implementation can refer to it.
 struct RBNodeRRsetImpl;
 
+struct AdditionalNodeInfo;
+
 /// \brief Special RRset for optimizing memory datasource requirement
 ///
 /// To speed up the performance of the in-memory data source, at load time
@@ -148,6 +150,10 @@ public:
 
     virtual void removeRRsig();
 
+    /// \brief TBD
+    /// Note: this method is mostly private to the in-memory implementation.
+    void addAdditionalNode(const AdditionalNodeInfo& additional);
+
     /// \brief Return underlying RRset pointer
     ///
     /// ... mainly for testing.