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

[2850] Add isUsable() and getImplType() methods

It would be better if these were static (to save on space and also to
use them inside ZoneTableSegment::create()), but unfortunately we cannot
make it virtual then. Another option would be to pass a static string
from ZoneTableSegment::create() onto the ZoneTableSegment constructor
and make it a non-virtual base class method.
parent 32d750c6
......@@ -68,7 +68,7 @@ public:
class ResetFailedAndSegmentCleared : public isc::Exception {
public:
ResetFailedAndSegmentCleared(const char* file, size_t line,
const char* what) :
const char* what) :
isc::Exception(file, line, what)
{}
};
......@@ -119,6 +119,10 @@ public:
/// \brief Destructor
virtual ~ZoneTableSegment() {}
/// \brief Return a string name for the ZoneTableSegment
/// implementation.
virtual const std::string& getImplType() const = 0;
/// \brief Return the ZoneTableHeader for the zone table segment.
///
/// \throw isc::InvalidOperation may be thrown by some
......@@ -263,6 +267,13 @@ public:
/// \throw none
virtual void clear() = 0;
/// \brief Return true if the memory segment has been successfully
/// \c reset().
///
/// Note that after calling \c clear(), this method will return
/// false until the segment is reset again.
virtual bool isUsable() const = 0;
/// \brief Reset the table header address.
virtual void resetHeader() = 0;
};
......
......@@ -23,6 +23,7 @@ namespace memory {
ZoneTableSegmentLocal::ZoneTableSegmentLocal(const RRClass& rrclass) :
ZoneTableSegment(rrclass),
impl_type_("local"),
header_(ZoneTable::create(mem_sgmt_, rrclass))
{
}
......@@ -37,6 +38,11 @@ ZoneTableSegmentLocal::~ZoneTableSegmentLocal() {
assert(mem_sgmt_.allMemoryDeallocated());
}
const std::string&
ZoneTableSegmentLocal::getImplType() const {
return (impl_type_);
}
void
ZoneTableSegmentLocal::reset(MemorySegmentOpenMode,
isc::data::ConstElementPtr)
......
......@@ -18,6 +18,8 @@
#include <datasrc/memory/zone_table_segment.h>
#include <util/memory_segment_local.h>
#include <string>
namespace isc {
namespace datasrc {
namespace memory {
......@@ -42,6 +44,9 @@ public:
/// \brief Destructor
virtual ~ZoneTableSegmentLocal();
/// \brief Returns "local" as the implementation type.
virtual const std::string& getImplType() const;
/// \brief This method has an empty definition.
virtual void resetHeader();
......@@ -75,7 +80,16 @@ public:
/// \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_;
};
......
......@@ -36,6 +36,7 @@ const char* const ZONE_TABLE_HEADER_NAME = "zone_table_header";
ZoneTableSegmentMapped::ZoneTableSegmentMapped(const RRClass& rrclass) :
ZoneTableSegment(rrclass),
impl_type_("mapped"),
rrclass_(rrclass),
cached_header_(NULL)
{
......@@ -45,6 +46,11 @@ ZoneTableSegmentMapped::~ZoneTableSegmentMapped() {
sync();
}
const std::string&
ZoneTableSegmentMapped::getImplType() const {
return (impl_type_);
}
bool
ZoneTableSegmentMapped::processChecksum(MemorySegmentMapped& segment,
bool create,
......@@ -325,7 +331,7 @@ ZoneTableSegmentMapped::resetHeader() {
// getHeader() has to work on const objects too. So we do it here
// now.
if (!mem_sgmt_) {
if (!isUsable()) {
isc_throw(isc::InvalidOperation,
"resetHeader() called without calling reset() first");
}
......@@ -344,7 +350,7 @@ ZoneTableSegmentMapped::resetHeader() {
template<typename T>
T*
ZoneTableSegmentMapped::getHeaderHelper() const {
if (!mem_sgmt_) {
if (!isUsable()) {
isc_throw(isc::InvalidOperation,
"getHeader() called without calling reset() first");
}
......@@ -365,16 +371,22 @@ ZoneTableSegmentMapped::getHeader() const {
MemorySegment&
ZoneTableSegmentMapped::getMemorySegment() {
if (!mem_sgmt_) {
if (!isUsable()) {
isc_throw(isc::InvalidOperation,
"getMemorySegment() called without calling reset() first");
}
return (*mem_sgmt_);
}
bool
ZoneTableSegmentMapped::isUsable() const {
// If mem_sgmt_ is not empty, then it is usable.
return (mem_sgmt_);
}
bool
ZoneTableSegmentMapped::isWritable() const {
if (!mem_sgmt_) {
if (!isUsable()) {
// If reset() was never performed for this segment, or if the
// most recent reset() had failed, then the segment is not
// writable.
......
......@@ -19,6 +19,7 @@
#include <util/memory_segment_mapped.h>
#include <boost/scoped_ptr.hpp>
#include <string>
namespace isc {
namespace datasrc {
......@@ -46,6 +47,9 @@ public:
/// \brief Destructor
virtual ~ZoneTableSegmentMapped();
/// \brief Returns "mapped" as the implementation type.
virtual const std::string& getImplType() const;
/// \brief Reset the table header address from the named address in
/// the mapped file.
virtual void resetHeader();
......@@ -111,6 +115,11 @@ public:
/// \brief Unmap the current file (if mapped).
virtual void clear();
/// \brief Return true if the segment is usable.
///
/// See the base class for the description.
virtual bool isUsable() const;
private:
void sync();
......@@ -126,6 +135,7 @@ private:
template<typename T> T* getHeaderHelper() const;
private:
std::string impl_type_;
isc::dns::RRClass rrclass_;
MemorySegmentOpenMode current_mode_;
std::string current_filename_;
......
......@@ -172,6 +172,10 @@ ZoneTableSegmentMappedTest::setupMappedFiles() {
ztable_segment_->clear();
}
TEST_F(ZoneTableSegmentMappedTest, getImplType) {
EXPECT_EQ("mapped", ztable_segment_->getImplType());
}
TEST_F(ZoneTableSegmentMappedTest, getHeaderUninitialized) {
// This should throw as we haven't called reset() yet.
EXPECT_THROW(ztable_segment_->getHeader(), isc::InvalidOperation);
......@@ -182,6 +186,12 @@ TEST_F(ZoneTableSegmentMappedTest, getMemorySegmentUninitialized) {
EXPECT_THROW(ztable_segment_->getMemorySegment(), isc::InvalidOperation);
}
TEST_F(ZoneTableSegmentMappedTest, isUsableUninitialized) {
// isUsable() must return false by default, when the segment has not
// been reset() yet.
EXPECT_FALSE(ztable_segment_->isUsable());
}
TEST_F(ZoneTableSegmentMappedTest, isWritableUninitialized) {
// isWritable() must return false by default, when the segment has
// not been reset() yet.
......@@ -252,13 +262,15 @@ TEST_F(ZoneTableSegmentMappedTest, reset) {
EXPECT_THROW(ztable_segment_->getHeader(), isc::InvalidOperation);
EXPECT_THROW(ztable_segment_->getMemorySegment(), isc::InvalidOperation);
// isWritable() must still return false, because the segment has not
// been successfully reset() yet.
// isUsable() and isWritable() must still return false, because the
// segment has not been successfully reset() yet.
EXPECT_FALSE(ztable_segment_->isUsable());
EXPECT_FALSE(ztable_segment_->isWritable());
// READ_WRITE mode must create the mapped file if it doesn't exist
// (and must not result in an exception).
ztable_segment_->reset(ZoneTableSegment::READ_WRITE, config_params_);
EXPECT_TRUE(ztable_segment_->isUsable());
EXPECT_TRUE(ztable_segment_->isWritable());
// The following method calls should no longer throw:
......@@ -268,12 +280,14 @@ TEST_F(ZoneTableSegmentMappedTest, reset) {
// Let's try to re-open the mapped file in READ_ONLY mode. It should
// not fail now.
ztable_segment_->reset(ZoneTableSegment::READ_ONLY, config_params_);
EXPECT_TRUE(ztable_segment_->isUsable());
EXPECT_FALSE(ztable_segment_->isWritable());
// Re-creating the mapped file should erase old data and should not
// trigger any exceptions inside reset() due to old data (such as
// named addresses).
ztable_segment_->reset(ZoneTableSegment::CREATE, config_params_);
EXPECT_TRUE(ztable_segment_->isUsable());
EXPECT_TRUE(ztable_segment_->isWritable());
// When we reset() with an invalid paramter and it fails, then the
......@@ -282,6 +296,7 @@ TEST_F(ZoneTableSegmentMappedTest, reset) {
ztable_segment_->reset(ZoneTableSegment::CREATE,
Element::fromJSON("{}"));
}, isc::InvalidParameter);
EXPECT_TRUE(ztable_segment_->isUsable());
EXPECT_TRUE(ztable_segment_->isWritable());
// The following should not throw.
EXPECT_NO_THROW(ztable_segment_->getHeader());
......@@ -291,6 +306,7 @@ TEST_F(ZoneTableSegmentMappedTest, reset) {
// would use existing named addresses. This actually re-opens the
// currently open map.
ztable_segment_->reset(ZoneTableSegment::READ_WRITE, config_params_);
EXPECT_TRUE(ztable_segment_->isUsable());
EXPECT_TRUE(ztable_segment_->isWritable());
}
......@@ -301,6 +317,7 @@ TEST_F(ZoneTableSegmentMappedTest, resetCreate) {
// Open the underlying mapped file in create mode.
ztable_segment_->reset(ZoneTableSegment::CREATE, config_params_);
ASSERT_TRUE(ztable_segment_->isUsable());
ASSERT_TRUE(ztable_segment_->isWritable());
// Add the data.
......@@ -327,6 +344,7 @@ TEST_F(ZoneTableSegmentMappedTest, resetReadWrite) {
// Open the underlying mapped file in read+write mode.
ztable_segment_->reset(ZoneTableSegment::READ_WRITE, config_params_);
ASSERT_TRUE(ztable_segment_->isUsable());
ASSERT_TRUE(ztable_segment_->isWritable());
// Add the data.
......@@ -353,6 +371,7 @@ TEST_F(ZoneTableSegmentMappedTest, resetReadOnly) {
// Open the underlying mapped file in read+write mode.
ztable_segment_->reset(ZoneTableSegment::READ_WRITE, config_params_);
ASSERT_TRUE(ztable_segment_->isUsable());
ASSERT_TRUE(ztable_segment_->isWritable());
// Add the data.
......@@ -389,6 +408,7 @@ TEST_F(ZoneTableSegmentMappedTest, clearUninitialized) {
// isWritable() must still return false, because the segment has not
// been successfully reset() yet.
EXPECT_FALSE(ztable_segment_->isUsable());
EXPECT_FALSE(ztable_segment_->isWritable());
}
......@@ -397,6 +417,7 @@ TEST_F(ZoneTableSegmentMappedTest, clear) {
// exist yet)
ztable_segment_->reset(ZoneTableSegment::READ_WRITE, config_params_);
EXPECT_TRUE(ztable_segment_->isUsable());
EXPECT_TRUE(ztable_segment_->isWritable());
// The following method calls should no longer throw:
EXPECT_NO_THROW(ztable_segment_->getHeader());
......@@ -405,6 +426,7 @@ TEST_F(ZoneTableSegmentMappedTest, clear) {
// Now, clear the segment.
ztable_segment_->clear();
EXPECT_FALSE(ztable_segment_->isUsable());
EXPECT_FALSE(ztable_segment_->isWritable());
// The following method calls should now throw.
EXPECT_THROW(ztable_segment_->getHeader(), isc::InvalidOperation);
......@@ -425,11 +447,13 @@ TEST_F(ZoneTableSegmentMappedTest, resetFailedCorruptedChecksum) {
corruptChecksum(*segment);
segment.reset();
// Opening mapped file 2 in read-write mode should fail
// Resetting to mapped file 2 in read-write mode should fail
EXPECT_THROW({
ztable_segment_->reset(ZoneTableSegment::READ_WRITE, config_params2_);
}, ResetFailed);
EXPECT_TRUE(ztable_segment_->isUsable());
EXPECT_TRUE(ztable_segment_->isWritable());
// Check for the old data in the segment to make sure it is still
// available and correct.
EXPECT_TRUE(verifyData(ztable_segment_->getMemorySegment()));
......@@ -449,11 +473,13 @@ TEST_F(ZoneTableSegmentMappedTest, resetFailedMissingChecksum) {
deleteChecksum(*segment);
segment.reset();
// Opening mapped file 2 in read-only mode should fail
// Resetting to mapped file 2 in read-only mode should fail
EXPECT_THROW({
ztable_segment_->reset(ZoneTableSegment::READ_ONLY, config_params2_);
}, ResetFailed);
EXPECT_TRUE(ztable_segment_->isUsable());
EXPECT_TRUE(ztable_segment_->isWritable());
// Check for the old data in the segment to make sure it is still
// available and correct.
EXPECT_TRUE(verifyData(ztable_segment_->getMemorySegment()));
......@@ -473,11 +499,13 @@ TEST_F(ZoneTableSegmentMappedTest, resetFailedMissingHeader) {
deleteHeader(*segment);
segment.reset();
// Opening mapped file 2 in read-only mode should fail
// Resetting to mapped file 2 in read-only mode should fail
EXPECT_THROW({
ztable_segment_->reset(ZoneTableSegment::READ_ONLY, config_params2_);
}, ResetFailed);
EXPECT_TRUE(ztable_segment_->isUsable());
EXPECT_TRUE(ztable_segment_->isWritable());
// Check for the old data in the segment to make sure it is still
// available and correct.
EXPECT_TRUE(verifyData(ztable_segment_->getMemorySegment()));
......@@ -494,11 +522,13 @@ TEST_F(ZoneTableSegmentMappedTest, resetCreateOverCorruptedFile) {
corruptChecksum(*segment);
segment.reset();
// Resetting mapped file 1 in CREATE mode over a corrupted file
// Resetting to mapped file 1 in CREATE mode over a corrupted file
// should pass.
EXPECT_NO_THROW(ztable_segment_->reset(ZoneTableSegment::CREATE,
config_params_));
EXPECT_TRUE(ztable_segment_->isUsable());
EXPECT_TRUE(ztable_segment_->isWritable());
// Check for the old data in the segment. It should not be present
// (as we opened the segment in CREATE mode).
EXPECT_FALSE(verifyData(ztable_segment_->getMemorySegment()));
......@@ -513,11 +543,13 @@ TEST_F(ZoneTableSegmentMappedTest, resetCreateOverCorruptedFile) {
deleteChecksum(*segment);
segment.reset();
// Resetting mapped file 1 in CREATE mode over a file missing
// Resetting to mapped file 1 in CREATE mode over a file missing
// checksum should pass.
EXPECT_NO_THROW(ztable_segment_->reset(ZoneTableSegment::CREATE,
config_params_));
EXPECT_TRUE(ztable_segment_->isUsable());
EXPECT_TRUE(ztable_segment_->isWritable());
// Check for the old data in the segment. It should not be present
// (as we opened the segment in CREATE mode).
EXPECT_FALSE(verifyData(ztable_segment_->getMemorySegment()));
......
......@@ -20,6 +20,8 @@
#include <datasrc/memory/zone_data.h>
#include <datasrc/memory/zone_writer.h>
#include <string>
namespace isc {
namespace datasrc {
namespace memory {
......@@ -33,6 +35,7 @@ public:
ZoneTableSegmentMock(const isc::dns::RRClass& rrclass,
isc::util::MemorySegment& mem_sgmt) :
ZoneTableSegment(rrclass),
impl_type_("mock"),
mem_sgmt_(mem_sgmt),
header_(ZoneTable::create(mem_sgmt_, rrclass))
{}
......@@ -41,6 +44,10 @@ public:
ZoneTable::destroy(mem_sgmt_, header_.getTable());
}
const std::string& getImplType() const {
return (impl_type_);
}
virtual void reset(MemorySegmentOpenMode, isc::data::ConstElementPtr) {
isc_throw(isc::NotImplemented, "reset() is not implemented");
}
......@@ -66,11 +73,16 @@ public:
return (mem_sgmt_);
}
virtual bool isUsable() const {
return (true);
}
virtual bool isWritable() const {
return (true);
}
private:
std::string impl_type_;
isc::util::MemorySegment& mem_sgmt_;
ZoneTableHeader header_;
};
......
......@@ -41,6 +41,9 @@ protected:
ZoneTableSegment* ztable_segment_;
};
TEST_F(ZoneTableSegmentTest, getImplType) {
EXPECT_EQ("local", ztable_segment_->getImplType());
}
TEST_F(ZoneTableSegmentTest, create) {
// By default, a local zone table segment is created.
......@@ -106,6 +109,11 @@ TEST_F(ZoneTableSegmentTest, getMemorySegment) {
mem_sgmt.allMemoryDeallocated(); // use mem_sgmt
}
TEST_F(ZoneTableSegmentTest, isUsable) {
// Local segments are always usable.
EXPECT_TRUE(ztable_segment_->isUsable());
}
TEST_F(ZoneTableSegmentTest, isWritable) {
// Local segments are always writable.
EXPECT_TRUE(ztable_segment_->isWritable());
......
......@@ -95,6 +95,13 @@ public:
ZoneTableSegmentMock(rrclass, mem_sgmt)
{}
// Returns false indicating that the segment is not usable. We
// override this too as ZoneTableSegment implementations may use it
// internally.
virtual bool isUsable() const {
return (false);
}
// Returns false indicating it is a read-only segment. It is used in
// the ZoneWriter tests.
virtual bool isWritable() const {
......
Supports Markdown
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