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

[2098] supportd rdata iterator

parent f16244fa
......@@ -24,6 +24,11 @@
#include <gtest/gtest.h>
#include <string>
#include <vector>
using std::vector;
using std::string;
using namespace isc::dns;
using namespace isc::dns::rdata;
using namespace isc::datasrc::memory;
......@@ -39,7 +44,8 @@ protected:
rrclass_(RRClass::IN()),
origin_name_("example.com"), www_name_("www.example.com"),
ns_rrset_(textToRRset("example.com. 3600 IN NS ns.example.com.")),
a_rrset_(textToRRset("www.example.com. 3600 IN A 192.0.2.1")),
a_rrset_(textToRRset("www.example.com. 3600 IN A 192.0.2.1\n"
"www.example.com. 3600 IN A 192.0.2.2")),
dname_rrset_(textToRRset("example.com. 3600 IN DNAME d.example.org.")),
rrsig_rrset_(textToRRset("www.example.com. 3600 IN RRSIG "
"A 5 2 3600 20120814220826 20120715220826 "
......@@ -90,14 +96,14 @@ TEST_F(TreeNodeRRsetTest, create) {
EXPECT_EQ(RRClass::IN(), rrset1.getClass());
EXPECT_EQ(RRType::A(), rrset1.getType());
EXPECT_EQ(www_name_, rrset1.getName());
EXPECT_EQ(1, rrset1.getRdataCount());
EXPECT_EQ(2, rrset1.getRdataCount());
EXPECT_EQ(1, rrset1.getRRsigDataCount());
const TreeNodeRRset rrset2(RRClass::IN(), www_node_, a_rdataset_, false);
EXPECT_EQ(RRClass::IN(), rrset2.getClass());
EXPECT_EQ(RRType::A(), rrset2.getType());
EXPECT_EQ(www_name_, rrset2.getName());
EXPECT_EQ(1, rrset2.getRdataCount());
EXPECT_EQ(2, rrset2.getRdataCount());
EXPECT_EQ(0, rrset2.getRRsigDataCount());
}
......@@ -167,4 +173,45 @@ TEST_F(TreeNodeRRsetTest, toWire) {
Name("example.org"), dname_rrset_, ConstRRsetPtr(),
false);
}
void
checkRdataIterator(const vector<string>& expected, RdataIteratorPtr rit) {
for (vector<string>::const_iterator it = expected.begin();
it != expected.end();
++it)
{
ASSERT_FALSE(rit->isLast());
EXPECT_EQ(*it, rit->getCurrent().toText());
rit->next();
}
// We should have reached the end of RDATA
EXPECT_TRUE(rit->isLast());
// move to the first RDATA again, and check the value.
rit->first();
EXPECT_EQ(expected[0], rit->getCurrent().toText());
}
TEST_F(TreeNodeRRsetTest, getRdataIterator) {
// This RRset should have 2 A RDATAs
vector<string> expected;
expected.push_back("192.0.2.1");
expected.push_back("192.0.2.2");
checkRdataIterator(expected,
TreeNodeRRset(rrclass_, www_node_, a_rdataset_, true).
getRdataIterator());
// The iterator shouldn't work different with or without RRSIG
checkRdataIterator(expected,
TreeNodeRRset(rrclass_, www_node_, a_rdataset_, false).
getRdataIterator());
// This RRset should have 1 NS RDATA (containing name field)
expected.clear();
expected.push_back("ns.example.com.");
checkRdataIterator(expected,
TreeNodeRRset(rrclass_, origin_node_, ns_rdataset_,
false).getRdataIterator());
}
}
......@@ -31,6 +31,7 @@
#include <cassert>
#include <string>
#include <vector>
using namespace isc::dns;
using namespace isc::dns::rdata;
......@@ -158,11 +159,67 @@ TreeNodeRRset::addRdata(const rdata::Rdata&) {
isc_throw(Unexpected, "unexpected method called on TreeNodeRRset");
}
namespace {
// In this namespace we define a set of helper stuff to implement the
// RdataIterator for the TreeNodeRRset. We should eventually optimize
// the code so that performance sensitive path won't require the iterator,
// so, at the moment, the implementation is straightforward, but less
// efficient one: It builds a vector of Rdata objects on construction,
// and its getCurrent() returns the stored data.
class TreeNodeRdataIterator : public RdataIterator {
public:
TreeNodeRdataIterator(const std::vector<ConstRdataPtr>& rdata_list) :
rdata_list_(rdata_list), rdata_it_(rdata_list_.begin())
{}
virtual void first() { rdata_it_ = rdata_list_.begin(); }
virtual void next() {
++rdata_it_;
}
virtual const rdata::Rdata& getCurrent() const {
return (**rdata_it_);
}
virtual bool isLast() const { return (rdata_it_ == rdata_list_.end()); }
private:
const std::vector<ConstRdataPtr> rdata_list_;
std::vector<ConstRdataPtr>::const_iterator rdata_it_;
};
void
renderNameToBuffer(const LabelSequence& name_labels, RdataNameAttributes,
util::OutputBuffer* buffer)
{
size_t data_len;
const uint8_t *data = name_labels.getData(&data_len);
buffer->writeData(data, data_len);
}
void
renderDataToBuffer(const void* data, size_t data_len,
util::OutputBuffer* buffer)
{
buffer->writeData(data, data_len);
}
}
// needed
RdataIteratorPtr
TreeNodeRRset::getRdataIterator() const {
isc_throw(Unexpected, "unexpected method called on TreeNodeRRset");
util::OutputBuffer buffer(0);
RdataReader reader(rrclass_, rdataset_->type, rdataset_->getDataBuf(),
rdataset_->getRdataCount(), rrsig_count_,
boost::bind(renderNameToBuffer, _1, _2, &buffer),
boost::bind(renderDataToBuffer, _1, _2, &buffer));
std::vector<ConstRdataPtr> rdata_list;
for (size_t i = 0; i < rdataset_->getRdataCount(); ++i) {
buffer.clear();
const bool rendered = reader.iterateRdata();
assert(rendered == true);
util::InputBuffer ib(buffer.getData(), buffer.getLength());
rdata_list.push_back(createRdata(rdataset_->type, rrclass_,
ib, ib.getLength()));
}
return (RdataIteratorPtr(new TreeNodeRdataIterator(rdata_list)));
}
RRsetPtr
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment