[svn] commit: r3018 - in /branches/trac311: ./ doc/guide/ src/bin/auth/ src/bin/auth/benchmarks/ src/bin/auth/tests/ src/bin/bind10/ src/bin/bind10/tests/ src/bin/bindctl/ src/bin/bindctl/tests/ src/bin/cfgmgr/ src/bin/cfgmgr/tests/ src/bin/cmdctl/ src/bin/cmdctl/tests/ src/bin/loadzone/ src/bin/loadzone/tests/correct/ src/bin/loadzone/tests/error/ src/bin/msgq/ src/bin/msgq/tests/ src/bin/xfrin/ src/bin/xfrin/tests/ src/bin/xfrout/ src/bin/xfrout/tests/ src/bin/zonemgr/ src/bin/zonemgr/tests/ src/lib/bench/ src/lib/bench/tests/ src/lib/cc/ src/lib/cc/tests/ src/lib/config/ src/lib/config/tests/ src/lib/datasrc/ src/lib/datasrc/tests/ src/lib/dns/ src/lib/dns/python/ src/lib/dns/python/tests/ src/lib/dns/rdata/generic/ src/lib/dns/tests/ src/lib/exceptions/tests/ src/lib/python/isc/cc/ src/lib/python/isc/cc/tests/ src/lib/python/isc/config/ src/lib/python/isc/config/tests/ src/lib/python/isc/dns/ src/lib/python/isc/log/ src/lib/python/isc/log/tests/ src/lib/python/isc/notify/ src/lib/python/isc/notify/tests/

BIND 10 source code commits bind10-changes at lists.isc.org
Sun Sep 26 03:25:19 UTC 2010


Author: jinmei
Date: Sun Sep 26 03:25:19 2010
New Revision: 3018

Log:
sync with trunk

Added:
    branches/trac311/src/bin/auth/benchmarks/
      - copied from r3017, trunk/src/bin/auth/benchmarks/
    branches/trac311/src/bin/zonemgr/b10-zonemgr.8
      - copied unchanged from r3017, trunk/src/bin/zonemgr/b10-zonemgr.8
    branches/trac311/src/bin/zonemgr/b10-zonemgr.xml
      - copied unchanged from r3017, trunk/src/bin/zonemgr/b10-zonemgr.xml
    branches/trac311/src/lib/dns/python/pydnspp.cc
      - copied, changed from r3017, trunk/src/lib/dns/python/pydnspp.cc
    branches/trac311/src/lib/dns/python/pydnspp_common.cc
      - copied unchanged from r3017, trunk/src/lib/dns/python/pydnspp_common.cc
    branches/trac311/src/lib/dns/python/pydnspp_common.h
      - copied unchanged from r3017, trunk/src/lib/dns/python/pydnspp_common.h
Removed:
    branches/trac311/src/lib/dns/message_test.py
    branches/trac311/src/lib/dns/python/libdns_python_common.cc
    branches/trac311/src/lib/dns/python/libdns_python_common.h
    branches/trac311/src/lib/dns/python/tests/test.py
Modified:
    branches/trac311/   (props changed)
    branches/trac311/ChangeLog
    branches/trac311/README
    branches/trac311/configure.ac
    branches/trac311/doc/guide/bind10-guide.html
    branches/trac311/doc/guide/bind10-guide.xml
    branches/trac311/src/bin/auth/Makefile.am
    branches/trac311/src/bin/auth/asio_link.cc
    branches/trac311/src/bin/auth/asio_link.h
    branches/trac311/src/bin/auth/auth_srv.cc
    branches/trac311/src/bin/auth/auth_srv.h
    branches/trac311/src/bin/auth/b10-auth.8
    branches/trac311/src/bin/auth/b10-auth.xml
    branches/trac311/src/bin/auth/main.cc
    branches/trac311/src/bin/auth/tests/auth_srv_unittest.cc
    branches/trac311/src/bin/bind10/Makefile.am
    branches/trac311/src/bin/bind10/bind10.8
    branches/trac311/src/bin/bind10/bind10.py.in
    branches/trac311/src/bin/bind10/bind10.xml
    branches/trac311/src/bin/bind10/tests/Makefile.am
    branches/trac311/src/bin/bindctl/Makefile.am
    branches/trac311/src/bin/bindctl/bindcmd.py
    branches/trac311/src/bin/bindctl/tests/Makefile.am
    branches/trac311/src/bin/cfgmgr/Makefile.am
    branches/trac311/src/bin/cfgmgr/tests/Makefile.am
    branches/trac311/src/bin/cmdctl/Makefile.am
    branches/trac311/src/bin/cmdctl/cmdctl.py.in
    branches/trac311/src/bin/cmdctl/tests/Makefile.am
    branches/trac311/src/bin/loadzone/Makefile.am
    branches/trac311/src/bin/loadzone/tests/correct/Makefile.am
    branches/trac311/src/bin/loadzone/tests/error/Makefile.am
    branches/trac311/src/bin/msgq/Makefile.am
    branches/trac311/src/bin/msgq/tests/Makefile.am
    branches/trac311/src/bin/xfrin/   (props changed)
    branches/trac311/src/bin/xfrin/Makefile.am
    branches/trac311/src/bin/xfrin/TODO
    branches/trac311/src/bin/xfrin/b10-xfrin.8
    branches/trac311/src/bin/xfrin/b10-xfrin.xml
    branches/trac311/src/bin/xfrin/tests/Makefile.am
    branches/trac311/src/bin/xfrin/tests/xfrin_test.py
    branches/trac311/src/bin/xfrin/xfrin.py.in
    branches/trac311/src/bin/xfrout/Makefile.am
    branches/trac311/src/bin/xfrout/TODO
    branches/trac311/src/bin/xfrout/b10-xfrout.8
    branches/trac311/src/bin/xfrout/b10-xfrout.xml
    branches/trac311/src/bin/xfrout/tests/Makefile.am
    branches/trac311/src/bin/xfrout/tests/xfrout_test.py
    branches/trac311/src/bin/xfrout/xfrout.py.in
    branches/trac311/src/bin/zonemgr/Makefile.am
    branches/trac311/src/bin/zonemgr/TODO
    branches/trac311/src/bin/zonemgr/tests/Makefile.am
    branches/trac311/src/bin/zonemgr/zonemgr.py.in
    branches/trac311/src/lib/bench/   (props changed)
    branches/trac311/src/lib/bench/tests/benchmark_unittest.cc
    branches/trac311/src/lib/cc/   (props changed)
    branches/trac311/src/lib/cc/data.cc
    branches/trac311/src/lib/cc/data.h
    branches/trac311/src/lib/cc/session.cc
    branches/trac311/src/lib/cc/session.h
    branches/trac311/src/lib/cc/tests/   (props changed)
    branches/trac311/src/lib/cc/tests/data_unittests.cc
    branches/trac311/src/lib/cc/tests/session_unittests.cc
    branches/trac311/src/lib/config/ccsession.cc
    branches/trac311/src/lib/config/ccsession.h
    branches/trac311/src/lib/config/config_data.cc
    branches/trac311/src/lib/config/config_data.h
    branches/trac311/src/lib/config/documentation.txt
    branches/trac311/src/lib/config/module_spec.cc
    branches/trac311/src/lib/config/module_spec.h
    branches/trac311/src/lib/config/tests/Makefile.am
    branches/trac311/src/lib/config/tests/ccsession_unittests.cc
    branches/trac311/src/lib/config/tests/fake_session.cc
    branches/trac311/src/lib/config/tests/fake_session.h
    branches/trac311/src/lib/config/tests/module_spec_unittests.cc
    branches/trac311/src/lib/datasrc/   (props changed)
    branches/trac311/src/lib/datasrc/data_source.cc
    branches/trac311/src/lib/datasrc/data_source.h
    branches/trac311/src/lib/datasrc/sqlite3_datasrc.cc
    branches/trac311/src/lib/datasrc/sqlite3_datasrc.h
    branches/trac311/src/lib/datasrc/static_datasrc.cc
    branches/trac311/src/lib/datasrc/static_datasrc.h
    branches/trac311/src/lib/datasrc/tests/datasrc_unittest.cc
    branches/trac311/src/lib/datasrc/tests/sqlite3_unittest.cc
    branches/trac311/src/lib/datasrc/tests/test_datasrc.cc
    branches/trac311/src/lib/datasrc/tests/test_datasrc.h
    branches/trac311/src/lib/dns/   (props changed)
    branches/trac311/src/lib/dns/Makefile.am
    branches/trac311/src/lib/dns/messagerenderer.h
    branches/trac311/src/lib/dns/name.cc
    branches/trac311/src/lib/dns/python/Makefile.am
    branches/trac311/src/lib/dns/python/README
    branches/trac311/src/lib/dns/python/message_python.cc
    branches/trac311/src/lib/dns/python/messagerenderer_python.cc
    branches/trac311/src/lib/dns/python/name_python.cc
    branches/trac311/src/lib/dns/python/question_python.cc
    branches/trac311/src/lib/dns/python/rdata_python.cc
    branches/trac311/src/lib/dns/python/rrclass_python.cc
    branches/trac311/src/lib/dns/python/rrset_python.cc
    branches/trac311/src/lib/dns/python/rrttl_python.cc
    branches/trac311/src/lib/dns/python/rrtype_python.cc
    branches/trac311/src/lib/dns/python/tests/message_python_test.py
    branches/trac311/src/lib/dns/python/tests/messagerenderer_python_test.py
    branches/trac311/src/lib/dns/python/tests/name_python_test.py
    branches/trac311/src/lib/dns/python/tests/question_python_test.py
    branches/trac311/src/lib/dns/python/tests/rdata_python_test.py
    branches/trac311/src/lib/dns/python/tests/rrclass_python_test.py
    branches/trac311/src/lib/dns/python/tests/rrset_python_test.py
    branches/trac311/src/lib/dns/python/tests/rrttl_python_test.py
    branches/trac311/src/lib/dns/python/tests/rrtype_python_test.py
    branches/trac311/src/lib/dns/rdata/generic/rrsig_46.cc   (props changed)
    branches/trac311/src/lib/dns/rrset.h
    branches/trac311/src/lib/dns/tests/   (props changed)
    branches/trac311/src/lib/exceptions/tests/   (props changed)
    branches/trac311/src/lib/python/isc/cc/Makefile.am
    branches/trac311/src/lib/python/isc/cc/session.py
    branches/trac311/src/lib/python/isc/cc/tests/Makefile.am
    branches/trac311/src/lib/python/isc/cc/tests/session_test.py
    branches/trac311/src/lib/python/isc/config/Makefile.am
    branches/trac311/src/lib/python/isc/config/ccsession.py
    branches/trac311/src/lib/python/isc/config/cfgmgr.py
    branches/trac311/src/lib/python/isc/config/tests/Makefile.am
    branches/trac311/src/lib/python/isc/config/tests/unittest_fakesession.py   (contents, props changed)
    branches/trac311/src/lib/python/isc/dns/__init__.py
    branches/trac311/src/lib/python/isc/log/Makefile.am
    branches/trac311/src/lib/python/isc/log/tests/Makefile.am
    branches/trac311/src/lib/python/isc/log/tests/log_test.py
    branches/trac311/src/lib/python/isc/notify/Makefile.am
    branches/trac311/src/lib/python/isc/notify/notify_out.py
    branches/trac311/src/lib/python/isc/notify/tests/Makefile.am

Modified: branches/trac311/ChangeLog
==============================================================================
--- branches/trac311/ChangeLog (original)
+++ branches/trac311/ChangeLog Sun Sep 26 03:25:19 2010
@@ -1,3 +1,51 @@
+  98.	[build]		jinmei
+	The ./configure script now tries to search some common include
+	paths for boost header files to minimize the need for explicit
+	configuration with --with-boost-include. (Trac #323, svn r3006)
+
+  97.	[func]		jinmei
+	Added a micro benchmark test for query processing of b10-auth.
+	(Trac #308, svn r2982)
+
+  96.	[bug]		jinmei
+	Fixed two small issues with configure: Do not set CXXFLAGS so that
+	it can be customized; Make sure --disable-static works.
+	(Trac #325, r2976)
+
+bind10-devel-20100917 released on September 17, 2010 
+
+  95.	[doc]		jreed
+	Add b10-zonemgr manual page. Update other docs to introduce
+	this secondary manager. (Trac #341, svn r2951)
+
+  95.	[bug]		jreed
+	bin/xfrout and bin/zonemgr: Fixed some stderr output.
+	(Trac #342, svn r2949)
+
+  94.	[bug]		jelte
+  	bin/xfrout:  Fixed a problem in xfrout where only 2 or 3 RRs
+	were used per DNS message in the xfrout stream.
+	(Trac #334, r2931)
+
+  93.	[bug]		jinmei
+	lib/datasrc: A DS query could crash the library (and therefore,
+	e.g. the authoritative server) if some RR of the same apex name
+	is stored in the hot spot cache.  (Trac #307, svn r2923)
+
+  92.	[func]*		jelte
+	libdns_python (the python wrappers for libdns++) has been renamed
+	to pydnspp (Python DNS++). Programs and libraries that used
+	'import libdns_python' now need to use 'import pydnspp'.
+	(Trac #314, r2902)
+
+  91.	[func]*		jinmei
+	lib/cc: Use const pointers and const member functions for the API
+	as much as possible for safer operations.  Basically this does not
+	change the observable behavior, but some of the API were changed
+	in a backward incompatible manner.  This change also involves more
+	copies, but at this moment the overhead is deemed acceptable.
+	(Trac #310, r2803)
+
   90.	[build]		jinmei
 	(Darwin/Mac OS X specific) Specify DYLD_LIBRARY_PATH for tests and
 	experimental run under the source tree.  Without this loadable

Modified: branches/trac311/README
==============================================================================
--- branches/trac311/README (original)
+++ branches/trac311/README Sun Sep 26 03:25:19 2010
@@ -17,7 +17,8 @@
 bus, b10-auth authoritative DNS server (with SQLite3 backend),
 b10-cmdctl remote control daemon, b10-cfgmgr configuration manager,
 b10-xfrin AXFR inbound service, b10-xfrout outgoing AXFR service,
-and a new libdns++ library for C++ with a python wrapper.
+b10-zonemgr secondary manager, and a new libdns++ library for C++
+with a python wrapper.
 
 Documentation is included and also available via the BIND 10
 website at http://bind10.isc.org/

Modified: branches/trac311/configure.ac
==============================================================================
--- branches/trac311/configure.ac (original)
+++ branches/trac311/configure.ac Sun Sep 26 03:25:19 2010
@@ -39,6 +39,14 @@
   [build programs with static link [[default=no]]]),
   [enable_static_link=yes], [enable_static_link=no])
 AM_CONDITIONAL(USE_STATIC_LINK, test $enable_static_link = yes)
+
+# Check validity about some libtool options
+if test $enable_static_link = yes -a $enable_static = no; then
+	AC_MSG_ERROR([--enable-static-link requires --enable-static])
+fi
+if test $enable_shared = no; then
+	AC_MSG_ERROR([BIND 10 requires shared libraries to be built])
+fi
 
 # OS dependent configuration
 SET_ENV_LIBRARY_PATH=no
@@ -167,7 +175,6 @@
 # specify the default warning flags in CXXFLAGS and let specific modules
 # "override" the default.
 
-CXXFLAGS=-g
 werror_ok=0
 
 # SunStudio compiler requires special compiler options for boost
@@ -270,14 +277,31 @@
 fi
 AC_SUBST(USE_LCOV)
 
+#
+# Configure Boost header path
+#
+# If explicitly specified, use it.
 AC_ARG_WITH([boost-include],
   AC_HELP_STRING([--with-boost-include=PATH],
     [specify exact directory for Boost headers]),
     [boost_include_path="$withval"])
+# If not specified, try some common paths.
+if test -z "$with_boost_include"; then
+	boostdirs="/usr/local /usr/pkg /opt /opt/local"
+	for d in $boostdirs
+	do
+		if test -f $d/include/boost/shared_ptr.hpp; then
+			boost_include_path=$d/include
+			break
+		fi
+	done
+fi
 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.]))
 AC_SUBST(BOOST_INCLUDES)
 
 #
@@ -389,10 +413,6 @@
 	CPPFLAGS="$CPPFLAGS -DASIO_DISABLE_DEV_POLL=1"
 fi
 
-# Check for headers from required devel kits.
-AC_CHECK_HEADERS([boost/shared_ptr.hpp boost/foreach.hpp],,
-  AC_MSG_ERROR([Missing required header files.]))
-
 AC_ARG_ENABLE(man, [AC_HELP_STRING([--enable-man],
   [regenerate man pages [default=no]])] ,enable_man=yes, enable_man=no)
 
@@ -423,6 +443,7 @@
                  src/bin/msgq/tests/Makefile
                  src/bin/auth/Makefile
                  src/bin/auth/tests/Makefile
+                 src/bin/auth/benchmarks/Makefile
                  src/bin/xfrin/Makefile
                  src/bin/xfrin/tests/Makefile
                  src/bin/xfrout/Makefile
@@ -544,7 +565,6 @@
 Flags:
   DEFS:          $DEFS
   CPPFLAGS:      $CPPFLAGS
-  CFLAGS:        $CFLAGS
   CXXFLAGS:      $CXXFLAGS
   B10_CXXFLAGS:  $B10_CXXFLAGS
 dnl includes too

Modified: branches/trac311/doc/guide/bind10-guide.html
==============================================================================
--- branches/trac311/doc/guide/bind10-guide.html (original)
+++ branches/trac311/doc/guide/bind10-guide.html Sun Sep 26 03:25:19 2010
@@ -1,8 +1,8 @@
-<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>BIND 10 Guide</title><link rel="stylesheet" href="bind10-guide.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.75.2"><meta name="description" content="This is the reference guide for BIND 10. The most up-to-date version of this document, along with other documents for BIND 10, can be found at ."></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="book" title="BIND 10 Guide"><div class="titlepage"><div><div><h1 class="title"><a name="id1168230342594"></a>BIND 10 Guide</h1></div><div><h2 class="subtitle">Administrator Reference for BIND 10</h2></div><div><p class="copyright">Copyright © 2010 Internet Systems Consortium, Inc.</p></div><div><div class="abstract" title="Abstract"><p class="title"><b>Abstract</b></p><p>This is the reference guide for BIND 10.</p><p>
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>BIND 10 Guide</title><link rel="stylesheet" href="bind10-guide.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.75.2"><meta name="description" content="This is the reference guide for BIND 10. The most up-to-date version of this document, along with other documents for BIND 10, can be found at ."></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="book" title="BIND 10 Guide"><div class="titlepage"><div><div><h1 class="title"><a name="id1168230298903"></a>BIND 10 Guide</h1></div><div><h2 class="subtitle">Administrator Reference for BIND 10</h2></div><div><p class="copyright">Copyright © 2010 Internet Systems Consortium, Inc.</p></div><div><div class="abstract" title="Abstract"><p class="title"><b>Abstract</b></p><p>This is the reference guide for BIND 10.</p><p>
         The most up-to-date version of this document, along with other documents
         for BIND 10, can be found at
         <a class="ulink" href="http://bind10.isc.org/docs" target="_top">http://bind10.isc.org/docs</a>.
-      </p></div></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="chapter"><a href="#intro">1. Introduction</a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230342718">Supported Platforms</a></span></dt><dt><span class="section"><a href="#id1168230342746">Required Software</a></span></dt><dt><span class="section"><a href="#starting_stopping">Starting and Stopping the Server</a></span></dt><dt><span class="section"><a href="#managing_once_running">Managing BIND 10</a></span></dt></dl></dd><dt><span class="chapter"><a href="#installation">2. Installation</a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230328220">Building Requirements</a></span></dt><dt><span class="section"><a href="#quickstart">Quick start</a></span></dt><dt><span class="section"><a href="#install">Installation from source</a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230328406">Download Tar File</a></span></dt><dt><s
 pan class="section"><a href="#id1168230328426">Retrieve from Subversion</a></span></dt><dt><span class="section"><a href="#id1168230328486">Configure before the build</a></span></dt><dt><span class="section"><a href="#id1168230328584">Build</a></span></dt><dt><span class="section"><a href="#id1168230328599">Install</a></span></dt><dt><span class="section"><a href="#id1168230328622">Install Hierarchy</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#bind10">3. Starting BIND10 with <span class="command"><strong>bind10</strong></span></a></span></dt><dd><dl><dt><span class="section"><a href="#start">Starting BIND 10</a></span></dt></dl></dd><dt><span class="chapter"><a href="#msgq">4. Command channel</a></span></dt><dt><span class="chapter"><a href="#cfgmgr">5. Configuration manager</a></span></dt><dt><span class="chapter"><a href="#cmdctl">6. Remote control daemon</a></span></dt><dd><dl><dt><span class="section"><a href="#cmdctl.spec">Configuration specifi
 cation for b10-cmdctl</a></span></dt></dl></dd><dt><span class="chapter"><a href="#bindctl">7. Control and configure user interface</a></span></dt><dt><span class="chapter"><a href="#authserver">8. Authoritative Server</a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230329190">Server Configurations</a></span></dt><dt><span class="section"><a href="#id1168230329255">Data Source Backends</a></span></dt><dt><span class="section"><a href="#id1168230329285">Loading Master Zones Files</a></span></dt></dl></dd><dt><span class="chapter"><a href="#xfrin">9. Incoming Zone Transfers</a></span></dt><dt><span class="chapter"><a href="#xfrout">10. Outbound Zone Transfers</a></span></dt></dl></div><div class="chapter" title="Chapter 1. Introduction"><div class="titlepage"><div><div><h2 class="title"><a name="intro"></a>Chapter 1. Introduction</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#id1168230342718">S
 upported Platforms</a></span></dt><dt><span class="section"><a href="#id1168230342746">Required Software</a></span></dt><dt><span class="section"><a href="#starting_stopping">Starting and Stopping the Server</a></span></dt><dt><span class="section"><a href="#managing_once_running">Managing BIND 10</a></span></dt></dl></div><p>
+      </p></div></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="chapter"><a href="#intro">1. Introduction</a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230299028">Supported Platforms</a></span></dt><dt><span class="section"><a href="#id1168230299056">Required Software</a></span></dt><dt><span class="section"><a href="#starting_stopping">Starting and Stopping the Server</a></span></dt><dt><span class="section"><a href="#managing_once_running">Managing BIND 10</a></span></dt></dl></dd><dt><span class="chapter"><a href="#installation">2. Installation</a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230284542">Building Requirements</a></span></dt><dt><span class="section"><a href="#quickstart">Quick start</a></span></dt><dt><span class="section"><a href="#install">Installation from source</a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230284728">Download Tar File</a></span></dt><dt><s
 pan class="section"><a href="#id1168230284748">Retrieve from Subversion</a></span></dt><dt><span class="section"><a href="#id1168230284809">Configure before the build</a></span></dt><dt><span class="section"><a href="#id1168230284906">Build</a></span></dt><dt><span class="section"><a href="#id1168230284921">Install</a></span></dt><dt><span class="section"><a href="#id1168230284946">Install Hierarchy</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#bind10">3. Starting BIND10 with <span class="command"><strong>bind10</strong></span></a></span></dt><dd><dl><dt><span class="section"><a href="#start">Starting BIND 10</a></span></dt></dl></dd><dt><span class="chapter"><a href="#msgq">4. Command channel</a></span></dt><dt><span class="chapter"><a href="#cfgmgr">5. Configuration manager</a></span></dt><dt><span class="chapter"><a href="#cmdctl">6. Remote control daemon</a></span></dt><dd><dl><dt><span class="section"><a href="#cmdctl.spec">Configuration specifi
 cation for b10-cmdctl</a></span></dt></dl></dd><dt><span class="chapter"><a href="#bindctl">7. Control and configure user interface</a></span></dt><dt><span class="chapter"><a href="#authserver">8. Authoritative Server</a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230285515">Server Configurations</a></span></dt><dt><span class="section"><a href="#id1168230285580">Data Source Backends</a></span></dt><dt><span class="section"><a href="#id1168230285610">Loading Master Zones Files</a></span></dt></dl></dd><dt><span class="chapter"><a href="#xfrin">9. Incoming Zone Transfers</a></span></dt><dt><span class="chapter"><a href="#xfrout">10. Outbound Zone Transfers</a></span></dt><dt><span class="chapter"><a href="#zonemgr">11. Secondary Manager</a></span></dt></dl></div><div class="chapter" title="Chapter 1. Introduction"><div class="titlepage"><div><div><h2 class="title"><a name="intro"></a>Chapter 1. Introduction</h2></div></div></div><div class="toc"><p><b>T
 able of Contents</b></p><dl><dt><span class="section"><a href="#id1168230299028">Supported Platforms</a></span></dt><dt><span class="section"><a href="#id1168230299056">Required Software</a></span></dt><dt><span class="section"><a href="#starting_stopping">Starting and Stopping the Server</a></span></dt><dt><span class="section"><a href="#managing_once_running">Managing BIND 10</a></span></dt></dl></div><p>
       BIND is the popular implementation of a DNS server, developer
       interfaces, and DNS tools.
       BIND 10 is a rewrite of BIND 9.  BIND 10 is written in C++ and Python
@@ -11,10 +11,10 @@
         This guide covers the experimental prototype version of
         BIND 10.
       </p></div><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
-        BIND 10, at this time, does not provide an recursive
+        BIND 10, at this time, does not provide a recursive
         DNS server. It does provide a EDNS0- and DNSSEC-capable
         authoritative DNS server.
-      </p></div><div class="section" title="Supported Platforms"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230342718"></a>Supported Platforms</h2></div></div></div><p>
+      </p></div><div class="section" title="Supported Platforms"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230299028"></a>Supported Platforms</h2></div></div></div><p>
   BIND 10 builds have been tested on Debian GNU/Linux 5,
   Ubuntu 9.10, NetBSD 5, Solaris 10, FreeBSD 7, and CentOS
   Linux 5.3.
@@ -24,16 +24,16 @@
 
         It is planned for BIND 10 to build, install and run on
         Windows and standard Unix-type platforms.
-      </p></div><div class="section" title="Required Software"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230342746"></a>Required Software</h2></div></div></div><p>
+      </p></div><div class="section" title="Required Software"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230299056"></a>Required Software</h2></div></div></div><p>
         BIND 10 requires Python 3.1.  Later versions may work, but Python
         3.1 is the minimum version which will work.
       </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
 	For this development prototype release, the only supported
 	data source backend is SQLite3. The authoritative server
 	requires SQLite 3.3.9 or newer.
-        The <span class="command"><strong>b10-xfrin</strong></span> and <span class="command"><strong>b10-xfrout</strong></span>
-        modules require the libpython3 library and the Python
-        _sqlite3.so module.
+	The <span class="command"><strong>b10-xfrin</strong></span>, <span class="command"><strong>b10-xfrout</strong></span>,
+	and <span class="command"><strong>b10-zonemgr</strong></span> modules require the
+	libpython3 library and the Python _sqlite3.so module.
       </p></div><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
           Some operating systems do not provide these dependencies
           in their default installation nor standard packages
@@ -83,6 +83,11 @@
 	      This process is used to handle transfer requests to
 	      send a local zone to a remote secondary server,
 	      when acting as a master server.
+            </li><li class="listitem">
+              <span class="command"><strong>b10-zonemgr</strong></span> —
+              Secondary manager.
+	      This process keeps track of timers and other
+              necessary information for BIND 10 to act as a slave server.
             </li></ul></div><p>
       </p><p>
 	These are ran automatically by <span class="command"><strong>bind10</strong></span>
@@ -116,7 +121,7 @@
       and, of course, DNS. These include detailed developer
       documentation and code examples.
 
-    </p></div><div class="chapter" title="Chapter 2. Installation"><div class="titlepage"><div><div><h2 class="title"><a name="installation"></a>Chapter 2. Installation</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#id1168230328220">Building Requirements</a></span></dt><dt><span class="section"><a href="#quickstart">Quick start</a></span></dt><dt><span class="section"><a href="#install">Installation from source</a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230328406">Download Tar File</a></span></dt><dt><span class="section"><a href="#id1168230328426">Retrieve from Subversion</a></span></dt><dt><span class="section"><a href="#id1168230328486">Configure before the build</a></span></dt><dt><span class="section"><a href="#id1168230328584">Build</a></span></dt><dt><span class="section"><a href="#id1168230328599">Install</a></span></dt><dt><span class="section"><a href="#id1168230328622">Install
  Hierarchy</a></span></dt></dl></dd></dl></div><div class="section" title="Building Requirements"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230328220"></a>Building Requirements</h2></div></div></div><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
+    </p></div><div class="chapter" title="Chapter 2. Installation"><div class="titlepage"><div><div><h2 class="title"><a name="installation"></a>Chapter 2. Installation</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#id1168230284542">Building Requirements</a></span></dt><dt><span class="section"><a href="#quickstart">Quick start</a></span></dt><dt><span class="section"><a href="#install">Installation from source</a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230284728">Download Tar File</a></span></dt><dt><span class="section"><a href="#id1168230284748">Retrieve from Subversion</a></span></dt><dt><span class="section"><a href="#id1168230284809">Configure before the build</a></span></dt><dt><span class="section"><a href="#id1168230284906">Build</a></span></dt><dt><span class="section"><a href="#id1168230284921">Install</a></span></dt><dt><span class="section"><a href="#id1168230284946">Install
  Hierarchy</a></span></dt></dl></dd></dl></div><div class="section" title="Building Requirements"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230284542"></a>Building Requirements</h2></div></div></div><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
             Some operating systems have split their distribution packages into
             a run-time and a development package.  You will need to install
             the development package versions, which include header files and
@@ -176,14 +181,14 @@
         the Subversion code revision control system or as a downloadable
         tar file. It may also be available in pre-compiled ready-to-use
         packages from operating system vendors.
-      </p><div class="section" title="Download Tar File"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230328406"></a>Download Tar File</h3></div></div></div><p>
+      </p><div class="section" title="Download Tar File"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230284728"></a>Download Tar File</h3></div></div></div><p>
           Downloading a release tar file is the recommended method to
           obtain the source code.
         </p><p>
           The BIND 10 releases are available as tar file downloads from
           <a class="ulink" href="ftp://ftp.isc.org/isc/bind10/" target="_top">ftp://ftp.isc.org/isc/bind10/</a>.
           Periodic development snapshots may also be available.
-        </p></div><div class="section" title="Retrieve from Subversion"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230328426"></a>Retrieve from Subversion</h3></div></div></div><p>
+        </p></div><div class="section" title="Retrieve from Subversion"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230284748"></a>Retrieve from Subversion</h3></div></div></div><p>
           Downloading this "bleeding edge" code is recommended only for
           developers or advanced users.  Using development code in a production
           environment is not recommended.
@@ -215,7 +220,7 @@
           <span class="command"><strong>autoheader</strong></span>,
           <span class="command"><strong>automake</strong></span>,
           and related commands.
-        </p></div><div class="section" title="Configure before the build"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230328486"></a>Configure before the build</h3></div></div></div><p>
+        </p></div><div class="section" title="Configure before the build"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230284809"></a>Configure before the build</h3></div></div></div><p>
           BIND 10 uses the GNU Build System to discover build environment
           details.
           To generate the makefiles using the defaults, simply run:
@@ -246,16 +251,16 @@
         </p><p>
           If the configure fails, it may be due to missing or old
           dependencies.
-        </p></div><div class="section" title="Build"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230328584"></a>Build</h3></div></div></div><p>
+        </p></div><div class="section" title="Build"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230284906"></a>Build</h3></div></div></div><p>
     After the configure step is complete, to build the executables
     from the C++ code and prepare the Python scripts, run:
 
           </p><pre class="screen">$ <strong class="userinput"><code>make</code></strong></pre><p>
-        </p></div><div class="section" title="Install"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230328599"></a>Install</h3></div></div></div><p>
+        </p></div><div class="section" title="Install"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230284921"></a>Install</h3></div></div></div><p>
           To install the BIND 10 executables, support files,
           and documentation, run:
           </p><pre class="screen">$ <strong class="userinput"><code>make install</code></strong></pre><p>
-        </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>The install step may require superuser privileges.</p></div></div><div class="section" title="Install Hierarchy"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230328622"></a>Install Hierarchy</h3></div></div></div><p>
+        </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>The install step may require superuser privileges.</p></div></div><div class="section" title="Install Hierarchy"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230284946"></a>Install Hierarchy</h3></div></div></div><p>
           The following is the layout of the complete BIND 10 installation:
           </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">
                 <code class="filename">bin/</code> —
@@ -307,8 +312,9 @@
       The <span class="command"><strong>bind10</strong></span> master process will also start up
       <span class="command"><strong>b10-cmdctl</strong></span> for admins to communicate with the
       system, <span class="command"><strong>b10-auth</strong></span> for Authoritative DNS service,
-      <span class="command"><strong>b10-xfrin</strong></span> for inbound DNS zone transfers.
-      and <span class="command"><strong>b10-xfrout</strong></span> for outbound DNS zone transfers.
+      <span class="command"><strong>b10-xfrin</strong></span> for inbound DNS zone transfers,
+      <span class="command"><strong>b10-xfrout</strong></span> for outbound DNS zone transfers,
+      and <span class="command"><strong>b10-zonemgr</strong></span> for secondary service.
     </p><div class="section" title="Starting BIND 10"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="start"></a>Starting BIND 10</h2></div></div></div><p>
         To start the BIND 10 service, simply run <span class="command"><strong>bind10</strong></span>.
         Run it with the <code class="option">--verbose</code> switch to
@@ -467,7 +473,7 @@
       the details and relays (over a <span class="command"><strong>b10-msgq</strong></span> command
       channel) the configuration on to the specified module.
     </p><p>
-    </p></div><div class="chapter" title="Chapter 8. Authoritative Server"><div class="titlepage"><div><div><h2 class="title"><a name="authserver"></a>Chapter 8. Authoritative Server</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#id1168230329190">Server Configurations</a></span></dt><dt><span class="section"><a href="#id1168230329255">Data Source Backends</a></span></dt><dt><span class="section"><a href="#id1168230329285">Loading Master Zones Files</a></span></dt></dl></div><p>
+    </p></div><div class="chapter" title="Chapter 8. Authoritative Server"><div class="titlepage"><div><div><h2 class="title"><a name="authserver"></a>Chapter 8. Authoritative Server</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#id1168230285515">Server Configurations</a></span></dt><dt><span class="section"><a href="#id1168230285580">Data Source Backends</a></span></dt><dt><span class="section"><a href="#id1168230285610">Loading Master Zones Files</a></span></dt></dl></div><p>
       The <span class="command"><strong>b10-auth</strong></span> is the authoritative DNS server.
       It supports EDNS0 and DNSSEC. It supports IPv6.
       Normally it is started by the <span class="command"><strong>bind10</strong></span> master
@@ -475,7 +481,7 @@
     </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
       This development prototype release listens on all interfaces
       and the non-standard port 5300.
-    </p></div><div class="section" title="Server Configurations"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230329190"></a>Server Configurations</h2></div></div></div><p>
+    </p></div><div class="section" title="Server Configurations"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230285515"></a>Server Configurations</h2></div></div></div><p>
         <span class="command"><strong>b10-auth</strong></span> is configured via the
         <span class="command"><strong>b10-cfgmgr</strong></span> configuration manager.
         The module name is <span class="quote">“<span class="quote">Auth</span>”</span>.
@@ -495,7 +501,7 @@
         </p><div class="variablelist"><dl><dt><span class="term">shutdown</span></dt><dd>Stop the authoritative DNS server.
               </dd></dl></div><p>
 
-      </p></div><div class="section" title="Data Source Backends"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230329255"></a>Data Source Backends</h2></div></div></div><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
+      </p></div><div class="section" title="Data Source Backends"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230285580"></a>Data Source Backends</h2></div></div></div><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
         For the development prototype release, <span class="command"><strong>b10-auth</strong></span>
         only supports the SQLite3 data source backend.
         Upcoming versions will be able to use multiple different
@@ -508,7 +514,7 @@
         The default is <code class="filename">/usr/local/var/</code>.)
   This data file location may be changed by defining the
   <span class="quote">“<span class="quote">database_file</span>”</span> configuration.
-      </p></div><div class="section" title="Loading Master Zones Files"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230329285"></a>Loading Master Zones Files</h2></div></div></div><p>
+      </p></div><div class="section" title="Loading Master Zones Files"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230285610"></a>Loading Master Zones Files</h2></div></div></div><p>
         RFC 1035 style DNS master zone files may imported
         into a BIND 10 data source by using the
         <span class="command"><strong>b10-loadzone</strong></span> utility.
@@ -544,12 +550,12 @@
       transfer. When received, it is stored in the BIND 10
       data store, and its records can be served by
       <span class="command"><strong>b10-auth</strong></span>.
-      This allows the BIND 10 server to provide
-      <span class="quote">“<span class="quote">secondary</span>”</span> service.
+      In combination with <span class="command"><strong>b10-zonemgr</strong></span> (for
+      automated SOA checks), this allows the BIND 10 server to
+      provide <span class="quote">“<span class="quote">secondary</span>”</span> service.
     </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
      The current development release of BIND 10 only supports
      AXFR. (IXFR is not supported.) 
-     It also does not yet support automated SOA checks.
     </p></div><p>
        To manually trigger a zone transfer to retrieve a remote zone,
        you may use the <span class="command"><strong>bindctl</strong></span> utility.
@@ -564,9 +570,24 @@
       sends the zone.
       This is used to provide master DNS service to share zones
       to secondary name servers.
+      The <span class="command"><strong>b10-xfrout</strong></span> is also used to send
+      NOTIFY messages to slaves.
     </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
      The current development release of BIND 10 only supports
      AXFR. (IXFR is not supported.) 
-     It also does not yet support NOTIFY.
      Access control is not yet provided.
+    </p></div></div><div class="chapter" title="Chapter 11. Secondary Manager"><div class="titlepage"><div><div><h2 class="title"><a name="zonemgr"></a>Chapter 11. Secondary Manager</h2></div></div></div><p>
+      The <span class="command"><strong>b10-zonemgr</strong></span> process is started by
+      <span class="command"><strong>bind10</strong></span>.
+      It keeps track of SOA refresh, retry, and expire timers
+      and other details for BIND 10 to perform as a slave.
+      When the <span class="command"><strong>b10-auth</strong></span> authoritative DNS server
+      receives a NOTIFY message, <span class="command"><strong>b10-zonemgr</strong></span>
+      may tell <span class="command"><strong>b10-xfrin</strong></span> to do a refresh
+      to start an inbound zone transfer.
+      The secondary manager resets its counters when a new zone is
+      transferred in.
+    </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
+     Access control (such as allowing notifies) is not yet provided.
+     The primary/secondary service is not yet complete.
     </p></div></div></div></body></html>

Modified: branches/trac311/doc/guide/bind10-guide.xml
==============================================================================
--- branches/trac311/doc/guide/bind10-guide.xml (original)
+++ branches/trac311/doc/guide/bind10-guide.xml Sun Sep 26 03:25:19 2010
@@ -42,7 +42,7 @@
 
     <note>
       <para>
-        BIND 10, at this time, does not provide an recursive
+        BIND 10, at this time, does not provide a recursive
         DNS server. It does provide a EDNS0- and DNSSEC-capable
         authoritative DNS server.
       </para>
@@ -74,9 +74,9 @@
 	For this development prototype release, the only supported
 	data source backend is SQLite3. The authoritative server
 	requires SQLite 3.3.9 or newer.
-        The <command>b10-xfrin</command> and <command>b10-xfrout</command>
-        modules require the libpython3 library and the Python
-        _sqlite3.so module.
+	The <command>b10-xfrin</command>, <command>b10-xfrout</command>,
+	and <command>b10-zonemgr</command> modules require the
+	libpython3 library and the Python _sqlite3.so module.
       </para></note>
 <!-- TODO: this will change ... -->
 
@@ -165,6 +165,15 @@
             </simpara>
           </listitem>
 
+          <listitem>
+            <simpara>
+              <command>b10-zonemgr</command> —
+              Secondary manager.
+	      This process keeps track of timers and other
+              necessary information for BIND 10 to act as a slave server.
+            </simpara>
+          </listitem>
+
         </itemizedlist>
       </para>
 
@@ -650,8 +659,9 @@
       The <command>bind10</command> master process will also start up
       <command>b10-cmdctl</command> for admins to communicate with the
       system, <command>b10-auth</command> for Authoritative DNS service,
-      <command>b10-xfrin</command> for inbound DNS zone transfers.
-      and <command>b10-xfrout</command> for outbound DNS zone transfers.
+      <command>b10-xfrin</command> for inbound DNS zone transfers,
+      <command>b10-xfrout</command> for outbound DNS zone transfers,
+      and <command>b10-zonemgr</command> for secondary service.
     </para>
 
     <section id="start">
@@ -1173,14 +1183,14 @@
       transfer. When received, it is stored in the BIND 10
       data store, and its records can be served by
       <command>b10-auth</command>.
-      This allows the BIND 10 server to provide
-      <quote>secondary</quote> service.
+      In combination with <command>b10-zonemgr</command> (for
+      automated SOA checks), this allows the BIND 10 server to
+      provide <quote>secondary</quote> service.
     </para>
 
     <note><simpara>
      The current development release of BIND 10 only supports
      AXFR. (IXFR is not supported.) 
-     It also does not yet support automated SOA checks.
     </simpara></note>
 
     <para>
@@ -1204,12 +1214,13 @@
       sends the zone.
       This is used to provide master DNS service to share zones
       to secondary name servers.
+      The <command>b10-xfrout</command> is also used to send
+      NOTIFY messages to slaves.
     </para>
 
     <note><simpara>
      The current development release of BIND 10 only supports
      AXFR. (IXFR is not supported.) 
-     It also does not yet support NOTIFY.
      Access control is not yet provided.
     </simpara></note>
 
@@ -1226,6 +1237,31 @@
 
   </chapter>
 
+  <chapter id="zonemgr">
+    <title>Secondary Manager</title>
+
+    <para>
+      The <command>b10-zonemgr</command> process is started by
+      <command>bind10</command>.
+      It keeps track of SOA refresh, retry, and expire timers
+      and other details for BIND 10 to perform as a slave.
+      When the <command>b10-auth</command> authoritative DNS server
+      receives a NOTIFY message, <command>b10-zonemgr</command>
+      may tell <command>b10-xfrin</command> to do a refresh
+      to start an inbound zone transfer.
+      The secondary manager resets its counters when a new zone is
+      transferred in.
+    </para>
+
+    <note><simpara>
+     Access control (such as allowing notifies) is not yet provided.
+     The primary/secondary service is not yet complete.
+    </simpara></note>
+
+<!-- TODO: lots to describe for zonemgr -->
+
+  </chapter>
+
 <!-- TODO: how to help: run unit tests, join lists, review trac tickets -->
 
   <!-- <index>    <title>Index</title> </index> -->

Modified: branches/trac311/src/bin/auth/Makefile.am
==============================================================================
--- branches/trac311/src/bin/auth/Makefile.am (original)
+++ branches/trac311/src/bin/auth/Makefile.am Sun Sep 26 03:25:19 2010
@@ -1,4 +1,4 @@
-SUBDIRS = . tests
+SUBDIRS = . tests benchmarks
 
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += -I$(top_srcdir)/src/bin -I$(top_builddir)/src/bin
@@ -59,7 +59,7 @@
 b10_auth_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
 b10_auth_LDADD += $(top_builddir)/src/lib/cc/libcc.la
 b10_auth_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
-b10_auth_LDADD += $(top_builddir)/src/bin/auth/libasio_link.a
+b10_auth_LDADD += libasio_link.a
 b10_auth_LDADD += $(top_builddir)/src/lib/xfr/libxfr.la
 b10_auth_LDADD += $(SQLITE_LIBS)
 

Modified: branches/trac311/src/bin/auth/asio_link.cc
==============================================================================
--- branches/trac311/src/bin/auth/asio_link.cc (original)
+++ branches/trac311/src/bin/auth/asio_link.cc Sun Sep 26 03:25:19 2010
@@ -67,7 +67,7 @@
 // Note: this implementation is optimized for the case where this object
 // is created from an ASIO endpoint object in a receiving code path
 // by avoiding to make a copy of the base endpoint.  For TCP it may not be
-// a bug deal, but when we receive UDP packets at a high rate, the copy
+// a big deal, but when we receive UDP packets at a high rate, the copy
 // overhead might be significant.
 class TCPEndpoint : public IOEndpoint {
 public:

Modified: branches/trac311/src/bin/auth/asio_link.h
==============================================================================
--- branches/trac311/src/bin/auth/asio_link.h (original)
+++ branches/trac311/src/bin/auth/asio_link.h Sun Sep 26 03:25:19 2010
@@ -207,7 +207,7 @@
     /// will be thrown.
     ///
     /// Memory for the created object will be dynamically allocated.  It's
-    /// caller's responsibility to \c delete it later.
+    /// the caller's responsibility to \c delete it later.
     /// If resource allocation for the new object fails, a corresponding
     /// standard exception will be thrown.
     ///

Modified: branches/trac311/src/bin/auth/auth_srv.cc
==============================================================================
--- branches/trac311/src/bin/auth/auth_srv.cc (original)
+++ branches/trac311/src/bin/auth/auth_srv.cc Sun Sep 26 03:25:19 2010
@@ -69,7 +69,7 @@
 public:
     AuthSrvImpl(const bool use_cache, AbstractXfroutClient& xfrout_client);
     ~AuthSrvImpl();
-    isc::data::ElementPtr setDbFile(const isc::data::ElementPtr config);
+    isc::data::ConstElementPtr setDbFile(isc::data::ConstElementPtr config);
 
     bool processNormalQuery(const IOMessage& io_message, Message& message,
                             MessageRenderer& response_renderer);
@@ -190,6 +190,16 @@
 bool
 AuthSrv::getVerbose() const {
     return (impl_->verbose_mode_);
+}
+
+void
+AuthSrv::setCacheSlots(const size_t slots) {
+    impl_->cache_.setSlots(slots);
+}
+
+size_t
+AuthSrv::getCacheSlots() const {
+    return (impl_->cache_.getSlots());
 }
 
 void
@@ -433,7 +443,7 @@
     static const string command_template_end = "\"}]}";
 
     try {
-        ElementPtr notify_command = Element::fromJSON(
+        ConstElementPtr notify_command = Element::fromJSON(
                 command_template_start + question->getName().toText() + 
                 command_template_master + remote_ip_address +
                 command_template_rrclass + question->getClass().toText() +
@@ -441,7 +451,7 @@
         const unsigned int seq =
             xfrin_session_->group_sendmsg(notify_command, "Zonemgr",
                                           "*", "*");
-        ElementPtr env, answer, parsed_answer;
+        ConstElementPtr env, answer, parsed_answer;
         xfrin_session_->group_recvmsg(env, answer, false, seq);
         int rcode;
         parsed_answer = parseAnswer(rcode, answer);
@@ -466,19 +476,17 @@
     return (true);
 }
 
-ElementPtr
-AuthSrvImpl::setDbFile(const isc::data::ElementPtr config) {
-    ElementPtr answer = isc::config::createAnswer();
-    ElementPtr final;
+ConstElementPtr
+AuthSrvImpl::setDbFile(ConstElementPtr config) {
+    ConstElementPtr answer = isc::config::createAnswer();
 
     if (config && config->contains("database_file")) {
         db_file_ = config->get("database_file")->stringValue();
-        final = config;
     } else if (config_session_ != NULL) {
         bool is_default;
         string item("database_file");
-        ElementPtr value = config_session_->getValue(is_default, item);
-        final = Element::createMap();
+        ConstElementPtr value = config_session_->getValue(is_default, item);
+        ElementPtr final = Element::createMap();
 
         // If the value is the default, and we are running from
         // a specific directory ('from build'), we need to use
@@ -492,6 +500,7 @@
                                     "/bind10_zones.sqlite3");
         }
         final->set(item, value);
+        config = final;
 
         db_file_ = value->stringValue();
     } else {
@@ -508,7 +517,7 @@
     // fail, while acquiring resources in the RAII manner.  We then perform
     // delete and swap operations which should not fail.
     DataSrcPtr datasrc_ptr(DataSrcPtr(new Sqlite3DataSrc));
-    datasrc_ptr->init(final);
+    datasrc_ptr->init(config);
     data_sources_.addDataSrc(datasrc_ptr);
 
     // The following code should be exception free.
@@ -520,15 +529,12 @@
     return (answer);
 }
 
-ElementPtr
-AuthSrv::updateConfig(isc::data::ElementPtr new_config) {
+ConstElementPtr
+AuthSrv::updateConfig(ConstElementPtr new_config) {
     try {
         // the ModuleCCSession has already checked if we have
         // the correct ElementPtr type as specified in our .spec file
-        ElementPtr answer = isc::config::createAnswer();
-        answer = impl_->setDbFile(new_config);
-
-        return (answer);
+        return (impl_->setDbFile(new_config));
     } catch (const isc::Exception& error) {
         if (impl_->verbose_mode_) {
             cerr << "[b10-auth] error: " << error.what() << endl;

Modified: branches/trac311/src/bin/auth/auth_srv.h
==============================================================================
--- branches/trac311/src/bin/auth/auth_srv.h (original)
+++ branches/trac311/src/bin/auth/auth_srv.h Sun Sep 26 03:25:19 2010
@@ -69,9 +69,29 @@
                         isc::dns::MessageRenderer& response_renderer);
     void setVerbose(bool on);
     bool getVerbose() const;
-    isc::data::ElementPtr updateConfig(isc::data::ElementPtr config);
+    isc::data::ConstElementPtr updateConfig(isc::data::ConstElementPtr config);
     isc::config::ModuleCCSession* configSession() const;
     void setConfigSession(isc::config::ModuleCCSession* config_session);
+
+    /// \brief Set or update the size (number of slots) of hot spot cache.
+    ///
+    /// If the specified size is 0, it means the size will be unlimited.
+    /// The specified size is recorded even if the cache is disabled; the
+    /// new size will be effective when the cache is enabled.
+    ///
+    /// This method never throws an exception.
+    ///
+    /// \param slots The number of cache slots.
+    void setCacheSlots(const size_t slots);
+
+    /// \brief Get the current size (number of slots) of hot spot cache.
+    ///
+    /// It always returns the recorded size regardless of the cache is enabled.
+    ///
+    /// This method never throws an exception.
+    ///
+    /// \return The current number of cache slots.
+    size_t getCacheSlots() const;
 
     ///
     /// Note: this interface is tentative.  We'll revisit the ASIO and session

Modified: branches/trac311/src/bin/auth/b10-auth.8
==============================================================================
--- branches/trac311/src/bin/auth/b10-auth.8 (original)
+++ branches/trac311/src/bin/auth/b10-auth.8 Sun Sep 26 03:25:19 2010
@@ -137,6 +137,7 @@
 \fBb10-cmdctl\fR(8),
 \fBb10-loadzone\fR(8),
 \fBb10-msgq\fR(8),
+\fBb10-zonemgr\fR(8),
 \fBbind10\fR(8),
 BIND 10 Guide\&.
 .SH "HISTORY"

Modified: branches/trac311/src/bin/auth/b10-auth.xml
==============================================================================
--- branches/trac311/src/bin/auth/b10-auth.xml (original)
+++ branches/trac311/src/bin/auth/b10-auth.xml Sun Sep 26 03:25:19 2010
@@ -201,6 +201,9 @@
         <refentrytitle>b10-msgq</refentrytitle><manvolnum>8</manvolnum>
       </citerefentry>,
       <citerefentry>
+        <refentrytitle>b10-zonemgr</refentrytitle><manvolnum>8</manvolnum>
+      </citerefentry>,
+      <citerefentry>
         <refentrytitle>bind10</refentrytitle><manvolnum>8</manvolnum>
       </citerefentry>,
       <citetitle>BIND 10 Guide</citetitle>.

Modified: branches/trac311/src/bin/auth/main.cc
==============================================================================
--- branches/trac311/src/bin/auth/main.cc (original)
+++ branches/trac311/src/bin/auth/main.cc Sun Sep 26 03:25:19 2010
@@ -66,19 +66,19 @@
 
 asio_link::IOService* io_service;
 
-ElementPtr
-my_config_handler(ElementPtr new_config) {
+ConstElementPtr
+my_config_handler(ConstElementPtr new_config) {
     return (auth_server->updateConfig(new_config));
 }
 
-ElementPtr
-my_command_handler(const string& command, const ElementPtr args) {
-    ElementPtr answer = createAnswer();
+ConstElementPtr
+my_command_handler(const string& command, ConstElementPtr args) {
+    ConstElementPtr answer = createAnswer();
 
     if (command == "print_message") {
         cout << args << endl;
         /* let's add that message to our answer as well */
-        answer->get("result")->add(args);
+        answer = createAnswer(0, args);
     } else if (command == "shutdown") {
         io_service->stop();
     }

Modified: branches/trac311/src/bin/auth/tests/auth_srv_unittest.cc
==============================================================================
--- branches/trac311/src/bin/auth/tests/auth_srv_unittest.cc (original)
+++ branches/trac311/src/bin/auth/tests/auth_srv_unittest.cc Sun Sep 26 03:25:19 2010
@@ -85,26 +85,27 @@
         {}
         virtual void establish(const char* socket_file);
         virtual void disconnect();
-        virtual int group_sendmsg(ElementPtr msg, string group,
+        virtual int group_sendmsg(ConstElementPtr msg, string group,
                                   string instance, string to);
-        virtual bool group_recvmsg(ElementPtr& envelope, ElementPtr& msg,
+        virtual bool group_recvmsg(ConstElementPtr& envelope,
+                                   ConstElementPtr& msg,
                                    bool nonblock, int seq);
         virtual void subscribe(string group, string instance);
         virtual void unsubscribe(string group, string instance);
         virtual void startRead(boost::function<void()> read_callback);
-        virtual int reply(ElementPtr& envelope, ElementPtr& newmsg);
-        virtual bool hasQueuedMsgs();
+        virtual int reply(ConstElementPtr envelope, ConstElementPtr newmsg);
+        virtual bool hasQueuedMsgs() const;
         virtual void setTimeout(size_t timeout UNUSED_PARAM) {};
         virtual size_t getTimeout() const { return 0; };
 
-        void setMessage(ElementPtr msg) { msg_ = msg; }
+        void setMessage(ConstElementPtr msg) { msg_ = msg; }
         void disableSend() { send_ok_ = false; }
         void disableReceive() { receive_ok_ = false; }
 
-        ElementPtr sent_msg;
+        ConstElementPtr sent_msg;
         string msg_destination;
     private:
-        ElementPtr msg_;
+        ConstElementPtr msg_;
         bool send_ok_;
         bool receive_ok_;
     };
@@ -174,19 +175,19 @@
 {}
 
 int
-AuthSrvTest::MockSession::reply(ElementPtr& envelope UNUSED_PARAM,
-                                ElementPtr& newmsg UNUSED_PARAM)
+AuthSrvTest::MockSession::reply(ConstElementPtr envelope UNUSED_PARAM,
+                                ConstElementPtr newmsg UNUSED_PARAM)
 {
     return (-1);
 }
 
 bool
-AuthSrvTest::MockSession::hasQueuedMsgs() {
+AuthSrvTest::MockSession::hasQueuedMsgs() const {
     return (false);
 }
 
 int
-AuthSrvTest::MockSession::group_sendmsg(ElementPtr msg, string group,
+AuthSrvTest::MockSession::group_sendmsg(ConstElementPtr msg, string group,
                                         string instance UNUSED_PARAM,
                                         string to UNUSED_PARAM)
 {
@@ -200,8 +201,8 @@
 }
 
 bool
-AuthSrvTest::MockSession::group_recvmsg(ElementPtr& envelope UNUSED_PARAM,
-                                        ElementPtr& msg,
+AuthSrvTest::MockSession::group_recvmsg(ConstElementPtr& envelope UNUSED_PARAM,
+                                        ConstElementPtr& msg,
                                         bool nonblock UNUSED_PARAM,
                                         int seq UNUSED_PARAM)
 {
@@ -546,7 +547,8 @@
     EXPECT_EQ("Zonemgr", notify_session.msg_destination);
     EXPECT_EQ("notify",
               notify_session.sent_msg->get("command")->get(0)->stringValue());
-    ElementPtr notify_args = notify_session.sent_msg->get("command")->get(1);
+    ConstElementPtr notify_args =
+        notify_session.sent_msg->get("command")->get(1);
     EXPECT_EQ("example.com.", notify_args->get("zone_name")->stringValue());
     EXPECT_EQ(DEFAULT_REMOTE_ADDRESS,
               notify_args->get("master")->stringValue());
@@ -574,7 +576,8 @@
 
     // Other conditions should be the same, so simply confirm the RR class is
     // set correctly.
-    ElementPtr notify_args = notify_session.sent_msg->get("command")->get(1);
+    ConstElementPtr notify_args =
+        notify_session.sent_msg->get("command")->get(1);
     EXPECT_EQ("CH", notify_args->get("zone_class")->stringValue());
 }
 
@@ -702,12 +705,12 @@
 updateConfig(AuthSrv* server, const char* const dbfile,
              const bool expect_success)
 {
-    const ElementPtr config_answer =
+    ConstElementPtr config_answer =
         server->updateConfig(Element::fromJSON(dbfile));
     EXPECT_EQ(Element::map, config_answer->getType());
     EXPECT_TRUE(config_answer->contains("result"));
 
-    const ElementPtr result = config_answer->get("result");
+    ConstElementPtr result = config_answer->get("result");
     EXPECT_EQ(Element::list, result->getType());
     EXPECT_EQ(expect_success ? 0 : 1, result->get(0)->intValue());
 }
@@ -754,4 +757,14 @@
     headerCheck(parse_message, default_qid, Rcode::NOERROR(), opcode.getCode(),
                 QR_FLAG | AA_FLAG, 1, 1, 1, 0);
 }
-}
+
+TEST_F(AuthSrvTest, cacheSlots) {
+    // simple check for the get/set operations
+    server.setCacheSlots(10);    // 10 = arbitrary choice
+    EXPECT_EQ(10, server.getCacheSlots());
+
+    // 0 is a valid size
+    server.setCacheSlots(0);
+    EXPECT_EQ(00, server.getCacheSlots());
+}
+}

Modified: branches/trac311/src/bin/bind10/Makefile.am
==============================================================================
--- branches/trac311/src/bin/bind10/Makefile.am (original)
+++ branches/trac311/src/bin/bind10/Makefile.am Sun Sep 26 03:25:19 2010
@@ -1,4 +1,4 @@
-SUBDIRS = tests
+SUBDIRS = . tests
 
 sbin_SCRIPTS = bind10
 CLEANFILES = bind10 bind10.pyc

Modified: branches/trac311/src/bin/bind10/bind10.8
==============================================================================
--- branches/trac311/src/bin/bind10/bind10.8 (original)
+++ branches/trac311/src/bin/bind10/bind10.8 Sun Sep 26 03:25:19 2010
@@ -101,6 +101,8 @@
 \fBb10-cmdctl\fR(8),
 \fBb10-msgq\fR(8),
 \fBb10-xfrin\fR(8),
+\fBb10-xfrout\fR(8),
+\fBb10-zonemgr\fR(8),
 BIND 10 Guide\&.
 .SH "HISTORY"
 .PP

Modified: branches/trac311/src/bin/bind10/bind10.py.in
==============================================================================
--- branches/trac311/src/bin/bind10/bind10.py.in (original)
+++ branches/trac311/src/bin/bind10/bind10.py.in Sun Sep 26 03:25:19 2010
@@ -18,7 +18,7 @@
 """\
 This file implements the Boss of Bind (BoB, or bob) program.
 
-It's purpose is to start up the BIND 10 system, and then manage the
+Its purpose is to start up the BIND 10 system, and then manage the
 processes, by starting and stopping processes, plus restarting
 processes that exit.
 
@@ -65,7 +65,9 @@
 import isc.cc
 
 # This is the version that gets displayed to the user.
-__version__ = "v20100531"
+# The VERSION string consists of the module name, the module version
+# number, and the overall BIND 10 version number (set in configure.ac).
+VERSION = "bind10 20100916 (BIND 10 @PACKAGE_VERSION@)"
 
 class RestartSchedule:
     """
@@ -627,7 +629,7 @@
 
 
     # Parse any command-line options.
-    parser = OptionParser(version=__version__)
+    parser = OptionParser(version=VERSION)
     parser.add_option("-a", "--address", dest="address", type="string",
                       action="callback", callback=check_addr, default='',
                       help="address the b10-auth daemon will use (default: listen on all addresses)")
@@ -680,7 +682,7 @@
 
     # Announce startup.
     if options.verbose:
-        sys.stdout.write("BIND 10 %s\n" % __version__)
+        sys.stdout.write("%s\n" % VERSION)
 
     # TODO: set process name, perhaps by:
     #       http://code.google.com/p/procname/
@@ -735,7 +737,12 @@
 
         for fd in rlist + xlist:
             if fd == ccs_fd:
-                boss_of_bind.ccs.check_command()
+                try:
+                    boss_of_bind.ccs.check_command()
+                except isc.cc.session.ProtocolError:
+                    if options.verbose:
+                        sys.stderr.write("[bind10] msgq channel disappeared.\n")
+                    break
             elif fd == wakeup_fd:
                 os.read(wakeup_fd, 32)
 

Modified: branches/trac311/src/bin/bind10/bind10.xml
==============================================================================
--- branches/trac311/src/bin/bind10/bind10.xml (original)
+++ branches/trac311/src/bin/bind10/bind10.xml Sun Sep 26 03:25:19 2010
@@ -189,6 +189,12 @@
       <citerefentry>
         <refentrytitle>b10-xfrin</refentrytitle><manvolnum>8</manvolnum>
       </citerefentry>,
+      <citerefentry>
+        <refentrytitle>b10-xfrout</refentrytitle><manvolnum>8</manvolnum>
+      </citerefentry>,
+      <citerefentry>
+        <refentrytitle>b10-zonemgr</refentrytitle><manvolnum>8</manvolnum>
+      </citerefentry>,
       <citetitle>BIND 10 Guide</citetitle>.
     </para>
   </refsect1>

Modified: branches/trac311/src/bin/bind10/tests/Makefile.am
==============================================================================
--- branches/trac311/src/bin/bind10/tests/Makefile.am (original)
+++ branches/trac311/src/bin/bind10/tests/Makefile.am Sun Sep 26 03:25:19 2010
@@ -8,5 +8,5 @@
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/bin/bind10 \
-	$(PYCOVERAGE) $(abs_srcdir)/$$pytest ; \
+	$(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
 	done

Modified: branches/trac311/src/bin/bindctl/Makefile.am
==============================================================================
--- branches/trac311/src/bin/bindctl/Makefile.am (original)
+++ branches/trac311/src/bin/bindctl/Makefile.am Sun Sep 26 03:25:19 2010
@@ -1,4 +1,4 @@
-SUBDIRS = tests
+SUBDIRS = . tests
 
 bin_SCRIPTS = bindctl
 man_MANS = bindctl.1

Modified: branches/trac311/src/bin/bindctl/bindcmd.py
==============================================================================
--- branches/trac311/src/bin/bindctl/bindcmd.py (original)
+++ branches/trac311/src/bin/bindctl/bindcmd.py Sun Sep 26 03:25:19 2010
@@ -35,7 +35,6 @@
 import getpass
 from hashlib import sha1
 import csv
-import json
 import pwd
 import getpass
 

Modified: branches/trac311/src/bin/bindctl/tests/Makefile.am
==============================================================================
--- branches/trac311/src/bin/bindctl/tests/Makefile.am (original)
+++ branches/trac311/src/bin/bindctl/tests/Makefile.am Sun Sep 26 03:25:19 2010
@@ -8,5 +8,5 @@
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_srcdir)/src/bin \
-	$(PYCOVERAGE) $(abs_srcdir)/$$pytest ; \
+	$(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
 	done

Modified: branches/trac311/src/bin/cfgmgr/Makefile.am
==============================================================================
--- branches/trac311/src/bin/cfgmgr/Makefile.am (original)
+++ branches/trac311/src/bin/cfgmgr/Makefile.am Sun Sep 26 03:25:19 2010
@@ -1,4 +1,4 @@
-SUBDIRS = tests
+SUBDIRS = . tests
 
 pkglibexecdir = $(libexecdir)/@PACKAGE@
 

Modified: branches/trac311/src/bin/cfgmgr/tests/Makefile.am
==============================================================================
--- branches/trac311/src/bin/cfgmgr/tests/Makefile.am (original)
+++ branches/trac311/src/bin/cfgmgr/tests/Makefile.am Sun Sep 26 03:25:19 2010
@@ -9,5 +9,5 @@
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/bin/cfgmgr \
-	$(PYCOVERAGE) $(abs_builddir)/$$pytest ; \
+	$(PYCOVERAGE) $(abs_builddir)/$$pytest || exit ; \
 	done

Modified: branches/trac311/src/bin/cmdctl/Makefile.am
==============================================================================
--- branches/trac311/src/bin/cmdctl/Makefile.am (original)
+++ branches/trac311/src/bin/cmdctl/Makefile.am Sun Sep 26 03:25:19 2010
@@ -1,4 +1,4 @@
-SUBDIRS = tests
+SUBDIRS = . tests
 
 pkglibexecdir = $(libexecdir)/@PACKAGE@
 

Modified: branches/trac311/src/bin/cmdctl/cmdctl.py.in
==============================================================================
--- branches/trac311/src/bin/cmdctl/cmdctl.py.in (original)
+++ branches/trac311/src/bin/cmdctl/cmdctl.py.in Sun Sep 26 03:25:19 2010
@@ -380,6 +380,7 @@
     def send_command(self, module_name, command_name, params = None):
         '''Send the command from bindctl to proper module. '''
         errstr = 'unknown error'
+        answer = None
         if self._verbose:
             self.log_info("Begin send command '%s' to module '%s'" %(command_name, module_name))
 
@@ -390,7 +391,10 @@
             msg = ccsession.create_command(command_name, params)
             seq = self._cc.group_sendmsg(msg, module_name)
             #TODO, it may be blocked, msqg need to add a new interface waiting in timeout.
-            answer, env = self._cc.group_recvmsg(False, seq)
+            try:
+                answer, env = self._cc.group_recvmsg(False, seq)
+            except isc.cc.session.SessionTimeout:
+                errstr = "Module '%s' not responding" % module_name
 
         if self._verbose:
             self.log_info("Finish send command '%s' to module '%s'" % (command_name, module_name))
@@ -410,7 +414,6 @@
             except ccsession.ModuleCCSessionError as mcse:
                 errstr = str("Error in ccsession answer:") + str(mcse)
                 self.log_info(errstr)
-        
         return 1, {'error': errstr}
     
     def log_info(self, msg):
@@ -602,6 +605,9 @@
     except isc.cc.SessionError as err:
         sys.stderr.write("[b10-cmdctl] Error creating b10-cmdctl, "
                          "is the command channel daemon running?\n")        
+    except isc.cc.SessionTimeout:
+        sys.stderr.write("[b10-cmdctl] Error creating b10-cmdctl, "
+                         "is the configuration manager running?\n")        
     except KeyboardInterrupt:
         sys.stderr.write("[b10-cmdctl] exit from Cmdctl\n")
     except CmdctlException as err:

Modified: branches/trac311/src/bin/cmdctl/tests/Makefile.am
==============================================================================
--- branches/trac311/src/bin/cmdctl/tests/Makefile.am (original)
+++ branches/trac311/src/bin/cmdctl/tests/Makefile.am Sun Sep 26 03:25:19 2010
@@ -10,5 +10,5 @@
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/bin/cmdctl \
 	CMDCTL_SPEC_PATH=$(abs_top_builddir)/src/bin/cmdctl \
 	CMDCTL_SRC_PATH=$(abs_top_srcdir)/src/bin/cmdctl \
-	$(PYCOVERAGE) $(abs_srcdir)/$$pytest ; \
+	$(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
 	done

Modified: branches/trac311/src/bin/loadzone/Makefile.am
==============================================================================
--- branches/trac311/src/bin/loadzone/Makefile.am (original)
+++ branches/trac311/src/bin/loadzone/Makefile.am Sun Sep 26 03:25:19 2010
@@ -1,5 +1,4 @@
-SUBDIRS = tests/correct
-SUBDIRS += tests/error
+SUBDIRS = . tests/correct tests/error
 bin_SCRIPTS = b10-loadzone
 
 CLEANFILES = b10-loadzone

Modified: branches/trac311/src/bin/loadzone/tests/correct/Makefile.am
==============================================================================
--- branches/trac311/src/bin/loadzone/tests/correct/Makefile.am (original)
+++ branches/trac311/src/bin/loadzone/tests/correct/Makefile.am Sun Sep 26 03:25:19 2010
@@ -21,5 +21,5 @@
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/bin/loadzone \
-	$(SHELL) $(abs_builddir)/$$pytest ; \
+	$(SHELL) $(abs_builddir)/$$pytest || exit ; \
 	done

Modified: branches/trac311/src/bin/loadzone/tests/error/Makefile.am
==============================================================================
--- branches/trac311/src/bin/loadzone/tests/error/Makefile.am (original)
+++ branches/trac311/src/bin/loadzone/tests/error/Makefile.am Sun Sep 26 03:25:19 2010
@@ -21,5 +21,5 @@
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/bin/loadzone \
-	$(SHELL) $(abs_builddir)/$$pytest ; \
+	$(SHELL) $(abs_builddir)/$$pytest || exit ; \
 	done

Modified: branches/trac311/src/bin/msgq/Makefile.am
==============================================================================
--- branches/trac311/src/bin/msgq/Makefile.am (original)
+++ branches/trac311/src/bin/msgq/Makefile.am Sun Sep 26 03:25:19 2010
@@ -1,4 +1,4 @@
-SUBDIRS = tests
+SUBDIRS = . tests
 
 pkglibexecdir = $(libexecdir)/@PACKAGE@
  

Modified: branches/trac311/src/bin/msgq/tests/Makefile.am
==============================================================================
--- branches/trac311/src/bin/msgq/tests/Makefile.am (original)
+++ branches/trac311/src/bin/msgq/tests/Makefile.am Sun Sep 26 03:25:19 2010
@@ -8,6 +8,6 @@
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
 	env PYTHONPATH=$(abs_top_builddir)/src/bin/msgq:$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python \
-	$(PYCOVERAGE) $(abs_srcdir)/$$pytest ; \
+	$(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
 	done
 

Modified: branches/trac311/src/bin/xfrin/Makefile.am
==============================================================================
--- branches/trac311/src/bin/xfrin/Makefile.am (original)
+++ branches/trac311/src/bin/xfrin/Makefile.am Sun Sep 26 03:25:19 2010
@@ -1,4 +1,4 @@
-SUBDIRS = tests
+SUBDIRS = . tests
 
 pkglibexecdir = $(libexecdir)/@PACKAGE@
 

Modified: branches/trac311/src/bin/xfrin/TODO
==============================================================================
--- branches/trac311/src/bin/xfrin/TODO (original)
+++ branches/trac311/src/bin/xfrin/TODO Sun Sep 26 03:25:19 2010
@@ -63,3 +63,8 @@
     which a shutdown notification would be sent to the child.  With
     this approach each thread needs to watch at least two channels,
     and then it would need some asynchronous communication mechanism.
+17. Do zone transfer from notifyfrom address first, if it's one master of the zone.
+18. Check soa serial first when doing zone refreshment.
+19. Add configuration items to seperate zone, including ACL, multiple masters, etc.
+20. Be able to cancel the ongoing zone transfer, and be able to disable zone transfer.
+

Modified: branches/trac311/src/bin/xfrin/b10-xfrin.8
==============================================================================
--- branches/trac311/src/bin/xfrin/b10-xfrin.8 (original)
+++ branches/trac311/src/bin/xfrin/b10-xfrin.8 Sun Sep 26 03:25:19 2010
@@ -2,12 +2,12 @@
 .\"     Title: b10-xfrin
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: March 17, 2010
+.\"      Date: September 8, 2010
 .\"    Manual: BIND10
 .\"    Source: BIND10
 .\"  Language: English
 .\"
-.TH "B10\-XFRIN" "8" "March 17, 2010" "BIND10" "BIND10"
+.TH "B10\-XFRIN" "8" "September 8, 2010" "BIND10" "BIND10"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
@@ -47,7 +47,6 @@
 .sp .5v
 .RE
 .PP
-
 This daemon communicates with BIND 10 over a
 \fBb10-msgq\fR(8)
 C\-Channel connection\&. If this connection is not established,
@@ -60,24 +59,59 @@
 \fBb10-cfgmgr\fR(8)\&.
 .SH "CONFIGURATION AND COMMANDS"
 .PP
-The configurable setting is
+The configurable settings are:
+.PP
+\fImaster_addr\fR
+The default is 127\&.0\&.0\&.1\&.
+.PP
+\fImaster_port\fR
+The default is 53\&.
+.PP
 \fItransfers\-in\fR
-which defines the maximum number of inbound zone transfers that can run concurrently\&. The default is 10\&.
+defines the maximum number of inbound zone transfers that can run concurrently\&. The default is 10\&.
 .PP
 The configuration commands are:
+.PP
+
+\fBnotify\fR
+is sent by
+\fBb10-zonemgr\fR(8)
+when a DNS NOTIFY message is received to initiate a zone transfer\&.
+This is an internal command and not exposed to the administrator\&.
+.PP
+
+\fBrefresh\fR
+triggers the transfer in for a single zone\&. It is the same as
+\fBretransfer\fR
+except it checks the SOA serial first\&.
+This is an internal command and not exposed to the administrator\&.
+
+.PP
+
+\fBrefresh_from_zonemgr\fR
+is sent by
+\fBb10-zonemgr\fR(8)
+according to the SOA\'s REFRESH time to tell
+\fBb10\-xfrin\fR
+that the zone needs to do a zone refresh\&. This is an internal command and not exposed to the administrator\&.
+.PP
+
+\fBretransfer\fR
+triggers the transfer in for a single zone without checking the zone\'s serial number\&. It has the following arguments:
+\fIzone_name\fR
+to define the zone to request,
+\fIzone_class\fR
+to define the class (defaults to
+\(lqIN\(rq),
+\fImaster\fR
+to define the IP address of the authoritative server to transfer from, and
+\fIport\fR
+to define the port number on the authoritative server (defaults to 53)\&.
 .PP
 
 \fBshutdown\fR
 stops all incoming zone transfers and exits
 \fBb10\-xfrin\fR\&. (Note that the BIND 10 boss process will restart this service\&.)
-.PP
-
-\fBretransfer\fR
-triggers the transfer in for a single zone without checking the zone\'s serial number\&. It has the following arguments:
-\fIzone_name\fR
-to define the zone to request and
-\fImaster\fR
-to define the IP address of the authoritative server to transfer from\&.
 .if n \{\
 .sp
 .\}
@@ -99,6 +133,7 @@
 
 \fBb10-cfgmgr\fR(8),
 \fBb10-msgq\fR(8),
+\fBb10-zonemgr\fR(8),
 \fBbind10\fR(8),
 BIND 10 Guide\&.
 .SH "HISTORY"

Modified: branches/trac311/src/bin/xfrin/b10-xfrin.xml
==============================================================================
--- branches/trac311/src/bin/xfrin/b10-xfrin.xml (original)
+++ branches/trac311/src/bin/xfrin/b10-xfrin.xml Sun Sep 26 03:25:19 2010
@@ -21,7 +21,7 @@
 <refentry>
 
   <refentryinfo>
-    <date>March 17, 2010</date>
+    <date>September 8, 2010</date>
   </refentryinfo>
 
   <refmeta>
@@ -68,7 +68,6 @@
     </simpara></note>
 
     <para>
-<!-- TODO: does it really use msgq? what for? -->
       This daemon communicates with BIND 10 over a
       <citerefentry><refentrytitle>b10-msgq</refentrytitle><manvolnum>8</manvolnum></citerefentry>
       C-Channel connection.  If this connection is not established,
@@ -85,39 +84,82 @@
   <refsect1>
     <title>CONFIGURATION AND COMMANDS</title>
     <para>
-      The configurable setting is <varname>transfers-in</varname>
-      which defines the maximum number of inbound zone transfers
+      The configurable settings are:
+    </para>
+
+    <para><varname>master_addr</varname>
+<!-- TODO: how can there be a single setting for this? -->
+       The default is 127.0.0.1.
+    </para>
+
+    <para><varname>master_port</varname>
+<!-- TODO: what if custom is needed per zone? -->
+      The default is 53.
+    </para>
+
+    <para><varname>transfers-in</varname>
+      defines the maximum number of inbound zone transfers
       that can run concurrently. The default is 10.
     </para>
 
 <!-- TODO: formating -->
-<!-- TODO: refresh is code but not in spec -->
-<!-- schedule immediate maintenance for a zone(check soa serial ) -->
     <para>
       The configuration commands are:
     </para>
+
+    <para>
+      <command>notify</command> is sent by
+      <citerefentry><refentrytitle>b10-zonemgr</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+      when a DNS NOTIFY message is received to initiate a zone
+      transfer.
+<!-- TODO: document that zonemgr or xfrin checks if it needs to or not -->
+      This is an internal command and not exposed to the administrator.
+<!-- not defined in spec -->
+    </para>
+
+    <para>
+      <command>refresh</command> triggers the transfer in for
+      a single zone.
+      It is the same as <command>retransfer</command> except it
+      checks the SOA serial first.
+<!-- TODO more detail -->
+      This is an internal command and not exposed to the administrator.
+<!-- not defined in spec -->
+<!-- TODO: refresh is code but not in spec, see trac ticket #328 -->
+    </para>
+
+    <para>
+      <command>refresh_from_zonemgr</command> is sent by
+      <citerefentry><refentrytitle>b10-zonemgr</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+      according to the SOA's REFRESH time
+      to tell <command>b10-xfrin</command> that the zone needs to do
+      a zone refresh.
+      This is an internal command and not exposed to the administrator. 
+<!-- not defined in spec -->
+    </para>
+
+    <para>
+      <command>retransfer</command> triggers the transfer in for
+      a single zone without checking the zone's serial number.
+      It has the following arguments: <varname>zone_name</varname>
+      to define the zone to request,
+      <varname>zone_class</varname> to define the class (defaults to
+      <quote>IN</quote>),
+      <varname>master</varname> to define the IP address of
+      the authoritative server to transfer from,
+      and <varname>port</varname> to define the port number on the
+      authoritative server (defaults to 53).
+<!-- TODO: note: not documenting db_file since that will be removed. -->
+     </para>
+<!-- TODO: later hostname for master? -->
+
     <para>
       <command>shutdown</command> stops all incoming zone transfers
       and exits <command>b10-xfrin</command>. (Note that the BIND 10
       boss process will restart this service.)
     </para>
-    <para>
-      <command>retransfer</command> triggers the transfer in for
-      a single zone without checking the zone's serial number.
-      It has the following arguments: <varname>zone_name</varname>
-      to define the zone to request and <varname>master</varname>
-      to define the IP address of the authoritative server to
-      transfer from.
-     </para>
-<!-- TODO: later hostname for master? -->
-
 <!-- TODO:
 add a usage example of xfrin -->
-
-<!-- TODO:
-
-port (defaults to 53)
-db_file (defaults to zone.sqlite3) --> <!-- TODO: fix this -->
 
 <!-- TODO:
 
@@ -182,6 +224,9 @@
         <refentrytitle>b10-msgq</refentrytitle><manvolnum>8</manvolnum>
       </citerefentry>,
       <citerefentry>
+        <refentrytitle>b10-zonemgr</refentrytitle><manvolnum>8</manvolnum>
+      </citerefentry>,
+      <citerefentry>
         <refentrytitle>bind10</refentrytitle><manvolnum>8</manvolnum>
       </citerefentry>,
       <citetitle>BIND 10 Guide</citetitle>.

Modified: branches/trac311/src/bin/xfrin/tests/Makefile.am
==============================================================================
--- branches/trac311/src/bin/xfrin/tests/Makefile.am (original)
+++ branches/trac311/src/bin/xfrin/tests/Makefile.am Sun Sep 26 03:25:19 2010
@@ -16,5 +16,5 @@
 	echo Running test: $$pytest ; \
 	env PYTHONPATH=$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/bin/xfrin:$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python \
 	$(LIBRARY_PATH_PLACEHOLDER) \
-	$(PYCOVERAGE) $(abs_srcdir)/$$pytest ; \
+	$(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
 	done

Modified: branches/trac311/src/bin/xfrin/tests/xfrin_test.py
==============================================================================
--- branches/trac311/src/bin/xfrin/tests/xfrin_test.py (original)
+++ branches/trac311/src/bin/xfrin/tests/xfrin_test.py Sun Sep 26 03:25:19 2010
@@ -508,12 +508,12 @@
                                                   self.args)['result'][0], 1)
 
     def test_command_handler_retransfer_nomodule(self):
-        dns_module = sys.modules['libdns_python'] # this must exist
-        del sys.modules['libdns_python']
+        dns_module = sys.modules['pydnspp'] # this must exist
+        del sys.modules['pydnspp']
         self.assertEqual(self.xfr.command_handler("retransfer",
                                                   self.args)['result'][0], 1)
         # sys.modules is global, so we must recover it
-        sys.modules['libdns_python'] = dns_module
+        sys.modules['pydnspp'] = dns_module
 
     def test_command_handler_refresh(self):
         # at this level, refresh is no different than retransfer.

Modified: branches/trac311/src/bin/xfrin/xfrin.py.in
==============================================================================
--- branches/trac311/src/bin/xfrin/xfrin.py.in (original)
+++ branches/trac311/src/bin/xfrin/xfrin.py.in Sun Sep 26 03:25:19 2010
@@ -30,7 +30,7 @@
 from isc.config.ccsession import *
 from isc.notify import notify_out
 try:
-    from libdns_python import *
+    from pydnspp import *
 except ImportError as e:
     # C++ loadable module may not be installed; even so the xfrin process
     # must keep running, so we warn about it and move forward.
@@ -197,7 +197,6 @@
                                             self._handle_xfrin_response)
 
                 self.log_msg(logstr + 'succeeded')
-                ret = XFRIN_OK
 
         except XfrinException as e:
             self.log_msg(e)
@@ -523,8 +522,8 @@
 
     def xfrin_start(self, zone_name, rrclass, db_file, master_addrinfo,
                     check_soa = True):
-        if "libdns_python" not in sys.modules:
-            return (1, "xfrin failed, can't load dns message python library: 'libdns_python'")
+        if "pydnspp" not in sys.modules:
+            return (1, "xfrin failed, can't load dns message python library: 'pydnspp'")
 
         # check max_transfer_in, else return quota error
         if self.recorder.count() >= self._max_transfers_in:

Modified: branches/trac311/src/bin/xfrout/Makefile.am
==============================================================================
--- branches/trac311/src/bin/xfrout/Makefile.am (original)
+++ branches/trac311/src/bin/xfrout/Makefile.am Sun Sep 26 03:25:19 2010
@@ -1,4 +1,4 @@
-SUBDIRS = tests
+SUBDIRS = . tests
 
 pkglibexecdir = $(libexecdir)/@PACKAGE@
 

Modified: branches/trac311/src/bin/xfrout/TODO
==============================================================================
--- branches/trac311/src/bin/xfrout/TODO (original)
+++ branches/trac311/src/bin/xfrout/TODO Sun Sep 26 03:25:19 2010
@@ -1,1 +1,2 @@
-Add unittest code.
+Add unittest code.
+Be able to cancel the outgoing zone transfer, and also be able to disable outgoing zone transfer.

Modified: branches/trac311/src/bin/xfrout/b10-xfrout.8
==============================================================================
--- branches/trac311/src/bin/xfrout/b10-xfrout.8 (original)
+++ branches/trac311/src/bin/xfrout/b10-xfrout.8 Sun Sep 26 03:25:19 2010
@@ -2,12 +2,12 @@
 .\"     Title: b10-xfrout
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: April 20, 2010
+.\"      Date: September 8, 2010
 .\"    Manual: BIND10
 .\"    Source: BIND10
 .\"  Language: English
 .\"
-.TH "B10\-XFROUT" "8" "April 20, 2010" "BIND10" "BIND10"
+.TH "B10\-XFROUT" "8" "September 8, 2010" "BIND10" "BIND10"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
@@ -27,7 +27,7 @@
 .PP
 The
 \fBb10\-xfrout\fR
-daemon provides the BIND 10 outgoing DNS zone transfer service\&. Normally it is started by the
+daemon provides the BIND 10 outgoing DNS zone transfer service\&. It is also used to send outgoing NOTIFY messages\&. Normally it is started by the
 \fBbind10\fR(8)
 boss process\&. When the
 \fBb10\-auth\fR
@@ -67,13 +67,13 @@
 The configurable settings are:
 .PP
 
-\fItransfers\-out\fR
-defines the maximum number of outgoing zone transfers that can run concurrently\&. The default is 10\&.
-.PP
-
 \fIdb_file\fR
 defines the path to the SQLite3 data store file\&. The default is
 /usr/local/var/bind10\-devel/zone\&.sqlite3\&.
+.PP
+
+\fItransfers_out\fR
+defines the maximum number of outgoing zone transfers that can run concurrently\&. The default is 10\&.
 .if n \{\
 .sp
 .\}
@@ -91,25 +91,34 @@
 .sp .5v
 .RE
 .PP
-The configuration command is:
+The configuration commands are:
 .PP
 
 \fBshutdown\fR
 stops all outbound zone transfers and exits
 \fBb10\-xfrout\fR\&. (Note that the BIND 10 boss process will restart this service\&.)
+.PP
+
+\fBzone_new_data_ready\fR
+is sent from
+\fBb10-xfrin\fR(8)
+to indicate that the zone transferred in successfully\&. This triggers
+\fBb10\-xfrout\fR
+to send NOTIFY message(s)\&. This is an internal command and not exposed to the administrator\&.
 .SH "SEE ALSO"
 .PP
 
 \fBb10-auth\fR(8),
 \fBb10-cfgmgr\fR(8),
 \fBb10-msgq\fR(8),
+\fBb10-xfrin\fR(8),
 \fBbind10\fR(8),
 BIND 10 Guide\&.
 .SH "HISTORY"
 .PP
 The
 \fBb10\-xfrout\fR
-daemon was implemented in March 2010 by Zhang Likun of CNNIC for the ISC BIND 10 project\&.
+daemon was first implemented in March 2010 by Zhang Likun of CNNIC for the ISC BIND 10 project\&.
 .SH "COPYRIGHT"
 .br
 Copyright \(co 2010 Internet Systems Consortium, Inc. ("ISC")

Modified: branches/trac311/src/bin/xfrout/b10-xfrout.xml
==============================================================================
--- branches/trac311/src/bin/xfrout/b10-xfrout.xml (original)
+++ branches/trac311/src/bin/xfrout/b10-xfrout.xml Sun Sep 26 03:25:19 2010
@@ -21,7 +21,7 @@
 <refentry>
 
   <refentryinfo>
-    <date>April 20, 2010</date>
+    <date>September 8, 2010</date>
   </refentryinfo>
 
   <refmeta>
@@ -54,6 +54,7 @@
     <title>DESCRIPTION</title>
     <para>The <command>b10-xfrout</command> daemon provides the BIND 10
       outgoing DNS zone transfer service.
+      It is also used to send outgoing NOTIFY messages.
       Normally it is started by the
       <citerefentry><refentrytitle>bind10</refentrytitle><manvolnum>8</manvolnum></citerefentry>
       boss process.
@@ -93,16 +94,20 @@
       The configurable settings are:
     </para>
     <para>
-      <varname>transfers-out</varname>
-      defines the maximum number of outgoing zone transfers
-      that can run concurrently. The default is 10.
-    </para>
-    <para>
       <varname>db_file</varname>
       defines the path to the SQLite3 data store file.
       The default is
       <filename>/usr/local/var/bind10-devel/zone.sqlite3</filename>.
+<!-- TODO: db_file will be removed -->
     </para>
+    <para>
+      <varname>transfers_out</varname>
+      defines the maximum number of outgoing zone transfers
+      that can run concurrently. The default is 10.
+    </para>
+
+<!-- TODO: log configurations not documented yet in here. jreed
+     has some but waiting on decisions ... -->
 
     <note><simpara>
       This prototype version uses SQLite3 as its data source backend.
@@ -112,12 +117,22 @@
 
 <!-- TODO: formating -->
     <para>
-      The configuration command is:
+      The configuration commands are:
     </para>
     <para>
       <command>shutdown</command> stops all outbound zone transfers
       and exits <command>b10-xfrout</command>. (Note that the BIND 10
       boss process will restart this service.)
+    </para>
+
+    <para>
+      <command>zone_new_data_ready</command> is sent from
+      <citerefentry><refentrytitle>b10-xfrin</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+      to indicate that the zone transferred in successfully.
+      This triggers <command>b10-xfrout</command> to send NOTIFY
+      message(s).
+      This is an internal command and not exposed to the administrator.
+<!-- not defined in spec -->
     </para>
 
   </refsect1>
@@ -161,6 +176,9 @@
         <refentrytitle>b10-msgq</refentrytitle><manvolnum>8</manvolnum>
       </citerefentry>,
       <citerefentry>
+        <refentrytitle>b10-xfrin</refentrytitle><manvolnum>8</manvolnum>
+      </citerefentry>,
+      <citerefentry>
         <refentrytitle>bind10</refentrytitle><manvolnum>8</manvolnum>
       </citerefentry>,
       <citetitle>BIND 10 Guide</citetitle>.
@@ -170,8 +188,8 @@
   <refsect1>
     <title>HISTORY</title>
     <para>
-      The <command>b10-xfrout</command> daemon was implemented in March 2010
-      by Zhang Likun of CNNIC for the ISC BIND 10 project.
+      The <command>b10-xfrout</command> daemon was first implemented
+      in March 2010 by Zhang Likun of CNNIC for the ISC BIND 10 project.
     </para>
   </refsect1>
 </refentry><!--

Modified: branches/trac311/src/bin/xfrout/tests/Makefile.am
==============================================================================
--- branches/trac311/src/bin/xfrout/tests/Makefile.am (original)
+++ branches/trac311/src/bin/xfrout/tests/Makefile.am Sun Sep 26 03:25:19 2010
@@ -16,5 +16,5 @@
 	echo Running test: $$pytest ; \
 	env PYTHONPATH=$(abs_top_builddir)/src/bin/xfrout:$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/lib/xfr/.libs \
 	$(LIBRARY_PATH_PLACEHOLDER) \
-	$(PYCOVERAGE) $(abs_srcdir)/$$pytest ; \
+	$(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
 	done

Modified: branches/trac311/src/bin/xfrout/tests/xfrout_test.py
==============================================================================
--- branches/trac311/src/bin/xfrout/tests/xfrout_test.py (original)
+++ branches/trac311/src/bin/xfrout/tests/xfrout_test.py Sun Sep 26 03:25:19 2010
@@ -19,7 +19,7 @@
 import unittest
 import os
 from isc.cc.session import *
-from libdns_python import *
+from pydnspp import *
 from xfrout import *
 
 # our fake socket, where we can read and insert messages
@@ -40,8 +40,12 @@
         return len(data)
 
     def readsent(self):
-        result = self.sendqueue[:]
-        del self.sendqueue[:]
+        if len(self.sendqueue) >= 2:
+            size = 2 + struct.unpack("!H", self.sendqueue[:2])[0]
+        else:
+            size = 0
+        result = self.sendqueue[:size]
+        self.sendqueue = self.sendqueue[size:]
         return result
     
     def read_msg(self):
@@ -133,7 +137,7 @@
 
         msg = self.getmsg()
         msg.make_response()
-        self.xfrsess._send_message_with_last_soa(msg, self.sock, rrset_soa)
+        self.xfrsess._send_message_with_last_soa(msg, self.sock, rrset_soa, 0)
         get_msg = self.sock.read_msg()
 
         self.assertEqual(get_msg.get_rr_count(Section.QUESTION()), 1)
@@ -148,10 +152,52 @@
         rdata = answer.get_rdata()
         self.assertEqual(rdata[0].to_text(), self.soa_record[7])
 
-    def test_get_message_len(self):
-        msg = self.getmsg()
-        msg.make_response()  
-        self.assertEqual(self.xfrsess._get_message_len(msg), 29)
+    def test_trigger_send_message_with_last_soa(self):
+        rrset_a = RRset(Name("example.com"), RRClass.IN(), RRType.A(), RRTTL(3600))
+        rrset_a.add_rdata(Rdata(RRType.A(), RRClass.IN(), "192.0.2.1"))
+        rrset_soa = self.xfrsess._create_rrset_from_db_record(self.soa_record)
+
+        msg = self.getmsg()
+        msg.make_response()
+
+        msg.add_rrset(Section.ANSWER(), rrset_a)
+        # give the function a value that is larger than MAX-len(rrset)
+        self.xfrsess._send_message_with_last_soa(msg, self.sock, rrset_soa, 65520)
+
+        # this should have triggered the sending of two messages
+        # (1 with the rrset we added manually, and 1 that triggered
+        # the sending in _with_last_soa)
+        get_msg = self.sock.read_msg()
+        self.assertEqual(get_msg.get_rr_count(Section.QUESTION()), 1)
+        self.assertEqual(get_msg.get_rr_count(Section.ANSWER()), 1)
+        self.assertEqual(get_msg.get_rr_count(Section.AUTHORITY()), 0)
+
+        answer = get_msg.get_section(Section.ANSWER())[0]
+        self.assertEqual(answer.get_name().to_text(), "example.com.")
+        self.assertEqual(answer.get_class(), RRClass("IN"))
+        self.assertEqual(answer.get_type().to_text(), "A")
+        rdata = answer.get_rdata()
+        self.assertEqual(rdata[0].to_text(), "192.0.2.1")
+
+        get_msg = self.sock.read_msg()
+        self.assertEqual(get_msg.get_rr_count(Section.QUESTION()), 0)
+        self.assertEqual(get_msg.get_rr_count(Section.ANSWER()), 1)
+        self.assertEqual(get_msg.get_rr_count(Section.AUTHORITY()), 0)
+
+        #answer_rrset_iter = section_iter(get_msg, section.ANSWER())
+        answer = get_msg.get_section(Section.ANSWER())[0]
+        self.assertEqual(answer.get_name().to_text(), "example.com.")
+        self.assertEqual(answer.get_class(), RRClass("IN"))
+        self.assertEqual(answer.get_type().to_text(), "SOA")
+        rdata = answer.get_rdata()
+        self.assertEqual(rdata[0].to_text(), self.soa_record[7])
+
+        # and it should not have sent anything else
+        self.assertEqual(0, len(self.sock.sendqueue))
+
+    def test_get_rrset_len(self):
+        rrset_soa = self.xfrsess._create_rrset_from_db_record(self.soa_record)
+        self.assertEqual(82, get_rrset_len(rrset_soa))
 
     def test_zone_is_empty(self):
         global sqlite3_ds

Modified: branches/trac311/src/bin/xfrout/xfrout.py.in
==============================================================================
--- branches/trac311/src/bin/xfrout/xfrout.py.in (original)
+++ branches/trac311/src/bin/xfrout/xfrout.py.in Sun Sep 26 03:25:19 2010
@@ -27,7 +27,7 @@
 import os
 from isc.config.ccsession import *
 from isc.log.log import *
-from isc.cc import SessionError
+from isc.cc import SessionError, SessionTimeout
 from isc.notify import notify_out
 import socket
 import select
@@ -35,7 +35,7 @@
 from optparse import OptionParser, OptionValueError
 try:
     from libxfr_python import *
-    from libdns_python import *
+    from pydnspp import *
 except ImportError as e:
     # C++ loadable module may not be installed; even so the xfrout process
     # must keep running, so we warn about it and move forward.
@@ -57,6 +57,15 @@
 MAX_TRANSFERS_OUT = 10
 VERBOSE_MODE = False
 
+XFROUT_MAX_MESSAGE_SIZE = 65535
+
+def get_rrset_len(rrset):
+    """Returns the wire length of the given RRset"""
+    bytes = bytearray()
+    rrset.to_wire(bytes)
+    return len(bytes)
+
+
 class XfroutSession(BaseRequestHandler):
     def __init__(self, request, client_address, server, log):
         # The initializer for the superclass may call functions
@@ -121,10 +130,8 @@
 
 
     def _send_message(self, sock, msg):
-        #obuf = output_buffer(0)
-        #render = message_render(obuf)
         render = MessageRenderer()
-        render.set_length_limit(65535)
+        render.set_length_limit(XFROUT_MAX_MESSAGE_SIZE)
         msg.to_wire(render)
         header_len = struct.pack('H', socket.htons(render.get_length()))
         self._send_data(sock, header_len)
@@ -227,34 +234,20 @@
         rrset_.add_rdata(rdata_)
         return rrset_
          
-    def _send_message_with_last_soa(self, msg, sock, rrset_soa):
+    def _send_message_with_last_soa(self, msg, sock, rrset_soa, message_upper_len):
         '''Add the SOA record to the end of message. If it can't be
         added, a new message should be created to send out the last soa .
         '''
-
-        render = MessageRenderer()
-        msg.to_wire(render)
-        old_message_len = render.get_length()
-        msg.add_rrset(Section.ANSWER(), rrset_soa)
-
-        msg.to_wire(render)
-        message_len = render.get_length()
-
-        if message_len != old_message_len:
+        rrset_len = get_rrset_len(rrset_soa)
+
+        if message_upper_len + rrset_len < XFROUT_MAX_MESSAGE_SIZE:
+            msg.add_rrset(Section.ANSWER(), rrset_soa)
+        else:
             self._send_message(sock, msg)
-        else:
             msg = self._clear_message(msg)
             msg.add_rrset(Section.ANSWER(), rrset_soa)
-            self._send_message(sock, msg)
-
-    def _get_message_len(self, msg):
-        '''Get message length, every time need do like this? Actually there should be 
-        a better way, I need check with jinmei later.
-        '''
-
-        render = MessageRenderer()
-        msg.to_wire(render)
-        return render.get_length()
+
+        self._send_message(sock, msg)
 
 
     def _reply_xfrout_query(self, msg, sock, zone_name):
@@ -265,9 +258,8 @@
         rrset_soa = self._create_rrset_from_db_record(soa_record)
         msg.add_rrset(Section.ANSWER(), rrset_soa)
 
-        old_message_len = 0
-        # TODO, Since add_rrset() return nothing when rrset can't be added, so I have to compare
-        # the message length to know if the rrset has been added sucessfully.
+        message_upper_len = get_rrset_len(rrset_soa)
+
         for rr_data in sqlite3_ds.get_zone_datas(zone_name, self.server.get_db_file()):
             if  self.server._shutdown_event.is_set(): # Check if xfrout is shutdown
                 self._log.log_message("error", "shutdown!")
@@ -277,19 +269,22 @@
                 continue
 
             rrset_ = self._create_rrset_from_db_record(rr_data)
-            msg.add_rrset(Section.ANSWER(), rrset_)
-            message_len = self._get_message_len(msg)
-            if message_len != old_message_len:
-                old_message_len = message_len
+
+            # We calculate the maximum size of the RRset (i.e. the
+            # size without compression) and use that to see if we
+            # may have reached the limit
+            rrset_len = get_rrset_len(rrset_)
+            if message_upper_len + rrset_len < XFROUT_MAX_MESSAGE_SIZE:
+                msg.add_rrset(Section.ANSWER(), rrset_)
+                message_upper_len += rrset_len
                 continue
 
             self._send_message(sock, msg)
             msg = self._clear_message(msg)
             msg.add_rrset(Section.ANSWER(), rrset_) # Add the rrset to the new message
-            old_message_len = 0
-
-        self._send_message_with_last_soa(msg, sock, rrset_soa)
-
+            message_upper_len = rrset_len
+
+        self._send_message_with_last_soa(msg, sock, rrset_soa, message_upper_len)
 
 class UnixSockServer(ThreadingUnixStreamServer):
     '''The unix domain socket server which accept xfr query sent from auth server.'''
@@ -315,8 +310,8 @@
         If it's not a socket file or nobody is listening
         , it will be removed. If it can't be removed, exit from python. '''
         if self._sock_file_in_use(sock_file):
-            print("[b10-xfrout] Fail to start xfrout process, unix socket" 
-                  " file '%s' is being used by another xfrout process" % sock_file)
+            sys.stderr.write("[b10-xfrout] Fail to start xfrout process, unix socket" 
+                  " file '%s' is being used by another xfrout process\n" % sock_file)
             sys.exit(0)
         else:
             if not os.path.exists(sock_file):
@@ -325,7 +320,7 @@
             try:
                 os.unlink(sock_file)
             except OSError as err:
-                print('[b10-xfrout] Fail to remove file ' + sock_file, err)
+                sys.stderr.write('[b10-xfrout] Fail to remove file %s: %s\n' % (sock_file, err))
                 sys.exit(0)
    
     def _sock_file_in_use(self, sock_file):
@@ -409,9 +404,9 @@
         self._listen_sock_file = UNIX_SOCKET_FILE 
         self._shutdown_event = threading.Event()
         self._cc = isc.config.ModuleCCSession(SPECFILE_LOCATION, self.config_handler, self.command_handler)
-        self._cc.add_remote_config(AUTH_SPECFILE_LOCATION);
         self._config_data = self._cc.get_full_config()
         self._cc.start()
+        self._cc.add_remote_config(AUTH_SPECFILE_LOCATION);
         self._log = isc.log.NSLogger(self._config_data.get('log_name'), self._config_data.get('log_file'),
                                 self._config_data.get('log_severity'), self._config_data.get('log_versions'),
                                 self._config_data.get('log_max_bytes'), True)
@@ -481,8 +476,8 @@
             zone_name = args.get('zone_name')
             zone_class = args.get('zone_class')
             if zone_name and zone_class:
-                self._log.log_message("info", "Receive notify command for zone:'%s/%s'" \
-                                     % (zone_name, zone_class))
+                self._log.log_message("info", "zone '%s/%s': receive notify others command" \
+                                       % (zone_name, zone_class))
                 self.send_notify(zone_name, zone_class)
                 answer = create_answer(0)
             else:
@@ -525,12 +520,15 @@
         xfrout_server = XfroutServer()
         xfrout_server.run()
     except KeyboardInterrupt:
-        sys.stderr.write("[b10-xfrout] exit xfrout process")
+        sys.stderr.write("[b10-xfrout] exit xfrout process\n")
     except SessionError as e:
-        sys.stderr.write("[b10-xfrout] Error creating xfrout," 
-                           "is the command channel daemon running?")
+        sys.stderr.write("[b10-xfrout] Error creating xfrout, "
+                           "is the command channel daemon running?\n")
+    except SessionTimeout as e:
+        sys.stderr.write("[b10-xfrout] Error creating xfrout, " 
+                           "is the configuration manager running?\n")
     except ModuleCCSessionError as e:
-        sys.stderr.write("info", '[b10-xfrout] exit xfrout process:', e)
+        sys.stderr.write("[b10-xfrout] exit xfrout process:%s\n" % str(e))
 
     if xfrout_server:
         xfrout_server.shutdown()

Modified: branches/trac311/src/bin/zonemgr/Makefile.am
==============================================================================
--- branches/trac311/src/bin/zonemgr/Makefile.am (original)
+++ branches/trac311/src/bin/zonemgr/Makefile.am Sun Sep 26 03:25:19 2010
@@ -1,4 +1,4 @@
-SUBDIRS = tests
+SUBDIRS = . tests
 
 pkglibexecdir = $(libexecdir)/@PACKAGE@
 
@@ -9,6 +9,16 @@
 
 CLEANFILES = b10-zonemgr zonemgr.pyc zonemgr.spec
 
+man_MANS = b10-zonemgr.8
+EXTRA_DIST = $(man_MANS) b10-zonemgr.xml
+
+if ENABLE_MAN
+
+b10-zonemgr.8: b10-zonemgr.xml
+	xsltproc --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/b10-zonemgr.xml
+
+endif
+
 zonemgr.spec: zonemgr.spec.pre
 	$(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" zonemgr.spec.pre >$@
 

Modified: branches/trac311/src/bin/zonemgr/TODO
==============================================================================
--- branches/trac311/src/bin/zonemgr/TODO (original)
+++ branches/trac311/src/bin/zonemgr/TODO Sun Sep 26 03:25:19 2010
@@ -1,1 +1,6 @@
 1. Zonemgr should support adding/deleting zones dynamically.
+2. Make zonemgr  has customizable configurations for LOWERBOUND_REFRESH, LOWERBOUND_RETRY, MAX_TRANSFER_TIMEOUT, REFRESH_OFFSET, RETRY_OFFSET, EXPIRED_OFFSET, and/or jitter?
+3. There should be one way to see the current counters/timers and other data for each zone managed by zonemgr.
+4. There should be one way to turn off zonemgr.(Does user really need it? not sure what's the purpose of user)
+
+

Modified: branches/trac311/src/bin/zonemgr/tests/Makefile.am
==============================================================================
--- branches/trac311/src/bin/zonemgr/tests/Makefile.am (original)
+++ branches/trac311/src/bin/zonemgr/tests/Makefile.am Sun Sep 26 03:25:19 2010
@@ -8,5 +8,5 @@
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
 	env PYTHONPATH=$(abs_top_builddir)/src/bin/zonemgr:$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/lib/xfr/.libs \
-	$(PYCOVERAGE) $(abs_srcdir)/$$pytest ; \
+	$(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
 	done

Modified: branches/trac311/src/bin/zonemgr/zonemgr.py.in
==============================================================================
--- branches/trac311/src/bin/zonemgr/zonemgr.py.in (original)
+++ branches/trac311/src/bin/zonemgr/zonemgr.py.in Sun Sep 26 03:25:19 2010
@@ -153,8 +153,8 @@
     def zone_refresh_success(self, zone_name_class):
         """Update zone info after zone refresh success"""
         if (self._zone_not_exist(zone_name_class)):
-            raise ZonemgrException("[b10-zonemgr] Zone (%s, %s) doesn't \
-                                    belong to zonemgr" % zone_name_class)
+            raise ZonemgrException("[b10-zonemgr] Zone (%s, %s) doesn't "
+                                   "belong to zonemgr" % zone_name_class)
             return
         self.zonemgr_reload_zone(zone_name_class)
         self._set_zone_refresh_timer(zone_name_class)
@@ -164,8 +164,8 @@
     def zone_refresh_fail(self, zone_name_class):
         """Update zone info after zone refresh fail"""
         if (self._zone_not_exist(zone_name_class)):
-            raise ZonemgrException("[b10-zonemgr] Zone (%s, %s) doesn't \
-                                    belong to zonemgr" % zone_name_class)
+            raise ZonemgrException("[b10-zonemgr] Zone (%s, %s) doesn't "
+                                   "belong to zonemgr" % zone_name_class)
             return
         self._set_zone_state(zone_name_class, ZONE_OK)
         self._set_zone_retry_timer(zone_name_class)
@@ -173,8 +173,8 @@
     def zone_handle_notify(self, zone_name_class, master):
         """Handle zone notify"""
         if (self._zone_not_exist(zone_name_class)):
-            raise ZonemgrException("[b10-zonemgr] Notified zone (%s, %s) doesn't \
-                                    belong to zonemgr" % zone_name_class)
+            raise ZonemgrException("[b10-zonemgr] Notified zone (%s, %s) "
+                                   "doesn't belong to zonemgr" % zone_name_class)
             return
         self._set_zone_notifier_master(zone_name_class, master)
         self._set_zone_notify_timer(zone_name_class)
@@ -513,12 +513,15 @@
         zonemgrd = Zonemgr()
         zonemgrd.run()
     except KeyboardInterrupt:
-        sys.stderr.write("[b10-zonemgr] exit zonemgr process")
+        sys.stderr.write("[b10-zonemgr] exit zonemgr process\n")
     except isc.cc.session.SessionError as e:
-        sys.stderr.write("[b10-zonemgr] Error creating ,zonemgr" 
-                           "is the command channel daemon running?")
+        sys.stderr.write("[b10-zonemgr] Error creating zonemgr, " 
+                           "is the command channel daemon running?\n")
+    except isc.cc.session.SessionTimeout as e:
+        sys.stderr.write("[b10-zonemgr] Error creating zonemgr, " 
+                           "is the configuration manager running?\n")
     except isc.config.ModuleCCSessionError as e:
-        sys.stderr.write("info", "[b10-zonemgr] exit zonemgr process:", e)
+        sys.stderr.write("[b10-zonemgr] exit zonemgr process: %s\n" % str(e))
 
     if zonemgrd:
         zonemgrd.shutdown()

Modified: branches/trac311/src/lib/bench/tests/benchmark_unittest.cc
==============================================================================
--- branches/trac311/src/lib/bench/tests/benchmark_unittest.cc (original)
+++ branches/trac311/src/lib/bench/tests/benchmark_unittest.cc Sun Sep 26 03:25:19 2010
@@ -58,7 +58,7 @@
 };
 
 // XXX: some compilers cannot find class static constants used in
-// EXPECT_xxx macross, for which we need an explicit definition.
+// EXPECT_xxx macros, for which we need an explicit definition.
 template <typename T>
 const int BenchMark<T>::TIME_FAILURE;
 }

Modified: branches/trac311/src/lib/cc/data.cc
==============================================================================
--- branches/trac311/src/lib/cc/data.cc (original)
+++ branches/trac311/src/lib/cc/data.cc Sun Sep 26 03:25:19 2010
@@ -20,6 +20,7 @@
 
 #include <cassert>
 #include <climits>
+#include <map>
 #include <cstdio>
 #include <iostream>
 #include <string>
@@ -35,21 +36,21 @@
 namespace data {
 
 std::string
-Element::str() {
+Element::str() const {
     std::stringstream ss;
     toJSON(ss);
     return (ss.str());
 }
 
 std::string
-Element::toWire() {
+Element::toWire() const {
     std::stringstream ss;
     toJSON(ss);
     return (ss.str());
 }
 
 void
-Element::toWire(std::ostream& ss) {
+Element::toWire(std::ostream& ss) const {
     toJSON(ss);
 }
 
@@ -81,12 +82,12 @@
 }
 
 bool
-Element::getValue(std::vector<ElementPtr>& t UNUSED_PARAM) {
-    return (false);
-}
-
-bool
-Element::getValue(std::map<std::string, ElementPtr>& t UNUSED_PARAM) {
+Element::getValue(std::vector<ConstElementPtr>& t UNUSED_PARAM) {
+    return (false);
+}
+
+bool
+Element::getValue(std::map<std::string, ConstElementPtr>& t UNUSED_PARAM) {
     return (false);
 }
 
@@ -111,27 +112,29 @@
 }
 
 bool
-Element::setValue(const std::vector<ElementPtr>& v UNUSED_PARAM) {
-    return (false);
-}
-
-bool
-Element::setValue(const std::map<std::string, ElementPtr>& v UNUSED_PARAM) {
-    return (false);
-}
-
-ElementPtr
-Element::get(const int i UNUSED_PARAM) {
+Element::setValue(const std::vector<ConstElementPtr>& v UNUSED_PARAM) {
+    return (false);
+}
+
+bool
+Element::setValue(const std::map<std::string,
+                  ConstElementPtr>& v UNUSED_PARAM)
+{
+    return (false);
+}
+
+ConstElementPtr
+Element::get(const int i UNUSED_PARAM) const {
     isc_throw(TypeError, "get(int) called on a non-list Element");
 }
 
 void
-Element::set(const size_t i UNUSED_PARAM, ElementPtr element UNUSED_PARAM) {
+Element::set(const size_t i UNUSED_PARAM, ConstElementPtr element UNUSED_PARAM) {
     isc_throw(TypeError, "set(int, element) called on a non-list Element");
 }
 
 void
-Element::add(ElementPtr element UNUSED_PARAM) {
+Element::add(ConstElementPtr element UNUSED_PARAM) {
     isc_throw(TypeError, "add() called on a non-list Element");
 }
 
@@ -141,18 +144,18 @@
 }
 
 size_t
-Element::size() {
+Element::size() const {
     isc_throw(TypeError, "size() called on a non-list Element");
 }
 
-ElementPtr
-Element::get(const std::string& name UNUSED_PARAM) {
+ConstElementPtr
+Element::get(const std::string& name UNUSED_PARAM) const {
     isc_throw(TypeError, "get(string) called on a non-map Element");
 }
 
 void
 Element::set(const std::string& name UNUSED_PARAM,
-             ElementPtr element UNUSED_PARAM)
+             ConstElementPtr element UNUSED_PARAM)
 {
     isc_throw(TypeError, "set(name, element) called on a non-map Element");
 }
@@ -163,18 +166,18 @@
 }
 
 bool
-Element::contains(const std::string& name UNUSED_PARAM) {
+Element::contains(const std::string& name UNUSED_PARAM) const {
     isc_throw(TypeError, "contains(string) called on a non-map Element");
 }
 
-ElementPtr
-Element::find(const std::string& identifier UNUSED_PARAM) {
+ConstElementPtr
+Element::find(const std::string& identifier UNUSED_PARAM) const {
     isc_throw(TypeError, "find(string) called on a non-map Element");
 }
 
 bool
 Element::find(const std::string& identifier UNUSED_PARAM,
-              ElementPtr& t UNUSED_PARAM)
+              ConstElementPtr t UNUSED_PARAM) const
 {
     return (false);
 }
@@ -189,12 +192,18 @@
 }
 }
 
-std::ostream& operator <<(std::ostream &out, const isc::data::ElementPtr& e) {
-    return (out << e->str());
-}
-
-bool operator==(const isc::data::ElementPtr a, const isc::data::ElementPtr b) {
-    return (a->equals(b));
+std::ostream&
+operator<<(std::ostream &out, const Element& e) {
+    return (out << e.str());
+}
+
+bool
+operator==(const Element& a, const Element& b) {
+    return (a.equals(b));
+}
+
+bool operator!=(const Element& a, const Element& b) {
+    return (!a.equals(b));
 };
 
 //
@@ -428,7 +437,7 @@
 {
     char c = 0;
     ElementPtr list = Element::createList();
-    ElementPtr cur_list_element;
+    ConstElementPtr cur_list_element;
 
     skip_chars(in, " \t\n", line, pos);
     while (c != EOF && c != ']') {
@@ -462,7 +471,7 @@
             in.get();
             pos++;
 
-            ElementPtr value = Element::fromJSON(in, file, line, pos);
+            ConstElementPtr value = Element::fromJSON(in, file, line, pos);
             map->set(key, value);
             
             skip_to(in, file, line, pos, ",}", " \t\n");
@@ -614,20 +623,17 @@
 // to JSON format
 
 void
-IntElement::toJSON(std::ostream& ss)
-{
+IntElement::toJSON(std::ostream& ss) const {
     ss << intValue();
 }
 
 void
-DoubleElement::toJSON(std::ostream& ss)
-{
+DoubleElement::toJSON(std::ostream& ss) const {
     ss << doubleValue();
 }
 
 void
-BoolElement::toJSON(std::ostream& ss)
-{
+BoolElement::toJSON(std::ostream& ss) const {
     if (boolValue()) {
         ss << "true";
     } else {
@@ -636,26 +642,23 @@
 }
 
 void
-NullElement::toJSON(std::ostream& ss)
-{
+NullElement::toJSON(std::ostream& ss) const {
     ss << "null";
 }
 
 void
-StringElement::toJSON(std::ostream& ss)
-{
+StringElement::toJSON(std::ostream& ss) const {
     ss << "\"";
     ss << stringValue();
     ss << "\"";
 }
 
 void
-ListElement::toJSON(std::ostream& ss)
-{
+ListElement::toJSON(std::ostream& ss) const {
     ss << "[ ";
 
-    const std::vector<ElementPtr>& v = listValue();
-    for (std::vector<ElementPtr>::const_iterator it = v.begin();
+    const std::vector<ConstElementPtr>& v = listValue();
+    for (std::vector<ConstElementPtr>::const_iterator it = v.begin();
          it != v.end(); ++it) {
         if (it != v.begin()) {
             ss << ", ";
@@ -666,12 +669,11 @@
 }
 
 void
-MapElement::toJSON(std::ostream& ss)
-{
+MapElement::toJSON(std::ostream& ss) const {
     ss << "{ ";
 
-    const std::map<std::string, ElementPtr>& m = mapValue();
-    for (std::map<std::string, ElementPtr>::const_iterator it = m.begin();
+    const std::map<std::string, ConstElementPtr>& m = mapValue();
+    for (std::map<std::string, ConstElementPtr>::const_iterator it = m.begin();
          it != m.end(); ++it) {
         if (it != m.begin()) {
             ss << ", ";
@@ -690,13 +692,13 @@
 // we're looking for) is not a MapElement
 // returns 0 if it could simply not be found
 // should that also be an exception?
-ElementPtr
-MapElement::find(const std::string& id) {
+ConstElementPtr
+MapElement::find(const std::string& id) const {
     const size_t sep = id.find('/');
     if (sep == std::string::npos) {
         return (get(id));
     } else {
-        ElementPtr ce = get(id.substr(0, sep));
+        ConstElementPtr ce = get(id.substr(0, sep));
         if (ce) {
             // ignore trailing slash
             if  (sep + 1 != id.size()) {
@@ -735,14 +737,14 @@
 }
 
 void
-MapElement::set(const std::string& key, ElementPtr value) {
+MapElement::set(const std::string& key, ConstElementPtr value) {
     m[key] = value;
 }
 
 bool
-MapElement::find(const std::string& id, ElementPtr& t) {
+MapElement::find(const std::string& id, ConstElementPtr t) const {
     try {
-        ElementPtr p = find(id);
+        ConstElementPtr p = find(id);
         if (p) {
             t = p;
             return (true);
@@ -754,43 +756,43 @@
 }
 
 bool
-IntElement::equals(ElementPtr other) {
-    return (other->getType() == Element::integer) &&
-           (i == other->intValue());
-}
-
-bool
-DoubleElement::equals(ElementPtr other) {
-    return (other->getType() == Element::real) &&
-           (d == other->doubleValue());
-}
-
-bool
-BoolElement::equals(ElementPtr other) {
-    return (other->getType() == Element::boolean) &&
-           (b == other->boolValue());
-}
-
-bool
-NullElement::equals(ElementPtr other) {
-    return (other->getType() == Element::null);
-}
-
-bool
-StringElement::equals(ElementPtr other) {
-    return (other->getType() == Element::string) &&
-           (s == other->stringValue());
-}
-
-bool
-ListElement::equals(ElementPtr other) {
-    if (other->getType() == Element::list) {
+IntElement::equals(const Element& other) const {
+    return (other.getType() == Element::integer) &&
+           (i == other.intValue());
+}
+
+bool
+DoubleElement::equals(const Element& other) const {
+    return (other.getType() == Element::real) &&
+           (d == other.doubleValue());
+}
+
+bool
+BoolElement::equals(const Element& other) const {
+    return (other.getType() == Element::boolean) &&
+           (b == other.boolValue());
+}
+
+bool
+NullElement::equals(const Element& other) const {
+    return (other.getType() == Element::null);
+}
+
+bool
+StringElement::equals(const Element& other) const {
+    return (other.getType() == Element::string) &&
+           (s == other.stringValue());
+}
+
+bool
+ListElement::equals(const Element& other) const {
+    if (other.getType() == Element::list) {
         const int s = size();
-        if (s != other->size()) {
+        if (s != other.size()) {
             return (false);
         }
         for (int i = 0; i < s; ++i) {
-            if (!get(i)->equals(other->get(i))) {
+            if (!get(i)->equals(*other.get(i))) {
                 return (false);
             }
         }
@@ -801,13 +803,14 @@
 }
 
 bool
-MapElement::equals(ElementPtr other) {
-    if (other->getType() == Element::map) {
-        std::map<std::string, ElementPtr> m = mapValue();
-        for (std::map<std::string, ElementPtr>::const_iterator it = m.begin();
+MapElement::equals(const Element& other) const {
+    if (other.getType() == Element::map) {
+        const std::map<std::string, ConstElementPtr>& m = mapValue();
+        for (std::map<std::string, ConstElementPtr>::const_iterator it =
+                 m.begin();
              it != m.end() ; ++it) {
-            if (other->contains((*it).first)) {
-                if (!get((*it).first)->equals(other->get((*it).first))) {
+            if (other.contains((*it).first)) {
+                if (!get((*it).first)->equals(*other.get((*it).first))) {
                     return (false);
                 }
             } else {
@@ -819,9 +822,10 @@
         // compare those elements; if one of them is missing we
         // differ (and if it's not missing the loop above has checked
         // it)
-        m = other->mapValue();
-        for (std::map<std::string, ElementPtr>::const_iterator it = m.begin();
-             it != m.end() ; ++it) {
+        std::map<std::string, ConstElementPtr>::const_iterator it;
+        for (it = other.mapValue().begin();
+             it != other.mapValue().end();
+             ++it) {
             if (!contains((*it).first)) {
                 return (false);
             }
@@ -833,12 +837,12 @@
 }
 
 bool
-isNull(ElementPtr p) {
+isNull(ConstElementPtr p) {
     return (!p);
 }
 
 void
-removeIdentical(ElementPtr a, const ElementPtr b) {
+removeIdentical(ElementPtr a, ConstElementPtr b) {
     if (!b) {
         return;
     }
@@ -846,26 +850,50 @@
         isc_throw(TypeError, "Non-map Elements passed to removeIdentical");
     }
 
-    std::map<std::string, ElementPtr> m = a->mapValue();
-    for (std::map<std::string, ElementPtr>::const_iterator it = m.begin();
+    const std::map<std::string, ConstElementPtr>& m = a->mapValue();
+    for (std::map<std::string, ConstElementPtr>::const_iterator it = m.begin();
          it != m.end() ; ++it) {
         if (b->contains((*it).first)) {
-            if (a->get((*it).first)->equals(b->get((*it).first))) {
+            if (a->get((*it).first)->equals(*b->get((*it).first))) {
                 a->remove((*it).first);
             }
         }
     }
 }
 
-void
-merge(ElementPtr element, const ElementPtr other) {
+ConstElementPtr
+removeIdentical(ConstElementPtr a, ConstElementPtr b) {
+    ElementPtr result = Element::createMap();
+
+    if (!b) {
+        return (result);
+    }
+    
+    if (a->getType() != Element::map || b->getType() != Element::map) {
+        isc_throw(TypeError, "Non-map Elements passed to removeIdentical");
+    }
+
+    const std::map<std::string, ConstElementPtr>& m = a->mapValue();
+    for (std::map<std::string, ConstElementPtr>::const_iterator it = m.begin();
+         it != m.end() ; ++it) {
+        if (!b->contains((*it).first) ||
+            !a->get((*it).first)->equals(*b->get((*it).first))) {
+            result->set((*it).first, (*it).second);
+        }
+    }
+
+    return (result);
+}
+
+void
+merge(ElementPtr element, ConstElementPtr other) {
     if (element->getType() != Element::map ||
         other->getType() != Element::map) {
         isc_throw(TypeError, "merge arguments not MapElements");
     }
     
-    std::map<std::string, ElementPtr> m = other->mapValue();
-    for (std::map<std::string, ElementPtr>::const_iterator it = m.begin();
+    std::map<std::string, ConstElementPtr> m = other->mapValue();
+    for (std::map<std::string, ConstElementPtr>::const_iterator it = m.begin();
          it != m.end() ; ++it) {
         if ((*it).second && (*it).second->getType() != Element::null) {
             element->set((*it).first, (*it).second);

Modified: branches/trac311/src/lib/cc/data.h
==============================================================================
--- branches/trac311/src/lib/cc/data.h (original)
+++ branches/trac311/src/lib/cc/data.h Sun Sep 26 03:25:19 2010
@@ -29,6 +29,7 @@
 class Element;
 // todo: describe the rationale behind ElementPtr?
 typedef boost::shared_ptr<Element> ElementPtr;
+typedef boost::shared_ptr<const Element> ConstElementPtr;
 
 ///
 /// \brief A standard Data module exception that is thrown if a function
@@ -90,7 +91,7 @@
     virtual ~Element() {};
 
     /// \return the type of this element
-    int getType() { return (type); }
+    int getType() const { return (type); }
 
     /// Returns a string representing the Element and all its
     /// child elements; note that this is different from stringValue(),
@@ -99,24 +100,24 @@
     /// The resulting string will contain the Element in JSON format.
     ///
     /// \return std::string containing the string representation
-    std::string str();
+    std::string str() const;
 
     /// Returns the wireformat for the Element and all its child
     /// elements.
     ///
     /// \return std::string containing the element in wire format
-    std::string toWire();
-    void toWire(std::ostream& out);
+    std::string toWire() const;
+    void toWire(std::ostream& out) const;
 
     /// \name pure virtuals, every derived class must implement these
 
     /// \returns true if the other ElementPtr has the same type and
     ///          value
-    virtual bool equals(ElementPtr other) = 0;
+    virtual bool equals(const Element& other) const = 0;
     
     /// Converts the Element to JSON format and appends it to
     /// the given stringstream.
-    virtual void toJSON(std::ostream& ss) = 0;
+    virtual void toJSON(std::ostream& ss) const = 0;
 
     /// \name Type-specific getters
     ///
@@ -126,12 +127,22 @@
     /// If you want an exception-safe getter method, use
     /// getValue() below
     //@{
-    virtual long int intValue() { isc_throw(TypeError, "intValue() called on non-integer Element"); };
-    virtual double doubleValue() { isc_throw(TypeError, "doubleValue() called on non-double Element"); };
-    virtual bool boolValue() { isc_throw(TypeError, "boolValue() called on non-Bool Element"); };
-    virtual std::string stringValue() { isc_throw(TypeError, "stringValue() called on non-string Element"); };
-    virtual const std::vector<boost::shared_ptr<Element> >& listValue() { isc_throw(TypeError, "listValue() called on non-list Element"); }; // replace with real exception or empty vector?
-    virtual const std::map<std::string, boost::shared_ptr<Element> >& mapValue() { isc_throw(TypeError, "mapValue() called on non-map Element"); }; // replace with real exception or empty map?
+    virtual long int intValue() const
+    { isc_throw(TypeError, "intValue() called on non-integer Element"); };
+    virtual double doubleValue() const
+    { isc_throw(TypeError, "doubleValue() called on non-double Element"); };
+    virtual bool boolValue() const
+    { isc_throw(TypeError, "boolValue() called on non-Bool Element"); };
+    virtual std::string stringValue() const
+    { isc_throw(TypeError, "stringValue() called on non-string Element"); };
+    virtual const std::vector<ConstElementPtr>& listValue() const {
+        // replace with real exception or empty vector?
+        isc_throw(TypeError, "listValue() called on non-list Element");
+    };
+    virtual const std::map<std::string, ConstElementPtr>& mapValue() const {
+        // replace with real exception or empty map?
+        isc_throw(TypeError, "mapValue() called on non-map Element");
+    };
     //@}
 
     /// \name Exception-safe getters
@@ -147,8 +158,8 @@
     virtual bool getValue(double& t);
     virtual bool getValue(bool& t);
     virtual bool getValue(std::string& t);
-    virtual bool getValue(std::vector<ElementPtr>& t);
-    virtual bool getValue(std::map<std::string, ElementPtr>& t);
+    virtual bool getValue(std::vector<ConstElementPtr>& t);
+    virtual bool getValue(std::map<std::string, ConstElementPtr>& t);
     //@}
 
     ///
@@ -163,8 +174,8 @@
     virtual bool setValue(const double v);
     virtual bool setValue(const bool t);
     virtual bool setValue(const std::string& v);
-    virtual bool setValue(const std::vector<ElementPtr>& v);
-    virtual bool setValue(const std::map<std::string, ElementPtr>& v);
+    virtual bool setValue(const std::vector<ConstElementPtr>& v);
+    virtual bool setValue(const std::map<std::string, ConstElementPtr>& v);
     //@}
 
 
@@ -179,17 +190,17 @@
     /// Returns the ElementPtr at the given index. If the index is out
     /// of bounds, this function throws an std::out_of_range exception.
     /// \param i The position of the ElementPtr to return
-    virtual ElementPtr get(const int i);
+    virtual ConstElementPtr get(const int i) const;
 
     /// Sets the ElementPtr at the given index. If the index is out
     /// of bounds, this function throws an std::out_of_range exception.
     /// \param i The position of the ElementPtr to set
     /// \param element The ElementPtr to set at the position
-    virtual void set(const size_t i, ElementPtr element);
+    virtual void set(const size_t i, ConstElementPtr element);
 
     /// Adds an ElementPtr to the list
     /// \param element The ElementPtr to add
-    virtual void add(ElementPtr element);
+    virtual void add(ConstElementPtr element);
 
     /// Removes the element at the given position. If the index is out
     /// of nothing happens.
@@ -197,7 +208,7 @@
     virtual void remove(const int i);
 
     /// Returns the number of elements in the list.
-    virtual size_t size();
+    virtual size_t size() const;
     //@}
 
     
@@ -209,11 +220,11 @@
     /// Returns the ElementPtr at the given key
     /// \param name The key of the Element to return
     /// \return The ElementPtr at the given key
-    virtual ElementPtr get(const std::string& name);
+    virtual ConstElementPtr get(const std::string& name) const;
 
     /// Sets the ElementPtr at the given key
     /// \param name The key of the Element to set
-    virtual void set(const std::string& name, ElementPtr element);
+    virtual void set(const std::string& name, ConstElementPtr element);
 
     /// Remove the ElementPtr at the given key
     /// \param name The key of the Element to remove
@@ -222,7 +233,7 @@
     /// Checks if there is data at the given key
     /// \param name The key of the Element to remove
     /// \return true if there is data at the key, false if not.
-    virtual bool contains(const std::string& name);
+    virtual bool contains(const std::string& name) const;
 
     /// Recursively finds any data at the given identifier. The
     /// identifier is a /-separated list of names of nested maps, with
@@ -237,13 +248,13 @@
     /// \return The ElementPtr at the given identifier. Returns a
     /// null ElementPtr if it is not found, which can be checked with
     /// Element::is_null(ElementPtr e).
-    virtual ElementPtr find(const std::string& identifier);
+    virtual ConstElementPtr find(const std::string& identifier) const;
 
     /// See \c Element::find()
     /// \param identifier The identifier of the element to find
     /// \param t Reference to store the resulting ElementPtr, if found.
     /// \return true if the element was found, false if not.
-    virtual bool find(const std::string& identifier, ElementPtr& t);
+    virtual bool find(const std::string& identifier, ConstElementPtr t) const;
     //@}
 
 
@@ -365,13 +376,13 @@
 
 public:
     IntElement(long int v) : Element(integer), i(v) { }
-    long int intValue() { return (i); }
+    long int intValue() const { return (i); }
     using Element::getValue;
     bool getValue(long int& t) { t = i; return (true); }
     using Element::setValue;
     bool setValue(const long int v) { i = v; return (true); }
-    void toJSON(std::ostream& ss);
-    bool equals(ElementPtr other);
+    void toJSON(std::ostream& ss) const;
+    bool equals(const Element& other) const;
 };
 
 class DoubleElement : public Element {
@@ -379,13 +390,13 @@
 
 public:
     DoubleElement(double v) : Element(real), d(v) {};
-    double doubleValue() { return (d); }
+    double doubleValue() const { return (d); }
     using Element::getValue;
     bool getValue(double& t) { t = d; return (true); }
     using Element::setValue;
     bool setValue(const double v) { d = v; return (true); }
-    void toJSON(std::ostream& ss);
-    bool equals(ElementPtr other);
+    void toJSON(std::ostream& ss) const;
+    bool equals(const Element& other) const;
 };
 
 class BoolElement : public Element {
@@ -393,20 +404,20 @@
 
 public:
     BoolElement(const bool v) : Element(boolean), b(v) {};
-    bool boolValue() { return (b); }
+    bool boolValue() const { return (b); }
     using Element::getValue;
     bool getValue(bool& t) { t = b; return (true); }
     using Element::setValue;
     bool setValue(const bool v) { b = v; return (true); }
-    void toJSON(std::ostream& ss);
-    bool equals(ElementPtr other);
+    void toJSON(std::ostream& ss) const;
+    bool equals(const Element& other) const;
 };
 
 class NullElement : public Element {
 public:
     NullElement() : Element(null) {};
-    void toJSON(std::ostream& ss);
-    bool equals(ElementPtr other);
+    void toJSON(std::ostream& ss) const;
+    bool equals(const Element& other) const;
 };
 
 class StringElement : public Element {
@@ -414,77 +425,97 @@
 
 public:
     StringElement(std::string v) : Element(string), s(v) {};
-    std::string stringValue() { return (s); }
+    std::string stringValue() const { return (s); }
     using Element::getValue;
     bool getValue(std::string& t) { t = s; return (true); }
     using Element::setValue;
     bool setValue(const std::string& v) { s = v; return (true); }
-    void toJSON(std::ostream& ss);
-    bool equals(ElementPtr other);
+    void toJSON(std::ostream& ss) const;
+    bool equals(const Element& other) const;
 };
 
 class ListElement : public Element {
-    std::vector<ElementPtr> l;
-
-public:
-    ListElement() : Element(list), l(std::vector<ElementPtr>()) {};
-    const std::vector<ElementPtr>& listValue() { return (l); }
+    std::vector<ConstElementPtr> l;
+
+public:
+    ListElement() : Element(list) {}
+    const std::vector<ConstElementPtr>& listValue() const { return (l); }
     using Element::getValue;
-    bool getValue(std::vector<ElementPtr>& t) { t = l; return (true); }
+    bool getValue(std::vector<ConstElementPtr>& t) {
+        t = l;
+        return (true);
+    }
     using Element::setValue;
-    bool setValue(const std::vector<ElementPtr>& v) { l = v; return (true); }
+    bool setValue(const std::vector<ConstElementPtr>& v) {
+        l = v;
+        return (true);
+    }
     using Element::get;
-    ElementPtr get(int i) { return (l.at(i)); }
+    ConstElementPtr get(int i) const { return (l.at(i)); }
     using Element::set;
-    void set(size_t i, ElementPtr e) { if (i <= l.size()) {l[i] = e;} else { throw std::out_of_range("vector::_M_range_check"); } };
-    void add(ElementPtr e) { l.push_back(e); };
+    void set(size_t i, ConstElementPtr e) {
+        l.at(i) = e;
+    }
+    void add(ConstElementPtr e) { l.push_back(e); };
     using Element::remove;
     void remove(int i) { l.erase(l.begin() + i); };
-    void toJSON(std::ostream& ss);
-    size_t size() { return (l.size()); }
-    bool equals(ElementPtr other);
+    void toJSON(std::ostream& ss) const;
+    size_t size() const { return (l.size()); }
+    bool equals(const Element& other) const;
 };
 
 class MapElement : public Element {
-    std::map<std::string, ElementPtr> m;
-
-public:
-    MapElement() : Element(map), m(std::map<std::string, ElementPtr>()) {};
+    std::map<std::string, ConstElementPtr> m;
+
+public:
+    MapElement() : Element(map) {}
     // TODO: should we have direct iterators instead of exposing the std::map here?
-    const std::map<std::string, ElementPtr>& mapValue() { return (m); }
+    const std::map<std::string, ConstElementPtr>& mapValue() const {
+        return (m);
+    }
     using Element::getValue;
-    bool getValue(std::map<std::string, ElementPtr>& t) { t = m; return (true); }
+    bool getValue(std::map<std::string, ConstElementPtr>& t) {
+        t = m;
+        return (true);
+    }
     using Element::setValue;
-    bool setValue(std::map<std::string, ElementPtr>& v) { m = v; return (true); }
+    bool setValue(std::map<std::string, ConstElementPtr>& v) {
+        m = v;
+        return (true);
+    }
     using Element::get;
-    ElementPtr get(const std::string& s) { if (contains(s)) { return (m[s]); } else { return (ElementPtr());} }
+    ConstElementPtr get(const std::string& s) const {
+        return (contains(s) ? m.find(s)->second : ConstElementPtr());
+    }
     using Element::set;
-    void set(const std::string& key, ElementPtr value);
+    void set(const std::string& key, ConstElementPtr value);
     using Element::remove;
     void remove(const std::string& s) { m.erase(s); }
-    bool contains(const std::string& s) { return (m.find(s) != m.end()); }
-    void toJSON(std::ostream& ss);
+    bool contains(const std::string& s) const {
+        return (m.find(s) != m.end());
+    }
+    void toJSON(std::ostream& ss) const;
     
     // we should name the two finds better...
     // find the element at id; raises TypeError if one of the
     // elements at path except the one we're looking for is not a
     // mapelement.
     // returns an empty element if the item could not be found
-    ElementPtr find(const std::string& id);
+    ConstElementPtr find(const std::string& id) const;
 
     // find the Element at 'id', and store the element pointer in t
     // returns true if found, or false if not found (either because
     // it doesnt exist or one of the elements in the path is not
     // a MapElement)
-    bool find(const std::string& id, ElementPtr& t);
-
-    bool equals(ElementPtr other);
+    bool find(const std::string& id, ConstElementPtr t) const;
+
+    bool equals(const Element& other) const;
 };
 
 /// Checks whether the given ElementPtr is a NULL pointer
 /// \param p The ElementPtr to check
 /// \return true if it is NULL, false if not.
-bool isNull(ElementPtr p);
+bool isNull(ConstElementPtr p);
 
 ///
 /// \brief Remove all values from the first ElementPtr that are
@@ -493,7 +524,14 @@
 /// only contains new and changed values (for ModuleCCSession and
 /// configuration update handlers)
 /// Raises a TypeError if a or b are not MapElements
-void removeIdentical(ElementPtr a, const ElementPtr b);
+void removeIdentical(ElementPtr a, ConstElementPtr b);
+
+/// \brief Create a new ElementPtr from the first ElementPtr, removing all
+/// values that are equal in the second. Both ElementPtrs MUST be MapElements.
+/// The returned ElementPtr will be a MapElement that only contains new and
+/// changed values (for ModuleCCSession and configuration update handlers).
+/// Raises a TypeError if a or b are not MapElements
+ConstElementPtr removeIdentical(ConstElementPtr a, ConstElementPtr b);
 
 /// \brief Merges the data from other into element.
 /// (on the first level). Both elements must be
@@ -507,7 +545,7 @@
 /// configuration data (which would then result in reverting back
 /// to the default).
 /// Raises a TypeError if either ElementPtr is not a MapElement
-void merge(ElementPtr element, const ElementPtr other);
+void merge(ElementPtr element, ConstElementPtr other);
 
 ///
 /// \brief Insert the Element as a string into stream.
@@ -524,11 +562,11 @@
 /// \param e The \c ElementPtr object to insert.
 /// \return A reference to the same \c std::ostream object referenced by
 /// parameter \c os after the insertion operation.
-std::ostream& operator <<(std::ostream &out, const isc::data::ElementPtr& e);
-
-bool operator==(const isc::data::ElementPtr a, const isc::data::ElementPtr b);
+std::ostream& operator<<(std::ostream& out, const Element& e);
+
+bool operator==(const Element& a, const Element& b);
+bool operator!=(const Element& a, const Element& b);
 } }
-
 #endif // _ISC_DATA_H
 
 // Local Variables: 

Modified: branches/trac311/src/lib/cc/session.cc
==============================================================================
--- branches/trac311/src/lib/cc/session.cc (original)
+++ branches/trac311/src/lib/cc/session.cc Sun Sep 26 03:25:19 2010
@@ -296,11 +296,11 @@
     //
     // send a request for our local name, and wait for a response
     //
-    ElementPtr get_lname_msg =
+    ConstElementPtr get_lname_msg =
         Element::fromJSON("{ \"type\": \"getlname\" }");
     sendmsg(get_lname_msg);
 
-    ElementPtr routing, msg;
+    ConstElementPtr routing, msg;
     recvmsg(routing, msg, false);
 
     impl_->lname_ = msg->get("lname")->stringValue();
@@ -314,7 +314,7 @@
 // prefix.
 //
 void
-Session::sendmsg(ElementPtr& msg) {
+Session::sendmsg(ConstElementPtr msg) {
     std::string header_wire = msg->toWire();
     unsigned int length = 2 + header_wire.length();
     unsigned int length_net = htonl(length);
@@ -327,7 +327,7 @@
 }
 
 void
-Session::sendmsg(ElementPtr& env, ElementPtr& msg) {
+Session::sendmsg(ConstElementPtr env, ConstElementPtr msg) {
     std::string header_wire = env->toWire();
     std::string body_wire = msg->toWire();
     unsigned int length = 2 + header_wire.length() + body_wire.length();
@@ -342,18 +342,18 @@
 }
 
 bool
-Session::recvmsg(ElementPtr& msg, bool nonblock, int seq) {
-    ElementPtr l_env;
+Session::recvmsg(ConstElementPtr& msg, bool nonblock, int seq) {
+    ConstElementPtr l_env;
     return (recvmsg(l_env, msg, nonblock, seq));
 }
 
 bool
-Session::recvmsg(ElementPtr& env, ElementPtr& msg,
-                 bool nonblock, int seq) {
+Session::recvmsg(ConstElementPtr& env, ConstElementPtr& msg,
+                 bool nonblock, int seq)
+{
     size_t length = impl_->readDataLength();
-    ElementPtr l_env, l_msg;
     if (hasQueuedMsgs()) {
-        ElementPtr q_el;
+        ConstElementPtr q_el;
         for (int i = 0; i < impl_->queue_->size(); i++) {
             q_el = impl_->queue_->get(i);
             if (( seq == -1 &&
@@ -390,11 +390,13 @@
                                         length - header_length);
     std::stringstream header_wire_stream;
     header_wire_stream << header_wire;
-    l_env = Element::fromWire(header_wire_stream, header_length);
+    ConstElementPtr l_env =
+        Element::fromWire(header_wire_stream, header_length);
     
     std::stringstream body_wire_stream;
     body_wire_stream << body_wire;
-    l_msg = Element::fromWire(body_wire_stream, length - header_length);
+    ConstElementPtr l_msg =
+        Element::fromWire(body_wire_stream, length - header_length);
     if ((seq == -1 &&
          !l_env->contains("reply")
         ) || (
@@ -438,7 +440,7 @@
 }
 
 int
-Session::group_sendmsg(ElementPtr msg, std::string group,
+Session::group_sendmsg(ConstElementPtr msg, std::string group,
                        std::string instance, std::string to)
 {
     ElementPtr env = Element::createMap();
@@ -457,14 +459,14 @@
 }
 
 bool
-Session::group_recvmsg(ElementPtr& envelope, ElementPtr& msg,
+Session::group_recvmsg(ConstElementPtr& envelope, ConstElementPtr& msg,
                        bool nonblock, int seq)
 {
     return (recvmsg(envelope, msg, nonblock, seq));
 }
 
 int
-Session::reply(ElementPtr& envelope, ElementPtr& newmsg) {
+Session::reply(ConstElementPtr envelope, ConstElementPtr newmsg) {
     ElementPtr env = Element::createMap();
     long int nseq = ++impl_->sequence_;
     
@@ -482,7 +484,7 @@
 }
 
 bool
-Session::hasQueuedMsgs() {
+Session::hasQueuedMsgs() const {
     return (impl_->queue_->size() > 0);
 }
 

Modified: branches/trac311/src/lib/cc/session.h
==============================================================================
--- branches/trac311/src/lib/cc/session.h (original)
+++ branches/trac311/src/lib/cc/session.h Sun Sep 26 03:25:19 2010
@@ -81,12 +81,12 @@
             //@}
             virtual void establish(const char* socket_file) = 0;
             virtual void disconnect() = 0;
-            virtual int group_sendmsg(isc::data::ElementPtr msg,
+            virtual int group_sendmsg(isc::data::ConstElementPtr msg,
                                       std::string group,
                                       std::string instance = "*",
                                       std::string to = "*") = 0;
-            virtual bool group_recvmsg(isc::data::ElementPtr& envelope,
-                                       isc::data::ElementPtr& msg,
+            virtual bool group_recvmsg(isc::data::ConstElementPtr& envelope,
+                                       isc::data::ConstElementPtr& msg,
                                        bool nonblock = true,
                                        int seq = -1) = 0;
             virtual void subscribe(std::string group,
@@ -94,9 +94,9 @@
             virtual void unsubscribe(std::string group,
                              std::string instance = "*") = 0;
             virtual void startRead(boost::function<void()> read_callback) = 0;
-            virtual int reply(isc::data::ElementPtr& envelope,
-                               isc::data::ElementPtr& newmsg) = 0;
-            virtual bool hasQueuedMsgs() = 0;
+            virtual int reply(isc::data::ConstElementPtr envelope,
+                               isc::data::ConstElementPtr newmsg) = 0;
+            virtual bool hasQueuedMsgs() const = 0;
 
             /// \brief Sets the default timeout for blocking reads
             ///        in this session to the given number of milliseconds
@@ -130,28 +130,28 @@
                                    std::string instance = "*");
             virtual void unsubscribe(std::string group,
                              std::string instance = "*");
-            virtual int group_sendmsg(isc::data::ElementPtr msg,
+            virtual int group_sendmsg(isc::data::ConstElementPtr msg,
                                       std::string group,
                                       std::string instance = "*",
                                       std::string to = "*");
-            virtual bool group_recvmsg(isc::data::ElementPtr& envelope,
-                                       isc::data::ElementPtr& msg,
+            virtual bool group_recvmsg(isc::data::ConstElementPtr& envelope,
+                                       isc::data::ConstElementPtr& msg,
                                        bool nonblock = true,
                                        int seq = -1);
-            virtual int reply(isc::data::ElementPtr& envelope,
-                              isc::data::ElementPtr& newmsg);
-            virtual bool hasQueuedMsgs();
+            virtual int reply(isc::data::ConstElementPtr envelope,
+                              isc::data::ConstElementPtr newmsg);
+            virtual bool hasQueuedMsgs() const;
             virtual void setTimeout(size_t milliseconds);
             virtual size_t getTimeout() const;
     private:
-            void sendmsg(isc::data::ElementPtr& msg);
-            void sendmsg(isc::data::ElementPtr& env,
-                         isc::data::ElementPtr& msg);
-            bool recvmsg(isc::data::ElementPtr& msg,
+            void sendmsg(isc::data::ConstElementPtr msg);
+            void sendmsg(isc::data::ConstElementPtr env,
+                         isc::data::ConstElementPtr msg);
+            bool recvmsg(isc::data::ConstElementPtr& msg,
                          bool nonblock = true,
                          int seq = -1);
-            bool recvmsg(isc::data::ElementPtr& env,
-                         isc::data::ElementPtr& msg,
+            bool recvmsg(isc::data::ConstElementPtr& env,
+                         isc::data::ConstElementPtr& msg,
                          bool nonblock = true,
                          int seq = -1);
         };

Modified: branches/trac311/src/lib/cc/tests/data_unittests.cc
==============================================================================
--- branches/trac311/src/lib/cc/tests/data_unittests.cc (original)
+++ branches/trac311/src/lib/cc/tests/data_unittests.cc Sun Sep 26 03:25:19 2010
@@ -29,6 +29,7 @@
 using std::setw;
 using std::string;
 
+namespace {
 TEST(Element, type) {
     // this tests checks whether the getType() function returns the
     // correct type
@@ -73,7 +74,7 @@
     // a set of inputs that are the same when converted to json and
     // back to a string (tests for inputs that have equivalent, but
     // different string representations when converted back are below)
-    ElementPtr el;
+    ConstElementPtr el;
     std::vector<std::string> sv;
 
     sv.push_back("12");
@@ -92,25 +93,25 @@
     sv.push_back("-1.234");
     sv.push_back("-123.456");
     
-    BOOST_FOREACH(std::string s, sv) {
+    BOOST_FOREACH(const std::string& s, sv) {
         // test << operator, which uses Element::str()
         std::ostringstream stream;
         el = Element::fromJSON(s);
-        stream << el;
-        EXPECT_EQ(stream.str(), s);
+        stream << *el;
+        EXPECT_EQ(s, stream.str());
 
         // test toWire(ostream), which should also be the same now
         std::ostringstream wire_stream;
         el->toWire(wire_stream);
-        EXPECT_EQ(wire_stream.str(), s);
+        EXPECT_EQ(s, wire_stream.str());
     }
 
     // some parse errors
     try {
         Element::fromJSON("{1}");
-    } catch (isc::data::JSONError pe) {
+    } catch (const isc::data::JSONError& pe) {
         std::string s = std::string(pe.what());
-        EXPECT_EQ(s, "String expected in <string>:1:3");
+        EXPECT_EQ("String expected in <string>:1:3", s);
     }
     
     sv.clear();
@@ -169,9 +170,8 @@
     double d;
     bool b;
     std::string s("asdf");
-    std::vector<ElementPtr> v;
-    std::map<std::string, ElementPtr> m;
-    
+    std::vector<ConstElementPtr> v;
+    std::map<std::string, ConstElementPtr> m;
 
     el = Element::create(1);
     EXPECT_NO_THROW(el->intValue());
@@ -204,7 +204,7 @@
     EXPECT_THROW(el->set("foo", el), TypeError);
     EXPECT_THROW(el->remove("foo"), TypeError);
     EXPECT_THROW(el->contains("foo"), TypeError);
-    ElementPtr tmp;
+    ConstElementPtr tmp;
     EXPECT_FALSE(el->find("foo", tmp));
     
 
@@ -322,13 +322,19 @@
     EXPECT_ANY_THROW(el->get(3));
 
     el->add(Element::create(32));
-    EXPECT_EQ(el->get(2)->intValue(), 32);
+    EXPECT_EQ(32, el->get(2)->intValue());
+
+    // boundary condition tests for set()
+    el->set(2, Element::create(0)); // update the last entry of the list
+    EXPECT_EQ(0, el->get(2)->intValue());
+    // attempt of set beyond the range of list should trigger an exception.
+    EXPECT_ANY_THROW(el->set(3, Element::create(0)));
 }
 
 TEST(Element, MapElement) {
     // this function checks the specific functions for ListElements
     ElementPtr el = Element::fromJSON("{ \"name\": \"foo\", \"value1\": \"bar\", \"value2\": { \"number\": 42 } }");
-    ElementPtr el2;
+    ConstElementPtr el2;
     
     EXPECT_EQ(el->get("name")->stringValue(), "foo");
     EXPECT_EQ(el->get("value2")->getType(), Element::map);
@@ -376,7 +382,6 @@
 
 TEST(Element, to_and_from_wire) {
     // Wire format is now plain JSON.
-    ElementPtr el;
     EXPECT_EQ("1", Element::create(1)->toWire());
     EXPECT_EQ("1.1", Element::create(1.1)->toWire());
     EXPECT_EQ("true", Element::create(true)->toWire());
@@ -398,124 +403,167 @@
     EXPECT_THROW(Element::fromJSON("[ 1, 2, }"), isc::data::JSONError);
 }
 
-static ElementPtr
+ConstElementPtr
 efs(const std::string& str) {
     return (Element::fromJSON(str));
 }
 
 TEST(Element, equals) {
-    // why does EXPECT_EQ not work?
-    EXPECT_EQ(efs("1"), efs("1"));
-    EXPECT_NE(efs("1"), efs("2"));
-    EXPECT_NE(efs("1"), efs("\"1\""));
-    EXPECT_NE(efs("1"), efs("[]"));
-    EXPECT_NE(efs("1"), efs("True"));
-    EXPECT_NE(efs("1"), efs("{}"));
-
-    EXPECT_EQ(efs("1.1"), efs("1.1"));
-    EXPECT_NE(efs("1.0"), efs("1"));
-    EXPECT_NE(efs("1.1"), efs("\"1\""));
-    EXPECT_NE(efs("1.1"), efs("[]"));
-    EXPECT_NE(efs("1.1"), efs("True"));
-    EXPECT_NE(efs("1.1"), efs("{}"));
-
-    EXPECT_EQ(efs("True"), efs("True"));
-    EXPECT_NE(efs("True"), efs("False"));
-    EXPECT_NE(efs("True"), efs("1"));
-    EXPECT_NE(efs("True"), efs("\"1\""));
-    EXPECT_NE(efs("True"), efs("[]"));
-    EXPECT_NE(efs("True"), efs("{}"));
-
-    EXPECT_EQ(efs("\"foo\""), efs("\"foo\""));
-    EXPECT_NE(efs("\"foo\""), efs("\"bar\""));
-    EXPECT_NE(efs("\"foo\""), efs("1"));
-    EXPECT_NE(efs("\"foo\""), efs("\"1\""));
-    EXPECT_NE(efs("\"foo\""), efs("True"));
-    EXPECT_NE(efs("\"foo\""), efs("[]"));
-    EXPECT_NE(efs("\"foo\""), efs("{}"));
-
-    EXPECT_EQ(efs("[]"), efs("[]"));
-    EXPECT_EQ(efs("[ 1, 2, 3 ]"), efs("[ 1, 2, 3 ]"));
-    EXPECT_EQ(efs("[ \"a\", [ True, 1], 2.2 ]"), efs("[ \"a\", [ True, 1], 2.2 ]"));
-    EXPECT_NE(efs("[ \"a\", [ True, 1], 2.2 ]"), efs("[ \"a\", [ True, 2], 2.2 ]"));
-    EXPECT_NE(efs("[]"), efs("[1]"));
-    EXPECT_NE(efs("[]"), efs("1"));
-    EXPECT_NE(efs("[]"), efs("\"1\""));
-    EXPECT_NE(efs("[]"), efs("{}"));
-
-    EXPECT_EQ(efs("{}"), efs("{}"));
-    EXPECT_EQ(efs("{ \"foo\": \"bar\" }"), efs("{ \"foo\": \"bar\" }"));
-    EXPECT_EQ(efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"), efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"));
-    EXPECT_NE(efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"), efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar2\" } }"));
-    EXPECT_NE(efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"), efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\", 1 ], \"item3\": { \"foo\": \"bar\" } }"));
-    EXPECT_NE(efs("{ \"foo\": \"bar\" }"), efs("1"));
-    EXPECT_NE(efs("{ \"foo\": \"bar\" }"), efs("\"1\""));
-    EXPECT_NE(efs("{ \"foo\": \"bar\" }"), efs("[]"));
-    EXPECT_NE(efs("{ \"foo\": \"bar\" }"), efs("{}"));
-    EXPECT_NE(efs("{ \"foo\": \"bar\" }"), efs("{ \"something\": \"different\" }"));
-
-    EXPECT_EQ(efs("null"), Element::create());
+    EXPECT_EQ(*efs("1"), *efs("1"));
+    EXPECT_NE(*efs("1"), *efs("2"));
+    EXPECT_NE(*efs("1"), *efs("\"1\""));
+    EXPECT_NE(*efs("1"), *efs("[]"));
+    EXPECT_NE(*efs("1"), *efs("True"));
+    EXPECT_NE(*efs("1"), *efs("{}"));
+
+    EXPECT_EQ(*efs("1.1"), *efs("1.1"));
+    EXPECT_NE(*efs("1.0"), *efs("1"));
+    EXPECT_NE(*efs("1.1"), *efs("\"1\""));
+    EXPECT_NE(*efs("1.1"), *efs("[]"));
+    EXPECT_NE(*efs("1.1"), *efs("True"));
+    EXPECT_NE(*efs("1.1"), *efs("{}"));
+
+    EXPECT_EQ(*efs("True"), *efs("True"));
+    EXPECT_NE(*efs("True"), *efs("False"));
+    EXPECT_NE(*efs("True"), *efs("1"));
+    EXPECT_NE(*efs("True"), *efs("\"1\""));
+    EXPECT_NE(*efs("True"), *efs("[]"));
+    EXPECT_NE(*efs("True"), *efs("{}"));
+
+    EXPECT_EQ(*efs("\"foo\""), *efs("\"foo\""));
+    EXPECT_NE(*efs("\"foo\""), *efs("\"bar\""));
+    EXPECT_NE(*efs("\"foo\""), *efs("1"));
+    EXPECT_NE(*efs("\"foo\""), *efs("\"1\""));
+    EXPECT_NE(*efs("\"foo\""), *efs("True"));
+    EXPECT_NE(*efs("\"foo\""), *efs("[]"));
+    EXPECT_NE(*efs("\"foo\""), *efs("{}"));
+
+    EXPECT_EQ(*efs("[]"), *efs("[]"));
+    EXPECT_EQ(*efs("[ 1, 2, 3 ]"), *efs("[ 1, 2, 3 ]"));
+    EXPECT_EQ(*efs("[ \"a\", [ True, 1], 2.2 ]"), *efs("[ \"a\", [ True, 1], 2.2 ]"));
+    EXPECT_NE(*efs("[ \"a\", [ True, 1], 2.2 ]"), *efs("[ \"a\", [ True, 2], 2.2 ]"));
+    EXPECT_NE(*efs("[]"), *efs("[1]"));
+    EXPECT_NE(*efs("[]"), *efs("1"));
+    EXPECT_NE(*efs("[]"), *efs("\"1\""));
+    EXPECT_NE(*efs("[]"), *efs("{}"));
+
+    EXPECT_EQ(*efs("{}"), *efs("{}"));
+    EXPECT_EQ(*efs("{ \"foo\": \"bar\" }"), *efs("{ \"foo\": \"bar\" }"));
+    EXPECT_EQ(*efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"), *efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"));
+    EXPECT_NE(*efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"), *efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar2\" } }"));
+    EXPECT_NE(*efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"), *efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\", 1 ], \"item3\": { \"foo\": \"bar\" } }"));
+    EXPECT_NE(*efs("{ \"foo\": \"bar\" }"), *efs("1"));
+    EXPECT_NE(*efs("{ \"foo\": \"bar\" }"), *efs("\"1\""));
+    EXPECT_NE(*efs("{ \"foo\": \"bar\" }"), *efs("[]"));
+    EXPECT_NE(*efs("{ \"foo\": \"bar\" }"), *efs("{}"));
+    EXPECT_NE(*efs("{ \"foo\": \"bar\" }"), *efs("{ \"something\": \"different\" }"));
+
+    EXPECT_EQ(*efs("null"), *Element::create());
 }
 
 TEST(Element, removeIdentical) {
     ElementPtr a = Element::createMap();
-    ElementPtr b = Element::createMap();
-    ElementPtr c = Element::createMap();
-    removeIdentical(a, b);
-    EXPECT_EQ(a, c);
+    ConstElementPtr b = Element::createMap();
+    ConstElementPtr c = Element::createMap();
+    removeIdentical(a, b);
+    EXPECT_EQ(*a, *c);
 
     a = Element::fromJSON("{ \"a\": 1 }");
     b = Element::fromJSON("{ \"a\": 1 }");
     c = Element::createMap();
     removeIdentical(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
     a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
     b = Element::createMap();
     c = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
     removeIdentical(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
     a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
     b = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
     c = Element::createMap();
     removeIdentical(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
     a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
     b = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 3 ] }");
     c = Element::fromJSON("{ \"b\": [ 1, 2 ] }");
     removeIdentical(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
     a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     b = Element::createMap();
     c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     removeIdentical(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
     a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     b = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     c = Element::createMap();
     removeIdentical(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
     a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
     c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     removeIdentical(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
     EXPECT_THROW(removeIdentical(Element::create(1), Element::create(2)), TypeError);
 }
 
-TEST(Element, merge)
-{
+TEST(Element, constRemoveIdentical) {
+    ConstElementPtr a = Element::createMap();
+    ConstElementPtr b = Element::createMap();
+    ConstElementPtr c = Element::createMap();
+    EXPECT_EQ(*removeIdentical(a, b), *c);
+
+    a = Element::fromJSON("{ \"a\": 1 }");
+    b = Element::fromJSON("{ \"a\": 1 }");
+    c = Element::createMap();
+    EXPECT_EQ(*removeIdentical(a, b), *c);
+
+    a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
+    b = Element::createMap();
+    c = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
+    EXPECT_EQ(*removeIdentical(a, b), *c);
+
+    a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
+    b = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
+    c = Element::createMap();
+    EXPECT_EQ(*removeIdentical(a, b), *c);
+
+    a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
+    b = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 3 ] }");
+    c = Element::fromJSON("{ \"b\": [ 1, 2 ] }");
+    EXPECT_EQ(*removeIdentical(a, b), *c);
+
+    a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+    b = Element::createMap();
+    c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+    EXPECT_EQ(*removeIdentical(a, b), *c);
+
+    a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+    b = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+    c = Element::createMap();
+    EXPECT_EQ(*removeIdentical(a, b), *c);
+
+    a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+    b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
+    c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+    EXPECT_EQ(*removeIdentical(a, b), *c);
+
+    EXPECT_THROW(removeIdentical(Element::create(1), Element::create(2)),
+                 TypeError);
+}
+
+TEST(Element, merge) {
     ElementPtr a = Element::createMap();
     ElementPtr b = Element::createMap();
-    ElementPtr c = Element::createMap();
+    ConstElementPtr c = Element::createMap();
     merge(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
     a = Element::fromJSON("1");
     b = Element::createMap();
@@ -525,73 +573,74 @@
     b = Element::fromJSON("{ \"a\": 1 }");
     c = Element::fromJSON("{ \"a\": 1 }");
     merge(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
     a = Element::createMap();
     b = Element::fromJSON("{ \"a\": 1 }");
     c = Element::fromJSON("{ \"a\": 1 }");
     merge(b, a);
-    EXPECT_EQ(b, c);
+    EXPECT_EQ(*b, *c);
 
     a = Element::fromJSON("{ \"a\": 1 }");
     b = Element::fromJSON("{ \"a\": 2 }");
     c = Element::fromJSON("{ \"a\": 2 }");
     merge(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
     a = Element::fromJSON("{ \"a\": 1 }");
     b = Element::fromJSON("{ \"a\": 2 }");
     c = Element::fromJSON("{ \"a\": 1 }");
     merge(b, a);
-    EXPECT_EQ(b, c);
+    EXPECT_EQ(*b, *c);
 
     a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
     c = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
     merge(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
     a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
     c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     merge(b, a);
-    EXPECT_EQ(b, c);
+    EXPECT_EQ(*b, *c);
 
     a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     b = Element::fromJSON("{ \"a\": null }");
     c = Element::fromJSON("{  }");
     merge(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
     a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     b = Element::fromJSON("{ \"a\": null }");
     c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     merge(b, a);
-    EXPECT_EQ(b, c);
+    EXPECT_EQ(*b, *c);
     
     // And some tests with multiple values
     a = Element::fromJSON("{ \"a\": 1, \"b\": true, \"c\": null }");
     b = Element::fromJSON("{ \"a\": 1, \"b\": null, \"c\": \"a string\" }");
     c = Element::fromJSON("{ \"a\": 1, \"c\": \"a string\" }");
     merge(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
     a = Element::fromJSON("{ \"a\": 1, \"b\": true, \"c\": null }");
     b = Element::fromJSON("{ \"a\": 1, \"b\": null, \"c\": \"a string\" }");
     c = Element::fromJSON("{ \"a\": 1, \"b\": true }");
     merge(b, a);
-    EXPECT_EQ(b, c);
+    EXPECT_EQ(*b, *c);
 
     a = Element::fromJSON("{ \"a\": 1, \"b\": 2, \"c\": 3 }");
     b = Element::fromJSON("{ \"a\": 3, \"b\": 2, \"c\": 1 }");
     c = Element::fromJSON("{ \"a\": 3, \"b\": 2, \"c\": 1 }");
     merge(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
     a = Element::fromJSON("{ \"a\": 1, \"b\": 2, \"c\": 3 }");
     b = Element::fromJSON("{ \"a\": 3, \"b\": 2, \"c\": 1 }");
     c = Element::fromJSON("{ \"a\": 1, \"b\": 2, \"c\": 3 }");
     merge(b, a);
-    EXPECT_EQ(b, c);
-
-}
+    EXPECT_EQ(*b, *c);
+
+}
+}

Modified: branches/trac311/src/lib/cc/tests/session_unittests.cc
==============================================================================
--- branches/trac311/src/lib/cc/tests/session_unittests.cc (original)
+++ branches/trac311/src/lib/cc/tests/session_unittests.cc Sun Sep 26 03:25:19 2010
@@ -140,7 +140,7 @@
     // If this message is { "command": "stop" } it'll tell the
     // io_service it is done. Otherwise it'll re-register this handler
     void someHandler() {
-        isc::data::ElementPtr env, msg;
+        isc::data::ConstElementPtr env, msg;
         sess.group_recvmsg(env, msg, false, -1);
 
         sess.group_recvmsg(env, msg, false, -1);
@@ -188,7 +188,7 @@
     // Close the session again, so the next recv() should throw
     sess.disconnect();
 
-    isc::data::ElementPtr env, msg;
+    isc::data::ConstElementPtr env, msg;
     EXPECT_THROW(sess.group_recvmsg(env, msg, false, -1), SessionError);
 }
 

Modified: branches/trac311/src/lib/config/ccsession.cc
==============================================================================
--- branches/trac311/src/lib/config/ccsession.cc (original)
+++ branches/trac311/src/lib/config/ccsession.cc Sun Sep 26 03:25:19 2010
@@ -52,41 +52,47 @@
 namespace config {
 
 /// Creates a standard config/command protocol answer message
-ElementPtr
+ConstElementPtr
 createAnswer() {
     ElementPtr answer = Element::fromJSON("{\"result\": [] }");
-    ElementPtr answer_content = answer->get("result");
+    ElementPtr answer_content = Element::createList();
     answer_content->add(Element::create(0));
+    answer->set("result", answer_content);
+
     return (answer);
 }
 
-ElementPtr
-createAnswer(const int rcode, const ElementPtr arg) {
+ConstElementPtr
+createAnswer(const int rcode, ConstElementPtr arg) {
     if (rcode != 0 && (!arg || arg->getType() != Element::string)) {
         isc_throw(CCSessionError, "Bad or no argument for rcode != 0");
     }
     ElementPtr answer = Element::fromJSON("{\"result\": [] }");
-    ElementPtr answer_content = answer->get("result");
+    ElementPtr answer_content = Element::createList();
     answer_content->add(Element::create(rcode));
     answer_content->add(arg);
+    answer->set("result", answer_content);
+
     return (answer);
 }
 
-ElementPtr
+ConstElementPtr
 createAnswer(const int rcode, const std::string& arg) {
     ElementPtr answer = Element::fromJSON("{\"result\": [] }");
-    ElementPtr answer_content = answer->get("result");
+    ElementPtr answer_content = Element::createList();
     answer_content->add(Element::create(rcode));
     answer_content->add(Element::create(arg));
+    answer->set("result", answer_content);
+
     return (answer);
 }
 
-ElementPtr
-parseAnswer(int &rcode, const ElementPtr msg) {
+ConstElementPtr
+parseAnswer(int &rcode, ConstElementPtr msg) {
     if (msg &&
         msg->getType() == Element::map &&
         msg->contains("result")) {
-        ElementPtr result = msg->get("result");
+        ConstElementPtr result = msg->get("result");
         if (result->getType() != Element::list) {
             isc_throw(CCSessionError, "Result element in answer message is not a list");
         } else if (result->get(0)->getType() != Element::integer) {
@@ -111,13 +117,13 @@
     }
 }
 
-ElementPtr
+ConstElementPtr
 createCommand(const std::string& command) {
     return (createCommand(command, ElementPtr()));
 }
 
-ElementPtr
-createCommand(const std::string& command, ElementPtr arg) {
+ConstElementPtr
+createCommand(const std::string& command, ConstElementPtr arg) {
     ElementPtr cmd = Element::createMap();
     ElementPtr cmd_parts = Element::createList();
     cmd_parts->add(Element::create(command));
@@ -130,13 +136,12 @@
 
 /// Returns "" and empty ElementPtr() if this does not
 /// look like a command
-const std::string
-parseCommand(ElementPtr& arg, const ElementPtr command)
-{
+std::string
+parseCommand(ConstElementPtr& arg, ConstElementPtr command) {
     if (command &&
         command->getType() == Element::map &&
         command->contains("command")) {
-        ElementPtr cmd = command->get("command");
+        ConstElementPtr cmd = command->get("command");
         if (cmd->getType() == Element::list &&
             cmd->size() > 0 &&
             cmd->get(0)->getType() == Element::string) {
@@ -192,9 +197,10 @@
 ModuleCCSession::ModuleCCSession(
     const std::string& spec_file_name,
     isc::cc::AbstractSession& session,
-    isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config),
-    isc::data::ElementPtr(*command_handler)(
-        const std::string& command, const isc::data::ElementPtr args)
+    isc::data::ConstElementPtr(*config_handler)(
+        isc::data::ConstElementPtr new_config),
+    isc::data::ConstElementPtr(*command_handler)(
+        const std::string& command, isc::data::ConstElementPtr args)
     ) :
     session_(session)
 {
@@ -205,18 +211,20 @@
     config_handler_ = config_handler;
     command_handler_ = command_handler;
 
-    ElementPtr answer, env;
-
     session_.establish(NULL);
     session_.subscribe(module_name_, "*");
     //session_.subscribe("Boss", "*");
     //session_.subscribe("statistics", "*");
     // send the data specification
-    ElementPtr spec_msg = createCommand("module_spec", module_specification_.getFullSpec());
+
+    ConstElementPtr spec_msg = createCommand("module_spec",
+                                             module_specification_.getFullSpec());
     unsigned int seq = session_.group_sendmsg(spec_msg, "ConfigManager");
+
+    ConstElementPtr answer, env;
     session_.group_recvmsg(env, answer, false, seq);
     int rcode;
-    ElementPtr err = parseAnswer(rcode, answer);
+    ConstElementPtr err = parseAnswer(rcode, answer);
     if (rcode != 0) {
         std::cerr << "[" << module_name_ << "] Error in specification: " << answer << std::endl;
     }
@@ -224,10 +232,10 @@
     setLocalConfig(Element::fromJSON("{}"));
     // get any stored configuration from the manager
     if (config_handler_) {
-        ElementPtr cmd = Element::fromJSON("{ \"command\": [\"get_config\", {\"module_name\":\"" + module_name_ + "\"} ] }");
+        ConstElementPtr cmd = Element::fromJSON("{ \"command\": [\"get_config\", {\"module_name\":\"" + module_name_ + "\"} ] }");
         seq = session_.group_sendmsg(cmd, "ConfigManager");
         session_.group_recvmsg(env, answer, false, seq);
-        ElementPtr new_config = parseAnswer(rcode, answer);
+        ConstElementPtr new_config = parseAnswer(rcode, answer);
         if (rcode == 0) {
             handleConfigUpdate(new_config);
         } else {
@@ -242,30 +250,30 @@
 /// Validates the new config values, if they are correct,
 /// call the config handler with the values that have changed
 /// If that results in success, store the new config
-ElementPtr
-ModuleCCSession::handleConfigUpdate(ElementPtr new_config)
-{
-    ElementPtr answer;
+ConstElementPtr
+ModuleCCSession::handleConfigUpdate(ConstElementPtr new_config) {
+    ConstElementPtr answer;
     ElementPtr errors = Element::createList();
     if (!config_handler_) {
         answer = createAnswer(1, module_name_ + " does not have a config handler");
-    } else if (!module_specification_.validate_config(new_config, false, errors)) {
+    } else if (!module_specification_.validate_config(new_config, false,
+                                                      errors)) {
         std::stringstream ss;
         ss << "Error in config validation: ";
-        BOOST_FOREACH(ElementPtr error, errors->listValue()) {
+        BOOST_FOREACH(ConstElementPtr error, errors->listValue()) {
             ss << error->stringValue();
         }
         answer = createAnswer(2, ss.str());
     } else {
         // remove the values that have not changed
-        isc::data::removeIdentical(new_config, getLocalConfig());
+        ConstElementPtr diff = removeIdentical(new_config, getLocalConfig());
         // handle config update
-        answer = config_handler_(new_config);
+        answer = config_handler_(diff);
         int rcode;
         parseAnswer(rcode, answer);
         if (rcode == 0) {
             ElementPtr local_config = getLocalConfig();
-            isc::data::merge(local_config, new_config);
+            isc::data::merge(local_config, diff);
             setLocalConfig(local_config);
         }
     }
@@ -273,15 +281,13 @@
 }
 
 bool
-ModuleCCSession::hasQueuedMsgs()
-{
+ModuleCCSession::hasQueuedMsgs() const {
     return (session_.hasQueuedMsgs());
 }
 
 int
-ModuleCCSession::checkCommand()
-{
-    ElementPtr cmd, routing, data;
+ModuleCCSession::checkCommand() {
+    ConstElementPtr cmd, routing, data;
     if (session_.group_recvmsg(routing, data, true)) {
         
         /* ignore result messages (in case we're out of sync, to prevent
@@ -289,8 +295,8 @@
         if (data->getType() != Element::map || data->contains("result")) {
             return (0);
         }
-        ElementPtr arg;
-        ElementPtr answer;
+        ConstElementPtr arg;
+        ConstElementPtr answer;
         try {
             std::string cmd_str = parseCommand(arg, data);
             std::string target_module = routing->get("group")->stringValue();
@@ -313,7 +319,7 @@
                     }
                 }
             }
-        } catch (CCSessionError re) {
+        } catch (const CCSessionError& re) {
             // TODO: Once we have logging and timeouts, we should not
             // answer here (potential interference)
             answer = createAnswer(1, re.what());
@@ -335,15 +341,17 @@
     session_.subscribe(module_name);
 
     // Get the current configuration values for that module
-    ElementPtr cmd = Element::fromJSON("{ \"command\": [\"get_config\", {\"module_name\":\"" + module_name + "\"} ] }");
-    ElementPtr env, answer;
+    ConstElementPtr cmd = Element::fromJSON("{ \"command\": [\"get_config\", {\"module_name\":\"" + module_name + "\"} ] }");
+    unsigned int seq = session_.group_sendmsg(cmd, "ConfigManager");
+
+    ConstElementPtr env, answer;
+    session_.group_recvmsg(env, answer, false, seq);
     int rcode;
-    
-    unsigned int seq = session_.group_sendmsg(cmd, "ConfigManager");
-    session_.group_recvmsg(env, answer, false, seq);
-    ElementPtr new_config = parseAnswer(rcode, answer);
-    if (rcode == 0) {
-        rmod_config.setLocalConfig(new_config);
+    ConstElementPtr new_config = parseAnswer(rcode, answer);
+    if (rcode == 0 && new_config) {
+        ElementPtr local_config = rmod_config.getLocalConfig();
+        isc::data::merge(local_config, new_config);
+        rmod_config.setLocalConfig(local_config);
     } else {
         isc_throw(CCSessionError, "Error getting config for " + module_name + ": " + answer->str());
     }
@@ -365,21 +373,24 @@
     }
 }
 
-ElementPtr
-ModuleCCSession::getRemoteConfigValue(const std::string& module_name, const std::string& identifier)
+ConstElementPtr
+ModuleCCSession::getRemoteConfigValue(const std::string& module_name,
+                                      const std::string& identifier) const
 {
-    std::map<std::string, ConfigData>::iterator it;
-
-    it = remote_module_configs_.find(module_name);
+    std::map<std::string, ConfigData>::const_iterator it =
+        remote_module_configs_.find(module_name);
+
     if (it != remote_module_configs_.end()) {
-        return (remote_module_configs_[module_name].getValue(identifier));
+        return ((*it).second.getValue(identifier));
     } else {
-        isc_throw(CCSessionError, "Remote module " + module_name + " not found.");
+        isc_throw(CCSessionError,
+                  "Remote module " + module_name + " not found.");
     }
 }
 
 void
-ModuleCCSession::updateRemoteConfig(const std::string& module_name, ElementPtr new_config)
+ModuleCCSession::updateRemoteConfig(const std::string& module_name,
+                                    ConstElementPtr new_config)
 {
     std::map<std::string, ConfigData>::iterator it;
 

Modified: branches/trac311/src/lib/config/ccsession.h
==============================================================================
--- branches/trac311/src/lib/config/ccsession.h (original)
+++ branches/trac311/src/lib/config/ccsession.h Sun Sep 26 03:25:19 2010
@@ -31,7 +31,7 @@
 /// \brief Creates a standard config/command level success answer message
 ///        (i.e. of the form { "result": [ 0 ] }
 /// \return Standard command/config success answer message
-ElementPtr createAnswer();
+ConstElementPtr createAnswer();
 
 ///
 /// \brief Creates a standard config/command level answer message
@@ -43,7 +43,7 @@
 ///            Element type. For rcode == 1, this argument is mandatory,
 ///            and must be a StringElement containing an error description
 /// \return Standard command/config answer message
-ElementPtr createAnswer(const int rcode, const ElementPtr arg);
+ConstElementPtr createAnswer(const int rcode, ConstElementPtr arg);
 
 ///
 /// \brief Creates a standard config/command level answer message
@@ -52,7 +52,7 @@
 /// \param rcode The return code (0 for success)
 /// \param arg A string to put into the StringElement argument
 /// \return Standard command/config answer message
-ElementPtr createAnswer(const int rcode, const std::string& arg);
+ConstElementPtr createAnswer(const int rcode, const std::string& arg);
 
 ///
 /// Parses a standard config/command level answer message
@@ -63,8 +63,7 @@
 /// \return The optional argument in the message, or an empty ElementPtr
 ///         if there was no argument. If rcode != 0, this contains a
 ///         StringElement with the error description.
-ElementPtr parseAnswer(int &rcode, const ElementPtr msg);
-
+ConstElementPtr parseAnswer(int &rcode, ConstElementPtr msg);
 
 ///
 /// \brief Creates a standard config/command command message with no
@@ -72,7 +71,7 @@
 /// 
 /// \param command The command string
 /// \return The created message
-ElementPtr createCommand(const std::string& command);
+ConstElementPtr createCommand(const std::string& command);
 
 ///
 /// \brief Creates a standard config/command command message with the
@@ -82,7 +81,7 @@
 /// \param arg The optional argument for the command. This can be of 
 ///        any Element type, but it should conform to the .spec file.
 /// \return The created message
-ElementPtr createCommand(const std::string& command, ElementPtr arg);
+ConstElementPtr createCommand(const std::string& command, ConstElementPtr arg);
 
 ///
 /// \brief Parses the given command into a string containing the actual
@@ -93,7 +92,7 @@
 /// \param command The command message containing the command (as made
 ///        by createCommand()
 /// \return The command string
-const std::string parseCommand(ElementPtr& arg, const ElementPtr command);
+std::string parseCommand(ConstElementPtr& arg, ConstElementPtr command);
 
 
 ///
@@ -133,11 +132,11 @@
      */
     ModuleCCSession(const std::string& spec_file_name,
                     isc::cc::AbstractSession& session,
-                    isc::data::ElementPtr(*config_handler)(
-                        isc::data::ElementPtr new_config) = NULL,
-                    isc::data::ElementPtr(*command_handler)(
+                    isc::data::ConstElementPtr(*config_handler)(
+                        isc::data::ConstElementPtr new_config) = NULL,
+                    isc::data::ConstElementPtr(*command_handler)(
                         const std::string& command,
-                        const isc::data::ElementPtr args) = NULL
+                        isc::data::ConstElementPtr args) = NULL
                     );
 
     /**
@@ -148,7 +147,7 @@
      * 
      * @return true if there are unhandled queued messages
      */
-    bool hasQueuedMsgs();
+    bool hasQueuedMsgs() const;
 
     /**
      * Check if there is a command or config change on the command
@@ -167,7 +166,11 @@
      * 100000 zones, where the whole list is passed every time a single
      * thing changes)
      */
-    void setConfigHandler(isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config)) { config_handler_ = config_handler; };
+    void setConfigHandler(isc::data::ConstElementPtr(*config_handler)(
+                              isc::data::ConstElementPtr new_config))
+    {
+        config_handler_ = config_handler;
+    }
 
     /**
      * Set a command handler; the function that is passed takes an
@@ -179,7 +182,12 @@
      *
      * This protocol is very likely to change.
      */
-    void setCommandHandler(isc::data::ElementPtr(*command_handler)(const std::string& command, const isc::data::ElementPtr args)) { command_handler_ = command_handler; };
+    void setCommandHandler(isc::data::ConstElementPtr(*command_handler)(
+                               const std::string& command,
+                               isc::data::ConstElementPtr args))
+    {
+        command_handler_ = command_handler;
+    }
 
     /**
      * Gives access to the configuration values of a different module
@@ -217,7 +225,8 @@
      * \param identifier The identifier of the config value
      * \return The configuration setting at the given identifier
      */
-    ElementPtr getRemoteConfigValue(const std::string& module_name, const std::string& identifier);
+    ConstElementPtr getRemoteConfigValue(const std::string& module_name,
+                                         const std::string& identifier) const;
     
 private:
     ModuleSpec readModuleSpecification(const std::string& filename);
@@ -226,13 +235,17 @@
     std::string module_name_;
     isc::cc::AbstractSession& session_;
     ModuleSpec module_specification_;
-    ElementPtr handleConfigUpdate(ElementPtr new_config);
-
-    isc::data::ElementPtr(*config_handler_)(isc::data::ElementPtr new_config);
-    isc::data::ElementPtr(*command_handler_)(const std::string& command, const isc::data::ElementPtr args);
+    ConstElementPtr handleConfigUpdate(ConstElementPtr new_config);
+
+    isc::data::ConstElementPtr(*config_handler_)(
+        isc::data::ConstElementPtr new_config);
+    isc::data::ConstElementPtr(*command_handler_)(
+        const std::string& command,
+        isc::data::ConstElementPtr args);
 
     std::map<std::string, ConfigData> remote_module_configs_;
-    void updateRemoteConfig(const std::string& module_name, ElementPtr new_config);
+    void updateRemoteConfig(const std::string& module_name,
+                            ConstElementPtr new_config);
 };
 
 }

Modified: branches/trac311/src/lib/config/config_data.cc
==============================================================================
--- branches/trac311/src/lib/config/config_data.cc (original)
+++ branches/trac311/src/lib/config/config_data.cc Sun Sep 26 03:25:19 2010
@@ -36,15 +36,14 @@
 // If it is a map, we search through the list contained in its
 // 'map_item_spec' value. This code assumes the data has been
 // validated and conforms to the specification.
-static ElementPtr
-find_spec_part(ElementPtr spec, const std::string& identifier)
-{
+static ConstElementPtr
+find_spec_part(ConstElementPtr spec, const std::string& identifier) {
     //std::cout << "[XX] find_spec_part for " << identifier << std::endl;
     if (!spec) {
         isc_throw(DataNotFoundError, "Empty specification");
     }
     //std::cout << "in: " << std::endl << spec << std::endl;
-    ElementPtr spec_part = spec;
+    ConstElementPtr spec_part = spec;
     if (identifier == "") {
         isc_throw(DataNotFoundError, "Empty identifier");
     }
@@ -55,7 +54,7 @@
         //std::cout << "[XX] id part: " << part << std::endl;
         if (spec_part->getType() == Element::list) {
             bool found = false;
-            BOOST_FOREACH(ElementPtr list_el, spec_part->listValue()) {
+            BOOST_FOREACH(ConstElementPtr list_el, spec_part->listValue()) {
                 if (list_el->getType() == Element::map &&
                     list_el->contains("item_name") &&
                     list_el->get("item_name")->stringValue() == part) {
@@ -73,7 +72,7 @@
     if (id != "" && id != "/") {
         if (spec_part->getType() == Element::list) {
             bool found = false;
-            BOOST_FOREACH(ElementPtr list_el, spec_part->listValue()) {
+            BOOST_FOREACH(ConstElementPtr list_el, spec_part->listValue()) {
                 if (list_el->getType() == Element::map &&
                     list_el->contains("item_name") &&
                     list_el->get("item_name")->stringValue() == id) {
@@ -87,7 +86,8 @@
         } else if (spec_part->getType() == Element::map) {
             if (spec_part->contains("map_item_spec")) {
                 bool found = false;
-                BOOST_FOREACH(ElementPtr list_el, spec_part->get("map_item_spec")->listValue()) {
+                BOOST_FOREACH(ConstElementPtr list_el,
+                              spec_part->get("map_item_spec")->listValue()) {
                     if (list_el->getType() == Element::map &&
                         list_el->contains("item_name") &&
                         list_el->get("item_name")->stringValue() == id) {
@@ -113,10 +113,11 @@
 // Result must be a ListElement
 //
 static void
-spec_name_list(ElementPtr result, ElementPtr spec_part, std::string prefix, bool recurse = false)
+spec_name_list(ElementPtr result, ConstElementPtr spec_part,
+               const std::string& prefix, bool recurse = false)
 {
     if (spec_part->getType() == Element::list) {
-        BOOST_FOREACH(ElementPtr list_el, spec_part->listValue()) {
+        BOOST_FOREACH(ConstElementPtr list_el, spec_part->listValue()) {
             if (list_el->getType() == Element::map &&
                 list_el->contains("item_name")) {
                 std::string new_prefix = prefix;
@@ -136,26 +137,29 @@
                 }
             }
         }
-    } else if (spec_part->getType() == Element::map && spec_part->contains("map_item_spec")) {
-        spec_name_list(result, spec_part->get("map_item_spec"), prefix, recurse);
-    }
-}
-
-ElementPtr
-ConfigData::getValue(const std::string& identifier) {
+    } else if (spec_part->getType() == Element::map &&
+               spec_part->contains("map_item_spec")) {
+        spec_name_list(result, spec_part->get("map_item_spec"), prefix,
+                       recurse);
+    }
+}
+
+ConstElementPtr
+ConfigData::getValue(const std::string& identifier) const {
     // 'fake' is set, but dropped by this function and
     // serves no further purpose.
     bool fake;
     return (getValue(fake, identifier));
 }
 
-ElementPtr
-ConfigData::getValue(bool& is_default, const std::string& identifier) {
-    ElementPtr value = _config->find(identifier);
+ConstElementPtr
+ConfigData::getValue(bool& is_default, const std::string& identifier) const {
+    ConstElementPtr value = _config->find(identifier);
     if (value) {
         is_default = false;
     } else {
-        ElementPtr spec_part = find_spec_part(_module_spec.getConfigSpec(), identifier);
+        ConstElementPtr spec_part =
+            find_spec_part(_module_spec.getConfigSpec(), identifier);
         if (spec_part->contains("item_default")) {
             value = spec_part->get("item_default");
             is_default = true;
@@ -170,11 +174,10 @@
 /// Returns an ElementPtr pointing to a ListElement containing
 /// StringElements with the names of the options at the given
 /// identifier. If recurse is true, maps will be expanded as well
-ElementPtr
-ConfigData::getItemList(const std::string& identifier, bool recurse)
-{
+ConstElementPtr
+ConfigData::getItemList(const std::string& identifier, bool recurse) const {
     ElementPtr result = Element::createList();
-    ElementPtr spec_part = getModuleSpec().getConfigSpec();
+    ConstElementPtr spec_part = getModuleSpec().getConfigSpec();
     if (identifier != "" && identifier != "/") {
         spec_part = find_spec_part(spec_part, identifier);
     }
@@ -184,12 +187,11 @@
 
 /// Returns an ElementPtr containing a MapElement with identifier->value
 /// pairs.
-ElementPtr
-ConfigData::getFullConfig()
-{
+ConstElementPtr
+ConfigData::getFullConfig() const {
     ElementPtr result = Element::createMap();
-    ElementPtr items = getItemList("", true);
-    BOOST_FOREACH(ElementPtr item, items->listValue()) {
+    ConstElementPtr items = getItemList("", true);
+    BOOST_FOREACH(ConstElementPtr item, items->listValue()) {
         result->set(item->stringValue(), getValue(item->stringValue()));
     }
     return (result);

Modified: branches/trac311/src/lib/config/config_data.h
==============================================================================
--- branches/trac311/src/lib/config/config_data.h (original)
+++ branches/trac311/src/lib/config/config_data.h Sun Sep 26 03:25:19 2010
@@ -55,7 +55,7 @@
     /// Raises a DataNotFoundError if the identifier is bad.
     /// \param identifier The identifier pointing to the configuration
     ///        value that is to be returned
-    ElementPtr getValue(const std::string& identifier);
+    ConstElementPtr getValue(const std::string& identifier) const;
 
     /// Returns the value currently set for the given identifier
     /// If no value is set, the default value (as specified by the
@@ -67,10 +67,11 @@
     ///                   false otherwise
     /// \param identifier The identifier pointing to the configuration
     ///        value that is to be returned
-    ElementPtr getValue(bool &is_default, const std::string& identifier);
+    ConstElementPtr getValue(bool& is_default,
+                             const std::string& identifier) const;
 
     /// Returns the ModuleSpec associated with this ConfigData object
-    const ModuleSpec getModuleSpec() { return (_module_spec); }
+    const ModuleSpec& getModuleSpec() const { return (_module_spec); }
 
     /// Set the ModuleSpec associated with this ConfigData object
     void setModuleSpec(ModuleSpec module_spec) { _module_spec = module_spec; };
@@ -96,14 +97,15 @@
     ///         StringElements that specify the identifiers at the given
     ///         location (or all possible identifiers if identifier==""
     ///         and recurse==false)
-    ElementPtr getItemList(const std::string& identifier = "", bool recurse = false);
+    ConstElementPtr getItemList(const std::string& identifier = "",
+                                bool recurse = false) const;
 
     /// Returns all current configuration settings (both non-default and default).
     /// \return An ElementPtr pointing to a MapElement containing
     ///         string->value elements, where the string is the
     ///         full identifier of the configuration option and the
     ///         value is an ElementPtr with the value.
-    ElementPtr getFullConfig();
+    ConstElementPtr getFullConfig() const;
 
 private:
     ElementPtr _config;
@@ -113,3 +115,7 @@
 }
 }
 #endif
+
+// Local Variables: 
+// mode: c++
+// End: 

Modified: branches/trac311/src/lib/config/documentation.txt
==============================================================================
--- branches/trac311/src/lib/config/documentation.txt (original)
+++ branches/trac311/src/lib/config/documentation.txt Sun Sep 26 03:25:19 2010
@@ -53,7 +53,7 @@
 
 The new_config is a ElementPtr pointing to a MapElement containing data in the form as specified by the specification file. It only contains values that were changed.
 
-The module can walk through this set and alter it's behaviour accordingly if necessary. It can also simply check them and return success (see below) and reference the needed configuration values directly when necessary by calling get_config_value(std::string identifier).
+The module can walk through this set and alter its behaviour accordingly if necessary. It can also simply check them and return success (see below) and reference the needed configuration values directly when necessary by calling get_config_value(std::string identifier).
 
 The callback function must return an answer message, which is created with isc::config::createAnswer(). For successful handling of the configuration, it should return the result of createAnswer(0) (0 being the result code for success). If there is a problem, the function can return the result of createAnswer(non-zero, "string_with_error_message"). In this case, the new configuration is not stored, and the error is fed back to the configuration manager.
 

Modified: branches/trac311/src/lib/config/module_spec.cc
==============================================================================
--- branches/trac311/src/lib/config/module_spec.cc (original)
+++ branches/trac311/src/lib/config/module_spec.cc Sun Sep 26 03:25:19 2010
@@ -24,15 +24,16 @@
 
 // todo: add more context to thrown ModuleSpecErrors?
 
-namespace isc {
-namespace config {
-
-//
-// static functions
-//
-
-static void
-check_leaf_item(const ElementPtr& spec, const std::string& name, Element::types type, bool mandatory)
+using namespace isc::config;
+
+namespace {
+//
+// Private functions
+//
+
+void
+check_leaf_item(ConstElementPtr spec, const std::string& name,
+                Element::types type, bool mandatory)
 {
     if (spec->contains(name)) {
         if (spec->get(name)->getType() == type) {
@@ -48,10 +49,10 @@
     }
 }
 
-static void check_config_item_list(const ElementPtr& spec);
-
-static void
-check_config_item(const ElementPtr& spec) {
+void check_config_item_list(ConstElementPtr spec);
+
+void
+check_config_item(ConstElementPtr spec) {
     check_leaf_item(spec, "item_name", Element::string, true);
     check_leaf_item(spec, "item_type", Element::string, true);
     check_leaf_item(spec, "item_optional", Element::boolean, true);
@@ -72,35 +73,35 @@
     }
 }
 
-static void
-check_config_item_list(const ElementPtr& spec) {
+void
+check_config_item_list(ConstElementPtr spec) {
     if (spec->getType() != Element::list) {
         throw ModuleSpecError("config_data is not a list of elements");
     }
-    BOOST_FOREACH(ElementPtr item, spec->listValue()) {
+    BOOST_FOREACH(ConstElementPtr item, spec->listValue()) {
         check_config_item(item);
     }
 }
 
-static void
-check_command(const ElementPtr& spec) {
+void
+check_command(ConstElementPtr spec) {
     check_leaf_item(spec, "command_name", Element::string, true);
     check_leaf_item(spec, "command_args", Element::list, true);
     check_config_item_list(spec->get("command_args"));
 }
 
-static void
-check_command_list(const ElementPtr& spec) {
+void
+check_command_list(ConstElementPtr spec) {
     if (spec->getType() != Element::list) {
         throw ModuleSpecError("commands is not a list of elements");
     }
-    BOOST_FOREACH(ElementPtr item, spec->listValue()) {
+    BOOST_FOREACH(ConstElementPtr item, spec->listValue()) {
         check_command(item);
     }
 }
 
-static void
-check_data_specification(const ElementPtr& spec) {
+void
+check_data_specification(ConstElementPtr spec) {
     check_leaf_item(spec, "module_name", Element::string, true);
     check_leaf_item(spec, "module_description", Element::string, false);
     // config_data is not mandatory; module could just define
@@ -115,21 +116,23 @@
 
 // checks whether the given element is a valid module specification
 // throws a ModuleSpecError if the specification is bad
-static void
-check_module_specification(const ElementPtr& def)
-{
+void
+check_module_specification(ConstElementPtr def) {
     try {
         check_data_specification(def);
     } catch (TypeError te) {
         throw ModuleSpecError(te.what());
     }
 }
-
+}
+
+namespace isc {
+namespace config {
 //
 // Public functions
 //
 
-ModuleSpec::ModuleSpec(ElementPtr module_spec_element,
+ModuleSpec::ModuleSpec(ConstElementPtr module_spec_element,
                        const bool check)
                        throw(ModuleSpecError)
                        
@@ -140,7 +143,7 @@
     }
 }
 
-const ElementPtr
+ConstElementPtr
 ModuleSpec::getCommandsSpec() const {
     if (module_specification->contains("commands")) {
         return (module_specification->get("commands"));
@@ -149,7 +152,7 @@
     }
 }
 
-const ElementPtr
+ConstElementPtr
 ModuleSpec::getConfigSpec() const {
     if (module_specification->contains("config_data")) {
         return (module_specification->get("config_data"));
@@ -173,16 +176,16 @@
 }
 
 bool
-ModuleSpec::validate_config(const ElementPtr data, const bool full) {
-    ElementPtr spec = module_specification->find("config_data");
+ModuleSpec::validate_config(ConstElementPtr data, const bool full) const {
+    ConstElementPtr spec = module_specification->find("config_data");
     return (validate_spec_list(spec, data, full, ElementPtr()));
 }
 
 bool
-ModuleSpec::validate_config(const ElementPtr data, const bool full,
-                            ElementPtr errors)
-{
-    ElementPtr spec = module_specification->find("config_data");
+ModuleSpec::validate_config(ConstElementPtr data, const bool full,
+                            ElementPtr errors) const
+{
+    ConstElementPtr spec = module_specification->find("config_data");
     return (validate_spec_list(spec, data, full, errors));
 }
 
@@ -199,7 +202,7 @@
         throw ModuleSpecError(errs.str());
     }
 
-    ElementPtr module_spec_element = Element::fromJSON(file, file_name);
+    ConstElementPtr module_spec_element = Element::fromJSON(file, file_name);
     if (module_spec_element->contains("module_spec")) {
         return (ModuleSpec(module_spec_element->get("module_spec"), check));
     } else {
@@ -211,7 +214,7 @@
 moduleSpecFromFile(std::ifstream& in, const bool check)
                    throw(JSONError, ModuleSpecError)
 {
-    ElementPtr module_spec_element = Element::fromJSON(in);
+    ConstElementPtr module_spec_element = Element::fromJSON(in);
     if (module_spec_element->contains("module_spec")) {
         return (ModuleSpec(module_spec_element->get("module_spec"), check));
     } else {
@@ -220,6 +223,7 @@
 }
 
 
+namespace {
 //
 // private functions
 //
@@ -227,9 +231,8 @@
 //
 // helper functions for validation
 //
-static bool
-check_type(ElementPtr spec, ElementPtr element)
-{
+bool
+check_type(ConstElementPtr spec, ConstElementPtr element) {
     std::string cur_item_type;
     cur_item_type = spec->get("item_type")->stringValue();
     if (cur_item_type == "any") {
@@ -257,9 +260,12 @@
     }
     return (false);
 }
-
-bool
-ModuleSpec::validate_item(const ElementPtr spec, const ElementPtr data, const bool full, ElementPtr errors) {
+}
+
+bool
+ModuleSpec::validate_item(ConstElementPtr spec, ConstElementPtr data,
+                          const bool full, ElementPtr errors) const
+{
     if (!check_type(spec, data)) {
         // we should do some proper error feedback here
         // std::cout << "type mismatch; not " << spec->get("item_type") << ": " << data << std::endl;
@@ -270,8 +276,8 @@
         return (false);
     }
     if (data->getType() == Element::list) {
-        ElementPtr list_spec = spec->get("list_item_spec");
-        BOOST_FOREACH(ElementPtr list_el, data->listValue()) {
+        ConstElementPtr list_spec = spec->get("list_item_spec");
+        BOOST_FOREACH(ConstElementPtr list_el, data->listValue()) {
             if (!check_type(list_spec, list_el)) {
                 if (errors) {
                     errors->add(Element::create("Type mismatch"));
@@ -295,10 +301,12 @@
 
 // spec is a map with item_name etc, data is a map
 bool
-ModuleSpec::validate_spec(const ElementPtr spec, const ElementPtr data, const bool full, ElementPtr errors) {
+ModuleSpec::validate_spec(ConstElementPtr spec, ConstElementPtr data,
+                          const bool full, ElementPtr errors) const
+{
     std::string item_name = spec->get("item_name")->stringValue();
     bool optional = spec->get("item_optional")->boolValue();
-    ElementPtr data_el;
+    ConstElementPtr data_el;
     data_el = data->get(item_name);
     
     if (data_el) {
@@ -318,10 +326,11 @@
 
 // spec is a list of maps, data is a map
 bool
-ModuleSpec::validate_spec_list(const ElementPtr spec, const ElementPtr data, const bool full, ElementPtr errors) {
-    ElementPtr cur_data_el;
+ModuleSpec::validate_spec_list(ConstElementPtr spec, ConstElementPtr data,
+                               const bool full, ElementPtr errors) const
+{
     std::string cur_item_name;
-    BOOST_FOREACH(ElementPtr cur_spec_el, spec->listValue()) {
+    BOOST_FOREACH(ConstElementPtr cur_spec_el, spec->listValue()) {
         if (!validate_spec(cur_spec_el, data, full, errors)) {
             return (false);
         }

Modified: branches/trac311/src/lib/config/module_spec.h
==============================================================================
--- branches/trac311/src/lib/config/module_spec.h (original)
+++ branches/trac311/src/lib/config/module_spec.h Sun Sep 26 03:25:19 2010
@@ -51,28 +51,28 @@
     ///
     class ModuleSpec {
     public:
-        explicit ModuleSpec() {};
+        ModuleSpec() {};
         /// Create a \c ModuleSpec instance with the given data as
         /// the specification
         /// \param e The Element containing the data specification
-        explicit ModuleSpec(ElementPtr e, const bool check = true)
-                            throw(ModuleSpecError);
+        explicit ModuleSpec(ConstElementPtr e, const bool check = true)
+            throw(ModuleSpecError);
 
         /// Returns the commands part of the specification as an
         /// ElementPtr, returns an empty ElementPtr if there is none
         /// \return ElementPtr Shared pointer to the commands
         ///                    part of the specification
-        const ElementPtr getCommandsSpec() const;
+        ConstElementPtr getCommandsSpec() const;
 
         /// Returns the configuration part of the specification as an
         /// ElementPtr
         /// \return ElementPtr Shared pointer to the configuration
         ///                    part of the specification
-        const ElementPtr getConfigSpec() const;
+        ConstElementPtr getConfigSpec() const;
 
         /// Returns the full module specification as an ElementPtr
         /// \return ElementPtr Shared pointer to the specification
-        const ElementPtr getFullSpec() const { return (module_specification); }
+        ConstElementPtr getFullSpec() const { return module_specification; }
 
         /// Returns the module name as specified by the specification
         const std::string getModuleName() const;
@@ -87,17 +87,22 @@
         /// \param data The base \c Element of the data to check
         /// \return true if the data conforms to the specification,
         /// false otherwise.
-        bool validate_config(const ElementPtr data, const bool full = false);
+        bool validate_config(ConstElementPtr data,
+                             const bool full = false) const;
 
         /// errors must be of type ListElement
-        bool validate_config(const ElementPtr data, const bool full, ElementPtr errors);
+        bool validate_config(ConstElementPtr data, const bool full,
+                             ElementPtr errors) const;
 
     private:
-        bool validate_item(const ElementPtr spec, const ElementPtr data, const bool full, ElementPtr errors);
-        bool validate_spec(const ElementPtr spec, const ElementPtr data, const bool full, ElementPtr errors);
-        bool validate_spec_list(const ElementPtr spec, const ElementPtr data, const bool full, ElementPtr errors);
+        bool validate_item(ConstElementPtr spec, ConstElementPtr data,
+                           const bool full, ElementPtr errors) const;
+        bool validate_spec(ConstElementPtr spec, ConstElementPtr data,
+                           const bool full, ElementPtr errors) const;
+        bool validate_spec_list(ConstElementPtr spec, ConstElementPtr data,
+                                const bool full, ElementPtr errors) const;
 
-        ElementPtr module_specification;
+        ConstElementPtr module_specification;
     };
 
     /// Creates a \c ModuleSpec instance from the contents
@@ -126,3 +131,7 @@
 } }
 
 #endif // _DATA_DEF_H
+
+// Local Variables: 
+// mode: c++
+// End: 

Modified: branches/trac311/src/lib/config/tests/Makefile.am
==============================================================================
--- branches/trac311/src/lib/config/tests/Makefile.am (original)
+++ branches/trac311/src/lib/config/tests/Makefile.am Sun Sep 26 03:25:19 2010
@@ -21,15 +21,13 @@
 run_unittests_SOURCES = ccsession_unittests.cc module_spec_unittests.cc config_data_unittests.cc run_unittests.cc
 
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
-run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
+# TODO: remove PTHREAD_LDFLAGS (and from configure too)
+run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS) $(PTHREAD_LDFLAGS)
 run_unittests_LDADD =  $(GTEST_LDADD)
 run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
+run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.la
 run_unittests_LDADD += libfake_session.la
 run_unittests_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
-# link *only* to data.o from lib/cc (more importantly, don't link in
-# the session class provided there, since we use our own fake_session
-# here)
-run_unittests_LDADD += $(top_builddir)/src/lib/cc/data.o
 
 endif
 

Modified: branches/trac311/src/lib/config/tests/ccsession_unittests.cc
==============================================================================
--- branches/trac311/src/lib/config/tests/ccsession_unittests.cc (original)
+++ branches/trac311/src/lib/config/tests/ccsession_unittests.cc Sun Sep 26 03:25:19 2010
@@ -57,7 +57,7 @@
 };
 
 TEST_F(CCSessionTest, createAnswer) {
-    ElementPtr answer;
+    ConstElementPtr answer;
     answer = createAnswer();
     EXPECT_EQ("{ \"result\": [ 0 ] }", answer->str());
     answer = createAnswer(1, "error");
@@ -66,14 +66,14 @@
     EXPECT_THROW(createAnswer(1, ElementPtr()), CCSessionError);
     EXPECT_THROW(createAnswer(1, Element::create(1)), CCSessionError);
 
-    ElementPtr arg = el("[ \"just\", \"some\", \"data\" ]");
+    ConstElementPtr arg = el("[ \"just\", \"some\", \"data\" ]");
     answer = createAnswer(0, arg);
     EXPECT_EQ("{ \"result\": [ 0, [ \"just\", \"some\", \"data\" ] ] }", answer->str());
 }
 
 TEST_F(CCSessionTest, parseAnswer) {
-    ElementPtr answer;
-    ElementPtr arg;
+    ConstElementPtr answer;
+    ConstElementPtr arg;
     int rcode;
 
     EXPECT_THROW(parseAnswer(rcode, ElementPtr()), CCSessionError);
@@ -103,8 +103,8 @@
 }
 
 TEST_F(CCSessionTest, createCommand) {
-    ElementPtr command;
-    ElementPtr arg;
+    ConstElementPtr command;
+    ConstElementPtr arg;
 
     command = createCommand("my_command");
     ASSERT_EQ("{ \"command\": [ \"my_command\" ] }", command->str());
@@ -123,7 +123,7 @@
 }
 
 TEST_F(CCSessionTest, parseCommand) {
-    ElementPtr arg;
+    ConstElementPtr arg;
     std::string cmd;
 
     // should throw
@@ -155,7 +155,7 @@
     EXPECT_EQ(true, session.haveSubscription("Spec1", "*"));
 
     EXPECT_EQ(1, session.getMsgQueue()->size());
-    ElementPtr msg;
+    ConstElementPtr msg;
     std::string group, to;
     msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"command\": [ \"module_spec\", { \"module_name\": \"Spec1\" } ] }", msg->str());
@@ -171,7 +171,7 @@
     EXPECT_EQ(true, session.haveSubscription("Spec2", "*"));
 
     EXPECT_EQ(1, session.getMsgQueue()->size());
-    ElementPtr msg;
+    ConstElementPtr msg;
     std::string group, to;
     msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"command\": [ \"module_spec\", { \"commands\": [ { \"command_args\": [ { \"item_default\": \"\", \"item_name\": \"message\", \"item_optional\": false, \"item_type\": \"string\" } ], \"command_description\": \"Print the given message to stdout\", \"command_name\": \"print_message\" }, { \"command_args\": [  ], \"command_description\": \"Shut down BIND 10\", \"command_name\": \"shutdown\" } ], \"config_data\": [ { \"item_default\": 1, \"item_name\": \"item1\", \"item_optional\": false, \"item_type\": \"integer\" }, { \"item_default\": 1.1, \"item_name\": \"item2\", \"item_optional\": false, \"item_type\": \"real\" }, { \"item_default\": true, \"item_name\": \"item3\", \"item_optional\": false, \"item_type\": \"boolean\" }, { \"item_default\": \"test\", \"item_name\": \"item4\", \"item_optional\": false, \"item_type\": \"string\" }, { \"item_default\": [ \"a\", \"b\" ], \"item_name\": \"item5\", \"item_optional\": false, \"item_type\": \"list\", \"list_item_sp
 ec\": { \"item_default\": \"\", \"item_name\": \"list_element\", \"item_optional\": false, \"item_type\": \"string\" } }, { \"item_default\": {  }, \"item_name\": \"item6\", \"item_optional\": false, \"item_type\": \"map\", \"map_item_spec\": [ { \"item_default\": \"default\", \"item_name\": \"value1\", \"item_optional\": true, \"item_type\": \"string\" }, { \"item_name\": \"value2\", \"item_optional\": true, \"item_type\": \"integer\" } ] } ], \"module_name\": \"Spec2\" } ] }", msg->str());
@@ -180,7 +180,7 @@
     EXPECT_EQ(0, session.getMsgQueue()->size());
 }
 
-ElementPtr my_config_handler(ElementPtr new_config) {
+ConstElementPtr my_config_handler(ConstElementPtr new_config) {
     if (new_config && new_config->contains("item1") &&
         new_config->get("item1")->intValue() == 5) {
         return (createAnswer(6, "I do not like the number 5"));
@@ -188,8 +188,8 @@
     return (createAnswer());
 }
 
-ElementPtr my_command_handler(const std::string& command,
-                              ElementPtr arg UNUSED_PARAM)
+ConstElementPtr my_command_handler(const std::string& command,
+                                   ConstElementPtr arg UNUSED_PARAM)
 {
     if (command == "good_command") {
         return (createAnswer());
@@ -218,7 +218,7 @@
     EXPECT_EQ(true, session.haveSubscription("Spec2", "*"));
 
     EXPECT_EQ(2, session.getMsgQueue()->size());
-    ElementPtr msg;
+    ConstElementPtr msg;
     std::string group, to;
     msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"command\": [ \"module_spec\", { \"commands\": [ { \"command_args\": [ { \"item_default\": \"\", \"item_name\": \"message\", \"item_optional\": false, \"item_type\": \"string\" } ], \"command_description\": \"Print the given message to stdout\", \"command_name\": \"print_message\" }, { \"command_args\": [  ], \"command_description\": \"Shut down BIND 10\", \"command_name\": \"shutdown\" } ], \"config_data\": [ { \"item_default\": 1, \"item_name\": \"item1\", \"item_optional\": false, \"item_type\": \"integer\" }, { \"item_default\": 1.1, \"item_name\": \"item2\", \"item_optional\": false, \"item_type\": \"real\" }, { \"item_default\": true, \"item_name\": \"item3\", \"item_optional\": false, \"item_type\": \"boolean\" }, { \"item_default\": \"test\", \"item_name\": \"item4\", \"item_optional\": false, \"item_type\": \"string\" }, { \"item_default\": [ \"a\", \"b\" ], \"item_name\": \"item5\", \"item_optional\": false, \"item_type\": \"list\", \"list_item_sp
 ec\": { \"item_default\": \"\", \"item_name\": \"list_element\", \"item_optional\": false, \"item_type\": \"string\" } }, { \"item_default\": {  }, \"item_name\": \"item6\", \"item_optional\": false, \"item_type\": \"map\", \"map_item_spec\": [ { \"item_default\": \"default\", \"item_name\": \"value1\", \"item_optional\": true, \"item_type\": \"string\" }, { \"item_name\": \"value2\", \"item_optional\": true, \"item_type\": \"integer\" } ] } ], \"module_name\": \"Spec2\" } ] }", msg->str());
@@ -242,7 +242,7 @@
     EXPECT_EQ(true, session.haveSubscription("Spec2", "*"));
 
     EXPECT_EQ(2, session.getMsgQueue()->size());
-    ElementPtr msg;
+    ConstElementPtr msg;
     std::string group, to;
     // checked above, drop em
     msg = session.getFirstMessage(group, to);
@@ -381,7 +381,7 @@
     EXPECT_THROW(mccs.addRemoteConfig(ccspecfile("spec2.spec")), CCSessionError);
     
     session.getMessages()->add(createAnswer());
-    mccs.addRemoteConfig(ccspecfile("spec2.spec"));
+    EXPECT_THROW(mccs.addRemoteConfig(ccspecfile("spec2.spec")), CCSessionError);
 }
 
 TEST_F(CCSessionTest, ignoreRemoteConfigCommands) {
@@ -393,7 +393,7 @@
     EXPECT_EQ(true, session.haveSubscription("Spec2", "*"));
 
     EXPECT_EQ(2, session.getMsgQueue()->size());
-    ElementPtr msg;
+    ConstElementPtr msg;
     std::string group, to;
     // drop the module_spec and config commands
     session.getFirstMessage(group, to);

Modified: branches/trac311/src/lib/config/tests/fake_session.cc
==============================================================================
--- branches/trac311/src/lib/config/tests/fake_session.cc (original)
+++ branches/trac311/src/lib/config/tests/fake_session.cc Sun Sep 26 03:25:19 2010
@@ -40,12 +40,12 @@
 
 // ok i want these in cc/data 
 bool
-listContains(ElementPtr list, ElementPtr el) {
+listContains(ConstElementPtr list, ConstElementPtr el) {
     if (!list) {
         return (false);
     }
-    BOOST_FOREACH(ElementPtr l_el, list->listValue()) {
-        if (l_el == el) {
+    BOOST_FOREACH(ConstElementPtr l_el, list->listValue()) {
+        if (*l_el == *el) {
             return (true);
         }
     }
@@ -53,10 +53,10 @@
 }
 
 void
-listRemove(ElementPtr list, ElementPtr el) {
+listRemove(ElementPtr list, ConstElementPtr el) {
     int i = -1;
-    BOOST_FOREACH(ElementPtr s_el, list->listValue()) {
-        if (el == s_el) {
+    BOOST_FOREACH(ConstElementPtr s_el, list->listValue()) {
+        if (*el == *s_el) {
             i = 0;
         }
         i++;
@@ -82,11 +82,6 @@
 FakeSession::~FakeSession() {
 }
 
-bool
-FakeSession::connect() {
-    return (true);
-}
-
 void
 FakeSession::disconnect() {
 }
@@ -99,25 +94,8 @@
 FakeSession::establish(const char* socket_file) {
 }
 
-//
-// Convert to wire format and send this on the TCP stream with its length prefix
-//
-void
-FakeSession::sendmsg(ElementPtr& msg) {
-    //cout << "[XX] client sends message: " << msg << endl;
-    // err, to where?
-    addMessage(msg, "*", "*");
-}
-
-void
-FakeSession::sendmsg(ElementPtr& env, ElementPtr& msg) {
-    //cout << "[XX] client sends message: " << msg << endl;
-    //cout << "[XX] env: " << env << endl;
-    addMessage(msg, env->get("group")->stringValue(), env->get("to")->stringValue());
-}
-
-bool
-FakeSession::recvmsg(ElementPtr& msg, bool nonblock UNUSED_PARAM,
+bool
+FakeSession::recvmsg(ConstElementPtr& msg, bool nonblock UNUSED_PARAM,
                      int seq UNUSED_PARAM)
 {
     //cout << "[XX] client asks for message " << endl;
@@ -133,7 +111,7 @@
 }
 
 bool
-FakeSession::recvmsg(ElementPtr& env, ElementPtr& msg,
+FakeSession::recvmsg(ConstElementPtr& env, ConstElementPtr& msg,
                      bool nonblock UNUSED_PARAM,
                      int seq UNUSED_PARAM)
 {
@@ -147,12 +125,13 @@
         messages_->remove(0);
         return (true);
     } else if (msg_queue_) {
-        BOOST_FOREACH(ElementPtr c_m, msg_queue_->listValue()) {
-            ElementPtr to_remove = ElementPtr();
+        BOOST_FOREACH(ConstElementPtr c_m, msg_queue_->listValue()) {
+            ConstElementPtr to_remove = ElementPtr();
             if (haveSubscription(c_m->get(0), c_m->get(1))) {
-                env = Element::createMap();
-                env->set("group", c_m->get(0));
-                env->set("to", c_m->get(1));
+                ElementPtr new_env = Element::createMap();
+                new_env->set("group", c_m->get(0));
+                new_env->set("to", c_m->get(1));
+                env = new_env;
                 msg = c_m->get(2);
                 to_remove = c_m;
             }
@@ -192,7 +171,7 @@
 }
 
 int
-FakeSession::group_sendmsg(ElementPtr msg, std::string group,
+FakeSession::group_sendmsg(ConstElementPtr msg, std::string group,
                            std::string to, std::string instance UNUSED_PARAM)
 {
     //cout << "[XX] client sends message: " << msg << endl;
@@ -202,28 +181,29 @@
 }
 
 bool
-FakeSession::group_recvmsg(ElementPtr& envelope, ElementPtr& msg,
+FakeSession::group_recvmsg(ConstElementPtr& envelope, ConstElementPtr& msg,
                            bool nonblock, int seq)
 {
     return (recvmsg(envelope, msg, nonblock, seq));
 }
 
 int
-FakeSession::reply(ElementPtr& envelope, ElementPtr& newmsg) {
+FakeSession::reply(ConstElementPtr envelope, ConstElementPtr newmsg) {
     //cout << "[XX] client sends reply: " << newmsg << endl;
     //cout << "[XX] env: " << envelope << endl;
-    addMessage(newmsg, envelope->get("group")->stringValue(), envelope->get("to")->stringValue());
+    addMessage(newmsg, envelope->get("group")->stringValue(),
+               envelope->get("to")->stringValue());
     return (1);
 }
 
 bool
-FakeSession::hasQueuedMsgs() {
+FakeSession::hasQueuedMsgs() const {
     return (false);
 }
 
-ElementPtr
-FakeSession::getFirstMessage(std::string& group, std::string& to) {
-    ElementPtr el;
+ConstElementPtr
+FakeSession::getFirstMessage(std::string& group, std::string& to) const {
+    ConstElementPtr el;
     if (msg_queue_ && msg_queue_->size() > 0) {
         el = msg_queue_->get(0);
         msg_queue_->remove(0);
@@ -238,7 +218,7 @@
 }
 
 void
-FakeSession::addMessage(ElementPtr msg, const std::string& group,
+FakeSession::addMessage(ConstElementPtr msg, const std::string& group,
                         const std::string& to)
 {
     ElementPtr m_el = Element::createList();
@@ -270,8 +250,7 @@
 }
 
 bool
-FakeSession::haveSubscription(const ElementPtr group,
-                              const ElementPtr instance)
+FakeSession::haveSubscription(ConstElementPtr group, ConstElementPtr instance)
 {
     return (haveSubscription(group->stringValue(), instance->stringValue()));
 }

Modified: branches/trac311/src/lib/config/tests/fake_session.h
==============================================================================
--- branches/trac311/src/lib/config/tests/fake_session.h (original)
+++ branches/trac311/src/lib/config/tests/fake_session.h Sun Sep 26 03:25:19 2010
@@ -47,40 +47,32 @@
     virtual void startRead(boost::function<void()> read_callback);
 
     virtual void establish(const char* socket_file = NULL);
-    bool connect();
     virtual void disconnect();
-    void sendmsg(isc::data::ElementPtr& msg);
-    void sendmsg(isc::data::ElementPtr& env,
-                 isc::data::ElementPtr& msg);
-    bool recvmsg(isc::data::ElementPtr& msg,
-                 bool nonblock = true, int seq = -1);
-    bool recvmsg(isc::data::ElementPtr& env,
-                 isc::data::ElementPtr& msg,
-                 bool nonblock = true, int seq = -1);
     virtual void subscribe(std::string group,
                            std::string instance = "*");
     virtual void unsubscribe(std::string group,
                              std::string instance = "*");
-    virtual int group_sendmsg(isc::data::ElementPtr msg,
+    virtual int group_sendmsg(isc::data::ConstElementPtr msg,
                               std::string group,
                               std::string instance = "*",
                               std::string to = "*");
-    virtual bool group_recvmsg(isc::data::ElementPtr& envelope,
-                               isc::data::ElementPtr& msg,
+    virtual bool group_recvmsg(isc::data::ConstElementPtr& envelope,
+                               isc::data::ConstElementPtr& msg,
                                bool nonblock = true,
                                int seq = -1);
-    virtual int reply(isc::data::ElementPtr& envelope,
-                      isc::data::ElementPtr& newmsg);
-    virtual bool hasQueuedMsgs();
-    virtual void setTimeout(size_t milliseconds) {};
-    virtual size_t getTimeout() const { return 0; };
-    isc::data::ElementPtr getFirstMessage(std::string& group, std::string& to);
-    void addMessage(isc::data::ElementPtr, const std::string& group,
+    virtual int reply(isc::data::ConstElementPtr envelope,
+                      isc::data::ConstElementPtr newmsg);
+    virtual bool hasQueuedMsgs() const;
+    virtual void setTimeout(size_t milliseconds) {}
+    virtual size_t getTimeout() const { return (0); }
+    isc::data::ConstElementPtr getFirstMessage(std::string& group,
+                                               std::string& to) const;
+    void addMessage(isc::data::ConstElementPtr, const std::string& group,
                     const std::string& to);
     bool haveSubscription(const std::string& group,
                           const std::string& instance);
-    bool haveSubscription(const isc::data::ElementPtr group,
-                          const isc::data::ElementPtr instance);
+    bool haveSubscription(const isc::data::ConstElementPtr group,
+                          const isc::data::ConstElementPtr instance);
 
     // For the convenience of tests, we share these internal members
     // with the tester.  The test code may insert update and check,
@@ -90,6 +82,12 @@
     isc::data::ElementPtr getMsgQueue() { return (msg_queue_); }
 
 private:
+    bool recvmsg(isc::data::ConstElementPtr& msg,
+                 bool nonblock = true, int seq = -1);
+    bool recvmsg(isc::data::ConstElementPtr& env,
+                 isc::data::ConstElementPtr& msg,
+                 bool nonblock = true, int seq = -1);
+
     const isc::data::ElementPtr messages_;
     isc::data::ElementPtr subscriptions_;
     isc::data::ElementPtr msg_queue_;

Modified: branches/trac311/src/lib/config/tests/module_spec_unittests.cc
==============================================================================
--- branches/trac311/src/lib/config/tests/module_spec_unittests.cc (original)
+++ branches/trac311/src/lib/config/tests/module_spec_unittests.cc Sun Sep 26 03:25:19 2010
@@ -134,23 +134,24 @@
 }
 
 bool
-data_test(ModuleSpec dd, const std::string& data_file_name) {
+data_test(const ModuleSpec& dd, const std::string& data_file_name) {
     std::ifstream data_file;
 
     data_file.open(specfile(data_file_name).c_str());
-    ElementPtr data = Element::fromJSON(data_file, data_file_name);
+    ConstElementPtr data = Element::fromJSON(data_file, data_file_name);
     data_file.close();
 
     return (dd.validate_config(data));
 }
 
 bool
-data_test_with_errors(ModuleSpec dd, const std::string& data_file_name, ElementPtr errors)
+data_test_with_errors(const ModuleSpec& dd, const std::string& data_file_name,
+                      ElementPtr errors)
 {
     std::ifstream data_file;
 
     data_file.open(specfile(data_file_name).c_str());
-    ElementPtr data = Element::fromJSON(data_file, data_file_name);
+    ConstElementPtr data = Element::fromJSON(data_file, data_file_name);
     data_file.close();
 
     return (dd.validate_config(data, true, errors));

Modified: branches/trac311/src/lib/datasrc/data_source.cc
==============================================================================
--- branches/trac311/src/lib/datasrc/data_source.cc (original)
+++ branches/trac311/src/lib/datasrc/data_source.cc Sun Sep 26 03:25:19 2010
@@ -206,6 +206,11 @@
         if (!hit || !rrset || (flags & DataSrc::CNAME_FOUND) != 0) {
             hit = cache.retrieve(task.qname, task.qclass, RRType::CNAME(),
                                  rrset, flags);
+            if (!rrset) {
+                // If we don't have a positive cache, forget it; otherwise the
+                // intermediate result may confuse the subsequent processing.
+                hit = false;
+            }
         }
 
         if (hit) {
@@ -1245,7 +1250,7 @@
 // installed files we define the methods here.
 //
 DataSrc::Result
-DataSrc::init(const isc::data::ElementPtr config UNUSED_PARAM) {
+DataSrc::init(isc::data::ConstElementPtr config UNUSED_PARAM) {
     return (NOT_IMPLEMENTED);
 }
 

Modified: branches/trac311/src/lib/datasrc/data_source.h
==============================================================================
--- branches/trac311/src/lib/datasrc/data_source.h (original)
+++ branches/trac311/src/lib/datasrc/data_source.h Sun Sep 26 03:25:19 2010
@@ -115,7 +115,7 @@
     // Optional 'low-level' methods.  These will have stub implementations
     // in the general DataSrc class but MAY be overwritten by subclasses
     virtual Result init() = 0;
-    virtual Result init(const isc::data::ElementPtr config) = 0;
+    virtual Result init(isc::data::ConstElementPtr config) = 0;
     virtual Result close() = 0;
 
     // Mandatory 'low-level' methods: These will NOT be implemented by
@@ -187,7 +187,7 @@
     void setClass(const isc::dns::RRClass& c) { rrclass = c; }
 
     Result init() { return (NOT_IMPLEMENTED); }
-    Result init(const isc::data::ElementPtr config);
+    Result init(isc::data::ConstElementPtr config);
     Result close() { return (NOT_IMPLEMENTED); }
 
     virtual Result findRRset(const isc::dns::Name& qname,

Modified: branches/trac311/src/lib/datasrc/sqlite3_datasrc.cc
==============================================================================
--- branches/trac311/src/lib/datasrc/sqlite3_datasrc.cc (original)
+++ branches/trac311/src/lib/datasrc/sqlite3_datasrc.cc Sun Sep 26 03:25:19 2010
@@ -558,7 +558,7 @@
 }
 
 DataSrc::Result
-Sqlite3DataSrc::init(const isc::data::ElementPtr config) {
+Sqlite3DataSrc::init(isc::data::ConstElementPtr config) {
     if (config && config->contains("database_file")) {
         open(config->get("database_file")->stringValue());
     } else {

Modified: branches/trac311/src/lib/datasrc/sqlite3_datasrc.h
==============================================================================
--- branches/trac311/src/lib/datasrc/sqlite3_datasrc.h (original)
+++ branches/trac311/src/lib/datasrc/sqlite3_datasrc.h Sun Sep 26 03:25:19 2010
@@ -95,7 +95,7 @@
                              isc::dns::RRsetList& target) const;
 
     Result init() { return (init(isc::data::ElementPtr())); }
-    Result init(const isc::data::ElementPtr config);
+    Result init(const isc::data::ConstElementPtr config);
     Result close();
 
 private:

Modified: branches/trac311/src/lib/datasrc/static_datasrc.cc
==============================================================================
--- branches/trac311/src/lib/datasrc/static_datasrc.cc (original)
+++ branches/trac311/src/lib/datasrc/static_datasrc.cc Sun Sep 26 03:25:19 2010
@@ -260,7 +260,7 @@
 // Static data source is "configuration less", so the \c config parameter
 // is intentionally ignored.
 DataSrc::Result
-StaticDataSrc::init(const isc::data::ElementPtr config UNUSED_PARAM) {
+StaticDataSrc::init(isc::data::ConstElementPtr config UNUSED_PARAM) {
     return (init());
 }
 

Modified: branches/trac311/src/lib/datasrc/static_datasrc.h
==============================================================================
--- branches/trac311/src/lib/datasrc/static_datasrc.h (original)
+++ branches/trac311/src/lib/datasrc/static_datasrc.h Sun Sep 26 03:25:19 2010
@@ -81,7 +81,7 @@
                             isc::dns::RRsetList& target) const;
 
     Result init();
-    Result init(const isc::data::ElementPtr config);
+    Result init(isc::data::ConstElementPtr config);
     Result close();
 private:
     StaticDataSrcImpl* impl_;

Modified: branches/trac311/src/lib/datasrc/tests/datasrc_unittest.cc
==============================================================================
--- branches/trac311/src/lib/datasrc/tests/datasrc_unittest.cc (original)
+++ branches/trac311/src/lib/datasrc/tests/datasrc_unittest.cc Sun Sep 26 03:25:19 2010
@@ -49,7 +49,7 @@
 using namespace isc::data;
 
 namespace {
-const ElementPtr SQLITE_DBFILE_EXAMPLE = Element::fromJSON(
+ConstElementPtr SQLITE_DBFILE_EXAMPLE = Element::fromJSON(
     "{ \"database_file\": \"" TEST_DATA_DIR "/example.org.sqlite3\"}");
 
 class DataSrcTest : public ::testing::Test {
@@ -915,6 +915,24 @@
     headerCheck(msg, Rcode::REFUSED(), true, false, true, 0, 0, 0);
 }
 
+TEST_F(DataSrcTest, DSQueryFromCache) {
+    // explicitly enable hot spot cache
+    cache.setEnabled(true);
+
+    // The first query will create a negative cache for example.org/CNAME
+    createAndProcessQuery(Name("example.org"), RRClass::IN(), RRType::SOA());
+
+    // the cached CNAME shouldn't confuse subsequent query.
+    // there may be several different possible cases that could trigger a bug,
+    // but DS query is the only known example.
+    msg.clear(Message::PARSE);
+    createAndProcessQuery(Name("example.org"), RRClass::IN(), RRType::DS());
+
+    // returning refused is probably a bad behavior, but it's a different
+    // issue -- see Trac Ticket #306.
+    headerCheck(msg, Rcode::REFUSED(), true, false, true, 0, 0, 0);
+}
+
 // Non-existent name in the "static" data source.  The purpose of this test
 // is to check a corner case behavior when atypical RRClass (CH in this case)
 // is specified.

Modified: branches/trac311/src/lib/datasrc/tests/sqlite3_unittest.cc
==============================================================================
--- branches/trac311/src/lib/datasrc/tests/sqlite3_unittest.cc (original)
+++ branches/trac311/src/lib/datasrc/tests/sqlite3_unittest.cc Sun Sep 26 03:25:19 2010
@@ -43,22 +43,22 @@
 using namespace isc::data;
 
 namespace {
-ElementPtr SQLITE_DBFILE_EXAMPLE = Element::fromJSON(
+ConstElementPtr SQLITE_DBFILE_EXAMPLE = Element::fromJSON(
     "{ \"database_file\": \"" TEST_DATA_DIR "/test.sqlite3\"}");
-ElementPtr SQLITE_DBFILE_EXAMPLE2 = Element::fromJSON(
+ConstElementPtr SQLITE_DBFILE_EXAMPLE2 = Element::fromJSON(
     "{ \"database_file\": \"" TEST_DATA_DIR "/example2.com.sqlite3\"}");
-ElementPtr SQLITE_DBFILE_EXAMPLE_ROOT = Element::fromJSON(
+ConstElementPtr SQLITE_DBFILE_EXAMPLE_ROOT = Element::fromJSON(
     "{ \"database_file\": \"" TEST_DATA_DIR "/test-root.sqlite3\"}");
-ElementPtr SQLITE_DBFILE_BROKENDB = Element::fromJSON(
+ConstElementPtr SQLITE_DBFILE_BROKENDB = Element::fromJSON(
     "{ \"database_file\": \"" TEST_DATA_DIR "/brokendb.sqlite3\"}");
-ElementPtr SQLITE_DBFILE_MEMORY = Element::fromJSON(
+ConstElementPtr SQLITE_DBFILE_MEMORY = Element::fromJSON(
     "{ \"database_file\": \":memory:\"}");
 
 // The following file must be non existent and must be non"creatable";
 // the sqlite3 library will try to create a new DB file if it doesn't exist,
 // so to test a failure case the create operation should also fail.
 // The "nodir", a non existent directory, is inserted for this purpose.
-ElementPtr SQLITE_DBFILE_NOTEXIST = Element::fromJSON(
+ConstElementPtr SQLITE_DBFILE_NOTEXIST = Element::fromJSON(
     "{ \"database_file\": \"" TEST_DATA_DIR "/nodir/notexist\"}");
 
 const string sigdata_common(" 20100322084538 20100220084538 "

Modified: branches/trac311/src/lib/datasrc/tests/test_datasrc.cc
==============================================================================
--- branches/trac311/src/lib/datasrc/tests/test_datasrc.cc (original)
+++ branches/trac311/src/lib/datasrc/tests/test_datasrc.cc Sun Sep 26 03:25:19 2010
@@ -307,8 +307,7 @@
 }
 
 DataSrc::Result
-TestDataSrc::init(const isc::data::ElementPtr config UNUSED_PARAM)
-{
+TestDataSrc::init(isc::data::ConstElementPtr config UNUSED_PARAM) {
     return (init());
 }
 

Modified: branches/trac311/src/lib/datasrc/tests/test_datasrc.h
==============================================================================
--- branches/trac311/src/lib/datasrc/tests/test_datasrc.h (original)
+++ branches/trac311/src/lib/datasrc/tests/test_datasrc.h Sun Sep 26 03:25:19 2010
@@ -85,7 +85,7 @@
                              isc::dns::RRsetList& target) const;
 
     Result init();
-    Result init(const isc::data::ElementPtr config);
+    Result init(isc::data::ConstElementPtr config);
     Result close() { return (SUCCESS); }
 
 private:

Modified: branches/trac311/src/lib/dns/Makefile.am
==============================================================================
--- branches/trac311/src/lib/dns/Makefile.am (original)
+++ branches/trac311/src/lib/dns/Makefile.am Sun Sep 26 03:25:19 2010
@@ -89,8 +89,8 @@
 rrclass.h rrtype.h rrparamregistry.cc rdataclass.h rdataclass.cc: Makefile
 	./gen-rdatacode.py
 
-libdns++_includedir = $(includedir)/dns
-libdns++_include_HEADERS = \
+libdns___includedir = $(includedir)/dns
+libdns___include_HEADERS = \
 	buffer.h \
 	dnssectime.h \
 	exceptions.h \

Modified: branches/trac311/src/lib/dns/messagerenderer.h
==============================================================================
--- branches/trac311/src/lib/dns/messagerenderer.h (original)
+++ branches/trac311/src/lib/dns/messagerenderer.h Sun Sep 26 03:25:19 2010
@@ -109,7 +109,7 @@
     /// The destructor does nothing on the given \c buffer on construction;
     /// in fact, it is expected that the user will use the resulting buffer
     /// for some post rendering purposes (e.g., send the data to the network).
-    /// It's user's responsibility to do any necessary cleanup for the
+    /// It's the user's responsibility to do any necessary cleanup for the
     /// \c buffer.
     ~MessageRenderer();
     //@}

Modified: branches/trac311/src/lib/dns/name.cc
==============================================================================
--- branches/trac311/src/lib/dns/name.cc (original)
+++ branches/trac311/src/lib/dns/name.cc Sun Sep 26 03:25:19 2010
@@ -601,17 +601,17 @@
 
 Name
 Name::concatenate(const Name& suffix) const {
-    assert(this->length_ > 0 && suffix.length_ > 0);
-    assert(this->labelcount_ > 0 && suffix.labelcount_ > 0);
-
-    unsigned int length = this->length_ + suffix.length_ - 1;
+    assert(length_ > 0 && suffix.length_ > 0);
+    assert(labelcount_ > 0 && suffix.labelcount_ > 0);
+
+    unsigned int length = length_ + suffix.length_ - 1;
     if (length > Name::MAX_WIRE) {
         isc_throw(TooLongName, "names are too long to concatenate");
     }
 
     Name retname;
     retname.ndata_.reserve(length);
-    retname.ndata_.assign(this->ndata_, 0, this->length_ - 1);
+    retname.ndata_.assign(ndata_, 0, length_ - 1);
     retname.ndata_.insert(retname.ndata_.end(),
                           suffix.ndata_.begin(), suffix.ndata_.end());
     assert(retname.ndata_.size() == length);
@@ -622,14 +622,13 @@
     // excluding that for the trailing dot, and append the offsets of the
     // suffix name with the additional offset of the length of the prefix.
     //
-    unsigned int labels = this->labelcount_ + suffix.labelcount_ - 1;
+    unsigned int labels = labelcount_ + suffix.labelcount_ - 1;
     assert(labels <= Name::MAX_LABELS);
     retname.offsets_.reserve(labels);
-    retname.offsets_.assign(&this->offsets_[0],
-                            &this->offsets_[0] + this->labelcount_ - 1);
+    retname.offsets_.assign(&offsets_[0], &offsets_[0] + labelcount_ - 1);
     transform(suffix.offsets_.begin(), suffix.offsets_.end(),
               back_inserter(retname.offsets_),
-              bind2nd(plus<char>(), this->length_ - 1));
+              bind2nd(plus<char>(), length_ - 1));
     assert(retname.offsets_.size() == labels);
     retname.labelcount_ = labels;
 

Modified: branches/trac311/src/lib/dns/python/Makefile.am
==============================================================================
--- branches/trac311/src/lib/dns/python/Makefile.am (original)
+++ branches/trac311/src/lib/dns/python/Makefile.am Sun Sep 26 03:25:19 2010
@@ -1,27 +1,16 @@
-SUBDIRS = tests
+SUBDIRS = . tests
 
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
-
 AM_CXXFLAGS = $(B10_CXXFLAGS)
 
-if USE_GXX
-AM_CXXFLAGS += -Wno-write-strings
-endif
-
-#lib_LTLIBRARIES = libdns_python_name.la libdns_python_rrset.la
-#libdns_python_name_la_SOURCES = name_python.cc
-#libdns_python_name_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
-#libdns_python_name_la_LDFLAGS = $(PYTHON_LDFLAGS)
-
-#lib_LTLIBRARIES = libdns_python_name.la libdns_python_rrset.la
-pyexec_LTLIBRARIES = libdns_python.la
-libdns_python_la_SOURCES = libdns_python.cc libdns_python_common.cc
-libdns_python_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
-libdns_python_la_LDFLAGS = $(PYTHON_LDFLAGS)
+pyexec_LTLIBRARIES = pydnspp.la
+pydnspp_la_SOURCES = pydnspp.cc pydnspp_common.cc
+pydnspp_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
+pydnspp_la_LDFLAGS = $(PYTHON_LDFLAGS)
 
 # directly included from source files, so these don't have their own
 # rules
-EXTRA_DIST = libdns_python_common.h
+EXTRA_DIST = pydnspp_common.h
 EXTRA_DIST += edns_python.h
 EXTRA_DIST += messagerenderer_python.cc
 EXTRA_DIST += message_python.cc
@@ -35,7 +24,7 @@
 
 # Python prefers .so, while some OSes (specifically MacOS) use a different
 # suffix for dynamic objects.  -module is necessary to work this around.
-libdns_python_la_LDFLAGS += -module
-libdns_python_la_LIBADD = $(top_builddir)/src/lib/dns/libdns++.la
-libdns_python_la_LIBADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
-libdns_python_la_LIBADD += $(PYTHON_LIB)
+pydnspp_la_LDFLAGS += -module
+pydnspp_la_LIBADD = $(top_builddir)/src/lib/dns/libdns++.la
+pydnspp_la_LIBADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
+pydnspp_la_LIBADD += $(PYTHON_LIB)

Modified: branches/trac311/src/lib/dns/python/README
==============================================================================
--- branches/trac311/src/lib/dns/python/README (original)
+++ branches/trac311/src/lib/dns/python/README Sun Sep 26 03:25:19 2010
@@ -1,14 +1,14 @@
 
 This is an implementation of the python wrappers for isc::dns.
 
-Currently, when compiled the module is called libdns_python. If we
+When compiled the module is called pydnspp. If we
 decide to always need it we can add a default import under
 lib/python/isc.
 
 To use it from the source tree, you must add src/lib/dns/python/.libs
 to your PYTHONPATH environment variable. Within python you can then use
-> import libdns_python
-> rrc = libdns_python.RRClass("IN")
+> import pydnspp
+> rrc = pydnspp.RRClass("IN")
 etc.
 
 Notes:
@@ -26,8 +26,8 @@
 If you have specific functionality you do need, please ask for it and we
 will add it.
 
-The 'main' module is defined in libdns_python.cc.
-There is a libdns_python_common.[cc|h] for helper functions.
+The 'main' module is defined in pydnspp.cc.
+There is a pydnspp_common.[cc|h] for helper functions.
 
 Implementation notes:
 
@@ -87,7 +87,7 @@
 
 Finally we define the function to add the class, constants, exceptions,
 and enums to the module. This function is called from the init function
-in libdns_python.cc, has the name
+in pydnspp.cc, has the name
 initModulePart_<c++ class name>, returns a boolean
 (true on success, false on failure), and takes the module as a
 PyObject*. There is a convenience function called addClassVariable to

Modified: branches/trac311/src/lib/dns/python/message_python.cc
==============================================================================
--- branches/trac311/src/lib/dns/python/message_python.cc (original)
+++ branches/trac311/src/lib/dns/python/message_python.cc Sun Sep 26 03:25:19 2010
@@ -70,7 +70,7 @@
 
 static PyTypeObject messageflag_type = {
     PyVarObject_HEAD_INIT(NULL, 0)
-    "libdns_python.MessageFlag",
+    "pydnspp.MessageFlag",
     sizeof(s_MessageFlag),              // tp_basicsize
     0,                                  // tp_itemsize
     (destructor)MessageFlag_destroy,    // tp_dealloc
@@ -246,7 +246,7 @@
 
 static PyTypeObject opcode_type = {
     PyVarObject_HEAD_INIT(NULL, 0)
-    "libdns_python.Opcode",
+    "pydnspp.Opcode",
     sizeof(s_Opcode),                   // tp_basicsize
     0,                                  // tp_itemsize
     (destructor)Opcode_destroy,         // tp_dealloc
@@ -534,7 +534,7 @@
 
 static PyTypeObject rcode_type = {
     PyVarObject_HEAD_INIT(NULL, 0)
-    "libdns_python.Rcode",
+    "pydnspp.Rcode",
     sizeof(s_Rcode),                    // tp_basicsize
     0,                                  // tp_itemsize
     (destructor)Rcode_destroy,          // tp_dealloc
@@ -809,7 +809,7 @@
 
 static PyTypeObject section_type = {
     PyVarObject_HEAD_INIT(NULL, 0)
-    "libdns_python.Section",
+    "pydnspp.Section",
     sizeof(s_Section),                  // tp_basicsize
     0,                                  // tp_itemsize
     (destructor)Section_destroy,        // tp_dealloc
@@ -1099,7 +1099,7 @@
 // Most of the functions are not actually implemented and NULL here.
 static PyTypeObject message_type = {
     PyVarObject_HEAD_INIT(NULL, 0)
-    "libdns_python.Message",
+    "pydnspp.Message",
     sizeof(s_Message),                  // tp_basicsize
     0,                                  // tp_itemsize
     (destructor)Message_destroy,        // tp_dealloc
@@ -1501,7 +1501,7 @@
 Message_toWire(s_Message* self, PyObject* args) {
     s_MessageRenderer* mr;
     
-    if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, (PyObject**) &mr)) {
+    if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
         try {
             self->message->toWire(*mr->messagerenderer);
             // If we return NULL it is seen as an error, so use this for
@@ -1593,14 +1593,16 @@
     addClassVariable(message_type, "DEFAULT_MAX_UDPSIZE", Py_BuildValue("I", Message::DEFAULT_MAX_UDPSIZE));
 
     /* Class-specific exceptions */
-    po_MessageTooShort = PyErr_NewException("libdns_python.MessageTooShort", NULL, NULL);
+    po_MessageTooShort = PyErr_NewException("pydnspp.MessageTooShort", NULL, NULL);
     PyModule_AddObject(mod, "MessageTooShort", po_MessageTooShort);
-    po_InvalidMessageSection = PyErr_NewException("libdns_python.InvalidMessageSection", NULL, NULL);
+    po_InvalidMessageSection = PyErr_NewException("pydnspp.InvalidMessageSection", NULL, NULL);
     PyModule_AddObject(mod, "InvalidMessageSection", po_InvalidMessageSection);
-    po_InvalidMessageOperation = PyErr_NewException("libdns_python.InvalidMessageOperation", NULL, NULL);
+    po_InvalidMessageOperation = PyErr_NewException("pydnspp.InvalidMessageOperation", NULL, NULL);
     PyModule_AddObject(mod, "InvalidMessageOperation", po_InvalidMessageOperation);
-    po_InvalidMessageUDPSize = PyErr_NewException("libdns_python.InvalidMessageUDPSize", NULL, NULL);
+    po_InvalidMessageUDPSize = PyErr_NewException("pydnspp.InvalidMessageUDPSize", NULL, NULL);
     PyModule_AddObject(mod, "InvalidMessageUDPSize", po_InvalidMessageUDPSize);
+    po_DNSMessageBADVERS = PyErr_NewException("pydnspp.DNSMessageBADVERS", NULL, NULL);
+    PyModule_AddObject(mod, "DNSMessageBADVERS", po_DNSMessageBADVERS);
 
     Py_INCREF(&message_type);
     PyModule_AddObject(mod, "Message",

Modified: branches/trac311/src/lib/dns/python/messagerenderer_python.cc
==============================================================================
--- branches/trac311/src/lib/dns/python/messagerenderer_python.cc (original)
+++ branches/trac311/src/lib/dns/python/messagerenderer_python.cc Sun Sep 26 03:25:19 2010
@@ -65,7 +65,7 @@
 
 static PyTypeObject messagerenderer_type = {
     PyVarObject_HEAD_INIT(NULL, 0)
-    "libdns_python.MessageRenderer",
+    "pydnspp.MessageRenderer",
     sizeof(s_MessageRenderer),          // tp_basicsize
     0,                                  // tp_itemsize
     (destructor)MessageRenderer_destroy,// tp_dealloc

Modified: branches/trac311/src/lib/dns/python/name_python.cc
==============================================================================
--- branches/trac311/src/lib/dns/python/name_python.cc (original)
+++ branches/trac311/src/lib/dns/python/name_python.cc Sun Sep 26 03:25:19 2010
@@ -68,7 +68,7 @@
 
 static PyTypeObject name_comparison_result_type = {
     PyVarObject_HEAD_INIT(NULL, 0)
-    "libdns_python.NameComparisonResult",
+    "pydnspp.NameComparisonResult",
     sizeof(s_NameComparisonResult),           // tp_basicsize
     0,                                        // tp_itemsize
     (destructor)NameComparisonResult_destroy, // tp_dealloc
@@ -222,7 +222,7 @@
 
 static PyTypeObject name_type = {
     PyVarObject_HEAD_INIT(NULL, 0)
-    "libdns_python.Name",
+    "pydnspp.Name",
     sizeof(s_Name),                     // tp_basicsize
     0,                                  // tp_itemsize
     (destructor)Name_destroy,           // tp_dealloc
@@ -421,7 +421,7 @@
         // to prevent memory leak
         Py_DECREF(name_bytes);
         return (result);
-    } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, (PyObject**) &mr)) {
+    } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
         self->name->toWire(*mr->messagerenderer);
         // If we return NULL it is seen as an error, so use this for
         // None returns
@@ -437,7 +437,7 @@
 Name_compare(s_Name* self, PyObject* args) {
     s_Name* other;
 
-    if (!PyArg_ParseTuple(args, "O!", &name_type, (PyObject* *) &other))
+    if (!PyArg_ParseTuple(args, "O!", &name_type, &other))
         return (NULL);
 
     s_NameComparisonResult* ret = PyObject_New(s_NameComparisonResult, &name_comparison_result_type);
@@ -452,7 +452,7 @@
 Name_equals(s_Name* self, PyObject* args) {
     s_Name* other;
 
-    if (!PyArg_ParseTuple(args, "O!", &name_type, (PyObject* *) &other))
+    if (!PyArg_ParseTuple(args, "O!", &name_type, &other))
         return (NULL);
 
     if (self->name->equals(*other->name))
@@ -565,7 +565,7 @@
 Name_concatenate(s_Name* self, PyObject* args) {
     s_Name* other;
 
-    if (!PyArg_ParseTuple(args, "O!", &name_type, (PyObject**) &other))
+    if (!PyArg_ParseTuple(args, "O!", &name_type, &other))
         return (NULL);
 
     s_Name* ret = PyObject_New(s_Name, &name_type);
@@ -651,30 +651,30 @@
     
 
     // Add the exceptions to the module
-    po_EmptyLabel = PyErr_NewException("libdns_python.EmptyLabel", NULL, NULL);
+    po_EmptyLabel = PyErr_NewException("pydnspp.EmptyLabel", NULL, NULL);
     PyModule_AddObject(mod, "EmptyLabel", po_EmptyLabel);
 
-    po_TooLongName = PyErr_NewException("libdns_python.TooLongName", NULL, NULL);
+    po_TooLongName = PyErr_NewException("pydnspp.TooLongName", NULL, NULL);
     PyModule_AddObject(mod, "TooLongName", po_TooLongName);
 
-    po_TooLongLabel = PyErr_NewException("libdns_python.TooLongLabel", NULL, NULL);
+    po_TooLongLabel = PyErr_NewException("pydnspp.TooLongLabel", NULL, NULL);
     PyModule_AddObject(mod, "TooLongLabel", po_TooLongLabel);
 
-    po_BadLabelType = PyErr_NewException("libdns_python.BadLabelType", NULL, NULL);
+    po_BadLabelType = PyErr_NewException("pydnspp.BadLabelType", NULL, NULL);
     PyModule_AddObject(mod, "BadLabelType", po_BadLabelType);
 
-    po_BadEscape = PyErr_NewException("libdns_python.BadEscape", NULL, NULL);
+    po_BadEscape = PyErr_NewException("pydnspp.BadEscape", NULL, NULL);
     PyModule_AddObject(mod, "BadEscape", po_BadEscape);
 
-    po_IncompleteName = PyErr_NewException("libdns_python.IncompleteName", NULL, NULL);
+    po_IncompleteName = PyErr_NewException("pydnspp.IncompleteName", NULL, NULL);
     PyModule_AddObject(mod, "IncompleteName", po_IncompleteName);
 
-    po_InvalidBufferPosition = PyErr_NewException("libdns_python.InvalidBufferPosition", NULL, NULL);
+    po_InvalidBufferPosition = PyErr_NewException("pydnspp.InvalidBufferPosition", NULL, NULL);
     PyModule_AddObject(mod, "InvalidBufferPosition", po_InvalidBufferPosition);
 
     // This one could have gone into the message_python.cc file, but is
     // already needed here.
-    po_DNSMessageFORMERR = PyErr_NewException("libdns_python.DNSMessageFORMERR", NULL, NULL);
+    po_DNSMessageFORMERR = PyErr_NewException("pydnspp.DNSMessageFORMERR", NULL, NULL);
     PyModule_AddObject(mod, "DNSMessageFORMERR", po_DNSMessageFORMERR);
 
     return (true);

Modified: branches/trac311/src/lib/dns/python/question_python.cc
==============================================================================
--- branches/trac311/src/lib/dns/python/question_python.cc (original)
+++ branches/trac311/src/lib/dns/python/question_python.cc Sun Sep 26 03:25:19 2010
@@ -76,7 +76,7 @@
 // Most of the functions are not actually implemented and NULL here.
 static PyTypeObject question_type = {
     PyVarObject_HEAD_INIT(NULL, 0)
-    "libdns_python.Question",
+    "pydnspp.Question",
     sizeof(s_Question),                 // tp_basicsize
     0,                                  // tp_itemsize
     (destructor)Question_destroy,       // tp_dealloc
@@ -254,8 +254,7 @@
         // to prevent memory leak
         Py_DECREF(n);
         return (result);
-    } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type,
-                                reinterpret_cast<PyObject**>(&mr))) {
+    } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
         self->question->toWire(*mr->messagerenderer);
         // If we return NULL it is seen as an error, so use this for
         // None returns

Modified: branches/trac311/src/lib/dns/python/rdata_python.cc
==============================================================================
--- branches/trac311/src/lib/dns/python/rdata_python.cc (original)
+++ branches/trac311/src/lib/dns/python/rdata_python.cc Sun Sep 26 03:25:19 2010
@@ -92,7 +92,7 @@
 // Most of the functions are not actually implemented and NULL here.
 static PyTypeObject rdata_type = {
     PyVarObject_HEAD_INIT(NULL, 0)
-    "libdns_python.Rdata",
+    "pydnspp.Rdata",
     sizeof(s_Rdata),                    // tp_basicsize
     0,                                  // tp_itemsize
     (destructor)Rdata_destroy,          // tp_dealloc
@@ -204,7 +204,7 @@
         // to prevent memory leak
         Py_DECREF(rd_bytes);
         return (result);
-    } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, (PyObject**) &mr)) {
+    } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
         self->rdata->toWire(*mr->messagerenderer);
         // If we return NULL it is seen as an error, so use this for
         // None returns
@@ -276,13 +276,13 @@
                        reinterpret_cast<PyObject*>(&rdata_type));
 
     // Add the exceptions to the class
-    po_InvalidRdataLength = PyErr_NewException("libdns_python.InvalidRdataLength", NULL, NULL);
+    po_InvalidRdataLength = PyErr_NewException("pydnspp.InvalidRdataLength", NULL, NULL);
     PyModule_AddObject(mod, "InvalidRdataLength", po_InvalidRdataLength);
 
-    po_InvalidRdataText = PyErr_NewException("libdns_python.InvalidRdataText", NULL, NULL);
+    po_InvalidRdataText = PyErr_NewException("pydnspp.InvalidRdataText", NULL, NULL);
     PyModule_AddObject(mod, "InvalidRdataText", po_InvalidRdataText);
 
-    po_CharStringTooLong = PyErr_NewException("libdns_python.CharStringTooLong", NULL, NULL);
+    po_CharStringTooLong = PyErr_NewException("pydnspp.CharStringTooLong", NULL, NULL);
     PyModule_AddObject(mod, "CharStringTooLong", po_CharStringTooLong);
 
     

Modified: branches/trac311/src/lib/dns/python/rrclass_python.cc
==============================================================================
--- branches/trac311/src/lib/dns/python/rrclass_python.cc (original)
+++ branches/trac311/src/lib/dns/python/rrclass_python.cc Sun Sep 26 03:25:19 2010
@@ -100,7 +100,7 @@
 // Most of the functions are not actually implemented and NULL here.
 static PyTypeObject rrclass_type = {
     PyVarObject_HEAD_INIT(NULL, 0)
-    "libdns_python.RRClass",
+    "pydnspp.RRClass",
     sizeof(s_RRClass),                  // tp_basicsize
     0,                                  // tp_itemsize
     (destructor)RRClass_destroy,        // tp_dealloc
@@ -157,7 +157,7 @@
     unsigned int i;
     PyObject* bytes = NULL;
     // The constructor argument can be a string ("IN"), an integer (1),
-    // or a sequence of numbers between 0 and 255 (wire code)
+    // or a sequence of numbers between 0 and 65535 (wire code)
 
     // Note that PyArg_ParseType can set PyError, and we need to clear
     // that if we try several like here. Otherwise the *next* python
@@ -170,7 +170,7 @@
         } else if (PyArg_ParseTuple(args, "I", &i)) {
             PyErr_Clear();
             if (i > 65535) {
-                PyErr_SetString(po_InvalidRRClass, "Class number too high");
+                PyErr_SetString(po_InvalidRRClass, "RR class number too high");
                 return (-1);
             }
             self->rrclass = new RRClass(i);
@@ -236,7 +236,7 @@
         // to prevent memory leak
         Py_DECREF(n);
         return (result);
-    } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, (PyObject**) &mr)) {
+    } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
         self->rrclass->toWire(*mr->messagerenderer);
         // If we return NULL it is seen as an error, so use this for
         // None returns
@@ -332,10 +332,10 @@
 bool
 initModulePart_RRClass(PyObject* mod) {
     // Add the exceptions to the module
-    po_InvalidRRClass = PyErr_NewException("libdns_python.InvalidRRClass", NULL, NULL);
+    po_InvalidRRClass = PyErr_NewException("pydnspp.InvalidRRClass", NULL, NULL);
     Py_INCREF(po_InvalidRRClass);
     PyModule_AddObject(mod, "InvalidRRClass", po_InvalidRRClass);
-    po_IncompleteRRClass = PyErr_NewException("libdns_python.IncompleteRRClass", NULL, NULL);
+    po_IncompleteRRClass = PyErr_NewException("pydnspp.IncompleteRRClass", NULL, NULL);
     Py_INCREF(po_IncompleteRRClass);
     PyModule_AddObject(mod, "IncompleteRRClass", po_IncompleteRRClass);
 

Modified: branches/trac311/src/lib/dns/python/rrset_python.cc
==============================================================================
--- branches/trac311/src/lib/dns/python/rrset_python.cc (original)
+++ branches/trac311/src/lib/dns/python/rrset_python.cc Sun Sep 26 03:25:19 2010
@@ -94,7 +94,7 @@
 
 static PyTypeObject rrset_type = {
     PyVarObject_HEAD_INIT(NULL, 0)
-    "libdns_python.RRset",
+    "pydnspp.RRset",
     sizeof(s_RRset),                    // tp_basicsize
     0,                                  // tp_itemsize
     (destructor)RRset_destroy,          // tp_dealloc
@@ -315,7 +315,7 @@
             // to prevent memory leak
             Py_DECREF(n);
             return (result);
-        } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, (PyObject**) &mr)) {
+        } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
             self->rrset->toWire(*mr->messagerenderer);
             // If we return NULL it is seen as an error, so use this for
             // None returns
@@ -379,7 +379,7 @@
 bool
 initModulePart_RRset(PyObject* mod) {
     // Add the exceptions to the module
-    po_EmptyRRset = PyErr_NewException("libdns_python.EmptyRRset", NULL, NULL);
+    po_EmptyRRset = PyErr_NewException("pydnspp.EmptyRRset", NULL, NULL);
     PyModule_AddObject(mod, "EmptyRRset", po_EmptyRRset);
 
     // Add the enums to the module

Modified: branches/trac311/src/lib/dns/python/rrttl_python.cc
==============================================================================
--- branches/trac311/src/lib/dns/python/rrttl_python.cc (original)
+++ branches/trac311/src/lib/dns/python/rrttl_python.cc Sun Sep 26 03:25:19 2010
@@ -91,7 +91,7 @@
 // Most of the functions are not actually implemented and NULL here.
 static PyTypeObject rrttl_type = {
     PyVarObject_HEAD_INIT(NULL, 0)
-    "libdns_python.RRTTL",
+    "pydnspp.RRTTL",
     sizeof(s_RRTTL),                    // tp_basicsize
     0,                                  // tp_itemsize
     (destructor)RRTTL_destroy,          // tp_dealloc
@@ -235,7 +235,7 @@
         // to prevent memory leak
         Py_DECREF(n);
         return (result);
-    } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, (PyObject**) &mr)) {
+    } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
         self->rrttl->toWire(*mr->messagerenderer);
         // If we return NULL it is seen as an error, so use this for
         // None returns
@@ -296,9 +296,9 @@
 bool
 initModulePart_RRTTL(PyObject* mod) {
     // Add the exceptions to the module
-    po_InvalidRRTTL = PyErr_NewException("libdns_python.InvalidRRTTL", NULL, NULL);
+    po_InvalidRRTTL = PyErr_NewException("pydnspp.InvalidRRTTL", NULL, NULL);
     PyModule_AddObject(mod, "InvalidRRTTL", po_InvalidRRTTL);
-    po_IncompleteRRTTL = PyErr_NewException("libdns_python.IncompleteRRTTL", NULL, NULL);
+    po_IncompleteRRTTL = PyErr_NewException("pydnspp.IncompleteRRTTL", NULL, NULL);
     PyModule_AddObject(mod, "IncompleteRRTTL", po_IncompleteRRTTL);
 
     // We initialize the static description object with PyType_Ready(),

Modified: branches/trac311/src/lib/dns/python/rrtype_python.cc
==============================================================================
--- branches/trac311/src/lib/dns/python/rrtype_python.cc (original)
+++ branches/trac311/src/lib/dns/python/rrtype_python.cc Sun Sep 26 03:25:19 2010
@@ -130,7 +130,7 @@
 // Most of the functions are not actually implemented and NULL here.
 static PyTypeObject rrtype_type = {
     PyVarObject_HEAD_INIT(NULL, 0)
-    "libdns_python.RRType",
+    "pydnspp.RRType",
     sizeof(s_RRType),                   // tp_basicsize
     0,                                  // tp_itemsize
     (destructor)RRType_destroy,         // tp_dealloc
@@ -186,8 +186,8 @@
     const char* s;
     unsigned int i;
     PyObject* bytes = NULL;
-    // The constructor argument can be a string ("IN"), an integer (1),
-    // or a sequence of numbers between 0 and 255 (wire code)
+    // The constructor argument can be a string ("A"), an integer (1),
+    // or a sequence of numbers between 0 and 65535 (wire code)
 
     // Note that PyArg_ParseType can set PyError, and we need to clear
     // that if we try several like here. Otherwise the *next* python
@@ -200,7 +200,7 @@
         } else if (PyArg_ParseTuple(args, "I", &i)) {
             PyErr_Clear();
             if (i > 65535) {
-                PyErr_SetString(po_InvalidRRType, "Class number too high");
+                PyErr_SetString(po_InvalidRRType, "RR Type number too high");
                 return (-1);
             }
             self->rrtype = new RRType(i);
@@ -273,7 +273,7 @@
         // to prevent memory leak
         Py_DECREF(n);
         return (result);
-    } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, (PyObject**) &mr)) {
+    } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
         self->rrtype->toWire(*mr->messagerenderer);
         // If we return NULL it is seen as an error, so use this for
         // None returns
@@ -446,9 +446,9 @@
 bool
 initModulePart_RRType(PyObject* mod) {
     // Add the exceptions to the module
-    po_InvalidRRType = PyErr_NewException("libdns_python.InvalidRRType", NULL, NULL);
+    po_InvalidRRType = PyErr_NewException("pydnspp.InvalidRRType", NULL, NULL);
     PyModule_AddObject(mod, "InvalidRRType", po_InvalidRRType);
-    po_IncompleteRRType = PyErr_NewException("libdns_python.IncompleteRRType", NULL, NULL);
+    po_IncompleteRRType = PyErr_NewException("pydnspp.IncompleteRRType", NULL, NULL);
     PyModule_AddObject(mod, "IncompleteRRType", po_IncompleteRRType);
 
     // We initialize the static description object with PyType_Ready(),

Modified: branches/trac311/src/lib/dns/python/tests/message_python_test.py
==============================================================================
--- branches/trac311/src/lib/dns/python/tests/message_python_test.py (original)
+++ branches/trac311/src/lib/dns/python/tests/message_python_test.py Sun Sep 26 03:25:19 2010
@@ -14,12 +14,12 @@
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 #
-# Tests for the message part of the libdns_python module
+# Tests for the message part of the pydnspp module
 #
 
 import unittest
 import os
-from libdns_python import *
+from pydnspp import *
 from testutil import *
 
 class MessageFlagTest(unittest.TestCase):

Modified: branches/trac311/src/lib/dns/python/tests/messagerenderer_python_test.py
==============================================================================
--- branches/trac311/src/lib/dns/python/tests/messagerenderer_python_test.py (original)
+++ branches/trac311/src/lib/dns/python/tests/messagerenderer_python_test.py Sun Sep 26 03:25:19 2010
@@ -14,12 +14,12 @@
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 #
-# Tests for the messagerenderer part of the libdns_python module
+# Tests for the messagerenderer part of the pydnspp module
 #
 
 import unittest
 import os
-from libdns_python import *
+from pydnspp import *
 
 class MessageRendererTest(unittest.TestCase):
 

Modified: branches/trac311/src/lib/dns/python/tests/name_python_test.py
==============================================================================
--- branches/trac311/src/lib/dns/python/tests/name_python_test.py (original)
+++ branches/trac311/src/lib/dns/python/tests/name_python_test.py Sun Sep 26 03:25:19 2010
@@ -14,12 +14,12 @@
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 #
-# Tests for the messagerenderer part of the libdns_python module
+# Tests for the messagerenderer part of the pydnspp module
 #
 
 import unittest
 import os
-from libdns_python import *
+from pydnspp import *
 
 class NameComparisonTest(unittest.TestCase):
     def setUp(self):

Modified: branches/trac311/src/lib/dns/python/tests/question_python_test.py
==============================================================================
--- branches/trac311/src/lib/dns/python/tests/question_python_test.py (original)
+++ branches/trac311/src/lib/dns/python/tests/question_python_test.py Sun Sep 26 03:25:19 2010
@@ -14,12 +14,12 @@
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 #
-# Tests for the rrtype part of the libdns_python module
+# Tests for the rrtype part of the pydnspp module
 #
 
 import unittest
 import os
-from libdns_python import *
+from pydnspp import *
 from testutil import *
 
 if "TESTDATA_PATH" in os.environ:

Modified: branches/trac311/src/lib/dns/python/tests/rdata_python_test.py
==============================================================================
--- branches/trac311/src/lib/dns/python/tests/rdata_python_test.py (original)
+++ branches/trac311/src/lib/dns/python/tests/rdata_python_test.py Sun Sep 26 03:25:19 2010
@@ -14,12 +14,12 @@
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 #
-# Tests for the rdata part of the libdns_python module
+# Tests for the rdata part of the pydnspp module
 #
 
 import unittest
 import os
-from libdns_python import *
+from pydnspp import *
 
 class RdataTest(unittest.TestCase):
     def setUp(self):

Modified: branches/trac311/src/lib/dns/python/tests/rrclass_python_test.py
==============================================================================
--- branches/trac311/src/lib/dns/python/tests/rrclass_python_test.py (original)
+++ branches/trac311/src/lib/dns/python/tests/rrclass_python_test.py Sun Sep 26 03:25:19 2010
@@ -14,12 +14,12 @@
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 #
-# Tests for the rrclass part of the libdns_python module
+# Tests for the rrclass part of the pydnspp module
 #
 
 import unittest
 import os
-from libdns_python import *
+from pydnspp import *
 
 class RRClassTest(unittest.TestCase):
     def setUp(self):

Modified: branches/trac311/src/lib/dns/python/tests/rrset_python_test.py
==============================================================================
--- branches/trac311/src/lib/dns/python/tests/rrset_python_test.py (original)
+++ branches/trac311/src/lib/dns/python/tests/rrset_python_test.py Sun Sep 26 03:25:19 2010
@@ -14,12 +14,12 @@
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 #
-# Tests for the rrtype part of the libdns_python module
+# Tests for the rrtype part of the pydnspp module
 #
 
 import unittest
 import os
-from libdns_python import *
+from pydnspp import *
 
 class TestModuleSpec(unittest.TestCase):
     

Modified: branches/trac311/src/lib/dns/python/tests/rrttl_python_test.py
==============================================================================
--- branches/trac311/src/lib/dns/python/tests/rrttl_python_test.py (original)
+++ branches/trac311/src/lib/dns/python/tests/rrttl_python_test.py Sun Sep 26 03:25:19 2010
@@ -14,12 +14,12 @@
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 #
-# Tests for the rrttl part of the libdns_python module
+# Tests for the rrttl part of the pydnspp module
 #
 
 import unittest
 import os
-from libdns_python import *
+from pydnspp import *
 
 class RRTTLTest(unittest.TestCase):
     def setUp(self):

Modified: branches/trac311/src/lib/dns/python/tests/rrtype_python_test.py
==============================================================================
--- branches/trac311/src/lib/dns/python/tests/rrtype_python_test.py (original)
+++ branches/trac311/src/lib/dns/python/tests/rrtype_python_test.py Sun Sep 26 03:25:19 2010
@@ -14,12 +14,12 @@
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 #
-# Tests for the rrtype part of the libdns_python module
+# Tests for the rrtype part of the pydnspp module
 #
 
 import unittest
 import os
-from libdns_python import *
+from pydnspp import *
 
 class TestModuleSpec(unittest.TestCase):
     

Modified: branches/trac311/src/lib/dns/rrset.h
==============================================================================
--- branches/trac311/src/lib/dns/rrset.h (original)
+++ branches/trac311/src/lib/dns/rrset.h Sun Sep 26 03:25:19 2010
@@ -692,8 +692,8 @@
     /// \brief Adds an RRSIG RR to this RRset's signatures
     virtual void addRRsig(const rdata::RdataPtr rdata) {
         if (!rrsig_) {
-            rrsig_ = RRsetPtr(new RRset(this->getName(), this->getClass(),
-                                        RRType::RRSIG(), this->getTTL()));
+            rrsig_ = RRsetPtr(new RRset(getName(), getClass(),
+                                        RRType::RRSIG(), getTTL()));
         }
         rrsig_->addRdata(rdata);
     }
@@ -703,8 +703,8 @@
         RdataIteratorPtr it = sigs.getRdataIterator();
 
         if (!rrsig_) {
-            rrsig_ = RRsetPtr(new RRset(this->getName(), this->getClass(),
-                                        RRType::RRSIG(), this->getTTL()));
+            rrsig_ = RRsetPtr(new RRset(getName(), getClass(),
+                                        RRType::RRSIG(), getTTL()));
         }
 
         for (it->first(); !it->isLast(); it->next()) {

Modified: branches/trac311/src/lib/python/isc/cc/Makefile.am
==============================================================================
--- branches/trac311/src/lib/python/isc/cc/Makefile.am (original)
+++ branches/trac311/src/lib/python/isc/cc/Makefile.am Sun Sep 26 03:25:19 2010
@@ -1,4 +1,4 @@
-SUBDIRS = tests
+SUBDIRS = . tests
 
 python_PYTHON =	__init__.py data.py session.py message.py
 

Modified: branches/trac311/src/lib/python/isc/cc/session.py
==============================================================================
--- branches/trac311/src/lib/python/isc/cc/session.py (original)
+++ branches/trac311/src/lib/python/isc/cc/session.py Sun Sep 26 03:25:19 2010
@@ -16,6 +16,7 @@
 import sys
 import socket
 import struct
+import errno
 import os
 import threading
 import bind10_config
@@ -25,21 +26,21 @@
 class ProtocolError(Exception): pass
 class NetworkError(Exception): pass
 class SessionError(Exception): pass
+class SessionTimeout(Exception): pass
 
 class Session:
+    MSGQ_DEFAULT_TIMEOUT = 4000
+    
     def __init__(self, socket_file=None):
         self._socket = None
-        # store the current timeout value in seconds (the way
-        # settimeout() wants them, our API takes milliseconds
-        # so that it is consistent with the C++ version)
-        self._socket_timeout = 4;
         self._lname = None
-        self._recvbuffer = bytearray()
-        self._recvlength = 0
         self._sequence = 1
         self._closed = False
         self._queue = []
         self._lock = threading.RLock()
+        self.set_timeout(self.MSGQ_DEFAULT_TIMEOUT);
+        self._recv_len_size = 0
+        self._recv_size = 0
 
         if socket_file is None:
             if "BIND10_MSGQ_SOCKET_FILE" in os.environ:
@@ -121,6 +122,43 @@
                     return isc.cc.message.from_wire(data[2:header_length+2]), None
             return None, None
 
+    def _receive_bytes(self, size):
+        """Try to get size bytes of data from the socket.
+           Raises a ProtocolError if the size is 0.
+           Raises any error from recv().
+           Returns whatever data was available (if >0 bytes).
+           """
+        data = self._socket.recv(size)
+        if len(data) == 0: # server closed connection
+            raise ProtocolError("Read of 0 bytes: connection closed")
+        return data
+        
+    def _receive_len_data(self):
+        """Reads self._recv_len_size bytes of data from the socket into
+           self._recv_len_data
+           This is done through class variables so in the case of
+           an EAGAIN we can continue on a subsequent call.
+           Raises a ProtocolError, a socket.error (which may be
+           timeout or eagain), or reads until we have all data we need.
+           """
+        while self._recv_len_size > 0:
+            new_data = self._receive_bytes(self._recv_len_size)
+            self._recv_len_data += new_data
+            self._recv_len_size -= len(new_data)
+
+    def _receive_data(self):
+        """Reads self._recv_size bytes of data from the socket into
+           self._recv_data.
+           This is done through class variables so in the case of
+           an EAGAIN we can continue on a subsequent call.
+           Raises a ProtocolError, a socket.error (which may be
+           timeout or eagain), or reads until we have all data we need.
+        """
+        while self._recv_size > 0:
+            new_data = self._receive_bytes(self._recv_size)
+            self._recv_data += new_data
+            self._recv_size -= len(new_data)
+
     def _receive_full_buffer(self, nonblock):
         if nonblock:
             self._socket.setblocking(0)
@@ -131,35 +169,47 @@
             else:
                 self._socket.settimeout(self._socket_timeout)
 
-        if self._recvlength == 0:
-            length = 4
-            length -= len(self._recvbuffer)
-            try:
-                data = self._socket.recv(length)
-            except:
+        try:
+            # we might be in a call following an EAGAIN, in which case
+            # we simply continue. In the first case, either
+            # recv_size or recv_len size are not zero
+            # they may never both be non-zero (we are either starting
+            # a full read, or continuing one of the reads
+            assert self._recv_size == 0 or self._recv_len_size == 0
+            
+            if self._recv_size == 0:
+                if self._recv_len_size == 0:
+                    # both zero, start a new full read
+                    self._recv_len_size = 4
+                    self._recv_len_data = bytearray()
+                self._receive_len_data()
+
+                self._recv_size = struct.unpack('>I', self._recv_len_data)[0]
+                self._recv_data = bytearray()
+            self._receive_data()
+
+            # no EAGAIN, so copy data and reset internal counters
+            data = self._recv_data
+
+            self._recv_len_size = 0
+            self._recv_size = 0
+
+            return (data)
+
+        except socket.timeout:
+            raise SessionTimeout("recv() on cc session timed out")
+        except socket.error as se:
+            # Only keep data in case of EAGAIN
+            if se.errno == errno.EAGAIN:
                 return None
-            if data == "": # server closed connection
-                raise ProtocolError("Read of 0 bytes: connection closed")
-            self._recvbuffer += data
-            if len(self._recvbuffer) < 4:
+            # unknown state otherwise, best to drop data
+            self._recv_len_size = 0
+            self._recv_size = 0
+            # ctrl-c can result in EINTR, return None to prevent
+            # stacktrace output
+            if se.errno == errno.EINTR:
                 return None
-            self._recvlength = struct.unpack('>I', self._recvbuffer)[0]
-            self._recvbuffer = bytearray()
-
-        length = self._recvlength - len(self._recvbuffer)
-        while (length > 0):
-            try:
-                data = self._socket.recv(length)
-            except:
-                return None
-            if data == "": # server closed connection
-                raise ProtocolError("Read of 0 bytes: connection closed")
-            self._recvbuffer += data
-            length -= len(data)
-        data = self._recvbuffer
-        self._recvbuffer = bytearray()
-        self._recvlength = 0
-        return (data)
+            raise se
 
     def _next_sequence(self):
         self._sequence += 1

Modified: branches/trac311/src/lib/python/isc/cc/tests/Makefile.am
==============================================================================
--- branches/trac311/src/lib/python/isc/cc/tests/Makefile.am (original)
+++ branches/trac311/src/lib/python/isc/cc/tests/Makefile.am Sun Sep 26 03:25:19 2010
@@ -12,5 +12,5 @@
 	echo Running test: $$pytest ; \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python \
 	BIND10_TEST_SOCKET_FILE=$(builddir)/test_socket.sock \
-	$(PYCOVERAGE) $(abs_srcdir)/$$pytest ; \
+	$(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
 	done

Modified: branches/trac311/src/lib/python/isc/cc/tests/session_test.py
==============================================================================
--- branches/trac311/src/lib/python/isc/cc/tests/session_test.py (original)
+++ branches/trac311/src/lib/python/isc/cc/tests/session_test.py Sun Sep 26 03:25:19 2010
@@ -28,6 +28,7 @@
         self.type = type
         self.recvqueue = bytearray()
         self.sendqueue = bytearray()
+        self._blocking = True
 
     def connect(self, to):
         pass
@@ -36,7 +37,7 @@
         pass
 
     def setblocking(self, val):
-        pass
+        self._blocking = val
 
     def send(self, data):
         self.sendqueue.extend(data);
@@ -67,6 +68,11 @@
         return result
 
     def recv(self, length):
+        if len(self.recvqueue) == 0:
+            if self._blocking:
+                return bytes()
+            else:
+                raise socket.error(errno.EAGAIN, "Resource temporarily unavailable")
         if length > len(self.recvqueue):
             raise Exception("Buffer underrun in test, does the test provide the right data?")
         result = self.recvqueue[:length]
@@ -105,7 +111,8 @@
         self._socket_timeout = 1
         self._lname = None
         self._recvbuffer = bytearray()
-        self._recvlength = 0
+        self._recv_len_size = 0
+        self._recv_size = 0
         self._sequence = 1
         self._closed = False
         self._queue = []
@@ -192,10 +199,10 @@
         # get no message without asking for a specific sequence number reply
         self.assertFalse(sess.has_queued_msgs())
         sess._socket.addrecv({'to': 'someone', 'reply': 1}, {"hello": "a"})
-        env, msg = sess.recvmsg(False)
+        env, msg = sess.recvmsg(True)
         self.assertEqual(None, env)
         self.assertTrue(sess.has_queued_msgs())
-        env, msg = sess.recvmsg(False, 1)
+        env, msg = sess.recvmsg(True, 1)
         self.assertEqual({'to': 'someone', 'reply': 1}, env)
         self.assertEqual({"hello": "a"}, msg)
         self.assertFalse(sess.has_queued_msgs())
@@ -204,11 +211,11 @@
         # then ask for the one that is there
         self.assertFalse(sess.has_queued_msgs())
         sess._socket.addrecv({'to': 'someone', 'reply': 1}, {"hello": "a"})
-        env, msg = sess.recvmsg(False, 2)
+        env, msg = sess.recvmsg(True, 2)
         self.assertEqual(None, env)
         self.assertEqual(None, msg)
         self.assertTrue(sess.has_queued_msgs())
-        env, msg = sess.recvmsg(False, 1)
+        env, msg = sess.recvmsg(True, 1)
         self.assertEqual({'to': 'someone', 'reply': 1}, env)
         self.assertEqual({"hello": "a"}, msg)
         self.assertFalse(sess.has_queued_msgs())
@@ -217,11 +224,11 @@
         # then ask for any message
         self.assertFalse(sess.has_queued_msgs())
         sess._socket.addrecv({'to': 'someone', 'reply': 1}, {"hello": "a"})
-        env, msg = sess.recvmsg(False, 2)
+        env, msg = sess.recvmsg(True, 2)
         self.assertEqual(None, env)
         self.assertEqual(None, msg)
         self.assertTrue(sess.has_queued_msgs())
-        env, msg = sess.recvmsg(False, 1)
+        env, msg = sess.recvmsg(True, 1)
         self.assertEqual({'to': 'someone', 'reply': 1}, env)
         self.assertEqual({"hello": "a"}, msg)
         self.assertFalse(sess.has_queued_msgs())
@@ -233,16 +240,16 @@
         # then ask for any message (get the second)
         self.assertFalse(sess.has_queued_msgs())
         sess._socket.addrecv({'to': 'someone', 'reply': 1}, {'hello': 'a'})
-        env, msg = sess.recvmsg(False, 2)
+        env, msg = sess.recvmsg(True, 2)
         self.assertEqual(None, env)
         self.assertEqual(None, msg)
         self.assertTrue(sess.has_queued_msgs())
         sess._socket.addrecv({'to': 'someone' }, {'hello': 'b'})
-        env, msg = sess.recvmsg(False, 1)
+        env, msg = sess.recvmsg(True, 1)
         self.assertEqual({'to': 'someone', 'reply': 1 }, env)
         self.assertEqual({"hello": "a"}, msg)
         self.assertFalse(sess.has_queued_msgs())
-        env, msg = sess.recvmsg(False)
+        env, msg = sess.recvmsg(True)
         self.assertEqual({'to': 'someone'}, env)
         self.assertEqual({"hello": "b"}, msg)
         self.assertFalse(sess.has_queued_msgs())
@@ -253,11 +260,11 @@
         self.assertFalse(sess.has_queued_msgs())
         sess._socket.addrecv({'to': 'someone' }, {'hello': 'b'})
         sess._socket.addrecv({'to': 'someone', 'reply': 1}, {'hello': 'a'})
-        env, msg = sess.recvmsg(False, 1)
+        env, msg = sess.recvmsg(True, 1)
         self.assertEqual({'to': 'someone', 'reply': 1}, env)
         self.assertEqual({"hello": "a"}, msg)
         self.assertTrue(sess.has_queued_msgs())
-        env, msg = sess.recvmsg(False)
+        env, msg = sess.recvmsg(True)
         self.assertEqual({'to': 'someone'}, env)
         self.assertEqual({"hello": "b"}, msg)
         self.assertFalse(sess.has_queued_msgs())
@@ -344,17 +351,19 @@
         if os.path.exists(TEST_SOCKET_FILE):
             os.remove(TEST_SOCKET_FILE)
         s1.bind(TEST_SOCKET_FILE)
-        s1.listen(1)
-
-        s2 = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-        s2.connect(TEST_SOCKET_FILE)
-        sess = MySession(1, s2)
-        # set timeout to 100 msec, so test does not take too long
-        sess.set_timeout(100)
-        env, msg = sess.group_recvmsg(False)
-        self.assertEqual(None, env)
-        self.assertEqual(None, msg)
-        
+
+        try:
+            s1.listen(1)
+
+            s2 = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+            s2.connect(TEST_SOCKET_FILE)
+            sess = MySession(1, s2)
+            # set timeout to 100 msec, so test does not take too long
+            sess.set_timeout(100)
+            self.assertRaises(SessionTimeout, sess.group_recvmsg, False)
+        finally:
+            os.remove(TEST_SOCKET_FILE)
+
 if __name__ == "__main__":
     unittest.main()
 

Modified: branches/trac311/src/lib/python/isc/config/Makefile.am
==============================================================================
--- branches/trac311/src/lib/python/isc/config/Makefile.am (original)
+++ branches/trac311/src/lib/python/isc/config/Makefile.am Sun Sep 26 03:25:19 2010
@@ -1,4 +1,4 @@
-SUBDIRS = tests
+SUBDIRS = . tests
 
 python_PYTHON = __init__.py ccsession.py cfgmgr.py config_data.py module_spec.py
 

Modified: branches/trac311/src/lib/python/isc/config/ccsession.py
==============================================================================
--- branches/trac311/src/lib/python/isc/config/ccsession.py (original)
+++ branches/trac311/src/lib/python/isc/config/ccsession.py Sun Sep 26 03:25:19 2010
@@ -177,10 +177,14 @@
     def check_command(self):
         """Check whether there is a command or configuration update
            on the channel. Call the corresponding callback function if
-           there is."""
-        msg, env = self._session.group_recvmsg(False)
+           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)
+        
         # should we default to an answer? success-by-default? unhandled error?
-        if msg and not 'result' in msg:
+        if msg is not None and not 'result' in msg:
             answer = None
             try:
                 module_name = env['group']
@@ -244,6 +248,8 @@
            also subscribes to the channel of the remote module name
            to receive the relevant updates. It is not possible to
            specify your own handler for this right now.
+           start() must have been called on this CCSession
+           prior to the call to this method.
            Returns the name of the module."""
         module_spec = isc.config.module_spec_from_file(spec_file_name)
         module_cfg = ConfigData(module_spec)
@@ -252,7 +258,13 @@
 
         # Get the current config for that module now
         seq = self._session.group_sendmsg(create_command(COMMAND_GET_CONFIG, { "module_name": module_name }), "ConfigManager")
-        answer, env = self._session.group_recvmsg(False, seq)
+
+        try:
+            answer, env = self._session.group_recvmsg(False, seq)
+        except isc.cc.SessionTimeout:
+            raise ModuleCCSessionError("No answer from ConfigManager when "
+                                       "asking about Remote module " +
+                                       module_name)
         if answer:
             rcode, value = parse_answer(answer)
             if rcode == 0:
@@ -283,25 +295,32 @@
         """Sends the data specification to the configuration manager"""
         msg = create_command(COMMAND_MODULE_SPEC, self.get_module_spec().get_full_spec())
         seq = self._session.group_sendmsg(msg, "ConfigManager")
-        answer, env = self._session.group_recvmsg(False, seq)
+        try:
+            answer, env = self._session.group_recvmsg(False, seq)
+        except isc.cc.SessionTimeout:
+            # TODO: log an error?
+            pass
         
     def __request_config(self):
         """Asks the configuration manager for the current configuration, and call the config handler if set.
            Raises a ModuleCCSessionError if there is no answer from the configuration manager"""
         seq = self._session.group_sendmsg(create_command(COMMAND_GET_CONFIG, { "module_name": self._module_name }), "ConfigManager")
-        answer, env = self._session.group_recvmsg(False, seq)
-        if answer:
-            rcode, value = parse_answer(answer)
-            if rcode == 0:
-                if value != None and self.get_module_spec().validate_config(False, value):
-                    self.set_local_config(value);
-                    if self._config_handler:
-                        self._config_handler(value)
+        try:
+            answer, env = self._session.group_recvmsg(False, seq)
+            if answer:
+                rcode, value = parse_answer(answer)
+                if rcode == 0:
+                    if value != None and self.get_module_spec().validate_config(False, value):
+                        self.set_local_config(value);
+                        if self._config_handler:
+                            self._config_handler(value)
+                else:
+                    # log error
+                    print("[" + self._module_name + "] Error requesting configuration: " + value)
             else:
-                # log error
-                print("[" + self._module_name + "] Error requesting configuration: " + value)
-        else:
-            raise ModuleCCSessionError("No answer from configuration manager")
+                raise ModuleCCSessionError("No answer from configuration manager")
+        except isc.cc.SessionTimeout:
+            raise ModuleCCSessionError("CC Session timeout waiting for configuration manager")
 
 
 class UIModuleCCSession(MultiConfigData):

Modified: branches/trac311/src/lib/python/isc/config/cfgmgr.py
==============================================================================
--- branches/trac311/src/lib/python/isc/config/cfgmgr.py (original)
+++ branches/trac311/src/lib/python/isc/config/cfgmgr.py Sun Sep 26 03:25:19 2010
@@ -283,7 +283,10 @@
             update_cmd = ccsession.create_command(ccsession.COMMAND_CONFIG_UPDATE,
                                                   conf_part)
             seq = self.cc.group_sendmsg(update_cmd, module_name)
-            answer, env = self.cc.group_recvmsg(False, seq)
+            try:
+                answer, env = self.cc.group_recvmsg(False, seq)
+            except isc.cc.SessionTimeout:
+                answer = ccsession.create_answer(1, "Timeout waiting for answer from " + module_name)
         else:
             conf_part = data.set(self.config.data, module_name, {})
             data.merge(conf_part[module_name], cmd[1])
@@ -292,7 +295,10 @@
                                                   conf_part[module_name])
             seq = self.cc.group_sendmsg(update_cmd, module_name)
             # replace 'our' answer with that of the module
-            answer, env = self.cc.group_recvmsg(False, seq)
+            try:
+                answer, env = self.cc.group_recvmsg(False, seq)
+            except isc.cc.SessionTimeout:
+                answer = ccsession.create_answer(1, "Timeout waiting for answer from " + module_name)
         if answer:
             rcode, val = ccsession.parse_answer(answer)
             if rcode == 0:
@@ -313,15 +319,19 @@
                 update_cmd = ccsession.create_command(ccsession.COMMAND_CONFIG_UPDATE,
                                                       self.config.data[module])
                 seq = self.cc.group_sendmsg(update_cmd, module)
-                answer, env = self.cc.group_recvmsg(False, seq)
-                if answer == None:
+                try:
+                    answer, env = self.cc.group_recvmsg(False, seq)
+                    if answer == None:
+                        got_error = True
+                        err_list.append("No answer message from " + module)
+                    else:
+                        rcode, val = ccsession.parse_answer(answer)
+                        if rcode != 0:
+                            got_error = True
+                            err_list.append(val)
+                except isc.cc.SessionTimeout:
                     got_error = True
-                    err_list.append("No answer message from " + module)
-                else:
-                    rcode, val = ccsession.parse_answer(answer)
-                    if rcode != 0:
-                        got_error = True
-                        err_list.append(val)
+                    err_list.append("CC Timeout waiting on answer message from " + module)
         if not got_error:
             self.write_config()
             return ccsession.create_answer(0)
@@ -394,8 +404,13 @@
         """Runs the configuration manager."""
         self.running = True
         while (self.running):
+            # we just wait eternally for any command here, so disable
+            # timeouts for this specific recv
+            self.cc.set_timeout(0)
             msg, env = self.cc.group_recvmsg(False)
-            # ignore 'None' value (current result of timeout)
+            # and set it back to whatever we default to
+            self.cc.set_timeout(isc.cc.Session.MSGQ_DEFAULT_TIMEOUT)
+            # ignore 'None' value (even though they should not occur)
             # and messages that are answers to questions we did
             # not ask
             if msg is not None and not 'result' in msg:

Modified: branches/trac311/src/lib/python/isc/config/tests/Makefile.am
==============================================================================
--- branches/trac311/src/lib/python/isc/config/tests/Makefile.am (original)
+++ branches/trac311/src/lib/python/isc/config/tests/Makefile.am Sun Sep 26 03:25:19 2010
@@ -7,12 +7,10 @@
 PYCOVERAGE = $(PYTHON)
 # test using command-line arguments, so use check-local target instead of TESTS
 check-local:
-	ret=0 ; \
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python \
 	CONFIG_TESTDATA_PATH=$(abs_top_srcdir)/src/lib/config/testdata \
 	CONFIG_WR_TESTDATA_PATH=$(abs_top_builddir)/src/lib/config/testdata \
-	$(PYCOVERAGE) $(abs_srcdir)/$$pytest || ret=1; \
-	done; \
-	exit $$ret
+	$(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
+	done

Modified: branches/trac311/src/lib/python/isc/config/tests/unittest_fakesession.py
==============================================================================
--- branches/trac311/src/lib/python/isc/config/tests/unittest_fakesession.py (original)
+++ branches/trac311/src/lib/python/isc/config/tests/unittest_fakesession.py Sun Sep 26 03:25:19 2010
@@ -1,4 +1,21 @@
+# Copyright (C) 2010  Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and 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 INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM 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.
 
+# $Id$
+
+import isc
 
 #
 # We can probably use a more general version of this
@@ -9,6 +26,10 @@
         # each entry is of the form [ channel, instance, message ]
         self.message_queue = []
         self._socket = "ok we just need something not-None here atm"
+        # if self.timeout is set to anything other than 0, and
+        # the message_queue is empty when receive is called, throw
+        # a SessionTimeout
+        self._timeout = 0
 
     def group_subscribe(self, group_name, instance_name = None):
         if not group_name in self.subscriptions:
@@ -48,7 +69,11 @@
             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]}
-        return None, None
+        if self._timeout == 0:
+            return None, None
+        else:
+            raise isc.cc.SessionTimeout("Timeout set but no data to "
+                                 "return to group_recvmsg()")
 
     def get_message(self, channel, target = None):
         for qm in self.message_queue:
@@ -60,4 +85,6 @@
     def close(self):
         # need to pass along somehow that this function has been called,
         self._socket = "closed"
-        pass
+
+    def set_timeout(self, timeout):
+        self._timeout = timeout

Modified: branches/trac311/src/lib/python/isc/dns/__init__.py
==============================================================================
--- branches/trac311/src/lib/python/isc/dns/__init__.py (original)
+++ branches/trac311/src/lib/python/isc/dns/__init__.py Sun Sep 26 03:25:19 2010
@@ -1,1 +1,1 @@
-from libdns_python_name import *
+from pydnspp import *

Modified: branches/trac311/src/lib/python/isc/log/Makefile.am
==============================================================================
--- branches/trac311/src/lib/python/isc/log/Makefile.am (original)
+++ branches/trac311/src/lib/python/isc/log/Makefile.am Sun Sep 26 03:25:19 2010
@@ -1,4 +1,4 @@
-SUBDIRS = tests
+SUBDIRS = . tests
 
 python_PYTHON = __init__.py log.py
 

Modified: branches/trac311/src/lib/python/isc/log/tests/Makefile.am
==============================================================================
--- branches/trac311/src/lib/python/isc/log/tests/Makefile.am (original)
+++ branches/trac311/src/lib/python/isc/log/tests/Makefile.am Sun Sep 26 03:25:19 2010
@@ -8,5 +8,5 @@
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/python/isc/log \
-	$(PYCOVERAGE) $(abs_srcdir)/$$pytest ; \
+	$(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
 	done

Modified: branches/trac311/src/lib/python/isc/log/tests/log_test.py
==============================================================================
--- branches/trac311/src/lib/python/isc/log/tests/log_test.py (original)
+++ branches/trac311/src/lib/python/isc/log/tests/log_test.py Sun Sep 26 03:25:19 2010
@@ -1,3 +1,22 @@
+# Copyright (C) 2010  Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and 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 INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM 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.
+
+#
+# Tests for the python logging module
+#
+
 from isc.log.log import *
 import unittest
 import os

Modified: branches/trac311/src/lib/python/isc/notify/Makefile.am
==============================================================================
--- branches/trac311/src/lib/python/isc/notify/Makefile.am (original)
+++ branches/trac311/src/lib/python/isc/notify/Makefile.am Sun Sep 26 03:25:19 2010
@@ -1,4 +1,4 @@
-SUBDIRS = tests
+SUBDIRS = . tests
 
 python_PYTHON = __init__.py notify_out.py
 

Modified: branches/trac311/src/lib/python/isc/notify/notify_out.py
==============================================================================
--- branches/trac311/src/lib/python/isc/notify/notify_out.py (original)
+++ branches/trac311/src/lib/python/isc/notify/notify_out.py Sun Sep 26 03:25:19 2010
@@ -22,7 +22,7 @@
 from isc.datasrc import sqlite3_ds
 import isc
 try: 
-    from libdns_python import * 
+    from pydnspp import * 
 except ImportError as e: 
     # C++ loadable module may not be installed; 
     sys.stderr.write('[b10-xfrout] failed to import DNS or XFR module: %s\n' % str(e)) 
@@ -256,7 +256,7 @@
     def _zone_notify_handler(self, zone_notify_info, event_type):
         '''Notify handler for one zone. The first notify message is 
         always triggered by the event "_EVENT_TIMEOUT" since when 
-        one zone prepares to notify its slaves, it's notify_timeout 
+        one zone prepares to notify its slaves, its notify_timeout 
         is set to now, which is used to trigger sending notify 
         message when dispatcher() scanning zones. '''
         tgt = zone_notify_info.get_current_notify_target()

Modified: branches/trac311/src/lib/python/isc/notify/tests/Makefile.am
==============================================================================
--- branches/trac311/src/lib/python/isc/notify/tests/Makefile.am (original)
+++ branches/trac311/src/lib/python/isc/notify/tests/Makefile.am Sun Sep 26 03:25:19 2010
@@ -16,5 +16,5 @@
 	echo Running test: $$pytest ; \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/python/.libs \
 	$(LIBRARY_PATH_PLACEHOLDER) \
-	$(PYCOVERAGE) $(abs_srcdir)/$$pytest ; \
+	$(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
 	done




More information about the bind10-changes mailing list