[svn] commit: r3437 - in /branches/trac358: ./ src/lib/bench/ src/lib/bench/example/ src/lib/bench/tests/ src/lib/datasrc/ src/lib/datasrc/tests/ src/lib/exceptions/ src/lib/exceptions/tests/ src/lib/python/isc/ src/lib/python/isc/Util/ src/lib/python/isc/config/ src/lib/python/isc/config/tests/ src/lib/python/isc/datasrc/ src/lib/python/isc/log/ src/lib/python/isc/log/tests/ src/lib/python/isc/net/ src/lib/python/isc/notify/ src/lib/python/isc/notify/tests/ src/lib/xfr/
BIND 10 source code commits
bind10-changes at lists.isc.org
Thu Nov 4 06:21:08 UTC 2010
Author: jinmei
Date: Thu Nov 4 06:21:08 2010
New Revision: 3437
Log:
sync with trunk
Added:
branches/trac358/src/lib/python/isc/net/
- copied from r3436, trunk/src/lib/python/isc/net/
Removed:
branches/trac358/src/lib/python/isc/Util/
Modified:
branches/trac358/ChangeLog
branches/trac358/configure.ac
branches/trac358/src/lib/bench/Makefile.am
branches/trac358/src/lib/bench/example/search_bench.cc
branches/trac358/src/lib/bench/tests/Makefile.am
branches/trac358/src/lib/datasrc/Makefile.am
branches/trac358/src/lib/datasrc/static_datasrc.cc
branches/trac358/src/lib/datasrc/tests/Makefile.am
branches/trac358/src/lib/datasrc/tests/run_unittests.cc
branches/trac358/src/lib/exceptions/exceptions.cc
branches/trac358/src/lib/exceptions/tests/run_unittests.cc
branches/trac358/src/lib/python/isc/Makefile.am
branches/trac358/src/lib/python/isc/config/ccsession.py
branches/trac358/src/lib/python/isc/config/module_spec.py
branches/trac358/src/lib/python/isc/config/tests/ccsession_test.py
branches/trac358/src/lib/python/isc/config/tests/cfgmgr_test.py
branches/trac358/src/lib/python/isc/config/tests/unittest_fakesession.py
branches/trac358/src/lib/python/isc/datasrc/master.py
branches/trac358/src/lib/python/isc/log/log.py
branches/trac358/src/lib/python/isc/log/tests/log_test.py
branches/trac358/src/lib/python/isc/notify/notify_out.py
branches/trac358/src/lib/python/isc/notify/tests/notify_out_test.py
branches/trac358/src/lib/xfr/Makefile.am
branches/trac358/src/lib/xfr/python_xfr.cc
branches/trac358/src/lib/xfr/xfrout_client.cc
Modified: branches/trac358/ChangeLog
==============================================================================
--- branches/trac358/ChangeLog (original)
+++ branches/trac358/ChangeLog Thu Nov 4 06:21:08 2010
@@ -1,3 +1,70 @@
+ 114. [build] jinmei
+ Supported clang++. Note: Boost >= 1.44 is required.
+ (Trac #365, svn r3383)
+
+ 113. [func]* zhanglikun
+ Folder name 'utils'(the folder in /src/lib/python/isc/) has been
+ renamed to 'util'. Programs that used 'import isc.utils.process'
+ now need to use 'import isc.util.process'. The folder
+ /src/lib/python/isc/Util is removed since it isn't used by any
+ program. (Trac #364, r3382)
+
+ 112. [func] zhang likun
+ Add one mixin class to override the naive serve_forever() provided
+ in python library socketserver. Instead of polling for shutdwon
+ every poll_interval seconds, one socketpair is used to wake up
+ the waiting server.(Trac #352, svn r3366)
+
+ 111. [bug]* zhanglikun, Michal Vaner
+ Make sure process xfrin/xfrout/zonemgr/cmdctl can be stoped
+ properly when user enter "ctrl+c" or 'Boss shutdown' command
+ through bindctl.
+
+ The ZonemgrRefresh.run_timer and NotifyOut.dispatcher spawn
+ a thread themselves.
+ (Trac #335, svn r3273)
+
+ 110. [func] Michal Vaner
+ Added isc.net.check module to check ip addresses and ports for
+ correctness and isc.net.addr to hold IP address. The bind10, xfrin
+ and cmdctl programs are modified to use it.
+ (Trac #353, svn r3240)
+
+ 109. [func] naokikambe
+ Added the initial version of the stats module for the statistics
+ feature of BIND 10, which supports the restricted features and
+ items and reports via bindctl command (Trac #191, r3218)
+ Added the document of the stats module, which is about how stats
+ module collects the data (Trac #170, [wiki:StatsModule])
+
+ 108. [func] jerry
+ src/bin/zonemgr: Provide customizable configurations for
+ lowerbound_refresh, lowerbound_retry, max_transfer_timeout and
+ jitter_scope. (Trac #340, r3205)
+
+ 107. [func] zhang likun
+ Remove the parameter 'db_file' for command 'retransfer' of
+ xfrin module. xfrin.spec will not be generated by script.
+ (Trac #329, r3171)
+
+ 106. [bug] zhang likun
+ When xfrin can't connect with one zone's master, it should tell
+ the bad news to zonemgr, so that zonemgr can reset the timer for
+ that zone. (Trac #329, r3170)
+
+ 105. [bug] Michal Vaner
+ Python processes: they no longer take 100% CPU while idle
+ due to a busy loop in reading command session in a nonblocking way.
+ (Trac #349, svn r3153), (Trac #382, svn r3294)
+
+ 104. [bug] jerry
+ bin/zonemgr: zonemgr should be attempting to refresh expired zones.
+ (Trac #336, r3139)
+
+ 103. [bug] jerry
+ lib/python/isc/log: Fixed an issue with python logging,
+ python log shouldn't die with OSError.(Trac #267, r3137)
+
102. [build] jinmei
Disable threads in ASIO to minimize build time dependency.
(Trac #345, r3100)
@@ -89,8 +156,8 @@
zone axfr/ixfr finishing, the server will notify its slaves.
(Trac #289, svn r2737)
- 86. [func] jerry
- bin/zonemgr: Added zone manager module. The zone manager is one
+ 86. [func] jerry
+ bin/zonemgr: Added zone manager module. The zone manager is one
of the co-operating processes of BIND10, which keeps track of
timers and other information necessary for BIND10 to act as a
slave. (Trac #215, svn r2737)
Modified: branches/trac358/configure.ac
==============================================================================
--- branches/trac358/configure.ac (original)
+++ branches/trac358/configure.ac Thu Nov 4 06:21:08 2010
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.59])
-AC_INIT(bind10-devel, 20100701, bind10-dev at isc.org)
+AC_INIT(bind10-devel, 20101013, bind10-dev at isc.org)
AC_CONFIG_SRCDIR(README)
AM_INIT_AUTOMAKE
AC_CONFIG_HEADERS([config.h])
@@ -17,6 +17,8 @@
# Identify the compiler: this check must be after AC_PROG_CXX and AC_LANG.
AM_CONDITIONAL(USE_GXX, test "X${GXX}" = "Xyes")
AC_CHECK_DECL([__SUNPRO_CC], [SUNCXX="yes"], [SUNCXX="no"])
+AC_CHECK_DECL([__clang__], [CLANGPP="yes"], [CLANGPP="no"])
+AM_CONDITIONAL(USE_CLANGPP, test "X${CLANGPP}" = "Xyes")
# Linker options
@@ -261,7 +263,6 @@
[ --with-gtest=PATH specify a path to gtest header files (PATH/include) and library (PATH/lib)],
gtest_path="$withval", gtest_path="no")
-
USE_LCOV="no"
if test "$lcov" != "no"; then
# force gtest if not set
@@ -314,12 +315,14 @@
fi
done
fi
+CPPFLAGS_SAVES="$CPPFLAGS"
if test "${boost_include_path}" ; then
BOOST_INCLUDES="-I${boost_include_path}"
CPPFLAGS="$CPPFLAGS $BOOST_INCLUDES"
fi
AC_CHECK_HEADERS([boost/shared_ptr.hpp boost/foreach.hpp],,
AC_MSG_ERROR([Missing required header files.]))
+CPPFLAGS="$CPPFLAGS_SAVES"
AC_SUBST(BOOST_INCLUDES)
#
@@ -435,7 +438,7 @@
fi
AC_ARG_ENABLE(man, [AC_HELP_STRING([--enable-man],
- [regenerate man pages [default=no]])] ,enable_man=yes, enable_man=no)
+ [regenerate man pages [default=no]])], enable_man=yes, enable_man=no)
AM_CONDITIONAL(ENABLE_MAN, test x$enable_man != xno)
@@ -472,6 +475,13 @@
src/bin/xfrout/tests/Makefile
src/bin/zonemgr/Makefile
src/bin/zonemgr/tests/Makefile
+ src/bin/stats/Makefile
+ src/bin/stats/tests/Makefile
+ src/bin/stats/tests/isc/Makefile
+ src/bin/stats/tests/isc/cc/Makefile
+ src/bin/stats/tests/isc/config/Makefile
+ src/bin/stats/tests/isc/util/Makefile
+ src/bin/stats/tests/testdata/Makefile
src/bin/usermgr/Makefile
src/bin/tests/Makefile
src/lib/Makefile
@@ -482,8 +492,8 @@
src/lib/cc/tests/Makefile
src/lib/python/Makefile
src/lib/python/isc/Makefile
- src/lib/python/isc/utils/Makefile
- src/lib/python/isc/utils/tests/Makefile
+ src/lib/python/isc/util/Makefile
+ src/lib/python/isc/util/tests/Makefile
src/lib/python/isc/datasrc/Makefile
src/lib/python/isc/cc/Makefile
src/lib/python/isc/cc/tests/Makefile
@@ -491,6 +501,8 @@
src/lib/python/isc/config/tests/Makefile
src/lib/python/isc/log/Makefile
src/lib/python/isc/log/tests/Makefile
+ src/lib/python/isc/net/Makefile
+ src/lib/python/isc/net/tests/Makefile
src/lib/python/isc/notify/Makefile
src/lib/python/isc/notify/tests/Makefile
src/lib/config/Makefile
@@ -515,7 +527,6 @@
src/bin/cmdctl/cmdctl.spec.pre
src/bin/xfrin/tests/xfrin_test
src/bin/xfrin/xfrin.py
- src/bin/xfrin/xfrin.spec.pre
src/bin/xfrin/run_b10-xfrin.sh
src/bin/xfrout/xfrout.py
src/bin/xfrout/xfrout.spec.pre
@@ -525,6 +536,12 @@
src/bin/zonemgr/zonemgr.spec.pre
src/bin/zonemgr/tests/zonemgr_test
src/bin/zonemgr/run_b10-zonemgr.sh
+ src/bin/stats/stats.py
+ src/bin/stats/stats_stub.py
+ src/bin/stats/stats.spec.pre
+ src/bin/stats/run_b10-stats.sh
+ src/bin/stats/run_b10-stats_stub.sh
+ src/bin/stats/tests/stats_test
src/bin/bind10/bind10.py
src/bin/bind10/tests/bind10_test
src/bin/bind10/run_bind10.sh
@@ -558,6 +575,9 @@
chmod +x src/bin/xfrin/run_b10-xfrin.sh
chmod +x src/bin/xfrout/run_b10-xfrout.sh
chmod +x src/bin/zonemgr/run_b10-zonemgr.sh
+ chmod +x src/bin/stats/tests/stats_test
+ chmod +x src/bin/stats/run_b10-stats.sh
+ chmod +x src/bin/stats/run_b10-stats_stub.sh
chmod +x src/bin/bind10/run_bind10.sh
chmod +x src/bin/cmdctl/tests/cmdctl_test
chmod +x src/bin/xfrin/tests/xfrin_test
@@ -588,6 +608,8 @@
Name: $PACKAGE_NAME
Version: $PACKAGE_VERSION
+C++ Compiler: $CXX
+
Flags:
DEFS: $DEFS
CPPFLAGS: $CPPFLAGS
@@ -597,6 +619,7 @@
Python: ${PYTHON_INCLUDES}
${PYTHON_LDFLAGS}
${PYTHON_LIB}
+ Boost: ${BOOST_INCLUDES}
SQLite: $SQLITE_CFLAGS
$SQLITE_LIBS
@@ -616,4 +639,3 @@
Now you can type "make" to build BIND 10
EOF
-
Modified: branches/trac358/src/lib/bench/Makefile.am
==============================================================================
--- branches/trac358/src/lib/bench/Makefile.am (original)
+++ branches/trac358/src/lib/bench/Makefile.am Thu Nov 4 06:21:08 2010
@@ -1,6 +1,7 @@
SUBDIRS = . tests example
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
+AM_CPPFLAGS += $(BOOST_INCLUDES)
AM_CXXFLAGS = $(B10_CXXFLAGS)
CLEANFILES = *.gcno *.gcda
Modified: branches/trac358/src/lib/bench/example/search_bench.cc
==============================================================================
--- branches/trac358/src/lib/bench/example/search_bench.cc (original)
+++ branches/trac358/src/lib/bench/example/search_bench.cc Thu Nov 4 06:21:08 2010
@@ -16,6 +16,7 @@
#include <unistd.h> // for getpid
+#include <cassert>
#include <cstdlib> // for rand
#include <algorithm>
#include <iostream>
@@ -42,9 +43,11 @@
vector<int>::const_iterator end_key = keys_.end();
for (iter = keys_.begin(); iter != end_key; ++iter) {
if (Sorted) {
- binary_search(data_.begin(), data_.end(), *iter);
+ // perform simple sanity check with assert() to ensure
+ // compiler optimization won't skip the search.
+ assert(binary_search(data_.begin(), data_.end(), *iter));
} else {
- find(data_.begin(), data_.end(), *iter);
+ assert(find(data_.begin(), data_.end(), *iter) != data_.end());
}
}
return (keys_.size());
@@ -63,7 +66,7 @@
vector<int>::const_iterator iter;
vector<int>::const_iterator end_key = keys_.end();
for (iter = keys_.begin(); iter != end_key; ++iter) {
- data_.find(*iter);
+ assert(data_.find(*iter) != data_.end());
}
return (keys_.size());
}
Modified: branches/trac358/src/lib/bench/tests/Makefile.am
==============================================================================
--- branches/trac358/src/lib/bench/tests/Makefile.am (original)
+++ branches/trac358/src/lib/bench/tests/Makefile.am Thu Nov 4 06:21:08 2010
@@ -1,4 +1,5 @@
AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
+AM_CPPFLAGS += $(BOOST_INCLUDES)
AM_CPPFLAGS += -DTEST_DATA_DIR=\"$(srcdir)/testdata\"
AM_CXXFLAGS = $(B10_CXXFLAGS)
Modified: branches/trac358/src/lib/datasrc/Makefile.am
==============================================================================
--- branches/trac358/src/lib/datasrc/Makefile.am (original)
+++ branches/trac358/src/lib/datasrc/Makefile.am Thu Nov 4 06:21:08 2010
@@ -2,6 +2,7 @@
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
+AM_CPPFLAGS += $(BOOST_INCLUDES)
AM_CPPFLAGS += $(SQLITE_CFLAGS)
AM_CXXFLAGS = $(B10_CXXFLAGS)
Modified: branches/trac358/src/lib/datasrc/static_datasrc.cc
==============================================================================
--- branches/trac358/src/lib/datasrc/static_datasrc.cc (original)
+++ branches/trac358/src/lib/datasrc/static_datasrc.cc Thu Nov 4 06:21:08 2010
@@ -110,14 +110,12 @@
"0 28800 7200 604800 86400"));
}
-StaticDataSrc::StaticDataSrc()
-{
+StaticDataSrc::StaticDataSrc() {
setClass(RRClass::CH());
impl_ = new StaticDataSrcImpl;
}
-StaticDataSrc::~StaticDataSrc()
-{
+StaticDataSrc::~StaticDataSrc() {
delete impl_;
}
Modified: branches/trac358/src/lib/datasrc/tests/Makefile.am
==============================================================================
--- branches/trac358/src/lib/datasrc/tests/Makefile.am (original)
+++ branches/trac358/src/lib/datasrc/tests/Makefile.am Thu Nov 4 06:21:08 2010
@@ -1,5 +1,7 @@
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += -I$(top_builddir)/src/lib/dns -I$(top_srcdir)/src/lib/dns
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+AM_CPPFLAGS += $(SQLITE_CFLAGS)
AM_CPPFLAGS += -DTEST_DATA_DIR=\"$(srcdir)/testdata\"
AM_CXXFLAGS = $(B10_CXXFLAGS)
Modified: branches/trac358/src/lib/datasrc/tests/run_unittests.cc
==============================================================================
--- branches/trac358/src/lib/datasrc/tests/run_unittests.cc (original)
+++ branches/trac358/src/lib/datasrc/tests/run_unittests.cc Thu Nov 4 06:21:08 2010
@@ -19,8 +19,7 @@
#include <dns/tests/unittest_util.h>
int
-main(int argc, char* argv[])
-{
+main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
isc::UnitTestUtil::addDataPath(TEST_DATA_DIR);
Modified: branches/trac358/src/lib/exceptions/exceptions.cc
==============================================================================
--- branches/trac358/src/lib/exceptions/exceptions.cc (original)
+++ branches/trac358/src/lib/exceptions/exceptions.cc Thu Nov 4 06:21:08 2010
@@ -23,8 +23,7 @@
namespace isc {
const char*
-Exception::what() const throw()
-{
+Exception::what() const throw() {
const char* whatstr = "isc::Exception";
// XXX: even though it's very unlikely that c_str() throws an exception,
Modified: branches/trac358/src/lib/exceptions/tests/run_unittests.cc
==============================================================================
--- branches/trac358/src/lib/exceptions/tests/run_unittests.cc (original)
+++ branches/trac358/src/lib/exceptions/tests/run_unittests.cc Thu Nov 4 06:21:08 2010
@@ -17,8 +17,7 @@
#include <gtest/gtest.h>
int
-main(int argc, char* argv[])
-{
+main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
return (RUN_ALL_TESTS());
}
Modified: branches/trac358/src/lib/python/isc/Makefile.am
==============================================================================
--- branches/trac358/src/lib/python/isc/Makefile.am (original)
+++ branches/trac358/src/lib/python/isc/Makefile.am Thu Nov 4 06:21:08 2010
@@ -1,4 +1,4 @@
-SUBDIRS = datasrc cc config log notify utils # Util
+SUBDIRS = datasrc cc config log net notify util
python_PYTHON = __init__.py
Modified: branches/trac358/src/lib/python/isc/config/ccsession.py
==============================================================================
--- branches/trac358/src/lib/python/isc/config/ccsession.py (original)
+++ branches/trac358/src/lib/python/isc/config/ccsession.py Thu Nov 4 06:21:08 2010
@@ -1,4 +1,5 @@
# Copyright (C) 2009 Internet Systems Consortium.
+# Copyright (C) 2010 CZ NIC
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@@ -169,20 +170,35 @@
time-critical, it is strongly recommended to only use
check_command(), and not look at the socket at all."""
return self._session._socket
-
+
def close(self):
"""Close the session to the command channel"""
self._session.close()
- def check_command(self):
- """Check whether there is a command or configuration update
- on the channel. Call the corresponding callback function if
- there is. This function does a non-blocking read on the
- cc session, and returns nothing. It will respond to any
- command by either an error or the answer message returned
- by the callback, unless the latter is None."""
- msg, env = self._session.group_recvmsg(True)
-
+ def check_command(self, nonblock=True):
+ """Check whether there is a command or configuration update on
+ the channel. This function does a read on the cc session, and
+ returns nothing.
+ It calls check_command_without_recvmsg()
+ to parse the received message.
+
+ If nonblock is True, it just checks if there's a command
+ and does nothing if there isn't. If nonblock is False, it
+ waits until it arrives. It temporarily sets timeout to infinity,
+ because commands may not come in arbitrary long time."""
+ timeout_orig = self._session.get_timeout()
+ self._session.set_timeout(0)
+ try:
+ msg, env = self._session.group_recvmsg(nonblock)
+ finally:
+ self._session.set_timeout(timeout_orig)
+ self.check_command_without_recvmsg(msg, env)
+
+ def check_command_without_recvmsg(self, msg, env):
+ """Parse the given message to see if there is a command or a
+ configuration update. Calls the corresponding handler
+ functions if present. Responds on the channel if the
+ handler returns a message."""
# should we default to an answer? success-by-default? unhandled error?
if msg is not None and not 'result' in msg:
answer = None
@@ -200,7 +216,8 @@
newc = self._remote_module_configs[module_name].get_local_config()
isc.cc.data.merge(newc, new_config)
self._remote_module_configs[module_name].set_local_config(newc)
- return
+ # For other modules, we're not supposed to answer
+ return
# ok, so apparently this update is for us.
errors = []
Modified: branches/trac358/src/lib/python/isc/config/module_spec.py
==============================================================================
--- branches/trac358/src/lib/python/isc/config/module_spec.py (original)
+++ branches/trac358/src/lib/python/isc/config/module_spec.py Thu Nov 4 06:21:08 2010
@@ -316,7 +316,9 @@
item_name = spec['item_name']
item_optional = spec['item_optional']
- if item_name in data:
+ if not data and item_optional:
+ return True
+ elif item_name in data:
return _validate_item(spec, full, data[item_name], errors)
elif full and not item_optional:
if errors != None:
Modified: branches/trac358/src/lib/python/isc/config/tests/ccsession_test.py
==============================================================================
--- branches/trac358/src/lib/python/isc/config/tests/ccsession_test.py (original)
+++ branches/trac358/src/lib/python/isc/config/tests/ccsession_test.py Thu Nov 4 06:21:08 2010
@@ -23,7 +23,7 @@
import os
from isc.config.ccsession import *
from isc.config.config_data import BIND10_CONFIG_DATA_VERSION
-from unittest_fakesession import FakeModuleCCSession
+from unittest_fakesession import FakeModuleCCSession, WouldBlockForever
class TestHelperFunctions(unittest.TestCase):
def test_parse_answer(self):
@@ -125,6 +125,8 @@
self.assertTrue("Spec1" in fake_session.subscriptions)
self.assertEqual(len(fake_session.message_queue), 0)
+ fake_session.group_sendmsg(None, 'Spec1')
+ fake_session.group_sendmsg(None, 'Spec1')
self.assertRaises(ModuleCCSessionError, mccs.start)
self.assertEqual(len(fake_session.message_queue), 2)
self.assertEqual({'command': ['module_spec', {'module_name': 'Spec1'}]},
@@ -150,6 +152,8 @@
fake_session = FakeModuleCCSession()
mccs = self.create_session("spec2.spec", None, None, fake_session)
self.assertEqual(len(fake_session.message_queue), 0)
+ fake_session.group_sendmsg(None, 'Spec2')
+ fake_session.group_sendmsg(None, 'Spec2')
self.assertRaises(ModuleCCSessionError, mccs.start)
self.assertEqual(len(fake_session.message_queue), 2)
self.assertEqual({'command': ['module_spec', mccs.specification._module_spec]},
@@ -173,6 +177,8 @@
mccs = self.create_session("spec2.spec", None, None, fake_session)
mccs.set_config_handler(self.my_config_handler_ok)
self.assertEqual(len(fake_session.message_queue), 0)
+ fake_session.group_sendmsg(None, 'Spec2')
+ fake_session.group_sendmsg(None, 'Spec2')
self.assertRaises(ModuleCCSessionError, mccs.start)
self.assertEqual(len(fake_session.message_queue), 2)
self.assertEqual({'command': ['module_spec', mccs.specification._module_spec]},
@@ -196,6 +202,8 @@
mccs = self.create_session("spec2.spec", None, None, fake_session)
mccs.set_config_handler(self.my_config_handler_ok)
self.assertEqual(len(fake_session.message_queue), 0)
+ fake_session.group_sendmsg(None, 'Spec2')
+ fake_session.group_sendmsg(None, 'Spec2')
self.assertRaises(ModuleCCSessionError, mccs.start)
self.assertEqual(len(fake_session.message_queue), 2)
self.assertEqual({'command': ['module_spec', mccs.specification._module_spec]},
@@ -327,30 +335,173 @@
self.assertEqual(len(fake_session.message_queue), 1)
self.assertEqual({'result': [2, 'Spec2 has no command handler']},
fake_session.get_message('Spec2', None))
-
- def test_check_command7(self):
- fake_session = FakeModuleCCSession()
- mccs = self.create_session("spec2.spec", None, None, fake_session)
- mccs.set_command_handler(self.my_command_handler_ok)
+
+ """Many check_command tests look too similar, this is common body."""
+ def common_check_command_check(self, cmd_handler,
+ cmd_check=lambda mccs, _: mccs.check_command()):
+ fake_session = FakeModuleCCSession()
+ mccs = self.create_session("spec2.spec", None, None, fake_session)
+ mccs.set_command_handler(cmd_handler)
self.assertEqual(len(fake_session.message_queue), 0)
cmd = isc.config.ccsession.create_command("print_message", "just a message")
fake_session.group_sendmsg(cmd, 'Spec2')
self.assertEqual(len(fake_session.message_queue), 1)
- mccs.check_command()
+ cmd_check(mccs, fake_session)
+ return fake_session
+
+ def test_check_command7(self):
+ fake_session = self.common_check_command_check(
+ self.my_command_handler_ok)
self.assertEqual(len(fake_session.message_queue), 1)
self.assertEqual({'result': [0]},
fake_session.get_message('Spec2', None))
-
+
def test_check_command8(self):
- fake_session = FakeModuleCCSession()
- mccs = self.create_session("spec2.spec", None, None, fake_session)
- mccs.set_command_handler(self.my_command_handler_no_answer)
+ fake_session = self.common_check_command_check(
+ self.my_command_handler_no_answer)
+ self.assertEqual(len(fake_session.message_queue), 0)
+
+ def test_check_command_block(self):
+ """See if the message gets there even in blocking mode."""
+ fake_session = self.common_check_command_check(
+ self.my_command_handler_ok,
+ lambda mccs, _: mccs.check_command(False))
+ self.assertEqual(len(fake_session.message_queue), 1)
+ self.assertEqual({'result': [0]},
+ fake_session.get_message('Spec2', None))
+
+ def test_check_command_block_timeout(self):
+ """Check it works if session has timeout and it sets it back."""
+ def cmd_check(mccs, session):
+ session.set_timeout(1)
+ mccs.check_command(False)
+ fake_session = self.common_check_command_check(
+ self.my_command_handler_ok, cmd_check)
+ self.assertEqual(len(fake_session.message_queue), 1)
+ self.assertEqual({'result': [0]},
+ fake_session.get_message('Spec2', None))
+ self.assertEqual(fake_session.get_timeout(), 1)
+
+ def test_check_command_blocks_forever(self):
+ """Check it would wait forever checking a command."""
+ fake_session = FakeModuleCCSession()
+ mccs = self.create_session("spec2.spec", None, None, fake_session)
+ mccs.set_command_handler(self.my_command_handler_ok)
+ self.assertRaises(WouldBlockForever, lambda: mccs.check_command(False))
+
+ def test_check_command_blocks_forever_timeout(self):
+ """Like above, but it should wait forever even with timeout here."""
+ fake_session = FakeModuleCCSession()
+ fake_session.set_timeout(1)
+ mccs = self.create_session("spec2.spec", None, None, fake_session)
+ mccs.set_command_handler(self.my_command_handler_ok)
+ self.assertRaises(WouldBlockForever, lambda: mccs.check_command(False))
+
+ def test_check_command_without_recvmsg1(self):
+ "copied from test_check_command2"
+ fake_session = FakeModuleCCSession()
+ mccs = self.create_session("spec1.spec", None, None, fake_session)
+ mccs.set_config_handler(self.my_config_handler_ok)
+ self.assertEqual(len(fake_session.message_queue), 0)
+ cmd = isc.config.ccsession.create_command(isc.config.ccsession.COMMAND_CONFIG_UPDATE, { 'Spec1': 'abcd' })
+ env = { 'group': 'Spec1', 'from':None };
+ mccs.check_command_without_recvmsg(cmd, env)
+ self.assertEqual(len(fake_session.message_queue), 1)
+ self.assertEqual({'result': [1, 'No config_data specification']},
+ fake_session.get_message('Spec1', None))
+
+ def test_check_command_without_recvmsg2(self):
+ "copied from test_check_command3"
+ fake_session = FakeModuleCCSession()
+ mccs = self.create_session("spec2.spec", None, None, fake_session)
+ mccs.set_config_handler(self.my_config_handler_ok)
+ self.assertEqual(len(fake_session.message_queue), 0)
+ cmd = isc.config.ccsession.create_command(isc.config.ccsession.COMMAND_CONFIG_UPDATE, { 'Spec2': { 'item1': 2 }})
+ self.assertEqual(len(fake_session.message_queue), 0)
+ env = { 'group':'Spec2', 'from':None }
+ mccs.check_command_without_recvmsg(cmd, env)
+ self.assertEqual(len(fake_session.message_queue), 1)
+ self.assertEqual({'result': [0]},
+ fake_session.get_message('Spec2', None))
+
+ def test_check_command_without_recvmsg3(self):
+ "copied from test_check_command7"
+ fake_session = FakeModuleCCSession()
+ mccs = self.create_session("spec2.spec", None, None, fake_session)
+ mccs.set_command_handler(self.my_command_handler_ok)
self.assertEqual(len(fake_session.message_queue), 0)
cmd = isc.config.ccsession.create_command("print_message", "just a message")
- fake_session.group_sendmsg(cmd, 'Spec2')
- self.assertEqual(len(fake_session.message_queue), 1)
- mccs.check_command()
- self.assertEqual(len(fake_session.message_queue), 0)
+ env = { 'group':'Spec2', 'from':None }
+ self.assertEqual(len(fake_session.message_queue), 0)
+ mccs.check_command_without_recvmsg(cmd, env)
+ self.assertEqual({'result': [0]},
+ fake_session.get_message('Spec2', None))
+
+ def test_check_command_without_recvmsg_remote_module(self):
+ "copied from test_check_command3"
+ fake_session = FakeModuleCCSession()
+ mccs = self.create_session("spec1.spec", None, None, fake_session)
+ mccs.set_config_handler(self.my_config_handler_ok)
+ self.assertEqual(len(fake_session.message_queue), 0)
+
+ fake_session.group_sendmsg(None, 'Spec2')
+ rmodname = mccs.add_remote_config(self.spec_file("spec2.spec"))
+ print(fake_session.message_queue)
+ self.assertEqual({'command': ['get_config', {'module_name': 'Spec2'}]},
+ fake_session.get_message('ConfigManager', None))
+ self.assertEqual(len(fake_session.message_queue), 0)
+
+ cmd = isc.config.ccsession.create_command(isc.config.ccsession.COMMAND_CONFIG_UPDATE, { 'Spec2': { 'item1': 2 }})
+ env = { 'group':'Spec2', 'from':None }
+ self.assertEqual(len(fake_session.message_queue), 0)
+ mccs.check_command_without_recvmsg(cmd, env)
+ self.assertEqual(len(fake_session.message_queue), 0)
+
+ def test_check_command_without_recvmsg_remote_module2(self):
+ "copied from test_check_command3"
+ fake_session = FakeModuleCCSession()
+ mccs = self.create_session("spec1.spec", None, None, fake_session)
+ mccs.set_config_handler(self.my_config_handler_ok)
+ self.assertEqual(len(fake_session.message_queue), 0)
+
+ fake_session.group_sendmsg(None, 'Spec2')
+ rmodname = mccs.add_remote_config(self.spec_file("spec2.spec"))
+ self.assertEqual({'command': ['get_config', {'module_name': 'Spec2'}]},
+ fake_session.get_message('ConfigManager', None))
+ self.assertEqual(len(fake_session.message_queue), 0)
+
+ cmd = isc.config.ccsession.create_command(isc.config.ccsession.COMMAND_CONFIG_UPDATE, { 'Spec3': { 'item1': 2 }})
+ env = { 'group':'Spec3', 'from':None }
+ self.assertEqual(len(fake_session.message_queue), 0)
+ mccs.check_command_without_recvmsg(cmd, env)
+ self.assertEqual(len(fake_session.message_queue), 0)
+
+ def test_check_command_block_timeout(self):
+ """Check it works if session has timeout and it sets it back."""
+ def cmd_check(mccs, session):
+ session.set_timeout(1)
+ mccs.check_command(False)
+ fake_session = self.common_check_command_check(
+ self.my_command_handler_ok, cmd_check)
+ self.assertEqual(len(fake_session.message_queue), 1)
+ self.assertEqual({'result': [0]},
+ fake_session.get_message('Spec2', None))
+ self.assertEqual(fake_session.get_timeout(), 1)
+
+ def test_check_command_blocks_forever(self):
+ """Check it would wait forever checking a command."""
+ fake_session = FakeModuleCCSession()
+ mccs = self.create_session("spec2.spec", None, None, fake_session)
+ mccs.set_command_handler(self.my_command_handler_ok)
+ self.assertRaises(WouldBlockForever, lambda: mccs.check_command(False))
+
+ def test_check_command_blocks_forever_timeout(self):
+ """Like above, but it should wait forever even with timeout here."""
+ fake_session = FakeModuleCCSession()
+ fake_session.set_timeout(1)
+ mccs = self.create_session("spec2.spec", None, None, fake_session)
+ mccs.set_command_handler(self.my_command_handler_ok)
+ self.assertRaises(WouldBlockForever, lambda: mccs.check_command(False))
def test_remote_module(self):
fake_session = FakeModuleCCSession()
@@ -360,6 +511,7 @@
self.assertRaises(ModuleCCSessionError, mccs.get_remote_config_value, "Spec2", "item1")
self.assertFalse("Spec2" in fake_session.subscriptions)
+ fake_session.group_sendmsg(None, 'Spec2')
rmodname = mccs.add_remote_config(self.spec_file("spec2.spec"))
self.assertTrue("Spec2" in fake_session.subscriptions)
self.assertEqual("Spec2", rmodname)
@@ -373,6 +525,7 @@
self.assertRaises(ModuleCCSessionError, mccs.get_remote_config_value, "Spec2", "item1")
# test if unsubscription is alse sent when object is deleted
+ fake_session.group_sendmsg({'result' : [0]}, 'Spec2')
rmodname = mccs.add_remote_config(self.spec_file("spec2.spec"))
self.assertTrue("Spec2" in fake_session.subscriptions)
mccs = None
@@ -383,6 +536,7 @@
fake_session = FakeModuleCCSession()
mccs = self.create_session("spec1.spec", None, None, fake_session)
mccs.set_command_handler(self.my_command_handler_ok)
+ fake_session.group_sendmsg(None, 'Spec2')
rmodname = mccs.add_remote_config(self.spec_file("spec2.spec"))
# remove the 'get config' from the queue
Modified: branches/trac358/src/lib/python/isc/config/tests/cfgmgr_test.py
==============================================================================
--- branches/trac358/src/lib/python/isc/config/tests/cfgmgr_test.py (original)
+++ branches/trac358/src/lib/python/isc/config/tests/cfgmgr_test.py Thu Nov 4 06:21:08 2010
@@ -255,6 +255,7 @@
self.fake_session.get_message(self.name, None))
self.assertEqual(len(self.fake_session.message_queue), 0)
+ self.fake_session.group_sendmsg(None, 'ConfigManager')
self._handle_msg_helper({ "command": [ "set_config", [ ] ] },
{'result': [1, 'Wrong number of arguments']} )
self._handle_msg_helper({ "command": [ "set_config", [ self.name, { "test": 125 }] ] },
Modified: branches/trac358/src/lib/python/isc/config/tests/unittest_fakesession.py
==============================================================================
--- branches/trac358/src/lib/python/isc/config/tests/unittest_fakesession.py (original)
+++ branches/trac358/src/lib/python/isc/config/tests/unittest_fakesession.py Thu Nov 4 06:21:08 2010
@@ -16,6 +16,13 @@
# $Id$
import isc
+
+class WouldBlockForever(Exception):
+ """
+ This is thrown by the FakeModuleCCSession if it would need
+ to block forever for incoming message.
+ """
+ pass
#
# We can probably use a more general version of this
@@ -64,13 +71,18 @@
if 'group' in env:
self.message_queue.append([ env['group'], None, msg])
- def group_recvmsg(self, blocking, seq = None):
+ def group_recvmsg(self, nonblock=True, seq = None):
for qm in self.message_queue:
- if qm[0] in self.subscriptions and (qm[1] == None or qm[1] in self.subscriptions[qm[0]]):
+ if qm[0] in self.subscriptions and (qm[1] == None or qm[1] in
+ self.subscriptions[qm[0]]):
self.message_queue.remove(qm)
return qm[2], {'group': qm[0], 'from': qm[1]}
if self._timeout == 0:
- return None, None
+ if nonblock:
+ return None, None
+ else:
+ raise WouldBlockForever(
+ "Blocking read without timeout and no message ready")
else:
raise isc.cc.SessionTimeout("Timeout set but no data to "
"return to group_recvmsg()")
@@ -88,3 +100,6 @@
def set_timeout(self, timeout):
self._timeout = timeout
+
+ def get_timeout(self):
+ return self._timeout
Modified: branches/trac358/src/lib/python/isc/datasrc/master.py
==============================================================================
--- branches/trac358/src/lib/python/isc/datasrc/master.py (original)
+++ branches/trac358/src/lib/python/isc/datasrc/master.py Thu Nov 4 06:21:08 2010
@@ -269,7 +269,7 @@
if second[-1] == '.':
self.__origin = second
elif not self.__origin:
- raise MasterFileError("$ORIGIN is not absolute in record:%s" % s)
+ raise MasterFileError("$ORIGIN is not absolute in record: %s" % s)
elif self.__origin != '.':
self.__origin = second + '.' + self.__origin
else:
Modified: branches/trac358/src/lib/python/isc/log/log.py
==============================================================================
--- branches/trac358/src/lib/python/isc/log/log.py (original)
+++ branches/trac358/src/lib/python/isc/log/log.py Thu Nov 4 06:21:08 2010
@@ -19,6 +19,7 @@
To use, simply 'import isc.log.log' and log away!
"""
import os
+import sys
import syslog
import logging
import logging.handlers
@@ -31,47 +32,73 @@
'error' : logging.ERROR,
'critical' : logging.CRITICAL}
-
FORMATTER = logging.Formatter("%(name)s: %(levelname)s: %(message)s")
TIME_FORMATTER = logging.Formatter("%(asctime)s.%(msecs)03d %(name)s: %(levelname)s: %(message)s",
"%d-%b-%Y %H:%M:%S")
+def log_err(err_type, err_msg):
+ sys.stderr.write(err_type + ": " + "%s.\n" % str(err_msg)[str(err_msg).find(']')+1:])
+
+
class NSFileLogHandler(logging.handlers.RotatingFileHandler):
"""RotatingFileHandler: replace RotatingFileHandler with a custom handler"""
def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=0):
- dir = os.path.split(filename)
- if not (os.path.exists(dir[0])):
- os.makedirs(dir[0])
- super(NSFileLogHandler, self).__init__(filename, mode, maxBytes,
+ abs_file_name = self._get_abs_file_path(filename)
+ """Create log directory beforehand, because the underlying logging framework won't
+ create non-exsiting log directory on writing logs.
+ """
+ if not (os.path.exists(os.path.dirname(abs_file_name))):
+ os.makedirs(os.path.dirname(abs_file_name))
+ super(NSFileLogHandler, self).__init__(abs_file_name, mode, maxBytes,
backupCount, encoding, delay)
+
+ def handleError(self, record):
+ """Overwrite handleError to provide more user-friendly error messages"""
+ if logging.raiseExceptions:
+ ei = sys.exc_info()
+ if (ei[1]):
+ sys.stderr.write("[b10-logging] : " + str(ei[1]))
+
+ def _get_abs_file_path(self, file_name):
+ """ Get absolute file path"""
+ # For a bare filename, log_dir will be set the current directory.
+ if not os.path.dirname(file_name):
+ abs_file_dir = os.getcwd()
+ else:
+ abs_file_dir = os.path.abspath(os.path.dirname(file_name))
+ abs_file_name = os.path.join(abs_file_dir, os.path.basename(file_name))
+ return abs_file_name
def shouldRollover(self, record):
"""Rewrite RotatingFileHandler.shouldRollover.
If the log file is deleted at runtime, a new file will be created.
"""
- dfn = self.baseFilename
+ dfn = self.baseFilename
if (self.stream) and (not os.path.exists(dfn)): #Does log file exist?
- self.stream.close()
- dir = os.path.split(dfn)
- if not (os.path.exists(dir[0])): #Does log subdirectory exist?
- os.makedirs(dir[0])
+ self.stream = None
+ """ Log directory may be deleted while bind10 running or updated with a
+ non-existing directory. Need to create log directory beforehand, because
+ the underlying logging framework won't create non-exsiting log directory
+ on writing logs.
+ """
+ if not (os.path.exists(os.path.dirname(dfn))): #Does log subdirectory exist?
+ os.makedirs(os.path.dirname(dfn))
self.stream = self._open()
return super(NSFileLogHandler, self).shouldRollover(record)
def update_config(self, file_name, backup_count, max_bytes):
"""Update RotatingFileHandler configuration.
-
- If the file path does not exist, we will use the old log file.
+ Changes will be picked up in the next call to shouldRollover().
+
input:
log file name
max backup count
predetermined log file size
"""
- dir = os.path.split(file_name)
- if (os.path.exists(dir[0])):
- self.baseFilename = file_name
+ abs_file_name = self._get_abs_file_path(file_name)
+ self.baseFilename = abs_file_name
self.maxBytes = max_bytes
self.backupCount = backup_count
@@ -162,8 +189,9 @@
try:
self._file_handler = NSFileLogHandler(filename = log_file,
maxBytes = max_bytes, backupCount = backup_count)
- except IOError:
+ except (IOError, OSError) as e:
self._file_handler = None
+ log_err("[b10-logging] Add file handler fail", str(e))
return
self._file_handler.setFormatter(TIME_FORMATTER)
self.addHandler(self._file_handler)
@@ -244,6 +272,9 @@
logger.log_message('info', "We have a %s", "mysterious problem").
"""
logLevel = LEVELS.get(level, logging.NOTSET)
- self.log(logLevel, msg, *args, **kwargs)
-
-
+ try:
+ self.log(logLevel, msg, *args, **kwargs)
+ except (TypeError, KeyError) as e:
+ sys.stderr.write("[b10-logging] Log message fail %s\n" % (str(e)))
+
+
Modified: branches/trac358/src/lib/python/isc/log/tests/log_test.py
==============================================================================
--- branches/trac358/src/lib/python/isc/log/tests/log_test.py (original)
+++ branches/trac358/src/lib/python/isc/log/tests/log_test.py Thu Nov 4 06:21:08 2010
@@ -20,6 +20,7 @@
from isc.log.log import *
import unittest
import os
+import sys
import tempfile
@@ -46,21 +47,48 @@
self.handler.shouldRollover(record)
self.assertTrue(os.path.exists(self.FILE_LOG1.name))
+ def test_get_absolute_file_path(self):
+ abs_file_name = self.handler._get_abs_file_path(self.FILE_LOG1.name)
+ self.assertEqual(abs_file_name, self.FILE_LOG1.name)
+ # test bare filename
+ file_name1 = "bind10.py"
+ abs_file_name = self.handler._get_abs_file_path(file_name1)
+ self.assertEqual(abs_file_name, os.path.join(os.getcwd(), file_name1))
+ # test relative path
+ file_name2 = "./bind10.py"
+ abs_file_name = self.handler._get_abs_file_path(file_name2)
+ self.assertEqual(abs_file_name, os.path.join(os.getcwd(), os.path.basename(file_name2)))
+
def test_update_config(self):
self.handler.update_config(self.FILE_LOG2.name, 3, 512)
self.assertEqual(self.handler.baseFilename, self.FILE_LOG2.name)
self.assertEqual(self.handler.maxBytes, 512)
self.assertEqual(self.handler.backupCount, 3)
- dir = os.path.split(self.FILE_LOG3.name)
- path = dir[0] + "path_not_exists"
- update_file = os.path.join(path, dir[1])
-
- if not os.path.exists(path):
- self.handler.update_config(update_file, 4, 1024)
- self.assertEqual(self.handler.baseFilename, self.FILE_LOG2.name)
- self.assertEqual(self.handler.maxBytes, 1024)
- self.assertEqual(self.handler.backupCount, 4)
+ # check the existence of new log file.
+ # emit() will call shouldRollover() to update the log file
+ if(os.path.exists(self.FILE_LOG2.name)):
+ os.remove(self.FILE_LOG2.name)
+ record = logging.LogRecord(None, None, "", 0, "rotate file handler", (), None, None)
+ self.handler.emit(record)
+ self.assertTrue(os.path.exists(self.FILE_LOG2.name))
+
+ def test_handle_Error(self):
+ if(os.path.exists(self.FILE_LOG3.name)):
+ os.remove(self.FILE_LOG3.name)
+ # redirect error message to file
+ savederr = sys.stderr
+ errfd = open(self.FILE_LOG3.name, 'w+')
+ sys.stderr = errfd
+ record = logging.LogRecord(None, None, "", 0, "record message", (), None, None)
+ try:
+ raise ValueError("ValueError")
+ except ValueError:
+ self.handler.handleError(record)
+
+ self.assertEqual("[b10-logging] : ValueError", errfd.read())
+ sys.stderr = savederr
+ errfd.close()
def tearDown(self):
self.handler.flush()
@@ -78,50 +106,46 @@
self.assertEqual(sysLevel, syslog.LOG_ERR)
def test_emit(self):
- record = logging.LogRecord(None, None, "", 0, "syslog handler", (), None, None)
+ syslog_message = "bind10 syslog testing"
+ record = logging.LogRecord(None, None, "", 0, syslog_message, (), None, None)
self.handler.emit(record)
-
class TestLogging(unittest.TestCase):
def setUp(self):
- self.FILE_STREAM_LOG1= tempfile.NamedTemporaryFile(mode='w',
+ self.FILE_STREAM_LOG1 = tempfile.NamedTemporaryFile(mode='w',
prefix="b10",
delete=True)
- self.FILE_STREAM_LOG2= tempfile.NamedTemporaryFile(mode='w',
+ self.FILE_STREAM_LOG2 = tempfile.NamedTemporaryFile(mode='w',
prefix="b10",
delete=True)
- self.FILE_STREAM_LOG3= tempfile.NamedTemporaryFile(mode='w',
+ self.FILE_STREAM_LOG3 = tempfile.NamedTemporaryFile(mode='w',
prefix="b10",
delete=True)
self.file_stream_logger = NSLogger('File_Stream_Logger',
self.FILE_STREAM_LOG1.name,
'debug', 5, 1024, True)
self.syslog_logger = NSLogger('SysLogger', '', 'info', 5, 1024, False)
+ self.stderr_bak = sys.stderr
+ sys.stderr = open(os.devnull, 'w')
def test_logging_init(self):
self.assertNotEqual(self.file_stream_logger._file_handler, None)
self.assertNotEqual(self.file_stream_logger._stream_handler, None)
self.assertEqual(self.file_stream_logger._syslog_handler, None)
- ret = self.file_stream_logger._file_handler in self.file_stream_logger.handlers
- self.assertTrue(ret)
- ret = self.file_stream_logger._stream_handler in self.file_stream_logger.handlers
- self.assertTrue(ret)
- ret = self.file_stream_logger._syslog_handler in self.file_stream_logger.handlers
- self.assertFalse(ret)
+ self.assertIn(self.file_stream_logger._file_handler, self.file_stream_logger.handlers)
+ self.assertIn(self.file_stream_logger._stream_handler, self.file_stream_logger.handlers)
+ self.assertNotIn(self.file_stream_logger._syslog_handler, self.file_stream_logger.handlers)
logLevel = LEVELS.get('debug', logging.NOTSET)
self.assertEqual(self.file_stream_logger.getEffectiveLevel(), logLevel)
self.assertEqual(self.syslog_logger._file_handler, None)
self.assertEqual(self.syslog_logger._stream_handler, None)
self.assertNotEqual(self.syslog_logger._syslog_handler, None)
- ret = self.syslog_logger._file_handler in self.syslog_logger.handlers
- self.assertFalse(ret)
- ret = self.syslog_logger._stream_handler in self.syslog_logger.handlers
- self.assertFalse(ret)
- ret = self.syslog_logger._syslog_handler in self.syslog_logger.handlers
- self.assertTrue(ret)
+ self.assertNotIn(self.syslog_logger._file_handler, self.syslog_logger.handlers)
+ self.assertNotIn(self.syslog_logger._stream_handler, self.syslog_logger.handlers)
+ self.assertIn(self.syslog_logger._syslog_handler, self.syslog_logger.handlers)
logLevel = LEVELS.get('info', logging.NOTSET)
self.assertEqual(self.syslog_logger.getEffectiveLevel(), logLevel)
@@ -131,41 +155,52 @@
self.syslog_logger.removeHandler(self.syslog_logger._file_handler)
self.syslog_logger._add_rotate_handler('', 5, 1024)
- ret = self.syslog_logger._file_handler in self.syslog_logger.handlers
- self.assertFalse(ret)
+ self.assertNotIn(self.syslog_logger._file_handler, self.syslog_logger.handlers)
self.syslog_logger._add_rotate_handler(self.FILE_STREAM_LOG1.name, 5, 1024)
- ret = self.syslog_logger._file_handler in self.syslog_logger.handlers
- self.assertTrue(ret)
+ self.assertIn(self.syslog_logger._file_handler, self.syslog_logger.handlers)
+
+ # test IOError exception
+ self.syslog_logger.removeHandler(self.syslog_logger._file_handler)
+ log_file = self.FILE_STREAM_LOG1.name + '/logfile'
+ self.syslog_logger._add_rotate_handler(log_file, 5, 1024)
+ self.assertNotIn(self.syslog_logger._file_handler, self.syslog_logger.handlers)
def test_add_stream_handler(self):
if(self.file_stream_logger._stream_handler in self.file_stream_logger.handlers):
self.file_stream_logger.removeHandler(self.file_stream_logger._stream_handler)
self.file_stream_logger._add_stream_handler()
- ret = self.file_stream_logger._stream_handler in self.file_stream_logger.handlers
- self.assertTrue(ret)
+ self.assertIn(self.file_stream_logger._stream_handler, self.file_stream_logger.handlers)
def test_add_syslog_handler(self):
if(self.syslog_logger._syslog_handler in self.syslog_logger.handlers):
self.syslog_logger.removeHandler(self.syslog_logger._syslog_handler)
self.syslog_logger._add_syslog_handler()
- ret = self.syslog_logger._syslog_handler in self.syslog_logger.handlers
- self.assertTrue(ret)
+ self.assertIn(self.syslog_logger._syslog_handler, self.syslog_logger.handlers)
def test_update_rotate_handler(self):
self.file_stream_logger._update_rotate_handler(self.FILE_STREAM_LOG2.name, 4, 1024)
- ret = self.file_stream_logger._file_handler in self.file_stream_logger.handlers
- self.assertTrue(ret)
+ self.assertIn(self.file_stream_logger._file_handler, self.file_stream_logger.handlers)
self.file_stream_logger._update_rotate_handler('', 5, 1024)
- ret = self.file_stream_logger._file_handler in self.file_stream_logger.handlers
- self.assertFalse(ret)
+ self.assertNotIn(self.file_stream_logger._file_handler, self.file_stream_logger.handlers)
self.file_stream_logger._update_rotate_handler(self.FILE_STREAM_LOG1.name, 4, 1024)
- ret = self.file_stream_logger._file_handler in self.file_stream_logger.handlers
- self.assertTrue(ret)
+ self.assertIn(self.file_stream_logger._file_handler, self.file_stream_logger.handlers)
+
+ def test_get_config(self):
+ config_data = {'log_file' : self.FILE_STREAM_LOG1.name,
+ 'log_severity' : 'critical',
+ 'log_versions' : 4,
+ 'log_max_bytes' : 1024}
+ self.file_stream_logger._get_config(config_data)
+ self.assertEqual(self.file_stream_logger._log_file, self.FILE_STREAM_LOG1.name)
+ self.assertEqual(self.file_stream_logger._severity, 'critical')
+ self.assertEqual(self.file_stream_logger._versions, 4)
+ self.assertEqual(self.file_stream_logger._max_bytes, 1024)
+
def test_update_config(self):
update_config = {'log_file' : self.FILE_STREAM_LOG1.name,
@@ -183,15 +218,20 @@
'log_max_bytes' : 1024}
self.file_stream_logger.update_config(update_config)
self.file_stream_logger.log_message('debug', 'debug message')
- self.file_stream_logger.log_message('info', 'info message')
self.file_stream_logger.log_message('warning', 'warning message')
self.file_stream_logger.log_message('error', 'error message')
+ #test non-exist log level
+ self.assertRaises(None, self.file_stream_logger.log_message('not-exist', 'not exist message'))
+ #test log_message KeyError exception
+ self.assertRaises(None, self.file_stream_logger.log_message('critical', 'critical message', extra=['message', 'asctime']))
self.assertTrue(os.path.exists(self.FILE_STREAM_LOG3.name))
def tearDown(self):
self.FILE_STREAM_LOG1.close()
self.FILE_STREAM_LOG2.close()
self.FILE_STREAM_LOG3.close()
+ sys.stderr.flush();
+ sys.stderr = self.stderr_bak
if __name__ == '__main__':
unittest.main()
Modified: branches/trac358/src/lib/python/isc/notify/notify_out.py
==============================================================================
--- branches/trac358/src/lib/python/isc/notify/notify_out.py (original)
+++ branches/trac358/src/lib/python/isc/notify/notify_out.py Thu Nov 4 06:21:08 2010
@@ -19,6 +19,7 @@
import socket
import threading
import time
+import errno
from isc.datasrc import sqlite3_ds
import isc
try:
@@ -44,29 +45,11 @@
_BAD_QR = 4
_BAD_REPLY_PACKET = 5
+SOCK_DATA = b's'
def addr_to_str(addr):
return '%s#%s' % (addr[0], addr[1])
-def dispatcher(notifier):
- '''The loop function for handling notify related events.
- If one zone get the notify reply before timeout, call the
- handle to process the reply. If one zone can't get the notify
- before timeout, call the handler to resend notify or notify
- next slave.
- notifier: one object of class NotifyOut. '''
- while True:
- replied_zones, not_replied_zones = notifier._wait_for_notify_reply()
- if len(replied_zones) == 0 and len(not_replied_zones) == 0:
- time.sleep(_IDLE_SLEEP_TIME) #TODO set a better time for idle sleep
- continue
-
- for name_ in replied_zones:
- notifier._zone_notify_handler(replied_zones[name_], _EVENT_READ)
-
- for name_ in not_replied_zones:
- if not_replied_zones[name_].notify_timeout <= time.time():
- notifier._zone_notify_handler(not_replied_zones[name_], _EVENT_TIMEOUT)
-
+
class ZoneNotifyInfo:
'''This class keeps track of notify-out information for one zone.'''
@@ -115,14 +98,17 @@
class NotifyOut:
'''This class is used to handle notify logic for all zones(sending
- notify message to its slaves).The only interface provided to
- the user is send_notify(). the object of this class should be
- used together with function dispatcher(). '''
+ notify message to its slaves). notify service can be started by
+ calling dispatcher(), and it can be stoped by calling shutdown()
+ in another thread. '''
def __init__(self, datasrc_file, log=None, verbose=True):
self._notify_infos = {} # key is (zone_name, zone_class)
self._waiting_zones = []
self._notifying_zones = []
self._log = log
+ self._serving = False
+ self._read_sock, self._write_sock = socket.socketpair()
+ self._read_sock.setblocking(False)
self.notify_num = 0 # the count of in progress notifies
self._verbose = verbose
self._lock = threading.Lock()
@@ -164,6 +150,70 @@
self._notify_infos[zone_id].prepare_notify_out()
self.notify_num += 1
self._notifying_zones.append(zone_id)
+
+ def _dispatcher(self, started_event):
+ started_event.set() # Let the master know we are alive already
+ while self._serving:
+ replied_zones, not_replied_zones = self._wait_for_notify_reply()
+
+ for name_ in replied_zones:
+ self._zone_notify_handler(replied_zones[name_], _EVENT_READ)
+
+ for name_ in not_replied_zones:
+ if not_replied_zones[name_].notify_timeout <= time.time():
+ self._zone_notify_handler(not_replied_zones[name_], _EVENT_TIMEOUT)
+
+ def dispatcher(self, daemon=False):
+ """Spawns a thread that will handle notify related events.
+
+ If one zone get the notify reply before timeout, call the
+ handle to process the reply. If one zone can't get the notify
+ before timeout, call the handler to resend notify or notify
+ next slave.
+
+ The thread can be stopped by calling shutdown().
+
+ Returns the thread object to anyone interested.
+ """
+
+ if self._serving:
+ raise RuntimeError(
+ 'Dispatcher already running, tried to start twice')
+
+ # Prepare for launch
+ self._serving = True
+ started_event = threading.Event()
+
+ # Start
+ self._thread = threading.Thread(target=self._dispatcher,
+ args=[started_event])
+ if daemon:
+ self._thread.daemon = daemon
+ self._thread.start()
+
+ # Wait for it to get started
+ started_event.wait()
+
+ # Return it to anyone listening
+ return self._thread
+
+ def shutdown(self):
+ """Stop the dispatcher() thread. Blocks until the thread stopped."""
+
+ if not self._serving:
+ raise RuntimeError('Tried to stop while not running')
+
+ # Ask it to stop
+ self._serving = False
+ self._write_sock.send(SOCK_DATA) # make self._read_sock be readable.
+
+ # Wait for it
+ self._thread.join()
+
+ # Clean up
+ self._write_sock = None
+ self._read_sock = None
+ self._thread = None
def _get_rdata_data(self, rr):
return rr[7].strip()
@@ -200,49 +250,68 @@
return addr_list
def _prepare_select_info(self):
- '''Prepare the information for select(), returned
- value is one tuple
+ '''
+ Prepare the information for select(), returned
+ value is one tuple
(block_timeout, valid_socks, notifying_zones)
block_timeout: the timeout for select()
valid_socks: sockets list for waiting ready reading.
- notifying_zones: the zones which have been triggered
- for notify. '''
+ notifying_zones: the zones which have been triggered
+ for notify.
+ '''
valid_socks = []
notifying_zones = {}
- min_timeout = None
+ min_timeout = None
for info in self._notify_infos:
sock = self._notify_infos[info].get_socket()
if sock:
valid_socks.append(sock)
notifying_zones[info] = self._notify_infos[info]
tmp_timeout = self._notify_infos[info].notify_timeout
- if min_timeout:
+ if min_timeout is not None:
if tmp_timeout < min_timeout:
min_timeout = tmp_timeout
else:
min_timeout = tmp_timeout
-
- block_timeout = 0
- if min_timeout:
+
+ block_timeout = _IDLE_SLEEP_TIME
+ if min_timeout is not None:
block_timeout = min_timeout - time.time()
if block_timeout < 0:
block_timeout = 0
-
+
return (block_timeout, valid_socks, notifying_zones)
def _wait_for_notify_reply(self):
- '''receive notify replies in specified time. returned value
- is one tuple:(replied_zones, not_replied_zones)
+ '''
+ Receive notify replies in specified time. returned value
+ is one tuple:(replied_zones, not_replied_zones). ({}, {}) is
+ returned if shutdown() was called.
+
replied_zones: the zones which receive notify reply.
not_replied_zones: the zones which haven't got notify reply.
+
'''
- (block_timeout, valid_socks, notifying_zones) = self._prepare_select_info()
+ (block_timeout, valid_socks, notifying_zones) = \
+ self._prepare_select_info()
+ # This is None only during some tests
+ if self._read_sock is not None:
+ valid_socks.append(self._read_sock)
try:
r_fds, w, e = select.select(valid_socks, [], [], block_timeout)
except select.error as err:
if err.args[0] != EINTR:
- return [], []
-
+ return {}, {}
+
+ if self._read_sock in r_fds: # user has called shutdown()
+ try:
+ # Noone should write anything else than shutdown
+ assert self._read_sock.recv(len(SOCK_DATA)) == SOCK_DATA
+ return {}, {}
+ except socket.error as e: # Workaround around rare linux bug
+ if e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK:
+ raise
+
not_replied_zones = {}
replied_zones = {}
for info in notifying_zones:
Modified: branches/trac358/src/lib/python/isc/notify/tests/notify_out_test.py
==============================================================================
--- branches/trac358/src/lib/python/isc/notify/tests/notify_out_test.py (original)
+++ branches/trac358/src/lib/python/isc/notify/tests/notify_out_test.py Thu Nov 4 06:21:08 2010
@@ -20,7 +20,7 @@
import time
import socket
from isc.datasrc import sqlite3_ds
-from isc.notify import notify_out
+from isc.notify import notify_out, SOCK_DATA
class TestZoneNotifyInfo(unittest.TestCase):
def setUp(self):
@@ -53,8 +53,6 @@
class TestNotifyOut(unittest.TestCase):
def setUp(self):
- self.old_stdout = sys.stdout
- sys.stdout = open(os.devnull, 'w')
self._db_file = tempfile.NamedTemporaryFile(delete=False)
sqlite3_ds.load(self._db_file.name, 'cn.', self._cn_data_reader)
sqlite3_ds.load(self._db_file.name, 'com.', self._com_data_reader)
@@ -70,7 +68,6 @@
info.notify_slaves.append(('1.1.1.1', 5353))
def tearDown(self):
- sys.stdout = self.old_stdout
self._db_file.close()
os.unlink(self._db_file.name)
@@ -123,6 +120,20 @@
self.assertTrue(('com.', 'IN') in timeout_zones.keys())
self.assertLess(time.time(), self._notify._notify_infos[('com.', 'IN')].notify_timeout)
+ def test_wait_for_notify_reply_2(self):
+ # Test the returned value when the read_side socket is readable.
+ self._notify.send_notify('cn.')
+ self._notify.send_notify('com.')
+
+ # Now make one socket be readable
+ self._notify._notify_infos[('cn.', 'IN')].notify_timeout = time.time() + 10
+ self._notify._notify_infos[('com.', 'IN')].notify_timeout = time.time() + 10
+ self._notify._read_sock, self._notify._write_sock = socket.socketpair()
+ self._notify._write_sock.send(SOCK_DATA)
+ replied_zones, timeout_zones = self._notify._wait_for_notify_reply()
+ self.assertEqual(0, len(replied_zones))
+ self.assertEqual(0, len(timeout_zones))
+
def test_notify_next_target(self):
self._notify.send_notify('cn.')
self._notify.send_notify('com.')
@@ -258,7 +269,7 @@
def test_prepare_select_info(self):
timeout, valid_fds, notifying_zones = self._notify._prepare_select_info()
- self.assertEqual(0, timeout)
+ self.assertEqual(notify_out._IDLE_SLEEP_TIME, timeout)
self.assertListEqual([], valid_fds)
self._notify._notify_infos[('cn.', 'IN')]._sock = 1
@@ -279,6 +290,12 @@
self.assertEqual(timeout, 0)
self.assertListEqual([2, 1], valid_fds)
+ def test_shutdown(self):
+ thread = self._notify.dispatcher()
+ self.assertTrue(thread.is_alive())
+ self._notify.shutdown()
+ self.assertFalse(thread.is_alive())
+
if __name__== "__main__":
unittest.main()
Modified: branches/trac358/src/lib/xfr/Makefile.am
==============================================================================
--- branches/trac358/src/lib/xfr/Makefile.am (original)
+++ branches/trac358/src/lib/xfr/Makefile.am Thu Nov 4 06:21:08 2010
@@ -1,8 +1,12 @@
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
+AM_CPPFLAGS += $(BOOST_INCLUDES)
AM_CXXFLAGS = $(B10_CXXFLAGS) -Wno-strict-aliasing
AM_CXXFLAGS += -Wno-unused-parameter # see src/lib/cc/Makefile.am
+if USE_CLANGPP
+AM_CXXFLAGS += -Wno-error
+endif
CLEANFILES = *.gcno *.gcda
Modified: branches/trac358/src/lib/xfr/python_xfr.cc
==============================================================================
--- branches/trac358/src/lib/xfr/python_xfr.cc (original)
+++ branches/trac358/src/lib/xfr/python_xfr.cc Thu Nov 4 06:21:08 2010
@@ -28,8 +28,7 @@
using namespace isc::xfr;
using namespace boost::python;
-BOOST_PYTHON_MODULE(bind10_xfr)
-{
+BOOST_PYTHON_MODULE(bind10_xfr) {
def("recv_fd", &recv_fd);
def("send_fd", &send_fd);
}
Modified: branches/trac358/src/lib/xfr/xfrout_client.cc
==============================================================================
--- branches/trac358/src/lib/xfr/xfrout_client.cc (original)
+++ branches/trac358/src/lib/xfr/xfrout_client.cc Thu Nov 4 06:21:08 2010
@@ -47,8 +47,7 @@
impl_(new XfroutClientImpl(file))
{}
-XfroutClient::~XfroutClient()
-{
+XfroutClient::~XfroutClient() {
delete impl_;
}
More information about the bind10-changes
mailing list