// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // PERFORMANCE OF THIS SOFTWARE. #ifndef DATASRC_MEMORY_TREENODE_RRSET_H #define DATASRC_MEMORY_TREENODE_RRSET_H 1 #include #include #include #include #include #include #include #include #include #include #include #include namespace isc { namespace datasrc { namespace memory { /// \brief Special RRset for optimizing memory datasource requirement /// /// This is a derived class of \c dns::AbstractRRset intended to be used /// by the in-memory data source finder implementation. It is designed /// so performance sensitive operations will be lightweight; for example, /// (in the general case) the construction is just set up references to /// pre-loaded in-memory objects, not involving any dynamic memory allocation. /// Its \c toWire() method is also customized so it won't have to use /// the generic but expensive \c dns::RdataIterator. /// /// On the other hand, some other performance-insensitive methods could be /// even less efficient than the generic version. Those include \c getName(), /// \c toText(), and \c getRdataIterator() methods. /// /// \note Right now, the authoritative server's query processing still needs /// to use \c getRdataIterator() and \c getName() for relatively rare case /// operations. We should revise that part of the authoritative server /// implementation in the next phase in order to eliminate the bottleneck. /// /// Since this class is assumed to be instantiated only from the in-memory /// zone finder, which only returns immutable (const) \c RRset objects, /// we skip implementing non const virtual methods of this class. /// Unless the application intentionally breaks the constness or the class /// is abused outside of the in-memory data source implementation, this /// should be safe because such methods should never be called. /// /// Some other const member methods are still incomplete; if they are called /// it will result in an exception. In the expected usage of this class /// it should be safe, but we should eventually provide complete /// implementations of these methods. /// /// This class can internally maintain dynamically allocated resource. /// It would cause copying a class object complicated while objects of /// this class are not expected to be copyable in the usage, so it's /// explicitly defined non copyable. /// /// \note This class is exposed in this separate header file so that other /// part of the in-memory data source implementation and test code /// can refer to its definition, and only for that purpose. Otherwise this is /// essentially a private class of the in-memory data source implementation, /// and an application shouldn't directly refer to this class. class TreeNodeRRset : boost::noncopyable, public dns::AbstractRRset { public: /// \brief Normal case constructor. /// /// This class object is basically defined with a \c ZoneNode and /// \c RdataSet. The former determines the owner name of the RRset, /// and the latter provides the rest of the RRset parameters. /// Since the RR class is maintained outside of the \c ZoneData, /// it must be explicitly given as a constructor parameter. /// /// The \c RdataSet may or may not be associated with RRSIGs. It's /// fixed at the load time, but depending on the query context they /// may or may not be requested (and supposed to be visible to the /// caller). Since \c rdataset cannot be modified at the time of /// construction, a separate parameter (\c dnssec_ok) controls this /// policy. Any associated RRSIGs are visible if and only if \c dnssec_ok /// is true. If the RRset is not associated with RRSIGs, the value /// does not have any effect. /// /// In some rare cases \c rdataset may only consist of RRSIGs (when /// the zone contains an RRSIG that doesn't have covered RRsets). /// This class works for such cases, too. /// /// \throw none /// /// \param rrclass The RR class of the RRset. This must be consistent /// with the corresponding zone class. /// \param node The \c ZoneNode for the \c RRset. Must not be NULL. /// \param rdataset The \c RdataSet for the \c RRset. Must not be NULL. /// \param dnssec_ok Whether the RRSIGs for the RRset (if associated) /// should be visible to the caller. TreeNodeRRset(const dns::RRClass& rrclass, const ZoneNode* node, const RdataSet* rdataset, bool dnssec_ok) : node_(node), rdataset_(rdataset), rrsig_count_(rdataset_->getSigRdataCount()), rrclass_(rrclass), dnssec_ok_(dnssec_ok), name_(NULL), realname_(NULL), ttl_(NULL) {} /// \brief Constructor for wildcard-expanded owner name. /// /// This constructor is mostly the same as the other version, but takes /// an extra parameter, \c realname. It effectively overrides the owner /// name of the RRset; wherever the owner name is used (e.g., in the /// \c toWire() method), the specified name will be used instead of /// the name associated with \c node. /// /// The expected usage is \c node has a wildcard name (such as /// *.example.com), but this constructor does not enforce the assumption. /// /// \throw std::bad_alloc Memory allocation fails TreeNodeRRset(const dns::Name& realname, const dns::RRClass& rrclass, const ZoneNode* node, const RdataSet* rdataset, bool dnssec_ok) : node_(node), rdataset_(rdataset), rrsig_count_(rdataset_->getSigRdataCount()), rrclass_(rrclass), dnssec_ok_(dnssec_ok), name_(NULL), realname_(new dns::Name(realname)), ttl_(NULL) {} virtual ~TreeNodeRRset() { delete realname_; delete ttl_; delete name_; } virtual unsigned int getRdataCount() const { return (rdataset_->getRdataCount()); } virtual const dns::Name& getName() const; virtual const dns::RRClass& getClass() const { return (rrclass_); } virtual const dns::RRType& getType() const { return (rdataset_->type); } /// \brief Specialized version of \c getTTL() for \c TreeNodeRRset. virtual const dns::RRTTL& getTTL() const; /// \brief Specialized version of \c setName() for \c TreeNodeRRset. /// /// It throws \c isc::Unexpected unconditionally. virtual void setName(const dns::Name& name); /// \brief Specialized version of \c setName() for \c TreeNodeRRset. /// /// It throws \c isc::Unexpected unconditionally. virtual void setTTL(const dns::RRTTL& ttl); virtual std::string toText() const; virtual unsigned int toWire(dns::AbstractMessageRenderer& renderer) const; /// \brief Specialized version of \c toWire(buffer) for \c TreeNodeRRset. /// /// It throws \c isc::Unexpected unconditionally. virtual unsigned int toWire(util::OutputBuffer& buffer) const; /// \brief Specialized version of \c addRdata() for \c TreeNodeRRset. /// /// It throws \c isc::Unexpected unconditionally. virtual void addRdata(dns::rdata::ConstRdataPtr rdata); /// \brief Specialized version of \c addRdata() for \c TreeNodeRRset. /// /// It throws \c isc::Unexpected unconditionally. virtual void addRdata(const dns::rdata::Rdata& rdata); virtual dns::RdataIteratorPtr getRdataIterator() const; /// \brief Specialized version of \c getRRsig() for \c TreeNodeRRset. virtual dns::RRsetPtr getRRsig() const; virtual unsigned int getRRsigDataCount() const { return (dnssec_ok_ ? rrsig_count_ : 0); } /// /// \name Specialized version of RRsig related methods for /// \c TreeNodeRRset. /// /// These throw \c isc::Unexpected unconditionally. //// //@{ virtual void addRRsig(const dns::rdata::ConstRdataPtr& rdata); virtual void addRRsig(const dns::rdata::RdataPtr& rdata); virtual void addRRsig(const dns::AbstractRRset& sigs); virtual void addRRsig(const dns::ConstRRsetPtr& sigs); virtual void addRRsig(const dns::RRsetPtr& sigs); virtual void removeRRsig(); //@} /// \brief Specialized version of \c isSameKind() for \c TreeNodeRRset. /// /// As a kind of optimization, this implementation exploits the assumption /// of how \c TreeNodeRRset objects are created: They must be always /// created inside the in-memory data source finder implementation, /// and they are constructed with the \c realname parameter if and only /// if the corresponding query name is subject to wildcard substitution. /// /// So, if the given RRset is of \c TreeNodeRRset, and one and only one of /// of them has \c realname, they are considered to have different names. /// /// Also, this implementation does not compare RR classes explicitly; /// if two \c TreeNodeRRset objects belong to different RR classes, /// they should belong to different zone trees (according to the assumption /// of how the zone data are built), and therefore they cannot be at /// same zone node. So it's sufficient to compare the (address of the) /// node; if they are different they cannot be of the same kind. virtual bool isSameKind(const dns::AbstractRRset& abs_other) const; private: dns::RdataIteratorPtr getSigRdataIterator() const; // Common backend for getRdataIterator() and getSigRdataIterator() dns::RdataIteratorPtr getRdataIteratorInternal(bool is_rrsig, size_t count) const; // Return \c LabelSequence for the owner name regardless of how this /// class is constructed (with or without 'realname') dns::LabelSequence getOwnerLabels( uint8_t labels_buf[dns::LabelSequence::MAX_SERIALIZED_LENGTH]) const { if (realname_ != NULL) { return (dns::LabelSequence(*realname_)); } return (node_->getAbsoluteLabels(labels_buf)); } const ZoneNode* node_; const RdataSet* rdataset_; const size_t rrsig_count_; const dns::RRClass rrclass_; const bool dnssec_ok_; mutable dns::Name* name_; const dns::Name* const realname_; mutable dns::RRTTL* ttl_; }; typedef boost::shared_ptr TreeNodeRRsetPtr; } // namespace memory } // namespace datasrc } // namespace isc #endif // DATASRC_MEMORY_TREENODE_RRSET_H // Local Variables: // mode: c++ // End: