Commit b372a33a authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[master] Merge branch 'trac2098'

parents b31ee711 83a40074
......@@ -12,6 +12,7 @@ noinst_LTLIBRARIES = libdatasrc_memory.la
libdatasrc_memory_la_SOURCES = domaintree.h
libdatasrc_memory_la_SOURCES += rdataset.h rdataset.cc
libdatasrc_memory_la_SOURCES += treenode_rrset.h treenode_rrset.cc
libdatasrc_memory_la_SOURCES += rdata_serialization.h rdata_serialization.cc
libdatasrc_memory_la_SOURCES += zone_data.h zone_data.cc
libdatasrc_memory_la_SOURCES += segment_object_holder.h
......
......@@ -9,10 +9,13 @@ endif
CLEANFILES = *.gcno *.gcda
noinst_PROGRAMS = rdata_reader_bench
noinst_PROGRAMS = rdata_reader_bench rrset_render_bench
rdata_reader_bench_SOURCES = rdata_reader_bench.cc
rdata_reader_bench_LDADD = $(top_builddir)/src/lib/datasrc/memory/libdatasrc_memory.la
rdata_reader_bench_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
rdata_reader_bench_LDADD += $(top_builddir)/src/lib/dns/libb10-dns++.la
rrset_render_bench_SOURCES = rrset_render_bench.cc
rrset_render_bench_LDADD = $(top_builddir)/src/lib/datasrc/memory/libdatasrc_memory.la
rrset_render_bench_LDADD += $(top_builddir)/src/lib/dns/libb10-dns++.la
// 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.
#include <bench/benchmark.h>
#include <util/buffer.h>
#include <util/memory_segment_local.h>
#include <dns/name.h>
#include <dns/messagerenderer.h>
#include <dns/rrset.h>
#include <dns/rrclass.h>
#include <dns/masterload.h>
#include <datasrc/memory/rdata_serialization.h>
#include <datasrc/memory/rdataset.h>
#include <datasrc/memory/treenode_rrset.h>
#include <datasrc/memory/zone_data.h>
#include <boost/bind.hpp>
#include <cassert>
#include <vector>
#include <sstream>
#include <unistd.h>
using std::vector;
using namespace isc::bench;
using namespace isc::datasrc::memory;
using namespace isc::dns;
namespace {
// A simple benchmark just repeating rendering a given set of RRsets.
class RRsetRenderBenchMark {
public:
RRsetRenderBenchMark(const vector<ConstRRsetPtr>& rrsets,
MessageRenderer& renderer) :
rrsets_(rrsets), renderer_(renderer)
{}
unsigned int run() {
renderer_.clear();
vector<ConstRRsetPtr>::const_iterator it;
const vector<ConstRRsetPtr>::const_iterator it_end = rrsets_.end();
for (it = rrsets_.begin(); it != it_end; ++it) {
(*it)->toWire(renderer_);
}
return (1);
}
private:
const vector<ConstRRsetPtr>& rrsets_;
MessageRenderer& renderer_;
};
// Builtin benchmark data. This is a list of RDATA (of RRs) in a response
// from a root server for the query for "www.example.com" (as of this
// implementation). We use a real world example to make the case practical.
const char* const delegation_rrsets_txt =
// AUTHORITY SECTION (NS)
"com. 172800 IN NS a.gtld-servers.net.\n"
"com. 172800 IN NS b.gtld-servers.net.\n"
"com. 172800 IN NS c.gtld-servers.net.\n"
"com. 172800 IN NS d.gtld-servers.net.\n"
"com. 172800 IN NS e.gtld-servers.net.\n"
"com. 172800 IN NS f.gtld-servers.net.\n"
"com. 172800 IN NS g.gtld-servers.net.\n"
"com. 172800 IN NS h.gtld-servers.net.\n"
"com. 172800 IN NS i.gtld-servers.net.\n"
"com. 172800 IN NS j.gtld-servers.net.\n"
"com. 172800 IN NS k.gtld-servers.net.\n"
"com. 172800 IN NS l.gtld-servers.net.\n"
"com. 172800 IN NS m.gtld-servers.net.\n"
// AUTHORITY SECTION (DS)
"com. 86400 IN DS 30909 8 2 "
"E2D3C916F6DEEAC73294E8268FB5885044A833FC5459588F4A9184CFC41A5766\n"
// AUTHORITY SECTION (RRSIG for DS)
"com. 86400 IN RRSIG DS 8 1 86400 20120822000000 20120814230000 50398 . "
"lcIpLRq4s91Fh1FihDXiDvVMMRqgy2jjlpiP4Y6sSjIrLue6Boi7xraj"
"Ouka34ubpl4KuIcopWe99LI/7Npvq0MYr9DaqfnX9dTW6Vc2C7/hKSsz"
"POYjraZZA3SCApgfNVzq+AscYlShi56f1vm7DQWw1eh1wHLdatidrQwNyDo=\n"
// ADDITIONAL SECTION
"a.gtld-servers.net. 172800 IN A 192.5.6.30\n"
"b.gtld-servers.net. 172800 IN A 192.33.14.30\n"
"c.gtld-servers.net. 172800 IN A 192.26.92.30\n"
"d.gtld-servers.net. 172800 IN A 192.31.80.30\n"
"e.gtld-servers.net. 172800 IN A 192.12.94.30\n"
"f.gtld-servers.net. 172800 IN A 192.35.51.30\n"
"g.gtld-servers.net. 172800 IN A 192.42.93.30\n"
"h.gtld-servers.net. 172800 IN A 192.54.112.30\n"
"i.gtld-servers.net. 172800 IN A 192.43.172.30\n"
"j.gtld-servers.net. 172800 IN A 192.48.79.30\n"
"k.gtld-servers.net. 172800 IN A 192.52.178.30\n"
"l.gtld-servers.net. 172800 IN A 192.41.162.30\n"
"m.gtld-servers.net. 172800 IN A 192.55.83.30\n"
"a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30\n"
"b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30";
// Likewise, it's a response from a root server for www.example.notexistent.
// An example that involves a few more RRSIGs.
const char* const nxdomain_rrsets_txt =
// AUTHORITY SECTION (NS)
". 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2012082901 1800 900 604800 86400\n"
". 86400 IN RRSIG SOA 8 0 86400 20120905000000 20120828230000 50398 . Wj6NgkA2TyJug9XfWYG/Cjh4d1JI99/Dv9S1TClbrhLdeMI4s9BEcBSA xdlPJN6L4uaupcYeEyRWGx3p0iq7VWFyjL4xy/+jXpUoHCgj0NlWa6eu C2litcnfcumTI97XJ5iod3ET+6vWnhwZQHDnz1fj4FuS8PPEJJ+Oy3M5 mcM=\n"
". 86400 IN NSEC ac. NS SOA RRSIG NSEC DNSKEY\n"
". 86400 IN RRSIG NSEC 8 0 86400 20120905000000 20120828230000 50398 . f8FEG1HzQtn/shZCdDgkB7TIpHAmH2hGlp5RubczukzD8XI3EGMVNoaf 2cUNPLpyhoBQkO1Rz+hANzI6Jkqq8PzhiQnLcW+y2Wl/BU2SaBQ2Otb2 5+VOOXux1veKaCZsRRU1VJnTUYguDayAgcS7BtB/rc7ez4nokkK98MA9 zcw=\n"
"no. 86400 IN NSEC np. NS RRSIG NSEC\n"
"no. 86400 IN RRSIG NSEC 8 1 86400 20120905000000 20120828230000 50398 . Z/E4hb6MMSpueGGjGoCWwnN2uKsQf88HPS1gbwVHBEhR+5eSn0BGqExs fQsjYL47SF/6pwMXjzmXCt8NPXXf9ImY/93GUuFL6j5OuL2MDIxt24MS u6hfxxiYTn+zF0dM8cn+UK5n1VEBB5JVJXf7FOr3OmaRLMD33Gl6yZJ/ l1E=";
void
usage() {
std::cerr << "Usage: rrset_render_bench [-n iterations]" << std::endl;
exit (1);
}
// Helper callback for masterLoad() used in main() to build test data.
void
setRRset(vector<ConstRRsetPtr>* rrsets, ConstRRsetPtr rrset) {
rrsets->push_back(rrset);
}
void
buildZone(isc::util::MemorySegmentLocal& mem_sgmt,
ZoneData* zone_data, const vector<ConstRRsetPtr>& rrsets,
vector<ConstRRsetPtr>& rrsets_build)
{
RdataEncoder encoder;
for (vector<ConstRRsetPtr>::const_iterator it = rrsets.begin();
it != rrsets.end();
++it)
{
ConstRRsetPtr rrset = *it;
ZoneNode* node;
zone_data->insertName(mem_sgmt, rrset->getName(), &node);
// For simplicity, we assume that if the current RRset has a next
// one that is of type RRSIG, that RRSIG should be associated with
// the current RRset (which should be the case for our test data).
ConstRRsetPtr sig_rrset;
if ((it + 1) != rrsets.end() &&
(*(it + 1))->getType() == RRType::RRSIG()) {
sig_rrset = *(++it);
assert(it != rrsets.end()); // to be safe, and silence cppcheck
}
RdataSet* rdataset =
RdataSet::create(mem_sgmt, encoder, rrset, sig_rrset);
rdataset->next = node->getData();
node->setData(rdataset);
rrsets_build.push_back(
ConstRRsetPtr(new TreeNodeRRset(rrset->getClass(), node, rdataset,
true)));
}
}
}
int
main(int argc, char* argv[]) {
int ch;
int iteration = 100000;
while ((ch = getopt(argc, argv, "n:")) != -1) {
switch (ch) {
case 'n':
iteration = atoi(optarg);
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argc != 0) {
usage();
}
// Build test data. rrsets will consist of a list of RRsets corresponding
// to the text defined above.
vector<ConstRRsetPtr> delegation_rrsets;
std::stringstream rrsets_stream(delegation_rrsets_txt);
masterLoad(rrsets_stream, Name::ROOT_NAME(), RRClass::IN(),
boost::bind(setRRset, &delegation_rrsets, _1));
vector<ConstRRsetPtr> nxdomain_rrsets;
std::stringstream rrsets_stream2(nxdomain_rrsets_txt);
masterLoad(rrsets_stream2, Name::ROOT_NAME(), RRClass::IN(),
boost::bind(setRRset, &nxdomain_rrsets, _1));
// Build in-memory zone using RRsets constructed above, storing
// the same set of RRsets as TreeNodeRRsets in separate vectors.
// This code below is not 100% exception safe (for simplicity), but at
// least it shouldn't leak memory in normal cases.
isc::util::MemorySegmentLocal mem_sgmt;
ZoneData* zone_data = ZoneData::create(mem_sgmt, Name::ROOT_NAME());
vector<ConstRRsetPtr> delegation_treenode_rrsets;
buildZone(mem_sgmt, zone_data, delegation_rrsets,
delegation_treenode_rrsets);
vector<ConstRRsetPtr> nxdomain_treenode_rrsets;
buildZone(mem_sgmt, zone_data, nxdomain_rrsets,
nxdomain_treenode_rrsets);
// The benchmark test uses a message renderer. Create it now and keep
// using it throughout the test.
isc::util::OutputBuffer buffer(4096); // 4096 should be sufficiently large
MessageRenderer renderer;
renderer.setBuffer(&buffer);
std::cout << "Benchmark for rendering basic RRsets (delegation)"
<< std::endl;
BenchMark<RRsetRenderBenchMark>(iteration,
RRsetRenderBenchMark(delegation_rrsets,
renderer));
std::cout << "Benchmark for rendering tree node RRsets (delegation)"
<< std::endl;
BenchMark<RRsetRenderBenchMark>(iteration,
RRsetRenderBenchMark(
delegation_treenode_rrsets, renderer));
std::cout << "Benchmark for rendering basic RRsets (nxdomain)"
<< std::endl;
BenchMark<RRsetRenderBenchMark>(iteration,
RRsetRenderBenchMark(nxdomain_rrsets,
renderer));
std::cout << "Benchmark for rendering tree node RRsets (nxdomain)"
<< std::endl;
BenchMark<RRsetRenderBenchMark>(iteration,
RRsetRenderBenchMark(
nxdomain_treenode_rrsets, renderer));
// Cleanup, and memory leak check
ZoneData::destroy(mem_sgmt, zone_data, RRClass::IN());
assert(mem_sgmt.allMemoryDeallocated());
return (0);
}
......@@ -226,6 +226,26 @@ public:
return (dns::LabelSequence(getLabelsData()));
}
/// \brief Return the absolute label sequence of the node.
///
/// This method returns the label sequence corresponding to the full
/// name of the node; i.e. the entire name as it appears in the zone.
///
/// It takes the (partial) name of the node itself, and extends it
/// with all upper nodes.
///
/// \note Care must be taken with the buffer that is used here; this
/// method overwrites its data, so it should not be associated with
/// any other LabelSequence during the lifetime of the LabelSequence
/// returned by this method. See LabelSequence::extend(), which is used
/// by this method.
///
/// \param buf A data buffer where the label sequence will be built.
/// The data in this buffer will be overwritten by this call.
/// \return A LabelSequence with the absolute name of this node.
isc::dns::LabelSequence getAbsoluteLabels(
uint8_t buf[isc::dns::LabelSequence::MAX_SERIALIZED_LENGTH]) const;
/// \brief Return the data stored in this node.
///
/// You should not delete the data, it is deleted when the tree is
......@@ -530,6 +550,21 @@ DomainTreeNode<T>::getUpperNode() const {
return (current->getParent());
}
template <typename T>
isc::dns::LabelSequence
DomainTreeNode<T>::getAbsoluteLabels(
uint8_t buf[isc::dns::LabelSequence::MAX_SERIALIZED_LENGTH]) const
{
isc::dns::LabelSequence result(getLabels(), buf);
const DomainTreeNode<T>* upper = getUpperNode();
while (upper != NULL) {
result.extend(upper->getLabels(), buf);
upper = upper->getUpperNode();
}
return (result);
}
template <typename T>
const DomainTreeNode<T>*
DomainTreeNode<T>::abstractSuccessor(
......
......@@ -248,6 +248,10 @@ public:
virtual void setTruncated() {}
virtual void setLengthLimit(size_t) {}
virtual void setCompressMode(CompressMode) {}
virtual void writeName(const LabelSequence&, bool) {
// We don't need this version of writeName
isc_throw(Unexpected, "unexpected version of writeName is called");
}
// Called for each domain name in the RDATA, from the RDATA's toWire()
// implementation.
......
......@@ -21,6 +21,7 @@ run_unittests_SOURCES = run_unittests.cc
run_unittests_SOURCES += rdata_serialization_unittest.cc
run_unittests_SOURCES += rdataset_unittest.cc
run_unittests_SOURCES += domaintree_unittest.cc
run_unittests_SOURCES += treenode_rrset_unittest.cc
run_unittests_SOURCES += zone_table_unittest.cc
run_unittests_SOURCES += zone_data_unittest.cc
run_unittests_SOURCES += memory_segment_test.h
......
......@@ -114,6 +114,7 @@ protected:
TestDomainTree& dtree_expose_empty_node;
TestDomainTreeNode* dtnode;
const TestDomainTreeNode* cdtnode;
uint8_t buf[LabelSequence::MAX_SERIALIZED_LENGTH];
};
TEST_F(DomainTreeTest, nodeCount) {
......@@ -470,6 +471,11 @@ TEST_F(DomainTreeTest, chainLevel) {
tree.find(node_name, &cdtnode, chain));
EXPECT_EQ(1, chain.getLevelCount());
// Check the name of the found node (should have '.' as both non-absolute
// and absolute name
EXPECT_EQ(".", cdtnode->getLabels().toText());
EXPECT_EQ(".", cdtnode->getAbsoluteLabels(buf).toText());
/*
* Now creating a possibly deepest tree with MAX_LABELS levels.
* it should look like:
......@@ -493,6 +499,12 @@ TEST_F(DomainTreeTest, chainLevel) {
EXPECT_EQ(TestDomainTree::EXACTMATCH,
tree.find(node_name, &cdtnode, found_chain));
EXPECT_EQ(i, found_chain.getLevelCount());
// The non-absolute name should only have the first label
EXPECT_EQ("a", cdtnode->getLabels().toText());
// But the absolute name should have all labels
EXPECT_EQ(node_name.toText(),
cdtnode->getAbsoluteLabels(buf).toText());
}
// Confirm the last inserted name has the possible maximum length with
......@@ -1039,4 +1051,44 @@ TEST_F(DomainTreeTest, root) {
root.find(Name("example.com"), &cdtnode));
EXPECT_EQ(dtnode, cdtnode);
}
TEST_F(DomainTreeTest, getAbsoluteLabels) {
// The full absolute names of the nodes in the tree
// with the addition of the explicit root node
const char* const domain_names[] = {
"c", "b", "a", "x.d.e.f", "z.d.e.f", "g.h", "i.g.h", "o.w.y.d.e.f",
"j.z.d.e.f", "p.w.y.d.e.f", "q.w.y.d.e.f", "k.g.h"};
// The names of the nodes themselves, as they end up in the tree
const char* const first_labels[] = {
"c", "b", "a", "x", "z", "g.h", "i", "o",
"j", "p", "q", "k"};
const int name_count = sizeof(domain_names) / sizeof(domain_names[0]);
for (int i = 0; i < name_count; ++i) {
EXPECT_EQ(TestDomainTree::EXACTMATCH, dtree.find(Name(domain_names[i]),
&cdtnode));
// First make sure the names themselves are not absolute
const LabelSequence ls(cdtnode->getLabels());
EXPECT_EQ(first_labels[i], ls.toText());
EXPECT_FALSE(ls.isAbsolute());
// Now check the absolute names
const LabelSequence abs_ls(cdtnode->getAbsoluteLabels(buf));
EXPECT_EQ(Name(domain_names[i]).toText(), abs_ls.toText());
EXPECT_TRUE(abs_ls.isAbsolute());
}
// Explicitly add and find a root node, to see that getAbsoluteLabels
// also works when getLabels() already returns an absolute LabelSequence
dtree.insert(mem_sgmt_, Name("."), &dtnode);
dtnode->setData(new int(1));
EXPECT_EQ(TestDomainTree::EXACTMATCH, dtree.find(Name("."), &cdtnode));
EXPECT_TRUE(cdtnode->getLabels().isAbsolute());
EXPECT_EQ(".", cdtnode->getLabels().toText());
EXPECT_TRUE(cdtnode->getAbsoluteLabels(buf).isAbsolute());
EXPECT_EQ(".", cdtnode->getAbsoluteLabels(buf).toText());
}
}
This diff is collapsed.
// 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.
#include <exceptions/exceptions.h>
#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 "treenode_rrset.h"
#include "rdata_serialization.h"
#include <boost/bind.hpp>
#include <cassert>
#include <string>
#include <vector>
using namespace isc::dns;
using namespace isc::dns::rdata;
namespace isc {
namespace datasrc {
namespace memory {
const Name&
TreeNodeRRset::getName() const {
if (realname_ != NULL) {
return (*realname_);
}
if (name_ == NULL) {
uint8_t labels_buf[LabelSequence::MAX_SERIALIZED_LENGTH];
const LabelSequence name_labels = getOwnerLabels(labels_buf);
size_t data_len;
const uint8_t* data = name_labels.getData(&data_len);
util::InputBuffer buffer(data, data_len);
name_ = new Name(buffer);
}
return (*name_);
}
const RRTTL&
TreeNodeRRset::getTTL() const {
isc_throw(Unexpected, "unexpected method called on TreeNodeRRset");
}
void
TreeNodeRRset::setName(const Name&) {
isc_throw(Unexpected, "unexpected method called on TreeNodeRRset");
}
void
TreeNodeRRset::setTTL(const RRTTL&) {
isc_throw(Unexpected, "unexpected method called on TreeNodeRRset");
}
std::string
TreeNodeRRset::toText() const {
// Create TTL from internal data
util::InputBuffer ttl_buffer(rdataset_->getTTLData(), sizeof(uint32_t));
const RRTTL ttl(ttl_buffer);
// Dump the main RRset, if not empty
std::string ret;
RRsetPtr tmp_rrset;
for (RdataIteratorPtr rit = getRdataIterator();
!rit->isLast();
rit->next())
{
if (!tmp_rrset) {
tmp_rrset = RRsetPtr(new RRset(getName(), rrclass_, getType(),
ttl));
}
tmp_rrset->addRdata(rit->getCurrent());
}
if (tmp_rrset) {
ret = tmp_rrset->toText();
}
// Dump any RRSIGs
tmp_rrset.reset();
for (RdataIteratorPtr rit = getSigRdataIterator();
!rit->isLast();
rit->next())
{
if (!tmp_rrset) {
tmp_rrset = RRsetPtr(new RRset(getName(), rrclass_,
RRType::RRSIG(), ttl));
}
tmp_rrset->addRdata(rit->getCurrent());
}
if (tmp_rrset) {
ret += tmp_rrset->toText();
}
return (ret);
}
namespace {
void
renderName(const LabelSequence& name_labels, RdataNameAttributes attr,
AbstractMessageRenderer* renderer)
{
renderer->writeName(name_labels, (attr & NAMEATTR_COMPRESSIBLE) != 0);
}
void
renderData(const void* data, size_t data_len,
AbstractMessageRenderer* renderer)
{
renderer->writeData(data, data_len);
}
// Common code logic for rendering a single (either main or RRSIG) RRset.
size_t
writeRRs(AbstractMessageRenderer& renderer, size_t rr_count,
const LabelSequence& name_labels, const RRType& rrtype,
const RRClass& rrclass, const void* ttl_data,
RdataReader& reader, bool (RdataReader::* rdata_iterate_fn)())
{
for (size_t i = 0; i < rr_count; ++i) {
const size_t pos0 = renderer.getLength();
// Name, type, class, TTL
renderer.writeName(name_labels, true);
rrtype.toWire(renderer);
rrclass.toWire(renderer);
renderer.writeData(ttl_data, sizeof(uint32_t));
// RDLEN and RDATA
const size_t pos = renderer.getLength();
renderer.skip(sizeof(uint16_t)); // leave the space for RDLENGTH
const bool rendered = (reader.*rdata_iterate_fn)();
assert(rendered == true);
renderer.writeUint16At(renderer.getLength() - pos - sizeof(uint16_t),
pos);
// Check if truncation would happen
if (renderer.getLength() > renderer.getLengthLimit()) {
renderer.trim(renderer.getLength() - pos0);
renderer.setTruncated();
return (i);
}
}
return (rr_count);
}
}
unsigned int
TreeNodeRRset::toWire(AbstractMessageRenderer& renderer) const {
RdataReader reader(rrclass_, rdataset_->type, rdataset_->getDataBuf(),
rdataset_->getRdataCount(), rrsig_count_,
boost::bind(renderName, _1, _2, &renderer),
boost::bind(renderData, _1, _2, &renderer));
// Get the owner name of the RRset in the form of LabelSequence.
uint8_t labels_buf[LabelSequence::MAX_SERIALIZED_LENGTH];
const LabelSequence name_labels = getOwnerLabels(labels_buf);