Commit 650c6ce2 authored by Mukund Sivaraman's avatar Mukund Sivaraman
Browse files

Merge branch 'trac2850_2'

parents 69cdc5f7 7ad877ff
......@@ -891,6 +891,9 @@ if test X$use_shared_memory = Xyes -a "$BOOST_MAPPED_FILE_WOULDFAIL" = "yes"; th
AC_MSG_ERROR([Boost shared memory does not compile on this system. If you don't need it (most normal users won't) build without it by rerunning this script with --without-shared-memory; using a different compiler or a different version of Boost may also help.])
fi
AM_CONDITIONAL([USE_SHARED_MEMORY], [test x$use_shared_memory = xyes])
if test "x$use_shared_memory" = "xyes"; then
AC_DEFINE(USE_SHARED_MEMORY, 1, [Define to 1 if shared memory support is enabled])
fi
AC_SUBST(BOOST_MAPPED_FILE_CXXFLAG)
# Add some default CPP flags needed for Boost, identified by the AX macro.
......
......@@ -153,13 +153,13 @@ ConfigurableClientList::configure(const ConstElementPtr& config,
<< zname << "/" << rrclass_);
}
assert(load_action); // in this loop this should be always true
boost::scoped_ptr<memory::ZoneWriter> writer;
try {
writer.reset(new_data_sources.back().ztable_segment_->
getZoneWriter(load_action, zname, rrclass_));
writer->load();
writer->install();
writer->cleanup();
memory::ZoneWriter writer(
*new_data_sources.back().ztable_segment_,
load_action, zname, rrclass_);
writer.load();
writer.install();
writer.cleanup();
} catch (const ZoneLoaderException& e) {
LOG_ERROR(logger, DATASRC_LOAD_ZONE_ERROR)
.arg(zname).arg(rrclass_).arg(name).arg(e.what());
......@@ -348,8 +348,9 @@ ConfigurableClientList::getCachedZoneWriter(const Name& name) {
}
return (ZoneWriterPair(ZONE_SUCCESS,
ZoneWriterPtr(
result.info->ztable_segment_->
getZoneWriter(load_action, name, rrclass_))));
new memory::ZoneWriter(
*result.info->ztable_segment_,
load_action, name, rrclass_))));
}
// NOTE: This function is not tested, it would be complicated. However, the
......
......@@ -22,11 +22,15 @@ libdatasrc_memory_la_SOURCES += zone_table.h zone_table.cc
libdatasrc_memory_la_SOURCES += zone_finder.h zone_finder.cc
libdatasrc_memory_la_SOURCES += zone_table_segment.h zone_table_segment.cc
libdatasrc_memory_la_SOURCES += zone_table_segment_local.h zone_table_segment_local.cc
if USE_SHARED_MEMORY
libdatasrc_memory_la_SOURCES += zone_table_segment_mapped.h zone_table_segment_mapped.cc
endif
libdatasrc_memory_la_SOURCES += zone_data_updater.h zone_data_updater.cc
libdatasrc_memory_la_SOURCES += zone_data_loader.h zone_data_loader.cc
libdatasrc_memory_la_SOURCES += memory_client.h memory_client.cc
libdatasrc_memory_la_SOURCES += zone_writer.h
libdatasrc_memory_la_SOURCES += zone_writer_local.h zone_writer_local.cc
libdatasrc_memory_la_SOURCES += zone_writer.h zone_writer.cc
libdatasrc_memory_la_SOURCES += load_action.h
libdatasrc_memory_la_SOURCES += util_internal.h
......
......@@ -12,8 +12,14 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include "config.h"
#include <datasrc/memory/zone_table_segment.h>
#include <datasrc/memory/zone_table_segment_local.h>
#ifdef USE_SHARED_MEMORY
#include <datasrc/memory/zone_table_segment_mapped.h>
#endif
#include <datasrc/memory/zone_writer.h>
#include <string>
......@@ -30,6 +36,10 @@ ZoneTableSegment::create(const RRClass& rrclass, const std::string& type) {
// Until that it becomes a real issue we won't be too smart.
if (type == "local") {
return (new ZoneTableSegmentLocal(rrclass));
#ifdef USE_SHARED_MEMORY
} else if (type == "mapped") {
return (new ZoneTableSegmentMapped(rrclass));
#endif
}
isc_throw(UnknownSegmentType, "Zone table segment type not supported: "
<< type);
......
......@@ -40,8 +40,8 @@ namespace datasrc {
namespace memory {
class ZoneWriter;
/// \brief Exception thrown when unknown or unsupported type of zone table
/// segment is specified.
/// \brief Exception thrown when unknown or unsupported type of
/// ZoneTableSegment is asked to be created.
class UnknownSegmentType : public Exception {
public:
UnknownSegmentType(const char* file, size_t line, const char* what) :
......@@ -49,12 +49,36 @@ public:
{}
};
/// \brief Exception thrown when a \c reset() on a \c ZoneTableSegment
/// fails (due to various reasons). When this exception is thrown, a
/// strong exception safety guarantee is provided, and the
/// \c ZoneTableSegment is usable as before.
class ResetFailed : public isc::Exception {
public:
ResetFailed(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what)
{}
};
/// \brief Exception thrown when a \c reset() on a \c ZoneTableSegment
/// fails (due to various reasons), and it was not able to preserve the
/// state of the \c ZoneTableSegment. When this exception is thrown,
/// only basic exception safety guarantee is provided and the
/// \c ZoneTableSegment must be expected as cleared.
class ResetFailedAndSegmentCleared : public isc::Exception {
public:
ResetFailedAndSegmentCleared(const char* file, size_t line,
const char* what) :
isc::Exception(file, line, what)
{}
};
/// \brief Memory-management independent entry point that contains a
/// pointer to a zone table in memory.
///
/// An instance of this type lives inside a ZoneTableSegment
/// implementation. It contains an offset pointer to the zone table (a
/// map from domain names to zone locators) in memory.
/// An instance of this type lives inside a \c ZoneTableSegment
/// implementation. It contains an offset pointer to the \c ZoneTable (a
/// map from domain names to zone locators) in the \c ZoneTableSegment.
struct ZoneTableHeader {
public:
ZoneTableHeader(ZoneTable* zone_table) :
......@@ -74,14 +98,20 @@ private:
boost::interprocess::offset_ptr<ZoneTable> table_;
};
/// \brief Manages a ZoneTableHeader, an entry point into a table of
/// \brief Manages a \c ZoneTableHeader, an entry point into a table of
/// zones
///
/// This class specifies an interface for derived implementations which
/// return a pointer to an object of type ZoneTableHeader, an entry
/// return a pointer to an object of type \c ZoneTableHeader, an entry
/// point into a table of zones regardless of the underlying memory
/// management implementation. Derived classes would implement the
/// interface for specific memory-implementation behavior.
/// management implementation. Derived classes implement the interface
/// for the specific memory-implementation behavior.
///
/// Note: At some point in the future, methods such as \c reset(),
/// \c clear(), \c resetHeader(), \c getHeader(), \c isWritable(),
/// \c isUsable() may become non-virtual methods. Such a change should
/// not affect any code that uses this class, but please be aware of
/// such plans.
class ZoneTableSegment {
protected:
/// \brief Protected constructor
......@@ -89,24 +119,63 @@ protected:
/// An instance implementing this interface is expected to be
/// created by the factory method (\c create()), so this constructor
/// is protected.
ZoneTableSegment(isc::dns::RRClass)
ZoneTableSegment(const isc::dns::RRClass&)
{}
public:
/// \brief Destructor
virtual ~ZoneTableSegment() {}
/// \brief Return the ZoneTableHeader for the zone table segment.
/// \brief Return a string name for the \c ZoneTableSegment
/// implementation.
///
/// \throw None This method's implementations must be
/// exception-free.
virtual const std::string& getImplType() const = 0;
/// \brief Return the \c ZoneTableHeader for the zone table segment.
///
/// As long as \c isUsable() returns true, this method must always
/// succeed without throwing an exception. If \c isUsable() returns
/// false, a derived class implementation can throw
/// \c isc::InvalidOperation depending on its implementation
/// details. Applications are generally expected to call this
/// method only when \c isUsable() returns true (either by making
/// sure explicitly or by some other indirect means).
///
/// \throw isc::InvalidOperation may be thrown by some
/// implementations if this method is called without calling
/// \c reset() successfully first.
virtual ZoneTableHeader& getHeader() = 0;
/// \brief const version of \c getHeader().
/// \brief \c const version of \c getHeader().
///
/// See the non- \c const version for documentation.
virtual const ZoneTableHeader& getHeader() const = 0;
/// \brief Return the MemorySegment for the zone table segment.
///
/// \throw isc::InvalidOperation may be thrown by some
/// implementations if this method is called without calling
/// \c reset() successfully first.
virtual isc::util::MemorySegment& getMemorySegment() = 0;
/// \brief Create an instance depending on the memory segment model
/// \brief Return true if the segment is writable.
///
/// The user of the zone table segment will load or update zones
/// into the segment only for writable ones. The precise definition
/// of "writability" differs in different derived classes (see
/// derived class documentation). In general, however, the user
/// should only rely on this interface rather than assume a specific
/// definition for a specific type of segment.
///
/// This is a factory method to create a derived ZoneTableSegment
/// \throw None This method's implementations must be
/// exception-free.
virtual bool isWritable() const = 0;
/// \brief Create an instance depending on the requested memory
/// segment implementation type.
///
/// This is a factory method to create a derived \c ZoneTableSegment
/// object based on the \c config passed. The method returns a
/// dynamically-allocated object. The caller is responsible for
/// destroying it with \c ZoneTableSegment::destroy().
......@@ -115,33 +184,162 @@ public:
/// \c config is not known or not supported in this implementation.
///
/// \param rrclass The RR class of the zones to be maintained in the table.
/// \param type The memory segment type used for the zone table segment.
/// \return Returns a ZoneTableSegment object of the specified type.
/// \param type The memory segment type to be used.
/// \return Returns a \c ZoneTableSegment object of the specified type.
static ZoneTableSegment* create(const isc::dns::RRClass& rrclass,
const std::string& type);
/// \brief Destroy a ZoneTableSegment
/// \brief Destroy a \c ZoneTableSegment
///
/// This method destroys the passed ZoneTableSegment. It must be
/// passed a segment previously created by \c ZoneTableSegment::create().
/// This method destroys the passed \c ZoneTableSegment. It must be
/// passed a segment previously created by
/// \c ZoneTableSegment::create().
///
/// \param segment The segment to destroy.
static void destroy(ZoneTableSegment* segment);
/// \brief Create a zone write corresponding to this segment
/// \brief The mode using which to create a MemorySegment.
///
/// Here, a \c MemorySegment (see its class documentation) is an
/// interface to a storage area, and provides operations to allocate
/// and deallocate from that storage area, and also to look up
/// addresses in that area. The storage area can be a buffer in
/// memory, a file on disk, or some kind of shared memory depending
/// on the \c MemorySegment implementation being used. In every
/// case in the documentation below, when we mention \c
/// MemorySegment, we mean both the \c MemorySegment object which
/// interfaces to the storage area and the contents of the
/// associated storage area.
///
/// - CREATE: If the \c MemorySegment's storage area doesn't exist,
/// create it. If it exists, overwrite it with a new
/// storage area (which does not remember old data). In
/// both cases, create a \c MemorySegment for it in
/// read+write mode.
///
/// This creates a new write that can be used to update zones
/// inside this zone table segment.
/// - READ_WRITE: If the \c MemorySegment's storage area doesn't
/// exist, create it. If it exists, use the existing
/// storage area as-is (keeping the existing data
/// intact). In both cases, create a \c MemorySegment
/// for it in read+write mode.
///
/// - READ_ONLY: If the \c MemorySegment's storage area doesn't
/// exist, throw an exception. If it exists, create a
/// \c MemorySegment for it in read-only mode.
enum MemorySegmentOpenMode {
CREATE,
READ_WRITE,
READ_ONLY
};
/// \brief Close the current \c MemorySegment (if open) and open the
/// requested one.
///
/// When we talk about "opening" a \c MemorySegment, it means to
/// construct a usable \c MemorySegment object that interfaces to
/// the actual memory storage area. "Closing" is the opposite
/// operation of opening.
///
/// In case opening the new \c MemorySegment fails for some reason,
/// one of the following documented (further below) exceptions may
/// be thrown. In case failures occur, implementations of this
/// method must strictly provide the associated behavior as follows
/// and in the exception documentation below. Code that uses
/// \c ZoneTableSegment would depend on such assurances.
///
/// First, in case a \c ZoneTableSegment was reset successfully
/// before and is currently usable (\c isUsable() returns true), and
/// an invalid configuration is passed in \c params to \c reset(),
/// the isc::InvalidParameter exception must be thrown. In this
/// case, a strong exception safety guarantee must be provided, and
/// the \c ZoneTableSegment must be usable as before.
///
/// In case a \c ZoneTableSegment was reset successfully before and
/// is currently usable (\c isUsable() returns true), and the attempt
/// to reset to a different \c MemorySegment storage area fails,
/// the \c ResetFailed exception must be thrown. In this
/// case, a strong exception safety guarantee must be provided, and
/// the \c ZoneTableSegment must be usable as before.
///
/// In case a \c ZoneTableSegment was reset successfully before and
/// is currently usable (\c isUsable() returns true), and the attempt
/// to reset to the same \c MemorySegment storage area fails, the
/// \c ResetFailedAndSegmentCleared exception must be thrown. In
/// this case, only basic exception safety guarantee is provided and
/// the \c ZoneTableSegment must be expected as cleared.
///
/// In case a \c ZoneTableSegment was not reset successfully before
/// and is currently not usable (\c isUsable() returns false), and
/// the attempt to reset fails, the \c ResetFailed exception must be
/// thrown. In this unique case, a strong exception safety guarantee
/// is provided by default, as the \c ZoneTableSegment was clear
/// previously, and remains cleared.
///
/// In all other cases, \c ZoneTableSegment contents can be expected
/// as reset.
///
/// See \c MemorySegmentOpenMode for a definition of "storage area"
/// and the various modes in which a \c MemorySegment can be opened.
///
/// \c params should contain an implementation-defined
/// configuration. See the specific \c ZoneTableSegment
/// implementation class for details of what to pass in this
/// argument.
///
/// \throw isc::InvalidParameter if the configuration in \c params
/// has incorrect syntax, but there is a strong exception safety
/// guarantee and the \c ZoneTableSegment is usable or unusable as
/// before.
///
/// \throw ResetFailed if there was a problem in opening the new
/// memory store, but there is a strong exception safety guarantee
/// and the \c ZoneTableSegment is usable or unusable as before.
///
/// \throw ResetFailedAndSegmentCleared if there was a problem in
/// opening the new memory store, but there is only a basic
/// exception safety guarantee and the \c ZoneTableSegment is not
/// usable without a further successful \c reset().
///
/// \throw isc::NotImplemented Some implementations may choose to
/// not implement this method. In this case, there must be a strong
/// exception safety guarantee and the \c ZoneTableSegment is usable
/// or unusable as before.
///
/// \param mode The open mode (see the MemorySegmentOpenMode
/// documentation).
/// \param params An element containing implementation-specific
/// config (see the description).
virtual void reset(MemorySegmentOpenMode mode,
isc::data::ConstElementPtr params) = 0;
/// \brief Close the currently configured \c MemorySegment (if
/// open).
///
/// See the \c reset() method's documentation for a definition of
/// "open" and "close".
///
/// Implementations of this method should close any currently
/// configured \c MemorySegment and clear the `ZoneTableSegment` to
/// a freshly constructed state.
///
/// \throw isc::NotImplemented Some implementations may choose to
/// not implement this method. In this case, there must be a strong
/// exception safety guarantee and the \c ZoneTableSegment is usable
/// or unusable as before.
virtual void clear() = 0;
/// \brief Return true if the \c ZoneTableSegment has been
/// successfully \c reset().
///
/// Note that after calling \c clear(), this method will return
/// false until the segment is reset successfully again.
virtual bool isUsable() const = 0;
/// \brief Reset the table header address.
///
/// \param loadAction Callback to provide the actual data.
/// \param origin The origin of the zone to reload.
/// \param rrclass The class of the zone to reload.
/// \return New instance of a zone writer. The ownership is passed
/// onto the caller and the caller needs to \c delete it when
/// it's done with the writer.
virtual ZoneWriter* getZoneWriter(const LoadAction& load_action,
const dns::Name& origin,
const dns::RRClass& rrclass) = 0;
/// This method must recalculate the \c ZoneTableHeader address, so
/// that it is valid when requested using the \c getHeader() method.
virtual void resetHeader() = 0;
};
} // namespace memory
......
......@@ -13,7 +13,6 @@
// PERFORMANCE OF THIS SOFTWARE.
#include <datasrc/memory/zone_table_segment_local.h>
#include "zone_writer_local.h"
using namespace isc::dns;
using namespace isc::util;
......@@ -24,6 +23,7 @@ namespace memory {
ZoneTableSegmentLocal::ZoneTableSegmentLocal(const RRClass& rrclass) :
ZoneTableSegment(rrclass),
impl_type_("local"),
header_(ZoneTable::create(mem_sgmt_, rrclass))
{
}
......@@ -38,6 +38,33 @@ ZoneTableSegmentLocal::~ZoneTableSegmentLocal() {
assert(mem_sgmt_.allMemoryDeallocated());
}
const std::string&
ZoneTableSegmentLocal::getImplType() const {
return (impl_type_);
}
void
ZoneTableSegmentLocal::reset(MemorySegmentOpenMode,
isc::data::ConstElementPtr)
{
isc_throw(isc::NotImplemented,
"ZoneTableSegmentLocal::reset() is not implemented and "
"should not be used.");
}
void
ZoneTableSegmentLocal::clear()
{
isc_throw(isc::NotImplemented,
"ZoneTableSegmentLocal::clear() is not implemented and "
"should not be used.");
}
void
ZoneTableSegmentLocal::resetHeader() {
// This method does not have to do anything in this implementation.
}
// After more methods' definitions are added here, it would be a good
// idea to move getHeader() and getMemorySegment() definitions to the
// header file.
......@@ -56,14 +83,6 @@ ZoneTableSegmentLocal::getMemorySegment() {
return (mem_sgmt_);
}
ZoneWriter*
ZoneTableSegmentLocal::getZoneWriter(const LoadAction& load_action,
const dns::Name& name,
const dns::RRClass& rrclass)
{
return (new ZoneWriterLocal(this, load_action, name, rrclass));
}
} // namespace memory
} // namespace datasrc
} // namespace isc
......@@ -18,19 +18,22 @@
#include <datasrc/memory/zone_table_segment.h>
#include <util/memory_segment_local.h>
#include <string>
namespace isc {
namespace datasrc {
namespace memory {
/// \brief Local implementation of ZoneTableSegment class
/// \brief Local implementation of \c ZoneTableSegment class
///
/// This class specifies a concrete implementation for a
/// MemorySegmentLocal based ZoneTableSegment. Please see the
/// ZoneTableSegment class documentation for usage.
/// \c MemorySegmentLocal -based \c ZoneTableSegment. Please see the
/// \c ZoneTableSegment class documentation for usage.
class ZoneTableSegmentLocal : public ZoneTableSegment {
// This is so that ZoneTableSegmentLocal can be instantiated from
// ZoneTableSegment::create().
// This is so that \c ZoneTableSegmentLocal can be instantiated from
// \c ZoneTableSegment::create().
friend class ZoneTableSegment;
protected:
/// \brief Protected constructor
///
......@@ -38,26 +41,64 @@ protected:
/// (\c ZoneTableSegment::create()), so this constructor is
/// protected.
ZoneTableSegmentLocal(const isc::dns::RRClass& rrclass);
public:
/// \brief Destructor
virtual ~ZoneTableSegmentLocal();
/// \brief Return the ZoneTableHeader for the local zone table
/// segment implementation.
/// \brief Returns "local" as the implementation type.
virtual const std::string& getImplType() const;
/// \brief This method does not have to do anything in this
/// implementation. It has an empty definition.
virtual void resetHeader();
/// \brief Return the \c ZoneTableHeader for this local zone table
/// segment.
virtual ZoneTableHeader& getHeader();
/// \brief const version of \c getHeader().
/// \brief \c const version of \c getHeader().
virtual const ZoneTableHeader& getHeader() const;
/// \brief Return the MemorySegment for the local zone table segment
/// implementation (a MemorySegmentLocal instance).
/// \brief Return the \c MemorySegment for the local zone table
/// segment implementation (a \c MemorySegmentLocal instance).
virtual isc::util::MemorySegment& getMemorySegment();
/// \brief Concrete implementation of ZoneTableSegment::getZoneWriter
virtual ZoneWriter* getZoneWriter(const LoadAction& load_action,
const dns::Name& origin,
const dns::RRClass& rrclass);
/// \brief Return true if the segment is writable.
///
/// Local segments are always writable. This implementation always
/// returns true.
virtual bool isWritable() const {
return (true);
}
/// \brief This method is not implemented.
///
/// Resetting a local \c ZoneTableSegment is not supported at this
/// time.
///
/// \throw isc::NotImplemented
virtual void reset(MemorySegmentOpenMode mode,
isc::data::ConstElementPtr params);
/// \brief This method is not implemented.
///
/// Clearing a local \c ZoneTableSegment is not supported at this
/// time.
///
/// \throw isc::NotImplemented
virtual void clear();
/// \brief Return true if the segment is usable.
///
/// Local segments are always usable. This implementation always
/// returns true.
virtual bool isUsable() const {
return (true);
}
private:
std::string impl_type_;
isc::util::MemorySegmentLocal mem_sgmt_;
ZoneTableHeader header_;
};
......
// Copyright (C) 2013 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 <datasrc/memory/zone_table_segment_mapped.h>
#include <memory>
using namespace isc::data;
using namespace isc::dns;
using namespace isc::util;
namespace isc {
namespace datasrc {
namespace memory {
namespace { // unnamed namespace
// The name with which the zone table checksum is associated in the segment.
const char* const ZONE_TABLE_CHECKSUM_NAME = "zone_table_checksum";
// The name with which the zone table header is associated in the segment.
const char* const ZONE_TABLE_HEADER_NAME = "zone_table_header";
} // end of unnamed namespace
ZoneTableSegmentMapped::ZoneTableSegmentMapped(const RRClass& rrclass) :
ZoneTableSegment(rrclass),
impl_type_