summaryrefslogtreecommitdiffstats
path: root/src/lib/datasrc/memory/treenode_rrset.h
blob: 640c9721dc0b918461e346d67144e671eb8caa66 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
// 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 <util/buffer.h>

#include <dns/messagerenderer.h>
#include <dns/name.h>
#include <dns/rrclass.h>
#include <dns/rrtype.h>
#include <dns/rrttl.h>
#include <dns/rdata.h>
#include <dns/rrset.h>

#include <datasrc/memory/zone_data.h>
#include <datasrc/memory/rdataset.h>

#include <boost/noncopyable.hpp>

#include <string>

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_data_(rdataset->getTTLData()), ttl_(NULL)
    {}

    /// \brief Constructor with a specific TTL.
    ///
    /// This constructor is mostly the same as the normal version, but takes
    /// an extra parameter, \c ttl_data.  It's expected to point to a memory
    /// region at least for 32 bits, and the corresponding 32-bit data will
    /// be used as wire-format TTL value of the RRset, instead of the TTL
    /// associated with \c rdataset.
    ///
    /// It's the caller's responsibility to guarantee the memory region is
    /// valid and intact throughout the lifetime of the RRset.
    ///
    /// \throw None
    TreeNodeRRset(const dns::RRClass& rrclass, const ZoneNode* node,
                  const RdataSet* rdataset, bool dnssec_ok,
                  const void* ttl_data) :
        node_(node), rdataset_(rdataset),
        rrsig_count_(rdataset_->getSigRdataCount()), rrclass_(rrclass),
        dnssec_ok_(dnssec_ok), name_(NULL), realname_(NULL),
        ttl_data_(ttl_data), ttl_(NULL)
    {}

    /// \brief Constructor for wildcard-expanded owner name.
    ///
    /// This constructor is mostly the same as the normal 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_data_(rdataset->getTTLData()), 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 setTTL() 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_;
    const void* const ttl_data_;
    mutable dns::RRTTL* ttl_;
};

typedef boost::shared_ptr<TreeNodeRRset> TreeNodeRRsetPtr;

} // namespace memory
} // namespace datasrc
} // namespace isc

#endif // DATASRC_MEMORY_TREENODE_RRSET_H

// Local Variables:
// mode: c++
// End: