it compiles, but some tests currently fail.
libb10_datasrc_la_LIBADD += $(top_builddir)/src/lib/dns/libb10-dns++.la
libb10_datasrc_la_LIBADD += $(top_builddir)/src/lib/log/libb10-log.la
libb10_datasrc_la_LIBADD += $(top_builddir)/src/lib/cc/libb10-cc.la
+libb10_datasrc_la_LIBADD += $(builddir)/memory/libdatasrc_memory.la
libb10_datasrc_la_LIBADD += $(SQLITE_LIBS)
BUILT_SOURCES = datasrc_config.h datasrc_messages.h datasrc_messages.cc
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
+#include <util/memory_segment_local.h>
+
#include "client_list.h"
#include "client.h"
#include "factory.h"
-#include "memory_datasrc.h"
+#include "memory/memory_client.h"
#include "logger.h"
#include <dns/masterload.h>
using namespace isc::data;
using namespace isc::dns;
using namespace std;
+using isc::util::MemorySegment;
using boost::lexical_cast;
using boost::shared_ptr;
using boost::dynamic_pointer_cast;
+using isc::datasrc::memory::InMemoryClient;
namespace isc {
namespace datasrc {
ConfigurableClientList::DataSourceInfo::DataSourceInfo(
DataSourceClient* data_src_client,
- const DataSourceClientContainerPtr& container, bool has_cache) :
+ const DataSourceClientContainerPtr& container, bool has_cache,
+ const RRClass& rrclass, MemorySegment& mem_sgmt) :
data_src_client_(data_src_client),
container_(container)
{
if (has_cache) {
- cache_.reset(new InMemoryClient);
+ cache_.reset(new InMemoryClient(mem_sgmt, rrclass));
}
}
-ConfigurableClientList::DataSourceInfo::DataSourceInfo(bool has_cache) :
+ConfigurableClientList::DataSourceInfo::DataSourceInfo(
+ const RRClass& rrclass, MemorySegment& mem_sgmt, bool has_cache) :
data_src_client_(NULL)
{
if (has_cache) {
- cache_.reset(new InMemoryClient);
+ cache_.reset(new InMemoryClient(mem_sgmt, rrclass));
}
}
+ConfigurableClientList::ConfigurableClientList(const RRClass& rrclass) :
+ rrclass_(rrclass),
+ mem_sgmt_(new util::MemorySegmentLocal),
+ configuration_(new isc::data::ListElement),
+ allow_cache_(false)
+{}
+
void
ConfigurableClientList::configure(const ConstElementPtr& config,
bool allow_cache)
isc_throw(ConfigurationError, "The cache must be enabled "
"for the MasterFiles type");
}
- new_data_sources.push_back(DataSourceInfo(true));
+ new_data_sources.push_back(DataSourceInfo(rrclass_, *mem_sgmt_,
+ true));
} else {
// Ask the factory to create the data source for us
const DataSourcePair ds(this->getDataSourceClient(type,
paramConf));
// And put it into the vector
new_data_sources.push_back(DataSourceInfo(ds.first, ds.second,
- want_cache));
+ want_cache, rrclass_,
+ *mem_sgmt_));
}
if (want_cache) {
for (vector<string>::const_iterator it(zones_origins.begin());
it != zones_origins.end(); ++it) {
const Name origin(*it);
- shared_ptr<InMemoryZoneFinder>
- finder(new
- InMemoryZoneFinder(rrclass_, origin));
if (type == "MasterFiles") {
try {
- finder->load(paramConf->get(*it)->stringValue());
- cache->addZone(finder);
+ cache->load(origin,
+ paramConf->get(*it)->stringValue());
} catch (const isc::dns::MasterLoadError& mle) {
LOG_ERROR(logger, DATASRC_MASTERLOAD_ERROR)
.arg(mle.what());
isc_throw(isc::Unexpected, "Got NULL iterator "
"for zone " << origin);
}
- finder->load(*iterator);
- cache->addZone(finder);
+ cache->load(origin, *iterator);
}
}
}
}
// Try to convert the finder to in-memory one. If it is the cache,
// it should work.
- shared_ptr<InMemoryZoneFinder>
- finder(dynamic_pointer_cast<InMemoryZoneFinder>(result.finder));
- const DataSourceInfo* info(result.info);
// It is of a different type or there's no cache.
- if (!info->cache_ || !finder) {
+ if (!result.info->cache_) {
return (ZONE_NOT_CACHED);
}
- DataSourceClient* client(info->data_src_client_);
+ DataSourceClient* client(result.info->data_src_client_);
if (client) {
// Now do the final reload. If it does not exist in client,
// DataSourceError is thrown, which is exactly the result what we
if (!iterator) {
isc_throw(isc::Unexpected, "Null iterator from " << name);
}
- finder->load(*iterator);
+ result.info->cache_->load(name, *iterator);
} else {
// The MasterFiles special case
- const string filename(finder->getFileName());
+ const string filename(result.info->cache_->getFileName(name));
if (filename.empty()) {
isc_throw(isc::Unexpected, "Confused about missing both filename "
"and data source");
}
- finder->load(filename);
+ result.info->cache_->load(name, filename);
}
return (ZONE_RELOADED);
}
#ifndef DATASRC_CONTAINER_H
#define DATASRC_CONTAINER_H
+#include <util/memory_segment.h>
+
#include <dns/name.h>
#include <dns/rrclass.h>
#include <cc/data.h>
#include <vector>
#include <boost/shared_ptr.hpp>
+#include <boost/scoped_ptr.hpp>
#include <boost/noncopyable.hpp>
namespace isc {
class DataSourceClientContainer;
typedef boost::shared_ptr<DataSourceClientContainer>
DataSourceClientContainerPtr;
+
+// XXX: it's better to even hide the existence of the "memory" namespace.
+// We should probably consider pimpl for details of ConfigurableClientList
+// and hide real definitions except for itself and tests.
+namespace memory {
class InMemoryClient;
+}
/// \brief The list of data source clients.
///
/// \brief Constructor
///
/// \param rrclass For which class the list should work.
- ConfigurableClientList(const isc::dns::RRClass &rrclass) :
- rrclass_(rrclass),
- configuration_(new isc::data::ListElement),
- allow_cache_(false)
- {}
+ ConfigurableClientList(const isc::dns::RRClass& rrclass);
+
/// \brief Exception thrown when there's an error in configuration.
class ConfigurationError : public Exception {
public:
/// \todo The content yet to be defined.
struct DataSourceInfo {
// Plays a role of default constructor too (for vector)
- DataSourceInfo(bool has_cache = false);
+ DataSourceInfo(const dns::RRClass& rrclass,
+ util::MemorySegment& mem_sgmt,
+ bool has_cache = false);
DataSourceInfo(DataSourceClient* data_src_client,
const DataSourceClientContainerPtr& container,
- bool has_cache);
+ bool has_cache, const dns::RRClass& rrclass,
+ util::MemorySegment& mem_sgmt);
DataSourceClient* data_src_client_;
DataSourceClientContainerPtr container_;
- boost::shared_ptr<InMemoryClient> cache_;
+ boost::shared_ptr<memory::InMemoryClient> cache_;
};
/// \brief The collection of data sources.
typedef std::vector<DataSourceInfo> DataSources;
-protected:
- /// \brief The data sources held here.
- ///
- /// All our data sources are stored here. It is protected to let the
- /// tests in. You should consider it private if you ever want to
- /// derive this class (which is not really recommended anyway).
- DataSources data_sources_;
/// \brief Convenience type alias.
///
void findInternal(MutableResult& result, const dns::Name& name,
bool want_exact_match, bool want_finder) const;
const isc::dns::RRClass rrclass_;
+
+ /// \brief Memory segment for in-memory cache.
+ ///
+ /// Note that this must be placed before data_sources_ so it won't be
+ /// destroyed before the built objects in the destructor.
+ boost::scoped_ptr<util::MemorySegment> mem_sgmt_;
+
/// \brief Currently active configuration.
isc::data::ConstElementPtr configuration_;
+
/// \brief The last set value of allow_cache.
bool allow_cache_;
+
+protected:
+ /// \brief The data sources held here.
+ ///
+ /// All our data sources are stored here. It is protected to let the
+ /// tests in. You should consider it private if you ever want to
+ /// derive this class (which is not really recommended anyway).
+ DataSources data_sources_;
};
} // namespace datasrc
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
+#include <util/memory_segment_local.h>
+
#include <datasrc/client_list.h>
#include <datasrc/client.h>
#include <datasrc/iterator.h>
#include <datasrc/data_source.h>
-#include <datasrc/memory_datasrc.h>
+#include <datasrc/memory/memory_client.h>
+#include <datasrc/memory/zone_finder.h>
#include <dns/rrclass.h>
#include <dns/rrttl.h>
#include <fstream>
using namespace isc::datasrc;
+using isc::datasrc::memory::InMemoryClient;
+using isc::datasrc::memory::InMemoryZoneFinder;
using namespace isc::data;
using namespace isc::dns;
using namespace boost;
class ListTest : public ::testing::Test {
public:
ListTest() :
+ rrclass_(RRClass::IN()),
// The empty list corresponds to a list with no elements inside
- list_(new TestedList(RRClass::IN())),
+ list_(new TestedList(rrclass_)),
config_elem_(Element::fromJSON("["
"{"
" \"type\": \"test_type\","
shared_ptr<MockDataSourceClient>
ds(new MockDataSourceClient(ds_zones[i]));
ds_.push_back(ds);
- ds_info_.push_back(ConfigurableClientList::DataSourceInfo(ds.get(),
- DataSourceClientContainerPtr(), false));
+ ds_info_.push_back(ConfigurableClientList::DataSourceInfo(
+ ds.get(), DataSourceClientContainerPtr(),
+ false, rrclass_, mem_sgmt_));
}
}
void prepareCache(size_t index, const Name& zone, bool prefill = false) {
- const shared_ptr<InMemoryClient> cache(new InMemoryClient());
- const shared_ptr<InMemoryZoneFinder>
- finder(new InMemoryZoneFinder(RRClass::IN(), zone));
+ const shared_ptr<InMemoryClient> cache(new InMemoryClient(mem_sgmt_,
+ rrclass_));
if (prefill) {
RRsetPtr soa(new RRset(zone, RRClass::IN(), RRType::SOA(),
RRTTL(3600)));
soa->addRdata(rdata::generic::SOA(Name::ROOT_NAME(),
Name::ROOT_NAME(),
0, 0, 0, 0, 0));
- finder->add(soa);
+ cache->add(zone, soa);
}
// If we don't do prefill, we leave the zone empty. This way,
// we can check when it was reloaded.
- cache->addZone(finder);
list_->getDataSources()[index].cache_ = cache;
}
// Check the positive result is as we expect it.
EXPECT_EQ(cache, list_->getDataSources()[index].cache_ !=
shared_ptr<InMemoryClient>());
}
+ const RRClass rrclass_;
+ isc::util::MemorySegmentLocal mem_sgmt_;
shared_ptr<TestedList> list_;
const ClientList::FindResult negative_result_;
vector<shared_ptr<MockDataSourceClient> > ds_;
// Test we can reload a zone
TEST_F(ListTest, reloadSuccess) {
list_->configure(config_elem_zones_, true);
- Name name("example.org");
+ const Name name("example.org");
prepareCache(0, name);
// Not there yet. It would be NXDOMAIN, but it is in apex and
// it returns NXRRSET instead.
// The cache is not enabled. The load should be rejected.
TEST_F(ListTest, reloadNotEnabled) {
list_->configure(config_elem_zones_, false);
- Name name("example.org");
+ const Name name("example.org");
// We put the cache in even when not enabled. This won't confuse the thing.
prepareCache(0, name);
// Not there yet. It would be NXDOMAIN, but it is in apex and
// Test several cases when the zone does not exist
TEST_F(ListTest, reloadNoSuchZone) {
list_->configure(config_elem_zones_, true);
- Name name("example.org");
+ const Name name("example.org");
// We put the cache in even when not enabled. This won't confuse the
// reload method, as that one looks at the real state of things, not
// at the configuration.
// the underlying data source when we want to reload it
TEST_F(ListTest, reloadZoneGone) {
list_->configure(config_elem_, true);
- Name name("example.org");
+ const Name name("example.org");
// We put in a cache for non-existant zone. This emulates being loaded
// and then the zone disappearing. We prefill the cache, so we can check
// it.
// The underlying data source throws. Check we don't modify the state.
TEST_F(ListTest, reloadZoneThrow) {
list_->configure(config_elem_zones_, true);
- Name name("noiter.org");
+ const Name name("noiter.org");
prepareCache(0, name, true);
// The zone contains stuff now
EXPECT_EQ(ZoneFinder::SUCCESS,
TEST_F(ListTest, reloadNullIterator) {
list_->configure(config_elem_zones_, true);
- Name name("null.org");
+ const Name name("null.org");
prepareCache(0, name, true);
// The zone contains stuff now
EXPECT_EQ(ZoneFinder::SUCCESS,