BIND 10 master, updated. 7868cb5a0cb2c276114c8d762a89bc59d8169df8 Merge #2207
BIND 10 source code commits
bind10-changes at lists.isc.org
Sat Oct 20 09:28:44 UTC 2012
The branch, master has been updated
via 7868cb5a0cb2c276114c8d762a89bc59d8169df8 (commit)
via 08e8d762ad041672b156204c21b42b32a510e94c (commit)
via bef1229c90595e4aa4a6c483fc99f7cac768a1b3 (commit)
via 21170f738cf943a5750c26eb8b418972a673a27f (commit)
via 396d1867ce3420d759bd5eaaed64ce3f83b0b874 (commit)
via c1e16071d91f9db0b3f78f7a09551c66278ace5e (commit)
via 451973cb26da61f3e5d56c441ea54a28c34acaa3 (commit)
via 83f878b651eb1be66dfcb1453cc074c2b5d3dc3f (commit)
via 100929f3fab349338ecbd8cbcdf090e1006f8ab0 (commit)
via 7265ccb300bd2a2e1789d8ce99182e787d97181c (commit)
via 399e4f0030d226010f2156e978fc2b7c179fe7b7 (commit)
via f0f7efe331713b84e4e95f872373d6d2906b5870 (commit)
via 16041df526aeb519ff158aa4cd89e0b4f503aece (commit)
via 6430d56ffc6be92717f50e576101546be2f4d6c9 (commit)
via ccfb2bf2c5226f21e793df4abaa9b98a993b6eb3 (commit)
via 4601f7ef87135a559b4fa7a1daaf2f1de8f040c3 (commit)
via 84e0dc1be1b2f22d46028944a3ce1a599aa24090 (commit)
via 2530e97e662406cb168e80358c764ff8692866cb (commit)
via 5b77cd205f08b1bc76ec5ff4248f4c9cb4e0ac27 (commit)
via 1ae2321d7183470ad3540d2a92436893724ea773 (commit)
via 03b8bddd309adeb39a99474aea530f05989b99ed (commit)
via 0d336b6f23ca4518b38f1e26e8b8b9998f426e5f (commit)
via 07e1f1ddbd299b60ee4009f53723b4271b5cea16 (commit)
via d5569a62a30b26294197381dadf4b28317fba3d9 (commit)
via b06d8d764e01652ef5d3e1eb50ed482ddeae8308 (commit)
via 51580fd1a4953d554b80306eec4f9fc89f166241 (commit)
via c55218e6bebfeec753b01e4cd724adcda40b3a5f (commit)
via c0e090f453d3a1627ccd0591e0ec0abc3e80a01b (commit)
via 70aa7bfa24600d5492056c860838d94c9243c6aa (commit)
via 419020c407ac9f1ca0ab1f5a5c8b8b6219fb5d5b (commit)
via 58c41ea9cdb2df726b4b54015500acab3ae34040 (commit)
via c64356e9fdf3be868bb2d624200219d68aca45e8 (commit)
via e5ad36f38f6066c50059ea02e06245d7bc5c7efd (commit)
via e70da63e4aa5a075928c5cdef4fed11d15eeaa5a (commit)
via 234026e024d6c4f35d2b7e1f34213949f79e614c (commit)
via c887cb05e27289bf5a80130c1a196dbbc1903234 (commit)
via b59e1eb450e7f4630ee4ee8e67b7dbb3cf6092de (commit)
via 98127986d0baa2f87e455035d778c823bbe59397 (commit)
from c13d57b516b4ed381a51916a5b726aebcc564f8f (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 7868cb5a0cb2c276114c8d762a89bc59d8169df8
Merge: c13d57b 08e8d76
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Sat Oct 20 11:11:33 2012 +0200
Merge #2207
"define and implement (datasrc::memory::)ZoneUpdater class"
It is now ZoneWriter.
No changelog.
Conflicts:
src/lib/datasrc/memory/Makefile.am
commit 08e8d762ad041672b156204c21b42b32a510e94c
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Sat Oct 20 11:09:58 2012 +0200
[2207] Note about compilation problem
-----------------------------------------------------------------------
Summary of changes:
src/lib/datasrc/memory/Makefile.am | 3 +
.../{zone_table_segment_local.cc => load_action.h} | 42 ++--
src/lib/datasrc/memory/zone_table_segment.h | 42 ++++
src/lib/datasrc/memory/zone_table_segment_local.cc | 9 +
src/lib/datasrc/memory/zone_table_segment_local.h | 4 +
src/lib/datasrc/memory/zone_writer.h | 89 +++++++
src/lib/datasrc/memory/zone_writer_local.cc | 93 ++++++++
src/lib/datasrc/memory/zone_writer_local.h | 95 ++++++++
src/lib/datasrc/tests/memory/Makefile.am | 1 +
.../tests/memory/zone_table_segment_unittest.cc | 24 ++
.../datasrc/tests/memory/zone_writer_unittest.cc | 249 ++++++++++++++++++++
11 files changed, 632 insertions(+), 19 deletions(-)
copy src/lib/datasrc/memory/{zone_table_segment_local.cc => load_action.h} (52%)
create mode 100644 src/lib/datasrc/memory/zone_writer.h
create mode 100644 src/lib/datasrc/memory/zone_writer_local.cc
create mode 100644 src/lib/datasrc/memory/zone_writer_local.h
create mode 100644 src/lib/datasrc/tests/memory/zone_writer_unittest.cc
-----------------------------------------------------------------------
diff --git a/src/lib/datasrc/memory/Makefile.am b/src/lib/datasrc/memory/Makefile.am
index 6fce958..7b82269 100644
--- a/src/lib/datasrc/memory/Makefile.am
+++ b/src/lib/datasrc/memory/Makefile.am
@@ -24,6 +24,9 @@ libdatasrc_memory_la_SOURCES += zone_table_segment_local.h zone_table_segment_lo
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 += load_action.h
nodist_libdatasrc_memory_la_SOURCES = memory_messages.h memory_messages.cc
diff --git a/src/lib/datasrc/memory/load_action.h b/src/lib/datasrc/memory/load_action.h
new file mode 100644
index 0000000..f9625af
--- /dev/null
+++ b/src/lib/datasrc/memory/load_action.h
@@ -0,0 +1,47 @@
+// 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 LOAD_ACTION_H
+#define LOAD_ACTION_H
+
+#include <boost/function.hpp>
+
+namespace isc {
+// Forward declarations
+namespace util{
+class MemorySegment;
+}
+namespace datasrc {
+namespace memory {
+class ZoneData;
+
+/// \brief Callback to load data into the memory
+///
+/// This is called from the ZoneWriter whenever there's need to load the
+/// zone data. The callback should allocate new ZoneData and fill it with
+/// the zone content. It is up to the callback to know where or how to
+/// load the data, or even the origin and class of the zone (it is assumed
+/// the callback will be some kind of functor).
+///
+/// All data should be allocated from the passed MemorySegment. The ownership
+/// is passed onto the caller.
+///
+/// It must not return NULL.
+typedef boost::function<ZoneData*(util::MemorySegment&)> LoadAction;
+
+}
+}
+}
+
+#endif
diff --git a/src/lib/datasrc/memory/zone_table_segment.h b/src/lib/datasrc/memory/zone_table_segment.h
index 7fd1310..8731718 100644
--- a/src/lib/datasrc/memory/zone_table_segment.h
+++ b/src/lib/datasrc/memory/zone_table_segment.h
@@ -16,6 +16,7 @@
#define __ZONE_TABLE_SEGMENT_H__
#include <datasrc/memory/zone_table.h>
+#include "load_action.h"
#include <cc/data.h>
#include <util/memory_segment.h>
@@ -24,8 +25,14 @@
#include <stdlib.h>
namespace isc {
+// Some forward declarations
+namespace dns {
+class Name;
+class RRClass;
+}
namespace datasrc {
namespace memory {
+class ZoneWriter;
/// \brief Memory-management independent entry point that contains a
/// pointer to a zone table in memory.
@@ -45,6 +52,26 @@ public:
return (table.get());
}
+ /// \brief Method to set the internal table
+ ///
+ /// The interface is tentative, we don't know if this is the correct place
+ /// and way to set the data. But for now, we need something to be there
+ /// at least for the tests. So we have this. For this reason, there are
+ /// no tests for this method directly. Do not use in actual
+ /// implementation.
+ ///
+ /// It can be used only once, to initially set it. It can't replace the
+ /// one already there.
+ ///
+ /// \param table Pointer to the table to use.
+ /// \throw isc::Unexpected if called the second time.
+ void setTable(ZoneTable* table) {
+ if (this->table.get() != NULL) {
+ isc_throw(isc::Unexpected, "Replacing table");
+ }
+ this->table = table;
+ }
+
private:
boost::interprocess::offset_ptr<ZoneTable> table;
};
@@ -101,6 +128,21 @@ public:
///
/// \param segment The segment to destroy.
static void destroy(ZoneTableSegment* segment);
+
+ /// \brief Create a zone write corresponding to this segment
+ ///
+ /// This creates a new write that can be used to update zones
+ /// inside this zone table segment.
+ ///
+ /// \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;
};
} // namespace memory
diff --git a/src/lib/datasrc/memory/zone_table_segment_local.cc b/src/lib/datasrc/memory/zone_table_segment_local.cc
index 589c9af..2630d1e 100644
--- a/src/lib/datasrc/memory/zone_table_segment_local.cc
+++ b/src/lib/datasrc/memory/zone_table_segment_local.cc
@@ -13,6 +13,7 @@
// PERFORMANCE OF THIS SOFTWARE.
#include <datasrc/memory/zone_table_segment_local.h>
+#include "zone_writer_local.h"
using namespace isc::util;
@@ -38,6 +39,14 @@ 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
diff --git a/src/lib/datasrc/memory/zone_table_segment_local.h b/src/lib/datasrc/memory/zone_table_segment_local.h
index de776a9..b83bd49 100644
--- a/src/lib/datasrc/memory/zone_table_segment_local.h
+++ b/src/lib/datasrc/memory/zone_table_segment_local.h
@@ -54,6 +54,10 @@ public:
/// implementation (a 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);
private:
ZoneTableHeader header_;
isc::util::MemorySegmentLocal mem_sgmt_;
diff --git a/src/lib/datasrc/memory/zone_writer.h b/src/lib/datasrc/memory/zone_writer.h
new file mode 100644
index 0000000..fe8dc2a
--- /dev/null
+++ b/src/lib/datasrc/memory/zone_writer.h
@@ -0,0 +1,89 @@
+// 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 MEM_ZONE_WRITER_H
+#define MEM_ZONE_WRITER_H
+
+#include "load_action.h"
+
+namespace isc {
+namespace datasrc {
+namespace memory {
+
+/// \brief Does an update to a zone.
+///
+/// This abstract base class represents the work of a reload of a zone.
+/// The work is divided into three stages -- load(), install() and cleanup().
+/// They should be called in this order for the effect to take place.
+///
+/// We divide them so the update of zone data can be done asynchronously,
+/// in a different thread. The install() operation is the only one that needs
+/// to be done in a critical section.
+///
+/// Each derived class implementation must provide the strong exception
+/// guarantee for each public method. That is, when any of the methods
+/// throws, the entire state should stay the same as before the call
+/// (how to achieve that may be implementation dependant).
+class ZoneWriter {
+public:
+ /// \brief Get the zone data into memory.
+ ///
+ /// This is the part that does the time-consuming loading into the memory.
+ /// This can be run in a separate thread, for example. It has no effect on
+ /// the data actually served, it only prepares them for future use.
+ ///
+ /// This is the first method you should call on the object. Never call it
+ /// multiple times.
+ ///
+ /// \note As this contains reading of files or other data sources, or with
+ /// some other source of the data to load, it may throw quite anything.
+ /// If it throws, do not call any other methods on the object and
+ /// discard it.
+ /// \note After successful load(), you have to call cleanup() some time
+ /// later.
+ /// \throw isc::InvalidOperation if called second time.
+ virtual void load() = 0;
+
+ /// \brief Put the changes to effect.
+ ///
+ /// This replaces the old version of zone with the one previously prepared
+ /// by load(). It takes ownership of the old zone data, if any.
+ ///
+ /// You may call it only after successful load() and at most once.
+ ///
+ /// The operation is expected to be fast and is meant to be used inside
+ /// a critical section.
+ ///
+ /// This may throw in rare cases, depending on the concrete implementation.
+ /// If it throws, you still need to call cleanup().
+ ///
+ /// \throw isc::InvalidOperation if called without previous load() or for
+ /// the second time or cleanup() was called already.
+ virtual void install() = 0;
+
+ /// \brief Clean up resources.
+ ///
+ /// This releases all resources held by owned zone data. That means the
+ /// one loaded by load() in case install() was not called or was not
+ /// successful, or the one replaced in install().
+ ///
+ /// Generally, this should never throw.
+ virtual void cleanup() = 0;
+};
+
+}
+}
+}
+
+#endif
diff --git a/src/lib/datasrc/memory/zone_writer_local.cc b/src/lib/datasrc/memory/zone_writer_local.cc
new file mode 100644
index 0000000..0cd9587
--- /dev/null
+++ b/src/lib/datasrc/memory/zone_writer_local.cc
@@ -0,0 +1,93 @@
+// 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 "zone_writer_local.h"
+#include "zone_data.h"
+#include "zone_table_segment_local.h"
+
+#include <memory>
+
+using std::auto_ptr;
+
+namespace isc {
+namespace datasrc {
+namespace memory {
+
+ZoneWriterLocal::ZoneWriterLocal(ZoneTableSegmentLocal* segment,
+ const LoadAction& load_action,
+ const dns::Name& origin,
+ const dns::RRClass& rrclass) :
+ segment_(segment),
+ load_action_(load_action),
+ origin_(origin),
+ rrclass_(rrclass),
+ zone_data_(NULL),
+ state_(ZW_UNUSED)
+{}
+
+ZoneWriterLocal::~ZoneWriterLocal() {
+ // Clean up everything there might be left if someone forgot, just
+ // in case.
+ cleanup();
+}
+
+void
+ZoneWriterLocal::load() {
+ if (state_ != ZW_UNUSED) {
+ isc_throw(isc::InvalidOperation, "Trying to load twice");
+ }
+
+ zone_data_ = load_action_(segment_->getMemorySegment());
+
+ if (zone_data_ == NULL) {
+ // Bug inside load_action_.
+ isc_throw(isc::InvalidOperation, "No data returned from load action");
+ }
+
+ state_ = ZW_LOADED;
+}
+
+void
+ZoneWriterLocal::install() {
+ if (state_ != ZW_LOADED) {
+ isc_throw(isc::InvalidOperation, "No data to install");
+ }
+
+
+ ZoneTable* table(segment_->getHeader().getTable());
+ if (table == NULL) {
+ isc_throw(isc::Unexpected, "No zone table present");
+ }
+ const ZoneTable::AddResult result(table->addZone(
+ segment_->getMemorySegment(),
+ rrclass_, origin_, zone_data_));
+
+ state_ = ZW_INSTALLED;
+ zone_data_ = result.zone_data;
+}
+
+void
+ZoneWriterLocal::cleanup() {
+ // We eat the data (if any) now.
+
+ if (zone_data_ != NULL) {
+ ZoneData::destroy(segment_->getMemorySegment(), zone_data_, rrclass_);
+ zone_data_ = NULL;
+ state_ = ZW_CLEANED;
+ }
+}
+
+}
+}
+}
diff --git a/src/lib/datasrc/memory/zone_writer_local.h b/src/lib/datasrc/memory/zone_writer_local.h
new file mode 100644
index 0000000..7231a57
--- /dev/null
+++ b/src/lib/datasrc/memory/zone_writer_local.h
@@ -0,0 +1,95 @@
+// 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 MEM_ZONE_WRITER_LOCAL_H
+#define MEM_ZONE_WRITER_LOCAL_H
+
+#include "zone_writer.h"
+
+#include <dns/rrclass.h>
+#include <dns/name.h>
+
+namespace isc {
+namespace datasrc {
+namespace memory {
+
+class ZoneData;
+class ZoneTableSegmentLocal;
+
+/// \brief Writer implementation which loads data locally.
+///
+/// This implementation prepares a clean zone data and lets one callback
+/// to fill it and another to install it somewhere. The class does mostly
+/// nothing (and delegates the work to the callbacks), just stores little bit
+/// of state between the calls.
+class ZoneWriterLocal : public ZoneWriter {
+public:
+ /// \brief Constructor
+ ///
+ /// \param segment The zone table segment to store the zone into.
+ /// \param load_action The callback used to load data.
+ /// \param install_action The callback used to install the loaded zone.
+ /// \param rrclass The class of the zone.
+ ZoneWriterLocal(ZoneTableSegmentLocal* segment,
+ const LoadAction& load_action, const dns::Name& name,
+ const dns::RRClass& rrclass);
+
+ /// \brief Destructor
+ ~ZoneWriterLocal();
+
+ /// \brief Loads the data.
+ ///
+ /// This calls the load_action (passed to constructor) and stores the
+ /// data for future use.
+ ///
+ /// \throw isc::InvalidOperation if it is called the second time in
+ /// lifetime of the object.
+ /// \throw Whatever the load_action throws, it is propagated up.
+ virtual void load();
+
+ /// \brief Installs the zone.
+ ///
+ /// It modifies the zone table accessible through the segment (passed to
+ /// constructor).
+ ///
+ /// \throw isc::InvalidOperation if it is called the second time in
+ /// lifetime of the object or if load() was not called previously or if
+ /// cleanup() was already called.
+ virtual void install();
+
+ /// \brief Clean up memory.
+ ///
+ /// Cleans up the memory used by load()ed zone if not yet installed, or
+ /// the old zone replaced by install().
+ virtual void cleanup();
+private:
+ ZoneTableSegmentLocal* segment_;
+ LoadAction load_action_;
+ dns::Name origin_;
+ dns::RRClass rrclass_;
+ ZoneData* zone_data_;
+ enum State {
+ ZW_UNUSED,
+ ZW_LOADED,
+ ZW_INSTALLED,
+ ZW_CLEANED
+ };
+ State state_;
+};
+
+}
+}
+}
+
+#endif
diff --git a/src/lib/datasrc/tests/memory/Makefile.am b/src/lib/datasrc/tests/memory/Makefile.am
index 37e9043..6a3d9a9 100644
--- a/src/lib/datasrc/tests/memory/Makefile.am
+++ b/src/lib/datasrc/tests/memory/Makefile.am
@@ -33,6 +33,7 @@ run_unittests_SOURCES += memory_segment_test.h
run_unittests_SOURCES += segment_object_holder_unittest.cc
run_unittests_SOURCES += memory_client_unittest.cc
run_unittests_SOURCES += zone_table_segment_unittest.cc
+run_unittests_SOURCES += zone_writer_unittest.cc
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
diff --git a/src/lib/datasrc/tests/memory/zone_table_segment_unittest.cc b/src/lib/datasrc/tests/memory/zone_table_segment_unittest.cc
index 6bdd737..928b6c4 100644
--- a/src/lib/datasrc/tests/memory/zone_table_segment_unittest.cc
+++ b/src/lib/datasrc/tests/memory/zone_table_segment_unittest.cc
@@ -13,8 +13,14 @@
// PERFORMANCE OF THIS SOFTWARE.
#include <datasrc/memory/zone_table_segment.h>
+#include <datasrc/memory/zone_writer_local.h>
#include <gtest/gtest.h>
+#include <boost/scoped_ptr.hpp>
+
+using boost::scoped_ptr;
+using isc::dns::Name;
+using isc::dns::RRClass;
using namespace isc::datasrc::memory;
using namespace isc::data;
using namespace isc::util;
@@ -80,4 +86,22 @@ TEST_F(ZoneTableSegmentTest, getMemorySegment) {
EXPECT_TRUE(mem_sgmt.allMemoryDeallocated());
}
+ZoneData*
+loadAction(MemorySegment&) {
+ // The function won't be called, so this is OK
+ return (NULL);
+}
+
+// Test we can get a writer.
+TEST_F(ZoneTableSegmentTest, getZoneWriter) {
+ scoped_ptr<ZoneWriter>
+ writer(segment_->getZoneWriter(loadAction, Name("example.org"),
+ RRClass::IN()));
+ // We have to get something
+ EXPECT_NE(static_cast<void*>(NULL), writer.get());
+ // And for now, it should be the local writer
+ EXPECT_NE(static_cast<void*>(NULL),
+ dynamic_cast<ZoneWriterLocal*>(writer.get()));
+}
+
} // anonymous namespace
diff --git a/src/lib/datasrc/tests/memory/zone_writer_unittest.cc b/src/lib/datasrc/tests/memory/zone_writer_unittest.cc
new file mode 100644
index 0000000..bc9b103
--- /dev/null
+++ b/src/lib/datasrc/tests/memory/zone_writer_unittest.cc
@@ -0,0 +1,249 @@
+// 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 <datasrc/memory/zone_writer_local.h>
+#include <datasrc/memory/zone_table_segment_local.h>
+#include <datasrc/memory/zone_data.h>
+
+#include <cc/data.h>
+#include <dns/rrclass.h>
+#include <dns/name.h>
+
+#include <gtest/gtest.h>
+
+#include <boost/scoped_ptr.hpp>
+#include <boost/bind.hpp>
+
+using boost::scoped_ptr;
+using boost::bind;
+using isc::dns::RRClass;
+using isc::dns::Name;
+using namespace isc::datasrc::memory;
+
+namespace {
+
+class TestException {};
+
+class ZoneWriterLocalTest : public ::testing::Test {
+public:
+ ZoneWriterLocalTest() :
+ // FIXME: The NullElement probably isn't the best one, but we don't
+ // know how the config will look, so it just fills the argument
+ // (which is currently ignored)
+ segment_(ZoneTableSegment::create(isc::data::NullElement())),
+ writer_(new
+ ZoneWriterLocal(dynamic_cast<ZoneTableSegmentLocal*>(segment_.
+ get()),
+ bind(&ZoneWriterLocalTest::loadAction, this, _1),
+ Name("example.org"), RRClass::IN())),
+ load_called_(false),
+ load_throw_(false),
+ load_null_(false),
+ load_data_(false)
+ {
+ // TODO: The setTable is only a temporary interface
+ segment_->getHeader().
+ setTable(ZoneTable::create(segment_->getMemorySegment(),
+ RRClass::IN()));
+ }
+ void TearDown() {
+ // Release the writer
+ writer_.reset();
+ // Release the table we used
+ ZoneTable::destroy(segment_->getMemorySegment(),
+ segment_->getHeader().getTable(), RRClass::IN());
+ // And check we freed all memory
+ EXPECT_TRUE(segment_->getMemorySegment().allMemoryDeallocated());
+ }
+protected:
+ scoped_ptr<ZoneTableSegment> segment_;
+ scoped_ptr<ZoneWriterLocal> writer_;
+ bool load_called_;
+ bool load_throw_;
+ bool load_null_;
+ bool load_data_;
+private:
+ ZoneData* loadAction(isc::util::MemorySegment& segment) {
+ // Make sure it is the correct segment passed. We know the
+ // exact instance, can compare pointers to them.
+ EXPECT_EQ(&segment_->getMemorySegment(), &segment);
+ // We got called
+ load_called_ = true;
+ if (load_throw_) {
+ throw TestException();
+ }
+
+ if (load_null_) {
+ // Be nasty to the caller and return NULL, which is forbidden
+ return (NULL);
+ }
+ ZoneData* data = ZoneData::create(segment, Name("example.org"));
+ if (load_data_) {
+ // Put something inside. The node itself should be enough for
+ // the tests.
+ ZoneNode* node(NULL);
+ data->insertName(segment, Name("subdomain.example.org"), &node);
+ EXPECT_NE(static_cast<ZoneNode*>(NULL), node);
+ }
+ return (data);
+ }
+};
+
+// We call it the way we are supposed to, check every callback is called in the
+// right moment.
+TEST_F(ZoneWriterLocalTest, correctCall) {
+ // Nothing called before we call it
+ EXPECT_FALSE(load_called_);
+
+ // Just the load gets called now
+ EXPECT_NO_THROW(writer_->load());
+ EXPECT_TRUE(load_called_);
+ load_called_ = false;
+
+ EXPECT_NO_THROW(writer_->install());
+ EXPECT_FALSE(load_called_);
+
+ // We don't check explicitly how this works, but call it to free memory. If
+ // everything is freed should be checked inside the TearDown.
+ EXPECT_NO_THROW(writer_->cleanup());
+}
+
+TEST_F(ZoneWriterLocalTest, loadTwice) {
+ // Load it the first time
+ EXPECT_NO_THROW(writer_->load());
+ EXPECT_TRUE(load_called_);
+ load_called_ = false;
+
+ // The second time, it should not be possible
+ EXPECT_THROW(writer_->load(), isc::InvalidOperation);
+ EXPECT_FALSE(load_called_);
+
+ // The object should not be damaged, try installing and clearing now
+ EXPECT_NO_THROW(writer_->install());
+ EXPECT_FALSE(load_called_);
+
+ // We don't check explicitly how this works, but call it to free memory. If
+ // everything is freed should be checked inside the TearDown.
+ EXPECT_NO_THROW(writer_->cleanup());
+}
+
+// Try loading after call to install and call to cleanup. Both is
+// forbidden.
+TEST_F(ZoneWriterLocalTest, loadLater) {
+ // Load first, so we can install
+ EXPECT_NO_THROW(writer_->load());
+ EXPECT_NO_THROW(writer_->install());
+ // Reset so we see nothing is called now
+ load_called_ = false;
+
+ EXPECT_THROW(writer_->load(), isc::InvalidOperation);
+ EXPECT_FALSE(load_called_);
+
+ // Cleanup and try loading again. Still shouldn't work.
+ EXPECT_NO_THROW(writer_->cleanup());
+
+ EXPECT_THROW(writer_->load(), isc::InvalidOperation);
+ EXPECT_FALSE(load_called_);
+}
+
+// Try calling install at various bad times
+TEST_F(ZoneWriterLocalTest, invalidInstall) {
+ // Nothing loaded yet
+ EXPECT_THROW(writer_->install(), isc::InvalidOperation);
+ EXPECT_FALSE(load_called_);
+
+ EXPECT_NO_THROW(writer_->load());
+ load_called_ = false;
+ // This install is OK
+ EXPECT_NO_THROW(writer_->install());
+ // But we can't call it second time now
+ EXPECT_THROW(writer_->install(), isc::InvalidOperation);
+ EXPECT_FALSE(load_called_);
+}
+
+// We check we can clean without installing first and nothing bad
+// happens. We also misuse the testcase to check we can't install
+// after cleanup.
+TEST_F(ZoneWriterLocalTest, cleanWithoutInstall) {
+ EXPECT_NO_THROW(writer_->load());
+ EXPECT_NO_THROW(writer_->cleanup());
+
+ EXPECT_TRUE(load_called_);
+
+ // We cleaned up, no way to install now
+ EXPECT_THROW(writer_->install(), isc::InvalidOperation);
+}
+
+// Test the case when load callback throws
+TEST_F(ZoneWriterLocalTest, loadThrows) {
+ load_throw_ = true;
+ EXPECT_THROW(writer_->load(), TestException);
+
+ // We can't install now
+ EXPECT_THROW(writer_->install(), isc::InvalidOperation);
+ EXPECT_TRUE(load_called_);
+
+ // But we can cleanup
+ EXPECT_NO_THROW(writer_->cleanup());
+}
+
+// Check the strong exception guarantee - if it throws, nothing happened
+// to the content.
+TEST_F(ZoneWriterLocalTest, retry) {
+ // First attempt fails due to some exception.
+ load_throw_ = true;
+ EXPECT_THROW(writer_->load(), TestException);
+ // This one shall succeed.
+ load_called_ = load_throw_ = false;
+ // We want some data inside.
+ load_data_ = true;
+ EXPECT_NO_THROW(writer_->load());
+ // And this one will fail again. But the old data will survive.
+ load_data_ = false;
+ EXPECT_THROW(writer_->load(), isc::InvalidOperation);
+
+ // The rest still works correctly
+ EXPECT_NO_THROW(writer_->install());
+ ZoneTable* const table(segment_->getHeader().getTable());
+ const ZoneTable::FindResult found(table->findZone(Name("example.org")));
+ ASSERT_EQ(isc::datasrc::result::SUCCESS, found.code);
+ // For some reason it doesn't seem to work by the ZoneNode typedef, using
+ // the full definition instead. At least on some compilers.
+ const isc::datasrc::memory::DomainTreeNode<RdataSet>* node;
+ EXPECT_EQ(isc::datasrc::memory::DomainTree<RdataSet>::EXACTMATCH,
+ found.zone_data->getZoneTree().
+ find(Name("subdomain.example.org"), &node));
+ EXPECT_NO_THROW(writer_->cleanup());
+}
+
+// Check the writer defends itsefl when load action returns NULL
+TEST_F(ZoneWriterLocalTest, loadNull) {
+ load_null_ = true;
+ EXPECT_THROW(writer_->load(), isc::InvalidOperation);
+
+ // We can't install that
+ EXPECT_THROW(writer_->install(), isc::InvalidOperation);
+
+ // It should be possible to clean up safely
+ EXPECT_NO_THROW(writer_->cleanup());
+}
+
+// Check the object cleans up in case we forget it.
+TEST_F(ZoneWriterLocalTest, autoCleanUp) {
+ // Load data and forget about it. It should get released
+ // when the writer itself is destroyed.
+ EXPECT_NO_THROW(writer_->load());
+}
+
+}
More information about the bind10-changes
mailing list