Commit c645605f authored by Mukund Sivaraman's avatar Mukund Sivaraman
Browse files

[2432] Add RRsetCollectionBase, and an implementation of RRsetCollection

parent ff7903d2
......@@ -127,6 +127,8 @@ libb10_dns___la_SOURCES += tsigrecord.h tsigrecord.cc
libb10_dns___la_SOURCES += character_string.h character_string.cc
libb10_dns___la_SOURCES += master_loader_callbacks.h master_loader_callbacks.cc
libb10_dns___la_SOURCES += master_loader.h
libb10_dns___la_SOURCES += rrset_collection_base.h rrset_collection_base.cc
libb10_dns___la_SOURCES += rrset_collection.h rrset_collection.cc
libb10_dns___la_SOURCES += rdata/generic/detail/char_string.h
libb10_dns___la_SOURCES += rdata/generic/detail/char_string.cc
libb10_dns___la_SOURCES += rdata/generic/detail/nsec_bitmap.h
......
// 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 <dns/rrset_collection.h>
#include <dns/master_loader_callbacks.h>
#include <dns/master_loader.h>
#include <boost/bind.hpp>
namespace isc {
namespace dns {
void
RRsetCollection::loaderCallback(const std::string&, size_t, const std::string&)
{
// We just ignore errors and warnings.
}
void
RRsetCollection::addRRset(const Name& name, const RRClass& rrclass,
const RRType& rrtype, const RRTTL& rrttl,
const rdata::RdataPtr& data)
{
RRsetPtr rrset(new BasicRRset(name, rrclass, rrtype, rrttl));
rrset->addRdata(data);
addRRset(rrset);
}
void
RRsetCollection::addRRset(RRsetPtr rrset) {
const CollectionKey key(rrset->getName(), rrset->getType());
rrsets_.insert(std::pair<CollectionKey, RRsetPtr>(key, rrset));
}
RRsetCollection::RRsetCollection(const char* filename, const Name& origin,
const RRClass& rrclass)
{
MasterLoaderCallbacks callbacks
(boost::bind(&RRsetCollection::loaderCallback, this, _1, _2, _3),
boost::bind(&RRsetCollection::loaderCallback, this, _1, _2, _3));
MasterLoader loader(filename, origin, rrclass, callbacks,
boost::bind(&RRsetCollection::addRRset,
this, _1, _2, _3, _4, _5),
MasterLoader::DEFAULT);
loader.load();
}
const AbstractRRset*
RRsetCollection::find(const Name& name, const RRType& rrtype) const {
const CollectionKey key(name, rrtype);
CollectionMap::const_iterator it = rrsets_.find(key);
if (it != rrsets_.end()) {
return (&(*it->second));
}
return (NULL);
}
RRsetPtr
RRsetCollection::find(const Name& name, const RRClass&, const RRType& rrtype) {
const CollectionKey key(name, rrtype);
CollectionMap::iterator it = rrsets_.find(key);
if (it != rrsets_.end()) {
return (it->second);
}
return (RRsetPtr());
}
ConstRRsetPtr
RRsetCollection::find(const Name& name, const RRClass&,
const RRType& rrtype) const
{
const CollectionKey key(name, rrtype);
CollectionMap::const_iterator it = rrsets_.find(key);
if (it != rrsets_.end()) {
return (it->second);
}
return (ConstRRsetPtr());
}
void
RRsetCollection::removeRRset(const Name& name, const RRClass&,
const RRType& rrtype)
{
const CollectionKey key(name, rrtype);
rrsets_.erase(key);
}
RRsetCollectionBase::IterPtr
RRsetCollection::getBeginning() {
CollectionMap::iterator it = rrsets_.begin();
return (RRsetCollectionBase::IterPtr(new DnsIter(it)));
}
RRsetCollectionBase::IterPtr
RRsetCollection::getEnd() {
CollectionMap::iterator it = rrsets_.end();
return (RRsetCollectionBase::IterPtr(new DnsIter(it)));
}
} // end of namespace dns
} // end of namespace isc
// 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 RRSET_COLLECTION_H
#define RRSET_COLLECTION_H 1
#include <dns/rrset_collection_base.h>
#include <dns/rrclass.h>
#include <utility>
#include <map>
namespace isc {
namespace dns {
/// \brief libdns++ implementation of RRsetCollectionBase using an STL
/// container.
class RRsetCollection : public RRsetCollectionBase {
public:
/// \brief Constructor.
///
/// The \c origin and \c rrclass arguments are required for the zone
/// loading, but \c RRsetCollection itself does not do any
/// validation, and the collection of RRsets does not have to form a
/// valid zone. The constructor throws MasterLoaderError if there is
/// an error during loading.
///
/// \param filename Name of a file containing a collection of RRs in
/// the master file format (which may or may not form a valid zone).
RRsetCollection(const char* filename, const isc::dns::Name& origin,
const isc::dns::RRClass& rrclass);
/// \brief Add an RRset to the collection.
///
/// Does not do any validation whether \c rrset belongs to a
/// particular zone or not.
void addRRset(isc::dns::RRsetPtr rrset);
/// \brief Remove an RRset from the collection.
///
/// RRset(s) matching the \c name, \c rrclass and \c rrtype are
/// removed from the collection.
void removeRRset(const isc::dns::Name& name,
const isc::dns::RRClass& rrclass,
const isc::dns::RRType& rrtype);
/// \brief Find a matching RRset in the collection.
///
/// Returns the RRset in the collection that exactly matches the
/// given \c name and \c rrtype. If no matching RRset is found,
/// \c NULL is returned.
///
/// \param name The name of the RRset to search for.
/// \param rrtype The type of the RRset to search for.
/// \returns A pointer to the RRset if found, \c NULL otherwise.
virtual const isc::dns::AbstractRRset* find(const isc::dns::Name& name,
const isc::dns::RRType& rrtype)
const;
isc::dns::RRsetPtr find(const isc::dns::Name& name,
const isc::dns::RRClass& rrclass,
const isc::dns::RRType& rrtype);
isc::dns::ConstRRsetPtr find(const isc::dns::Name& name,
const isc::dns::RRClass& rrclass,
const isc::dns::RRType& rrtype) const;
private:
void addRRset(const isc::dns::Name& name, const isc::dns::RRClass& rrclass,
const isc::dns::RRType& rrtype, const isc::dns::RRTTL& rrttl,
const isc::dns::rdata::RdataPtr& data);
void loaderCallback(const std::string&, size_t, const std::string&);
typedef std::pair<isc::dns::Name, isc::dns::RRType> CollectionKey;
typedef std::map<CollectionKey, isc::dns::RRsetPtr> CollectionMap;
CollectionMap rrsets_;
protected:
class DnsIter : public RRsetCollectionBase::Iter {
public:
DnsIter(CollectionMap::iterator& iter) :
iter_(iter)
{}
virtual const isc::dns::AbstractRRset& getValue() {
isc::dns::RRsetPtr& rrset = iter_->second;
return (*rrset);
}
virtual IterPtr getNext() {
CollectionMap::iterator it = iter_;
it++;
return (RRsetCollectionBase::IterPtr(new DnsIter(it)));
}
virtual bool equals(Iter& other) {
const DnsIter& other_real = dynamic_cast<DnsIter&>(other);
return (iter_ == other_real.iter_);
}
private:
CollectionMap::iterator iter_;
};
virtual RRsetCollectionBase::IterPtr getBeginning();
virtual RRsetCollectionBase::IterPtr getEnd();
};
} // end of namespace dns
} // end of namespace isc
#endif // RRSET_COLLECTION_H
// Local Variables:
// mode: c++
// End:
// 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 <dns/rrset_collection_base.h>
namespace isc {
namespace dns {
} // end of namespace dns
} // end of namespace isc
// 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 RRSET_COLLECTION_BASE_H
#define RRSET_COLLECTION_BASE_H 1
#include <dns/rrset.h>
#include <dns/name.h>
#include <boost/shared_ptr.hpp>
#include <iterator>
namespace isc {
namespace dns {
/// \brief Generic class to represent a set of RRsets.
///
/// This is a generic container and the stored set of RRsets does not
/// necessarily form a valid zone (e.g. there doesn't necessarily have
/// to be an SOA at the "origin"). Instead, it will be used to represent
/// a single zone for the purpose of zone loading/checking. It provides
/// a simple find() method to find an RRset for the given name and type
/// (and maybe class) and a way to iterate over all RRsets.
///
/// See \c RRsetCollection for a simple libdns++ implementation using an
/// STL container. libdatasrc will have another implementation.
class RRsetCollectionBase {
public:
/// \brief Find a matching RRset in the collection.
///
/// Returns the RRset in the collection that exactly matches the
/// given \c name and \c rrtype. If no matching RRset is found,
/// \c NULL is returned.
///
/// \param name The name of the RRset to search for.
/// \param rrtype The type of the RRset to search for.
/// \returns A pointer to the RRset if found, \c NULL otherwise.
virtual const isc::dns::AbstractRRset* find(const isc::dns::Name& name,
const isc::dns::RRType& rrtype)
const = 0;
protected:
class Iter; // forward declaration
typedef boost::shared_ptr<Iter> IterPtr;
class Iter {
public:
virtual const isc::dns::AbstractRRset& getValue() = 0;
virtual IterPtr getNext() = 0;
virtual bool equals(Iter& other) = 0;
};
virtual IterPtr getBeginning() = 0;
virtual IterPtr getEnd() = 0;
public:
class iterator : std::iterator<std::forward_iterator_tag,
const isc::dns::AbstractRRset>
{
public:
explicit iterator(IterPtr iter) :
iter_(iter)
{}
reference operator*() {
return (iter_->getValue());
}
iterator& operator++() {
iter_ = iter_->getNext();
return (*this);
}
iterator operator++(int) {
iterator tmp(iter_);
++*this;
return (tmp);
}
bool operator==(const iterator& other) const {
return (iter_->equals(*other.iter_));
}
bool operator!=(const iterator& other) const {
return (!iter_->equals(*other.iter_));
}
private:
IterPtr iter_;
};
iterator begin() {
return iterator(getBeginning());
}
iterator end() {
return iterator(getEnd());
}
};
} // end of namespace dns
} // end of namespace isc
#endif // RRSET_COLLECTION_BASE_H
// Local Variables:
// mode: c++
// End:
......@@ -75,6 +75,7 @@ run_unittests_SOURCES += tsigkey_unittest.cc
run_unittests_SOURCES += tsigrecord_unittest.cc
run_unittests_SOURCES += character_string_unittest.cc
run_unittests_SOURCES += master_loader_callbacks_test.cc
run_unittests_SOURCES += rrset_collection_unittest.cc
run_unittests_SOURCES += run_unittests.cc
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
# We shouldn't need to include BOTAN_LIBS here, but there
......
// 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 <dns/rrset_collection.h>
#include <dns/rrttl.h>
#include <dns/rdataclass.h>
#include <gtest/gtest.h>
using namespace isc::dns;
using namespace isc::dns::rdata;
using namespace std;
namespace {
class RRsetCollectionTest : public ::testing::Test {
public:
RRsetCollectionTest() :
rrclass("IN"),
origin("example.org"),
collection(TEST_DATA_SRCDIR "/example.org", origin, rrclass)
{}
const RRClass rrclass;
const Name origin;
RRsetCollection collection;
};
TEST_F(RRsetCollectionTest, findBase) {
// Test the find() that returns isc::dns::AbstractRRset*
const AbstractRRset* rrset = collection.find(Name("www.example.org"),
RRType::A());
EXPECT_NE(static_cast<AbstractRRset*>(NULL), rrset);
EXPECT_EQ(RRType::A(), rrset->getType());
EXPECT_EQ(RRTTL(3600), rrset->getTTL());
EXPECT_EQ(RRClass("IN"), rrset->getClass());
EXPECT_EQ(Name("www.example.org"), rrset->getName());
// foo.example.org doesn't exist
rrset = collection.find(Name("foo.example.org"), RRType::A());
EXPECT_EQ(static_cast<AbstractRRset*>(NULL), rrset);
// www.example.org exists, but not with MX
rrset = collection.find(Name("www.example.org"), RRType::MX());
EXPECT_EQ(static_cast<AbstractRRset*>(NULL), rrset);
// www.example.org exists, with AAAA
rrset = collection.find(Name("www.example.org"), RRType::AAAA());
EXPECT_NE(static_cast<AbstractRRset*>(NULL), rrset);
}
TEST_F(RRsetCollectionTest, findConst) {
// Test the find() that returns ConstRRsetPtr
const RRsetCollection& ccln = collection;
ConstRRsetPtr rrset = ccln.find(Name("www.example.org"), rrclass,
RRType::A());
EXPECT_TRUE(rrset);
EXPECT_EQ(RRType::A(), rrset->getType());
EXPECT_EQ(RRTTL(3600), rrset->getTTL());
EXPECT_EQ(RRClass("IN"), rrset->getClass());
EXPECT_EQ(Name("www.example.org"), rrset->getName());
// foo.example.org doesn't exist
rrset = ccln.find(Name("foo.example.org"), rrclass, RRType::A());
EXPECT_FALSE(rrset);
// www.example.org exists, but not with MX
rrset = ccln.find(Name("www.example.org"), rrclass, RRType::MX());
EXPECT_FALSE(rrset);
// www.example.org exists, with AAAA
rrset = ccln.find(Name("www.example.org"), rrclass, RRType::AAAA());
EXPECT_TRUE(rrset);
}
TEST_F(RRsetCollectionTest, find) {
// Test the find() that returns ConstRRsetPtr
RRsetPtr rrset = collection.find(Name("www.example.org"), rrclass,
RRType::A());
EXPECT_TRUE(rrset);
EXPECT_EQ(RRType::A(), rrset->getType());
EXPECT_EQ(RRTTL(3600), rrset->getTTL());
EXPECT_EQ(RRClass("IN"), rrset->getClass());
EXPECT_EQ(Name("www.example.org"), rrset->getName());
// foo.example.org doesn't exist
rrset = collection.find(Name("foo.example.org"), rrclass, RRType::A());
EXPECT_FALSE(rrset);
// www.example.org exists, but not with MX
rrset = collection.find(Name("www.example.org"), rrclass, RRType::MX());
EXPECT_FALSE(rrset);
// www.example.org exists, with AAAA
rrset = collection.find(Name("www.example.org"), rrclass, RRType::AAAA());
EXPECT_TRUE(rrset);
}
TEST_F(RRsetCollectionTest, addAndRemove) {
// foo.example.org/A doesn't exist
RRsetPtr rrset_found = collection.find(Name("foo.example.org"), rrclass,
RRType::A());
EXPECT_FALSE(rrset_found);
// Add foo.example.org/A
RRsetPtr rrset(new BasicRRset(Name("foo.example.org"), rrclass, RRType::A(),
RRTTL(7200)));
rrset->addRdata(in::A("192.0.2.1"));
collection.addRRset(rrset);
// foo.example.org/A should now exist
rrset_found = collection.find(Name("foo.example.org"), rrclass,
RRType::A());
EXPECT_TRUE(rrset_found);
EXPECT_EQ(RRType::A(), rrset_found->getType());
EXPECT_EQ(RRTTL(7200), rrset_found->getTTL());
EXPECT_EQ(RRClass("IN"), rrset_found->getClass());
EXPECT_EQ(Name("foo.example.org"), rrset_found->getName());
// Remove foo.example.org/A
collection.removeRRset(Name("foo.example.org"), rrclass, RRType::A());
// foo.example.org/A should not exist now
rrset_found = collection.find(Name("foo.example.org"), rrclass,
RRType::A());
EXPECT_FALSE(rrset_found);
}
TEST_F(RRsetCollectionTest, iteratorTest) {
RRsetCollection::iterator iter = collection.begin();
EXPECT_TRUE(iter != collection.end());
// Here, we just count the records and do some basic tests on them.
size_t count = 0;
for (RRsetCollection::iterator it = collection.begin();
it != collection.end(); ++it) {
++count;
const AbstractRRset& rrset = *it;
EXPECT_EQ(rrclass, rrset.getClass());
EXPECT_EQ(RRTTL(3600), rrset.getTTL());
}
// example.org master file has SOA, NS, A, AAAA
EXPECT_EQ(4, count);
}
} // namespace
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