Browse Source

[2376] A class to hold all the loader callbacks

Michal 'vorner' Vaner 12 years ago
parent
commit
20288af379

+ 1 - 0
src/lib/dns/Makefile.am

@@ -119,6 +119,7 @@ libb10_dns___la_SOURCES += tsigerror.h tsigerror.cc
 libb10_dns___la_SOURCES += tsigkey.h tsigkey.cc
 libb10_dns___la_SOURCES += tsigrecord.h tsigrecord.cc
 libb10_dns___la_SOURCES += character_string.h character_string.cc
+libb10_dns___la_SOURCES += loader_callbacks.h
 libb10_dns___la_SOURCES += rdata/generic/detail/nsec_bitmap.h
 libb10_dns___la_SOURCES += rdata/generic/detail/nsec_bitmap.cc
 libb10_dns___la_SOURCES += rdata/generic/detail/nsec3param_common.cc

+ 131 - 0
src/lib/dns/loader_callbacks.h

@@ -0,0 +1,131 @@
+// 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 LOADER_CALLBACKS_H
+#define LOADER_CALLBACKS_H
+
+#include <dns/rrset.h>
+
+#include <exceptions/exceptions.h>
+
+#include <string>
+#include <boost/function.hpp>
+
+namespace isc {
+namespace dns {
+
+/// \brief Set of callbacks for a loader.
+///
+/// This holds a set of callbacks by which a loader (such as MasterLoader)
+/// can report loaded RRsets, errors and other unusual conditions.
+///
+/// All the callbacks must be set.
+class LoaderCallbacks {
+public:
+    /// \brief Type of one callback to report problems.
+    ///
+    /// This is the type of one callback used to report an unusual
+    /// condition or error.
+    ///
+    /// \param source_name The name of the source where the problem happened.
+    ///     This is usually a file name.
+    /// \param source_line Position of the problem, counted in lines from the
+    ///     beginning of the source.
+    /// \param reason Human readable description of what happened.
+    typedef boost::function<void(const std::string& source_name,
+                                 size_t source_line,
+                                 const std::string& reason)> IssueCallback;
+
+    /// \brief Type of callback to add a RRset.
+    ///
+    /// This type of callback is used by the loader to report another loaded
+    /// RRset. The RRset is no longer preserved by the loader and is fully
+    /// owned by the callback.
+    ///
+    /// \param RRset The rrset to add. It does not contain the accompanying
+    ///     RRSIG (if the zone is signed), they are reported with separate
+    ///     calls to the callback.
+    typedef boost::function<void(const RRsetPtr& rrset)> AddCallback;
+
+    /// \brief Constructor
+    ///
+    /// Initializes the callbacks.
+    ///
+    /// \param error The error callback to use.
+    /// \param warning The warning callback to use.
+    /// \param add The add callback to use.
+    /// \throw isc::InvalidParameter if any of the callbacks is empty.
+    LoaderCallbacks(const IssueCallback& error, const IssueCallback& warning,
+                    const AddCallback& add) :
+        error_(error),
+        warning_(warning),
+        add_(add)
+    {
+        if (error_.empty() || warning_.empty() || add_.empty()) {
+            isc_throw(isc::InvalidParameter,
+                      "Empty function passed as callback");
+        }
+    }
+
+    /// \brief Call callback for serious errors
+    ///
+    /// This is called whenever there's a serious problem which makes the data
+    /// being loaded unusable. Further processing may or may not happen after
+    /// this (for example to detect further errors), but the data should not
+    /// be used.
+    ///
+    /// It calls whatever was passed to the error parameter to the constructor.
+    ///
+    /// If the caller of the loader wants to abort, it is possible to throw
+    /// from the callback, which aborts the load.
+    void error(const std::string& source_name, size_t source_line,
+               const std::string& reason)
+    {
+        error_(source_name, source_line, reason);
+    }
+
+    /// \brief Call callback for potential problems
+    ///
+    /// This is called whenever a minor problem is discovered. This might mean
+    /// the data is completely OK, it just looks suspicious.
+    ///
+    /// It calls whatever was passed to the error parameter to the constructor.
+    ///
+    /// The loading will continue after the callback. If the caller wants to
+    /// abort (which is probably not a very good idea, since warnings
+    /// may be false positives), it is possible to throw from inside the
+    /// callback.
+    void warning(const std::string& source_name, size_t source_line,
+                 const std::string& reason)
+    {
+        warning_(source_name, source_line, reason);
+    }
+
+    /// \brief Call the add callback.
+    ///
+    /// This is called for each loaded RRset.
+    void addRRset(const RRsetPtr& rrset)
+    {
+        add_(rrset);
+    }
+
+private:
+    IssueCallback error_, warning_;
+    AddCallback add_;
+};
+
+}
+}
+
+#endif // LOADER_CALLBACKS_H

