};
}
-// 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) :
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 {
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
* 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);
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() &&
* 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());
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_) {