Browse Source

Merge branch 'master' into trac2357

Mukund Sivaraman 12 years ago
parent
commit
dc3884d6b3

+ 16 - 0
configure.ac

@@ -12,6 +12,20 @@ AC_CONFIG_MACRO_DIR([m4macros])
 # Checks for programs.
 AC_PROG_CXX
 
+# Enable low-performing debugging facilities? This option optionally
+# enables some debugging aids that perform slowly and hence aren't built
+# by default.
+AC_ARG_ENABLE([debug],
+  AS_HELP_STRING([--enable-debug],
+    [enable debugging (default is no)]),
+  [case "${enableval}" in
+    yes) debug_enabled=yes ;;
+    no)  debug_enabled=no ;;
+    *)   AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;;
+  esac],[debug_enabled=no])
+AM_CONDITIONAL([DEBUG_ENABLED], [test x$debug_enabled = xyes])
+AM_COND_IF([DEBUG_ENABLED], [AC_DEFINE([ENABLE_DEBUG], [1], [Enable low-performing debugging facilities?])])
+
 # Libtool configuration
 #
 
@@ -1112,6 +1126,7 @@ AC_CONFIG_FILES([Makefile
                  src/bin/bindctl/Makefile
                  src/bin/bindctl/tests/Makefile
                  src/bin/cfgmgr/Makefile
+                 src/bin/cfgmgr/local_plugins/Makefile
                  src/bin/cfgmgr/plugins/Makefile
                  src/bin/cfgmgr/plugins/tests/Makefile
                  src/bin/cfgmgr/tests/Makefile
@@ -1421,6 +1436,7 @@ Features:
   $enable_features
 
 Developer:
+  Enable Debugging: $debug_enabled
   Google Tests: $enable_gtest
   Valgrind: $found_valgrind
   C++ Code Coverage: $USE_LCOV

+ 1 - 1
src/bin/cfgmgr/Makefile.am

@@ -1,4 +1,4 @@
-SUBDIRS = . plugins tests
+SUBDIRS = . plugins local_plugins tests
 
 pkglibexecdir = $(libexecdir)/@PACKAGE@
 

+ 11 - 0
src/bin/cfgmgr/local_plugins/Makefile.am

@@ -0,0 +1,11 @@
+# Nothing is installed from this directory.  This local_plugins
+# directory overrides the plugins directory when lettuce is run, and the
+# spec file here is used to serve the static zone from the source tree
+# for testing (instead of installation prefix).
+
+noinst_DATA = datasrc.spec
+
+datasrc.spec: ../plugins/datasrc.spec.pre
+	$(SED) -e "s|@@STATIC_ZONE_FILE@@|$(abs_top_builddir)/src/lib/datasrc/static.zone|;s|@@SQLITE3_DATABASE_FILE@@|$(abs_top_builddir)/local.zone.sqlite3|" ../plugins/datasrc.spec.pre >$@
+
+CLEANFILES = datasrc.spec

+ 1 - 1
src/bin/cfgmgr/plugins/Makefile.am

@@ -3,7 +3,7 @@ SUBDIRS = tests
 EXTRA_DIST = README logging.spec tsig_keys.spec
 
 datasrc.spec: datasrc.spec.pre
-	$(SED) -e "s|@@PKGDATADIR@@|$(pkgdatadir)|;s|@@LOCALSTATEDIR@@|$(localstatedir)|" datasrc.spec.pre >$@
+	$(SED) -e "s|@@STATIC_ZONE_FILE@@|$(pkgdatadir)/static.zone|;s|@@SQLITE3_DATABASE_FILE@@|$(localstatedir)/$(PACKAGE)/zone.sqlite3|" datasrc.spec.pre >$@
 
 config_plugindir = @prefix@/share/@PACKAGE@/config_plugins
 config_plugin_DATA = logging.spec tsig_keys.spec datasrc.spec

+ 2 - 2
src/bin/cfgmgr/plugins/datasrc.spec.pre.in

@@ -12,7 +12,7 @@
                         {
                             "type": "sqlite3",
                             "params": {
-                                "database_file": "@@LOCALSTATEDIR@@/@PACKAGE@/zone.sqlite3"
+                                "database_file": "@@SQLITE3_DATABASE_FILE@@"
                             }
                         }
                     ],
@@ -20,7 +20,7 @@
                         {
                             "type": "static",
                             "cache-enable": false,
-                            "params": "@@PKGDATADIR@@/static.zone"
+                            "params": "@@STATIC_ZONE_FILE@@"
                         }
                     ]
                 },

+ 3 - 1
src/lib/python/bind10_config.py.in

@@ -51,7 +51,7 @@ def reload():
     #  tree the programs in the tree (not installed ones) will be used.
     #
     # B10_FROM_SOURCE_LOCALSTATEDIR is specifically intended to be used for
-    # tests where we want to use variuos types of configuration within the test
+    # tests where we want to use various types of configuration within the test
     # environment.  (We may want to make it even more generic so that the path
     # is passed from the boss process)
     if "B10_FROM_SOURCE" in os.environ:
@@ -60,6 +60,8 @@ def reload():
         else:
             DATA_PATH = os.environ["B10_FROM_SOURCE"]
         PLUGIN_PATHS = [os.environ["B10_FROM_SOURCE"] +
+                            '/src/bin/cfgmgr/local_plugins',
+                             os.environ["B10_FROM_SOURCE"] +
                             '/src/bin/cfgmgr/plugins']
         programdirs = ['auth', 'cfgmgr', 'cmdctl', 'ddns', 'dhcp6', 'msgq',
                        'resolver', 'sockcreator', 'stats', 'xfrin', 'xfrout',

+ 52 - 25
src/lib/util/threads/sync.cc

@@ -12,6 +12,8 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#include "config.h"
+
 #include "sync.h"
 
 #include <exceptions/exceptions.h>
@@ -31,12 +33,16 @@ namespace thread {
 
 class Mutex::Impl {
 public:
-    Impl() :
-        locked_count(0)
+    Impl()
+#ifdef ENABLE_DEBUG
+        : locked_count(0)
+#endif // ENABLE_DEBUG
     {}
+
     pthread_mutex_t mutex;
-    // Only in debug mode
+#ifdef ENABLE_DEBUG
     size_t locked_count;
+#endif // ENABLE_DEBUG
 };
 
 namespace {
@@ -70,12 +76,20 @@ Mutex::Mutex() :
             isc_throw(isc::InvalidOperation, std::strerror(result));
     }
     Deinitializer deinitializer(attributes);
-    // TODO: Distinguish if debug mode is enabled in compilation.
-    // If so, it should be PTHREAD_MUTEX_NORMAL or NULL
+
+    // If debug mode is enabled in compilation, use the slower
+    // error-checking mutexes that detect deadlocks. Otherwise, use fast
+    // mutexes which don't. See the pthread_mutexattr_settype() POSIX
+    // documentation which describes these type attributes.
+#ifdef ENABLE_DEBUG
     result = pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_ERRORCHECK);
+#else
+    result = pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_NORMAL);
+#endif // ENABLE_DEBUG
     if (result != 0) {
         isc_throw(isc::InvalidOperation, std::strerror(result));
     }
+
     auto_ptr<Impl> impl(new Impl);
     result = pthread_mutex_init(&impl->mutex, &attributes);
     switch (result) {
@@ -93,12 +107,17 @@ Mutex::Mutex() :
 Mutex::~Mutex() {
     if (impl_ != NULL) {
         const int result = pthread_mutex_destroy(&impl_->mutex);
+
+#ifdef ENABLE_DEBUG
         const bool locked = impl_->locked_count != 0;
+#endif // ENABLE_DEBUG
+
         delete impl_;
         // We don't want to throw from the destructor. Also, if this ever
         // fails, something is really screwed up a lot.
         assert(result == 0);
 
+#ifdef ENABLE_DEBUG
         // We should not try to destroy a locked mutex, bad threaded monsters
         // could get loose if we ever do and it is also forbidden by pthreads.
 
@@ -106,29 +125,19 @@ Mutex::~Mutex() {
         // pthread_mutex_destroy should check for it already. But it seems
         // there are systems that don't check it.
         assert(!locked);
+#endif // ENABLE_DEBUG
     }
 }
 
+#ifdef ENABLE_DEBUG
+
 void
 Mutex::postLockAction() {
-    // This assertion would fail only in non-debugging mode, in which case
-    // this method wouldn't be called either, so we simply assert the
-    // condition.
     assert(impl_->locked_count == 0);
     ++impl_->locked_count;
 }
 
 void
-Mutex::lock() {
-    assert(impl_ != NULL);
-    const int result = pthread_mutex_lock(&impl_->mutex);
-    if (result != 0) {
-        isc_throw(isc::InvalidOperation, std::strerror(result));
-    }
-    postLockAction();           // Only in debug mode
-}
-
-void
 Mutex::preUnlockAction(bool throw_ok) {
     if (impl_->locked_count == 0) {
         if (throw_ok) {
@@ -141,20 +150,35 @@ Mutex::preUnlockAction(bool throw_ok) {
     --impl_->locked_count;
 }
 
+bool
+Mutex::locked() const {
+    return (impl_->locked_count != 0);
+}
+
+#endif // ENABLE_DEBUG
+
+void
+Mutex::lock() {
+    assert(impl_ != NULL);
+    const int result = pthread_mutex_lock(&impl_->mutex);
+    if (result != 0) {
+        isc_throw(isc::InvalidOperation, std::strerror(result));
+    }
+#ifdef ENABLE_DEBUG
+    postLockAction();           // Only in debug mode
+#endif // ENABLE_DEBUG
+}
+
 void
 Mutex::unlock() {
     assert(impl_ != NULL);
+#ifdef ENABLE_DEBUG
     preUnlockAction(false);     // Only in debug mode.  Ensure no throw.
+#endif // ENABLE_DEBUG
     const int result = pthread_mutex_unlock(&impl_->mutex);
     assert(result == 0); // This should never be possible
 }
 
-// TODO: Disable in non-debug build
-bool
-Mutex::locked() const {
-    return (impl_->locked_count != 0);
-}
-
 class CondVar::Impl {
 public:
     Impl() {
@@ -187,10 +211,13 @@ CondVar::~CondVar() {
 
 void
 CondVar::wait(Mutex& mutex) {
+#ifdef ENABLE_DEBUG
     mutex.preUnlockAction(true);    // Only in debug mode
     const int result = pthread_cond_wait(&impl_->cond_, &mutex.impl_->mutex);
     mutex.postLockAction();     // Only in debug mode
-
+#else
+    const int result = pthread_cond_wait(&impl_->cond_, &mutex.impl_->mutex);
+#endif
     // pthread_cond_wait should normally succeed unless mutex is completely
     // broken.
     if (result != 0) {

+ 6 - 0
src/lib/util/threads/sync.h

@@ -112,6 +112,9 @@ private:
 
     // Commonly called after acquiring the lock, checking and updating
     // internal state for debug.
+    //
+    // Note that this method is only available when the build is
+    // configured with debugging support.
     void postLockAction();
 
     // Commonly called before releasing the lock, checking and updating
@@ -121,6 +124,9 @@ private:
     // fails; otherwise it aborts the process.  This parameter must be set
     // to false if the call to this shouldn't result in an exception (e.g.
     // when called from a destructor).
+    //
+    // Note that this method is only available when the build is
+    // configured with debugging support.
     void preUnlockAction(bool throw_ok);
 
     class Impl;

+ 4 - 0
src/lib/util/threads/tests/condvar_unittest.cc

@@ -149,11 +149,15 @@ TEST_F(CondVarTest, DISABLED_destroyWhileWait) {
         }, "");
 }
 
+#ifdef ENABLE_DEBUG
+
 TEST_F(CondVarTest, badWait) {
     // In our implementation, wait() requires acquiring the lock beforehand.
     EXPECT_THROW(condvar_.wait(mutex_), isc::InvalidOperation);
 }
 
+#endif // ENABLE_DEBUG
+
 TEST_F(CondVarTest, emptySignal) {
     // It's okay to call signal when no one waits.
     EXPECT_NO_THROW(condvar_.signal());

+ 9 - 3
src/lib/util/threads/tests/lock_unittest.cc

@@ -26,20 +26,26 @@ using namespace isc::util::thread;
 
 namespace {
 
-// If we try to lock the debug mutex multiple times, it should throw.
+#ifdef ENABLE_DEBUG
+
+// If we try to lock the debug mutex multiple times, it should
+// throw. This test will complete properly only when pthread debugging
+// facilities are enabled by configuring the code for debug build.
 TEST(MutexTest, lockMultiple) {
-    // TODO: Once we support non-debug mutexes, disable the test if we compile
-    // with them.
     Mutex mutex;
     EXPECT_FALSE(mutex.locked()); // Debug-only build
+
     Mutex::Locker l1(mutex);
     EXPECT_TRUE(mutex.locked()); // Debug-only build
+
     EXPECT_THROW({
         Mutex::Locker l2(mutex); // Attempt to lock again.
     }, isc::InvalidOperation);
     EXPECT_TRUE(mutex.locked()); // Debug-only build
 }
 
+#endif // ENABLE_DEBUG
+
 // Destroying a locked mutex is a bad idea as well
 #ifdef EXPECT_DEATH
 TEST(MutexTest, destroyLocked) {

+ 1 - 0
tests/lettuce/configurations/auth/.gitignore

@@ -0,0 +1 @@
+/auth_basic.config

+ 22 - 0
tests/lettuce/configurations/auth/auth_basic.config.orig

@@ -0,0 +1,22 @@
+{
+    "version": 2,
+    "Logging": {
+        "loggers": [ {
+            "debuglevel": 99,
+            "severity": "DEBUG",
+            "name": "*"
+        } ]
+    },
+    "Auth": {
+        "listen_on": [ {
+            "port": 47806,
+            "address": "127.0.0.1"
+        } ]
+    },
+    "Boss": {
+        "components": {
+            "b10-auth": { "kind": "needed", "special": "auth" },
+            "b10-cmdctl": { "special": "cmdctl", "kind": "needed" }
+        }
+    }
+}

+ 20 - 0
tests/lettuce/features/auth_basic.feature

@@ -0,0 +1,20 @@
+Feature: Basic Authoritative DNS server
+    This feature set is for testing the execution of the b10-auth
+    component using its default datasource configurations. This
+    will start it and perform queries against it.
+
+    Scenario: Query builtin bind zone
+        Given I have bind10 running with configuration auth/auth_basic.config
+        And wait for bind10 stderr message BIND10_STARTED_CC
+        And wait for bind10 stderr message CMDCTL_STARTED
+        And wait for bind10 stderr message AUTH_SERVER_STARTED
+
+        bind10 module Auth should be running
+        And bind10 module Resolver should not be running
+
+        A query for example.com should have rcode REFUSED
+        A query for version.bind type TXT class CH should have rcode NOERROR
+        A query for authors.bind type TXT class CH should have rcode NOERROR
+
+        # TODO: to be compatible with BIND 9
+        # A query for nonexistent.bind type TXT class CH should have rcode REFUSED

+ 2 - 0
tests/lettuce/features/terrain/terrain.py

@@ -49,6 +49,8 @@ copylist = [
      "configurations/example.org.config"],
     ["configurations/bindctl/bindctl.config.orig",
      "configurations/bindctl/bindctl.config"],
+    ["configurations/auth/auth_basic.config.orig",
+     "configurations/auth/auth_basic.config"],
     ["configurations/resolver/resolver_basic.config.orig",
      "configurations/resolver/resolver_basic.config"],
     ["configurations/multi_instance/multi_auth.config.orig",