+ 1 - 0
src/lib/dns/tests/Makefile.am

@@ -71,6 +71,7 @@ run_unittests_SOURCES += tsigerror_unittest.cc
 run_unittests_SOURCES += tsigkey_unittest.cc
 run_unittests_SOURCES += tsigrecord_unittest.cc
 run_unittests_SOURCES += character_string_unittest.cc
+run_unittests_SOURCES += loader_callbacks_test.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

+ 98 - 0
src/lib/dns/tests/loader_callbacks_test.cc

@@ -0,0 +1,98 @@
+// 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/loader_callbacks.h>
+#include <dns/name.h>
+#include <dns/rrttl.h>
+#include <dns/rrclass.h>
+
+#include <exceptions/exceptions.h>
+
+#include <gtest/gtest.h>
+#include <boost/bind.hpp>
+
+namespace {
+
+using std::string;
+using namespace isc::dns;
+
+class LoaderCallbacksTest : public ::testing::Test {
+protected:
+    LoaderCallbacksTest() :
+        called_(false),
+        rrset_(new RRset(Name("example.org"), RRClass::IN(), RRType::A(),
+                         RRTTL(3600))),
+        error_(boost::bind(&LoaderCallbacksTest::checkCallback, this, true, _1,
+                           _2, _3)),
+        warning_(boost::bind(&LoaderCallbacksTest::checkCallback, this, false,
+                             _1, _2, _3)),
+        add_(boost::bind(&LoaderCallbacksTest::checkAdd, this, _1)),
+        callbacks_(error_, warning_, add_)
+    {}
+
+    void checkCallback(bool error, const string& source, size_t line,
+                       const string& reason)
+    {
+        called_ = true;
+        last_was_error_ = error;
+        EXPECT_EQ("source", source);
+        EXPECT_EQ(1, line);
+        EXPECT_EQ("reason", reason);
+    }
+    void checkAdd(const RRsetPtr& rrset) {
+        called_ = true;
+        EXPECT_EQ(rrset_, rrset);
+    }
+    bool last_was_error_;
+    bool called_;
+    const RRsetPtr rrset_;
+    const LoaderCallbacks::IssueCallback error_, warning_;
+    const LoaderCallbacks::AddCallback add_;
+    LoaderCallbacks callbacks_;
+};
+
+// Check the constructor rejects empty callbacks, but accepts non-empty ones
+TEST_F(LoaderCallbacksTest, constructor) {
+    EXPECT_THROW(LoaderCallbacks(LoaderCallbacks::IssueCallback(), warning_,
+                                 add_), isc::InvalidParameter);
+    EXPECT_THROW(LoaderCallbacks(error_, LoaderCallbacks::IssueCallback(),
+                                 add_), isc::InvalidParameter);
+    EXPECT_THROW(LoaderCallbacks(error_, warning_,
+                                 LoaderCallbacks::AddCallback()),
+                 isc::InvalidParameter);
+    EXPECT_NO_THROW(LoaderCallbacks(error_, warning_, add_));
+}
+
+// Call the issue callbacks
+TEST_F(LoaderCallbacksTest, issueCall) {
+    callbacks_.error("source", 1, "reason");
+    EXPECT_TRUE(last_was_error_);
+    EXPECT_TRUE(called_);
+
+    called_ = false;
+
+    callbacks_.warning("source", 1, "reason");
+    EXPECT_FALSE(last_was_error_);
+    EXPECT_TRUE(called_);
+}
+
+// Call the add callback
+TEST_F(LoaderCallbacksTest, addCall) {
+    EXPECT_FALSE(called_);
+    callbacks_.addRRset(rrset_);
+    EXPECT_TRUE(called_);
+}
+
+
+}