[svn] commit: r2849 - in /branches/trac232: ./ doc/ doc/guide/ ext/asio/ src/bin/ src/bin/auth/ 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/host/ src/bin/loadzone/tests/correct/ src/bin/loadzone/tests/error/ src/bin/msgq/ src/bin/msgq/tests/ src/bin/usermgr/ src/bin/xfrin/ src/bin/xfrin/tests/ src/bin/xfrout/ src/bin/xfrout/tests/ src/bin/zonemgr/ src/lib/ src/lib/bench/ src/lib/cc/ src/lib/cc/tests/ src/lib/config/ src/lib/config/testdata/ src/lib/config/tests/ src/lib/datasrc/ src/lib/datasrc/tests/ src/lib/datasrc/tests/testdata/ src/lib/dns/ src/lib/dns/python/ src/lib/dns/python/tests/ src/lib/dns/rdata/generic/ src/lib/dns/tests/ src/lib/dns/util/ src/lib/exceptions/ src/lib/exceptions/tests/ src/lib/python/isc/ 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/datasrc/ src/lib/python/isc/log/tests/ src/lib/python/isc/notify/ src/lib/xfr/

BIND 10 source code commits bind10-changes at lists.isc.org
Wed Sep 1 00:35:08 UTC 2010


Author: jelte
Date: Wed Sep  1 00:35:07 2010
New Revision: 2849

Log:
sync with trunk

Added:
    branches/trac232/ext/asio/README
      - copied unchanged from r2848, trunk/ext/asio/README
    branches/trac232/src/bin/auth/change_user.cc
      - copied unchanged from r2848, trunk/src/bin/auth/change_user.cc
    branches/trac232/src/bin/auth/change_user.h
      - copied unchanged from r2848, trunk/src/bin/auth/change_user.h
    branches/trac232/src/bin/auth/tests/asio_link_unittest.cc
      - copied unchanged from r2848, trunk/src/bin/auth/tests/asio_link_unittest.cc
    branches/trac232/src/bin/auth/tests/change_user_unittest.cc
      - copied unchanged from r2848, trunk/src/bin/auth/tests/change_user_unittest.cc
    branches/trac232/src/bin/zonemgr/
      - copied from r2848, trunk/src/bin/zonemgr/
    branches/trac232/src/lib/bench/
      - copied from r2848, trunk/src/lib/bench/
    branches/trac232/src/lib/cc/tests/
      - copied from r2848, trunk/src/lib/cc/tests/
    branches/trac232/src/lib/config/testdata/Makefile.am
      - copied unchanged from r2848, trunk/src/lib/config/testdata/Makefile.am
    branches/trac232/src/lib/config/testdata/b10-config-bad4.db
      - copied unchanged from r2848, trunk/src/lib/config/testdata/b10-config-bad4.db
    branches/trac232/src/lib/config/testdata/b10-config.db.master
      - copied unchanged from r2848, trunk/src/lib/config/testdata/b10-config.db.master
    branches/trac232/src/lib/config/testdata/spec28.spec
      - copied unchanged from r2848, trunk/src/lib/config/testdata/spec28.spec
    branches/trac232/src/lib/dns/tests/base32hex_unittest.cc
      - copied unchanged from r2848, trunk/src/lib/dns/tests/base32hex_unittest.cc
    branches/trac232/src/lib/dns/util/
      - copied from r2848, trunk/src/lib/dns/util/
    branches/trac232/src/lib/exceptions/tests/
      - copied from r2848, trunk/src/lib/exceptions/tests/
    branches/trac232/src/lib/python/isc/notify/
      - copied from r2848, trunk/src/lib/python/isc/notify/
Removed:
    branches/trac232/src/lib/cc/data_unittests.cc
    branches/trac232/src/lib/cc/run_unittests.cc
    branches/trac232/src/lib/cc/session_unittests.cc
    branches/trac232/src/lib/config/testdata/b10-config.db
    branches/trac232/src/lib/datasrc/tests/testdata/q_cname
    branches/trac232/src/lib/datasrc/tests/testdata/q_cname_ext
    branches/trac232/src/lib/datasrc/tests/testdata/q_cname_int
    branches/trac232/src/lib/datasrc/tests/testdata/q_dname
    branches/trac232/src/lib/datasrc/tests/testdata/q_example_dnskey
    branches/trac232/src/lib/datasrc/tests/testdata/q_example_ns
    branches/trac232/src/lib/datasrc/tests/testdata/q_example_ptr
    branches/trac232/src/lib/datasrc/tests/testdata/q_glork
    branches/trac232/src/lib/datasrc/tests/testdata/q_spork
    branches/trac232/src/lib/datasrc/tests/testdata/q_sql1
    branches/trac232/src/lib/datasrc/tests/testdata/q_subzone
    branches/trac232/src/lib/datasrc/tests/testdata/q_subzone_any
    branches/trac232/src/lib/datasrc/tests/testdata/q_subzone_dname
    branches/trac232/src/lib/datasrc/tests/testdata/q_subzone_ds
    branches/trac232/src/lib/datasrc/tests/testdata/q_subzone_ns
    branches/trac232/src/lib/datasrc/tests/testdata/q_subzone_nsec
    branches/trac232/src/lib/datasrc/tests/testdata/q_wild2_a
    branches/trac232/src/lib/datasrc/tests/testdata/q_wild2_aaaa
    branches/trac232/src/lib/datasrc/tests/testdata/q_wild3_a
    branches/trac232/src/lib/datasrc/tests/testdata/q_wild_a
    branches/trac232/src/lib/datasrc/tests/testdata/q_wild_aaaa
    branches/trac232/src/lib/dns/base32.cc
    branches/trac232/src/lib/dns/base32.h
    branches/trac232/src/lib/dns/base64.cc
    branches/trac232/src/lib/dns/base64.h
    branches/trac232/src/lib/dns/hex.cc
    branches/trac232/src/lib/dns/hex.h
    branches/trac232/src/lib/dns/sha1.cc
    branches/trac232/src/lib/dns/sha1.h
    branches/trac232/src/lib/dns/tests/base32_unittest.cc
    branches/trac232/src/lib/exceptions/exceptions_unittest.cc
    branches/trac232/src/lib/exceptions/run_unittests.cc
Modified:
    branches/trac232/   (props changed)
    branches/trac232/ChangeLog
    branches/trac232/Makefile.am
    branches/trac232/configure.ac
    branches/trac232/doc/Doxyfile
    branches/trac232/doc/guide/bind10-guide.html
    branches/trac232/doc/guide/bind10-guide.xml
    branches/trac232/src/bin/Makefile.am
    branches/trac232/src/bin/auth/Makefile.am
    branches/trac232/src/bin/auth/asio_link.cc
    branches/trac232/src/bin/auth/asio_link.h
    branches/trac232/src/bin/auth/auth.spec.pre.in
    branches/trac232/src/bin/auth/auth_srv.cc
    branches/trac232/src/bin/auth/auth_srv.h
    branches/trac232/src/bin/auth/b10-auth.8
    branches/trac232/src/bin/auth/b10-auth.xml
    branches/trac232/src/bin/auth/main.cc
    branches/trac232/src/bin/auth/tests/Makefile.am
    branches/trac232/src/bin/auth/tests/auth_srv_unittest.cc
    branches/trac232/src/bin/bind10/bind10.8
    branches/trac232/src/bin/bind10/bind10.py.in
    branches/trac232/src/bin/bind10/bind10.xml
    branches/trac232/src/bin/bind10/run_bind10.sh.in
    branches/trac232/src/bin/bind10/tests/Makefile.am
    branches/trac232/src/bin/bindctl/bindcmd.py
    branches/trac232/src/bin/bindctl/tests/Makefile.am
    branches/trac232/src/bin/bindctl/tests/bindctl_test.py
    branches/trac232/src/bin/cfgmgr/b10-cfgmgr.py.in
    branches/trac232/src/bin/cfgmgr/tests/Makefile.am
    branches/trac232/src/bin/cmdctl/TODO
    branches/trac232/src/bin/cmdctl/cmdctl.py.in
    branches/trac232/src/bin/cmdctl/cmdctl.spec.pre.in
    branches/trac232/src/bin/cmdctl/tests/Makefile.am
    branches/trac232/src/bin/cmdctl/tests/cmdctl_test.py
    branches/trac232/src/bin/host/Makefile.am
    branches/trac232/src/bin/host/host.cc
    branches/trac232/src/bin/loadzone/tests/correct/Makefile.am
    branches/trac232/src/bin/loadzone/tests/error/Makefile.am
    branches/trac232/src/bin/msgq/b10-msgq.8
    branches/trac232/src/bin/msgq/msgq.py.in
    branches/trac232/src/bin/msgq/msgq.xml
    branches/trac232/src/bin/msgq/tests/Makefile.am
    branches/trac232/src/bin/usermgr/b10-cmdctl-usermgr.py.in
    branches/trac232/src/bin/xfrin/   (props changed)
    branches/trac232/src/bin/xfrin/tests/Makefile.am
    branches/trac232/src/bin/xfrin/tests/xfrin_test.py
    branches/trac232/src/bin/xfrin/xfrin.py.in
    branches/trac232/src/bin/xfrin/xfrin.spec.pre.in
    branches/trac232/src/bin/xfrout/tests/Makefile.am
    branches/trac232/src/bin/xfrout/xfrout.py.in
    branches/trac232/src/bin/xfrout/xfrout.spec.pre.in
    branches/trac232/src/lib/Makefile.am
    branches/trac232/src/lib/cc/   (props changed)
    branches/trac232/src/lib/cc/Makefile.am
    branches/trac232/src/lib/cc/data.cc
    branches/trac232/src/lib/cc/data.h
    branches/trac232/src/lib/cc/session.cc
    branches/trac232/src/lib/cc/session.h
    branches/trac232/src/lib/config/Makefile.am
    branches/trac232/src/lib/config/ccsession.cc
    branches/trac232/src/lib/config/ccsession.h
    branches/trac232/src/lib/config/config_data.cc
    branches/trac232/src/lib/config/config_data.h
    branches/trac232/src/lib/config/documentation.txt
    branches/trac232/src/lib/config/module_spec.cc
    branches/trac232/src/lib/config/module_spec.h
    branches/trac232/src/lib/config/testdata/b10-config-bad1.db
    branches/trac232/src/lib/config/testdata/data22_1.data
    branches/trac232/src/lib/config/testdata/data22_2.data
    branches/trac232/src/lib/config/testdata/data22_3.data
    branches/trac232/src/lib/config/testdata/data22_4.data
    branches/trac232/src/lib/config/testdata/data22_5.data
    branches/trac232/src/lib/config/testdata/data22_6.data
    branches/trac232/src/lib/config/testdata/data22_7.data
    branches/trac232/src/lib/config/testdata/data22_8.data
    branches/trac232/src/lib/config/testdata/spec10.spec
    branches/trac232/src/lib/config/testdata/spec11.spec
    branches/trac232/src/lib/config/testdata/spec12.spec
    branches/trac232/src/lib/config/testdata/spec13.spec
    branches/trac232/src/lib/config/testdata/spec14.spec
    branches/trac232/src/lib/config/testdata/spec15.spec
    branches/trac232/src/lib/config/testdata/spec17.spec
    branches/trac232/src/lib/config/testdata/spec2.spec
    branches/trac232/src/lib/config/testdata/spec20.spec
    branches/trac232/src/lib/config/testdata/spec22.spec
    branches/trac232/src/lib/config/testdata/spec23.spec
    branches/trac232/src/lib/config/testdata/spec24.spec
    branches/trac232/src/lib/config/testdata/spec27.spec
    branches/trac232/src/lib/config/testdata/spec3.spec
    branches/trac232/src/lib/config/testdata/spec4.spec
    branches/trac232/src/lib/config/testdata/spec6.spec
    branches/trac232/src/lib/config/testdata/spec9.spec
    branches/trac232/src/lib/config/tests/Makefile.am
    branches/trac232/src/lib/config/tests/ccsession_unittests.cc
    branches/trac232/src/lib/config/tests/config_data_unittests.cc
    branches/trac232/src/lib/config/tests/fake_session.cc
    branches/trac232/src/lib/config/tests/fake_session.h
    branches/trac232/src/lib/config/tests/module_spec_unittests.cc
    branches/trac232/src/lib/datasrc/   (props changed)
    branches/trac232/src/lib/datasrc/cache.cc
    branches/trac232/src/lib/datasrc/data_source.cc
    branches/trac232/src/lib/datasrc/data_source.h
    branches/trac232/src/lib/datasrc/query.cc
    branches/trac232/src/lib/datasrc/query.h
    branches/trac232/src/lib/datasrc/sqlite3_datasrc.cc
    branches/trac232/src/lib/datasrc/sqlite3_datasrc.h
    branches/trac232/src/lib/datasrc/static_datasrc.cc
    branches/trac232/src/lib/datasrc/static_datasrc.h
    branches/trac232/src/lib/datasrc/tests/Makefile.am
    branches/trac232/src/lib/datasrc/tests/datasrc_unittest.cc
    branches/trac232/src/lib/datasrc/tests/query_unittest.cc
    branches/trac232/src/lib/datasrc/tests/sqlite3_unittest.cc
    branches/trac232/src/lib/datasrc/tests/static_unittest.cc
    branches/trac232/src/lib/datasrc/tests/test_datasrc.cc
    branches/trac232/src/lib/datasrc/tests/test_datasrc.h
    branches/trac232/src/lib/dns/   (props changed)
    branches/trac232/src/lib/dns/Makefile.am
    branches/trac232/src/lib/dns/message.h
    branches/trac232/src/lib/dns/messagerenderer.h
    branches/trac232/src/lib/dns/name.h
    branches/trac232/src/lib/dns/python/Makefile.am
    branches/trac232/src/lib/dns/python/libdns_python.cc
    branches/trac232/src/lib/dns/python/message_python.cc   (contents, props changed)
    branches/trac232/src/lib/dns/python/messagerenderer_python.cc
    branches/trac232/src/lib/dns/python/name_python.cc
    branches/trac232/src/lib/dns/python/question_python.cc
    branches/trac232/src/lib/dns/python/rdata_python.cc
    branches/trac232/src/lib/dns/python/rrclass_python.cc
    branches/trac232/src/lib/dns/python/rrset_python.cc
    branches/trac232/src/lib/dns/python/rrttl_python.cc
    branches/trac232/src/lib/dns/python/rrtype_python.cc
    branches/trac232/src/lib/dns/python/tests/Makefile.am
    branches/trac232/src/lib/dns/python/tests/rrset_python_test.py
    branches/trac232/src/lib/dns/rdata/generic/dnskey_48.cc
    branches/trac232/src/lib/dns/rdata/generic/ds_43.cc
    branches/trac232/src/lib/dns/rdata/generic/nsec3_50.cc
    branches/trac232/src/lib/dns/rdata/generic/nsec3param_51.cc
    branches/trac232/src/lib/dns/rdata/generic/nsec_47.cc
    branches/trac232/src/lib/dns/rdata/generic/rrsig_46.cc   (contents, props changed)
    branches/trac232/src/lib/dns/rdata/generic/txt_16.cc
    branches/trac232/src/lib/dns/rrsetlist.cc
    branches/trac232/src/lib/dns/rrtype-placeholder.h
    branches/trac232/src/lib/dns/tests/   (props changed)
    branches/trac232/src/lib/dns/tests/Makefile.am
    branches/trac232/src/lib/dns/tests/base64_unittest.cc
    branches/trac232/src/lib/dns/tests/hex_unittest.cc
    branches/trac232/src/lib/dns/tests/message_unittest.cc
    branches/trac232/src/lib/dns/tests/messagerenderer_unittest.cc
    branches/trac232/src/lib/dns/tests/name_unittest.cc
    branches/trac232/src/lib/dns/tests/question_unittest.cc
    branches/trac232/src/lib/dns/tests/rdata_cname_unittest.cc
    branches/trac232/src/lib/dns/tests/rdata_dname_unittest.cc
    branches/trac232/src/lib/dns/tests/rdata_dnskey_unittest.cc
    branches/trac232/src/lib/dns/tests/rdata_ds_unittest.cc
    branches/trac232/src/lib/dns/tests/rdata_in_a_unittest.cc
    branches/trac232/src/lib/dns/tests/rdata_in_aaaa_unittest.cc
    branches/trac232/src/lib/dns/tests/rdata_mx_unittest.cc
    branches/trac232/src/lib/dns/tests/rdata_ns_unittest.cc
    branches/trac232/src/lib/dns/tests/rdata_nsec3_unittest.cc
    branches/trac232/src/lib/dns/tests/rdata_nsec3param_unittest.cc
    branches/trac232/src/lib/dns/tests/rdata_nsec_unittest.cc
    branches/trac232/src/lib/dns/tests/rdata_opt_unittest.cc
    branches/trac232/src/lib/dns/tests/rdata_ptr_unittest.cc
    branches/trac232/src/lib/dns/tests/rdata_rrsig_unittest.cc
    branches/trac232/src/lib/dns/tests/rdata_soa_unittest.cc
    branches/trac232/src/lib/dns/tests/rdata_txt_unittest.cc
    branches/trac232/src/lib/dns/tests/rdata_unittest.cc
    branches/trac232/src/lib/dns/tests/rrclass_unittest.cc
    branches/trac232/src/lib/dns/tests/rrparamregistry_unittest.cc
    branches/trac232/src/lib/dns/tests/rrset_unittest.cc
    branches/trac232/src/lib/dns/tests/rrttl_unittest.cc
    branches/trac232/src/lib/dns/tests/rrtype_unittest.cc
    branches/trac232/src/lib/dns/tests/run_unittests.cc
    branches/trac232/src/lib/dns/tests/sha1_unittest.cc
    branches/trac232/src/lib/dns/tests/tsig_unittest.cc
    branches/trac232/src/lib/dns/tests/unittest_util.cc
    branches/trac232/src/lib/exceptions/Makefile.am
    branches/trac232/src/lib/exceptions/exceptions.cc
    branches/trac232/src/lib/exceptions/exceptions.h
    branches/trac232/src/lib/python/isc/Makefile.am
    branches/trac232/src/lib/python/isc/cc/data.py
    branches/trac232/src/lib/python/isc/cc/session.py
    branches/trac232/src/lib/python/isc/cc/tests/Makefile.am
    branches/trac232/src/lib/python/isc/cc/tests/data_test.py
    branches/trac232/src/lib/python/isc/cc/tests/session_test.py
    branches/trac232/src/lib/python/isc/config/ccsession.py
    branches/trac232/src/lib/python/isc/config/cfgmgr.py
    branches/trac232/src/lib/python/isc/config/config_data.py
    branches/trac232/src/lib/python/isc/config/module_spec.py
    branches/trac232/src/lib/python/isc/config/tests/Makefile.am
    branches/trac232/src/lib/python/isc/config/tests/ccsession_test.py
    branches/trac232/src/lib/python/isc/config/tests/cfgmgr_test.py
    branches/trac232/src/lib/python/isc/config/tests/config_data_test.py
    branches/trac232/src/lib/python/isc/config/tests/module_spec_test.py
    branches/trac232/src/lib/python/isc/config/tests/unittest_fakesession.py   (contents, props changed)
    branches/trac232/src/lib/python/isc/datasrc/sqlite3_ds.py
    branches/trac232/src/lib/python/isc/log/tests/Makefile.am
    branches/trac232/src/lib/python/isc/log/tests/log_test.py
    branches/trac232/src/lib/xfr/fd_share.cc
    branches/trac232/src/lib/xfr/fdshare_python.cc
    branches/trac232/src/lib/xfr/python_xfr.cc
    branches/trac232/src/lib/xfr/xfrout_client.cc
    branches/trac232/src/lib/xfr/xfrout_client.h

Modified: branches/trac232/ChangeLog
==============================================================================
--- branches/trac232/ChangeLog (original)
+++ branches/trac232/ChangeLog Wed Sep  1 00:35:07 2010
@@ -1,3 +1,121 @@
+  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
+	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
+	python modules refer to installation paths, which may confuse the
+	operation due to version mismatch or even trigger run time errors
+	due to missing libraries. (Trac #313, r2782)
+
+  89.	[build]		jinmei
+	Generate b10-config.db for tests at build time so that the source
+	tree does not have to be writable. (Trac #315, r2776)
+
+  88.   [func]		jelte
+	Blocking reads on the msgq command channel now have a timeout
+	(defaults to 4 seconds, modifiable as needed by modules).
+	Because of this, modules will no longer block indefinitely
+	if they are waiting for a message that is not sent for whatever
+	reason. (Trac #296, r2761)
+
+  87.   [func]		zhanglikun
+	lib/python/isc/notifyout: Add the feature of notify-out, when 
+	zone axfr/ixfr finishing, the server will notify its slaves.
+	(Trac #289, svn r2737)
+
+  86.   [func]		jerry
+    	bin/zonemgr: Added zone manager module. The zone manager is one 
+	of the co-operating processes of BIND10, which keeps track of 
+	timers and other information necessary for BIND10 to act as a 
+	slave. (Trac #215, svn r2737)
+
+  85.	[build]*	jinmei
+	Build programs using dynamic link by default.  A new configure
+	option --enable-static-link is provided to force static link for
+	executable programs.  Statically linked programs can be run on a
+	debugger more easily and would be convenient for developers.
+	(Trac #309, svn r2723)
+
+bind10-devel-20100812 released on August 12, 2010
+
+  84.	[bug]		jinmei, jerry
+	This is a quick fix patch for the issue: AXFR fails half the 
+	time because of connection problems. xfrout client will make
+	a new connection every time. (Trac #299, svn r2697)
+
+  83.	[build]*	jreed
+	The configure --with-boost-lib option is removed. It was not
+	used since the build included ASIO. (svn r2684)
+
+  82.	[func]		jinmei
+	bin/auth: Added -u option to change the effective process user
+	of the authoritative server after invocation.  The same option to
+	the boss process will be propagated to b10-auth, too.
+	(Trac #268, svn r2675)
+
+  81.	[func]		jinmei
+	Added a C++ framework for micro benchmark tests.  A supplemental
+	library functions to build query data for the tests were also
+	provided. (Trac #241, svn r2664)
+
+  80.	[bug]		jelte
+	bindctl no longer accepts configuration changes for unknown or
+	non-running modules (for the latter, this is until we have a
+	way to verify those options, at which point it'll be allowed
+	again).
+	(Trac #99, r2657)
+
+  79.	[func]		feng, jinmei
+	Refactored the ASIO link interfaces to move incoming XFR and
+	NOTIFY processing to the auth server class.  Wrapper classes for
+	ASIO specific concepts were also provided, so that other BIND 10
+	modules can (eventually) use the interface without including the
+	ASIO header file directly.  On top of these changes, AXFR and
+	NOTIFY processing was massively improved in terms of message
+	validation and protocol conformance.  Detailed tests were provided
+	to confirm the behavior.
+	Note: Right now, NOTIFY doesn't actually trigger subsequent zone
+	transfer due to security reasons. (Trac #221, r2565)
+
+  78.	[bug]		jinmei
+	lib/dns: Fixed miscellaneous bugs in the base32 (hex) and hex
+	(base16) implementation, including incorrect padding handling,
+	parser failure in decoding with a SunStudio build, missing
+	validation on the length of encoded hex string.  Test cases were
+	more detailed to identify these bugs and confirm the fix.  Also
+	renamed the incorrect term of "base32" to "base32hex".  This
+	changed the API, but they are not intended to be used outside
+	libdns++, so we don't consider it a backward incompatible change.
+	(Trac #256, r2549)
+
+  77.	[func]		zhanglikun
+	Make error message be more friendly when running cmdctl and it's 
+	already running(listening on same port)(Trac #277, r2540)
+
+  76.	[bug]		jelte
+	Fixed a bug in the handling of 'remote' config modules (i.e.
+	modules that peek at the configuration of other modules), where
+	they answered 'unknown command' to commands for those other
+	modules. (Trac #278, r2506)
+
+  75.	[bug]		jinmei
+	Fixed a bug in the sqlite3 data source where temporary strings
+	could be referenced after destruction.  It caused various lookup
+	failures with SunStudio build. (Trac #288, r2494)
+
+  74.	[func]*		jinmei
+	Refactored the cc::Session class by introducing an abstract base
+	class.  Test code can use their own derived mock class so that
+	tests can be done without establishing a real CC session.  This
+	change also modified some public APIs, mainly in the config
+	module. (Trac #275, r2459)
+
   73.	[bug]		jelte
   	Fixed a bug where in bindctl, locally changed settings were
 	reset when the list of running modules is updated. (Trac #285,
@@ -151,7 +269,11 @@
 	a remote server. (Trac #218, svn r2038)
 
   49.	[func]*		jelte
-	Use unix domain sockets for msgq. (Trac #183, svn r2009)
+	Use unix domain sockets for msgq. For b10-msgq, the command
+	line options --msgq-port and -m were removed. For bind10,
+	the -msgq-port option was removed, and the -m command line
+	option was changed to be a filename (instead of port number).
+	(Trac #183, svn r2009)
 
   48.	[func]		jelte
 	bin/auth: Use asio's io_service for the msgq handling.

Modified: branches/trac232/Makefile.am
==============================================================================
--- branches/trac232/Makefile.am (original)
+++ branches/trac232/Makefile.am Wed Sep  1 00:35:07 2010
@@ -28,6 +28,7 @@
 			c++/4.4\*/ext/\* \
 			c++/4.4\*/\*-\*/bits/\* \
 			boost/\* \
+			ext/asio/\* \
 			gtest/\* \
 			usr/include/\* \
 			tests/\* \
@@ -41,8 +42,8 @@
 coverage: clean-coverage perform-coverage report-coverage
 
 #### include external sources in the distributed tarball:
-# EXTRA_DIST = ext/asio/README
-EXTRA_DIST = ext/asio/asio/local/stream_protocol.hpp
+EXTRA_DIST = ext/asio/README
+EXTRA_DIST += ext/asio/asio/local/stream_protocol.hpp
 EXTRA_DIST += ext/asio/asio/local/basic_endpoint.hpp
 EXTRA_DIST += ext/asio/asio/local/datagram_protocol.hpp
 EXTRA_DIST += ext/asio/asio/local/connect_pair.hpp

Modified: branches/trac232/configure.ac
==============================================================================
--- branches/trac232/configure.ac (original)
+++ branches/trac232/configure.ac Wed Sep  1 00:35:07 2010
@@ -32,14 +32,38 @@
 	])
 LDFLAGS=$LDFLAGS_SAVED
 
-# OS dependent compiler flags
+# allow building programs with static link.  we need to make it selective
+# because loadable modules cannot be statically linked.
+AC_ARG_ENABLE([static-link],
+AC_HELP_STRING([--enable-static-link],
+  [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)
+
+# OS dependent configuration
+SET_ENV_LIBRARY_PATH=no
+ENV_LIBRARY_PATH=LD_LIBRARY_PATH
+
 case "$host" in
 *-solaris*)
 	# Solaris requires special definitions to get some standard libraries
 	# (e.g. getopt(3)) available with common used header files.
 	CPPFLAGS="$CPPFLAGS -D_XPG4_2 -D__EXTENSIONS__"
 	;;
+*-apple-darwin*)
+	# libtool doesn't work pefectly with Darwin: libtool embeds the
+	# final install path in dynamic libraries and our loadable python
+	# modules always refer to that path even if it's loaded within the
+	# source tree.  This prevents pre-install tests from working.
+	# To work around this problem we explicitly specify paths to dynamic
+	# libraries when we use them in the source tree.
+	SET_ENV_LIBRARY_PATH=yes
+	ENV_LIBRARY_PATH=DYLD_LIBRARY_PATH
+	;;
 esac
+AM_CONDITIONAL(SET_ENV_LIBRARY_PATH, test $SET_ENV_LIBRARY_PATH = yes)
+AC_SUBST(SET_ENV_LIBRARY_PATH)
+AC_SUBST(ENV_LIBRARY_PATH)
 
 m4_define([_AM_PYTHON_INTERPRETER_LIST], [python python3 python3.1])
 AC_ARG_WITH([pythonpath],
@@ -255,14 +279,6 @@
 	CPPFLAGS="$CPPFLAGS $BOOST_INCLUDES"
 fi
 AC_SUBST(BOOST_INCLUDES)
-
-AC_ARG_WITH([boost-lib],
-AC_HELP_STRING([--with-boost-lib=PATH],
-  [specify exact directory for Boost libraries]),
-  [if test "$withval" != "yes" -a "$withval" != "no"; then
-   BOOST_LDFLAGS="-L$withval"
-   fi])
-AC_SUBST(BOOST_LDFLAGS)
 
 #
 # Check availability of gtest, which will be used for unit tests.
@@ -411,9 +427,15 @@
                  src/bin/xfrin/tests/Makefile
                  src/bin/xfrout/Makefile
                  src/bin/xfrout/tests/Makefile
+                 src/bin/zonemgr/Makefile
+                 src/bin/zonemgr/tests/Makefile
                  src/bin/usermgr/Makefile
                  src/lib/Makefile
+                 src/lib/bench/Makefile
+                 src/lib/bench/example/Makefile
+                 src/lib/bench/tests/Makefile
                  src/lib/cc/Makefile
+                 src/lib/cc/tests/Makefile
                  src/lib/python/Makefile
                  src/lib/python/isc/Makefile
                  src/lib/python/isc/datasrc/Makefile
@@ -423,13 +445,17 @@
                  src/lib/python/isc/config/tests/Makefile
                  src/lib/python/isc/log/Makefile
                  src/lib/python/isc/log/tests/Makefile
+                 src/lib/python/isc/notify/Makefile
+                 src/lib/python/isc/notify/tests/Makefile
                  src/lib/config/Makefile
                  src/lib/config/tests/Makefile
+                 src/lib/config/testdata/Makefile
                  src/lib/dns/Makefile
                  src/lib/dns/tests/Makefile
                  src/lib/dns/python/Makefile
                  src/lib/dns/python/tests/Makefile
                  src/lib/exceptions/Makefile
+                 src/lib/exceptions/tests/Makefile
                  src/lib/datasrc/Makefile
                  src/lib/datasrc/tests/Makefile
                  src/lib/xfr/Makefile
@@ -448,6 +474,10 @@
            src/bin/xfrout/xfrout.spec.pre
            src/bin/xfrout/tests/xfrout_test
            src/bin/xfrout/run_b10-xfrout.sh
+           src/bin/zonemgr/zonemgr.py
+           src/bin/zonemgr/zonemgr.spec.pre
+           src/bin/zonemgr/tests/zonemgr_test
+           src/bin/zonemgr/run_b10-zonemgr.sh
            src/bin/bind10/bind10.py
            src/bin/bind10/tests/bind10_test
            src/bin/bind10/run_bind10.sh
@@ -469,18 +499,22 @@
            src/lib/python/isc/config/tests/config_test
            src/lib/python/isc/cc/tests/cc_test
            src/lib/python/isc/log/tests/log_test
+           src/lib/python/isc/notify/tests/notify_out_test
            src/lib/dns/gen-rdatacode.py
            src/lib/python/bind10_config.py
            src/lib/dns/tests/testdata/gen-wiredata.py
            src/lib/cc/session_config.h.pre
+           src/lib/cc/tests/session_unittests_config.h
           ], [
            chmod +x src/bin/cmdctl/run_b10-cmdctl.sh
            chmod +x src/bin/xfrin/run_b10-xfrin.sh
            chmod +x src/bin/xfrout/run_b10-xfrout.sh
+           chmod +x src/bin/zonemgr/run_b10-zonemgr.sh
            chmod +x src/bin/bind10/run_bind10.sh
            chmod +x src/bin/cmdctl/tests/cmdctl_test
            chmod +x src/bin/xfrin/tests/xfrin_test
            chmod +x src/bin/xfrout/tests/xfrout_test
+           chmod +x src/bin/zonemgr/tests/zonemgr_test
            chmod +x src/bin/bindctl/tests/bindctl_test
            chmod +x src/bin/bindctl/run_bindctl.sh
            chmod +x src/bin/loadzone/run_loadzone.sh

Modified: branches/trac232/doc/Doxyfile
==============================================================================
--- branches/trac232/doc/Doxyfile (original)
+++ branches/trac232/doc/Doxyfile Wed Sep  1 00:35:07 2010
@@ -568,7 +568,7 @@
 # directories like "/usr/src/myproject". Separate the files or directories
 # with spaces.
 
-INPUT                  = ../src/lib/cc ../src/lib/config ../src/lib/dns ../src/lib/exceptions ../src/lib/datasrc
+INPUT                  = ../src/lib/cc ../src/lib/config ../src/lib/dns ../src/lib/exceptions ../src/lib/datasrc ../src/bin/auth ../src/lib/bench
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is

Modified: branches/trac232/doc/guide/bind10-guide.html
==============================================================================
--- branches/trac232/doc/guide/bind10-guide.html (original)
+++ branches/trac232/doc/guide/bind10-guide.html Wed Sep  1 00:35:07 2010
@@ -2,7 +2,7 @@
         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="#id1168230328405">Download Tar File</a></span></dt><dt><s
 pan class="section"><a href="#id1168230328425">Retrieve from Subversion</a></span></dt><dt><span class="section"><a href="#id1168230328485">Configure before the build</a></span></dt><dt><span class="section"><a href="#id1168230328596">Build</a></span></dt><dt><span class="section"><a href="#id1168230328611">Install</a></span></dt><dt><span class="section"><a href="#id1168230328642">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="#id1168230329208">Server Configurations</a></span></dt><dt><span class="section"><a href="#id1168230329273">Data Source Backends</a></span></dt><dt><span class="section"><a href="#id1168230329303">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="#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>
       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
@@ -32,9 +32,8 @@
 	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 libboost library,
-        libpython3 library,
-	and the Python _sqlite3.so module.
+        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
@@ -117,7 +116,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="#id1168230328405">Download Tar File</a></span></dt><dt><span class="section"><a href="#id1168230328425">Retrieve from Subversion</a></span></dt><dt><span class="section"><a href="#id1168230328485">Configure before the build</a></span></dt><dt><span class="section"><a href="#id1168230328596">Build</a></span></dt><dt><span class="section"><a href="#id1168230328611">Install</a></span></dt><dt><span class="section"><a href="#id1168230328642">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="#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>
             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
@@ -128,9 +127,8 @@
   
   
         </p><p>
-	  The Boost Library, Python Library,
-	  and Python _sqlite3 module are required to enable the
-	  Xfrout and Xfrin support.
+	  The Python Library and Python _sqlite3 module are required to
+          enable the Xfrout and Xfrin support.
         </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
           The Python related libraries and modules need to be built
           for Python 3.1.
@@ -178,14 +176,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="id1168230328405"></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="id1168230328406"></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="id1168230328425"></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="id1168230328426"></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.
@@ -217,7 +215,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="id1168230328485"></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="id1168230328486"></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:
@@ -229,7 +227,6 @@
           </p><div class="variablelist"><dl><dt><span class="term">--prefix</span></dt><dd>Define the the installation location (the
                 default is <code class="filename">/usr/local/</code>).
               </dd><dt><span class="term">--with-boost-include</span></dt><dd>Define the path to find the Boost headers.
-              </dd><dt><span class="term">--with-boost-lib</span></dt><dd>Define the path to find the Boost library.
               </dd><dt><span class="term">--with-pythonpath</span></dt><dd>Define the path to Python 3.1 if it is not in the
                 standard execution path.
               </dd><dt><span class="term">--with-gtest</span></dt><dd>Enable building the C++ Unit Tests using the
@@ -239,31 +236,26 @@
 
         </p><p>
           For example, the following configures it to
-    find the Boost headers and library, find the
+    find the Boost headers, find the
     Python interpreter, and sets the installation location:
 
-          </p><pre class="screen">$ <strong class="userinput"><code>./configure --with-boost-lib=/usr/pkg/lib \
+          </p><pre class="screen">$ <strong class="userinput"><code>./configure \
       --with-boost-include=/usr/pkg/include \
       --with-pythonpath=/usr/pkg/bin/python3.1 \
       --prefix=/opt/bind10</code></strong></pre><p>
         </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="id1168230328596"></a>Build</h3></div></div></div><p>
+        </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>
     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="id1168230328611"></a>Install</h3></div></div></div><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>
           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 class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
-	  Depending on your system and the location of your Boost
-	  Python and Python shared libraries, you may need to
-	  configure your run-time linker to find them (such as
-	  setting LD_LIBRARY_PATH).
-        </p></div></div><div class="section" title="Install Hierarchy"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230328642"></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="id1168230328622"></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> —
@@ -475,7 +467,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="#id1168230329208">Server Configurations</a></span></dt><dt><span class="section"><a href="#id1168230329273">Data Source Backends</a></span></dt><dt><span class="section"><a href="#id1168230329303">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="#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>
       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
@@ -483,7 +475,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="id1168230329208"></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="id1168230329190"></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>.
@@ -503,7 +495,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="id1168230329273"></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="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>
         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
@@ -516,7 +508,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="id1168230329303"></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="id1168230329285"></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.

Modified: branches/trac232/doc/guide/bind10-guide.xml
==============================================================================
--- branches/trac232/doc/guide/bind10-guide.xml (original)
+++ branches/trac232/doc/guide/bind10-guide.xml Wed Sep  1 00:35:07 2010
@@ -75,9 +75,8 @@
 	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 libboost library,
-        libpython3 library,
-	and the Python _sqlite3.so module.
+        modules require the libpython3 library and the Python
+        _sqlite3.so module.
       </para></note>
 <!-- TODO: this will change ... -->
 
@@ -272,9 +271,8 @@
         </para>
 
         <para>
-	  The Boost Library, Python Library,
-	  and Python _sqlite3 module are required to enable the
-	  Xfrout and Xfrin support.
+	  The Python Library and Python _sqlite3 module are required to
+          enable the Xfrout and Xfrin support.
         </para>
 
         <note><simpara>
@@ -487,14 +485,6 @@
           </varlistentry>
 
           <varlistentry>
-            <term>--with-boost-lib</term>
-            <listitem> 
-              <simpara>Define the path to find the Boost library.
-              </simpara>
-            </listitem> 
-          </varlistentry>
-
-          <varlistentry>
             <term>--with-pythonpath</term>
             <listitem> 
               <simpara>Define the path to Python 3.1 if it is not in the
@@ -520,10 +510,10 @@
 
         <para>
           For example, the following configures it to
-    find the Boost headers and library, find the
+    find the Boost headers, find the
     Python interpreter, and sets the installation location:
 
-          <screen>$ <userinput>./configure --with-boost-lib=/usr/pkg/lib \
+          <screen>$ <userinput>./configure \
       --with-boost-include=/usr/pkg/include \
       --with-pythonpath=/usr/pkg/bin/python3.1 \
       --prefix=/opt/bind10</userinput></screen>
@@ -556,14 +546,6 @@
         <note>
           <para>The install step may require superuser privileges.</para>
         </note>
-
-<!-- Trac #148 -->
-        <note><simpara>
-	  Depending on your system and the location of your Boost
-	  Python and Python shared libraries, you may need to
-	  configure your run-time linker to find them (such as
-	  setting LD_LIBRARY_PATH).
-        </simpara></note>
 
       </section>
 

Modified: branches/trac232/src/bin/Makefile.am
==============================================================================
--- branches/trac232/src/bin/Makefile.am (original)
+++ branches/trac232/src/bin/Makefile.am Wed Sep  1 00:35:07 2010
@@ -1,1 +1,1 @@
-SUBDIRS = bind10 bindctl cfgmgr loadzone msgq host cmdctl auth xfrin xfrout usermgr
+SUBDIRS = bind10 bindctl cfgmgr loadzone msgq host cmdctl auth xfrin xfrout usermgr zonemgr

Modified: branches/trac232/src/bin/auth/Makefile.am
==============================================================================
--- branches/trac232/src/bin/auth/Makefile.am (original)
+++ branches/trac232/src/bin/auth/Makefile.am Wed Sep  1 00:35:07 2010
@@ -1,10 +1,16 @@
 SUBDIRS = . tests
 
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
+AM_CPPFLAGS += -I$(top_srcdir)/src/bin -I$(top_builddir)/src/bin
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
 AM_CPPFLAGS += -I$(top_builddir)/src/lib/cc
+AM_CPPFLAGS += -I$(top_srcdir)/src/bin -I$(top_builddir)/src/bin
 
 AM_CXXFLAGS = $(B10_CXXFLAGS)
+
+if USE_STATIC_LINK
+AM_LDFLAGS = -static
+endif
 
 pkglibexecdir = $(libexecdir)/@PACKAGE@
 
@@ -45,16 +51,17 @@
 BUILT_SOURCES = spec_config.h 
 pkglibexec_PROGRAMS = b10-auth
 b10_auth_SOURCES = auth_srv.cc auth_srv.h
+b10_auth_SOURCES += change_user.cc change_user.h
 b10_auth_SOURCES += common.h
 b10_auth_SOURCES += main.cc
-b10_auth_LDADD =  $(top_builddir)/src/lib/datasrc/.libs/libdatasrc.a
-b10_auth_LDADD += $(top_builddir)/src/lib/dns/.libs/libdns++.a
-b10_auth_LDADD += $(top_builddir)/src/lib/config/.libs/libcfgclient.a
-b10_auth_LDADD += $(top_builddir)/src/lib/cc/.libs/libcc.a
-b10_auth_LDADD += $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a
-b10_auth_LDADD += $(top_builddir)/src/bin/auth/libasio_link.a
+b10_auth_LDADD =  $(top_builddir)/src/lib/datasrc/libdatasrc.la
+b10_auth_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
+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 += libasio_link.a
+b10_auth_LDADD += $(top_builddir)/src/lib/xfr/libxfr.la
 b10_auth_LDADD += $(SQLITE_LIBS)
-b10_auth_LDADD += $(top_builddir)/src/lib/xfr/.libs/libxfr.a
 
 # TODO: config.h.in is wrong because doesn't honor pkgdatadir
 # and can't use @datadir@ because doesn't expand default ${prefix}

Modified: branches/trac232/src/bin/auth/asio_link.cc
==============================================================================
--- branches/trac232/src/bin/auth/asio_link.cc (original)
+++ branches/trac232/src/bin/auth/asio_link.cc Wed Sep  1 00:35:07 2010
@@ -17,83 +17,167 @@
 #include <config.h>
 
 #include <unistd.h>             // for some IPC/network system calls
+#include <sys/socket.h>
+#include <netinet/in.h>
+
 #include <asio.hpp>
 #include <boost/lexical_cast.hpp>
 #include <boost/bind.hpp>
 
+#include <boost/shared_ptr.hpp>
+
 #include <dns/buffer.h>
 #include <dns/message.h>
 #include <dns/messagerenderer.h>
 
-#include <xfr/xfrout_client.h>
-
 #include <asio_link.h>
 
-#include "spec_config.h"        // for XFROUT.  should not be here.
-#include "auth_srv.h"
-#include "common.h"
+#include <auth/auth_srv.h>
+#include <auth/common.h>
 
 using namespace asio;
-using ip::udp;
-using ip::tcp;
+using asio::ip::udp;
+using asio::ip::tcp;
 
 using namespace std;
 using namespace isc::dns;
-using namespace isc::xfr;
-
-namespace {
-// As a short term workaround, we have XFROUT specific code.  We should soon
-// refactor the code with some abstraction so that we can separate this level
-// details from the (AS)IO module.
-
-// This was contained in an ifdef USE_XFROUT, but we should really check
-// live if we do xfrout
-//TODO. The sample way for checking axfr query, the code should be merged to auth server class
-bool
-check_axfr_query(char* const msg_data, const uint16_t msg_len) {
-    if (msg_len < 15) {
-        return false;
-    }
-
-    const uint16_t query_type = *(uint16_t *)(msg_data + (msg_len - 4));
-    if ( query_type == 0xFC00) {
-        return true;
-    }
-    
-    return false;
-}
-
-//TODO. Send the xfr query to xfrout module, the code should be merged to auth server class
-//BIGGERTODO: stop using hardcoded install-path locations! 
-void
-dispatch_axfr_query(const int tcp_sock, char const axfr_query[],
-                    const uint16_t query_len)
+
+namespace asio_link {
+IOAddress::IOAddress(const string& address_str)
+    // XXX: we cannot simply construct the address in the initialization list
+    // because we'd like to throw our own exception on failure.
 {
-    string path;
-    if (getenv("B10_FROM_BUILD")) {
-        path = string(getenv("B10_FROM_BUILD")) + "/auth_xfrout_conn";
-    } else {
-        path = UNIX_SOCKET_FILE;
-    }
-    
-    if (getenv("B10_FROM_BUILD")) {
-        path = string(getenv("B10_FROM_BUILD")) + "/auth_xfrout_conn";
-    }
-    XfroutClient xfr_client(path);
-    try {
-        xfr_client.connect();
-        xfr_client.sendXfroutRequestInfo(tcp_sock, (uint8_t *)axfr_query,
-                                         query_len);
-        xfr_client.disconnect();
-    }
-    catch (const exception & err) {
-        //if (verbose_mode)
-        cerr << "error handle xfr query " << UNIX_SOCKET_FILE << ":" << err.what() << endl;
-    }
-}
-}
-
-namespace asio_link {
+    error_code err;
+    asio_address_ = ip::address::from_string(address_str, err);
+    if (err) {
+        isc_throw(IOError, "Failed to convert string to address '"
+                  << address_str << "': " << err.message());
+    }
+}
+
+IOAddress::IOAddress(const ip::address& asio_address) :
+    asio_address_(asio_address)
+{}
+
+string
+IOAddress::toText() const {
+    return (asio_address_.to_string());
+}
+
+// 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
+// overhead might be significant.
+class TCPEndpoint : public IOEndpoint {
+public:
+    TCPEndpoint(const IOAddress& address, const unsigned short port) :
+        asio_endpoint_placeholder_(
+            new tcp::endpoint(ip::address::from_string(address.toText()),
+                              port)),
+        asio_endpoint_(*asio_endpoint_placeholder_)
+    {}
+    TCPEndpoint(const tcp::endpoint& asio_endpoint) :
+        asio_endpoint_placeholder_(NULL), asio_endpoint_(asio_endpoint)
+    {}
+        
+    ~TCPEndpoint() { delete asio_endpoint_placeholder_; }
+    virtual IOAddress getAddress() const {
+        return (asio_endpoint_.address());
+    }
+private:
+    const tcp::endpoint* asio_endpoint_placeholder_;
+    const tcp::endpoint& asio_endpoint_;
+};
+
+class UDPEndpoint : public IOEndpoint {
+public:
+    UDPEndpoint(const IOAddress& address, const unsigned short port) :
+        asio_endpoint_placeholder_(
+            new udp::endpoint(ip::address::from_string(address.toText()),
+                              port)),
+        asio_endpoint_(*asio_endpoint_placeholder_)
+    {}
+    UDPEndpoint(const udp::endpoint& asio_endpoint) :
+        asio_endpoint_placeholder_(NULL), asio_endpoint_(asio_endpoint)
+    {}
+    ~UDPEndpoint() { delete asio_endpoint_placeholder_; }
+    virtual IOAddress getAddress() const {
+        return (asio_endpoint_.address());
+    }
+private:
+    const udp::endpoint* asio_endpoint_placeholder_;
+    const udp::endpoint& asio_endpoint_;
+};
+
+const IOEndpoint*
+IOEndpoint::create(const int protocol, const IOAddress& address,
+                   const unsigned short port)
+{
+    if (protocol == IPPROTO_UDP) {
+        return (new UDPEndpoint(address, port));
+    } else if (protocol == IPPROTO_TCP) {
+        return (new TCPEndpoint(address, port));
+    }
+    isc_throw(IOError,
+              "IOEndpoint creation attempt for unsupported protocol: " <<
+              protocol);
+}
+
+class TCPSocket : public IOSocket {
+private:
+    TCPSocket(const TCPSocket& source);
+    TCPSocket& operator=(const TCPSocket& source);
+public:
+    TCPSocket(tcp::socket& socket) : socket_(socket) {}
+    virtual int getNative() const { return (socket_.native()); }
+    virtual int getProtocol() const { return (IPPROTO_TCP); }
+private:
+    tcp::socket& socket_;
+};
+
+class UDPSocket : public IOSocket {
+private:
+    UDPSocket(const UDPSocket& source);
+    UDPSocket& operator=(const UDPSocket& source);
+public:
+    UDPSocket(udp::socket& socket) : socket_(socket) {}
+    virtual int getNative() const { return (socket_.native()); }
+    virtual int getProtocol() const { return (IPPROTO_UDP); }
+private:
+    udp::socket& socket_;
+};
+
+class DummySocket : public IOSocket {
+private:
+    DummySocket(const DummySocket& source);
+    DummySocket& operator=(const DummySocket& source);
+public:
+    DummySocket(const int protocol) : protocol_(protocol) {}
+    virtual int getNative() const { return (-1); }
+    virtual int getProtocol() const { return (protocol_); }
+private:
+    const int protocol_;
+};
+
+IOSocket&
+IOSocket::getDummyUDPSocket() {
+    static DummySocket socket(IPPROTO_UDP);
+    return (socket);
+}
+
+IOSocket&
+IOSocket::getDummyTCPSocket() {
+    static DummySocket socket(IPPROTO_TCP);
+    return (socket);
+}
+
+IOMessage::IOMessage(const void* data, const size_t data_size,
+                     IOSocket& io_socket, const IOEndpoint& remote_endpoint) :
+    data_(data), data_size_(data_size), io_socket_(io_socket),
+    remote_endpoint_(remote_endpoint)
+{}
+
 //
 // Helper classes for asynchronous I/O using asio
 //
@@ -102,15 +186,18 @@
     TCPClient(AuthSrv* auth_server, io_service& io_service) :
         auth_server_(auth_server),
         socket_(io_service),
+        io_socket_(socket_),
         response_buffer_(0),
         responselen_buffer_(TCP_MESSAGE_LENGTHSIZE),
         response_renderer_(response_buffer_),
-        dns_message_(Message::PARSE)
+        dns_message_(Message::PARSE),
+        custom_callback_(NULL)
     {}
 
     void start() {
         // Check for queued configuration commands
-        if (auth_server_->configSession()->hasQueuedMsgs()) {
+        if (auth_server_ != NULL &&
+            auth_server_->configSession()->hasQueuedMsgs()) {
             auth_server_->configSession()->checkCommand();
         }
         async_read(socket_, asio::buffer(data_, TCP_MESSAGE_LENGTHSIZE),
@@ -129,7 +216,6 @@
 
             uint16_t msglen = dnsbuffer.readUint16();
             async_read(socket_, asio::buffer(data_, msglen),
-
                        boost::bind(&TCPClient::requestRead, this,
                                    placeholders::error,
                                    placeholders::bytes_transferred));
@@ -142,25 +228,28 @@
                      size_t bytes_transferred)
     {
         if (!error) {
-            InputBuffer dnsbuffer(data_, bytes_transferred);
-            if (check_axfr_query(data_, bytes_transferred)) {
-                dispatch_axfr_query(socket_.native(), data_, bytes_transferred); 
-                // start to get new query ?
+            const TCPEndpoint remote_endpoint(socket_.remote_endpoint());
+            const IOMessage io_message(data_, bytes_transferred, io_socket_,
+                                       remote_endpoint);
+            // currently, for testing purpose only
+            if (custom_callback_ != NULL) {
+                (*custom_callback_)(io_message);
                 start();
+                return;
+            }
+
+            if (auth_server_->processMessage(io_message, dns_message_,
+                                             response_renderer_)) {
+                responselen_buffer_.writeUint16(
+                    response_buffer_.getLength());
+                async_write(socket_,
+                            asio::buffer(
+                                responselen_buffer_.getData(),
+                                responselen_buffer_.getLength()),
+                            boost::bind(&TCPClient::responseWrite, this,
+                                        placeholders::error));
             } else {
-                if (auth_server_->processMessage(dnsbuffer, dns_message_,
-                                                response_renderer_, false)) {
-                    responselen_buffer_.writeUint16(
-                        response_buffer_.getLength());
-                    async_write(socket_,
-                                asio::buffer(
-                                    responselen_buffer_.getData(),
-                                    responselen_buffer_.getLength()),
-                                boost::bind(&TCPClient::responseWrite, this,
-                                            placeholders::error));
-                } else {
-                    delete this;
-                }
+                delete this;
             }
         } else {
             delete this;
@@ -171,9 +260,9 @@
         if (!error) {
                 async_write(socket_,
                             asio::buffer(response_buffer_.getData(),
-                                                response_buffer_.getLength()),
-                        boost::bind(&TCPClient::handleWrite, this,
-                                    placeholders::error));
+                                         response_buffer_.getLength()),
+                            boost::bind(&TCPClient::handleWrite, this,
+                                        placeholders::error));
         } else {
             delete this;
         }
@@ -187,9 +276,15 @@
       }
     }
 
+    // Currently this is for tests only
+    void setCallBack(const IOService::IOCallBack* callback) {
+        custom_callback_ = callback;
+    }
+
 private:
     AuthSrv* auth_server_;
     tcp::socket socket_;
+    TCPSocket io_socket_;
     OutputBuffer response_buffer_;
     OutputBuffer responselen_buffer_;
     MessageRenderer response_renderer_;
@@ -197,21 +292,25 @@
     enum { MAX_LENGTH = 65535 };
     static const size_t TCP_MESSAGE_LENGTHSIZE = 2;
     char data_[MAX_LENGTH];
+
+    // currently, for testing purpose only.
+    const IOService::IOCallBack* custom_callback_;
 };
 
 class TCPServer {
 public:
     TCPServer(AuthSrv* auth_server, io_service& io_service,
-              int af, uint16_t port) :
+              const ip::address& addr, const uint16_t port) :
         auth_server_(auth_server), io_service_(io_service),
         acceptor_(io_service_), listening_(new TCPClient(auth_server_,
-                                                         io_service_))
-    {
-        tcp::endpoint endpoint(af == AF_INET6 ? tcp::v6() : tcp::v4(), port);
+                                                         io_service_)),
+        custom_callback_(NULL)
+    {
+        tcp::endpoint endpoint(addr, port);
         acceptor_.open(endpoint.protocol());
         // Set v6-only (we use a different instantiation for v4,
         // otherwise asio will bind to both v4 and v6
-        if (af == AF_INET6) {
+        if (addr.is_v6()) {
             acceptor_.set_option(ip::v6_only(true));
         }
         acceptor_.set_option(tcp::acceptor::reuse_address(true));
@@ -222,23 +321,6 @@
                                            listening_, placeholders::error));
     }
 
-    TCPServer(AuthSrv* auth_server, io_service& io_service,
-              asio::ip::address addr, uint16_t port) :
-        auth_server_(auth_server),
-        io_service_(io_service), acceptor_(io_service_),
-        listening_(new TCPClient(auth_server, io_service_))
-    {
-        tcp::endpoint endpoint(addr, port);
-        acceptor_.open(endpoint.protocol());
-
-        acceptor_.set_option(tcp::acceptor::reuse_address(true));
-        acceptor_.bind(endpoint);
-        acceptor_.listen();
-        acceptor_.async_accept(listening_->getSocket(),
-                               boost::bind(&TCPServer::handleAccept, this,
-                                           listening_, placeholders::error));
-    }
-
     ~TCPServer() { delete listening_; }
 
     void handleAccept(TCPClient* new_client,
@@ -246,6 +328,7 @@
     {
         if (!error) {
             assert(new_client == listening_);
+            new_client->setCallBack(custom_callback_);
             new_client->start();
             listening_ = new TCPClient(auth_server_, io_service_);
             acceptor_.async_accept(listening_->getSocket(),
@@ -257,44 +340,43 @@
         }
     }
 
+    // Currently this is for tests only
+    void setCallBack(const IOService::IOCallBack* callback) {
+        custom_callback_ = callback;
+    }
+
 private:
     AuthSrv* auth_server_;
     io_service& io_service_;
     tcp::acceptor acceptor_;
     TCPClient* listening_;
+
+    // currently, for testing purpose only.
+    const IOService::IOCallBack* custom_callback_;
 };
 
 class UDPServer {
 public:
     UDPServer(AuthSrv* auth_server, io_service& io_service,
-              int af, uint16_t port) :
+              const ip::address& addr, const uint16_t port) :
         auth_server_(auth_server),
         io_service_(io_service),
-        socket_(io_service, af == AF_INET6 ? udp::v6() : udp::v4()),
+        socket_(io_service, addr.is_v6() ? udp::v6() : udp::v4()),
+        io_socket_(socket_),
         response_buffer_(0),
         response_renderer_(response_buffer_),
-        dns_message_(Message::PARSE)
-    {
+        dns_message_(Message::PARSE),
+        custom_callback_(NULL)
+    {
+        socket_.set_option(socket_base::reuse_address(true));
         // Set v6-only (we use a different instantiation for v4,
         // otherwise asio will bind to both v4 and v6
-        if (af == AF_INET6) {
+        if (addr.is_v6()) {
             socket_.set_option(asio::ip::v6_only(true));
-            socket_.bind(udp::endpoint(udp::v6(), port));
+            socket_.bind(udp::endpoint(addr, port));
         } else {
-            socket_.bind(udp::endpoint(udp::v4(), port));
-        }
-        startReceive();
-    }
-
-    UDPServer(AuthSrv* auth_server, io_service& io_service,
-              asio::ip::address addr, uint16_t port) :
-        auth_server_(auth_server), io_service_(io_service),
-        socket_(io_service, addr.is_v6() ? udp::v6() : udp::v4()),
-        response_buffer_(0),
-        response_renderer_(response_buffer_),
-        dns_message_(Message::PARSE)
-    {
-        socket_.bind(udp::endpoint(addr, port));
+            socket_.bind(udp::endpoint(addr, port));
+        }
         startReceive();
     }
 
@@ -302,16 +384,25 @@
                        size_t bytes_recvd)
     {
         // Check for queued configuration commands
-        if (auth_server_->configSession()->hasQueuedMsgs()) {
+        if (auth_server_ != NULL &&
+            auth_server_->configSession()->hasQueuedMsgs()) {
             auth_server_->configSession()->checkCommand();
         }
         if (!error && bytes_recvd > 0) {
-            InputBuffer request_buffer(data_, bytes_recvd);
+            const UDPEndpoint remote_endpoint(sender_endpoint_);
+            const IOMessage io_message(data_, bytes_recvd, io_socket_,
+                                       remote_endpoint);
+            // currently, for testing purpose only
+            if (custom_callback_ != NULL) {
+                (*custom_callback_)(io_message);
+                startReceive();
+                return;
+            }
 
             dns_message_.clear(Message::PARSE);
             response_renderer_.clear();
-            if (auth_server_->processMessage(request_buffer, dns_message_,
-                                            response_renderer_, true)) {
+            if (auth_server_->processMessage(io_message, dns_message_,
+                                             response_renderer_)) {
                 socket_.async_send_to(
                     asio::buffer(response_buffer_.getData(),
                                         response_buffer_.getLength()),
@@ -335,6 +426,11 @@
         // the next request.
         startReceive();
     }
+
+    // Currently this is for tests only
+    void setCallBack(const IOService::IOCallBack* callback) {
+        custom_callback_ = callback;
+    }
 private:
     void startReceive() {
         socket_.async_receive_from(
@@ -348,121 +444,107 @@
     AuthSrv* auth_server_;
     io_service& io_service_;
     udp::socket socket_;
+    UDPSocket io_socket_;
     OutputBuffer response_buffer_;
     MessageRenderer response_renderer_;
     Message dns_message_;
     udp::endpoint sender_endpoint_;
     enum { MAX_LENGTH = 4096 };
     char data_[MAX_LENGTH];
-};
-
-// This is a helper structure just to make the construction of IOServiceImpl
-// exception safe.  If the constructor of {UDP/TCP}Server throws an exception,
-// the destructor of this class will automatically perform the necessary
-// cleanup.
-struct ServerSet {
-    ServerSet() : udp4_server(NULL), udp6_server(NULL),
-                  tcp4_server(NULL), tcp6_server(NULL)
-    {}
-    ~ServerSet() {
-        delete udp4_server;
-        delete udp6_server;
-        delete tcp4_server;
-        delete tcp6_server;
-    }
-    UDPServer* udp4_server;
-    UDPServer* udp6_server;
-    TCPServer* tcp4_server;
-    TCPServer* tcp6_server;
+
+    // currently, for testing purpose only.
+    const IOService::IOCallBack* custom_callback_;
 };
 
 class IOServiceImpl {
 public:
-    IOServiceImpl(AuthSrv* auth_server, const char* address, const char* port,
-                  const bool use_ipv4, const bool use_ipv6);
-    ~IOServiceImpl();
+    IOServiceImpl(AuthSrv* auth_server, const char& port,
+                  const ip::address* v4addr, const ip::address* v6addr);
     asio::io_service io_service_;
     AuthSrv* auth_server_;
-    UDPServer* udp4_server_;
-    UDPServer* udp6_server_;
-    TCPServer* tcp4_server_;
-    TCPServer* tcp6_server_;
-};
-
-IOServiceImpl::IOServiceImpl(AuthSrv* auth_server, const char* const address,
-                             const char* const port, const bool use_ipv4,
-                             const bool use_ipv6) :
-    auth_server_(auth_server), udp4_server_(NULL), udp6_server_(NULL),
-    tcp4_server_(NULL), tcp6_server_(NULL)
+
+    typedef boost::shared_ptr<UDPServer> UDPServerPtr;
+    typedef boost::shared_ptr<TCPServer> TCPServerPtr;
+    UDPServerPtr udp4_server_;
+    UDPServerPtr udp6_server_;
+    TCPServerPtr tcp4_server_;
+    TCPServerPtr tcp6_server_;
+
+    // This member is used only for testing at the moment.
+    IOService::IOCallBack callback_;
+};
+
+IOServiceImpl::IOServiceImpl(AuthSrv* auth_server, const char& port,
+                             const ip::address* const v4addr,
+                             const ip::address* const v6addr) :
+    auth_server_(auth_server),
+    udp4_server_(UDPServerPtr()), udp6_server_(UDPServerPtr()),
+    tcp4_server_(TCPServerPtr()), tcp6_server_(TCPServerPtr())
 {
-    ServerSet servers;
-    uint16_t portnum = atoi(port);
+    uint16_t portnum;
 
     try {
-        portnum = boost::lexical_cast<uint16_t>(port);
-    } catch (const std::exception& ex) {
-        isc_throw(FatalError, "[b10-auth] Invalid port number '"
-                              << port << "'");
-    }
-
-    if (address != NULL) {
-        asio::ip::address addr = asio::ip::address::from_string(address);
-
-        if ((addr.is_v6() && !use_ipv6)) {
-            isc_throw(FatalError,
-                      "[b10-auth] Error: -4 conflicts with " << addr);
-        }
-
-        if ((addr.is_v4() && !use_ipv4)) {
-            isc_throw(FatalError,
-                      "[b10-auth] Error: -6 conflicts with " << addr);
-        }
-
-        if (addr.is_v4()) {
-            servers.udp4_server = new UDPServer(auth_server, io_service_,
-                                                addr, portnum);
-            servers.tcp4_server = new TCPServer(auth_server, io_service_,
-                                                addr, portnum);
-         } else {
-            servers.udp6_server = new UDPServer(auth_server, io_service_,
-                                                addr, portnum);
-            servers.tcp6_server = new TCPServer(auth_server, io_service_,
-                                                addr, portnum);
-        }
-    } else {
-        if (use_ipv4) {
-            servers.udp4_server = new UDPServer(auth_server, io_service_,
-                                                AF_INET, portnum);
-            servers.tcp4_server = new TCPServer(auth_server, io_service_,
-                                                AF_INET, portnum);
-        }
-        if (use_ipv6) {
-            servers.udp6_server = new UDPServer(auth_server, io_service_,
-                                                AF_INET6, portnum);
-            servers.tcp6_server = new TCPServer(auth_server, io_service_,
-                                                AF_INET6, portnum);
-        }
-    }
-
-    // Now we don't have to worry about exception, and need to make sure that
-    // the server objects won't be accidentally cleaned up.
-    servers.udp4_server = NULL;
-    servers.udp6_server = NULL;
-    servers.tcp4_server = NULL;
-    servers.tcp6_server = NULL;
-}
-
-IOServiceImpl::~IOServiceImpl() {
-    delete udp4_server_;
-    delete udp6_server_;
-    delete tcp4_server_;
-    delete tcp6_server_;
-}
-
-IOService::IOService(AuthSrv* auth_server, const char* const address,
-                     const char* const port, const bool use_ipv4,
-                     const bool use_ipv6) {
-    impl_ = new IOServiceImpl(auth_server, address, port, use_ipv4, use_ipv6);
+        // XXX: SunStudio with stlport4 doesn't reject some invalid
+        // representation such as "-1" by lexical_cast<uint16_t>, so
+        // we convert it into a signed integer of a larger size and perform
+        // range check ourselves.
+        const int32_t portnum32 = boost::lexical_cast<int32_t>(&port);
+        if (portnum32 < 0 || portnum32 > 65535) {
+            isc_throw(IOError, "Invalid port number '" << &port);
+        }
+        portnum = portnum32;
+    } catch (const boost::bad_lexical_cast& ex) {
+        isc_throw(IOError, "Invalid port number '" << &port << "': " <<
+                  ex.what());
+    }
+
+    try {
+        if (v4addr != NULL) {
+            udp4_server_ = UDPServerPtr(new UDPServer(auth_server, io_service_,
+                                                      *v4addr, portnum));
+            tcp4_server_ = TCPServerPtr(new TCPServer(auth_server, io_service_,
+                                                      *v4addr, portnum));
+        }
+        if (v6addr != NULL) {
+            udp6_server_ = UDPServerPtr(new UDPServer(auth_server, io_service_,
+                                                      *v6addr, portnum));
+            tcp6_server_ = TCPServerPtr(new TCPServer(auth_server, io_service_,
+                                                      *v6addr, portnum));
+        }
+    } catch (const asio::system_error& err) {
+        // We need to catch and convert any ASIO level exceptions.
+        // This can happen for unavailable address, binding a privilege port
+        // without the privilege, etc.
+        isc_throw(IOError, "Failed to initialize network servers: " <<
+                  err.what());
+    }
+}
+
+IOService::IOService(AuthSrv* auth_server, const char& port,
+                     const char& address) :
+    impl_(NULL)
+{
+    error_code err;
+    const ip::address addr = ip::address::from_string(&address, err);
+    if (err) {
+        isc_throw(IOError, "Invalid IP address '" << &address << "': "
+                  << err.message());
+    }
+
+    impl_ = new IOServiceImpl(auth_server, port,
+                              addr.is_v4() ? &addr : NULL,
+                              addr.is_v6() ? &addr : NULL);
+}
+
+IOService::IOService(AuthSrv* auth_server, const char& port,
+                     const bool use_ipv4, const bool use_ipv6) :
+    impl_(NULL)
+{
+    const ip::address v4addr_any = ip::address(ip::address_v4::any());
+    const ip::address* const v4addrp = use_ipv4 ? &v4addr_any : NULL; 
+    const ip::address v6addr_any = ip::address(ip::address_v6::any());
+    const ip::address* const v6addrp = use_ipv6 ? &v6addr_any : NULL;
+    impl_ = new IOServiceImpl(auth_server, port, v4addrp, v6addrp);
 }
 
 IOService::~IOService() {
@@ -481,6 +563,23 @@
 
 asio::io_service&
 IOService::get_io_service() {
-    return impl_->io_service_;
-}
-}
+    return (impl_->io_service_);
+}
+
+void
+IOService::setCallBack(const IOCallBack callback) {
+    impl_->callback_ = callback;
+    if (impl_->udp4_server_ != NULL) {
+        impl_->udp4_server_->setCallBack(&impl_->callback_);
+    }
+    if (impl_->udp6_server_ != NULL) {
+        impl_->udp6_server_->setCallBack(&impl_->callback_);
+    }
+    if (impl_->tcp4_server_ != NULL) {
+        impl_->tcp4_server_->setCallBack(&impl_->callback_);
+    }
+    if (impl_->tcp6_server_ != NULL) {
+        impl_->tcp6_server_->setCallBack(&impl_->callback_);
+    }
+}
+}

Modified: branches/trac232/src/bin/auth/asio_link.h
==============================================================================
--- branches/trac232/src/bin/auth/asio_link.h (original)
+++ branches/trac232/src/bin/auth/asio_link.h Wed Sep  1 00:35:07 2010
@@ -17,20 +17,430 @@
 #ifndef __ASIO_LINK_H
 #define __ASIO_LINK_H 1
 
+// IMPORTANT NOTE: only very few ASIO headers files can be included in
+// this file.  In particular, asio.hpp should never be included here.
+// See the description of the namespace below.
+#include <unistd.h>             // for some network system calls
+#include <asio/ip/address.hpp>
+
+#include <functional>
+#include <string>
+
+#include <boost/function.hpp>
+
+#include <exceptions/exceptions.h>
+
+namespace asio {
+// forward declaration for IOService::get_io_service() below
+class io_service;
+}
+
 class AuthSrv;
+
+/// \namespace asio_link
+/// \brief A wrapper interface for the ASIO library.
+///
+/// The \c asio_link namespace is used to define a set of wrapper interfaces
+/// for the ASIO library.
+///
+/// BIND 10 uses the non-Boost version of ASIO because it's header-only,
+/// i.e., does not require a separate library object to be linked, and thus
+/// lowers the bar for introduction.
+///
+/// But the advantage comes with its own costs: since the header-only version
+/// includes more definitions in public header files, it tends to trigger
+/// more compiler warnings for our own sources, and, depending on the
+/// compiler options, may make the build fail.
+///
+/// We also found it may be tricky to use ASIO and standard C++ libraries
+/// in a single translation unit, i.e., a .cc file: depending on the order
+/// of including header files, ASIO may or may not work on some platforms.
+///
+/// This wrapper interface is intended to centralize these
+/// problematic issues in a single sub module.  Other BIND 10 modules should
+/// simply include \c asio_link.h and use the wrapper API instead of
+/// including ASIO header files and using ASIO-specific classes directly.
+///
+/// This wrapper may be used for other IO libraries if and when we want to
+/// switch, but generality for that purpose is not the primary goal of
+/// this module.  The resulting interfaces are thus straightforward mapping
+/// to the ASIO counterparts.
+///
+/// Notes to developers:
+/// Currently the wrapper interface is specific to the authoritative
+/// server implementation.  But the plan is to generalize it and have
+/// other modules use it.
+///
+/// One obvious drawback of this approach is performance overhead
+/// due to the additional layer.  We should eventually evaluate the cost
+/// of the wrapper abstraction in benchmark tests. Another drawback is
+/// that the wrapper interfaces don't provide all features of ASIO
+/// (at least for the moment).  We should also re-evaluate the
+/// maintenance overhead of providing necessary wrappers as we develop
+/// more.
+///
+/// On the other hand, we may be able to exploit the wrapper approach to
+/// simplify the interfaces (by limiting the usage) and unify performance
+/// optimization points.
+///
+/// As for optimization, we may want to provide a custom allocator for
+/// the placeholder of callback handlers:
+/// http://think-async.com/Asio/asio-1.3.1/doc/asio/reference/asio_handler_allocate.html
 
 namespace asio_link {
 struct IOServiceImpl;
 
+/// \brief An exception that is thrown if an error occurs within the IO
+/// module.  This is mainly intended to be a wrapper exception class for
+/// ASIO specific exceptions.
+class IOError : public isc::Exception {
+public:
+    IOError(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+/// \brief The \c IOAddress class represents an IP addresses (version
+/// agnostic)
+///
+/// This class is a wrapper for the ASIO \c ip::address class.
+class IOAddress {
+public:
+    ///
+    /// \name Constructors and Destructor
+    ///
+    /// This class is copyable.  We use default versions of copy constructor
+    /// and the assignment operator.
+    /// We use the default destructor.
+    //@{
+    /// \brief Constructor from string.
+    ///
+    /// This constructor converts a textual representation of IPv4 and IPv6
+    /// addresses into an IOAddress object.
+    /// If \c address_str is not a valid representation of any type of
+    /// address, an exception of class \c IOError will be thrown.
+    /// This constructor allocates memory for the object, and if that fails
+    /// a corresponding standard exception will be thrown.
+    ///
+    /// \param address_str Textual representation of address.
+    IOAddress(const std::string& address_str);
+
+    /// \brief Constructor from an ASIO \c ip::address object.
+    ///
+    /// This constructor is intended to be used within the wrapper
+    /// implementation; user applications of the wrapper API won't use it.
+    ///
+    /// This constructor never throws an exception.
+    ///
+    /// \param asio_address The ASIO \c ip::address to be converted.
+    IOAddress(const asio::ip::address& asio_adress);
+    //@}
+
+    /// \brief Convert the address to a string.
+    ///
+    /// This method is basically expected to be exception free, but
+    /// generating the string will involve resource allocation,
+    /// and if it fails the corresponding standard exception will be thrown.
+    ///
+    /// \return A string representation of the address.
+    std::string toText() const;
+private:
+    asio::ip::address asio_address_;
+};
+
+/// \brief The \c IOEndpoint class is an abstract base class to represent
+/// a communication endpoint.
+///
+/// This class is a wrapper for the ASIO endpoint classes such as
+/// \c ip::tcp::endpoint and \c ip::udp::endpoint.
+///
+/// Derived class implementations are completely hidden within the
+/// implementation.  User applications only get access to concrete
+/// \c IOEndpoint objects via the abstract interfaces.
+class IOEndpoint {
+    ///
+    /// \name Constructors and Destructor
+    ///
+    /// Note: The copy constructor and the assignment operator are
+    /// intentionally defined as private, making this class non-copyable.
+    //@{
+private:
+    IOEndpoint(const IOEndpoint& source);
+    IOEndpoint& operator=(const IOEndpoint& source);
+protected:
+    /// \brief The default constructor.
+    ///
+    /// This is intentionally defined as \c protected as this base class
+    /// should never be instantiated (except as part of a derived class).
+    IOEndpoint() {}
+public:
+    /// The destructor.
+    virtual ~IOEndpoint() {}
+    //@}
+
+    /// \brief Returns the address of the endpoint.
+    ///
+    /// This method returns an IOAddress object corresponding to \c this
+    /// endpoint.
+    /// Note that the return value is a real object, not a reference or
+    /// a pointer.
+    /// This is aligned with the interface of the ASIO counterpart:
+    /// the \c address() method of \c ip::xxx::endpoint classes returns
+    /// an \c ip::address object.
+    /// This also means handling the address of an endpoint using this method
+    /// can be expensive.  If the address information is necessary in a
+    /// performance sensitive context and there's a more efficient interface
+    /// for that purpose, it's probably better to avoid using this method.
+    ///
+    /// This method never throws an exception.
+    ///
+    /// \return A copy of \c IOAddress object corresponding to the endpoint.
+    virtual IOAddress getAddress() const = 0;
+
+    /// \brief A polymorphic factory of endpoint from address and port.
+    ///
+    /// This method creates a new instance of (a derived class of)
+    /// \c IOEndpoint object that identifies the pair of given address
+    /// and port.
+    /// The appropriate derived class is chosen based on the specified
+    /// transport protocol.  If the \c protocol doesn't specify a protocol
+    /// supported in this implementation, an exception of class \c IOError
+    /// will be thrown.
+    ///
+    /// Memory for the created object will be dynamically allocated.  It's
+    /// the caller's responsibility to \c delete it later.
+    /// If resource allocation for the new object fails, a corresponding
+    /// standard exception will be thrown.
+    ///
+    /// \param protocol The transport protocol used for the endpoint.
+    /// Currently, only \c IPPROTO_UDP and \c IPPROTO_TCP can be specified.
+    /// \param address The (IP) address of the endpoint.
+    /// \param port The transport port number of the endpoint
+    /// \return A pointer to a newly created \c IOEndpoint object.
+    static const IOEndpoint* create(const int protocol,
+                                    const IOAddress& address,
+                                    const unsigned short port);
+};
+
+/// \brief The \c IOSocket class is an abstract base class to represent
+/// various types of network sockets.
+///
+/// This class is a wrapper for the ASIO socket classes such as
+/// \c ip::tcp::socket and \c ip::udp::socket.
+///
+/// Derived class implementations are completely hidden within the
+/// implementation.  User applications only get access to concrete
+/// \c IOSocket objects via the abstract interfaces.
+/// We may revisit this decision when we generalize the wrapper and more
+/// modules use it.  Also, at that point we may define a separate (visible)
+/// derived class for testing purposes rather than providing factory methods
+/// (i.e., getDummy variants below).
+class IOSocket {
+    ///
+    /// \name Constructors and Destructor
+    ///
+    /// Note: The copy constructor and the assignment operator are
+    /// intentionally defined as private, making this class non-copyable.
+    //@{
+private:
+    IOSocket(const IOSocket& source);
+    IOSocket& operator=(const IOSocket& source);
+protected:
+    /// \brief The default constructor.
+    ///
+    /// This is intentionally defined as \c protected as this base class
+    /// should never be instantiated (except as part of a derived class).
+    IOSocket() {}
+public:
+    /// The destructor.
+    virtual ~IOSocket() {}
+    //@}
+
+    /// \brief Return the "native" representation of the socket.
+    ///
+    /// In practice, this is the file descriptor of the socket for
+    /// UNIX-like systems so the current implementation simply uses
+    /// \c int as the type of the return value.
+    /// We may have to need revisit this decision later.
+    ///
+    /// In general, the application should avoid using this method;
+    /// it essentially discloses an implementation specific "handle" that
+    /// can change the internal state of the socket (consider the
+    /// application closes it, for example).
+    /// But we sometimes need to perform very low-level operations that
+    /// requires the native representation.  Passing the file descriptor
+    /// to a different process is one example.
+    /// This method is provided as a necessary evil for such limited purposes.
+    ///
+    /// This method never throws an exception.
+    ///
+    /// \return The native representation of the socket.  This is the socket
+    /// file descriptor for UNIX-like systems.
+    virtual int getNative() const = 0;
+
+    /// \brief Return the transport protocol of the socket.
+    ///
+    /// Currently, it returns \c IPPROTO_UDP for UDP sockets, and
+    /// \c IPPROTO_TCP for TCP sockets.
+    ///
+    /// This method never throws an exception.
+    ///
+    /// \return IPPROTO_UDP for UDP sockets
+    /// \return IPPROTO_TCP for TCP sockets
+    virtual int getProtocol() const = 0;
+
+    /// \brief Return a non-usable "dummy" UDP socket for testing.
+    ///
+    /// This is a class method that returns a "mock" of UDP socket.
+    /// This is not associated with any actual socket, and its only
+    /// responsibility is to return \c IPPROTO_UDP from \c getProtocol().
+    /// The only feasible usage of this socket is for testing so that
+    /// the test code can prepare some "UDP data" even without opening any
+    /// actual socket.
+    ///
+    /// This method never throws an exception.
+    ///
+    /// \return A reference to an \c IOSocket object whose \c getProtocol()
+    /// returns \c IPPROTO_UDP.
+    static IOSocket& getDummyUDPSocket();
+
+    /// \brief Return a non-usable "dummy" TCP socket for testing.
+    ///
+    /// See \c getDummyUDPSocket().  This method is its TCP version.
+    ///
+    /// \return A reference to an \c IOSocket object whose \c getProtocol()
+    /// returns \c IPPROTO_TCP.
+    static IOSocket& getDummyTCPSocket();
+};
+
+/// \brief The \c IOMessage class encapsulates an incoming message received
+/// on a socket.
+///
+/// An \c IOMessage object represents a tuple of a chunk of data
+/// (a UDP packet or some segment of TCP stream), the socket over which the
+/// data is passed, the information about the other end point of the
+/// communication, and perhaps more.
+///
+/// The current design and interfaces of this class is tentative.
+/// It only provides a minimal level of support that is necessary for
+/// the current implementation of the authoritative server.
+/// A future version of this class will definitely support more.
+class IOMessage {
+    ///
+    /// \name Constructors and Destructor
+    ///
+    /// Note: The copy constructor and the assignment operator are
+    /// intentionally defined as private, making this class non-copyable.
+    //@{
+private:
+    IOMessage(const IOMessage& source);
+    IOMessage& operator=(const IOMessage& source);
+public:
+    /// \brief Constructor from message information.
+    ///
+    /// This constructor needs to handle the ASIO \c ip::address class,
+    /// and is intended to be used within this wrapper implementation.
+    /// Once the \c IOMessage object is created, the application can
+    /// get access to the information via the wrapper interface such as
+    /// \c getRemoteAddress().
+    ///
+    /// This constructor never throws an exception.
+    ///
+    /// \param data A pointer to the message data.
+    /// \param data_size The size of the message data in bytes.
+    /// \param io_socket The socket over which the data is given.
+    /// \param remote_endpoint The other endpoint of the socket, that is,
+    /// the sender of the message.
+    IOMessage(const void* data, const size_t data_size, IOSocket& io_socket,
+              const IOEndpoint& remote_endpoint);
+    //@}
+
+    /// \brief Returns a pointer to the received data.
+    const void* getData() const { return (data_); }
+
+    /// \brief Returns the size of the received data in bytes.
+    size_t getDataSize() const { return (data_size_); }
+
+    /// \brief Returns the socket on which the message arrives.
+    const IOSocket& getSocket() const { return (io_socket_); }
+
+    /// \brief Returns the endpoint that sends the message.
+    const IOEndpoint& getRemoteEndpoint() const { return (remote_endpoint_); }
+private:
+    const void* data_;
+    const size_t data_size_;
+    IOSocket& io_socket_;
+    const IOEndpoint& remote_endpoint_;
+};
+
+/// \brief The \c IOService class is a wrapper for the ASIO \c io_service
+/// class.
+///
+/// Currently, the interface of this class is very specific to the
+/// authoritative server implementation as indicated in the signature of
+/// the constructor, but the plan is to generalize it so that other BIND 10
+/// modules can use this interface, too.
 class IOService {
-public:
-    IOService(AuthSrv* auth_server,
-              const char* const address, const char* const port,
+    ///
+    /// \name Constructors and Destructor
+    ///
+    /// These are currently very specific to the authoritative server
+    /// implementation.
+    ///
+    /// Note: The copy constructor and the assignment operator are
+    /// intentionally defined as private, making this class non-copyable.
+    //@{
+private:
+    IOService(const IOService& source);
+    IOService& operator=(const IOService& source);
+public:
+    /// \brief The constructor with a specific IP address and port on which
+    /// the services listen on.
+    IOService(AuthSrv* auth_server, const char& port, const char& address);
+    /// \brief The constructor with a specific port on which the services
+    /// listen on.
+    ///
+    /// It effectively listens on "any" IPv4 and/or IPv6 addresses.
+    /// IPv4/IPv6 services will be available if and only if \c use_ipv4
+    /// or \c use_ipv6 is \c true, respectively.
+    IOService(AuthSrv* auth_server, const char& port,
               const bool use_ipv4, const bool use_ipv6);
+    /// \brief The destructor.
     ~IOService();
+    //@}
+
+    /// \brief Start the underlying event loop.
+    ///
+    /// This method does not return control to the caller until
+    /// the \c stop() method is called via some handler.
     void run();
+
+    /// \brief Stop the underlying event loop.
+    ///
+    /// This will return the control to the caller of the \c run() method.
     void stop();
+
+    /// \brief Return the native \c io_service object used in this wrapper.
+    ///
+    /// This is a short term work around to support other BIND 10 modules
+    /// that share the same \c io_service with the authoritative server.
+    /// It will eventually be removed once the wrapper interface is
+    /// generalized.
     asio::io_service& get_io_service();
+
+    /// \brief A functor(-like) class that specifies a custom call back
+    /// invoked from the event loop instead of the embedded authoritative
+    /// server callbacks.
+    ///
+    /// Currently, the callback is intended to be used only for testing
+    /// purposes.  But we'll need a generic callback type like this to
+    /// generalize the wrapper interface.
+    typedef boost::function<void(const IOMessage& io_message)> IOCallBack;
+
+    /// \brief Set the custom call back invoked from the event loop.
+    ///
+    /// Right now this method is only for testing, but will eventually be
+    /// generalized.
+    void setCallBack(IOCallBack callback);
 private:
     IOServiceImpl* impl_;
 };

Modified: branches/trac232/src/bin/auth/auth.spec.pre.in
==============================================================================
--- branches/trac232/src/bin/auth/auth.spec.pre.in (original)
+++ branches/trac232/src/bin/auth/auth.spec.pre.in Wed Sep  1 00:35:07 2010
@@ -5,7 +5,7 @@
     "config_data": [
       { "item_name": "database_file",
         "item_type": "string",
-        "item_optional": True,
+        "item_optional": true,
         "item_default": "@@LOCALSTATEDIR@@/@PACKAGE@/zone.sqlite3"
       }
     ],
@@ -21,32 +21,32 @@
         "command_args": [
           { "item_name": "zone_name",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": ""
           },
           { "item_name": "rr_name",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": ""
           },
           { "item_name": "rr_class",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": ""
           },
           { "item_name": "rr_type",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": ""
           },
           { "item_name": "rr_ttl",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": ""
           },
           { "item_name": "rr_rdata",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": ""
           }
         ]
@@ -57,27 +57,27 @@
         "command_args": [
           { "item_name": "zone_name",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": ""
           },
           { "item_name": "rr_name",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": ""
           },
           { "item_name": "rr_class",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": ""
           },
           { "item_name": "rr_type",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": ""
           },
           { "item_name": "rr_rdata",
             "item_type": "string",
-            "item_optional": True,
+            "item_optional": true,
             "item_default": ""
           }
         ]
@@ -88,17 +88,17 @@
         "command_args": [
           { "item_name": "zone_name",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": ""
           },
           { "item_name": "rr_class",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": ""
           },
           { "item_name": "file_name",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": ""
           },
         ]
@@ -109,17 +109,17 @@
         "command_args": [
           { "item_name": "zone_name",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": ""
           },
           { "item_name": "rr_class",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": ""
           },
           { "item_name": "response_file",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": ""
           }
         ]

Modified: branches/trac232/src/bin/auth/auth_srv.cc
==============================================================================
--- branches/trac232/src/bin/auth/auth_srv.cc (original)
+++ branches/trac232/src/bin/auth/auth_srv.cc Wed Sep  1 00:35:07 2010
@@ -14,6 +14,8 @@
 
 // $Id$
 
+#include <netinet/in.h>
+
 #include <algorithm>
 #include <cassert>
 #include <iostream>
@@ -41,10 +43,11 @@
 
 #include <cc/data.h>
 
-#include "common.h"
-#include "auth_srv.h"
-
-#include <boost/lexical_cast.hpp>
+#include <xfr/xfrout_client.h>
+
+#include <auth/common.h>
+#include <auth/auth_srv.h>
+#include <auth/asio_link.h>
 
 #include <fstream>
 #include <sstream>
@@ -53,11 +56,14 @@
 using namespace std;
 
 using namespace isc;
+using namespace isc::cc;
 using namespace isc::datasrc;
 using namespace isc::dns;
 using namespace isc::dns::rdata;
 using namespace isc::data;
 using namespace isc::config;
+using namespace isc::xfr;
+using namespace asio_link;
 
 class AuthSrvImpl {
 private:
@@ -65,12 +71,18 @@
     AuthSrvImpl(const AuthSrvImpl& source);
     AuthSrvImpl& operator=(const AuthSrvImpl& source);
 public:
-    AuthSrvImpl(const bool use_cache);
-
-    isc::data::ElementPtr setDbFile(const isc::data::ElementPtr config);
-
+    AuthSrvImpl(const bool use_cache, AbstractXfroutClient& xfrout_client);
+    ~AuthSrvImpl();
+    isc::data::ConstElementPtr setDbFile(isc::data::ConstElementPtr config);
+
+    bool processNormalQuery(const IOMessage& io_message, Message& message,
+                            MessageRenderer& response_renderer);
+    bool processAxfrQuery(const IOMessage& io_message, Message& message,
+                            MessageRenderer& response_renderer);
+    bool processNotify(const IOMessage& io_message, Message& message, 
+                            MessageRenderer& response_renderer);
     std::string db_file_;
-    ModuleCCSession* cs_;
+    ModuleCCSession* config_session_;
     MetaDataSrc data_sources_;
     /// We keep a pointer to the currently running sqlite datasource
     /// so that we can specifically remove that one should the database
@@ -79,6 +91,11 @@
 
     bool verbose_mode_;
 
+    AbstractSession* xfrin_session_;
+
+    bool xfrout_connected_;
+    AbstractXfroutClient& xfrout_client_;
+
     /// Currently non-configurable, but will be.
     static const uint16_t DEFAULT_LOCAL_UDPSIZE = 4096;
 
@@ -86,8 +103,12 @@
     isc::datasrc::HotCache cache_;
 };
 
-AuthSrvImpl::AuthSrvImpl(const bool use_cache) :
-    cs_(NULL), verbose_mode_(false)
+AuthSrvImpl::AuthSrvImpl(const bool use_cache,
+                         AbstractXfroutClient& xfrout_client) :
+    config_session_(NULL), verbose_mode_(false),
+    xfrin_session_(NULL),
+    xfrout_connected_(false),
+    xfrout_client_(xfrout_client)
 {
     // cur_datasrc_ is automatically initialized by the default constructor,
     // effectively being an empty (sqlite) data source.  once ccsession is up
@@ -100,8 +121,16 @@
     cache_.setEnabled(use_cache);
 }
 
-AuthSrv::AuthSrv(const bool use_cache) : impl_(new AuthSrvImpl(use_cache)) {
-}
+AuthSrvImpl::~AuthSrvImpl() {
+    if (xfrout_connected_) {
+        xfrout_client_.disconnect();
+        xfrout_connected_ = false;
+    }
+}
+
+AuthSrv::AuthSrv(const bool use_cache, AbstractXfroutClient& xfrout_client) :
+    impl_(new AuthSrvImpl(use_cache, xfrout_client))
+{}
 
 AuthSrv::~AuthSrv() {
     delete impl_;
@@ -130,8 +159,9 @@
     const Opcode& opcode = message.getOpcode();
     vector<QuestionPtr> questions;
 
-    // If this is an error to a query, we should also copy the question section.
-    if (opcode == Opcode::QUERY()) {
+    // If this is an error to a query or notify, we should also copy the
+    // question section.
+    if (opcode == Opcode::QUERY() || opcode == Opcode::NOTIFY()) {
         questions.assign(message.beginQuestion(), message.endQuestion());
     }
 
@@ -152,8 +182,7 @@
 
     if (verbose_mode) {
         cerr << "[b10-auth] sending an error response (" <<
-            boost::lexical_cast<string>(renderer.getLength())
-             << " bytes):\n" << message.toText() << endl;
+            renderer.getLength() << " bytes):\n" << message.toText() << endl;
     }
 }
 }
@@ -169,20 +198,26 @@
 }
 
 void
-AuthSrv::setConfigSession(ModuleCCSession* cs) {
-    impl_->cs_ = cs;
+AuthSrv::setXfrinSession(AbstractSession* xfrin_session) {
+    impl_->xfrin_session_ = xfrin_session;
+}
+
+void
+AuthSrv::setConfigSession(ModuleCCSession* config_session) {
+    impl_->config_session_ = config_session;
 }
 
 ModuleCCSession*
 AuthSrv::configSession() const {
-    return (impl_->cs_);
+    return (impl_->config_session_);
 }
 
 bool
-AuthSrv::processMessage(InputBuffer& request_buffer, Message& message,
-                        MessageRenderer& response_renderer,
-                        const bool udp_buffer)
-{
+AuthSrv::processMessage(const IOMessage& io_message, Message& message,
+                        MessageRenderer& response_renderer)
+{
+    InputBuffer request_buffer(io_message.getData(), io_message.getDataSize());
+
     // First, check the header part.  If we fail even for the base header,
     // just drop the message.
     try {
@@ -191,7 +226,8 @@
         // Ignore all responses.
         if (message.getHeaderFlag(MessageFlag::QR())) {
             if (impl_->verbose_mode_) {
-                cerr << "[b10-auth] received unexpected response, ignoring" << endl;
+                cerr << "[b10-auth] received unexpected response, ignoring"
+                     << endl;
             }
             return (false);
         }
@@ -204,8 +240,8 @@
         message.fromWire(request_buffer);
     } catch (const DNSProtocolError& error) {
         if (impl_->verbose_mode_) {
-            cerr << "[b10-auth] returning " <<  error.getRcode().toText() << ": "
-                 << error.what() << endl;
+            cerr << "[b10-auth] returning " <<  error.getRcode().toText()
+                 << ": " << error.what() << endl;
         }
         makeErrorMessage(message, response_renderer, error.getRcode(),
                          impl_->verbose_mode_);
@@ -225,8 +261,9 @@
 
     // Perform further protocol-level validation.
 
-    // In this implementation, we only support normal queries
-    if (message.getOpcode() != Opcode::QUERY()) {
+    if (message.getOpcode() == Opcode::NOTIFY()) {
+        return (impl_->processNotify(io_message, message, response_renderer));
+    } else if (message.getOpcode() != Opcode::QUERY()) {
         if (impl_->verbose_mode_) {
             cerr << "[b10-auth] unsupported opcode" << endl;
         }
@@ -241,6 +278,25 @@
         return (true);
     }
 
+    ConstQuestionPtr question = *message.beginQuestion();
+    const RRType &qtype = question->getType();
+    if (qtype == RRType::AXFR()) {
+        return (impl_->processAxfrQuery(io_message, message,
+                                        response_renderer));
+    } else if (qtype == RRType::IXFR()) {
+        makeErrorMessage(message, response_renderer, Rcode::NOTIMP(),
+                         impl_->verbose_mode_);
+        return (true);
+    } else {
+        return (impl_->processNormalQuery(io_message, message,
+                                          response_renderer));
+    }
+}
+
+bool
+AuthSrvImpl::processNormalQuery(const IOMessage& io_message, Message& message,
+                                MessageRenderer& response_renderer)
+{
     const bool dnssec_ok = message.isDNSSECSupported();
     const uint16_t remote_bufsize = message.getUDPSize();
 
@@ -251,42 +307,174 @@
     message.setUDPSize(AuthSrvImpl::DEFAULT_LOCAL_UDPSIZE);
 
     try {
-        Query query(message, impl_->cache_, dnssec_ok);
-        impl_->data_sources_.doQuery(query);
+        Query query(message, cache_, dnssec_ok);
+        data_sources_.doQuery(query);
     } catch (const Exception& ex) {
-        if (impl_->verbose_mode_) {
+        if (verbose_mode_) {
             cerr << "[b10-auth] Internal error, returning SERVFAIL: " <<
                 ex.what() << endl;
         }
         makeErrorMessage(message, response_renderer, Rcode::SERVFAIL(),
-                         impl_->verbose_mode_);
-        return (true);
-    }
-
+                         verbose_mode_);
+        return (true);
+    }
+
+    const bool udp_buffer =
+        (io_message.getSocket().getProtocol() == IPPROTO_UDP);
     response_renderer.setLengthLimit(udp_buffer ? remote_bufsize : 65535);
     message.toWire(response_renderer);
-    if (impl_->verbose_mode_) {
-        cerr << "[b10-auth] sending a response (" <<
-            boost::lexical_cast<string>(response_renderer.getLength())
+    if (verbose_mode_) {
+        cerr << "[b10-auth] sending a response ("
+             << response_renderer.getLength()
              << " bytes):\n" << message.toText() << endl;
     }
 
     return (true);
 }
 
-ElementPtr
-AuthSrvImpl::setDbFile(const isc::data::ElementPtr config) {
-    ElementPtr answer = isc::config::createAnswer();
-    ElementPtr final;
+bool
+AuthSrvImpl::processAxfrQuery(const IOMessage& io_message, Message& message,
+                            MessageRenderer& response_renderer)
+{
+    if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
+        if (verbose_mode_) {
+            cerr << "[b10-auth] AXFR query over UDP isn't allowed" << endl;
+        }
+        makeErrorMessage(message, response_renderer, Rcode::FORMERR(),
+                         verbose_mode_);
+        return (true);
+    }
+
+    try {
+        xfrout_client_.connect();
+        xfrout_connected_ = true;
+        xfrout_client_.sendXfroutRequestInfo(
+            io_message.getSocket().getNative(),
+            io_message.getData(),
+            io_message.getDataSize());
+    } catch (const XfroutError& err) {
+        if (xfrout_connected_) {
+            // disconnect() may trigger an exception, but since we try it
+            // only if we've successfully opened it, it shouldn't happen in
+            // normal condition.  Should this occur, we'll propagate it to the
+            // upper layer.
+            xfrout_client_.disconnect();
+            xfrout_connected_ = false;
+        }
+        
+        if (verbose_mode_) {
+            cerr << "[b10-auth] Error in handling XFR request: " << err.what()
+                 << endl;
+        }
+        makeErrorMessage(message, response_renderer, Rcode::SERVFAIL(),
+                         verbose_mode_);
+        return (true);
+    }
+
+    xfrout_client_.disconnect();
+    xfrout_connected_ = false;
+
+    return (false);
+}
+
+bool
+AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message, 
+                           MessageRenderer& response_renderer) 
+{
+    // The incoming notify must contain exactly one question for SOA of the
+    // zone name.
+    if (message.getRRCount(Section::QUESTION()) != 1) {
+        if (verbose_mode_) {
+                cerr << "[b10-auth] invalid number of questions in notify: "
+                     << message.getRRCount(Section::QUESTION()) << endl;
+        }
+        makeErrorMessage(message, response_renderer, Rcode::FORMERR(),
+                         verbose_mode_);
+        return (true);
+    }
+    ConstQuestionPtr question = *message.beginQuestion();
+    if (question->getType() != RRType::SOA()) {
+        if (verbose_mode_) {
+                cerr << "[b10-auth] invalid question RR type in notify: "
+                     << question->getType() << endl;
+        }
+        makeErrorMessage(message, response_renderer, Rcode::FORMERR(),
+                         verbose_mode_);
+        return (true);
+    }
+
+    // According to RFC 1996, rcode should be "no error" and AA bit should be
+    // on, but we don't check these conditions.  This behavior is compatible
+    // with BIND 9.
+
+    // TODO check with the conf-mgr whether current server is the auth of the
+    // zone
+
+    // In the code that follows, we simply ignore the notify if any internal
+    // error happens rather than returning (e.g.) SERVFAIL.  RFC 1996 is
+    // silent about such cases, but there doesn't seem to be anything we can
+    // improve at the primary server side by sending an error anyway.
+    if (xfrin_session_ == NULL) {
+        if (verbose_mode_) {
+            cerr << "[b10-auth] "
+                "session interface for xfrin is not available" << endl;
+        }
+        return (false);
+    }
+    
+    const string remote_ip_address =
+        io_message.getRemoteEndpoint().getAddress().toText();
+    static const string command_template_start =
+        "{\"command\": [\"notify\", {\"zone_name\" : \"";
+    static const string command_template_master = "\", \"master\" : \"";
+    static const string command_template_rrclass = "\", \"zone_class\" : \"";
+    static const string command_template_end = "\"}]}";
+
+    try {
+        ConstElementPtr notify_command = Element::fromJSON(
+                command_template_start + question->getName().toText() + 
+                command_template_master + remote_ip_address +
+                command_template_rrclass + question->getClass().toText() +
+                command_template_end);
+        const unsigned int seq =
+            xfrin_session_->group_sendmsg(notify_command, "Zonemgr",
+                                          "*", "*");
+        ConstElementPtr env, answer, parsed_answer;
+        xfrin_session_->group_recvmsg(env, answer, false, seq);
+        int rcode;
+        parsed_answer = parseAnswer(rcode, answer);
+        if (rcode != 0) {
+            if (verbose_mode_) {
+                cerr << "[b10-auth] failed to notify Zonemgr: "
+                     << parsed_answer->str() << endl; 
+            }
+            return (false);
+        }
+    } catch (const Exception& ex) {
+        if (verbose_mode_) {
+            cerr << "[b10-auth] failed to notify Zonemgr: " << ex.what() << endl;
+        }
+        return (false);
+    }
+
+    message.makeResponse();
+    message.setHeaderFlag(MessageFlag::AA());
+    message.setRcode(Rcode::NOERROR());
+    message.toWire(response_renderer);
+    return (true);
+}
+
+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 (cs_ != NULL) {
+    } else if (config_session_ != NULL) {
         bool is_default;
         string item("database_file");
-        ElementPtr value = cs_->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
@@ -300,6 +488,7 @@
                                     "/bind10_zones.sqlite3");
         }
         final->set(item, value);
+        config = final;
 
         db_file_ = value->stringValue();
     } else {
@@ -316,7 +505,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.
@@ -328,20 +517,17 @@
     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;
         }
-        return isc::config::createAnswer(1, error.what());
+        return (isc::config::createAnswer(1, error.what()));
     }
 }
 
@@ -349,8 +535,8 @@
 // TEMP, just a bindctl command to add an RR
 //
 
-ElementPtr
-AuthSrv::addRR(isc::data::ElementPtr args)
+ConstElementPtr
+AuthSrv::addRR(isc::data::ConstElementPtr args)
 {
     Name zone_name = Name(args->get("zone_name")->stringValue());
     RRClass rrclass = RRClass(args->get("rr_class")->stringValue());
@@ -387,8 +573,8 @@
     }
 }
 
-ElementPtr
-AuthSrv::delRR(isc::data::ElementPtr args)
+ConstElementPtr
+AuthSrv::delRR(isc::data::ConstElementPtr args)
 {
     Name zone_name = Name(args->get("zone_name")->stringValue());
     RRClass rrclass = RRClass(args->get("rr_class")->stringValue());
@@ -442,8 +628,8 @@
 // to quickly test the backend)
 // one RR per line, must be fully 'expanded'
 // can only handle 1 rr per name/class/type
-ElementPtr
-AuthSrv::loadZone(isc::data::ElementPtr args)
+ConstElementPtr
+AuthSrv::loadZone(isc::data::ConstElementPtr args)
 {
     ifstream myfile(args->get("file_name")->stringValue().c_str());
 
@@ -526,8 +712,9 @@
         return isc::config::createAnswer(1, exc.what());
     }
 }
-ElementPtr
-AuthSrv::ixfr(isc::data::ElementPtr args)
+
+ConstElementPtr
+AuthSrv::ixfr(isc::data::ConstElementPtr args)
 {
     try {
         Name zone_name = Name(args->get("zone_name")->stringValue());

Modified: branches/trac232/src/bin/auth/auth_srv.h
==============================================================================
--- branches/trac232/src/bin/auth/auth_srv.h (original)
+++ branches/trac232/src/bin/auth/auth_srv.h Wed Sep  1 00:35:07 2010
@@ -28,6 +28,14 @@
 class Message;
 class MessageRenderer;
 }
+
+namespace xfr {
+class AbstractXfroutClient;
+};
+}
+
+namespace asio_link {
+class IOMessage;
 }
 
 class AuthSrvImpl;
@@ -36,33 +44,54 @@
     ///
     /// \name Constructors, Assignment Operator and Destructor.
     ///
-    /// Note: The copy constructor and the assignment operator are intentionally
-    /// defined as private.
+    /// Note: The copy constructor and the assignment operator are
+    /// intentionally defined as private.
     //@{
 private:
     AuthSrv(const AuthSrv& source);
     AuthSrv& operator=(const AuthSrv& source);
 public:
-    explicit AuthSrv(const bool use_cache);
+    /// The constructor.
+    ///
+    /// \param use_cache Whether to enable hot spot cache for lookup results.
+    /// \param xfrout_client Communication interface with a separate xfrout
+    /// process.  It's normally a reference to an xfr::XfroutClient object,
+    /// but can refer to a local mock object for testing (or other
+    /// experimental) purposes.
+    AuthSrv(const bool use_cache,
+            isc::xfr::AbstractXfroutClient& xfrout_client);
     ~AuthSrv();
     //@}
     /// \return \c true if the \message contains a response to be returned;
     /// otherwise \c false.
-    bool processMessage(isc::dns::InputBuffer& request_buffer,
+    bool processMessage(const asio_link::IOMessage& io_message,
                         isc::dns::Message& message,
-                        isc::dns::MessageRenderer& response_renderer,
-                        bool udp_buffer);
+                        isc::dns::MessageRenderer& response_renderer);
     void setVerbose(bool on);
     bool getVerbose() const;
-    void serve(std::string zone_name);
-    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* cs);
+    void setConfigSession(isc::config::ModuleCCSession* config_session);
+
+    ///
+    /// Note: this interface is tentative.  We'll revisit the ASIO and session
+    /// frameworks, at which point the session will probably be passed on
+    /// construction of the server.
+    ///
+    /// \param xfrin_session A Session object over which NOTIFY message
+    /// information is exchanged with a XFRIN handler.
+    /// The session must be established before setting in the server
+    /// object.
+    /// Ownership isn't transferred: the caller is responsible for keeping
+    /// this object to be valid while the server object is working and for
+    /// disconnecting the session and destroying the object when the server
+    ///
+    void setXfrinSession(isc::cc::AbstractSession* xfrin_session);
     // temporarily added for manual testing of writable data sources
-    isc::data::ElementPtr addRR(isc::data::ElementPtr arg);
-    isc::data::ElementPtr delRR(isc::data::ElementPtr arg);
-    isc::data::ElementPtr loadZone(isc::data::ElementPtr arg);
-    isc::data::ElementPtr ixfr(isc::data::ElementPtr arg);
+    isc::data::ConstElementPtr addRR(isc::data::ConstElementPtr arg);
+    isc::data::ConstElementPtr delRR(isc::data::ConstElementPtr arg);
+    isc::data::ConstElementPtr loadZone(isc::data::ConstElementPtr arg);
+    isc::data::ConstElementPtr ixfr(isc::data::ConstElementPtr arg);
     // end temp add
 private:
     AuthSrvImpl* impl_;

Modified: branches/trac232/src/bin/auth/b10-auth.8
==============================================================================
--- branches/trac232/src/bin/auth/b10-auth.8 (original)
+++ branches/trac232/src/bin/auth/b10-auth.8 Wed Sep  1 00:35:07 2010
@@ -2,12 +2,12 @@
 .\"     Title: b10-auth
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: March 16, 2010
+.\"      Date: July 29, 2010
 .\"    Manual: BIND10
 .\"    Source: BIND10
 .\"  Language: English
 .\"
-.TH "B10\-AUTH" "8" "March 16, 2010" "BIND10" "BIND10"
+.TH "B10\-AUTH" "8" "July 29, 2010" "BIND10" "BIND10"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
@@ -22,7 +22,7 @@
 b10-auth \- Authoritative DNS server
 .SH "SYNOPSIS"
 .HP \w'\fBb10\-auth\fR\ 'u
-\fBb10\-auth\fR [\fB\-4\fR] [\fB\-6\fR] [\fB\-p\ \fR\fB\fInumber\fR\fR] [\fB\-v\fR]
+\fBb10\-auth\fR [\fB\-4\fR] [\fB\-6\fR] [\fB\-a\ \fR\fB\fIaddress\fR\fR] [\fB\-n\fR] [\fB\-p\ \fR\fB\fInumber\fR\fR] [\fB\-u\ \fR\fB\fIusername\fR\fR] [\fB\-v\fR]
 .SH "DESCRIPTION"
 .PP
 The
@@ -64,13 +64,30 @@
 \fB\-4\fR
 .RS 4
 Enables IPv4 only mode\&. This switch may not be used with
-\fB\-6\fR\&. By default, it listens on both IPv4 and IPv6 (if capable)\&.
+\fB\-6\fR
+nor
+\fB\-a\fR\&. By default, it listens on both IPv4 and IPv6 (if capable)\&.
 .RE
 .PP
 \fB\-6\fR
 .RS 4
 Enables IPv6 only mode\&. This switch may not be used with
-\fB\-4\fR\&. By default, it listens on both IPv4 and IPv6 (if capable)\&.
+\fB\-4\fR
+nor
+\fB\-a\fR\&. By default, it listens on both IPv4 and IPv6 (if capable)\&.
+.RE
+.PP
+\fB\-a \fR\fB\fIaddress\fR\fR
+.RS 4
+The IPv4 or IPv6 address to listen on\&. This switch may not be used with
+\fB\-4\fR
+nor
+\fB\-6\fR\&. The default is to listen on all addresses\&. (This is a short term workaround\&. This argument may change\&.)
+.RE
+.PP
+\fB\-n\fR
+.RS 4
+Do not cache answers in memory\&. The default is to use the cache for faster responses\&. The cache keeps the most recent 30,000 answers (positive and negative) in memory for 30 seconds (instead of querying the data source, such as SQLite3 database, each time)\&.
 .RE
 .PP
 \fB\-p \fR\fB\fInumber\fR\fR
@@ -91,6 +108,15 @@
 The Y1 prototype runs on all interfaces and on this nonstandard port\&.
 .sp .5v
 .RE
+.RE
+.PP
+\fB\-u \fR\fB\fIusername\fR\fR
+.RS 4
+The user name of the
+\fBb10\-auth\fR
+daemon\&. If specified, the daemon changes the process owner to the specified user\&. The
+\fIusername\fR
+must be either a valid numeric user ID or a valid user name\&. By default the daemon runs as the user who invokes it\&.
 .RE
 .PP
 \fB\-v\fR

Modified: branches/trac232/src/bin/auth/b10-auth.xml
==============================================================================
--- branches/trac232/src/bin/auth/b10-auth.xml (original)
+++ branches/trac232/src/bin/auth/b10-auth.xml Wed Sep  1 00:35:07 2010
@@ -21,7 +21,7 @@
 <refentry>
 
   <refentryinfo>
-    <date>March 16, 2010</date>
+    <date>July 29, 2010</date>
   </refentryinfo>
 
   <refmeta>
@@ -47,7 +47,10 @@
       <command>b10-auth</command>
       <arg><option>-4</option></arg>
       <arg><option>-6</option></arg>
+      <arg><option>-a <replaceable>address</replaceable></option></arg>
+      <arg><option>-n</option></arg>
       <arg><option>-p <replaceable>number</replaceable></option></arg>
+      <arg><option>-u <replaceable>username</replaceable></option></arg>
       <arg><option>-v</option></arg>
     </cmdsynopsis>
   </refsynopsisdiv>
@@ -95,7 +98,8 @@
         <term><option>-4</option></term>
         <listitem><para>
           Enables IPv4 only mode.
-          This switch may not be used with <option>-6</option>.
+          This switch may not be used with <option>-6</option> nor
+          <option>-a</option>.
           By default, it listens on both IPv4 and IPv6 (if capable).
         </para></listitem>
       </varlistentry>
@@ -104,8 +108,33 @@
         <term><option>-6</option></term>
         <listitem><para>
           Enables IPv6 only mode.
-          This switch may not be used with <option>-4</option>.
+          This switch may not be used with <option>-4</option> nor
+          <option>-a</option>.
           By default, it listens on both IPv4 and IPv6 (if capable).
+        </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>-a <replaceable>address</replaceable></option></term>
+
+        <listitem>
+          <para>The IPv4 or IPv6 address to listen on.
+            This switch may not be used with <option>-4</option> nor
+            <option>-6</option>.
+            The default is to listen on all addresses.
+            (This is a short term workaround. This argument may change.)   
+          </para>                      
+         </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>-n</option></term>
+        <listitem><para>
+          Do not cache answers in memory.
+          The default is to use the cache for faster responses.
+	  The cache keeps the most recent 30,000 answers (positive
+	  and negative) in memory for 30 seconds (instead of querying
+	  the data source, such as SQLite3 database, each time).
         </para></listitem>
       </varlistentry>
 
@@ -120,6 +149,20 @@
       </varlistentry>
 
       <varlistentry>
+        <term><option>-u <replaceable>username</replaceable></option></term>
+        <listitem>
+	  <para>
+	    The user name of the <command>b10-auth</command> daemon.
+	    If specified, the daemon changes the process owner to the
+	    specified user.
+	    The <replaceable>username</replaceable> must be either a
+	    valid numeric user ID or a valid user name.
+	    By default the daemon runs as the user who invokes it.
+	  </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
         <term><option>-v</option></term>
         <listitem><para>
           Enabled verbose mode. This enables diagnostic messages to

Modified: branches/trac232/src/bin/auth/main.cc
==============================================================================
--- branches/trac232/src/bin/auth/main.cc (original)
+++ branches/trac232/src/bin/auth/main.cc Wed Sep  1 00:35:07 2010
@@ -14,8 +14,6 @@
 
 // $Id$
 
-#include "config.h"
-
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/select.h>
@@ -39,16 +37,20 @@
 #include <cc/data.h>
 #include <config/ccsession.h>
 
-#include "spec_config.h"
-#include "common.h"
-#include "auth_srv.h"
-#include "asio_link.h"
+#include <xfr/xfrout_client.h>
+
+#include <auth/spec_config.h>
+#include <auth/common.h>
+#include <auth/change_user.h>
+#include <auth/auth_srv.h>
+#include <auth/asio_link.h>
 
 using namespace std;
 using namespace isc::data;
 using namespace isc::cc;
 using namespace isc::config;
 using namespace isc::dns;
+using namespace isc::xfr;
 
 namespace {
 
@@ -64,19 +66,19 @@
 
 asio_link::IOService* io_service;
 
-ElementPtr
-my_config_handler(ElementPtr new_config) {
-    return auth_server->updateConfig(new_config);
-}
-
-ElementPtr
-my_command_handler(const string& command, const ElementPtr args) {
-    ElementPtr answer = createAnswer();
+ConstElementPtr
+my_config_handler(ConstElementPtr new_config) {
+    return (auth_server->updateConfig(new_config));
+}
+
+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 == "add_rr") {
         answer = auth_server->addRR(args);
     } else if (command == "del_rr") {
@@ -89,12 +91,12 @@
         io_service->stop();
     }
     
-    return answer;
+    return (answer);
 }
 
 void
 usage() {
-    cerr << "Usage: b10-auth [-p port] [-4|-6] [-nv]" << endl;
+    cerr << "Usage: b10-auth [-a address] [-p port] [-4|-6] [-nv]" << endl;
     exit(1);
 }
 } // end of anonymous namespace
@@ -104,9 +106,10 @@
     int ch;
     const char* port = DNSPORT;
     const char* address = NULL;
+    const char* uid = NULL;
     bool use_ipv4 = true, use_ipv6 = true, cache = true;
 
-    while ((ch = getopt(argc, argv, "46np:v")) != -1) {
+    while ((ch = getopt(argc, argv, "46a:np:u:v")) != -1) {
         switch (ch) {
         case '4':
             // Note that -4 means "ipv4 only", we need to set "use_ipv6" here,
@@ -128,6 +131,9 @@
         case 'p':
             port = optarg;
             break;
+        case 'u':
+            uid = optarg;
+            break;
         case 'v':
             verbose_mode = true;
             break;
@@ -146,8 +152,25 @@
         usage();
     }
 
-    // initialize command channel
+    if ((!use_ipv4 || !use_ipv6) && address != NULL) {
+        cerr << "[b10-auth] Error: -4|-6 and -a can't coexist" << endl;
+        usage();
+    }
+
     int ret = 0;
+
+    // XXX: we should eventually pass io_service here.
+    Session* cc_session = NULL;
+    Session* xfrin_session = NULL;
+    bool xfrin_session_established = false; // XXX (see Trac #287)
+    ModuleCCSession* config_session = NULL;
+    string xfrout_socket_path;
+    if (getenv("B10_FROM_BUILD") != NULL) {
+        xfrout_socket_path = string(getenv("B10_FROM_BUILD")) + "/auth_xfrout_conn";
+    } else {
+        xfrout_socket_path = UNIX_SOCKET_FILE;
+    }
+    XfroutClient xfrout_client(xfrout_socket_path);
     try {
         string specfile;
         if (getenv("B10_FROM_BUILD")) {
@@ -157,26 +180,68 @@
             specfile = string(AUTH_SPECFILE_LOCATION);
         }
 
-        auth_server = new AuthSrv(cache);
+        auth_server = new AuthSrv(cache, xfrout_client);
         auth_server->setVerbose(verbose_mode);
-
-        io_service = new asio_link::IOService(auth_server, address, port,
-                                              use_ipv4, use_ipv6);
-
-        ModuleCCSession cs(specfile, io_service->get_io_service(),
-                           my_config_handler, my_command_handler);
-
-        auth_server->setConfigSession(&cs);
+        cout << "[b10-auth] Server created." << endl;
+
+        if (address != NULL) {
+            // XXX: we can only specify at most one explicit address.
+            // This also means the server cannot run in the dual address
+            // family mode if explicit addresses need to be specified.
+            // We don't bother to fix this problem, however.  The -a option
+            // is a short term workaround until we support dynamic listening
+            // port allocation.
+            io_service = new asio_link::IOService(auth_server, *port,
+                                                  *address);
+        } else {
+            io_service = new asio_link::IOService(auth_server, *port,
+                                                  use_ipv4, use_ipv6);
+        }
+        cout << "[b10-auth] IOService created." << endl;
+
+        cc_session = new Session(io_service->get_io_service());
+        cout << "[b10-auth] Configuration session channel created." << endl;
+
+        config_session = new ModuleCCSession(specfile, *cc_session,
+                                             my_config_handler,
+                                             my_command_handler);
+        cout << "[b10-auth] Configuration channel established." << endl;
+
+        if (uid != NULL) {
+            changeUser(uid);
+        }
+
+        xfrin_session = new Session(io_service->get_io_service());
+        cout << "[b10-auth] Xfrin session channel created." << endl;
+        xfrin_session->establish(NULL);
+        xfrin_session_established = true;
+        cout << "[b10-auth] Xfrin session channel established." << endl;
+
+        // XXX: with the current interface to asio_link we have to create
+        // auth_server before io_service while Session needs io_service.
+        // In a next step of refactoring we should make asio_link independent
+        // from auth_server, and create io_service, auth_server, and
+        // sessions in that order.
+        auth_server->setXfrinSession(xfrin_session);
+        auth_server->setConfigSession(config_session);
         auth_server->updateConfig(ElementPtr());
 
         cout << "[b10-auth] Server started." << endl;
         io_service->run();
     } catch (const std::exception& ex) {
-        cerr << "[b10-auth] " << ex.what() << endl;
+        cerr << "[b10-auth] Initialization failed: " << ex.what() << endl;
         ret = 1;
     }
 
+    if (xfrin_session_established) {
+        xfrin_session->disconnect();
+    }
+
+    delete xfrin_session;
+    delete config_session;
+    delete cc_session;
     delete io_service;
     delete auth_server;
+
     return (ret);
 }

Modified: branches/trac232/src/bin/auth/tests/Makefile.am
==============================================================================
--- branches/trac232/src/bin/auth/tests/Makefile.am (original)
+++ branches/trac232/src/bin/auth/tests/Makefile.am Wed Sep  1 00:35:07 2010
@@ -4,6 +4,10 @@
 AM_CPPFLAGS += -DTEST_DATA_DIR=\"$(srcdir)/testdata\"
 
 AM_CXXFLAGS = $(B10_CXXFLAGS)
+
+if USE_STATIC_LINK
+AM_LDFLAGS = -static
+endif
 
 CLEANFILES = *.gcno *.gcda
 
@@ -13,17 +17,22 @@
 run_unittests_SOURCES = $(top_srcdir)/src/lib/dns/tests/unittest_util.h
 run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
 run_unittests_SOURCES += ../auth_srv.h ../auth_srv.cc
+run_unittests_SOURCES += ../change_user.h ../change_user.cc
 run_unittests_SOURCES += auth_srv_unittest.cc
+run_unittests_SOURCES += change_user_unittest.cc
+run_unittests_SOURCES += asio_link_unittest.cc
 run_unittests_SOURCES += run_unittests.cc
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 run_unittests_LDADD = $(GTEST_LDADD)
 run_unittests_LDADD += $(SQLITE_LIBS)
-run_unittests_LDADD +=  $(top_builddir)/src/lib/datasrc/.libs/libdatasrc.a
-run_unittests_LDADD +=  $(top_builddir)/src/lib/dns/.libs/libdns++.a
-run_unittests_LDADD += $(top_builddir)/src/lib/config/.libs/libcfgclient.a
-run_unittests_LDADD += $(top_builddir)/src/lib/cc/.libs/libcc.a
-run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a
+run_unittests_LDADD +=  $(top_builddir)/src/lib/datasrc/libdatasrc.la
+run_unittests_LDADD +=  $(top_builddir)/src/lib/dns/libdns++.la
+run_unittests_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
+run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.la
+run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
+run_unittests_LDADD += $(top_builddir)/src/bin/auth/libasio_link.a
+run_unittests_LDADD += $(top_builddir)/src/lib/xfr/libxfr.la
 endif
 
 noinst_PROGRAMS = $(TESTS)

Modified: branches/trac232/src/bin/auth/tests/auth_srv_unittest.cc
==============================================================================
--- branches/trac232/src/bin/auth/tests/auth_srv_unittest.cc (original)
+++ branches/trac232/src/bin/auth/tests/auth_srv_unittest.cc Wed Sep  1 00:35:07 2010
@@ -14,6 +14,8 @@
 
 // $Id$
 
+#include <config.h>
+
 #include <gtest/gtest.h>
 
 #include <dns/buffer.h>
@@ -24,33 +26,108 @@
 #include <dns/rrtype.h>
 
 #include <cc/data.h>
+#include <cc/session.h>
+
+#include <xfr/xfrout_client.h>
 
 #include <auth/auth_srv.h>
+#include <auth/asio_link.h>
 
 #include <dns/tests/unittest_util.h>
 
 using isc::UnitTestUtil;
 using namespace std;
+using namespace isc::cc;
 using namespace isc::dns;
 using namespace isc::data;
+using namespace isc::xfr;
+using namespace asio_link;
 
 namespace {
-const char* CONFIG_TESTDB =
+const char* const CONFIG_TESTDB =
     "{\"database_file\": \"" TEST_DATA_DIR "/example.sqlite3\"}";
 // The following file must be non existent and must be non"creatable" (see
 // the sqlite3 test).
-const char* BADCONFIG_TESTDB =
+const char* const BADCONFIG_TESTDB =
     "{ \"database_file\": \"" TEST_DATA_DIR "/nodir/notexist\"}";
+const char* const DEFAULT_REMOTE_ADDRESS = "192.0.2.1";
 
 class AuthSrvTest : public ::testing::Test {
+private:
+    class MockXfroutClient : public AbstractXfroutClient {
+    public:
+        MockXfroutClient() :
+            is_connected_(false), connect_ok_(true), send_ok_(true),
+            disconnect_ok_(true)
+        {}
+        virtual void connect();
+        virtual void disconnect();
+        virtual int sendXfroutRequestInfo(int tcp_sock, const void* msg_data,
+                                          uint16_t msg_len);
+        bool isConnected() const { return (is_connected_); }
+        void disableConnect() { connect_ok_ = false; }
+        void disableDisconnect() { disconnect_ok_ = false; }
+        void enableDisconnect() { disconnect_ok_ = true; }
+        void disableSend() { send_ok_ = false; }
+    private:
+        bool is_connected_;
+        bool connect_ok_;
+        bool send_ok_;
+        bool disconnect_ok_;
+    };
+
+    class MockSession : public AbstractSession {
+    public:
+        MockSession() :
+            // by default we return a simple "success" message.
+            msg_(Element::fromJSON("{\"result\": [0, \"SUCCESS\"]}")),
+            send_ok_(true), receive_ok_(true)
+        {}
+        virtual void establish(const char* socket_file);
+        virtual void disconnect();
+        virtual int group_sendmsg(ConstElementPtr msg, string group,
+                                  string instance, string to);
+        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(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(ConstElementPtr msg) { msg_ = msg; }
+        void disableSend() { send_ok_ = false; }
+        void disableReceive() { receive_ok_ = false; }
+
+        ConstElementPtr sent_msg;
+        string msg_destination;
+    private:
+        ConstElementPtr msg_;
+        bool send_ok_;
+        bool receive_ok_;
+    };
+
 protected:
-    AuthSrvTest() : server(true), request_message(Message::RENDER),
+    AuthSrvTest() : server(true, xfrout),
+                    request_message(Message::RENDER),
                     parse_message(Message::PARSE), default_qid(0x1035),
                     opcode(Opcode(Opcode::QUERY())), qname("www.example.com"),
-                    qclass(RRClass::IN()), qtype(RRType::A()), ibuffer(NULL),
-                    request_obuffer(0), request_renderer(request_obuffer),
+                    qclass(RRClass::IN()), qtype(RRType::A()),
+                    io_message(NULL), endpoint(NULL), request_obuffer(0),
+                    request_renderer(request_obuffer),
                     response_obuffer(0), response_renderer(response_obuffer)
-    {}
+    {
+        server.setXfrinSession(&notify_session);
+    }
+    ~AuthSrvTest() {
+        delete io_message;
+        delete endpoint;
+    }
+    MockSession notify_session;
+    MockXfroutClient xfrout;
     AuthSrv server;
     Message request_message;
     Message parse_message;
@@ -59,15 +136,113 @@
     const Name qname;
     const RRClass qclass;
     const RRType qtype;
-    InputBuffer* ibuffer;
+    IOMessage* io_message;
+    const IOEndpoint* endpoint;
     OutputBuffer request_obuffer;
     MessageRenderer request_renderer;
     OutputBuffer response_obuffer;
     MessageRenderer response_renderer;
     vector<uint8_t> data;
 
-    void createDataFromFile(const char* const datafile);
+    void createDataFromFile(const char* const datafile, int protocol);
+    void createRequestMessage(const Opcode& opcode, const Name& request_name,
+                              const RRClass& rrclass, const RRType& rrtype);
+    void createRequestPacket(const Opcode& opcode, const Name& request_name,
+                             const RRClass& rrclass, const RRType& rrtype,
+                             int protocol);
+    void createRequestPacket(int protocol);
 };
+
+void
+AuthSrvTest::MockSession::establish(const char* socket_file UNUSED_PARAM) {}
+
+void
+AuthSrvTest::MockSession::disconnect() {}
+
+void
+AuthSrvTest::MockSession::subscribe(string group UNUSED_PARAM,
+                                    string instance UNUSED_PARAM)
+{}
+
+void
+AuthSrvTest::MockSession::unsubscribe(string group UNUSED_PARAM,
+                                      string instance UNUSED_PARAM)
+{}
+
+void
+AuthSrvTest::MockSession::startRead(
+    boost::function<void()> read_callback UNUSED_PARAM)
+{}
+
+int
+AuthSrvTest::MockSession::reply(ConstElementPtr envelope UNUSED_PARAM,
+                                ConstElementPtr newmsg UNUSED_PARAM)
+{
+    return (-1);
+}
+
+bool
+AuthSrvTest::MockSession::hasQueuedMsgs() const {
+    return (false);
+}
+
+int
+AuthSrvTest::MockSession::group_sendmsg(ConstElementPtr msg, string group,
+                                        string instance UNUSED_PARAM,
+                                        string to UNUSED_PARAM)
+{
+    if (!send_ok_) {
+        isc_throw(XfroutError, "mock session send is disabled for test");
+    }
+
+    sent_msg = msg;
+    msg_destination = group;
+    return (0);
+}
+
+bool
+AuthSrvTest::MockSession::group_recvmsg(ConstElementPtr& envelope UNUSED_PARAM,
+                                        ConstElementPtr& msg,
+                                        bool nonblock UNUSED_PARAM,
+                                        int seq UNUSED_PARAM)
+{
+    if (!receive_ok_) {
+        isc_throw(XfroutError, "mock session receive is disabled for test");
+    }
+
+    msg = msg_;
+    return (true);
+}
+
+void
+AuthSrvTest::MockXfroutClient::connect() {
+    if (!connect_ok_) {
+        isc_throw(XfroutError, "xfrout connection disabled for test");
+    }
+    is_connected_ = true;
+}
+
+void
+AuthSrvTest::MockXfroutClient::disconnect() {
+    if (!disconnect_ok_) {
+        isc_throw(XfroutError,
+                  "closing xfrout connection is disabled for test");
+    }
+    is_connected_ = false;
+}
+
+int
+AuthSrvTest::MockXfroutClient::sendXfroutRequestInfo(
+    const int tcp_sock UNUSED_PARAM,
+    const void* msg_data UNUSED_PARAM,
+    const uint16_t msg_len UNUSED_PARAM)
+{
+    if (!send_ok_) {
+        isc_throw(XfroutError, "xfrout connection send is disabled for test");
+    }
+    return (0);
+}
+
 
 // These are flags to indicate whether the corresponding flag bit of the
 // DNS header is to be set in the test cases.  (Note that the flag values
@@ -81,12 +256,56 @@
 const unsigned int CD_FLAG = 0x40;
 
 void
-AuthSrvTest::createDataFromFile(const char* const datafile) {
-    delete ibuffer;
+AuthSrvTest::createDataFromFile(const char* const datafile,
+                                const int protocol = IPPROTO_UDP)
+{
+    delete io_message;
     data.clear();
 
+    delete endpoint;
+    endpoint = IOEndpoint::create(protocol,
+                                  IOAddress(DEFAULT_REMOTE_ADDRESS), 5300);
     UnitTestUtil::readWireData(datafile, data);
-    ibuffer = new InputBuffer(&data[0], data.size());
+    io_message = new IOMessage(&data[0], data.size(),
+                               protocol == IPPROTO_UDP ?
+                               IOSocket::getDummyUDPSocket() :
+                               IOSocket::getDummyTCPSocket(), *endpoint);
+}
+
+void
+AuthSrvTest::createRequestMessage(const Opcode& opcode,
+                                  const Name& request_name,
+                                  const RRClass& rrclass,
+                                  const RRType& rrtype)
+{
+    request_message.clear(Message::RENDER);
+    request_message.setOpcode(opcode);
+    request_message.setQid(default_qid);
+    request_message.addQuestion(Question(request_name, rrclass, rrtype));
+}
+
+void
+AuthSrvTest::createRequestPacket(const Opcode& opcode,
+                                 const Name& request_name,
+                                 const RRClass& rrclass, const RRType& rrtype,
+                                 const int protocol = IPPROTO_UDP)
+{
+    createRequestMessage(opcode, request_name, rrclass, rrtype);
+    createRequestPacket(protocol);
+}
+
+void
+AuthSrvTest::createRequestPacket(const int protocol = IPPROTO_UDP) {
+    request_message.toWire(request_renderer);
+
+    delete io_message;
+    endpoint = IOEndpoint::create(protocol,
+                                  IOAddress(DEFAULT_REMOTE_ADDRESS), 5300);
+    io_message = new IOMessage(request_renderer.getData(),
+                               request_renderer.getLength(),
+                               protocol == IPPROTO_UDP ?
+                               IOSocket::getDummyUDPSocket() :
+                               IOSocket::getDummyTCPSocket(), *endpoint);
 }
 
 void
@@ -115,15 +334,19 @@
 
 // Unsupported requests.  Should result in NOTIMP.
 TEST_F(AuthSrvTest, unsupportedRequest) {
-    for (unsigned int i = 1; i < 16; ++i) {
+    for (unsigned int i = 0; i < 16; ++i) {
         // set Opcode to 'i', which iterators over all possible codes except
-        // the standard query (0)
+        // the standard query and notify
+        if (i == Opcode::QUERY().getCode() ||
+            i == Opcode::NOTIFY().getCode()) {
+            continue;
+        }
         createDataFromFile("simplequery_fromWire");
         data[2] = ((i << 3) & 0xff);
 
         parse_message.clear(Message::PARSE);
-        EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
-                                              response_renderer, true));
+        EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                              response_renderer));
         headerCheck(parse_message, default_qid, Rcode::NOTIMP(), i, QR_FLAG,
                     0, 0, 0, 0);
     }
@@ -141,8 +364,8 @@
 // Multiple questions.  Should result in FORMERR.
 TEST_F(AuthSrvTest, multiQuestion) {
     createDataFromFile("multiquestion_fromWire");
-    EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
-                                          response_renderer, true));
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
     headerCheck(parse_message, default_qid, Rcode::FORMERR(), opcode.getCode(),
                 QR_FLAG, 2, 0, 0, 0);
 
@@ -162,8 +385,8 @@
 // dropped.
 TEST_F(AuthSrvTest, shortMessage) {
     createDataFromFile("shortmessage_fromWire");
-    EXPECT_EQ(false, server.processMessage(*ibuffer, parse_message,
-                                           response_renderer, true));
+    EXPECT_EQ(false, server.processMessage(*io_message, parse_message,
+                                           response_renderer));
 }
 
 // Response messages.  Must be silently dropped, whether it's a valid response
@@ -171,26 +394,26 @@
 TEST_F(AuthSrvTest, response) {
     // A valid (although unusual) response
     createDataFromFile("simpleresponse_fromWire");
-    EXPECT_EQ(false, server.processMessage(*ibuffer, parse_message,
-                                           response_renderer, true));
+    EXPECT_EQ(false, server.processMessage(*io_message, parse_message,
+                                           response_renderer));
 
     // A response with a broken question section.  must be dropped rather than
     // returning FORMERR.
     createDataFromFile("shortresponse_fromWire");
-    EXPECT_EQ(false, server.processMessage(*ibuffer, parse_message,
-                                           response_renderer, true));
+    EXPECT_EQ(false, server.processMessage(*io_message, parse_message,
+                                           response_renderer));
 
     // A response to iquery.  must be dropped rather than returning NOTIMP.
     createDataFromFile("iqueryresponse_fromWire");
-    EXPECT_EQ(false, server.processMessage(*ibuffer, parse_message,
-                                           response_renderer, true));
+    EXPECT_EQ(false, server.processMessage(*io_message, parse_message,
+                                           response_renderer));
 }
 
 // Query with a broken question
 TEST_F(AuthSrvTest, shortQuestion) {
     createDataFromFile("shortquestion_fromWire");
-    EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
-                                          response_renderer, true));
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
     // Since the query's question is broken, the question section of the
     // response should be empty.
     headerCheck(parse_message, default_qid, Rcode::FORMERR(), opcode.getCode(),
@@ -200,8 +423,8 @@
 // Query with a broken answer section
 TEST_F(AuthSrvTest, shortAnswer) {
     createDataFromFile("shortanswer_fromWire");
-    EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
-                                          response_renderer, true));
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
 
     // This is a bogus query, but question section is valid.  So the response
     // should copy the question section.
@@ -219,8 +442,8 @@
 // Query with unsupported version of EDNS.
 TEST_F(AuthSrvTest, ednsBadVers) {
     createDataFromFile("queryBadEDNS_fromWire");
-    EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
-                                          response_renderer, true));
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
 
     // The response must have an EDNS OPT RR in the additional section.
     // Note that the DNSSEC DO bit is cleared even if this bit in the query
@@ -231,16 +454,256 @@
     EXPECT_FALSE(parse_message.isDNSSECSupported());
 }
 
+TEST_F(AuthSrvTest, AXFROverUDP) {
+    // AXFR over UDP is invalid and should result in FORMERR.
+    createRequestPacket(opcode, Name("example.com"), RRClass::IN(),
+                        RRType::AXFR(), IPPROTO_UDP);
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
+    headerCheck(parse_message, default_qid, Rcode::FORMERR(), opcode.getCode(),
+                QR_FLAG, 1, 0, 0, 0);
+}
+
+TEST_F(AuthSrvTest, AXFRSuccess) {
+    EXPECT_FALSE(xfrout.isConnected());
+    createRequestPacket(opcode, Name("example.com"), RRClass::IN(),
+                        RRType::AXFR(), IPPROTO_TCP);
+    // On success, the AXFR query has been passed to a separate process,
+    // so we shouldn't have to respond.
+    EXPECT_EQ(false, server.processMessage(*io_message, parse_message,
+                                           response_renderer));
+    EXPECT_FALSE(xfrout.isConnected());
+}
+
+TEST_F(AuthSrvTest, AXFRConnectFail) {
+    EXPECT_FALSE(xfrout.isConnected()); // check prerequisite
+    xfrout.disableConnect();
+    createRequestPacket(opcode, Name("example.com"), RRClass::IN(),
+                        RRType::AXFR(), IPPROTO_TCP);
+    EXPECT_TRUE(server.processMessage(*io_message, parse_message,
+                                      response_renderer));
+    headerCheck(parse_message, default_qid, Rcode::SERVFAIL(),
+                opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
+    // For a shot term workaround with xfrout we currently close the connection
+    // for each AXFR attempt
+    EXPECT_FALSE(xfrout.isConnected());
+}
+
+TEST_F(AuthSrvTest, AXFRSendFail) {
+    // first send a valid query, making the connection with the xfr process
+    // open.
+    createRequestPacket(opcode, Name("example.com"), RRClass::IN(),
+                        RRType::AXFR(), IPPROTO_TCP);
+    server.processMessage(*io_message, parse_message, response_renderer);
+    EXPECT_FALSE(xfrout.isConnected()); // see above
+
+    xfrout.disableSend();
+    parse_message.clear(Message::PARSE);
+    response_renderer.clear();
+    createRequestPacket(opcode, Name("example.com"), RRClass::IN(),
+                        RRType::AXFR(), IPPROTO_TCP);
+    EXPECT_TRUE(server.processMessage(*io_message, parse_message,
+                                      response_renderer));
+    headerCheck(parse_message, default_qid, Rcode::SERVFAIL(),
+                opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
+
+    // The connection should have been closed due to the send failure.
+    EXPECT_FALSE(xfrout.isConnected());
+}
+
+TEST_F(AuthSrvTest, AXFRDisconnectFail) {
+    // In our usage disconnect() shouldn't fail.  So we'll see the exception
+    // should it be thrown.
+    xfrout.disableSend();
+    xfrout.disableDisconnect();
+    createRequestPacket(opcode, Name("example.com"), RRClass::IN(),
+                        RRType::AXFR(), IPPROTO_TCP);
+    EXPECT_THROW(server.processMessage(*io_message, parse_message,
+                                       response_renderer),
+                 XfroutError);
+    EXPECT_TRUE(xfrout.isConnected());
+    // XXX: we need to re-enable disconnect.  otherwise an exception would be
+    // thrown via the destructor of the server.
+    xfrout.enableDisconnect();
+}
+
+TEST_F(AuthSrvTest, notify) {
+    createRequestMessage(Opcode::NOTIFY(), Name("example.com"), RRClass::IN(),
+                        RRType::SOA());
+    request_message.setHeaderFlag(MessageFlag::AA());
+    createRequestPacket(IPPROTO_UDP);
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
+
+    // An internal command message should have been created and sent to an
+    // external module.  Check them.
+    EXPECT_EQ("Zonemgr", notify_session.msg_destination);
+    EXPECT_EQ("notify",
+              notify_session.sent_msg->get("command")->get(0)->stringValue());
+    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());
+    EXPECT_EQ("IN", notify_args->get("zone_class")->stringValue());
+
+    // On success, the server should return a response to the notify.
+    headerCheck(parse_message, default_qid, Rcode::NOERROR(),
+                Opcode::NOTIFY().getCode(), QR_FLAG | AA_FLAG, 1, 0, 0, 0);
+
+    // The question must be identical to that of the received notify
+    ConstQuestionPtr question = *parse_message.beginQuestion();
+    EXPECT_EQ(Name("example.com"), question->getName());
+    EXPECT_EQ(RRClass::IN(), question->getClass());
+    EXPECT_EQ(RRType::SOA(), question->getType());
+}
+
+TEST_F(AuthSrvTest, notifyForCHClass) {
+    // Same as the previous test, but for the CH RRClass.
+    createRequestMessage(Opcode::NOTIFY(), Name("example.com"), RRClass::CH(),
+                        RRType::SOA());
+    request_message.setHeaderFlag(MessageFlag::AA());
+    createRequestPacket(IPPROTO_UDP);
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
+
+    // Other conditions should be the same, so simply confirm the RR class is
+    // set correctly.
+    ConstElementPtr notify_args =
+        notify_session.sent_msg->get("command")->get(1);
+    EXPECT_EQ("CH", notify_args->get("zone_class")->stringValue());
+}
+
+TEST_F(AuthSrvTest, notifyEmptyQuestion) {
+    request_message.clear(Message::RENDER);
+    request_message.setOpcode(Opcode::NOTIFY());
+    request_message.setHeaderFlag(MessageFlag::AA());
+    request_message.setQid(default_qid);
+    request_message.toWire(request_renderer);
+    createRequestPacket(IPPROTO_UDP);
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
+    headerCheck(parse_message, default_qid, Rcode::FORMERR(),
+                Opcode::NOTIFY().getCode(), QR_FLAG, 0, 0, 0, 0);
+}
+
+TEST_F(AuthSrvTest, notifyMultiQuestions) {
+    createRequestMessage(Opcode::NOTIFY(), Name("example.com"), RRClass::IN(),
+                        RRType::SOA());
+    // add one more SOA question
+    request_message.addQuestion(Question(Name("example.com"), RRClass::IN(),
+                                         RRType::SOA()));
+    request_message.setHeaderFlag(MessageFlag::AA());
+    createRequestPacket(IPPROTO_UDP);
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
+    headerCheck(parse_message, default_qid, Rcode::FORMERR(),
+                Opcode::NOTIFY().getCode(), QR_FLAG, 2, 0, 0, 0);
+}
+
+TEST_F(AuthSrvTest, notifyNonSOAQuestion) {
+    createRequestMessage(Opcode::NOTIFY(), Name("example.com"), RRClass::IN(),
+                        RRType::NS());
+    request_message.setHeaderFlag(MessageFlag::AA());
+    createRequestPacket(IPPROTO_UDP);
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
+    headerCheck(parse_message, default_qid, Rcode::FORMERR(),
+                Opcode::NOTIFY().getCode(), QR_FLAG, 1, 0, 0, 0);
+}
+
+TEST_F(AuthSrvTest, notifyWithoutAA) {
+    // implicitly leave the AA bit off.  our implementation will accept it.
+    createRequestPacket(Opcode::NOTIFY(), Name("example.com"), RRClass::IN(),
+                        RRType::SOA());
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
+    headerCheck(parse_message, default_qid, Rcode::NOERROR(),
+                Opcode::NOTIFY().getCode(), QR_FLAG | AA_FLAG, 1, 0, 0, 0);
+}
+
+TEST_F(AuthSrvTest, notifyWithErrorRcode) {
+    createRequestMessage(Opcode::NOTIFY(), Name("example.com"), RRClass::IN(),
+                        RRType::SOA());
+    request_message.setHeaderFlag(MessageFlag::AA());
+    request_message.setRcode(Rcode::SERVFAIL());
+    createRequestPacket(IPPROTO_UDP);
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
+    headerCheck(parse_message, default_qid, Rcode::NOERROR(),
+                Opcode::NOTIFY().getCode(), QR_FLAG | AA_FLAG, 1, 0, 0, 0);
+}
+
+TEST_F(AuthSrvTest, notifyWithoutSession) {
+    server.setXfrinSession(NULL);
+
+    createRequestMessage(Opcode::NOTIFY(), Name("example.com"), RRClass::IN(),
+                        RRType::SOA());
+    request_message.setHeaderFlag(MessageFlag::AA());
+    createRequestPacket(IPPROTO_UDP);
+
+    // we simply ignore the notify and let it be resent if an internal error
+    // happens.
+    EXPECT_FALSE(server.processMessage(*io_message, parse_message,
+                                       response_renderer));
+}
+
+TEST_F(AuthSrvTest, notifySendFail) {
+    notify_session.disableSend();
+
+    createRequestMessage(Opcode::NOTIFY(), Name("example.com"), RRClass::IN(),
+                        RRType::SOA());
+    request_message.setHeaderFlag(MessageFlag::AA());
+    createRequestPacket(IPPROTO_UDP);
+
+    EXPECT_FALSE(server.processMessage(*io_message, parse_message,
+                                       response_renderer));
+}
+
+TEST_F(AuthSrvTest, notifyReceiveFail) {
+    notify_session.disableReceive();
+
+    createRequestMessage(Opcode::NOTIFY(), Name("example.com"), RRClass::IN(),
+                        RRType::SOA());
+    request_message.setHeaderFlag(MessageFlag::AA());
+    createRequestPacket(IPPROTO_UDP);
+    EXPECT_FALSE(server.processMessage(*io_message, parse_message,
+                                       response_renderer));
+}
+
+TEST_F(AuthSrvTest, notifyWithBogusSessionMessage) {
+    notify_session.setMessage(Element::fromJSON("{\"foo\": 1}"));
+
+    createRequestMessage(Opcode::NOTIFY(), Name("example.com"), RRClass::IN(),
+                        RRType::SOA());
+    request_message.setHeaderFlag(MessageFlag::AA());
+    createRequestPacket(IPPROTO_UDP);
+    EXPECT_FALSE(server.processMessage(*io_message, parse_message,
+                                       response_renderer));
+}
+
+TEST_F(AuthSrvTest, notifyWithSessionMessageError) {
+    notify_session.setMessage(
+        Element::fromJSON("{\"result\": [1, \"FAIL\"]}"));
+
+    createRequestMessage(Opcode::NOTIFY(), Name("example.com"), RRClass::IN(),
+                        RRType::SOA());
+    request_message.setHeaderFlag(MessageFlag::AA());
+    createRequestPacket(IPPROTO_UDP);
+    EXPECT_FALSE(server.processMessage(*io_message, parse_message,
+                                       response_renderer));
+}
+
 void
 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());
 }
@@ -253,8 +716,8 @@
     // response should have the AA flag on, and have an RR in each answer
     // and authority section.
     createDataFromFile("examplequery_fromWire");
-    EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
-                                          response_renderer, true));
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
     headerCheck(parse_message, default_qid, Rcode::NOERROR(), opcode.getCode(),
                 QR_FLAG | AA_FLAG, 1, 1, 1, 0);
 }
@@ -267,10 +730,10 @@
     // in a SERVFAIL response, and the answer and authority sections should
     // be empty.
     createDataFromFile("badExampleQuery_fromWire");
-    EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
-                                          response_renderer, true));
-    headerCheck(parse_message, default_qid, Rcode::SERVFAIL(), opcode.getCode(),
-                QR_FLAG, 1, 0, 0, 0);
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
+    headerCheck(parse_message, default_qid, Rcode::SERVFAIL(),
+                opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
 }
 
 TEST_F(AuthSrvTest, updateConfigFail) {
@@ -282,8 +745,8 @@
 
     // The original data source should still exist.
     createDataFromFile("examplequery_fromWire");
-    EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
-                                          response_renderer, true));
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
     headerCheck(parse_message, default_qid, Rcode::NOERROR(), opcode.getCode(),
                 QR_FLAG | AA_FLAG, 1, 1, 1, 0);
 }

Modified: branches/trac232/src/bin/bind10/bind10.8
==============================================================================
--- branches/trac232/src/bin/bind10/bind10.8 (original)
+++ branches/trac232/src/bin/bind10/bind10.8 Wed Sep  1 00:35:07 2010
@@ -2,12 +2,12 @@
 .\"     Title: bind10
 .\"    Author: [see the "AUTHORS" section]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: April 19, 2010
+.\"      Date: July 29, 2010
 .\"    Manual: BIND10
 .\"    Source: BIND10
 .\"  Language: English
 .\"
-.TH "BIND10" "8" "April 19, 2010" "BIND10" "BIND10"
+.TH "BIND10" "8" "July 29, 2010" "BIND10" "BIND10"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
@@ -22,7 +22,7 @@
 bind10 \- BIND 10 boss process
 .SH "SYNOPSIS"
 .HP \w'\fBbind10\fR\ 'u
-\fBbind10\fR [\fB\-m\ \fR\fB\fInumber\fR\fR] [\fB\-p\ \fR\fB\fInumber\fR\fR] [\fB\-v\fR] [\fB\-msgq\-port\ \fR\fB\fInumber\fR\fR] [\fB\-port\ \fR\fB\fInumber\fR\fR] [\fB\-verbose\fR]
+\fBbind10\fR [\fB\-a\ \fR\fB\fIaddress\fR\fR] [\fB\-m\ \fR\fB\fIfile\fR\fR] [\fB\-n\fR] [\fB\-p\ \fR\fB\fInumber\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [\fB\-\-address\ \fR\fB\fIaddress\fR\fR] [\fB\-\-msgq\-socket\-file\ \fR\fB\fIfile\fR\fR] [\fB\-\-no\-cache\fR] [\fB\-\-port\ \fR\fB\fInumber\fR\fR] [\fB\-\-user\ \fR\fB\fIuser\fR\fR] [\fB\-\-verbose\fR]
 .SH "DESCRIPTION"
 .PP
 The
@@ -32,11 +32,26 @@
 .PP
 The arguments are as follows:
 .PP
-\fB\-m\fR \fInumber\fR, \fB\-\-msgq\-port\fR \fInumber\fR
+\fB\-a\fR \fIaddress\fR, \fB\-\-address\fR \fIaddress\fR
 .RS 4
-The port number for the
+The IPv4 or IPv6 address for the
+\fBb10-auth\fR(8)
+daemon to listen on\&. The default is to listen on all addresses\&. (This is a short term workaround\&. This argument may change\&.)
+.RE
+.PP
+\fB\-m\fR \fIfile\fR, \fB\-\-msgq\-socket\-file\fR \fIfile\fR
+.RS 4
+The UNIX domain socket file for the
 \fBb10-msgq\fR(8)
-daemon to listen on\&. The default is 9912\&.
+daemon to use\&. The default is
+/usr/local/var/bind10\-devel/msg_socket\&.
+.RE
+.PP
+\fB\-n\fR, \fB\-\-no\-cache\fR
+.RS 4
+Disables the hot\-spot caching used by the
+\fBb10-auth\fR(8)
+daemon\&.
 .RE
 .PP
 \fB\-p\fR \fInumber\fR, \fB\-\-port\fR \fInumber\fR
@@ -59,6 +74,16 @@
 The Y1 prototype release uses a non\-default port for domain service\&.
 .sp .5v
 .RE
+.RE
+.PP
+\fB\-u\fR \fIuser\fR, \fB\-\-user\fR \fIname\fR
+.RS 4
+The username for
+\fBbind10\fR
+to run as\&.
+
+\fBbind10\fR
+must be initially ran as the root user to use this option\&. The default is to run as the current user\&.
 .RE
 .PP
 \fB\-v\fR, \fB\-\-verbose\fR

Modified: branches/trac232/src/bin/bind10/bind10.py.in
==============================================================================
--- branches/trac232/src/bin/bind10/bind10.py.in (original)
+++ branches/trac232/src/bin/bind10/bind10.py.in Wed Sep  1 00:35:07 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.
 
@@ -336,6 +336,8 @@
             authargs += ['-a', str(self.address)]
         if self.nocache:
             authargs += ['-n']
+        if self.uid:
+            authargs += ['-u', str(self.uid)]
         if self.verbose:
             authargs += ['-v']
             sys.stdout.write("Starting b10-auth using port %d" %
@@ -396,6 +398,26 @@
             sys.stdout.write("[bind10] Started b10-xfrin (PID %d)\n" % 
                              xfrind.pid)
 
+        # start b10-zonemgr
+        zonemgr_args = ['b10-zonemgr']
+        if self.verbose:
+            sys.stdout.write("[bind10] Starting b10-zonemgr\n")
+            zonemgr_args += ['-v']
+        try:
+            zonemgr = ProcessInfo("b10-zonemgr", zonemgr_args,
+                                 c_channel_env)
+        except Exception as e:
+            c_channel.process.kill()
+            bind_cfgd.process.kill()
+            xfrout.process.kill()
+            auth.process.kill()
+            xfrind.process.kill()
+            return "Unable to start b10-zonemgr; " + str(e)
+        self.processes[zonemgr.pid] = zonemgr 
+        if self.verbose:
+            sys.stdout.write("[bind10] Started b10-zonemgr(PID %d)\n" % 
+                             zonemgr.pid)
+
         # start the b10-cmdctl
         # XXX: we hardcode port 8080
         cmdctl_args = ['b10-cmdctl']
@@ -411,6 +433,7 @@
             xfrout.process.kill()
             auth.process.kill()
             xfrind.process.kill()
+            zonemgr.process.kill()
             return "Unable to start b10-cmdctl; " + str(e)
         self.processes[cmd_ctrld.pid] = cmd_ctrld
         if self.verbose:
@@ -429,6 +452,7 @@
         self.cc_session.group_sendmsg(cmd, "Boss", "Auth")
         self.cc_session.group_sendmsg(cmd, "Boss", "Xfrout")
         self.cc_session.group_sendmsg(cmd, "Boss", "Xfrin")
+        self.cc_session.group_sendmsg(cmd, "Boss", "Zonemgr")
 
     def stop_process(self, process):
         """Stop the given process, friendly-like."""

Modified: branches/trac232/src/bin/bind10/bind10.xml
==============================================================================
--- branches/trac232/src/bin/bind10/bind10.xml (original)
+++ branches/trac232/src/bin/bind10/bind10.xml Wed Sep  1 00:35:07 2010
@@ -21,7 +21,7 @@
 <refentry>
 
   <refentryinfo>
-    <date>April 19, 2010</date>
+    <date>July 29, 2010</date>
   </refentryinfo>
 
   <refmeta>
@@ -45,12 +45,18 @@
   <refsynopsisdiv>
     <cmdsynopsis>
       <command>bind10</command>    
-      <arg><option>-m <replaceable>number</replaceable></option></arg>
+      <arg><option>-a <replaceable>address</replaceable></option></arg>
+      <arg><option>-m <replaceable>file</replaceable></option></arg>
+      <arg><option>-n</option></arg>
       <arg><option>-p <replaceable>number</replaceable></option></arg>
+      <arg><option>-u <replaceable>user</replaceable></option></arg>
       <arg><option>-v</option></arg>
-      <arg><option>-msgq-port <replaceable>number</replaceable></option></arg>
-      <arg><option>-port <replaceable>number</replaceable></option></arg>
-      <arg><option>-verbose</option></arg>
+      <arg><option>--address <replaceable>address</replaceable></option></arg>
+      <arg><option>--msgq-socket-file <replaceable>file</replaceable></option></arg>
+      <arg><option>--no-cache</option></arg>
+      <arg><option>--port <replaceable>number</replaceable></option></arg>
+      <arg><option>--user <replaceable>user</replaceable></option></arg>
+      <arg><option>--verbose</option></arg>
     </cmdsynopsis>
   </refsynopsisdiv>
 
@@ -80,14 +86,40 @@
     <variablelist>
 
       <varlistentry>
-        <term><option>-m</option> <replaceable>number</replaceable>, <option>--msgq-port</option> <replaceable>number</replaceable></term>
-
-        <listitem>
-          <para>The port number for the
+        <term><option>-a</option> <replaceable>address</replaceable>, <option>--address</option> <replaceable>address</replaceable></term>
+
+        <listitem>
+	  <para>The IPv4 or IPv6 address for the
+	    <citerefentry><refentrytitle>b10-auth</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+            daemon to listen on.
+            The default is to listen on all addresses. 
+            (This is a short term workaround. This argument may change.)
+          </para>
+         </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>-m</option> <replaceable>file</replaceable>,
+           <option>--msgq-socket-file</option> <replaceable>file</replaceable></term>
+
+        <listitem>
+          <para>The UNIX domain socket file for the
 	    <citerefentry><refentrytitle>b10-msgq</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-            daemon to listen on.
-            The default is 9912.</para>
-         </listitem>
+            daemon to use.
+            The default is
+            <filename>/usr/local/var/bind10-devel/msg_socket</filename>.
+<!-- @localstatedir@/@PACKAGE_NAME@/msg_socket -->
+           </para>
+         </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>-n</option>, <option>--no-cache</option></term>
+        <listitem>
+	  <para>Disables the hot-spot caching used by the
+	    <citerefentry><refentrytitle>b10-auth</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+	  daemon.</para>
+        </listitem>
       </varlistentry>
 
       <varlistentry>
@@ -105,6 +137,18 @@
       </varlistentry>
 
       <varlistentry>
+        <term><option>-u</option> <replaceable>user</replaceable>, <option>--user</option> <replaceable>name</replaceable></term>
+
+        <listitem>
+          <para>The username for <command>bind10</command> to run as.
+<!-- TODO: example more detail. -->
+            <command>bind10</command> must be initially ran as the
+            root user to use this option.
+            The default is to run as the current user.</para>
+         </listitem>
+      </varlistentry>
+
+      <varlistentry>
         <term><option>-v</option>, <option>--verbose</option></term>
         <listitem>
 	  <para>Display more about what is going on for
@@ -112,6 +156,7 @@
 <!-- TODO: not true about all children yet -->
         </listitem>
       </varlistentry>
+
     </variablelist>
   </refsect1>
 

Modified: branches/trac232/src/bin/bind10/run_bind10.sh.in
==============================================================================
--- branches/trac232/src/bin/bind10/run_bind10.sh.in (original)
+++ branches/trac232/src/bin/bind10/run_bind10.sh.in Wed Sep  1 00:35:07 2010
@@ -20,12 +20,19 @@
 
 BIND10_PATH=@abs_top_builddir@/src/bin/bind10
 
-PATH=@abs_top_builddir@/src/bin/msgq:@abs_top_builddir@/src/bin/auth:@abs_top_builddir@/src/bin/cfgmgr:@abs_top_builddir@/src/bin/cmdctl:@abs_top_builddir@/src/bin/xfrin:@abs_top_builddir@/src/bin/xfrout:$PATH
+PATH=@abs_top_builddir@/src/bin/msgq:@abs_top_builddir@/src/bin/auth:@abs_top_builddir@/src/bin/cfgmgr:@abs_top_builddir@/src/bin/cmdctl:@abs_top_builddir@/src/bin/xfrin:@abs_top_builddir@/src/bin/xfrout:@abs_top_builddir@/src/bin/zonemgr:$PATH
 export PATH
 
 PYTHONPATH=@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/lib/dns/python/.libs:@abs_top_builddir@/src/lib/xfr/.libs
-#PYTHONPATH=@abs_top_srcdir@/src/lib/python:@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/lib/dns/.libs:@abs_top_builddir@/src/lib/xfr/.libs
 export PYTHONPATH
+
+# If necessary (rare cases), explicitly specify paths to dynamic libraries
+# required by loadable python modules.
+SET_ENV_LIBRARY_PATH=@SET_ENV_LIBRARY_PATH@
+if test $SET_ENV_LIBRARY_PATH = yes; then
+	@ENV_LIBRARY_PATH@=@abs_top_builddir@/src/lib/dns/.libs:@abs_top_builddir@/src/lib/exceptions/.libs:$@ENV_LIBRARY_PATH@
+	export @ENV_LIBRARY_PATH@
+fi
 
 B10_FROM_SOURCE=@abs_top_srcdir@
 export B10_FROM_SOURCE

Modified: branches/trac232/src/bin/bind10/tests/Makefile.am
==============================================================================
--- branches/trac232/src/bin/bind10/tests/Makefile.am (original)
+++ branches/trac232/src/bin/bind10/tests/Makefile.am Wed Sep  1 00:35:07 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/trac232/src/bin/bindctl/bindcmd.py
==============================================================================
--- branches/trac232/src/bin/bindctl/bindcmd.py (original)
+++ branches/trac232/src/bin/bindctl/bindcmd.py Wed Sep  1 00:35:07 2010
@@ -35,10 +35,8 @@
 import getpass
 from hashlib import sha1
 import csv
-import ast
 import pwd
 import getpass
-import traceback
 
 try:
     from collections import OrderedDict
@@ -123,7 +121,6 @@
         except FailToLogin as err:
             print(err)
             print(FAIL_TO_CONNECT_WITH_CMDCTL)
-            traceback.print_exc()
         except KeyboardInterrupt:
             print('\nExit from bindctl')
 
@@ -142,8 +139,8 @@
             users_info = csv.reader(csvfile)
             for row in users_info:
                 users.append([row[0], row[1]])
-        except (IOError, IndexError) as e:
-            pass
+        except (IOError, IndexError) as err:
+            print("Error reading saved username and password from %s%s: %s" % (dir, file_name, err))
         finally:
             if csvfile:
                 csvfile.close()
@@ -162,8 +159,9 @@
             writer = csv.writer(csvfile)
             writer.writerow([username, passwd])
             csvfile.close()
-        except Exception as e:
-            print(e, "\nCannot write %s%s; default user is not stored" % (dir, file_name))
+        except IOError as err:
+            print("Error saving user information:", err)
+            print("user info file name: %s%s" % (dir, file_name))
             return False
 
         return True
@@ -183,8 +181,8 @@
             try:
                 response = self.send_POST('/login', param)
                 data = response.read().decode()
-            except socket.error:
-                traceback.print_exc()
+            except socket.error as err:
+                print("Socket error while sending login information:", err)
                 raise FailToLogin()
 
             if response.status == http.client.OK:
@@ -206,8 +204,8 @@
                 response = self.send_POST('/login', param)
                 data = response.read().decode()
                 print(data)
-            except socket.error as e:
-                traceback.print_exc()
+            except socket.error as err:
+                print("Socket error while sending login information:", err)
                 raise FailToLogin()
 
             if response.status == http.client.OK:
@@ -543,6 +541,16 @@
                     identifier = cmd.params['identifier']
                 else:
                     identifier += cmd.params['identifier']
+
+                # Check if the module is known; for unknown modules
+                # we currently deny setting preferences, as we have
+                # no way yet to determine if they are ok.
+                module_name = identifier.split('/')[1]
+                if self.config_data is None or \
+                   not self.config_data.have_specification(module_name):
+                    print("Error: Module '" + module_name + "' unknown or not running")
+                    return
+
             if cmd.command == "show":
                 values = self.config_data.get_value_maps(identifier)
                 for value_map in values:
@@ -568,7 +576,7 @@
                 else:
                     parsed_value = None
                     try:
-                        parsed_value = ast.literal_eval(cmd.params['value'])
+                        parsed_value = json.loads(cmd.params['value'])
                     except Exception as exc:
                         # ok could be an unquoted string, interpret as such
                         parsed_value = cmd.params['value']

Modified: branches/trac232/src/bin/bindctl/tests/Makefile.am
==============================================================================
--- branches/trac232/src/bin/bindctl/tests/Makefile.am (original)
+++ branches/trac232/src/bin/bindctl/tests/Makefile.am Wed Sep  1 00:35:07 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/trac232/src/bin/bindctl/tests/bindctl_test.py
==============================================================================
--- branches/trac232/src/bin/bindctl/tests/bindctl_test.py (original)
+++ branches/trac232/src/bin/bindctl/tests/bindctl_test.py Wed Sep  1 00:35:07 2010
@@ -237,6 +237,11 @@
             assert self.random_names[i] == cmd_names[i+1]
             assert self.random_names[i] == module_names[i+1]
             i = i + 1
+
+    def test_apply_cfg_command(self):
+        self.tool.location = '/'
+        cmd = cmdparse.BindCmdParse("config set identifier=\"foo/bar\" value=\"5\"")
+        self.tool.apply_config_cmd(cmd)
     
 class FakeBindCmdInterpreter(bindcmd.BindCmdInterpreter):
     def __init__(self):

Modified: branches/trac232/src/bin/cfgmgr/b10-cfgmgr.py.in
==============================================================================
--- branches/trac232/src/bin/cfgmgr/b10-cfgmgr.py.in (original)
+++ branches/trac232/src/bin/cfgmgr/b10-cfgmgr.py.in Wed Sep  1 00:35:07 2010
@@ -19,7 +19,7 @@
 
 import sys; sys.path.append ('@@PYTHONPATH@@')
 
-from isc.config.cfgmgr import ConfigManager
+from isc.config.cfgmgr import ConfigManager, ConfigManagerDataReadError
 from isc.cc import SessionError
 import signal
 import os
@@ -52,10 +52,15 @@
     except SessionError as se:
         print("[b10-cfgmgr] Error creating config manager, "
               "is the command channel daemon running?")
+        return 1
     except KeyboardInterrupt as kie:
         print("[b10-cfgmgr] Interrupted, exiting")
+    except ConfigManagerDataReadError as cmdre:
+        print("[b10-cfgmgr] " + str(cmdre))
+        return 2
     if cm:
-        cm.write_config()
+        return cm.write_config()
+    return 0
 
 if __name__ == "__main__":
-    main()
+    sys.exit(main())

Modified: branches/trac232/src/bin/cfgmgr/tests/Makefile.am
==============================================================================
--- branches/trac232/src/bin/cfgmgr/tests/Makefile.am (original)
+++ branches/trac232/src/bin/cfgmgr/tests/Makefile.am Wed Sep  1 00:35:07 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/trac232/src/bin/cmdctl/TODO
==============================================================================
--- branches/trac232/src/bin/cmdctl/TODO (original)
+++ branches/trac232/src/bin/cmdctl/TODO Wed Sep  1 00:35:07 2010
@@ -3,4 +3,5 @@
 . Add check for the content of key/certificate file
   (when cmdctl starts or is configured by bindctl).
 . Use only one msgq/session to communicate with other modules?
-
+. Add more test cases, especially about the cases where CmdctlException
+  is raised

Modified: branches/trac232/src/bin/cmdctl/cmdctl.py.in
==============================================================================
--- branches/trac232/src/bin/cmdctl/cmdctl.py.in (original)
+++ branches/trac232/src/bin/cmdctl/cmdctl.py.in Wed Sep  1 00:35:07 2010
@@ -441,7 +441,11 @@
                  CommandControlClass,
                  idle_timeout = 1200, verbose = False):
         '''idle_timeout: the max idle time for login'''
-        http.server.HTTPServer.__init__(self, server_address, RequestHandlerClass)
+        try:
+            http.server.HTTPServer.__init__(self, server_address, RequestHandlerClass)
+        except socket.error as err:
+            raise CmdctlException("Error creating server, because: %s \n" % str(err))
+
         self.user_sessions = {}
         self.idle_timeout = idle_timeout
         self.cmdctl = CommandControlClass(self, verbose)
@@ -587,20 +591,23 @@
             help="display more about what is going on")
 
 if __name__ == '__main__':
+    set_signal_handler()
+    parser = OptionParser(version = __version__)
+    set_cmd_options(parser)
+    (options, args) = parser.parse_args()
+    result = 1                  # in case of failure
     try:
-        set_signal_handler()
-        parser = OptionParser(version = __version__)
-        set_cmd_options(parser)
-        (options, args) = parser.parse_args()
         run(options.addr, options.port, options.idle_timeout, options.verbose)
-    except isc.cc.SessionError as se:
+        result = 0
+    except isc.cc.SessionError as err:
         sys.stderr.write("[b10-cmdctl] Error creating b10-cmdctl, "
-                "is the command channel daemon running?\n")        
+                         "is the command channel daemon running?\n")        
     except KeyboardInterrupt:
-        sys.stderr.write("[b10-cmdctl] exit http server\n")
+        sys.stderr.write("[b10-cmdctl] exit from Cmdctl\n")
+    except CmdctlException as err:
+        sys.stderr.write("[b10-cmdctl] " + str(err) + "\n")
 
     if httpd:
         httpd.shutdown()
 
-
-
+    sys.exit(result)

Modified: branches/trac232/src/bin/cmdctl/cmdctl.spec.pre.in
==============================================================================
--- branches/trac232/src/bin/cmdctl/cmdctl.spec.pre.in (original)
+++ branches/trac232/src/bin/cmdctl/cmdctl.spec.pre.in Wed Sep  1 00:35:07 2010
@@ -6,20 +6,20 @@
       {
         "item_name": "key_file",
         "item_type": "string",
-        "item_optional": False,
-        "item_default": '@@SYSCONFDIR@@/@PACKAGE@/cmdctl-keyfile.pem'
+        "item_optional": false,
+        "item_default": "@@SYSCONFDIR@@/@PACKAGE@/cmdctl-keyfile.pem"
       },
       {
         "item_name": "cert_file",
         "item_type": "string",
-        "item_optional": False,
-        "item_default": '@@SYSCONFDIR@@/@PACKAGE@/cmdctl-certfile.pem'
+        "item_optional": false,
+        "item_default": "@@SYSCONFDIR@@/@PACKAGE@/cmdctl-certfile.pem"
       },
       {
         "item_name": "accounts_file",
         "item_type": "string",
-        "item_optional": False,
-        "item_default": '@@SYSCONFDIR@@/@PACKAGE@/cmdctl-accounts.csv'
+        "item_optional": false,
+        "item_default": "@@SYSCONFDIR@@/@PACKAGE@/cmdctl-accounts.csv"
       }
     ],
     "commands": [
@@ -32,7 +32,7 @@
         "command_name": "shutdown",
         "command_description": "shutdown cmdctl",
         "command_args": []
-      },
+      }
     ]
   }
 }

Modified: branches/trac232/src/bin/cmdctl/tests/Makefile.am
==============================================================================
--- branches/trac232/src/bin/cmdctl/tests/Makefile.am (original)
+++ branches/trac232/src/bin/cmdctl/tests/Makefile.am Wed Sep  1 00:35:07 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/trac232/src/bin/cmdctl/tests/cmdctl_test.py
==============================================================================
--- branches/trac232/src/bin/cmdctl/tests/cmdctl_test.py (original)
+++ branches/trac232/src/bin/cmdctl/tests/cmdctl_test.py Wed Sep  1 00:35:07 2010
@@ -17,6 +17,7 @@
 import unittest
 import socket
 import tempfile
+import sys
 from cmdctl import *
 
 SPEC_FILE_PATH = '..' + os.sep
@@ -383,13 +384,31 @@
 class TestSecureHTTPServer(unittest.TestCase):
     def setUp(self):
         self.old_stdout = sys.stdout
+        self.old_stderr = sys.stderr
         sys.stdout = open(os.devnull, 'w')
+        sys.stderr = sys.stdout
         self.server = MySecureHTTPServer(('localhost', 8080), 
                                          MySecureHTTPRequestHandler,
                                          MyCommandControl, verbose=True)
 
     def tearDown(self):
         sys.stdout = self.old_stdout
+        sys.stderr = self.old_stderr
+
+    def test_addr_in_use(self):
+        server_one = None
+        try:
+            server_one = SecureHTTPServer(('localhost', 53531),
+                                        MySecureHTTPRequestHandler,
+                                        MyCommandControl)
+        except CmdctlException:
+            pass
+        else:
+            self.assertRaises(CmdctlException, SecureHTTPServer,
+                              ('localhost', 53531),
+                              MySecureHTTPRequestHandler, MyCommandControl)
+        if server_one:
+            server_one.server_close()
 
     def test_create_user_info(self):
         self.server._create_user_info('/local/not-exist')

Modified: branches/trac232/src/bin/host/Makefile.am
==============================================================================
--- branches/trac232/src/bin/host/Makefile.am (original)
+++ branches/trac232/src/bin/host/Makefile.am Wed Sep  1 00:35:07 2010
@@ -3,12 +3,16 @@
 
 AM_CXXFLAGS = $(B10_CXXFLAGS)
 
+if USE_STATIC_LINK
+AM_LDFLAGS = -static
+endif
+
 CLEANFILES = *.gcno *.gcda
 
 bin_PROGRAMS = host
 host_SOURCES = host.cc
-host_LDADD = $(top_builddir)/src/lib/dns/.libs/libdns++.a
-host_LDADD += $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a
+host_LDADD = $(top_builddir)/src/lib/dns/libdns++.la
+host_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 
 #man_MANS = host.1
 #EXTRA_DIST = $(man_MANS) host.xml

Modified: branches/trac232/src/bin/host/host.cc
==============================================================================
--- branches/trac232/src/bin/host/host.cc (original)
+++ branches/trac232/src/bin/host/host.cc Wed Sep  1 00:35:07 2010
@@ -24,14 +24,14 @@
 #include <string>
 #include <iostream>
 
-#include "dns/buffer.h"
-#include "dns/name.h"
-#include "dns/message.h"
-#include "dns/messagerenderer.h"
-#include "dns/rrclass.h"
-#include "dns/rrtype.h"
-#include "dns/rrset.h"
-#include "dns/message.h"
+#include <dns/buffer.h>
+#include <dns/name.h>
+#include <dns/message.h>
+#include <dns/messagerenderer.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+#include <dns/rrset.h>
+#include <dns/message.h>
 
 using namespace std;
 using namespace isc::dns;

Modified: branches/trac232/src/bin/loadzone/tests/correct/Makefile.am
==============================================================================
--- branches/trac232/src/bin/loadzone/tests/correct/Makefile.am (original)
+++ branches/trac232/src/bin/loadzone/tests/correct/Makefile.am Wed Sep  1 00:35:07 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/trac232/src/bin/loadzone/tests/error/Makefile.am
==============================================================================
--- branches/trac232/src/bin/loadzone/tests/error/Makefile.am (original)
+++ branches/trac232/src/bin/loadzone/tests/error/Makefile.am Wed Sep  1 00:35:07 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/trac232/src/bin/msgq/b10-msgq.8
==============================================================================
--- branches/trac232/src/bin/msgq/b10-msgq.8 (original)
+++ branches/trac232/src/bin/msgq/b10-msgq.8 Wed Sep  1 00:35:07 2010
@@ -2,12 +2,12 @@
 .\"     Title: b10-msgq
 .\"    Author: [see the "AUTHORS" section]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: April 19, 2010
+.\"      Date: August 4, 2010
 .\"    Manual: BIND10
 .\"    Source: BIND10
 .\"  Language: English
 .\"
-.TH "B10\-MSGQ" "8" "April 19, 2010" "BIND10" "BIND10"
+.TH "B10\-MSGQ" "8" "August 4, 2010" "BIND10" "BIND10"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
@@ -22,7 +22,7 @@
 b10-msgq \- message routing daemon for the Command Channel
 .SH "SYNOPSIS"
 .HP \w'\fBb10\-msgq\fR\ 'u
-\fBb10\-msgq\fR [\fB\-m\ \fR\fB\fInumber\fR\fR] [\fB\-v\fR] [\fB\-\-msgq\-port\ \fR\fB\fInumber\fR\fR] [\fB\-\-verbose\fR]
+\fBb10\-msgq\fR [\fB\-s\ \fR\fB\fIfile\fR\fR] [\fB\-v\fR] [\fB\-\-socket\-file\ \fR\fB\fIfile\fR\fR] [\fB\-\-verbose\fR]
 .SH "DESCRIPTION"
 .PP
 The
@@ -96,11 +96,10 @@
 .PP
 The arguments are as follows:
 .PP
-\fB\-m \fR\fB\fInumber\fR\fR, \fB\-\-msgq\-port \fR\fB\fInumber\fR\fR
+\fB\-s \fR\fB\fIfile\fR\fR, \fB\-\-socket\-file \fR\fB\fIfile\fR\fR
 .RS 4
-The port number that
-\fBb10\-msgq\fR
-will listen on\&. The default is 9912\&.
+The UNIX domain socket file this daemon will use\&. The default is
+/usr/local/var/bind10\-devel/msg_socket\&.
 .RE
 .PP
 \fB\-v\fR, \fB\-\-verbose\fR

Modified: branches/trac232/src/bin/msgq/msgq.py.in
==============================================================================
--- branches/trac232/src/bin/msgq/msgq.py.in (original)
+++ branches/trac232/src/bin/msgq/msgq.py.in Wed Sep  1 00:35:07 2010
@@ -212,7 +212,10 @@
            EOF."""
         received = b''
         while len(received) < length:
-            data = sock.recv(length - len(received))
+            try:
+                data = sock.recv(length - len(received))
+            except socket.error:
+                raise MsgQReceiveError(socket.error)
             if len(data) == 0:
                 raise MsgQReceiveError("EOF")
             received += data

Modified: branches/trac232/src/bin/msgq/msgq.xml
==============================================================================
--- branches/trac232/src/bin/msgq/msgq.xml (original)
+++ branches/trac232/src/bin/msgq/msgq.xml Wed Sep  1 00:35:07 2010
@@ -21,7 +21,7 @@
 <refentry>
 
   <refentryinfo>
-    <date>April 19, 2010</date>
+    <date>August 4, 2010</date>
   </refentryinfo>
 
   <refmeta>
@@ -45,9 +45,9 @@
   <refsynopsisdiv>
     <cmdsynopsis>
       <command>b10-msgq</command>
-      <arg><option>-m <replaceable>number</replaceable></option></arg>
+      <arg><option>-s <replaceable>file</replaceable></option></arg>
       <arg><option>-v</option></arg>
-      <arg><option>--msgq-port <replaceable>number</replaceable></option></arg>
+      <arg><option>--socket-file <replaceable>file</replaceable></option></arg>
       <arg><option>--verbose</option></arg>
     </cmdsynopsis>
   </refsynopsisdiv>
@@ -111,12 +111,14 @@
 
     <variablelist>
       <varlistentry>
-        <term><option>-m <replaceable>number</replaceable></option>,
-          <option>--msgq-port <replaceable>number</replaceable></option></term>
+        <term><option>-s <replaceable>file</replaceable></option>,
+          <option>--socket-file <replaceable>file</replaceable></option></term>
         <listitem><para>
-          The port number that <command>b10-msgq</command> will listen on.
-          The default is 9912.</para>
-        </listitem>
+          The UNIX domain socket file this daemon will use.
+          The default is
+          <filename>/usr/local/var/bind10-devel/msg_socket</filename>.
+<!-- @localstatedir@/@PACKAGE_NAME@/msg_socket -->
+          </para></listitem>
       </varlistentry>
 
       <varlistentry>

Modified: branches/trac232/src/bin/msgq/tests/Makefile.am
==============================================================================
--- branches/trac232/src/bin/msgq/tests/Makefile.am (original)
+++ branches/trac232/src/bin/msgq/tests/Makefile.am Wed Sep  1 00:35:07 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/trac232/src/bin/usermgr/b10-cmdctl-usermgr.py.in
==============================================================================
--- branches/trac232/src/bin/usermgr/b10-cmdctl-usermgr.py.in (original)
+++ branches/trac232/src/bin/usermgr/b10-cmdctl-usermgr.py.in Wed Sep  1 00:35:07 2010
@@ -69,8 +69,8 @@
 def main():
     filename = DEFAULT_FILE
     try: 
-        opts, args = getopt.getopt(sys.argv[1:], 'hvf:', 
-                                   ['help', 'file=', 'version=']) 
+        opts, args = getopt.getopt(sys.argv[1:], 'f:hv', 
+                                   ['file=', 'help', 'version']) 
     except getopt.GetoptError as err: 
         print(err) 
         usage() 

Modified: branches/trac232/src/bin/xfrin/tests/Makefile.am
==============================================================================
--- branches/trac232/src/bin/xfrin/tests/Makefile.am (original)
+++ branches/trac232/src/bin/xfrin/tests/Makefile.am Wed Sep  1 00:35:07 2010
@@ -1,5 +1,12 @@
 PYTESTS = xfrin_test.py
 EXTRA_DIST = $(PYTESTS)
+
+# If necessary (rare cases), explicitly specify paths to dynamic libraries
+# required by loadable python modules.
+LIBRARY_PATH_PLACEHOLDER =
+if SET_ENV_LIBRARY_PATH
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/xfr/.libs:$$$(ENV_LIBRARY_PATH)
+endif
 
 # later will have configure option to choose this, like: coverage run --branch
 PYCOVERAGE = $(PYTHON)
@@ -7,6 +14,7 @@
 check-local:
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
-	env PYTHONPATH=$(abs_top_builddir)/src/lib/dns/.libs:$(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 \
-	$(PYCOVERAGE) $(abs_srcdir)/$$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 || exit ; \
 	done

Modified: branches/trac232/src/bin/xfrin/tests/xfrin_test.py
==============================================================================
--- branches/trac232/src/bin/xfrin/tests/xfrin_test.py (original)
+++ branches/trac232/src/bin/xfrin/tests/xfrin_test.py Wed Sep  1 00:35:07 2010
@@ -63,6 +63,9 @@
 
     def _cc_setup(self):
         pass
+
+    def _get_db_file(self):
+        pass
     
     def _cc_check_command(self):
         self._shutdown_event.set()
@@ -408,53 +411,68 @@
     def tearDown(self):
         self.xfr.shutdown()
 
-    def _do_parse(self):
-        return self.xfr._parse_cmd_params(self.args)
+    def _do_parse_zone_name_class(self):
+        return self.xfr._parse_zone_name_and_class(self.args)
+
+    def _do_parse_master_port(self):
+        return self.xfr._parse_master_and_port(self.args)
 
     def test_parse_cmd_params(self):
-        name, master_addrinfo, db_file = self._do_parse()
+        name, rrclass = self._do_parse_zone_name_class()
+        master_addrinfo = self._do_parse_master_port()
+        db_file = self.args.get('db_file')
         self.assertEqual(master_addrinfo[4][1], int(TEST_MASTER_PORT))
         self.assertEqual(name, TEST_ZONE_NAME)
+        self.assertEqual(rrclass, TEST_RRCLASS)
         self.assertEqual(master_addrinfo[4][0], TEST_MASTER_IPV4_ADDRESS)
         self.assertEqual(db_file, TEST_DB_FILE)
 
     def test_parse_cmd_params_default_port(self):
         del self.args['port']
-        master_addrinfo = self._do_parse()[1]
+        master_addrinfo = self._do_parse_master_port()
         self.assertEqual(master_addrinfo[4][1], 53)
 
     def test_parse_cmd_params_ip6master(self):
         self.args['master'] = TEST_MASTER_IPV6_ADDRESS
-        master_addrinfo = self._do_parse()[1]
+        master_addrinfo = self._do_parse_master_port()
         self.assertEqual(master_addrinfo[4][0], TEST_MASTER_IPV6_ADDRESS)
+
+    def test_parse_cmd_params_chclass(self):
+        self.args['zone_class'] = 'CH'
+        self.assertEqual(self._do_parse_zone_name_class()[1], RRClass.CH())
+
+    def test_parse_cmd_params_bogusclass(self):
+        self.args['zone_class'] = 'XXX'
+        self.assertRaises(XfrinException, self._do_parse_zone_name_class)
 
     def test_parse_cmd_params_nozone(self):
         # zone name is mandatory.
         del self.args['zone_name']
-        self.assertRaises(XfrinException, self._do_parse)
+        self.assertRaises(XfrinException, self._do_parse_zone_name_class)
 
     def test_parse_cmd_params_nomaster(self):
         # master address is mandatory.
         del self.args['master']
-        self.assertRaises(XfrinException, self._do_parse)
+        master_addrinfo = self._do_parse_master_port()
+        self.assertEqual(master_addrinfo[4][0], DEFAULT_MASTER)
 
     def test_parse_cmd_params_bad_ip4(self):
         self.args['master'] = '3.3.3.3.3'
-        self.assertRaises(XfrinException, self._do_parse)
+        self.assertRaises(XfrinException, self._do_parse_master_port)
 
     def test_parse_cmd_params_bad_ip6(self):
         self.args['master'] = '1::1::1'
-        self.assertRaises(XfrinException, self._do_parse)
+        self.assertRaises(XfrinException, self._do_parse_master_port)
 
     def test_parse_cmd_params_bad_port(self):
         self.args['port'] = '-1'
-        self.assertRaises(XfrinException, self._do_parse)
+        self.assertRaises(XfrinException, self._do_parse_master_port)
 
         self.args['port'] = '65536'
-        self.assertRaises(XfrinException, self._do_parse)
+        self.assertRaises(XfrinException, self._do_parse_master_port)
 
         self.args['port'] = 'http'
-        self.assertRaises(XfrinException, self._do_parse)
+        self.assertRaises(XfrinException, self._do_parse_master_port)
 
     def test_command_handler_shutdown(self):
         self.assertEqual(self.xfr.command_handler("shutdown",
@@ -504,16 +522,44 @@
         self.assertEqual(self.xfr.command_handler("refresh",
                                                   self.args)['result'][0], 0)
 
+    def test_command_handler_notify(self):
+        # at this level, refresh is no different than retransfer.
+        self.args['master'] = TEST_MASTER_IPV6_ADDRESS
+        # ...but right now we disable the feature due to security concerns.
+        self.assertEqual(self.xfr.command_handler("notify",
+                                                  self.args)['result'][0], 0)
+
     def test_command_handler_unknown(self):
         self.assertEqual(self.xfr.command_handler("xxx", None)['result'][0], 1)
 
+    def test_command_handler_transfers_in(self):
+        self.assertEqual(self.xfr.config_handler({})['result'][0], 0)
+        self.assertEqual(self.xfr.config_handler({'transfers_in': 3})['result'][0], 0)
+        self.assertEqual(self.xfr._max_transfers_in, 3)
+
+    def test_command_handler_masters(self):
+        master_info = {'master_addr': '1.1.1.1', 'master_port':53}
+        self.assertEqual(self.xfr.config_handler(master_info)['result'][0], 0)
+
+        master_info = {'master_addr': '1111.1.1.1', 'master_port':53 }
+        self.assertEqual(self.xfr.config_handler(master_info)['result'][0], 1)
+
+        master_info = {'master_addr': '2.2.2.2', 'master_port':530000 }
+        self.assertEqual(self.xfr.config_handler(master_info)['result'][0], 1)
+
+        master_info = {'master_addr': '2.2.2.2', 'master_port':53 } 
+        self.xfr.config_handler(master_info)
+        self.assertEqual(self.xfr._master_addr, '2.2.2.2')
+        self.assertEqual(self.xfr._master_port, 53)
+
+
 def raise_interrupt():
     raise KeyboardInterrupt()
 
 def raise_ccerror():
     raise isc.cc.session.SessionError('test error')
 
-def raise_excpetion():
+def raise_exception():
     raise Exception('test exception')
 
 class TestMain(unittest.TestCase):
@@ -535,7 +581,7 @@
         main(MockXfrin, False)
 
     def test_startup_generalerror(self):
-        MockXfrin.check_command_hook = raise_excpetion
+        MockXfrin.check_command_hook = raise_exception
         main(MockXfrin, False)
 
 if __name__== "__main__":

Modified: branches/trac232/src/bin/xfrin/xfrin.py.in
==============================================================================
--- branches/trac232/src/bin/xfrin/xfrin.py.in (original)
+++ branches/trac232/src/bin/xfrin/xfrin.py.in Wed Sep  1 00:35:07 2010
@@ -28,6 +28,7 @@
 import random
 from optparse import OptionParser, OptionValueError
 from isc.config.ccsession import *
+from isc.notify import notify_out
 try:
     from libdns_python import *
 except ImportError as e:
@@ -49,13 +50,17 @@
 SPECFILE_LOCATION = SPECFILE_PATH + "/xfrin.spec"
 AUTH_SPECFILE_LOCATION = AUTH_SPECFILE_PATH + "/auth.spec"
 
-
+XFROUT_MODULE_NAME = 'Xfrout'
+ZONE_MANAGER_MODULE_NAME = 'Zonemgr'
+REFRESH_FROM_ZONEMGR = 'refresh_from_zonemgr'
+ZONE_XFRIN_FAILED = 'zone_xfrin_failed'
 __version__ = 'BIND10'
 # define xfrin rcode
 XFRIN_OK = 0
 XFRIN_FAIL = 1
 
 DEFAULT_MASTER_PORT = '53'
+DEFAULT_MASTER = '127.0.0.1'
 
 def log_error(msg):
     sys.stderr.write("[b10-xfrin] %s\n" % str(msg))
@@ -316,14 +321,15 @@
             sys.stdout.write('[b10-xfrin] %s\n' % str(msg))
 
 
-def process_xfrin(xfrin_recorder, zone_name, rrclass, db_file, 
+def process_xfrin(server, xfrin_recorder, zone_name, rrclass, db_file, 
                   shutdown_event, master_addrinfo, check_soa, verbose):
     xfrin_recorder.increment(zone_name)
     sock_map = {}
     conn = XfrinConnection(sock_map, zone_name, rrclass, db_file,
                            shutdown_event, master_addrinfo, verbose)
     if conn.connect_to_master():
-        conn.do_xfrin(check_soa)
+        ret = conn.do_xfrin(check_soa)
+        server.publish_xfrin_news(zone_name, rrclass, ret)
 
     xfrin_recorder.decrement(zone_name)
 
@@ -358,32 +364,54 @@
 
 class Xfrin:
     def __init__(self, verbose = False):
+        self._max_transfers_in = 10
+        #TODO, this is the temp way to set the zone's master.
+        self._master_addr = DEFAULT_MASTER
+        self._master_port = DEFAULT_MASTER_PORT
         self._cc_setup()
-        self._max_transfers_in = 10
         self.recorder = XfrinRecorder()
         self._shutdown_event = threading.Event()
         self._verbose = verbose
 
     def _cc_setup(self):
-        '''
-This method is used only as part of initialization, but is implemented
-separately for convenience of unit tests; by letting the test code override
-this method we can test most of this class without requiring a command channel.
-'''
-        self._cc = isc.config.ModuleCCSession(SPECFILE_LOCATION,
+        '''This method is used only as part of initialization, but is 
+        implemented separately for convenience of unit tests; by letting 
+        the test code override this method we can test most of this class 
+        without requiring a command channel.'''
+        # Create one session for sending command to other modules, because the 
+        # listening session will block the send operation.
+        self._send_cc_session = isc.cc.Session()
+        self._module_cc = isc.config.ModuleCCSession(SPECFILE_LOCATION,
                                               self.config_handler,
                                               self.command_handler)
-        self._cc.start()
+        self._module_cc.start()
+        config_data = self._module_cc.get_full_config()
+        self._max_transfers_in = config_data.get("transfers_in")
+        self._master_addr = config_data.get('master_addr') or self._master_addr
+        self._master_port = config_data.get('master_port') or self._master_port
 
     def _cc_check_command(self):
-        '''
-This is a straightforward wrapper for cc.check_command, but provided as
-a separate method for the convenience of unit tests.
-'''
-        self._cc.check_command()
+        '''This is a straightforward wrapper for cc.check_command, 
+        but provided as a separate method for the convenience 
+        of unit tests.'''
+        self._module_cc.check_command()
 
     def config_handler(self, new_config):
-        # TODO, process new config data
+        self._max_transfers_in = new_config.get("transfers_in") or self._max_transfers_in
+        if ('master_addr' in new_config) or ('master_port' in new_config):
+            # Check if the new master is valid, there should be library for check it.
+            # and user should change the port and address together.
+            try:
+                addr = new_config.get('master_addr') or self._master_addr
+                port = new_config.get('master_port') or self._master_port
+                check_addr_port(addr, port)
+                self._master_addr = addr
+                self._master_port = port
+            except:
+                errmsg = "bad format for zone's master: " + str(new_config)
+                log_error(errmsg)
+                return create_answer(1, errmsg)
+
         return create_answer(0)
 
     def shutdown(self):
@@ -397,60 +425,97 @@
                 continue
             th.join()
 
-
     def command_handler(self, command, args):
         answer = create_answer(0)
         try:
             if command == 'shutdown':
                 self._shutdown_event.set()
+            elif command == 'notify' or command == REFRESH_FROM_ZONEMGR:
+                # Xfrin receives the refresh/notify command from zone manager. 
+                # notify command maybe has the parameters which 
+                # specify the notifyfrom address and port, according the RFC1996, zone
+                # transfer should starts first from the notifyfrom, but now, let 'TODO' it.
+                (zone_name, rrclass) = self._parse_zone_name_and_class(args)
+                (master_addr) = check_addr_port(self._master_addr, self._master_port)
+                ret = self.xfrin_start(zone_name, 
+                                       rrclass, 
+                                       self._get_db_file(),
+                                       master_addr,
+                                       True)
+                answer = create_answer(ret[0], ret[1])
+
             elif command == 'retransfer' or command == 'refresh':
-                # The default RR class is IN.  We should fix this so that
-                # the class is passed in the command arg (where we specify
-                # the default)
-                rrclass = RRClass.IN()
-                zone_name, master_addr, db_file = self._parse_cmd_params(args)
-                ret = self.xfrin_start(zone_name, rrclass, db_file, master_addr,
-                                   False if command == 'retransfer' else True)
+                # Xfrin receives the retransfer/refresh from cmdctl(sent by bindctl).
+                # If the command has specified master address, do transfer from the 
+                # master address, or else do transfer from the configured masters.                
+                (zone_name, rrclass) = self._parse_zone_name_and_class(args)
+                master_addr = self._parse_master_and_port(args)
+                db_file = args.get('db_file') or self._get_db_file()
+                ret = self.xfrin_start(zone_name, 
+                                       rrclass, 
+                                       db_file, 
+                                       master_addr,
+                                       (False if command == 'retransfer' else True))
                 answer = create_answer(ret[0], ret[1])
+
             else:
                 answer = create_answer(1, 'unknown command: ' + command)
-
         except XfrinException as err:
+            log_error('error happened for command: %s, %s' % (command, str(err)) )
             answer = create_answer(1, str(err))
-
         return answer
 
-    def _parse_cmd_params(self, args):
+    def _parse_zone_name_and_class(self, args):
         zone_name = args.get('zone_name')
         if not zone_name:
             raise XfrinException('zone name should be provided')
 
-        master = args.get('master')
-        if not master:
-            raise XfrinException('master address should be provided')
-
-        port_str = args.get('port')
-        if not port_str:
-            port_str = DEFAULT_MASTER_PORT
-        master_addrinfo = check_addr_port(master, port_str)
-
-        db_file = args.get('db_file')
-        if not db_file:
-            #TODO, the db file path should be got in auth server's configuration
-            # if we need access to this configuration more often, we
-            # should add it on start, and not remove it here
-            # (or, if we have writable ds, we might not need this in
-            # the first place)
-            self._cc.add_remote_config(AUTH_SPECFILE_LOCATION)
-            db_file, is_default = self._cc.get_remote_config_value("Auth", "database_file")
-            if is_default and "B10_FROM_BUILD" in os.environ:
-                # this too should be unnecessary, but currently the
-                # 'from build' override isn't stored in the config
-                # (and we don't have writable datasources yet)
-                db_file = os.environ["B10_FROM_BUILD"] + os.sep + "bind10_zones.sqlite3"
-            self._cc.remove_remote_config(AUTH_SPECFILE_LOCATION)
-
-        return (zone_name, master_addrinfo, db_file)
+        rrclass = args.get('zone_class')
+        if not rrclass:
+            rrclass = RRClass.IN()
+        else:
+            try:
+                rrclass = RRClass(rrclass)
+            except InvalidRRClass as e:
+                raise XfrinException('invalid RRClass: ' + rrclass)
+        
+        return zone_name, rrclass
+
+    def _parse_master_and_port(self, args):
+        port = args.get('port') or self._master_port
+        master = args.get('master') or self._master_addr
+        return check_addr_port(master, port)
+ 
+    def _get_db_file(self):
+        #TODO, the db file path should be got in auth server's configuration
+        # if we need access to this configuration more often, we
+        # should add it on start, and not remove it here
+        # (or, if we have writable ds, we might not need this in
+        # the first place)
+        self._module_cc.add_remote_config(AUTH_SPECFILE_LOCATION)
+        db_file, is_default = self._module_cc.get_remote_config_value("Auth", "database_file")
+        if is_default and "B10_FROM_BUILD" in os.environ:
+            # this too should be unnecessary, but currently the
+            # 'from build' override isn't stored in the config
+            # (and we don't have writable datasources yet)
+            db_file = os.environ["B10_FROM_BUILD"] + os.sep + "bind10_zones.sqlite3"
+        self._module_cc.remove_remote_config(AUTH_SPECFILE_LOCATION)
+        return db_file
+       
+    def publish_xfrin_news(self, zone_name, zone_class,  xfr_result):
+        '''Send command to xfrout/zone manager module.
+        If xfrin has finished successfully for one zone, tell the good 
+        news(command: zone_new_data_ready) to zone manager and xfrout.
+        if xfrin failed, just tell the bad news to zone manager, so that 
+        it can reset the refresh timer for that zone. '''
+        param = {'zone_name': zone_name, 'zone_class': zone_class.to_text()}
+        if xfr_result == XFRIN_OK:
+            msg = create_command(notify_out.ZONE_NEW_DATA_READY_CMD, param)
+            self._send_cc_session.group_sendmsg(msg, XFROUT_MODULE_NAME)
+            self._send_cc_session.group_sendmsg(msg, ZONE_MANAGER_MODULE_NAME)
+        else:
+            msg = create_command(ZONE_XFRIN_FAILED, param)
+            self._send_cc_session.group_sendmsg(msg, ZONE_MANAGER_MODULE_NAME)
 
     def startup(self):
         while not self._shutdown_event.is_set():
@@ -469,7 +534,8 @@
             return (1, 'zone xfrin is in progress')
 
         xfrin_thread = threading.Thread(target = process_xfrin,
-                                        args = (self.recorder,
+                                        args = (self,
+                                                self.recorder,
                                                 zone_name, rrclass,
                                                 db_file,
                                                 self._shutdown_event,

Modified: branches/trac232/src/bin/xfrin/xfrin.spec.pre.in
==============================================================================
--- branches/trac232/src/bin/xfrin/xfrin.spec.pre.in (original)
+++ branches/trac232/src/bin/xfrin/xfrin.spec.pre.in Wed Sep  1 00:35:07 2010
@@ -6,37 +6,54 @@
       {
         "item_name": "transfers_in",
         "item_type": "integer",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 10
+      },
+      {
+        "item_name": "master_addr",
+        "item_type": "string",
+        "item_optional": false,
+        "item_default": ""
+      },
+      { "item_name": "master_port",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 53
       }
     ],
     "commands": [
      {
-        'command_name': 'retransfer',
-        "command_description": 'retransfer a single zone without checking zone serial number',
-        'command_args': [ {
+        "command_name": "retransfer",
+        "command_description": "retransfer a single zone without checking zone serial number",
+        "command_args": [ {
             "item_name": "zone_name",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": ""
+          },
+          {
+            "item_name": "zone_class",
+            "item_type": "string",
+            "item_optional": true,
+            "item_default": "IN"
           },
           {
             "item_name": "master",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": true,
             "item_default": ""
           },
           {
             "item_name": "port",
             "item_type": "integer",
-            "item_optional": True,
+            "item_optional": true,
             "item_default": 53
           },
           {
             "item_name": "db_file",
             "item_type": "string",
-            "item_optional": True,
-            "item_default": '@@LOCALSTATEDIR@@/@PACKAGE@/zone.sqlite3'
+            "item_optional": true,
+            "item_default": "@@LOCALSTATEDIR@@/@PACKAGE@/zone.sqlite3"
           }
         ]
       },

Modified: branches/trac232/src/bin/xfrout/tests/Makefile.am
==============================================================================
--- branches/trac232/src/bin/xfrout/tests/Makefile.am (original)
+++ branches/trac232/src/bin/xfrout/tests/Makefile.am Wed Sep  1 00:35:07 2010
@@ -1,5 +1,12 @@
 PYTESTS = xfrout_test.py
 EXTRA_DIST = $(PYTESTS)
+
+# If necessary (rare cases), explicitly specify paths to dynamic libraries
+# required by loadable python modules.
+LIBRARY_PATH_PLACEHOLDER =
+if SET_ENV_LIBRARY_PATH
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/xfr/.libs:$$$(ENV_LIBRARY_PATH)
+endif
 
 # later will have configure option to choose this, like: coverage run --branch
 PYCOVERAGE = $(PYTHON)
@@ -7,6 +14,7 @@
 check-local:
 	for pytest in $(PYTESTS) ; do \
 	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/.libs:$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/lib/xfr/.libs \
-	$(PYCOVERAGE) $(abs_srcdir)/$$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 || exit ; \
 	done

Modified: branches/trac232/src/bin/xfrout/xfrout.py.in
==============================================================================
--- branches/trac232/src/bin/xfrout/xfrout.py.in (original)
+++ branches/trac232/src/bin/xfrout/xfrout.py.in Wed Sep  1 00:35:07 2010
@@ -28,6 +28,7 @@
 from isc.config.ccsession import *
 from isc.log.log import *
 from isc.cc import SessionError
+from isc.notify import notify_out
 import socket
 import select
 import errno
@@ -303,7 +304,7 @@
         self._log = log
         self.update_config_data(config_data)
         self._cc = cc
-
+        
     def finish_request(self, request, client_address):
         '''Finish one request by instantiating RequestHandlerClass.'''
         self.RequestHandlerClass(request, client_address, self, self._log)
@@ -415,16 +416,25 @@
                                 self._config_data.get('log_severity'), self._config_data.get('log_versions'),
                                 self._config_data.get('log_max_bytes'), True)
         self._start_xfr_query_listener()
+        self._start_notifier()
 
     def _start_xfr_query_listener(self):
         '''Start a new thread to accept xfr query. '''
-    
         self._unix_socket_server = UnixSockServer(self._listen_sock_file, XfroutSession, 
                                                   self._shutdown_event, self._config_data,
                                                   self._cc, self._log);
         listener = threading.Thread(target = listen_on_xfr_query, args = (self._unix_socket_server,))
         listener.start()
-
+        
+    def _start_notifier(self):
+        datasrc = self._unix_socket_server.get_db_file()
+        self._notifier = notify_out.NotifyOut(datasrc, self._log)
+        td = threading.Thread(target = notify_out.dispatcher, args = (self._notifier,))
+        td.daemon = True
+        td.start()
+
+    def send_notify(self, zone_name, zone_class):
+        self._notifier.send_notify(zone_name, zone_class)
 
     def config_handler(self, new_config):
         '''Update config data. TODO. Do error check'''
@@ -466,11 +476,22 @@
             self._log.log_message("info", "Received shutdown command.")
             self.shutdown()
             answer = create_answer(0)
+        
+        elif cmd == notify_out.ZONE_NEW_DATA_READY_CMD:
+            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.send_notify(zone_name, zone_class)
+                answer = create_answer(0)
+            else:
+                answer = create_answer(1, "Bad command parameter:" + str(args))
+
         else: 
             answer = create_answer(1, "Unknown command:" + str(cmd))
 
         return answer    
- 
 
     def run(self):
         '''Get and process all commands sent from cfgmgr or other modules. '''

Modified: branches/trac232/src/bin/xfrout/xfrout.spec.pre.in
==============================================================================
--- branches/trac232/src/bin/xfrout/xfrout.spec.pre.in (original)
+++ branches/trac232/src/bin/xfrout/xfrout.spec.pre.in Wed Sep  1 00:35:07 2010
@@ -5,43 +5,43 @@
        {
          "item_name": "transfers_out",
          "item_type": "integer",
-         "item_optional": False,
+         "item_optional": false,
          "item_default": 10
        },
        {
          "item_name": "db_file",
          "item_type": "string",
-         "item_optional": False,
+         "item_optional": false,
          "item_default": "@@LOCALSTATEDIR@@/@PACKAGE@/zone.sqlite3"
        },
        {
          "item_name": "log_name",
          "item_type": "string",
-         "item_optional": False,
+         "item_optional": false,
          "item_default": "Xfrout"
        },
        {
          "item_name": "log_file",
     	 "item_type": "string",
-         "item_optional": False,
+         "item_optional": false,
          "item_default": "@@LOCALSTATEDIR@@/@PACKAGE@/log/Xfrout.log"
        },
        {
          "item_name": "log_severity",
     	 "item_type": "string",
-         "item_optional": False,
+         "item_optional": false,
     	 "item_default": "debug"
        },
        {
          "item_name": "log_versions",
     	 "item_type": "integer",
-         "item_optional": False,
+         "item_optional": false,
     	 "item_default": 5
        },
        {
          "item_name": "log_max_bytes",
     	 "item_type": "integer",
-         "item_optional": False,
+         "item_optional": false,
     	 "item_default": 1048576
        }
       ],

Modified: branches/trac232/src/lib/Makefile.am
==============================================================================
--- branches/trac232/src/lib/Makefile.am (original)
+++ branches/trac232/src/lib/Makefile.am Wed Sep  1 00:35:07 2010
@@ -1,1 +1,1 @@
-SUBDIRS = exceptions dns cc config datasrc python xfr
+SUBDIRS = exceptions dns cc config datasrc python xfr bench

Modified: branches/trac232/src/lib/cc/Makefile.am
==============================================================================
--- branches/trac232/src/lib/cc/Makefile.am (original)
+++ branches/trac232/src/lib/cc/Makefile.am Wed Sep  1 00:35:07 2010
@@ -1,3 +1,5 @@
+SUBDIRS = . tests
+
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
 
@@ -19,20 +21,3 @@
 	$(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" session_config.h.pre >$@
 
 BUILT_SOURCES = session_config.h 
-
-TESTS =
-if HAVE_GTEST
-TESTS += run_unittests
-# (TODO: these need to be completed and moved to tests/)
-run_unittests_SOURCES = data_unittests.cc session_unittests.cc run_unittests.cc
-run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
-# TODO: remove PTHREAD_LDFLAGS (and from configure too)
-run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS) $(PTHREAD_LDFLAGS)
-
-run_unittests_LDADD = libcc.la $(GTEST_LDADD)
-run_unittests_LDADD +=  $(top_builddir)/src/lib/dns/.libs/libdns++.a
-run_unittests_LDADD +=  $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a
-
-endif
-
-noinst_PROGRAMS = $(TESTS)

Modified: branches/trac232/src/lib/cc/data.cc
==============================================================================
--- branches/trac232/src/lib/cc/data.cc (original)
+++ branches/trac232/src/lib/cc/data.cc Wed Sep  1 00:35:07 2010
@@ -14,12 +14,13 @@
 
 // $Id$
 
-#include "config.h"
-
-#include "data.h"
+#include <config.h>
+
+#include <cc/data.h>
 
 #include <cassert>
 #include <climits>
+#include <map>
 #include <cstdio>
 #include <iostream>
 #include <string>
@@ -35,24 +36,21 @@
 namespace data {
 
 std::string
-Element::str()
-{
+Element::str() const {
     std::stringstream ss;
     toJSON(ss);
-    return ss.str();
+    return (ss.str());
 }
 
 std::string
-Element::toWire()
-{
+Element::toWire() const {
     std::stringstream ss;
     toJSON(ss);
-    return ss.str();
-}
-
-void
-Element::toWire(std::ostream& ss)
-{
+    return (ss.str());
+}
+
+void
+Element::toWire(std::ostream& ss) const {
     toJSON(ss);
 }
 
@@ -65,77 +63,78 @@
 //
 bool
 Element::getValue(long int& t UNUSED_PARAM) {
-    return false;
+    return (false);
 }
 
 bool
 Element::getValue(double& t UNUSED_PARAM) {
-    return false;
+    return (false);
 }
 
 bool
 Element::getValue(bool& t UNUSED_PARAM) {
-    return false;
+    return (false);
 }
 
 bool
 Element::getValue(std::string& t UNUSED_PARAM) {
-    return false;
-}
-
-bool
-Element::getValue(std::vector<ElementPtr>& t UNUSED_PARAM) {
-    return false;
-}
-
-bool
-Element::getValue(std::map<std::string, ElementPtr>& t UNUSED_PARAM) {
-    return false;
+    return (false);
+}
+
+bool
+Element::getValue(std::vector<ConstElementPtr>& t UNUSED_PARAM) {
+    return (false);
+}
+
+bool
+Element::getValue(std::map<std::string, ConstElementPtr>& t UNUSED_PARAM) {
+    return (false);
 }
 
 bool
 Element::setValue(const long int v UNUSED_PARAM) {
-    return false;
+    return (false);
 }
 
 bool
 Element::setValue(const double v UNUSED_PARAM) {
-    return false;
+    return (false);
 }
 
 bool
 Element::setValue(const bool t UNUSED_PARAM) {
-    return false;
+    return (false);
 }
 
 bool
 Element::setValue(const std::string& v UNUSED_PARAM) {
-    return false;
-}
-
-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) {
+    return (false);
+}
+
+bool
+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");
 }
 
@@ -145,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");
 }
@@ -167,20 +166,20 @@
 }
 
 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)
-{
-    return false;
+              ConstElementPtr t UNUSED_PARAM) const
+{
+    return (false);
 }
 
 namespace {
@@ -193,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));
 };
 
 //
@@ -206,37 +211,37 @@
 //
 ElementPtr
 Element::create() {
-    return ElementPtr(new NullElement());
+    return (ElementPtr(new NullElement()));
 }
 
 ElementPtr
 Element::create(const long int i) {
-    return ElementPtr(new IntElement(i));
+    return (ElementPtr(new IntElement(i)));
 }
 
 ElementPtr
 Element::create(const double d) {
-    return ElementPtr(new DoubleElement(d));
+    return (ElementPtr(new DoubleElement(d)));
 }
 
 ElementPtr
 Element::create(const std::string& s) {
-    return ElementPtr(new StringElement(s));
+    return (ElementPtr(new StringElement(s)));
 }
 
 ElementPtr
 Element::create(const bool b) {
-    return ElementPtr(new BoolElement(b));
+    return (ElementPtr(new BoolElement(b)));
 }
 
 ElementPtr
 Element::createList() {
-    return ElementPtr(new ListElement());
+    return (ElementPtr(new ListElement()));
 }
 
 ElementPtr
 Element::createMap() {
-    return ElementPtr(new MapElement());
+    return (ElementPtr(new MapElement()));
 }
 
 
@@ -248,10 +253,10 @@
 char_in(const char c, const char *chars) {
     for (size_t i = 0; i < strlen(chars); ++i) {
         if (chars[i] == c) {
-            return true;
-        }
-    }
-    return false;
+            return (true);
+        }
+    }
+    return (false);
 }
 
 void
@@ -332,7 +337,7 @@
         c = in.get();
         ++pos;
     }
-    return ss.str();
+    return (ss.str());
 }
 
 std::string
@@ -342,7 +347,7 @@
         ss << (char) in.get();
     }
     pos += ss.str().size();
-    return ss.str();
+    return (ss.str());
 }
 
 static std::string
@@ -353,7 +358,7 @@
         ss << (char) in.get();
     }
     pos += ss.str().size();
-    return ss.str();
+    return (ss.str());
 }
 
 // Should we change from IntElement and DoubleElement to NumberElement
@@ -386,9 +391,9 @@
     }
     
     if (is_double) {
-        return Element::create(d);
-    } else {
-        return Element::create(i);
+        return (Element::create(d));
+    } else {
+        return (Element::create(i));
     }
 }
 
@@ -398,13 +403,13 @@
 {
     const std::string word = word_from_stringstream(in, pos);
     if (boost::iequals(word, "True")) {
-        return Element::create(true);
+        return (Element::create(true));
     } else if (boost::iequals(word, "False")) {
-        return Element::create(false);
+        return (Element::create(false));
     } else {
         throwJSONError(std::string("Bad boolean value: ") + word, file, line, pos);
         // above is a throw shortcurt, return empty is never reached
-        return ElementPtr();
+        return (ElementPtr());
     }
 }
 
@@ -414,17 +419,17 @@
 {
     const std::string word = word_from_stringstream(in, pos);
     if (boost::iequals(word, "null")) {
-        return Element::create();
+        return (Element::create());
     } else {
         throwJSONError(std::string("Bad null value: ") + word, file, line, pos);
-        return ElementPtr();
+        return (ElementPtr());
     }
 }
 
 ElementPtr
 from_stringstream_string(std::istream& in, const std::string& file, int& line, int& pos)
 {
-    return Element::create(str_from_stringstream(in, file, line, pos));
+    return (Element::create(str_from_stringstream(in, file, line, pos)));
 }
 
 ElementPtr
@@ -432,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 != ']') {
@@ -444,7 +449,7 @@
         c = in.get();
         pos++;
     }
-    return list;
+    return (list);
 }
 
 ElementPtr
@@ -466,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");
@@ -474,53 +479,53 @@
             pos++;
         }
     }
-    return map;
+    return (map);
 }
 }
 
 std::string
 Element::typeToName(Element::types type)
 {
-    switch(type) {
+    switch (type) {
     case Element::integer:
-        return std::string("integer");
+        return (std::string("integer"));
     case Element::real:
-        return std::string("real");
+        return (std::string("real"));
     case Element::boolean:
-        return std::string("boolean");
+        return (std::string("boolean"));
     case Element::string:
-        return std::string("string");
+        return (std::string("string"));
     case Element::list:
-        return std::string("list");
+        return (std::string("list"));
     case Element::map:
-        return std::string("map");
+        return (std::string("map"));
     case Element::null:
-        return std::string("null");
+        return (std::string("null"));
     case Element::any:
-        return std::string("any");
+        return (std::string("any"));
     default:
-        return std::string("unknown");
+        return (std::string("unknown"));
     }
 }
 
 Element::types
 Element::nameToType(const std::string& type_name) {
     if (type_name == "integer") {
-        return Element::integer;
+        return (Element::integer);
     } else if (type_name == "real") {
-        return Element::real;
+        return (Element::real);
     } else if (type_name == "boolean") {
-        return Element::boolean;
+        return (Element::boolean);
     } else if (type_name == "string") {
-        return Element::string;
+        return (Element::string);
     } else if (type_name == "list") {
-        return Element::list;
+        return (Element::list);
     } else if (type_name == "map") {
-        return Element::map;
+        return (Element::map);
     } else if (type_name == "null") {
-        return Element::null;
+        return (Element::null);
     } else if (type_name == "any") {
-        return Element::any;
+        return (Element::any);
     } else {
         isc_throw(TypeError, type_name + " is not a valid type name");
     }
@@ -529,14 +534,14 @@
 ElementPtr
 Element::fromJSON(std::istream& in) throw(JSONError) {
     int line = 1, pos = 1;
-    return fromJSON(in, "<istream>", line, pos);
+    return (fromJSON(in, "<istream>", line, pos));
 }
 
 ElementPtr
 Element::fromJSON(std::istream& in, const std::string& file_name) throw(JSONError)
 {
     int line = 1, pos = 1;
-    return fromJSON(in, file_name, line, pos);
+    return (fromJSON(in, file_name, line, pos));
 }
 
 ElementPtr
@@ -602,7 +607,7 @@
         }
     }
     if (el_read) {
-        return element;
+        return (element);
     } else {
         isc_throw(JSONError, "nothing read");
     }
@@ -612,26 +617,23 @@
 Element::fromJSON(const std::string &in) {
     std::stringstream ss;
     ss << in;
-    return fromJSON(ss, "<string>");
+    return (fromJSON(ss, "<string>"));
 }
 
 // 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 {
@@ -640,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 << ", ";
@@ -670,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 << ", ";
@@ -694,22 +692,22 @@
 // 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));
+        return (get(id));
+    } else {
+        ConstElementPtr ce = get(id.substr(0, sep));
         if (ce) {
             // ignore trailing slash
             if  (sep + 1 != id.size()) {
-                return ce->find(id.substr(sep + 1));
+                return (ce->find(id.substr(sep + 1)));
             } else {
-                return ce;
+                return (ce);
             }
         } else {
-            return ElementPtr();
+            return (ElementPtr());
         }
     }
 }
@@ -719,7 +717,7 @@
     std::stringstream ss;
     ss << s;
     int line = 0, pos = 0;
-    return fromJSON(ss, "<wire>", line, pos);
+    return (fromJSON(ss, "<wire>", line, pos));
 }
 
 ElementPtr
@@ -735,87 +733,88 @@
     //}
     //length -= 4;
     int line = 0, pos = 0;
-    return fromJSON(in, "<wire>", line, pos);
-}
-
-void
-MapElement::set(const std::string& key, ElementPtr value) {
+    return (fromJSON(in, "<wire>", line, pos));
+}
+
+void
+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;
+            return (true);
         }
     } catch (const TypeError& e) {
         // ignore
     }
-    return false;
-}
-
-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) {
+    return (false);
+}
+
+bool
+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()) {
-            return false;
+        if (s != other.size()) {
+            return (false);
         }
         for (int i = 0; i < s; ++i) {
-            if (!get(i)->equals(other->get(i))) {
-                return false;
+            if (!get(i)->equals(*other.get(i))) {
+                return (false);
             }
         }
-        return true;
-    } else {
-        return false;
-    }
-}
-
-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();
+        return (true);
+    } else {
+        return (false);
+    }
+}
+
+bool
+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))) {
-                    return false;
+            if (other.contains((*it).first)) {
+                if (!get((*it).first)->equals(*other.get((*it).first))) {
+                    return (false);
                 }
             } else {
-                return false;
+                return (false);
             }
         }
         // quickly walk through the other map too, to see if there's
@@ -823,26 +822,27 @@
         // 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;
+                return (false);
             }
         }
-        return true;
-    } else {
-        return false;
-    }
-}
-
-bool
-isNull(ElementPtr p) {
-    return !p;
-}
-
-void
-removeIdentical(ElementPtr a, const ElementPtr b) {
+        return (true);
+    } else {
+        return (false);
+    }
+}
+
+bool
+isNull(ConstElementPtr p) {
+    return (!p);
+}
+
+void
+removeIdentical(ElementPtr a, ConstElementPtr b) {
     if (!b) {
         return;
     }
@@ -850,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/trac232/src/lib/cc/data.h
==============================================================================
--- branches/trac232/src/lib/cc/data.h (original)
+++ branches/trac232/src/lib/cc/data.h Wed Sep  1 00:35:07 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;
     //@}
 
 
@@ -265,13 +276,13 @@
     //@{
     static ElementPtr create();
     static ElementPtr create(const long int i);
-    static ElementPtr create(const int i) { return create(static_cast<long int>(i)); };
+    static ElementPtr create(const int i) { return (create(static_cast<long int>(i))); };
     static ElementPtr create(const double d);
     static ElementPtr create(const bool b);
     static ElementPtr create(const std::string& s);
     // need both std:string and char *, since c++ will match
     // bool before std::string when you pass it a char *
-    static ElementPtr create(const char *s) { return create(std::string(s)); };
+    static ElementPtr create(const char *s) { return (create(std::string(s))); }
 
     /// \brief Creates an empty ListElement type ElementPtr.
     static ElementPtr createList();
@@ -364,14 +375,14 @@
     long int i;
 
 public:
-    IntElement(long int v) : Element(integer), i(v) { };
-    long int intValue() { return i; }
+    IntElement(long int v) : Element(integer), i(v) { }
+    long int intValue() const { return (i); }
     using Element::getValue;
-    bool getValue(long int& t) { t = i; return true; };
+    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);
+    bool setValue(const long int v) { i = v; return (true); }
+    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; };
+    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);
+    bool setValue(const double v) { d = v; return (true); }
+    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; };
+    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);
+    bool setValue(const bool v) { b = v; return (true); }
+    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; };
+    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);
+    bool setValue(const std::string& v) { s = v; return (true); }
+    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/trac232/src/lib/cc/session.cc
==============================================================================
--- branches/trac232/src/lib/cc/session.cc (original)
+++ branches/trac232/src/lib/cc/session.cc Wed Sep  1 00:35:07 2010
@@ -15,7 +15,7 @@
 // $Id$
 
 #include <config.h>
-#include "session_config.h"
+#include <cc/session_config.h>
 
 #include <stdint.h>
 
@@ -28,6 +28,7 @@
 #include <unistd.h>             // for some IPC/network system calls
 #include <asio.hpp>
 #include <asio/error_code.hpp>
+#include <asio/deadline_timer.hpp>
 #include <asio/system_error.hpp>
 
 #include <cstdio>
@@ -38,12 +39,14 @@
 #include <sys/un.h>
 
 #include <boost/bind.hpp>
+#include <boost/optional.hpp>
 #include <boost/function.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
 
 #include <exceptions/exceptions.h>
 
-#include "data.h"
-#include "session.h"
+#include <cc/data.h>
+#include <cc/session.h>
 
 using namespace std;
 using namespace isc::cc;
@@ -52,44 +55,45 @@
 // some of the asio names conflict with socket API system calls
 // (e.g. write(2)) so we don't import the entire asio namespace.
 using asio::io_service;
-using asio::ip::tcp;
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
+
+namespace {
+/// \brief Sets the given Optional 'result' to the given error code
+/// Used as a callback for emulating sync reads with async calls
+/// \param result Pointer to the optional to set
+/// \param err The error code to set it to
+void
+setResult(boost::optional<asio::error_code>* result,
+          const asio::error_code& err)
+{
+    result->reset(err);
+}
+}
 
 namespace isc {
 namespace cc {
 
 class SessionImpl {
 public:
-    SessionImpl() : sequence_(-1) { queue_ = Element::createList(); }
-    virtual ~SessionImpl() {}
-    virtual void establish(const char& socket_file) = 0;
-    virtual int getSocket() = 0;
-    virtual void disconnect() = 0;
-    virtual void writeData(const void* data, size_t datalen) = 0;
-    virtual size_t readDataLength() = 0;
-    virtual void readData(void* data, size_t datalen) = 0;
-    virtual void startRead(boost::function<void()> user_handler) = 0;
-    
+    SessionImpl(io_service& io_service) :
+        sequence_(-1), queue_(Element::createList()),
+        io_service_(io_service), socket_(io_service_), data_length_(0),
+        timeout_(MSGQ_DEFAULT_TIMEOUT)
+    {}
+    void establish(const char& socket_file);
+    void disconnect();
+    void writeData(const void* data, size_t datalen);
+    size_t readDataLength();
+    // Blocking read. Will throw a SessionTimeout if the timeout value
+    // (in seconds) is thrown. If timeout is 0 it will block forever
+    void readData(void* data, size_t datalen);
+    void startRead(boost::function<void()> user_handler);
+    void setTimeout(size_t seconds) { timeout_ = seconds; };
+    size_t getTimeout() const { return timeout_; };
+
     long int sequence_; // the next sequence number to use
     std::string lname_;
     ElementPtr queue_;
-};
-
-class ASIOSession : public SessionImpl {
-public:
-    ASIOSession(io_service& io_service) :
-        io_service_(io_service), socket_(io_service_), data_length_(0)
-    {}
-    virtual void establish(const char& socket_file);
-    virtual void disconnect();
-    virtual int getSocket() { return (socket_.native()); }
-    virtual void writeData(const void* data, size_t datalen);
-    virtual size_t readDataLength();
-    virtual void readData(void* data, size_t datalen);
-    virtual void startRead(boost::function<void()> user_handler);
+
 private:
     void internalRead(const asio::error_code& error,
                       size_t bytes_transferred);
@@ -100,30 +104,41 @@
     uint32_t data_length_;
     boost::function<void()> user_handler_;
     asio::error_code error_;
+    size_t timeout_;
+
+    // By default, unless changed or disabled, blocking reads on
+    // the msgq channel will time out after 4 seconds in this
+    // implementation.
+    // This number is chosen to be low enough so that whatever
+    // component is blocking does not seem to be hanging, but
+    // still gives enough time for other modules to respond if they
+    // are busy. If this choice turns out to be a bad one, we can
+    // change it later.
+    static const size_t MSGQ_DEFAULT_TIMEOUT = 4000;
 };
 
-
-
-void
-ASIOSession::establish(const char& socket_file) {
+void
+SessionImpl::establish(const char& socket_file) {
     try {
-        socket_.connect(asio::local::stream_protocol::endpoint(&socket_file), error_);
-    } catch (asio::system_error& se) {
+        socket_.connect(asio::local::stream_protocol::endpoint(&socket_file),
+                        error_);
+    } catch(const asio::system_error& se) {
         isc_throw(SessionError, se.what());
     }
     if (error_) {
-        isc_throw(SessionError, "Unable to connect to message queue.");
-    }
-}
-
-void
-ASIOSession::disconnect() {
+        isc_throw(SessionError, "Unable to connect to message queue: " <<
+                  error_.message());
+    }
+}
+
+void
+SessionImpl::disconnect() {
     socket_.close();
     data_length_ = 0;
 }
 
 void
-ASIOSession::writeData(const void* data, size_t datalen) {
+SessionImpl::writeData(const void* data, size_t datalen) {
     try {
         asio::write(socket_, asio::buffer(data, datalen));
     } catch (const asio::system_error& asio_ex) {
@@ -132,7 +147,7 @@
 }
 
 size_t
-ASIOSession::readDataLength() {
+SessionImpl::readDataLength() {
     size_t ret_len = data_length_;
     
     if (ret_len == 0) {
@@ -148,29 +163,72 @@
 }
 
 void
-ASIOSession::readData(void* data, size_t datalen) {
+SessionImpl::readData(void* data, size_t datalen) {
+    boost::optional<asio::error_code> read_result;
+    boost::optional<asio::error_code> timer_result;
+
     try {
-        asio::read(socket_, asio::buffer(data, datalen));
+        asio::async_read(socket_, asio::buffer(data, datalen),
+                         boost::bind(&setResult, &read_result, _1));
+        asio::deadline_timer timer(socket_.io_service());
+    
+        if (getTimeout() != 0) {
+            timer.expires_from_now(boost::posix_time::milliseconds(getTimeout()));
+            timer.async_wait(boost::bind(&setResult, &timer_result, _1));
+        }
+
+        // wait until either we have read the data we want, the
+        // timer expires, or one of the two is triggered with an error.
+        // When one of them has a result, cancel the other, and wait
+        // until the cancel is processed before we continue
+        while (!read_result && !timer_result) {
+            socket_.io_service().run_one();
+
+            // Don't cancel the timer if we haven't set it
+            if (read_result && getTimeout() != 0) {
+                timer.cancel();
+                while (!timer_result) {
+                    socket_.io_service().run_one();
+                }
+            } else if (timer_result) {
+                socket_.cancel();
+                while (!read_result) {
+                    socket_.io_service().run_one();
+                }
+            }
+        }
+
+        // asio::error_code evaluates to false if there was no error
+        if (*read_result) {
+            if (*read_result == asio::error::operation_aborted) {
+                isc_throw(SessionTimeout,
+                          "Timeout while reading data from cc session");
+            } else {
+                isc_throw(SessionError,
+                          "Error while reading data from cc session: " <<
+                          read_result->message());
+            }
+        }
     } catch (const asio::system_error& asio_ex) {
-        // to hide boost specific exceptions, we catch them explicitly
+        // to hide ASIO specific exceptions, we catch them explicitly
         // and convert it to SessionError.
         isc_throw(SessionError, "ASIO read failed: " << asio_ex.what());
     }
 }
 
 void
-ASIOSession::startRead(boost::function<void()> user_handler) {
+SessionImpl::startRead(boost::function<void()> user_handler) {
     data_length_ = 0;
     user_handler_ = user_handler;
-    async_read(socket_, asio::buffer(&data_length_,
-                                            sizeof(data_length_)),
-               boost::bind(&ASIOSession::internalRead, this,
-                           asio::placeholders::error,
-                           asio::placeholders::bytes_transferred));
-}
-
-void
-ASIOSession::internalRead(const asio::error_code& error,
+    asio::async_read(socket_, asio::buffer(&data_length_,
+                                           sizeof(data_length_)),
+                     boost::bind(&SessionImpl::internalRead, this,
+                                 asio::placeholders::error,
+                                 asio::placeholders::bytes_transferred));
+}
+
+void
+SessionImpl::internalRead(const asio::error_code& error,
                           size_t bytes_transferred)
 {
     if (!error) {
@@ -185,27 +243,22 @@
     }
 }
 
-class SocketSession : public SessionImpl {
-public:
-    SocketSession() : sock_(-1) {}
-    virtual ~SocketSession() { disconnect(); }
-    virtual int getSocket() { return (sock_); }
-    void establish(const char& socket_file);
-    virtual void disconnect()
-    {
-        if (sock_ >= 0) {
-            close(sock_);
-        }
-        sock_ = -1;
-    }
-    virtual void writeData(const void* data, size_t datalen);
-    virtual void readData(void* data, size_t datalen);
-    virtual size_t readDataLength();
-    virtual void startRead(boost::function<void()> user_handler UNUSED_PARAM)
-    {} // nothing to do for this class
-private:
-    int sock_;
-};
+Session::Session(io_service& io_service) : impl_(new SessionImpl(io_service))
+{}
+
+Session::~Session() {
+    delete impl_;
+}
+
+void
+Session::disconnect() {
+    impl_->disconnect();
+}
+
+void
+Session::startRead(boost::function<void()> read_callback) {
+    impl_->startRead(read_callback);
+}
 
 namespace {                     // maybe unnecessary.
 // This is a helper class to make the establish() method (below) exception-safe
@@ -225,83 +278,6 @@
 }
 
 void
-SocketSession::establish(const char& socket_file) {
-    struct sockaddr_un s_un;
-#ifdef HAVE_SA_LEN
-    s_un.sun_len = sizeof(struct sockaddr_un);
-#endif
-
-    if (strlen(&socket_file) >= sizeof(s_un.sun_path)) {
-        isc_throw(SessionError, "Unable to connect to message queue; "
-                  "socket file path too long: " << socket_file);
-    }
-    s_un.sun_family = AF_UNIX;
-    strncpy(s_un.sun_path, &socket_file, sizeof(s_un.sun_path) - 1);
-
-    int s = socket(AF_UNIX, SOCK_STREAM, 0);
-    if (s < 0) {
-        isc_throw(SessionError, "socket() failed");
-    }
-
-    if (connect(s, (struct sockaddr *)&s_un, sizeof(s_un)) < 0) {
-        close(s);
-        isc_throw(SessionError, "Unable to connect to message queue");
-    }
-
-    sock_ = s;
-}
-
-void
-SocketSession::writeData(const void* data, const size_t datalen) {
-    int cc = write(sock_, data, datalen);
-    if (cc != datalen) {
-        isc_throw(SessionError, "Write failed: expect " << datalen <<
-                  ", actual " << cc);
-    }
-}
-
-size_t
-SocketSession::readDataLength() {
-    uint32_t length;
-    readData(&length, sizeof(length));
-    return (ntohl(length));
-}
-
-void
-SocketSession::readData(void* data, const size_t datalen) {
-    int cc = read(sock_, data, datalen);
-    if (cc != datalen) {
-        isc_throw(SessionError, "Read failed: expect " << datalen <<
-                  ", actual " << cc);
-    }
-}
-
-Session::Session() : impl_(new SocketSession)
-{}
-
-Session::Session(io_service& io_service) : impl_(new ASIOSession(io_service))
-{}
-
-Session::~Session() {
-    delete impl_;
-}
-
-void
-Session::disconnect() {
-    impl_->disconnect();
-}
-
-int
-Session::getSocket() const {
-    return (impl_->getSocket());
-}
-
-void
-Session::startRead(boost::function<void()> read_callback) {
-    impl_->startRead(read_callback);
-}
-
-void
 Session::establish(const char* socket_file) {
     if (socket_file == NULL) {
         socket_file = getenv("BIND10_MSGQ_SOCKET_FILE");
@@ -320,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();
@@ -334,10 +310,11 @@
 }
 
 //
-// Convert to wire format and send this on the TCP stream with its length prefix
+// Convert to wire format and send this via the stream socket with its length
+// 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);
@@ -350,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();
@@ -365,18 +342,18 @@
 }
 
 bool
-Session::recvmsg(ElementPtr& msg, bool nonblock, int seq) {
-    ElementPtr l_env;
-    return recvmsg(l_env, msg, nonblock, seq);
+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 &&
@@ -389,7 +366,7 @@
                    env = q_el->get(0);
                    msg = q_el->get(1);
                    impl_->queue_->remove(i);
-                   return true;
+                   return (true);
             }
         }
     }
@@ -413,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")
         ) || (
@@ -427,13 +406,13 @@
        ) {
         env = l_env;
         msg = l_msg;
-        return true;
+        return (true);
     } else {
         ElementPtr q_el = Element::createList();
         q_el->add(l_env);
         q_el->add(l_msg);
         impl_->queue_->add(q_el);
-        return recvmsg(env, msg, nonblock, seq);
+        return (recvmsg(env, msg, nonblock, seq));
     }
     // XXXMLG handle non-block here, and return false for short reads
 }
@@ -461,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();
@@ -476,18 +455,18 @@
     //env->set("msg", Element::create(msg->toWire()));
 
     sendmsg(env, msg);
-    return nseq;
+    return (nseq);
 }
 
 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_;
     
@@ -501,14 +480,22 @@
 
     sendmsg(env, newmsg);
 
-    return nseq;
+    return (nseq);
 }
 
 bool
-Session::hasQueuedMsgs()
-{
+Session::hasQueuedMsgs() const {
     return (impl_->queue_->size() > 0);
 }
 
-}
-}
+void
+Session::setTimeout(size_t milliseconds) {
+    impl_->setTimeout(milliseconds);
+}
+
+size_t
+Session::getTimeout() const {
+    return (impl_->getTimeout());
+}
+}
+}

Modified: branches/trac232/src/lib/cc/session.h
==============================================================================
--- branches/trac232/src/lib/cc/session.h (original)
+++ branches/trac232/src/lib/cc/session.h Wed Sep  1 00:35:07 2010
@@ -23,8 +23,8 @@
 
 #include <exceptions/exceptions.h>
 
-#include "data.h"
-#include "session_config.h"
+#include <cc/data.h>
+#include <cc/session_config.h>
 
 namespace asio {
 class io_service;
@@ -40,7 +40,77 @@
                 isc::Exception(file, line, what) {}
         };
 
-        class Session {
+        /// \brief A standard Exception class that is thrown when a
+        /// blocking readData call does not read the given number of
+        /// bytes before the timeout expires
+        class SessionTimeout : public isc::Exception {
+        public:
+            SessionTimeout(const char* file, size_t line, const char* what) :
+                isc::Exception(file, line, what) {}
+        };
+
+        /// \brief The AbstractSession class is an abstract base class that
+        /// defines the interfaces of Session.
+        /// The intended primary usage of abstraction is to allow tests for the
+        /// user class of Session without requiring actual communication
+        /// channels.
+        /// For simplicity we only define the methods that are necessary for
+        /// existing test cases that use this base class.  Eventually we'll
+        /// probably have to extend them.
+        class AbstractSession {
+            ///
+            /// \name Constructors, Assignment Operator and Destructor.
+            ///
+            /// Note: The copy constructor and the assignment operator are
+            /// intentionally defined as private to make it explicit that
+            /// this is a pure base class.
+            //@{
+        private:
+            AbstractSession(const AbstractSession& source);
+            AbstractSession& operator=(const AbstractSession& source);
+        protected:
+            /// \brief The default constructor.
+            ///
+            /// This is intentionally defined as \c protected as this base
+            /// class should never be instantiated (except as part of a
+            /// derived class).
+            AbstractSession() {}
+        public:
+            /// \brief The destructor.
+            virtual ~AbstractSession() {}
+            //@}
+            virtual void establish(const char* socket_file) = 0;
+            virtual void disconnect() = 0;
+            virtual int group_sendmsg(isc::data::ConstElementPtr msg,
+                                      std::string group,
+                                      std::string instance = "*",
+                                      std::string to = "*") = 0;
+            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,
+                                   std::string instance = "*") = 0;
+            virtual void unsubscribe(std::string group,
+                             std::string instance = "*") = 0;
+            virtual void startRead(boost::function<void()> read_callback) = 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
+            /// \param milliseconds the timeout for blocking reads in
+            ///        milliseconds, if this is set to 0, reads will block
+            ///        forever.
+            virtual void setTimeout(size_t milliseconds) = 0;
+
+            /// \brief Returns the current timeout for blocking reads
+            /// \return The timeout (in milliseconds)
+            virtual size_t getTimeout() const = 0;
+        };
+
+    class Session : public AbstractSession {
         private:
             SessionImpl* impl_;
 
@@ -49,42 +119,41 @@
             Session& operator=(const Session& source);
 
         public:
-            Session();
             Session(asio::io_service& ioservice);
-            ~Session();
+            virtual ~Session();
 
-            // XXX: quick hack to allow the user to watch the socket directly.
-            int getSocket() const;
+            virtual void startRead(boost::function<void()> read_callback);
 
-            void startRead(boost::function<void()> read_callback);
-
-            void establish(const char* socket_file = NULL);
-            void disconnect();
-            void sendmsg(isc::data::ElementPtr& msg);
-            void sendmsg(isc::data::ElementPtr& env,
-                         isc::data::ElementPtr& msg);
-            bool recvmsg(isc::data::ElementPtr& msg,
+            virtual void establish(const char* socket_file = NULL);
+            virtual void disconnect();
+            virtual void subscribe(std::string group,
+                                   std::string instance = "*");
+            virtual void unsubscribe(std::string group,
+                             std::string instance = "*");
+            virtual int group_sendmsg(isc::data::ConstElementPtr msg,
+                                      std::string group,
+                                      std::string instance = "*",
+                                      std::string to = "*");
+            virtual bool group_recvmsg(isc::data::ConstElementPtr& envelope,
+                                       isc::data::ConstElementPtr& msg,
+                                       bool nonblock = true,
+                                       int seq = -1);
+            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::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);
-            void subscribe(std::string group,
-                           std::string instance = "*");
-            void unsubscribe(std::string group,
-                             std::string instance = "*");
-            int group_sendmsg(isc::data::ElementPtr msg,
-                                       std::string group,
-                                       std::string instance = "*",
-                                       std::string to = "*");
-            bool group_recvmsg(isc::data::ElementPtr& envelope,
-                               isc::data::ElementPtr& msg,
-                               bool nonblock = true,
-                               int seq = -1);
-            int reply(isc::data::ElementPtr& envelope,
-                               isc::data::ElementPtr& newmsg);
-            bool hasQueuedMsgs();
         };
     } // namespace cc
 } // namespace isc

Modified: branches/trac232/src/lib/config/Makefile.am
==============================================================================
--- branches/trac232/src/lib/config/Makefile.am (original)
+++ branches/trac232/src/lib/config/Makefile.am Wed Sep  1 00:35:07 2010
@@ -1,3 +1,5 @@
+SUBDIRS = . testdata tests
+
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += -I$(top_builddir)/src/lib/cc
 AM_CXXFLAGS = $(B10_CXXFLAGS) -Wno-strict-aliasing
@@ -7,15 +9,11 @@
 
 CLEANFILES = *.gcno *.gcda
 
-TESTS =
-if HAVE_GTEST
-SUBDIRS = . tests
-endif
-
 EXTRA_DIST =  testdata/b10-config-bad1.db
 EXTRA_DIST += testdata/b10-config-bad2.db
 EXTRA_DIST += testdata/b10-config-bad3.db
-EXTRA_DIST += testdata/b10-config.db
+EXTRA_DIST += testdata/b10-config-bad4.db
+EXTRA_DIST += testdata/b10-config.db.master #.db will be auto-generated
 EXTRA_DIST += testdata/data22_1.data
 EXTRA_DIST += testdata/data22_2.data
 EXTRA_DIST += testdata/data22_3.data
@@ -51,3 +49,4 @@
 EXTRA_DIST += testdata/spec25.spec
 EXTRA_DIST += testdata/spec26.spec
 EXTRA_DIST += testdata/spec27.spec
+EXTRA_DIST += testdata/spec28.spec

Modified: branches/trac232/src/lib/config/ccsession.cc
==============================================================================
--- branches/trac232/src/lib/config/ccsession.cc (original)
+++ branches/trac232/src/lib/config/ccsession.cc Wed Sep  1 00:35:07 2010
@@ -20,7 +20,7 @@
 //               react on config change announcements)
 //
 
-#include "config.h"
+#include <config.h>
 
 #include <stdexcept>
 #include <stdlib.h>
@@ -40,8 +40,7 @@
 #include <cc/session.h>
 #include <exceptions/exceptions.h>
 
-#include "ccsession.h"
-#include "config.h"
+#include <config/ccsession.h>
 
 using namespace std;
 
@@ -53,45 +52,47 @@
 namespace config {
 
 /// Creates a standard config/command protocol answer message
-ElementPtr
-createAnswer()
-{
+ConstElementPtr
+createAnswer() {
     ElementPtr answer = Element::fromJSON("{\"result\": [] }");
-    ElementPtr answer_content = answer->get("result");
+    ElementPtr answer_content = Element::createList();
     answer_content->add(Element::create(0));
-    return answer;
-}
-
-ElementPtr
-createAnswer(const int rcode, const ElementPtr arg)
-{
+    answer->set("result", answer_content);
+
+    return (answer);
+}
+
+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);
-    return answer;
-}
-
-ElementPtr
-createAnswer(const int rcode, const std::string& arg)
-{
+    answer->set("result", answer_content);
+
+    return (answer);
+}
+
+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));
-    return answer;
-}
-
-ElementPtr
-parseAnswer(int &rcode, const ElementPtr msg)
-{
+    answer->set("result", answer_content);
+
+    return (answer);
+}
+
+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) {
@@ -100,13 +101,13 @@
         rcode = result->get(0)->intValue();
         if (result->size() > 1) {
             if (rcode == 0 || result->get(1)->getType() == Element::string) {
-                return result->get(1);
+                return (result->get(1));
             } else {
                 isc_throw(CCSessionError, "Error description in result with rcode != 0 is not a string");
             }
         } else {
             if (rcode == 0) {
-                return ElementPtr();
+                return (ElementPtr());
             } else {
                 isc_throw(CCSessionError, "Result with rcode != 0 does not have an error description");
             }
@@ -116,15 +117,13 @@
     }
 }
 
-ElementPtr
-createCommand(const std::string& command)
-{
-    return createCommand(command, ElementPtr());
-}
-
-ElementPtr
-createCommand(const std::string& command, ElementPtr arg)
-{
+ConstElementPtr
+createCommand(const std::string& command) {
+    return (createCommand(command, ElementPtr()));
+}
+
+ConstElementPtr
+createCommand(const std::string& command, ConstElementPtr arg) {
     ElementPtr cmd = Element::createMap();
     ElementPtr cmd_parts = Element::createList();
     cmd_parts->add(Element::create(command));
@@ -132,18 +131,17 @@
         cmd_parts->add(arg);
     }
     cmd->set("command", cmd_parts);
-    return cmd;
+    return (cmd);
 }
 
 /// 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) {
@@ -152,7 +150,7 @@
             } else {
                 arg = ElementPtr();
             }
-            return cmd->get(0)->stringValue();
+            return (cmd->get(0)->stringValue());
         } else {
             isc_throw(CCSessionError, "Command part in command message missing, empty, or not a list");
         }
@@ -183,7 +181,7 @@
         exit(1);
     }
     file.close();
-    return module_spec;
+    return (module_spec);
 }
 
 void
@@ -197,37 +195,14 @@
 }
 
 ModuleCCSession::ModuleCCSession(
-    std::string spec_file_name,
-    asio::io_service& io_service,
-    isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config),
-    isc::data::ElementPtr(*command_handler)(
-        const std::string& command, const isc::data::ElementPtr args)
-    ) throw (isc::cc::SessionError) :
-    session_(io_service)
-{
-    init(spec_file_name, config_handler, command_handler);
-
-    // register callback for asynchronous read
-    session_.startRead(boost::bind(&ModuleCCSession::startCheck, this));
-}
-
-ModuleCCSession::ModuleCCSession(
-    std::string spec_file_name,
-    isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config),
-    isc::data::ElementPtr(*command_handler)(
-        const std::string& command, const isc::data::ElementPtr args)
-    ) throw (isc::cc::SessionError)
-{
-    init(spec_file_name, config_handler, command_handler);
-}
-
-void
-ModuleCCSession::init(
-    std::string spec_file_name,
-    isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config),
-    isc::data::ElementPtr(*command_handler)(
-        const std::string& command, const isc::data::ElementPtr args)
-    ) throw (isc::cc::SessionError)
+    const std::string& spec_file_name,
+    isc::cc::AbstractSession& session,
+    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)
 {
     module_specification_ = readModuleSpecification(spec_file_name);
     setModuleSpec(module_specification_);
@@ -236,18 +211,20 @@
     config_handler_ = config_handler;
     command_handler_ = command_handler;
 
-    ElementPtr answer, env;
-
-    session_.establish();
+    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;
     }
@@ -255,76 +232,71 @@
     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 {
             std::cerr << "[" << module_name_ << "] Error getting config: " << new_config << std::endl;
         }
     }
+
+    // register callback for asynchronous read
+    session_.startRead(boost::bind(&ModuleCCSession::startCheck, this));
 }
 
 /// 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);
         }
     }
-    return answer;
+    return (answer);
+}
+
+bool
+ModuleCCSession::hasQueuedMsgs() const {
+    return (session_.hasQueuedMsgs());
 }
 
 int
-ModuleCCSession::getSocket()
-{
-    return (session_.getSocket());
-}
-
-bool
-ModuleCCSession::hasQueuedMsgs()
-{
-    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
          * pingpongs */
         if (data->getType() != Element::map || data->contains("result")) {
-            return 0;
-        }
-        ElementPtr arg;
-        ElementPtr answer;
+            return (0);
+        }
+        ConstElementPtr arg;
+        ConstElementPtr answer;
         try {
             std::string cmd_str = parseCommand(arg, data);
             std::string target_module = routing->get("group")->stringValue();
@@ -336,7 +308,7 @@
                     // in our remote config list, update that
                     updateRemoteConfig(target_module, arg);
                     // we're not supposed to answer to this, so return
-                    return 0;
+                    return (0);
                 }
             } else {
                 if (target_module == module_name_) {
@@ -347,7 +319,9 @@
                     }
                 }
             }
-        } catch (CCSessionError re) {
+        } catch (const CCSessionError& re) {
+            // TODO: Once we have logging and timeouts, we should not
+            // answer here (potential interference)
             // TODO: Once we have logging and timeouts, we should not
             // answer here (potential interference)
             answer = createAnswer(1, re.what());
@@ -357,7 +331,7 @@
         }
     }
     
-    return 0;
+    return (0);
 }
 
 std::string
@@ -369,22 +343,24 @@
     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());
     }
 
     // all ok, add it
     remote_module_configs_[module_name] = rmod_config;
-    return module_name;
+    return (module_name);
 }
 
 void
@@ -399,21 +375,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/trac232/src/lib/config/ccsession.h
==============================================================================
--- branches/trac232/src/lib/config/ccsession.h (original)
+++ branches/trac232/src/lib/config/ccsession.h Wed Sep  1 00:35:07 2010
@@ -24,10 +24,6 @@
 #include <cc/session.h>
 #include <cc/data.h>
 
-namespace asio {
-class io_service;
-}
-
 namespace isc {
 namespace config {
 
@@ -35,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
@@ -47,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
@@ -56,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
@@ -67,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
@@ -76,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
@@ -86,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
@@ -97,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);
 
 
 ///
@@ -112,7 +107,7 @@
 };
 
 ///
-/// \brief This modules keeps a connection to the command channel,
+/// \brief This module keeps a connection to the command channel,
 /// holds configuration information, and handles messages from
 /// the command channel
 ///
@@ -120,32 +115,29 @@
 public:
     /**
      * Initialize a config/command session
-     * @param module_name: The name of this module. This is not a
-     *                     reference because we expect static strings
-     *                     to be passed here.
-     * @param spec_file_name: The name of the file containing the
+     *
+     * @param spec_file_name The name of the file containing the
      *                        module specification.
-     */
-    ModuleCCSession(std::string spec_file_name,
-                    isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config) = NULL,
-                    isc::data::ElementPtr(*command_handler)(const std::string& command, const isc::data::ElementPtr args) = NULL
-                    ) throw (isc::cc::SessionError);
-    ModuleCCSession(std::string spec_file_name,
-                    asio::io_service& io_service,
-                    isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config) = NULL,
-                    isc::data::ElementPtr(*command_handler)(const std::string& command, const isc::data::ElementPtr args) = NULL
-                    ) throw (isc::cc::SessionError);
-
-    /**
-     * Returns the socket that is used to communicate with the msgq
-     * command channel. This socket should *only* be used to run a
-     * select() loop over it. And if not time-critical, it is strongly
-     * recommended to only use checkCommand() to check for messages
-     *
-     * @return The socket used to communicate with the msgq command
-     *         channel.
-     */
-    int getSocket();
+     * @param session A Session object over which configuration and command
+     * data are exchanged.
+     * @param config_handler A callback function pointer to be called when
+     * configuration of the local module needs to be updated.
+     * This must refer to a valid object of a concrete derived class of
+     * AbstractSession without establishing the session.
+     * Note: the design decision on who is responsible for establishing the
+     * session is in flux, and may change in near future.
+     * @param command_handler A callback function pointer to be called when
+     * a control command from a remote agent needs to be performed on the
+     * local module.
+     */
+    ModuleCCSession(const std::string& spec_file_name,
+                    isc::cc::AbstractSession& session,
+                    isc::data::ConstElementPtr(*config_handler)(
+                        isc::data::ConstElementPtr new_config) = NULL,
+                    isc::data::ConstElementPtr(*command_handler)(
+                        const std::string& command,
+                        isc::data::ConstElementPtr args) = NULL
+                    );
 
     /**
      * Optional optimization for checkCommand loop; returns true
@@ -155,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
@@ -174,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
@@ -186,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
@@ -224,29 +225,27 @@
      * \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:
-    void init(
-        std::string spec_file_name,
-        isc::data::ElementPtr(*config_handler)(
-            isc::data::ElementPtr new_config),
-        isc::data::ElementPtr(*command_handler)(
-            const std::string& command, const isc::data::ElementPtr args)
-        ) throw (isc::cc::SessionError);
     ModuleSpec readModuleSpecification(const std::string& filename);
     void startCheck();
     
     std::string module_name_;
-    isc::cc::Session session_;
+    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/trac232/src/lib/config/config_data.cc
==============================================================================
--- branches/trac232/src/lib/config/config_data.cc (original)
+++ branches/trac232/src/lib/config/config_data.cc Wed Sep  1 00:35:07 2010
@@ -14,7 +14,7 @@
 
 // $Id$
 
-#include "config_data.h"
+#include <config/config_data.h>
 
 #include <boost/foreach.hpp>
 
@@ -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) {
@@ -104,7 +104,7 @@
         }
     }
     //std::cout << "[XX] found spec part: " << std::endl << spec_part << std::endl;
-    return spec_part;
+    return (spec_part);
 }
 
 //
@@ -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,28 +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);
+    return (getValue(fake, 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;
@@ -166,36 +168,34 @@
             value = ElementPtr();
         }
     }
-    return value;
+    return (value);
 }
 
 /// 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);
     }
     spec_name_list(result, spec_part, identifier, recurse);
-    return result;
+    return (result);
 }
 
 /// 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;
-}
-
-}
-}
+    return (result);
+}
+
+}
+}

Modified: branches/trac232/src/lib/config/config_data.h
==============================================================================
--- branches/trac232/src/lib/config/config_data.h (original)
+++ branches/trac232/src/lib/config/config_data.h Wed Sep  1 00:35:07 2010
@@ -40,7 +40,7 @@
     /// Constructs a ConfigData option with no specification and an
     /// empty configuration.
     ConfigData() { _config = Element::createMap(); };
-    
+
     /// Constructs a ConfigData option with the given specification
     /// and an empty configuration.
     /// \param module_spec A ModuleSpec for the relevant module
@@ -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,25 +67,26 @@
     ///                   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; };
-    
+
     /// Set the local configuration (i.e. all non-default values)
     /// \param config An ElementPtr pointing to a MapElement containing
     ///        *all* non-default configuration values. Existing values
     ///        will be removed.
     void setLocalConfig(ElementPtr config) { _config = config; }
-    
+
     /// Returns the local (i.e. non-default) configuration.
     /// \returns An ElementPtr pointing to a MapElement containing all
     ///          non-default configuration options.
-    ElementPtr getLocalConfig() { return _config; }
-    
+    ElementPtr getLocalConfig() { return (_config); }
+
     /// Returns a list of all possible configuration options as specified
     ///         by the ModuleSpec.
     /// \param identifier If given, show the items at the given identifier
@@ -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/trac232/src/lib/config/documentation.txt
==============================================================================
--- branches/trac232/src/lib/config/documentation.txt (original)
+++ branches/trac232/src/lib/config/documentation.txt Wed Sep  1 00:35:07 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/trac232/src/lib/config/module_spec.cc
==============================================================================
--- branches/trac232/src/lib/config/module_spec.cc (original)
+++ branches/trac232/src/lib/config/module_spec.cc Wed Sep  1 00:35:07 2010
@@ -13,7 +13,7 @@
 // NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 // WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-#include "module_spec.h"
+#include <config/module_spec.h>
 
 #include <sstream>
 #include <iostream>
@@ -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,54 +143,50 @@
     }
 }
 
-const ElementPtr
-ModuleSpec::getCommandsSpec() const
-{
+ConstElementPtr
+ModuleSpec::getCommandsSpec() const {
     if (module_specification->contains("commands")) {
-        return module_specification->get("commands");
-    } else {
-        return ElementPtr();
-    }
-}
-
-const ElementPtr
-ModuleSpec::getConfigSpec() const
-{
+        return (module_specification->get("commands"));
+    } else {
+        return (ElementPtr());
+    }
+}
+
+ConstElementPtr
+ModuleSpec::getConfigSpec() const {
     if (module_specification->contains("config_data")) {
-        return module_specification->get("config_data");
-    } else {
-        return ElementPtr();
+        return (module_specification->get("config_data"));
+    } else {
+        return (ElementPtr());
     }
 }
 
 const std::string
-ModuleSpec::getModuleName() const
-{
-    return module_specification->get("module_name")->stringValue();
+ModuleSpec::getModuleName() const {
+    return (module_specification->get("module_name")->stringValue());
 }
 
 const std::string
-ModuleSpec::getModuleDescription() const
-{
+ModuleSpec::getModuleDescription() const {
     if (module_specification->contains("module_description")) {
-        return module_specification->get("module_description")->stringValue();
-    } else {
-        return std::string("");
-    }
-}
-
-bool
-ModuleSpec::validate_config(const ElementPtr data, const bool full)
-{
-    ElementPtr 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");
-    return validate_spec_list(spec, data, full, errors);
+        return (module_specification->get("module_description")->stringValue());
+    } else {
+        return (std::string(""));
+    }
+}
+
+bool
+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(ConstElementPtr data, const bool full,
+                            ElementPtr errors) const
+{
+    ConstElementPtr spec = module_specification->find("config_data");
+    return (validate_spec_list(spec, data, full, errors));
 }
 
 ModuleSpec
@@ -203,9 +202,9 @@
         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);
+        return (ModuleSpec(module_spec_element->get("module_spec"), check));
     } else {
         throw ModuleSpecError("No module_spec in specification");
     }
@@ -213,16 +212,18 @@
 
 ModuleSpec
 moduleSpecFromFile(std::ifstream& in, const bool check)
-                   throw(JSONError, ModuleSpecError) {
-    ElementPtr module_spec_element = Element::fromJSON(in);
+                   throw(JSONError, ModuleSpecError)
+{
+    ConstElementPtr module_spec_element = Element::fromJSON(in);
     if (module_spec_element->contains("module_spec")) {
-        return ModuleSpec(module_spec_element->get("module_spec"), check);
+        return (ModuleSpec(module_spec_element->get("module_spec"), check));
     } else {
         throw ModuleSpecError("No module_spec in specification");
     }
 }
 
 
+namespace {
 //
 // private functions
 //
@@ -230,39 +231,41 @@
 //
 // 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") {
-        return true;
+        return (true);
     }
     switch (element->getType()) {
         case Element::integer:
-            return cur_item_type == "integer";
+            return (cur_item_type == "integer");
             break;
         case Element::real:
-            return cur_item_type == "real";
+            return (cur_item_type == "real");
             break;
         case Element::boolean:
-            return cur_item_type == "boolean";
+            return (cur_item_type == "boolean");
             break;
         case Element::string:
-            return cur_item_type == "string";
+            return (cur_item_type == "string");
             break;
         case Element::list:
-            return cur_item_type == "list";
+            return (cur_item_type == "list");
             break;
         case Element::map:
-            return cur_item_type == "map";
-            break;
-    }
-    return false;
-}
-
-bool
-ModuleSpec::validate_item(const ElementPtr spec, const ElementPtr data, const bool full, ElementPtr errors) {
+            return (cur_item_type == "map");
+            break;
+    }
+    return (false);
+}
+}
+
+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,67 +273,70 @@
         if (errors) {
             errors->add(Element::create("Type mismatch"));
         }
-        return false;
+        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"));
                 }
-                return false;
+                return (false);
             }
             if (list_spec->get("item_type")->stringValue() == "map") {
                 if (!validate_item(list_spec, list_el, full, errors)) {
-                    return false;
+                    return (false);
                 }
             }
         }
     }
     if (data->getType() == Element::map) {
         if (!validate_spec_list(spec->get("map_item_spec"), data, full, errors)) {
-            return false;
-        }
-    }
-    return true;
+            return (false);
+        }
+    }
+    return (true);
 }
 
 // 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) {
         if (!validate_item(spec, data_el, full, errors)) {
-            return false;
+            return (false);
         }
     } else {
         if (!optional && full) {
             if (errors) {
                 errors->add(Element::create("Non-optional value missing"));
             }
-            return false;
-        }
-    }
-    return true;
+            return (false);
+        }
+    }
+    return (true);
 }
 
 // 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;
-        }
-    }
-    return true;
-}
-
-}
-}
+            return (false);
+        }
+    }
+    return (true);
+}
+
+}
+}

Modified: branches/trac232/src/lib/config/module_spec.h
==============================================================================
--- branches/trac232/src/lib/config/module_spec.h (original)
+++ branches/trac232/src/lib/config/module_spec.h Wed Sep  1 00:35:07 2010
@@ -34,7 +34,7 @@
     public:
         ModuleSpecError(std::string m = "Module specification is invalid") : msg(m) {}
         ~ModuleSpecError() throw() {}
-        const char* what() const throw() { return msg.c_str(); }
+        const char* what() const throw() { return (msg.c_str()); }
     private:
         std::string msg;
     };
@@ -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/trac232/src/lib/config/testdata/b10-config-bad1.db
==============================================================================
--- branches/trac232/src/lib/config/testdata/b10-config-bad1.db (original)
+++ branches/trac232/src/lib/config/testdata/b10-config-bad1.db Wed Sep  1 00:35:07 2010
@@ -1,1 +1,1 @@
-{'version': 0}
+{"version": 0}

Modified: branches/trac232/src/lib/config/testdata/data22_1.data
==============================================================================
--- branches/trac232/src/lib/config/testdata/data22_1.data (original)
+++ branches/trac232/src/lib/config/testdata/data22_1.data Wed Sep  1 00:35:07 2010
@@ -1,9 +1,9 @@
 {
     "value1": 1,
     "value2": 2.3,
-    "value3": True,
+    "value3": true,
     "value4": "foo",
     "value5": [ 1, 2, 3 ],
-    "value6": { "v61": "bar", "v62": True },
+    "value6": { "v61": "bar", "v62": true },
     "value9": { "v91": "hi", "v92": { "v92a": "Hi", "v92b": 3 } }
 }

Modified: branches/trac232/src/lib/config/testdata/data22_2.data
==============================================================================
--- branches/trac232/src/lib/config/testdata/data22_2.data (original)
+++ branches/trac232/src/lib/config/testdata/data22_2.data Wed Sep  1 00:35:07 2010
@@ -1,8 +1,8 @@
 {
     "value1": "asdf",
     "value2": 2.3,
-    "value3": True,
+    "value3": true,
     "value4": "foo",
     "value5": [ 1, 2, 3 ],
-    "value6": { "v61": "bar", "v62": True }
+    "value6": { "v61": "bar", "v62": true }
 }

Modified: branches/trac232/src/lib/config/testdata/data22_3.data
==============================================================================
--- branches/trac232/src/lib/config/testdata/data22_3.data (original)
+++ branches/trac232/src/lib/config/testdata/data22_3.data Wed Sep  1 00:35:07 2010
@@ -1,8 +1,8 @@
 {
     "value1": 1,
-    "value2": False,
-    "value3": True,
+    "value2": false,
+    "value3": true,
     "value4": "foo",
     "value5": [ 1, 2, 3 ],
-    "value6": { "v61": "bar", "v62": True }
+    "value6": { "v61": "bar", "v62": true }
 }

Modified: branches/trac232/src/lib/config/testdata/data22_4.data
==============================================================================
--- branches/trac232/src/lib/config/testdata/data22_4.data (original)
+++ branches/trac232/src/lib/config/testdata/data22_4.data Wed Sep  1 00:35:07 2010
@@ -1,8 +1,8 @@
 {
     "value1": 1,
     "value2": 2.3,
-    "value3": True,
+    "value3": true,
     "value4": "foo",
     "value5": [ 1, 2, "a" ],
-    "value6": { "v61": "bar", "v62": True }
+    "value6": { "v61": "bar", "v62": true }
 }

Modified: branches/trac232/src/lib/config/testdata/data22_5.data
==============================================================================
--- branches/trac232/src/lib/config/testdata/data22_5.data (original)
+++ branches/trac232/src/lib/config/testdata/data22_5.data Wed Sep  1 00:35:07 2010
@@ -1,7 +1,7 @@
 {
     "value1": 1,
     "value2": 2.3,
-    "value3": True,
+    "value3": true,
     "value4": "foo",
     "value5": [ 1, 2, 3 ],
     "value6": { "v61": "bar", "v62": "Break" }

Modified: branches/trac232/src/lib/config/testdata/data22_6.data
==============================================================================
--- branches/trac232/src/lib/config/testdata/data22_6.data (original)
+++ branches/trac232/src/lib/config/testdata/data22_6.data Wed Sep  1 00:35:07 2010
@@ -1,10 +1,10 @@
 {
     "value1": 1,
     "value2": 2.3,
-    "value3": True,
+    "value3": true,
     "value4": "foo",
     "value5": [ 1, 2, 3 ],
-    "value6": { "v61": "bar", "v62": True },
-    "value7": [ 1, 2.2, "str", True ],
+    "value6": { "v61": "bar", "v62": true },
+    "value7": [ 1, 2.2, "str", true ],
     "value9": { "v91": "hi", "v92": { "v92a": "Hi", "v92b": 3 } }
 }

Modified: branches/trac232/src/lib/config/testdata/data22_7.data
==============================================================================
--- branches/trac232/src/lib/config/testdata/data22_7.data (original)
+++ branches/trac232/src/lib/config/testdata/data22_7.data Wed Sep  1 00:35:07 2010
@@ -1,10 +1,10 @@
 {
     "value1": 1,
     "value2": 2.3,
-    "value3": True,
+    "value3": true,
     "value4": "foo",
     "value5": [ 1, 2, 3 ],
-    "value6": { "v61": "bar", "v62": True },
+    "value6": { "v61": "bar", "v62": true },
     "value8": [ { "a": "d" }, { "a": "e" } ],
     "value9": { "v91": "hi", "v92": { "v92a": "Hi", "v92b": 3 } }
 }

Modified: branches/trac232/src/lib/config/testdata/data22_8.data
==============================================================================
--- branches/trac232/src/lib/config/testdata/data22_8.data (original)
+++ branches/trac232/src/lib/config/testdata/data22_8.data Wed Sep  1 00:35:07 2010
@@ -1,9 +1,9 @@
 {
     "value1": 1,
     "value2": 2.3,
-    "value3": True,
+    "value3": true,
     "value4": "foo",
     "value5": [ 1, 2, 3 ],
-    "value6": { "v61": "bar", "v62": True },
+    "value6": { "v61": "bar", "v62": true },
     "value8": [ { "a": "d" }, { "a": 1 } ]
 }

Modified: branches/trac232/src/lib/config/testdata/spec10.spec
==============================================================================
--- branches/trac232/src/lib/config/testdata/spec10.spec (original)
+++ branches/trac232/src/lib/config/testdata/spec10.spec Wed Sep  1 00:35:07 2010
@@ -4,7 +4,7 @@
     "config_data": [
       { "item_name": "item1",
         "item_type": "real",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 1
       }
     ]

Modified: branches/trac232/src/lib/config/testdata/spec11.spec
==============================================================================
--- branches/trac232/src/lib/config/testdata/spec11.spec (original)
+++ branches/trac232/src/lib/config/testdata/spec11.spec Wed Sep  1 00:35:07 2010
@@ -4,7 +4,7 @@
     "config_data": [
       { "item_name": "item1",
         "item_type": "boolean",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 1
       }
     ]

Modified: branches/trac232/src/lib/config/testdata/spec12.spec
==============================================================================
--- branches/trac232/src/lib/config/testdata/spec12.spec (original)
+++ branches/trac232/src/lib/config/testdata/spec12.spec Wed Sep  1 00:35:07 2010
@@ -4,7 +4,7 @@
     "config_data": [
       { "item_name": "item1",
         "item_type": "string",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 1
       }
     ]

Modified: branches/trac232/src/lib/config/testdata/spec13.spec
==============================================================================
--- branches/trac232/src/lib/config/testdata/spec13.spec (original)
+++ branches/trac232/src/lib/config/testdata/spec13.spec Wed Sep  1 00:35:07 2010
@@ -4,7 +4,7 @@
     "config_data": [
       { "item_name": "item1",
         "item_type": "list",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 1
       }
     ]

Modified: branches/trac232/src/lib/config/testdata/spec14.spec
==============================================================================
--- branches/trac232/src/lib/config/testdata/spec14.spec (original)
+++ branches/trac232/src/lib/config/testdata/spec14.spec Wed Sep  1 00:35:07 2010
@@ -4,7 +4,7 @@
     "config_data": [
       { "item_name": "item1",
         "item_type": "map",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 1
       }
     ]

Modified: branches/trac232/src/lib/config/testdata/spec15.spec
==============================================================================
--- branches/trac232/src/lib/config/testdata/spec15.spec (original)
+++ branches/trac232/src/lib/config/testdata/spec15.spec Wed Sep  1 00:35:07 2010
@@ -4,7 +4,7 @@
     "config_data": [
       { "item_name": "item1",
         "item_type": "badname",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 1
       }
     ]

Modified: branches/trac232/src/lib/config/testdata/spec17.spec
==============================================================================
--- branches/trac232/src/lib/config/testdata/spec17.spec (original)
+++ branches/trac232/src/lib/config/testdata/spec17.spec Wed Sep  1 00:35:07 2010
@@ -7,7 +7,7 @@
         "command_args": [ {
           "item_name": "message",
           "item_type": "string",
-          "item_optional": False,
+          "item_optional": false,
           "item_default": ""
         } ]
       }

Modified: branches/trac232/src/lib/config/testdata/spec2.spec
==============================================================================
--- branches/trac232/src/lib/config/testdata/spec2.spec (original)
+++ branches/trac232/src/lib/config/testdata/spec2.spec Wed Sep  1 00:35:07 2010
@@ -4,48 +4,48 @@
     "config_data": [
       { "item_name": "item1",
         "item_type": "integer",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 1
       },
       { "item_name": "item2",
         "item_type": "real",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 1.1
       },
       { "item_name": "item3",
         "item_type": "boolean",
-        "item_optional": False,
-        "item_default": True
+        "item_optional": false,
+        "item_default": true
       },
       { "item_name": "item4",
         "item_type": "string",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": "test"
       },
       { "item_name": "item5",
         "item_type": "list",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": [ "a", "b" ],
         "list_item_spec": {
           "item_name": "list_element",
           "item_type": "string",
-          "item_optional": False,
+          "item_optional": false,
           "item_default": ""
         }
       },
       { "item_name": "item6",
         "item_type": "map",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": {},
         "map_item_spec": [
           { "item_name": "value1",
             "item_type": "string",
-            "item_optional": True,
+            "item_optional": true,
             "item_default": "default"
           },
           { "item_name": "value2",
             "item_type": "integer",
-            "item_optional": True
+            "item_optional": true
           }
         ]
       }
@@ -57,7 +57,7 @@
         "command_args": [ {
           "item_name": "message",
           "item_type": "string",
-          "item_optional": False,
+          "item_optional": false,
           "item_default": ""
         } ]
       },

Modified: branches/trac232/src/lib/config/testdata/spec20.spec
==============================================================================
--- branches/trac232/src/lib/config/testdata/spec20.spec (original)
+++ branches/trac232/src/lib/config/testdata/spec20.spec Wed Sep  1 00:35:07 2010
@@ -8,7 +8,7 @@
         "command_args": [ {
           "item_name": "message",
           "item_type": "somethingbad",
-          "item_optional": False,
+          "item_optional": false,
           "item_default": ""
         } ]
       }

Modified: branches/trac232/src/lib/config/testdata/spec22.spec
==============================================================================
--- branches/trac232/src/lib/config/testdata/spec22.spec (original)
+++ branches/trac232/src/lib/config/testdata/spec22.spec Wed Sep  1 00:35:07 2010
@@ -4,75 +4,75 @@
     "config_data": [
       { "item_name": "value1",
         "item_type": "integer",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 9
       },
       { "item_name": "value2",
         "item_type": "real",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 9.9
       },
       { "item_name": "value3",
         "item_type": "boolean",
-        "item_optional": False,
-        "item_default": False
+        "item_optional": false,
+        "item_default": false
       },
       { "item_name": "value4",
         "item_type": "string",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": "default_string"
       },
       { "item_name": "value5",
         "item_type": "list",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": [ "a", "b" ],
         "list_item_spec": {
           "item_name": "list_element",
           "item_type": "integer",
-          "item_optional": False,
+          "item_optional": false,
           "item_default": 8
         }
       },
       { "item_name": "value6",
         "item_type": "map",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": {},
         "map_item_spec": [
           { "item_name": "v61",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": "def"
           },
           { "item_name": "v62",
             "item_type": "boolean",
-            "item_optional": False,
-            "item_default": False
+            "item_optional": false,
+            "item_default": false
           }
         ]
       },
       { "item_name": "value7",
         "item_type": "list",
-        "item_optional": True,
+        "item_optional": true,
         "item_default": [ ],
         "list_item_spec": {
           "item_name": "list_element",
           "item_type": "any",
-          "item_optional": True
+          "item_optional": true
         }
       },
       { "item_name": "value8",
         "item_type": "list",
-        "item_optional": True,
+        "item_optional": true,
         "item_default": [ ],
         "list_item_spec": {
           "item_name": "list_element",
           "item_type": "map",
-          "item_optional": True,
+          "item_optional": true,
           "item_default": { "a": "b" },
           "map_item_spec": [
             { "item_name": "a",
               "item_type": "string",
-              "item_optional": True,
+              "item_optional": true,
               "item_default": "empty"
             }
           ]
@@ -80,28 +80,28 @@
       },
       { "item_name": "value9",
         "item_type": "map",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": {},
         "map_item_spec": [
           { "item_name": "v91",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": "def"
           },
           { "item_name": "v92",
             "item_type": "map",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": {},
             "map_item_spec": [
               { "item_name": "v92a",
                 "item_type": "string",
-                "item_optional": False,
+                "item_optional": false,
                 "item_default": "Hello"
               } ,
               {
                 "item_name": "v92b",
                 "item_type": "integer",
-                "item_optional": False,
+                "item_optional": false,
                 "item_default": 47806
               }
             ]

Modified: branches/trac232/src/lib/config/testdata/spec23.spec
==============================================================================
--- branches/trac232/src/lib/config/testdata/spec23.spec (original)
+++ branches/trac232/src/lib/config/testdata/spec23.spec Wed Sep  1 00:35:07 2010
@@ -8,7 +8,7 @@
         "command_args": [ {
           "item_name": "message",
           "item_type": "string",
-          "item_optional": False,
+          "item_optional": false,
           "item_default": ""
         } ]
       }

Modified: branches/trac232/src/lib/config/testdata/spec24.spec
==============================================================================
--- branches/trac232/src/lib/config/testdata/spec24.spec (original)
+++ branches/trac232/src/lib/config/testdata/spec24.spec Wed Sep  1 00:35:07 2010
@@ -4,11 +4,11 @@
     "config_data": [
       { "item_name": "item",
         "item_type": "list",
-        "item_optional": True,
+        "item_optional": true,
         "list_item_spec": {
           "item_name": "list_element",
           "item_type": "string",
-          "item_optional": False,
+          "item_optional": false,
           "item_default": ""
         }
       }

Modified: branches/trac232/src/lib/config/testdata/spec27.spec
==============================================================================
--- branches/trac232/src/lib/config/testdata/spec27.spec (original)
+++ branches/trac232/src/lib/config/testdata/spec27.spec Wed Sep  1 00:35:07 2010
@@ -3,81 +3,81 @@
     "module_name": "Spec27",
     "commands": [
     {
-        'command_name': 'cmd1',
+        "command_name": "cmd1",
         "command_description": "command_for_unittest",
-        'command_args': [ 
+        "command_args": [ 
           {
             "item_name": "value1",
             "item_type": "integer",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": 9
           },
           { "item_name": "value2",
             "item_type": "real",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": 9.9
           },
           { "item_name": "value3",
             "item_type": "boolean",
-            "item_optional": False,
-            "item_default": False
+            "item_optional": false,
+            "item_default": false
           },
           { "item_name": "value4",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": "default_string"
           },
           { "item_name": "value5",
             "item_type": "list",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": [ "a", "b" ],
             "list_item_spec": {
               "item_name": "list_element",
               "item_type": "integer",
-              "item_optional": False,
+              "item_optional": false,
               "item_default": 8
             }
           },
           { "item_name": "value6",
             "item_type": "map",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": {},
             "map_item_spec": [
               { "item_name": "v61",
                 "item_type": "string",
-                "item_optional": False,
+                "item_optional": false,
                 "item_default": "def"
               },
               { "item_name": "v62",
                 "item_type": "boolean",
-                "item_optional": False,
-                "item_default": False
+                "item_optional": false,
+                "item_default": false
               }
             ]
           },
           { "item_name": "value7",
             "item_type": "list",
-            "item_optional": True,
+            "item_optional": true,
             "item_default": [ ],
             "list_item_spec": {
               "item_name": "list_element",
               "item_type": "any",
-              "item_optional": True
+              "item_optional": true
             }
           },
           { "item_name": "value8",
             "item_type": "list",
-            "item_optional": True,
+            "item_optional": true,
             "item_default": [ ],
             "list_item_spec": {
               "item_name": "list_element",
               "item_type": "map",
-              "item_optional": True,
+              "item_optional": true,
               "item_default": { "a": "b" },
               "map_item_spec": [
                 { "item_name": "a",
                   "item_type": "string",
-                  "item_optional": True,
+                  "item_optional": true,
                   "item_default": "empty"
                 }
               ]
@@ -85,28 +85,28 @@
           },
           { "item_name": "value9",
             "item_type": "map",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": {},
             "map_item_spec": [
               { "item_name": "v91",
                 "item_type": "string",
-                "item_optional": False,
+                "item_optional": false,
                 "item_default": "def"
               },
               { "item_name": "v92",
                 "item_type": "map",
-                "item_optional": False,
+                "item_optional": false,
                 "item_default": {},
                 "map_item_spec": [
                   { "item_name": "v92a",
                     "item_type": "string",
-                    "item_optional": False,
+                    "item_optional": false,
                     "item_default": "Hello"
                   } ,
                   {
                     "item_name": "v92b",
                     "item_type": "integer",
-                    "item_optional": False,
+                    "item_optional": false,
                     "item_default": 47806
                   }
                 ]

Modified: branches/trac232/src/lib/config/testdata/spec3.spec
==============================================================================
--- branches/trac232/src/lib/config/testdata/spec3.spec (original)
+++ branches/trac232/src/lib/config/testdata/spec3.spec Wed Sep  1 00:35:07 2010
@@ -4,7 +4,7 @@
     "config_data": [
       {
         "item_type": "integer",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 1
       }
     ]

Modified: branches/trac232/src/lib/config/testdata/spec4.spec
==============================================================================
--- branches/trac232/src/lib/config/testdata/spec4.spec (original)
+++ branches/trac232/src/lib/config/testdata/spec4.spec Wed Sep  1 00:35:07 2010
@@ -3,7 +3,7 @@
     "module_name": "Spec2",
     "config_data": [
       { "item_name": "item1",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 1
       }
     ]

Modified: branches/trac232/src/lib/config/testdata/spec6.spec
==============================================================================
--- branches/trac232/src/lib/config/testdata/spec6.spec (original)
+++ branches/trac232/src/lib/config/testdata/spec6.spec Wed Sep  1 00:35:07 2010
@@ -4,7 +4,7 @@
     "config_data": [
       { "item_name": "item1",
         "item_type": "integer",
-        "item_optional": False
+        "item_optional": false
       }
     ]
   }

Modified: branches/trac232/src/lib/config/testdata/spec9.spec
==============================================================================
--- branches/trac232/src/lib/config/testdata/spec9.spec (original)
+++ branches/trac232/src/lib/config/testdata/spec9.spec Wed Sep  1 00:35:07 2010
@@ -4,7 +4,7 @@
     "config_data": [
       { "item_name": "item1",
         "item_type": "integer",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": "asdf"
       }
     ]

Modified: branches/trac232/src/lib/config/tests/Makefile.am
==============================================================================
--- branches/trac232/src/lib/config/tests/Makefile.am (original)
+++ branches/trac232/src/lib/config/tests/Makefile.am Wed Sep  1 00:35:07 2010
@@ -1,9 +1,13 @@
-AM_CPPFLAGS = -I$(top_srcdir)/src/lib
+AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
 
 AM_CXXFLAGS = $(B10_CXXFLAGS)
 # see src/lib/cc/Makefile.am for -Wno-unused-parameter
 if USE_GXX
 AM_CXXFLAGS += -Wno-unused-parameter
+endif
+
+if USE_STATIC_LINK
+AM_LDFLAGS = -static
 endif
 
 CLEANFILES = *.gcno *.gcda

Modified: branches/trac232/src/lib/config/tests/ccsession_unittests.cc
==============================================================================
--- branches/trac232/src/lib/config/tests/ccsession_unittests.cc (original)
+++ branches/trac232/src/lib/config/tests/ccsession_unittests.cc Wed Sep  1 00:35:07 2010
@@ -14,57 +14,50 @@
 
 // $Id: module_spec_unittests.cc 1321 2010-03-11 10:17:03Z jelte $
 
-#include "config.h"
+#include <config.h>
 
 #include <gtest/gtest.h>
 
-#include "fake_session.h"
+#include <config/tests/fake_session.h>
 
 #include <config/ccsession.h>
 
 #include <fstream>
 
-#include "data_def_unittests_config.h"
+#include <config/tests/data_def_unittests_config.h>
 
 using namespace isc::data;
 using namespace isc::config;
+using namespace isc::cc;
 using namespace std;
 
-std::string ccspecfile(const std::string name) {
-    return std::string(TEST_DATA_PATH) + "/" + name;
-}
-
-static ElementPtr
-el(const std::string& str)
-{
-    return Element::fromJSON(str);
-}
-
-// upon creation of a ModuleCCSession, the class
-// sends its specification to the config manager
-// it expects an ok answer back, so everytime we
-// create a ModuleCCSession, we must set an initial
-// ok answer
-void
-initFakeSession()
-{
-    initial_messages = el("[]");
-    msg_queue = el("[]");
-    subscriptions = el("[]");
-    initial_messages->add(createAnswer());
-}
-
-void
-endFakeSession()
-{
-    initial_messages = ElementPtr();
-    msg_queue = ElementPtr();
-    subscriptions = ElementPtr();
-}
-
-TEST(CCSession, createAnswer)
-{
-    ElementPtr answer;
+namespace {
+std::string
+ccspecfile(const std::string name) {
+    return (std::string(TEST_DATA_PATH) + "/" + name);
+}
+
+ElementPtr
+el(const std::string& str) {
+    return (Element::fromJSON(str));
+}
+
+class CCSessionTest : public ::testing::Test {
+protected:
+    CCSessionTest() : session(el("[]"), el("[]"), el("[]")) {
+        // upon creation of a ModuleCCSession, the class
+        // sends its specification to the config manager.
+        // it expects an ok answer back, so everytime we
+        // create a ModuleCCSession, we must set an initial
+        // ok answer.
+        session.getMessages()->add(createAnswer());
+    }
+    ~CCSessionTest() {}
+    FakeSession session;
+};
+
+TEST_F(CCSessionTest, createAnswer) {
+    ConstElementPtr answer;
     answer = createAnswer();
     EXPECT_EQ("{ \"result\": [ 0 ] }", answer->str());
     answer = createAnswer(1, "error");
@@ -73,15 +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(CCSession, parseAnswer)
-{
-    ElementPtr answer;
-    ElementPtr arg;
+TEST_F(CCSessionTest, parseAnswer) {
+    ConstElementPtr answer;
+    ConstElementPtr arg;
     int rcode;
 
     EXPECT_THROW(parseAnswer(rcode, ElementPtr()), CCSessionError);
@@ -110,10 +102,9 @@
     EXPECT_EQ("[ \"just\", \"some\", \"data\" ]", arg->str());
 }
 
-TEST(CCSession, createCommand)
-{
-    ElementPtr command;
-    ElementPtr arg;
+TEST_F(CCSessionTest, createCommand) {
+    ConstElementPtr command;
+    ConstElementPtr arg;
 
     command = createCommand("my_command");
     ASSERT_EQ("{ \"command\": [ \"my_command\" ] }", command->str());
@@ -131,9 +122,8 @@
     ASSERT_EQ("{ \"command\": [ \"foo\", { \"a\": \"map\" } ] }", command->str());
 }
 
-TEST(CCSession, parseCommand)
-{
-    ElementPtr arg;
+TEST_F(CCSessionTest, parseCommand) {
+    ConstElementPtr arg;
     std::string cmd;
 
     // should throw
@@ -159,287 +149,274 @@
 
 }
 
-TEST(CCSession, session1)
-{
-    initFakeSession();
-    EXPECT_EQ(false, haveSubscription("Spec1", "*"));
-    ModuleCCSession mccs(ccspecfile("spec1.spec"), NULL, NULL);
-    EXPECT_EQ(true, haveSubscription("Spec1", "*"));
-
-    EXPECT_EQ(1, msg_queue->size());
-    ElementPtr msg;
+TEST_F(CCSessionTest, session1) {
+    EXPECT_EQ(false, session.haveSubscription("Spec1", "*"));
+    ModuleCCSession mccs(ccspecfile("spec1.spec"), session, NULL, NULL);
+    EXPECT_EQ(true, session.haveSubscription("Spec1", "*"));
+
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    ConstElementPtr msg;
     std::string group, to;
-    msg = getFirstMessage(group, to);
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"command\": [ \"module_spec\", { \"module_name\": \"Spec1\" } ] }", msg->str());
     EXPECT_EQ("ConfigManager", group);
     EXPECT_EQ("*", to);
-    EXPECT_EQ(0, msg_queue->size());
-    endFakeSession();
-}
-
-TEST(CCSession, session2)
+    EXPECT_EQ(0, session.getMsgQueue()->size());
+}
+
+TEST_F(CCSessionTest, session2)
 {
-    initFakeSession();
-    EXPECT_EQ(false, haveSubscription("Spec2", "*"));
-    ModuleCCSession mccs(ccspecfile("spec2.spec"), NULL, NULL);
-    EXPECT_EQ(true, haveSubscription("Spec2", "*"));
-
-    EXPECT_EQ(1, msg_queue->size());
-    ElementPtr msg;
+    EXPECT_EQ(false, session.haveSubscription("Spec2", "*"));
+    ModuleCCSession mccs(ccspecfile("spec2.spec"), session, NULL, NULL);
+    EXPECT_EQ(true, session.haveSubscription("Spec2", "*"));
+
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    ConstElementPtr msg;
     std::string group, to;
-    msg = getFirstMessage(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());
     EXPECT_EQ("ConfigManager", group);
     EXPECT_EQ("*", to);
-    EXPECT_EQ(0, msg_queue->size());
-    endFakeSession();
-}
-
-ElementPtr my_config_handler(ElementPtr new_config)
-{
+    EXPECT_EQ(0, session.getMsgQueue()->size());
+}
+
+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");
+        return (createAnswer(6, "I do not like the number 5"));
     }
-    return createAnswer();
-}
-
-ElementPtr my_command_handler(const std::string& command, ElementPtr arg UNUSED_PARAM)
+    return (createAnswer());
+}
+
+ConstElementPtr my_command_handler(const std::string& command,
+                                   ConstElementPtr arg UNUSED_PARAM)
 {
     if (command == "good_command") {
-        return createAnswer();
+        return (createAnswer());
     } else if (command == "command_with_arg") {
         if (arg) {
             if (arg->getType() == Element::integer) {
-                return createAnswer(0, el("2"));
+                return (createAnswer(0, el("2")));
             } else {
-                return createAnswer(1, "arg bad type");
+                return (createAnswer(1, "arg bad type"));
             }
         } else {
-            return createAnswer(1, "arg missing");
+            return (createAnswer(1, "arg missing"));
         }
     } else {
-        return createAnswer(1, "bad command");
+        return (createAnswer(1, "bad command"));
     }
 }
 
-TEST(CCSession, session3)
-{
-    initFakeSession();
+TEST_F(CCSessionTest, session3) {
     // client will ask for config
-    initial_messages->add(createAnswer(0, el("{  }")));
-
-    EXPECT_EQ(false, haveSubscription("Spec2", "*"));
-    ModuleCCSession mccs(ccspecfile("spec2.spec"), my_config_handler, my_command_handler);
-    EXPECT_EQ(true, haveSubscription("Spec2", "*"));
-
-    EXPECT_EQ(2, msg_queue->size());
-    ElementPtr msg;
+    session.getMessages()->add(createAnswer(0, el("{}")));
+
+    EXPECT_EQ(false, session.haveSubscription("Spec2", "*"));
+    ModuleCCSession mccs(ccspecfile("spec2.spec"), session, my_config_handler,
+                         my_command_handler);
+    EXPECT_EQ(true, session.haveSubscription("Spec2", "*"));
+
+    EXPECT_EQ(2, session.getMsgQueue()->size());
+    ConstElementPtr msg;
     std::string group, to;
-    msg = getFirstMessage(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());
     EXPECT_EQ("ConfigManager", group);
     EXPECT_EQ("*", to);
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"command\": [ \"get_config\", { \"module_name\": \"Spec2\" } ] }", msg->str());
     EXPECT_EQ("ConfigManager", group);
     EXPECT_EQ("*", to);
-    EXPECT_EQ(0, msg_queue->size());
-    endFakeSession();
-}
-
-TEST(CCSession, checkCommand)
-{
-    initFakeSession();
+    EXPECT_EQ(0, session.getMsgQueue()->size());
+}
+
+TEST_F(CCSessionTest, checkCommand) {
     // client will ask for config
-    initial_messages->add(createAnswer(0, el("{  }")));
-
-    EXPECT_EQ(false, haveSubscription("Spec2", "*"));
-    ModuleCCSession mccs(ccspecfile("spec2.spec"), my_config_handler, my_command_handler);
-    EXPECT_EQ(true, haveSubscription("Spec2", "*"));
-
-    EXPECT_EQ(2, msg_queue->size());
-    ElementPtr msg;
+    session.getMessages()->add(createAnswer(0, el("{}")));
+
+    EXPECT_EQ(false, session.haveSubscription("Spec2", "*"));
+    ModuleCCSession mccs(ccspecfile("spec2.spec"), session, my_config_handler,
+                         my_command_handler);
+    EXPECT_EQ(true, session.haveSubscription("Spec2", "*"));
+
+    EXPECT_EQ(2, session.getMsgQueue()->size());
+    ConstElementPtr msg;
     std::string group, to;
     // checked above, drop em
-    msg = getFirstMessage(group, to);
-    msg = getFirstMessage(group, to);
+    msg = session.getFirstMessage(group, to);
+    msg = session.getFirstMessage(group, to);
 
     int result;
     result = mccs.checkCommand();
     EXPECT_EQ(0, result);
 
     // not a command, should be ignored
-    addMessage(el("1"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(0, result);
-
-    addMessage(el("{ \"command\": [ \"good_command\" ] }"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    session.addMessage(el("1"), "Spec2", "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(0, result);
+
+    session.addMessage(el("{ \"command\": [ \"good_command\" ] }"), "Spec2",
+                       "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"result\": [ 0 ] }", msg->str());
     EXPECT_EQ(0, result);
 
-    addMessage(el("{ \"command\": \"bad_command\" }"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    session.addMessage(el("{ \"command\": \"bad_command\" }"), "Spec2", "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"result\": [ 1, \"Command part in command message missing, empty, or not a list\" ] }", msg->str());
     EXPECT_EQ(0, result);
 
-    addMessage(el("{ \"command\": [ \"bad_command\" ] }"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    session.addMessage(el("{ \"command\": [ \"bad_command\" ] }"),
+                       "Spec2", "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"result\": [ 1, \"bad command\" ] }", msg->str());
     EXPECT_EQ(0, result);
 
-    addMessage(el("{ \"command\": [ \"command_with_arg\", 1 ] }"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    session.addMessage(el("{ \"command\": [ \"command_with_arg\", 1 ] }"),
+                       "Spec2", "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"result\": [ 0, 2 ] }", msg->str());
     EXPECT_EQ(0, result);
 
-    addMessage(el("{ \"command\": [ \"command_with_arg\" ] }"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    session.addMessage(el("{ \"command\": [ \"command_with_arg\" ] }"), "Spec2", "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"result\": [ 1, \"arg missing\" ] }", msg->str());
     EXPECT_EQ(0, result);
 
-    addMessage(el("{ \"command\": [ \"command_with_arg\", \"asdf\" ] }"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    session.addMessage(el("{ \"command\": [ \"command_with_arg\", \"asdf\" ] }"), "Spec2", "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"result\": [ 1, \"arg bad type\" ] }", msg->str());
     EXPECT_EQ(0, result);
 
     mccs.setCommandHandler(NULL);
-    addMessage(el("{ \"command\": [ \"whatever\" ] }"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    session.addMessage(el("{ \"command\": [ \"whatever\" ] }"), "Spec2", "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"result\": [ 1, \"Command given but no command handler for module\" ] }", msg->str());
     EXPECT_EQ(0, result);
 
     EXPECT_EQ(1, mccs.getValue("item1")->intValue());
-    addMessage(el("{ \"command\": [ \"config_update\", { \"item1\": 2 } ] }"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    session.addMessage(el("{ \"command\": [ \"config_update\", { \"item1\": 2 } ] }"), "Spec2", "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"result\": [ 0 ] }", msg->str());
     EXPECT_EQ(0, result);
     EXPECT_EQ(2, mccs.getValue("item1")->intValue());
 
-    addMessage(el("{ \"command\": [ \"config_update\", { \"item1\": \"asdf\" } ] }"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    session.addMessage(el("{ \"command\": [ \"config_update\", { \"item1\": \"asdf\" } ] }"), "Spec2", "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"result\": [ 2, \"Error in config validation: Type mismatch\" ] }", msg->str());
     EXPECT_EQ(0, result);
     EXPECT_EQ(2, mccs.getValue("item1")->intValue());
 
-    addMessage(el("{ \"command\": [ \"config_update\", { \"item1\": 5 } ] }"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    session.addMessage(el("{ \"command\": [ \"config_update\", { \"item1\": 5 } ] }"), "Spec2", "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"result\": [ 6, \"I do not like the number 5\" ] }", msg->str());
     EXPECT_EQ(0, result);
     EXPECT_EQ(2, mccs.getValue("item1")->intValue());
-
-    endFakeSession();
-}
-
-TEST(CCSession, remoteConfig)
-{
+}
+
+TEST_F(CCSessionTest, remoteConfig) {
     std::string module_name;
     int item1;
     
-    initFakeSession();
-    ModuleCCSession mccs(ccspecfile("spec1.spec"), NULL, NULL);
-    EXPECT_EQ(true, haveSubscription("Spec1", "*"));
+    ModuleCCSession mccs(ccspecfile("spec1.spec"), session, NULL, NULL);
+    EXPECT_EQ(true, session.haveSubscription("Spec1", "*"));
     
     // first simply connect, with no config values, and see we get
     // the default
-    initial_messages->add(createAnswer(0, el("{  }")));
-
-    EXPECT_EQ(false, haveSubscription("Spec2", "*"));
+    session.getMessages()->add(createAnswer(0, el("{}")));
+
+    EXPECT_EQ(false, session.haveSubscription("Spec2", "*"));
     module_name = mccs.addRemoteConfig(ccspecfile("spec2.spec"));
     EXPECT_EQ("Spec2", module_name);
-    EXPECT_EQ(true, haveSubscription("Spec2", "*"));
+    EXPECT_EQ(true, session.haveSubscription("Spec2", "*"));
 
     item1 = mccs.getRemoteConfigValue(module_name, "item1")->intValue();
     EXPECT_EQ(1, item1);
 
     // Remove it and see we get an error asking for a config value
     mccs.removeRemoteConfig(module_name);
-    EXPECT_EQ(false, haveSubscription("Spec2", "*"));
+    EXPECT_EQ(false, session.haveSubscription("Spec2", "*"));
     EXPECT_THROW(mccs.getRemoteConfigValue(module_name, "item1"), CCSessionError);
 
     // Now re-add it, with a specific config value, and see we get that
-    initial_messages->add(createAnswer(0, el("{ \"item1\": 2 }")));
+    session.getMessages()->add(createAnswer(0, el("{ \"item1\": 2 }")));
     module_name = mccs.addRemoteConfig(ccspecfile("spec2.spec"));
     item1 = mccs.getRemoteConfigValue(module_name, "item1")->intValue();
     EXPECT_EQ(2, item1);
 
     // Try a config_update command
-    addMessage(el("{ \"command\": [ \"config_update\", { \"item1\": 3 } ] }"), module_name, "*");
+    session.addMessage(el("{ \"command\": [ \"config_update\", { \"item1\": 3 } ] }"), module_name, "*");
     mccs.checkCommand();
     item1 = mccs.getRemoteConfigValue(module_name, "item1")->intValue();
     EXPECT_EQ(3, item1);
 
     // remove, re-add, now with a *bad* config request answer
     mccs.removeRemoteConfig(module_name);
-    initial_messages->add(el("{  }"));
+    session.getMessages()->add(el("{}"));
     EXPECT_THROW(mccs.addRemoteConfig(ccspecfile("spec2.spec")), CCSessionError);
     
-    initial_messages->add(createAnswer(1, "my_error"));
+    session.getMessages()->add(createAnswer(1, "my_error"));
     EXPECT_THROW(mccs.addRemoteConfig(ccspecfile("spec2.spec")), CCSessionError);
     
-    initial_messages->add(createAnswer());
-    mccs.addRemoteConfig(ccspecfile("spec2.spec"));
-    
-    endFakeSession();
-}
-
-TEST(CCSession, ignoreRemoteConfigCommands) {
-
-    initFakeSession();
+    session.getMessages()->add(createAnswer());
+    EXPECT_THROW(mccs.addRemoteConfig(ccspecfile("spec2.spec")), CCSessionError);
+}
+
+TEST_F(CCSessionTest, ignoreRemoteConfigCommands) {
     // client will ask for config
-    initial_messages->add(createAnswer(0, el("{  }")));
-
-    EXPECT_EQ(false, haveSubscription("Spec2", "*"));
-    ModuleCCSession mccs(ccspecfile("spec2.spec"), my_config_handler, my_command_handler);
-    EXPECT_EQ(true, haveSubscription("Spec2", "*"));
-
-    EXPECT_EQ(2, msg_queue->size());
-    ElementPtr msg;
+    session.getMessages()->add(createAnswer(0, el("{  }")));
+
+    EXPECT_EQ(false, session.haveSubscription("Spec2", "*"));
+    ModuleCCSession mccs(ccspecfile("spec2.spec"), session, my_config_handler, my_command_handler);
+    EXPECT_EQ(true, session.haveSubscription("Spec2", "*"));
+
+    EXPECT_EQ(2, session.getMsgQueue()->size());
+    ConstElementPtr msg;
     std::string group, to;
     // drop the module_spec and config commands
-    getFirstMessage(group, to);
-    getFirstMessage(group, to);
-
-    initial_messages->add(createAnswer(0, el("{  }")));
+    session.getFirstMessage(group, to);
+    session.getFirstMessage(group, to);
+
+    session.getMessages()->add(createAnswer(0, el("{  }")));
     mccs.addRemoteConfig(ccspecfile("spec1.spec"));
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
 
     // Check if commands for the module are handled
-    addMessage(el("{ \"command\": [ \"good_command\" ] }"), "Spec2", "*");
+    session.addMessage(el("{ \"command\": [ \"good_command\" ] }"), "Spec2", "*");
     int result = mccs.checkCommand();
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"result\": [ 0 ] }", msg->str());
     EXPECT_EQ(0, result);
 
     // Check if commands for the other module are ignored
-    addMessage(el("{ \"command\": [ \"good_command\" ] }"), "Spec1", "*");
-    EXPECT_EQ(1, msg_queue->size());
-    result = mccs.checkCommand();
-    EXPECT_EQ(0, msg_queue->size());
-    
-    endFakeSession();
-}
+    session.addMessage(el("{ \"command\": [ \"good_command\" ] }"), "Spec1", "*");
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    result = mccs.checkCommand();
+    EXPECT_EQ(0, session.getMsgQueue()->size());
+}
+
+}

Modified: branches/trac232/src/lib/config/tests/config_data_unittests.cc
==============================================================================
--- branches/trac232/src/lib/config/tests/config_data_unittests.cc (original)
+++ branches/trac232/src/lib/config/tests/config_data_unittests.cc Wed Sep  1 00:35:07 2010
@@ -17,7 +17,7 @@
 
 #include <gtest/gtest.h>
 
-#include "data_def_unittests_config.h"
+#include <config/tests/data_def_unittests_config.h>
 #include <config/config_data.h>
 
 #include <iostream>
@@ -26,10 +26,9 @@
 using namespace isc::config;
 
 ConfigData
-setupSpec2()
-{
+setupSpec2() {
     ModuleSpec spec2 = moduleSpecFromFile(std::string(TEST_DATA_PATH) + "/spec22.spec");
-    return ConfigData(spec2);
+    return (ConfigData(spec2));
 }
 
 TEST(ConfigData, Creation) {

Modified: branches/trac232/src/lib/config/tests/fake_session.cc
==============================================================================
--- branches/trac232/src/lib/config/tests/fake_session.cc (original)
+++ branches/trac232/src/lib/config/tests/fake_session.cc Wed Sep  1 00:35:07 2010
@@ -14,7 +14,7 @@
 
 // $Id: session.cc 1250 2010-03-09 22:52:15Z jinmei $
 
-#include "config.h"
+#include <config.h>
 
 #include <stdint.h>
 
@@ -28,7 +28,7 @@
 #include <exceptions/exceptions.h>
 
 #include <cc/data.h>
-#include "fake_session.h"
+#include <config/tests/fake_session.h>
 
 using namespace std;
 using namespace isc::cc;
@@ -38,30 +38,25 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 
-isc::data::ElementPtr initial_messages;
-isc::data::ElementPtr subscriptions;
-isc::data::ElementPtr msg_queue;
-
 // ok i want these in cc/data 
-static bool
-listContains(ElementPtr list, ElementPtr el)
-{
+bool
+listContains(ConstElementPtr list, ConstElementPtr el) {
     if (!list) {
-        return false;
-    }
-    BOOST_FOREACH(ElementPtr l_el, list->listValue()) {
-        if (l_el == el) {
-            return true;
+        return (false);
+    }
+    BOOST_FOREACH(ConstElementPtr l_el, list->listValue()) {
+        if (*l_el == *el) {
+            return (true);
         }
     }
-    return false;
-}
-
-static void
-listRemove(ElementPtr list, ElementPtr el) {
+    return (false);
+}
+
+void
+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++;
@@ -72,40 +67,176 @@
 }
 // endwant
 
-ElementPtr
-getFirstMessage(std::string& group, std::string& to)
-{
-    ElementPtr el;
-    if (msg_queue && msg_queue->size() > 0) {
-        el = msg_queue->get(0);
-        msg_queue->remove(0);
+namespace isc {
+namespace cc {
+
+FakeSession::FakeSession(isc::data::ElementPtr initial_messages,
+                         isc::data::ElementPtr subscriptions,
+                         isc::data::ElementPtr msg_queue) :
+    messages_(initial_messages),
+    subscriptions_(subscriptions),
+    msg_queue_(msg_queue)
+{
+}
+
+FakeSession::~FakeSession() {
+}
+
+void
+FakeSession::disconnect() {
+}
+
+void
+FakeSession::startRead(boost::function<void()> read_callback UNUSED_PARAM) {
+}
+
+void
+FakeSession::establish(const char* socket_file) {
+}
+
+bool
+FakeSession::recvmsg(ConstElementPtr& msg, bool nonblock UNUSED_PARAM,
+                     int seq UNUSED_PARAM)
+{
+    //cout << "[XX] client asks for message " << endl;
+    if (messages_ &&
+        messages_->getType() == Element::list &&
+        messages_->size() > 0) {
+        msg = messages_->get(0);
+        messages_->remove(0);
+    } else {
+        msg = ElementPtr();
+    }
+    return (true);
+}
+
+bool
+FakeSession::recvmsg(ConstElementPtr& env, ConstElementPtr& msg,
+                     bool nonblock UNUSED_PARAM,
+                     int seq UNUSED_PARAM)
+{
+    //cout << "[XX] client asks for message and env" << endl;
+    env = ElementPtr();
+    if (messages_ &&
+        messages_->getType() == Element::list &&
+        messages_->size() > 0) {
+        // do we need initial message to have env[group] and [to] too?
+        msg = messages_->get(0);
+        messages_->remove(0);
+        return (true);
+    } else if (msg_queue_) {
+        BOOST_FOREACH(ConstElementPtr c_m, msg_queue_->listValue()) {
+            ConstElementPtr to_remove = ElementPtr();
+            if (haveSubscription(c_m->get(0), 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;
+            }
+            if (to_remove) {
+                listRemove(msg_queue_, to_remove);
+                return (true);
+            }
+        }
+    }
+    msg = ElementPtr();
+    env = ElementPtr();
+    return (false);
+}
+
+void
+FakeSession::subscribe(std::string group, std::string instance) {
+    //cout << "[XX] client subscribes to " << group << " . " << instance << endl;
+    ElementPtr s_el = Element::createList();
+    s_el->add(Element::create(group));
+    s_el->add(Element::create(instance));
+    if (!subscriptions_) {
+        subscriptions_ = Element::createList();
+    }
+    subscriptions_->add(s_el);
+}
+
+void
+FakeSession::unsubscribe(std::string group, std::string instance) {
+    //cout << "[XX] client unsubscribes from " << group << " . " << instance << endl;
+    ElementPtr s_el = Element::createList();
+    s_el->add(Element::create(group));
+    s_el->add(Element::create(instance));
+    if (!subscriptions_) {
+        return;
+    }
+    listRemove(subscriptions_, s_el);
+}
+
+int
+FakeSession::group_sendmsg(ConstElementPtr msg, std::string group,
+                           std::string to, std::string instance UNUSED_PARAM)
+{
+    //cout << "[XX] client sends message: " << msg << endl;
+    //cout << "[XX] to: " << group << " . " << instance << "." << to << endl;
+    addMessage(msg, group, to);
+    return (1);
+}
+
+bool
+FakeSession::group_recvmsg(ConstElementPtr& envelope, ConstElementPtr& msg,
+                           bool nonblock, int seq)
+{
+    return (recvmsg(envelope, msg, nonblock, seq));
+}
+
+int
+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());
+    return (1);
+}
+
+bool
+FakeSession::hasQueuedMsgs() const {
+    return (false);
+}
+
+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);
         group = el->get(0)->stringValue();
         to = el->get(1)->stringValue();
-        return el->get(2);
+        return (el->get(2));
     } else {
         group = "";
         to = "";
-        return ElementPtr();
-    }
-}
-
-void
-addMessage(ElementPtr msg, const std::string& group, const std::string& to) {
+        return (ElementPtr());
+    }
+}
+
+void
+FakeSession::addMessage(ConstElementPtr msg, const std::string& group,
+                        const std::string& to)
+{
     ElementPtr m_el = Element::createList();
     m_el->add(Element::create(group));
     m_el->add(Element::create(to));
     m_el->add(msg);
-    if (!msg_queue) {
-        msg_queue = Element::createList();
-    }
-    msg_queue->add(m_el);
-}
-
-bool
-haveSubscription(const std::string& group, const std::string& instance)
-{
-    if (!subscriptions) {
-        return false;
+    if (!msg_queue_) {
+        msg_queue_ = Element::createList();
+    }
+    msg_queue_->add(m_el);
+}
+
+bool
+FakeSession::haveSubscription(const std::string& group,
+                              const std::string& instance)
+{
+    if (!subscriptions_) {
+        return (false);
     }
     ElementPtr s1 = Element::createList();
     ElementPtr s2 = Element::createList();
@@ -113,168 +244,16 @@
     s1->add(Element::create(instance));
     s2->add(Element::create(group));
     s2->add(Element::create("*"));
-    bool result = (listContains(subscriptions, s1) || listContains(subscriptions, s2));
-    return result;
-}
-
-bool
-haveSubscription(const ElementPtr group, const ElementPtr instance)
-{
-    return haveSubscription(group->stringValue(), instance->stringValue());
-}
-
-namespace isc {
-namespace cc {
-
-Session::Session()
-{
-}
-
-Session::Session(asio::io_service& io_service UNUSED_PARAM)
-{
-}
-
-Session::~Session() {
-}
-
-bool
-Session::connect() {
-    return true;
-}
-
-void
-Session::disconnect() {
-}
-
-int
-Session::getSocket() const {
-    return 1;
-}
-
-void
-Session::startRead(boost::function<void()> read_callback UNUSED_PARAM) {
-}
-
-void
-Session::establish(const char* socket_file) {
-}
-
-//
-// Convert to wire format and send this on the TCP stream with its length prefix
-//
-void
-Session::sendmsg(ElementPtr& msg) {
-    //cout << "[XX] client sends message: " << msg << endl;
-    // err, to where?
-    addMessage(msg, "*", "*");
-}
-
-void
-Session::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
-Session::recvmsg(ElementPtr& msg, bool nonblock UNUSED_PARAM, int seq UNUSED_PARAM) {
-    //cout << "[XX] client asks for message " << endl;
-    if (initial_messages &&
-        initial_messages->getType() == Element::list &&
-        initial_messages->size() > 0) {
-        msg = initial_messages->get(0);
-        initial_messages->remove(0);
-    } else {
-        msg = ElementPtr();
-    }
-    return (true);
-}
-
-bool
-Session::recvmsg(ElementPtr& env, ElementPtr& msg, bool nonblock UNUSED_PARAM, int seq UNUSED_PARAM) {
-    //cout << "[XX] client asks for message and env" << endl;
-    env = ElementPtr();
-    if (initial_messages &&
-        initial_messages->getType() == Element::list &&
-        initial_messages->size() > 0) {
-        // do we need initial message to have env[group] and [to] too?
-        msg = initial_messages->get(0);
-        initial_messages->remove(0);
-        return true;
-    } else if (msg_queue) {
-        BOOST_FOREACH(ElementPtr c_m, msg_queue->listValue()) {
-            ElementPtr 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));
-                msg = c_m->get(2);
-                to_remove = c_m;
-            }
-            if (to_remove) {
-                listRemove(msg_queue, to_remove);
-                return true;
-            }
-        }
-    }
-    msg = ElementPtr();
-    env = ElementPtr();
-    return false;
-}
-
-void
-Session::subscribe(std::string group, std::string instance) {
-    //cout << "[XX] client subscribes to " << group << " . " << instance << endl;
-    ElementPtr s_el = Element::createList();
-    s_el->add(Element::create(group));
-    s_el->add(Element::create(instance));
-    if (!subscriptions) {
-        subscriptions = Element::createList();
-    }
-    subscriptions->add(s_el);
-}
-
-void
-Session::unsubscribe(std::string group, std::string instance) {
-    //cout << "[XX] client unsubscribes from " << group << " . " << instance << endl;
-    ElementPtr s_el = Element::createList();
-    s_el->add(Element::create(group));
-    s_el->add(Element::create(instance));
-    if (!subscriptions) {
-        return;
-    }
-    listRemove(subscriptions, s_el);
-}
-
-int
-Session::group_sendmsg(ElementPtr msg, std::string group,
-                       std::string to, std::string instance UNUSED_PARAM)
-{
-    //cout << "[XX] client sends message: " << msg << endl;
-    //cout << "[XX] to: " << group << " . " << instance << "." << to << endl;
-    addMessage(msg, group, to);
-    return 1;
-}
-
-bool
-Session::group_recvmsg(ElementPtr& envelope, ElementPtr& msg,
-                       bool nonblock, int seq)
-{
-    return (recvmsg(envelope, msg, nonblock, seq));
-}
-
-int
-Session::reply(ElementPtr& envelope, ElementPtr& newmsg) {
-    //cout << "[XX] client sends reply: " << newmsg << endl;
-    //cout << "[XX] env: " << envelope << endl;
-    addMessage(newmsg, envelope->get("group")->stringValue(), envelope->get("to")->stringValue());
-    return 1;
-}
-
-bool
-Session::hasQueuedMsgs() {
-    return false;
-}
-
-}
-}
+    bool result = (listContains(subscriptions_, s1) ||
+                   listContains(subscriptions_, s2));
+    return (result);
+}
+
+bool
+FakeSession::haveSubscription(ConstElementPtr group, ConstElementPtr instance)
+{
+    return (haveSubscription(group->stringValue(), instance->stringValue()));
+}
+
+}
+}

Modified: branches/trac232/src/lib/config/tests/fake_session.h
==============================================================================
--- branches/trac232/src/lib/config/tests/fake_session.h (original)
+++ branches/trac232/src/lib/config/tests/fake_session.h Wed Sep  1 00:35:07 2010
@@ -14,8 +14,8 @@
 
 // $Id: session.h 1250 2010-03-09 22:52:15Z jinmei $
 
-#ifndef _ISC_SESSION_H
-#define _ISC_SESSION_H 1
+#ifndef _ISC_FAKESESSION_H
+#define _ISC_FAKESESSION_H 1
 
 #include <string>
 
@@ -24,85 +24,78 @@
 #include <exceptions/exceptions.h>
 
 #include <cc/data.h>
-
-namespace asio {
-class io_service;
-}
-
-// global variables so tests can insert
-// update and check, before, during and after
-// the actual session object was created/destroyed
-
-// if initial_messages contains a list of messages,
-// these are sent when recv_msg or group_recvmsg is called
-// instead of whatever is in the msg queue
-extern isc::data::ElementPtr initial_messages;
-extern isc::data::ElementPtr subscriptions;
-extern isc::data::ElementPtr msg_queue;
-
-bool haveSubscription(const std::string& group, const std::string& instance);
-bool haveSubscription(const isc::data::ElementPtr group, const isc::data::ElementPtr instance);
-isc::data::ElementPtr getFirstMessage(std::string& group, std::string& to);
-void addMessage(isc::data::ElementPtr, const std::string& group, const std::string& to);
+#include <cc/session.h>
 
 namespace isc {
-    namespace cc {
+namespace cc {
+class FakeSession : public AbstractSession {
+private:
+    FakeSession(const Session& source);
+    FakeSession& operator=(const Session& source);
 
-        class SessionError : public isc::Exception {
-        public:
-            SessionError(const char* file, size_t line, const char* what) :
-                isc::Exception(file, line, what) {}
-        };
+public:
+    // if initial_messages contains a list of messages,
+    // these are sent when recv_msg or group_recvmsg is called
+    // instead of whatever is in the msg queue.
+    // The test can also add data to a copy of the message later to tweak
+    // the group_recvmsg() behavior.  See getMessages() below.
+    FakeSession(isc::data::ElementPtr initial_messages,
+                isc::data::ElementPtr subscriptions,
+                isc::data::ElementPtr msg_queue);
+    virtual ~FakeSession();
 
-        class Session {
-        private:
-            Session(const Session& source);
-            Session& operator=(const Session& source);
+    virtual void startRead(boost::function<void()> read_callback);
 
-        public:
-            // public so tests can inspect them
-        
-            Session();
-            Session(asio::io_service& ioservice);
-            ~Session();
-
-            // XXX: quick hack to allow the user to watch the socket directly.
-            int getSocket() const;
-
-            void startRead(boost::function<void()> read_callback);
-
-            void establish(const char* socket_file = NULL);
-            bool connect();
-            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);
-            void subscribe(std::string group,
+    virtual void establish(const char* socket_file = NULL);
+    virtual void disconnect();
+    virtual void subscribe(std::string group,
                            std::string instance = "*");
-            void unsubscribe(std::string group,
+    virtual void unsubscribe(std::string group,
                              std::string instance = "*");
-            int group_sendmsg(isc::data::ElementPtr msg,
+    virtual int group_sendmsg(isc::data::ConstElementPtr msg,
                               std::string group,
                               std::string instance = "*",
                               std::string to = "*");
-            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);
-            int reply(isc::data::ElementPtr& envelope,
-                      isc::data::ElementPtr& newmsg);
-            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 { 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::ConstElementPtr group,
+                          const isc::data::ConstElementPtr instance);
 
-        };
-    } // namespace cc
+    // For the convenience of tests, we share these internal members
+    // with the tester.  The test code may insert update and check,
+    // before (via the constructor parameters), during and after the actual
+    // session object was created/destroyed.
+    isc::data::ElementPtr getMessages() { return (messages_); }
+    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_;
+};
+} // namespace cc
 } // namespace isc
 
-#endif // _ISC_SESSION_H
+#endif // _ISC_FAKESESSION_H
 
 // Local Variables:
 // mode: c++

Modified: branches/trac232/src/lib/config/tests/module_spec_unittests.cc
==============================================================================
--- branches/trac232/src/lib/config/tests/module_spec_unittests.cc (original)
+++ branches/trac232/src/lib/config/tests/module_spec_unittests.cc Wed Sep  1 00:35:07 2010
@@ -20,13 +20,13 @@
 
 #include <fstream>
 
-#include "data_def_unittests_config.h"
+#include <config/tests/data_def_unittests_config.h>
 
 using namespace isc::data;
 using namespace isc::config;
 
 std::string specfile(const std::string name) {
-    return std::string(TEST_DATA_PATH) + "/" + name;
+    return (std::string(TEST_DATA_PATH) + "/" + name);
 }
 
 void
@@ -134,27 +134,27 @@
 }
 
 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());
+    ConstElementPtr data = Element::fromJSON(data_file, data_file_name);
+    data_file.close();
+
+    return (dd.validate_config(data));
+}
+
+bool
+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);
-}
-
-bool
-data_test_with_errors(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);
-    data_file.close();
-
-    return dd.validate_config(data, true, errors);
+    return (dd.validate_config(data, true, errors));
 }
 
 TEST(ModuleSpec, DataValidation) {

Modified: branches/trac232/src/lib/datasrc/cache.cc
==============================================================================
--- branches/trac232/src/lib/datasrc/cache.cc (original)
+++ branches/trac232/src/lib/datasrc/cache.cc Wed Sep  1 00:35:07 2010
@@ -240,8 +240,7 @@
     if (node->lru_entry_ == lru_.begin()) {
         return;
     }
-    lru_.erase(node->lru_entry_);
-    lru_.push_front(node);
+    lru_.splice(lru_.begin(), lru_, node->lru_entry_); // move node to front
     node->lru_entry_ = lru_.begin();
 }
 

Modified: branches/trac232/src/lib/datasrc/data_source.cc
==============================================================================
--- branches/trac232/src/lib/datasrc/data_source.cc (original)
+++ branches/trac232/src/lib/datasrc/data_source.cc Wed Sep  1 00:35:07 2010
@@ -14,7 +14,7 @@
 
 // $Id$
 
-#include "config.h"
+#include <config.h>
 
 #include <cassert>
 #include <iomanip>
@@ -28,14 +28,14 @@
 #include <datasrc/data_source.h>
 #include <datasrc/query.h>
 
-#include <dns/base32.h>
+#include <dns/util/base32hex.h>
 #include <dns/buffer.h>
 #include <dns/message.h>
 #include <dns/name.h>
 #include <dns/rdataclass.h>
 #include <dns/rrset.h>
 #include <dns/rrsetlist.h>
-#include <dns/sha1.h>
+#include <dns/util/sha1.h>
 
 #include <cc/data.h>
 
@@ -1234,7 +1234,7 @@
         inlength = SHA1_HASHSIZE;
     } while (n++ < iterations_);
 
-    return (encodeBase32(vector<uint8_t>(digest, digest + SHA1_HASHSIZE)));
+    return (encodeBase32Hex(vector<uint8_t>(digest, digest + SHA1_HASHSIZE)));
 }
 
 //
@@ -1245,7 +1245,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/trac232/src/lib/datasrc/data_source.h
==============================================================================
--- branches/trac232/src/lib/datasrc/data_source.h (original)
+++ branches/trac232/src/lib/datasrc/data_source.h Wed Sep  1 00:35:07 2010
@@ -126,7 +126,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
@@ -309,12 +309,12 @@
 
     virtual void findClosestEnclosure(DataSrcMatch& match) const = 0;
 
-    const isc::dns::RRClass& getClass() const { return rrclass; }
+    const isc::dns::RRClass& getClass() const { return (rrclass); }
     void setClass(isc::dns::RRClass& c) { rrclass = c; }
     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,
@@ -503,7 +503,7 @@
 
     void addDataSrc(ConstDataSrcPtr data_src);
     void removeDataSrc(ConstDataSrcPtr data_src);
-    size_t dataSrcCount() { return data_sources.size(); };
+    size_t dataSrcCount() { return (data_sources.size()); }
     
     void findClosestEnclosure(DataSrcMatch& match) const;
 

Modified: branches/trac232/src/lib/datasrc/query.cc
==============================================================================
--- branches/trac232/src/lib/datasrc/query.cc (original)
+++ branches/trac232/src/lib/datasrc/query.cc Wed Sep  1 00:35:07 2010
@@ -21,7 +21,7 @@
 
 #include <cc/data.h>
 
-#include "query.h"
+#include <datasrc/query.h>
 
 using namespace isc::dns;
 

Modified: branches/trac232/src/lib/datasrc/query.h
==============================================================================
--- branches/trac232/src/lib/datasrc/query.h (original)
+++ branches/trac232/src/lib/datasrc/query.h Wed Sep  1 00:35:07 2010
@@ -88,7 +88,7 @@
         AUTH_QUERY,
         GLUE_QUERY,
         NOGLUE_QUERY,
-        REF_QUERY,
+        REF_QUERY
     } op;
 
     // The state field indicates the state of the query; it controls

Modified: branches/trac232/src/lib/datasrc/sqlite3_datasrc.cc
==============================================================================
--- branches/trac232/src/lib/datasrc/sqlite3_datasrc.cc (original)
+++ branches/trac232/src/lib/datasrc/sqlite3_datasrc.cc Wed Sep  1 00:35:07 2010
@@ -21,7 +21,7 @@
 
 #include <sqlite3.h>
 
-#include "sqlite3_datasrc.h"
+#include <datasrc/sqlite3_datasrc.h>
 
 #include <dns/rrttl.h>
 #include <dns/rdata.h>
@@ -293,15 +293,16 @@
         isc_throw(Sqlite3Error, "Could not bind zone ID " << zone_id <<
                   " to SQL statement (query)");
     }
-    const string s_name = name.toText();
-    rc = sqlite3_bind_text(query, 2, s_name.c_str(), -1, SQLITE_STATIC);
-    if (rc != SQLITE_OK) {
-        isc_throw(Sqlite3Error, "Could not bind name " << s_name <<
+    const string name_text = name.toText();
+    rc = sqlite3_bind_text(query, 2, name_text.c_str(), -1, SQLITE_STATIC);
+    if (rc != SQLITE_OK) {
+        isc_throw(Sqlite3Error, "Could not bind name " << name_text <<
                   " to SQL statement (query)");
     }
 
+    const string rdtype_text = rdtype.toText();
     if (query == dbparameters->q_record_) {
-        rc = sqlite3_bind_text(query, 3, rdtype.toText().c_str(), -1,
+        rc = sqlite3_bind_text(query, 3, rdtype_text.c_str(), -1,
                                SQLITE_STATIC);
         if (rc != SQLITE_OK) {
             isc_throw(Sqlite3Error, "Could not bind RR type " <<
@@ -330,8 +331,9 @@
                   " to SQL statement (qcount)");
     }
 
-    rc = sqlite3_bind_text(dbparameters->q_count_, 2,
-                           name.reverse().toText().c_str(), -1, SQLITE_STATIC);
+    const string revname_text = name.reverse().toText();
+    rc = sqlite3_bind_text(dbparameters->q_count_, 2, revname_text.c_str(),
+                           -1, SQLITE_STATIC);
     if (rc != SQLITE_OK) {
         isc_throw(Sqlite3Error, "Could not bind name " << name.reverse() <<
                   " to SQL statement (qcount)");
@@ -406,8 +408,9 @@
         isc_throw(Sqlite3Error, "Could not bind zone ID " << zone_id <<
                   " to SQL statement (qprevious)");        
     }
+    const string revname_text = qname.reverse().toText();
     rc = sqlite3_bind_text(dbparameters->q_previous_, 2,
-                           qname.reverse().toText().c_str(), -1, SQLITE_STATIC);
+                           revname_text.c_str(), -1, SQLITE_STATIC);
     if (rc != SQLITE_OK) {
         isc_throw(Sqlite3Error, "Could not bind name " << qname <<
                   " to SQL statement (qprevious)");
@@ -585,7 +588,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/trac232/src/lib/datasrc/sqlite3_datasrc.h
==============================================================================
--- branches/trac232/src/lib/datasrc/sqlite3_datasrc.h (original)
+++ branches/trac232/src/lib/datasrc/sqlite3_datasrc.h Wed Sep  1 00:35:07 2010
@@ -21,7 +21,7 @@
 
 #include <exceptions/exceptions.h>
 
-#include "data_source.h"
+#include <datasrc/data_source.h>
 
 #include <dns/name.h>
 #include <dns/rrttl.h>
@@ -100,8 +100,8 @@
                              std::string& hash,
                              isc::dns::RRsetList& target) const;
 
-    Result init() { return init(isc::data::ElementPtr()); };
-    Result init(const isc::data::ElementPtr config);
+    Result init() { return (init(isc::data::ElementPtr())); }
+    Result init(const isc::data::ConstElementPtr config);
     Result close();
 
 

Modified: branches/trac232/src/lib/datasrc/static_datasrc.cc
==============================================================================
--- branches/trac232/src/lib/datasrc/static_datasrc.cc (original)
+++ branches/trac232/src/lib/datasrc/static_datasrc.cc Wed Sep  1 00:35:07 2010
@@ -14,7 +14,7 @@
 
 // $Id$
 
-#include "config.h"
+#include <config.h>
 
 #include <cassert>
 
@@ -26,8 +26,8 @@
 #include <dns/rrtype.h>
 #include <dns/rrttl.h>
 
-#include "data_source.h"
-#include "static_datasrc.h"
+#include <datasrc/data_source.h>
+#include <datasrc/static_datasrc.h>
 
 using namespace std;
 using namespace isc::dns;
@@ -70,6 +70,7 @@
 {
     authors = RRsetPtr(new RRset(authors_name, RRClass::CH(),
                                  RRType::TXT(), RRTTL(0)));
+    authors->addRdata(generic::TXT("Chen Zhengzhang")); // Jerry
     authors->addRdata(generic::TXT("Evan Hunt"));
     authors->addRdata(generic::TXT("Han Feng"));
     authors->addRdata(generic::TXT("Jelte Jansen"));
@@ -80,6 +81,8 @@
     authors->addRdata(generic::TXT("Michael Graff"));
     authors->addRdata(generic::TXT("Naoki Kambe"));
     authors->addRdata(generic::TXT("Shane Kerr"));
+    authors->addRdata(generic::TXT("Shen Tingting"));
+    authors->addRdata(generic::TXT("Stephen Morris"));
     authors->addRdata(generic::TXT("Zhang Likun"));
 
     authors_ns = RRsetPtr(new RRset(authors_name, RRClass::CH(),
@@ -257,8 +260,8 @@
 // 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) {
-    return init();
+StaticDataSrc::init(isc::data::ConstElementPtr config UNUSED_PARAM) {
+    return (init());
 }
 
 DataSrc::Result

Modified: branches/trac232/src/lib/datasrc/static_datasrc.h
==============================================================================
--- branches/trac232/src/lib/datasrc/static_datasrc.h (original)
+++ branches/trac232/src/lib/datasrc/static_datasrc.h Wed Sep  1 00:35:07 2010
@@ -25,7 +25,7 @@
 #ifndef __STATIC_DATA_SOURCE_H
 #define __STATIC_DATA_SOURCE_H
 
-#include "data_source.h"
+#include <datasrc/data_source.h>
 
 namespace isc {
 
@@ -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/trac232/src/lib/datasrc/tests/Makefile.am
==============================================================================
--- branches/trac232/src/lib/datasrc/tests/Makefile.am (original)
+++ branches/trac232/src/lib/datasrc/tests/Makefile.am Wed Sep  1 00:35:07 2010
@@ -6,7 +6,11 @@
 
 AM_CXXFLAGS = $(B10_CXXFLAGS)
 
-CLEANFILES = *.gcno *.gcda testdata/write_test.sqlite3
+if USE_STATIC_LINK
+AM_LDFLAGS = -static
+endif
+
+CLEANFILES = *.gcno *.gcda
 
 TESTS =
 if HAVE_GTEST
@@ -24,10 +28,10 @@
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 run_unittests_LDADD = $(GTEST_LDADD)
 run_unittests_LDADD += $(SQLITE_LIBS)
-run_unittests_LDADD += $(top_builddir)/src/lib/datasrc/.libs/libdatasrc.a 
-run_unittests_LDADD += $(top_builddir)/src/lib/dns/.libs/libdns++.a 
-run_unittests_LDADD += $(top_builddir)/src/lib/cc/.libs/libcc.a
-run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a
+run_unittests_LDADD += $(top_builddir)/src/lib/datasrc/libdatasrc.la 
+run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
+run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.la
+run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 endif
 
 noinst_PROGRAMS = $(TESTS)
@@ -39,27 +43,6 @@
 EXTRA_DIST += testdata/example2.com
 EXTRA_DIST += testdata/example2.com.sqlite3
 EXTRA_DIST += testdata/mkbrokendb.c
-EXTRA_DIST += testdata/q_cname
-EXTRA_DIST += testdata/q_cname_ext
-EXTRA_DIST += testdata/q_cname_int
-EXTRA_DIST += testdata/q_dname
-EXTRA_DIST += testdata/q_example_dnskey
-EXTRA_DIST += testdata/q_example_ns
-EXTRA_DIST += testdata/q_example_ptr
-EXTRA_DIST += testdata/q_glork
-EXTRA_DIST += testdata/q_spork
-EXTRA_DIST += testdata/q_sql1
-EXTRA_DIST += testdata/q_subzone
-EXTRA_DIST += testdata/q_subzone_any
-EXTRA_DIST += testdata/q_subzone_dname
-EXTRA_DIST += testdata/q_subzone_ds
-EXTRA_DIST += testdata/q_subzone_ns
-EXTRA_DIST += testdata/q_subzone_nsec
-EXTRA_DIST += testdata/q_wild2_a
-EXTRA_DIST += testdata/q_wild2_aaaa
-EXTRA_DIST += testdata/q_wild3_a
-EXTRA_DIST += testdata/q_wild_a
-EXTRA_DIST += testdata/q_wild_aaaa
 EXTRA_DIST += testdata/root.zone
 EXTRA_DIST += testdata/sql1.example.com.signed
 EXTRA_DIST += testdata/sql2.example.com.signed

Modified: branches/trac232/src/lib/datasrc/tests/datasrc_unittest.cc
==============================================================================
--- branches/trac232/src/lib/datasrc/tests/datasrc_unittest.cc (original)
+++ branches/trac232/src/lib/datasrc/tests/datasrc_unittest.cc Wed Sep  1 00:35:07 2010
@@ -39,7 +39,7 @@
 #include <datasrc/static_datasrc.h>
 
 #include <dns/tests/unittest_util.h>
-#include "test_datasrc.h"
+#include <datasrc/tests/test_datasrc.h>
 
 using isc::UnitTestUtil;
 using namespace std;
@@ -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 {
@@ -65,7 +65,6 @@
         meta_source.addDataSrc(static_source);
     }
     void QueryCommon(const RRClass& qclass);
-    void readAndProcessQuery(const char* datafile);
     void createAndProcessQuery(const Name& qname, const RRClass& qclass,
                                const RRType& qtype);
 
@@ -82,18 +81,6 @@
     message.setRcode(Rcode::NOERROR());
     Query q(message, cache, true);
     data_source.doQuery(q);
-}
-
-void
-DataSrcTest::readAndProcessQuery(const char* datafile) {
-    std::vector<unsigned char> data;
-    UnitTestUtil::readWireData(datafile, data);
-
-    InputBuffer buffer(&data[0], data.size());
-    msg.fromWire(buffer);
-
-    msg.makeResponse();
-    performQuery(meta_source, cache, msg);
 }
 
 void
@@ -193,8 +180,8 @@
 }
 
 TEST_F(DataSrcTest, NSQuery) {
-    readAndProcessQuery("q_example_ns");
-
+    createAndProcessQuery(Name("example.com"), RRClass::IN(),
+                          RRType::NS());
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 0, 6);
 
     RRsetIterator rit = msg.beginSection(Section::ANSWER());
@@ -216,7 +203,8 @@
 
 // Make sure two successive queries have the same result
 TEST_F(DataSrcTest, DuplicateQuery) {
-    readAndProcessQuery("q_example_ns");
+    createAndProcessQuery(Name("example.com"), RRClass::IN(),
+                          RRType::NS());
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 0, 6);
 
     RRsetIterator rit = msg.beginSection(Section::ANSWER());
@@ -236,7 +224,8 @@
     EXPECT_TRUE(it->isLast());
 
     msg.clear(Message::PARSE);
-    readAndProcessQuery("q_example_ns");
+    createAndProcessQuery(Name("example.com"), RRClass::IN(),
+                          RRType::NS());
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 0, 6);
 
     rit = msg.beginSection(Section::ANSWER());
@@ -257,7 +246,8 @@
 }
 
 TEST_F(DataSrcTest, DNSKEYQuery) {
-    readAndProcessQuery("q_example_dnskey");
+    createAndProcessQuery(Name("example.com"), RRClass::IN(),
+                          RRType::DNSKEY());
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 4, 6);
 
     RRsetIterator rit = msg.beginSection(Section::ANSWER());
@@ -271,7 +261,8 @@
 // We query for a record at a zone cut to ensure the REFERRAL flag doesn't
 // cause incorrect behavior.
 TEST_F(DataSrcTest, DNSKEYDuplicateQuery) {
-    readAndProcessQuery("q_example_dnskey");
+    createAndProcessQuery(Name("example.com"), RRClass::IN(),
+                          RRType::DNSKEY());
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 4, 6);
 
     RRsetIterator rit = msg.beginSection(Section::ANSWER());
@@ -281,9 +272,8 @@
     EXPECT_EQ(RRClass::IN(), rrset->getClass());
 
     msg.clear(Message::PARSE);
-    readAndProcessQuery("q_example_dnskey");
-    headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 4, 6);
-
+    createAndProcessQuery(Name("example.com"), RRClass::IN(),
+                          RRType::DNSKEY());
     rit = msg.beginSection(Section::ANSWER());
     rrset = *rit;
     EXPECT_EQ(Name("example.com"), rrset->getName());
@@ -292,7 +282,8 @@
 }
 
 TEST_F(DataSrcTest, NxRRset) {
-    readAndProcessQuery("q_example_ptr");
+    createAndProcessQuery(Name("example.com"), RRClass::IN(),
+                          RRType::PTR());
 
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 0, 4, 0);
 
@@ -303,7 +294,8 @@
 }
 
 TEST_F(DataSrcTest, Nxdomain) {
-    readAndProcessQuery("q_glork");
+    createAndProcessQuery(Name("glork.example.com"), RRClass::IN(),
+                          RRType::A());
 
     headerCheck(msg, Rcode::NXDOMAIN(), true, true, true, 0, 6, 0);
 
@@ -316,7 +308,8 @@
 }
 
 TEST_F(DataSrcTest, NxZone) {
-    readAndProcessQuery("q_spork");
+    createAndProcessQuery(Name("spork.example"), RRClass::IN(),
+                          RRType::A());
 
     headerCheck(msg, Rcode::REFUSED(), true, false, true, 0, 0, 0);
 
@@ -327,7 +320,8 @@
 }
 
 TEST_F(DataSrcTest, Wildcard) {
-    readAndProcessQuery("q_wild_a");
+    createAndProcessQuery(Name("www.wild.example.com"), RRClass::IN(),
+                          RRType::A());
 
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 2, 6, 6);
 
@@ -380,17 +374,26 @@
 }
 
 TEST_F(DataSrcTest, WildcardNodata) {
-
     // Check that a query for a data type not covered by the wildcard
     // returns NOERROR
-    readAndProcessQuery("q_wild_aaaa");
+    createAndProcessQuery(Name("www.wild.example.com"), RRClass::IN(),
+                          RRType::AAAA());
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 0, 2, 0);
+}
+
+TEST_F(DataSrcTest, DISABLED_WildcardAgainstMultiLabel) {
+    // this qname shouldn't match *.wild.com.com (because * can only match
+    // a single label), and it should result in NXDOMAIN.
+    createAndProcessQuery(Name("www.xxx.wild.example.com"), RRClass::IN(),
+                          RRType::A());
+    headerCheck(msg, Rcode::NXDOMAIN(), true, true, true, 0, 1, 0);
 }
 
 TEST_F(DataSrcTest, WildcardCname) {
     // Check that wildcard answers containing CNAMES are followed
     // correctly
-    readAndProcessQuery("q_wild2_a");
+    createAndProcessQuery(Name("www.wild2.example.com"), RRClass::IN(),
+                          RRType::A());
 
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 6, 6);
 
@@ -458,7 +461,8 @@
 TEST_F(DataSrcTest, WildcardCnameNodata) {
     // A wildcard containing a CNAME whose target does not include
     // data of this type.
-    readAndProcessQuery("q_wild2_aaaa");
+    createAndProcessQuery(Name("www.wild2.example.com"), RRClass::IN(),
+                          RRType::AAAA());
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 2, 4, 0);
 
     RRsetIterator rit = msg.beginSection(Section::ANSWER());
@@ -489,7 +493,8 @@
 
 TEST_F(DataSrcTest, WildcardCnameNxdomain) {
     // A wildcard containing a CNAME whose target does not exist
-    readAndProcessQuery("q_wild3_a");
+    createAndProcessQuery(Name("www.wild3.example.com"), RRClass::IN(),
+                          RRType::A());
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 2, 6, 0);
 
     RRsetIterator rit = msg.beginSection(Section::ANSWER());
@@ -525,7 +530,8 @@
     EXPECT_EQ(RRClass::IN(), rrset->getClass());
 }
 TEST_F(DataSrcTest, AuthDelegation) {
-    readAndProcessQuery("q_sql1");
+    createAndProcessQuery(Name("www.sql1.example.com"), RRClass::IN(),
+                          RRType::A());
 
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 2, 4, 6);
 
@@ -571,7 +577,8 @@
 }
 
 TEST_F(DataSrcTest, Dname) {
-    readAndProcessQuery("q_dname");
+    createAndProcessQuery(Name("www.dname.example.com"), RRClass::IN(),
+                          RRType::A());
 
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 5, 4, 6);
 
@@ -628,7 +635,8 @@
 }
 
 TEST_F(DataSrcTest, Cname) {
-    readAndProcessQuery("q_cname");
+    createAndProcessQuery(Name("foo.example.com"), RRClass::IN(),
+                          RRType::A());
 
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 2, 0, 0);
 
@@ -646,7 +654,8 @@
 }
 
 TEST_F(DataSrcTest, CnameInt) {
-    readAndProcessQuery("q_cname_int");
+    createAndProcessQuery(Name("cname-int.example.com"), RRClass::IN(),
+                          RRType::A());
 
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 4, 6);
 
@@ -672,7 +681,8 @@
 }
 
 TEST_F(DataSrcTest, CnameExt) {
-    readAndProcessQuery("q_cname_ext");
+    createAndProcessQuery(Name("cname-ext.example.com"), RRClass::IN(),
+                          RRType::A());
 
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 4, 6);
 
@@ -696,7 +706,8 @@
 }
 
 TEST_F(DataSrcTest, Delegation) {
-    readAndProcessQuery("q_subzone");
+    createAndProcessQuery(Name("www.subzone.example.com"), RRClass::IN(),
+                          RRType::A());
 
     headerCheck(msg, Rcode::NOERROR(), true, false, true, 0, 5, 2);
 
@@ -726,7 +737,8 @@
 }
 
 TEST_F(DataSrcTest, NSDelegation) {
-    readAndProcessQuery("q_subzone_ns");
+    createAndProcessQuery(Name("subzone.example.com"), RRClass::IN(),
+                          RRType::NS());
 
     headerCheck(msg, Rcode::NOERROR(), true, false, true, 0, 5, 2);
 
@@ -758,12 +770,13 @@
 TEST_F(DataSrcTest, ANYZonecut) {
     // An ANY query at a zone cut should behave the same as any other
     // delegation
-    readAndProcessQuery("q_subzone_any");
-
+    createAndProcessQuery(Name("subzone.example.com"), RRClass::IN(),
+                          RRType::ANY());
 }
 
 TEST_F(DataSrcTest, NSECZonecut) {
-    readAndProcessQuery("q_subzone_nsec");
+    createAndProcessQuery(Name("subzone.example.com"), RRClass::IN(),
+                          RRType::NSEC());
 
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 2, 4, 6);
 
@@ -791,7 +804,8 @@
 }
 
 TEST_F(DataSrcTest, DNAMEZonecut) {
-    readAndProcessQuery("q_subzone_dname");
+    createAndProcessQuery(Name("subzone.example.com"), RRClass::IN(),
+                          RRType::DNAME());
 
     headerCheck(msg, Rcode::NOERROR(), true, false, true, 0, 5, 2);
     RRsetIterator rit = msg.beginSection(Section::AUTHORITY());
@@ -820,7 +834,8 @@
 }
 
 TEST_F(DataSrcTest, DS) {
-    readAndProcessQuery("q_subzone_ds");
+    createAndProcessQuery(Name("subzone.example.com"), RRClass::IN(),
+                          RRType::DS());
 
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 3, 4, 6);
 
@@ -1041,7 +1056,6 @@
     EXPECT_EQ(&datasrc1, match.getDataSource());
 }
 
-// This test currently fails.
 TEST_F(DataSrcMatchTest, initialUpdateWithNoMatch) {
     DataSrcMatch match(Name("www.example.com"), RRClass::IN());
 

Modified: branches/trac232/src/lib/datasrc/tests/query_unittest.cc
==============================================================================
--- branches/trac232/src/lib/datasrc/tests/query_unittest.cc (original)
+++ branches/trac232/src/lib/datasrc/tests/query_unittest.cc Wed Sep  1 00:35:07 2010
@@ -32,20 +32,13 @@
 
 namespace {
 
-class QueryTest : public ::testing::Test {
-protected:
-    void readQuery(Message& m, const char* datafile);
-
-    HotCache cache;
-};
-
 void
-QueryTest::readQuery(Message& m, const char* datafile) {
-    std::vector<unsigned char> data;
-    UnitTestUtil::readWireData(datafile, data);
-
-    InputBuffer buffer(&data[0], data.size());
-    m.fromWire(buffer);
+createQuery(Message& m, const Name& qname, const RRClass& qclass,
+            const RRType& qtype)
+{
+    m.setOpcode(Opcode::QUERY());
+    m.setHeaderFlag(MessageFlag::RD());
+    m.addQuestion(Question(qname, qclass, qtype));
 }
 
 QueryTaskPtr
@@ -58,15 +51,18 @@
 
 // Check the QueryTask created using a temporary RRType object will remain
 // valid.
-TEST_F(QueryTest, constructWithTemporary) {
-    Message m1(Message::PARSE);
-    readQuery(m1, "q_wild_a");
+TEST(QueryTest, constructWithTemporary) {
+    HotCache cache;
+
+    Message m1(Message::RENDER);
+    createQuery(m1, Name("www.wild.example.com"), RRClass::IN(), RRType::A()); 
     QueryTaskPtr task_a = createTask(m1, Name("www.wild.example.com"),
                                         RRType::A(), cache);
     EXPECT_EQ(RRType::A(), task_a->qtype);
 
-    Message m2(Message::PARSE);
-    readQuery(m2, "q_wild_aaaa");
+    Message m2(Message::RENDER);
+    createQuery(m2, Name("www.wild.example.com"), RRClass::IN(),
+                RRType::AAAA());
     QueryTaskPtr task_aaaa = createTask(m2, Name("www.wild.example.com"),
                                         RRType::AAAA(), cache);
     EXPECT_EQ(RRType::AAAA(), task_aaaa->qtype);

Modified: branches/trac232/src/lib/datasrc/tests/sqlite3_unittest.cc
==============================================================================
--- branches/trac232/src/lib/datasrc/tests/sqlite3_unittest.cc (original)
+++ branches/trac232/src/lib/datasrc/tests/sqlite3_unittest.cc Wed Sep  1 00:35:07 2010
@@ -44,15 +44,15 @@
 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:\"}");
 ElementPtr SQLITE_DBFILE_WRITE = Element::fromJSON(
     "{ \"database_file\": \"" TEST_DATA_OUT_DIR "/write_test.sqlite3\"}");
@@ -61,7 +61,7 @@
 // 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/trac232/src/lib/datasrc/tests/static_unittest.cc
==============================================================================
--- branches/trac232/src/lib/datasrc/tests/static_unittest.cc (original)
+++ branches/trac232/src/lib/datasrc/tests/static_unittest.cc Wed Sep  1 00:35:07 2010
@@ -18,7 +18,7 @@
 #include <string>
 #include <vector>
 
-#include "config.h"
+#include <config.h>
 
 #include <gtest/gtest.h>
 
@@ -54,6 +54,7 @@
         version_data.push_back(PACKAGE_STRING);
 
         // XXX: in addition, the order the following items matter.
+        authors_data.push_back("Chen Zhengzhang");
         authors_data.push_back("Evan Hunt");
         authors_data.push_back("Han Feng");
         authors_data.push_back("Jelte Jansen");
@@ -64,6 +65,8 @@
         authors_data.push_back("Michael Graff");
         authors_data.push_back("Naoki Kambe");
         authors_data.push_back("Shane Kerr");
+        authors_data.push_back("Shen Tingting");
+        authors_data.push_back("Stephen Morris");
         authors_data.push_back("Zhang Likun");
 
         version_ns_data.push_back("version.bind.");

Modified: branches/trac232/src/lib/datasrc/tests/test_datasrc.cc
==============================================================================
--- branches/trac232/src/lib/datasrc/tests/test_datasrc.cc (original)
+++ branches/trac232/src/lib/datasrc/tests/test_datasrc.cc Wed Sep  1 00:35:07 2010
@@ -14,14 +14,14 @@
 
 // $Id$
 
-#include "config.h"
+#include <config.h>
 
 #include <cassert>
 
 #include <algorithm>
 
 #include <dns/tests/unittest_util.h>
-#include "test_datasrc.h"
+#include <datasrc/tests/test_datasrc.h>
 
 #include <datasrc/data_source.h>
 
@@ -307,9 +307,8 @@
 }
 
 DataSrc::Result
-TestDataSrc::init(const isc::data::ElementPtr config UNUSED_PARAM)
-{
-    return init();
+TestDataSrc::init(isc::data::ConstElementPtr config UNUSED_PARAM) {
+    return (init());
 }
 
 void

Modified: branches/trac232/src/lib/datasrc/tests/test_datasrc.h
==============================================================================
--- branches/trac232/src/lib/datasrc/tests/test_datasrc.h (original)
+++ branches/trac232/src/lib/datasrc/tests/test_datasrc.h Wed Sep  1 00:35:07 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/trac232/src/lib/dns/Makefile.am
==============================================================================
--- branches/trac232/src/lib/dns/Makefile.am (original)
+++ branches/trac232/src/lib/dns/Makefile.am Wed Sep  1 00:35:07 2010
@@ -57,12 +57,14 @@
 
 lib_LTLIBRARIES = libdns++.la
 
-libdns___la_SOURCES = base32.h base32.cc
-libdns___la_SOURCES += base64.h base64.cc
+libdns___la_SOURCES = util/base32hex.h util/base64.h util/base_n.cc
+libdns___la_SOURCES += util/base32hex_from_binary.h
+libdns___la_SOURCES += util/binary_from_base32hex.h
+libdns___la_SOURCES += util/base16_from_binary.h util/binary_from_base16.h
 libdns___la_SOURCES += buffer.h
 libdns___la_SOURCES += dnssectime.h dnssectime.cc
 libdns___la_SOURCES += exceptions.h exceptions.cc
-libdns___la_SOURCES += hex.h hex.cc
+libdns___la_SOURCES += util/hex.h
 libdns___la_SOURCES += message.h message.cc
 libdns___la_SOURCES += messagerenderer.h messagerenderer.cc
 libdns___la_SOURCES += name.h name.cc
@@ -74,7 +76,7 @@
 libdns___la_SOURCES += rrttl.h rrttl.cc
 libdns___la_SOURCES += rrtype.cc
 libdns___la_SOURCES += question.h question.cc
-libdns___la_SOURCES += sha1.h sha1.cc
+libdns___la_SOURCES += util/sha1.h util/sha1.cc
 libdns___la_SOURCES += tsig.h tsig.cc
 
 nodist_libdns___la_SOURCES = rdataclass.cc rrclass.h rrtype.h
@@ -105,9 +107,6 @@
 	rrtype.h \
 	tsig.h
 # Purposely not installing these headers:
-# base32.h # used only internally, and not actually DNS specific
-# base64.h # used only internally, and not actually DNS specific
-# hex.h # used only internally, and not actually DNS specific
-# sha1.h # used only internally, and not actually DNS specific
+# util/*.h: used only internally, and not actually DNS specific
 # rrclass-placeholder.h
 # rrtype-placeholder.h

Modified: branches/trac232/src/lib/dns/message.h
==============================================================================
--- branches/trac232/src/lib/dns/message.h (original)
+++ branches/trac232/src/lib/dns/message.h Wed Sep  1 00:35:07 2010
@@ -80,7 +80,7 @@
 class InputBuffer;
 class MessageRenderer;
 class Message;
-struct MessageImpl;
+class MessageImpl;
 
 template <typename T>
 struct SectionIteratorImpl;

Modified: branches/trac232/src/lib/dns/messagerenderer.h
==============================================================================
--- branches/trac232/src/lib/dns/messagerenderer.h (original)
+++ branches/trac232/src/lib/dns/messagerenderer.h Wed Sep  1 00:35:07 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/trac232/src/lib/dns/name.h
==============================================================================
--- branches/trac232/src/lib/dns/name.h (original)
+++ branches/trac232/src/lib/dns/name.h Wed Sep  1 00:35:07 2010
@@ -406,7 +406,7 @@
     /// This method simply negates the result of \c equal() method, and in that
     /// sense it's redundant.  The separate method is provided just for
     /// convenience.
-    bool nequals(const Name& other) const { return !(equals(other)); }
+    bool nequals(const Name& other) const { return (!(equals(other))); }
 
     /// Same as nequals()
     bool operator!=(const Name& other) const { return (nequals(other)); }

Modified: branches/trac232/src/lib/dns/python/Makefile.am
==============================================================================
--- branches/trac232/src/lib/dns/python/Makefile.am (original)
+++ branches/trac232/src/lib/dns/python/Makefile.am Wed Sep  1 00:35:07 2010
@@ -1,9 +1,7 @@
 SUBDIRS = tests
 
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
-if USE_GXX
-AM_CPPFLAGS += -Wno-write-strings
-endif
+AM_CXXFLAGS = $(B10_CXXFLAGS)
 
 #lib_LTLIBRARIES = libdns_python_name.la libdns_python_rrset.la
 #libdns_python_name_la_SOURCES = name_python.cc

Modified: branches/trac232/src/lib/dns/python/libdns_python.cc
==============================================================================
--- branches/trac232/src/lib/dns/python/libdns_python.cc (original)
+++ branches/trac232/src/lib/dns/python/libdns_python.cc Wed Sep  1 00:35:07 2010
@@ -23,11 +23,13 @@
 //
 // And of course care has to be taken that all identifiers be unique
 
+// $Id$
+
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
 #include <structmember.h>
 
-#include "config.h"
+#include <config.h>
 
 #include <exceptions/exceptions.h>
 
@@ -36,22 +38,22 @@
 #include <dns/name.h>
 #include <dns/messagerenderer.h>
 
-#include "libdns_python_common.h"
+#include <dns/python/libdns_python_common.h>
 
 // For our 'general' isc::Exception
 static PyObject* po_IscException;
 
 // order is important here!
-#include "messagerenderer_python.cc"
-#include "name_python.cc"           // needs Messagerenderer
-#include "rrclass_python.cc"        // needs Messagerenderer
-#include "rrtype_python.cc"         // needs Messagerenderer
-#include "rrttl_python.cc"          // needs Messagerenderer
-#include "rdata_python.cc"          // needs Type, Class
-#include "rrset_python.cc"          // needs Rdata, RRTTL
-#include "question_python.cc"       // needs RRClass, RRType, RRTTL,
-                                    //       Name
-#include "message_python.cc"        // needs RRset, Question
+#include <dns/python/messagerenderer_python.cc>
+#include <dns/python/name_python.cc>           // needs Messagerenderer
+#include <dns/python/rrclass_python.cc>        // needs Messagerenderer
+#include <dns/python/rrtype_python.cc>         // needs Messagerenderer
+#include <dns/python/rrttl_python.cc>          // needs Messagerenderer
+#include <dns/python/rdata_python.cc>          // needs Type, Class
+#include <dns/python/rrset_python.cc>          // needs Rdata, RRTTL
+#include <dns/python/question_python.cc>       // needs RRClass, RRType, RRTTL,
+                                               // Name
+#include <dns/python/message_python.cc>        // needs RRset, Question
 
 //
 // Definition of the module

Modified: branches/trac232/src/lib/dns/python/message_python.cc
==============================================================================
--- branches/trac232/src/lib/dns/python/message_python.cc (original)
+++ branches/trac232/src/lib/dns/python/message_python.cc Wed Sep  1 00:35:07 2010
@@ -12,7 +12,7 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-// $Id: message_python.cc 1711 2010-04-14 15:14:53Z jelte $
+// $Id$
 
 #include <dns/message.h>
 using namespace isc::dns;
@@ -326,9 +326,9 @@
 static PyObject*
 Opcode_str(PyObject* self) {
     // Simply call the to_text method we already defined
-    return PyObject_CallMethod(self,
+    return (PyObject_CallMethod(self,
                                const_cast<char*>("to_text"),
-                               const_cast<char*>(""));
+                                const_cast<char*>("")));
 }
 
 static PyObject*
@@ -589,7 +589,7 @@
         try {
             self->rcode = new Rcode(code);
             self->static_code = false;
-        } catch (isc::OutOfRange) {
+        } catch (const isc::OutOfRange&) {
             PyErr_SetString(PyExc_OverflowError,
                             "rcode out of range");
             return (-1);
@@ -624,9 +624,9 @@
 static PyObject*
 Rcode_str(PyObject* self) {
     // Simply call the to_text method we already defined
-    return PyObject_CallMethod(self,
+    return (PyObject_CallMethod(self,
                                const_cast<char*>("to_text"),
-                               const_cast<char*>(""));
+                                const_cast<char*>("")));
 }
 
 static PyObject*
@@ -886,22 +886,22 @@
 
 static PyObject*
 Section_QUESTION(s_Section* self UNUSED_PARAM) {
-    return Section_createStatic(Section::QUESTION());
+    return (Section_createStatic(Section::QUESTION()));
 }
 
 static PyObject*
 Section_ANSWER(s_Section* self UNUSED_PARAM) {
-    return Section_createStatic(Section::ANSWER());
+    return (Section_createStatic(Section::ANSWER()));
 }
 
 static PyObject*
 Section_AUTHORITY(s_Section* self UNUSED_PARAM) {
-    return Section_createStatic(Section::AUTHORITY());
+    return (Section_createStatic(Section::AUTHORITY()));
 }
 
 static PyObject*
 Section_ADDITIONAL(s_Section* self UNUSED_PARAM) {
-    return Section_createStatic(Section::ADDITIONAL());
+    return (Section_createStatic(Section::ADDITIONAL()));
 }
 
 static PyObject* 
@@ -1192,8 +1192,7 @@
 
 static void
 Message_destroy(s_Message* self) {
-    if (self->message != NULL)
-        delete self->message;
+    delete self->message;
     self->message = NULL;
     Py_TYPE(self)->tp_free(self);
 }
@@ -1222,7 +1221,7 @@
     try {
         self->message->setHeaderFlag(*messageflag->messageflag);
         Py_RETURN_NONE;
-    } catch (isc::dns::InvalidMessageOperation imo) {
+    } catch (const InvalidMessageOperation& imo) {
         PyErr_Clear();
         PyErr_SetString(po_InvalidMessageOperation, imo.what());
         return (NULL);
@@ -1239,7 +1238,7 @@
     try {
         self->message->clearHeaderFlag(*messageflag->messageflag);
         Py_RETURN_NONE;
-    } catch (isc::dns::InvalidMessageOperation imo) {
+    } catch (const InvalidMessageOperation& imo) {
         PyErr_Clear();
         PyErr_SetString(po_InvalidMessageOperation, imo.what());
         return (NULL);
@@ -1270,7 +1269,7 @@
             self->message->setDNSSECSupported(false);
         }
         Py_RETURN_NONE;
-    } catch (isc::dns::InvalidMessageOperation imo) {
+    } catch (const InvalidMessageOperation& imo) {
         PyErr_SetString(po_InvalidMessageOperation, imo.what());
         return (NULL);
     }
@@ -1290,10 +1289,10 @@
     try {
         self->message->setUDPSize(size);
         Py_RETURN_NONE;
-    } catch (isc::dns::InvalidMessageUDPSize imus) {
+    } catch (const InvalidMessageUDPSize& imus) {
         PyErr_SetString(po_InvalidMessageUDPSize, imus.what());
         return (NULL);
-    } catch (isc::dns::InvalidMessageOperation imo) {
+    } catch (const InvalidMessageOperation& imo) {
         PyErr_SetString(po_InvalidMessageOperation, imo.what());
         return (NULL);
     }
@@ -1313,7 +1312,7 @@
     try {
         self->message->setQid(id);
         Py_RETURN_NONE;
-    } catch (InvalidMessageOperation imo) {
+    } catch (const InvalidMessageOperation& imo) {
         PyErr_SetString(po_InvalidMessageOperation, imo.what());
         return (NULL);
     }
@@ -1345,7 +1344,7 @@
     try {
         self->message->setRcode(*rcode->rcode);
         Py_RETURN_NONE;
-    } catch (InvalidMessageOperation imo) {
+    } catch (const InvalidMessageOperation& imo) {
         PyErr_SetString(po_InvalidMessageOperation, imo.what());
         return (NULL);
     }
@@ -1380,7 +1379,7 @@
     try {
         self->message->setOpcode(*opcode->opcode);
         Py_RETURN_NONE;
-    } catch (InvalidMessageOperation imo) {
+    } catch (const InvalidMessageOperation& imo) {
         PyErr_SetString(po_InvalidMessageOperation, imo.what());
         return (NULL);
     }
@@ -1483,7 +1482,7 @@
             self->message->addRRset(*section->section, rrset->rrset, false);
         }
         Py_RETURN_NONE;
-    } catch (InvalidMessageOperation imo) {
+    } catch (const InvalidMessageOperation& imo) {
         PyErr_SetString(po_InvalidMessageOperation, imo.what());
         return (NULL);
     }
@@ -1527,9 +1526,9 @@
 static PyObject*
 Message_str(PyObject* self) {
     // Simply call the to_text method we already defined
-    return PyObject_CallMethod(self,
+    return (PyObject_CallMethod(self,
                                const_cast<char*>("to_text"),
-                               const_cast<char*>(""));
+                                const_cast<char*>("")));
 }
 
 static PyObject*
@@ -1542,7 +1541,7 @@
             // If we return NULL it is seen as an error, so use this for
             // None returns
             Py_RETURN_NONE;
-        } catch (isc::dns::InvalidMessageOperation imo) {
+        } catch (const InvalidMessageOperation& imo) {
             PyErr_Clear();
             PyErr_SetString(po_InvalidMessageOperation, imo.what());
             return (NULL);
@@ -1566,16 +1565,16 @@
     try {
         self->message->fromWire(inbuf);
         Py_RETURN_NONE;
-    } catch (isc::dns::InvalidMessageOperation imo) {
+    } catch (const InvalidMessageOperation& imo) {
         PyErr_SetString(po_InvalidMessageOperation, imo.what());
         return (NULL);
-    } catch (isc::dns::DNSMessageFORMERR dmfe) {
+    } catch (const DNSMessageFORMERR& dmfe) {
         PyErr_SetString(po_DNSMessageFORMERR, dmfe.what());
         return (NULL);
-    } catch (isc::dns::DNSMessageBADVERS dmfe) {
+    } catch (const DNSMessageBADVERS& dmfe) {
         PyErr_SetString(po_DNSMessageBADVERS, dmfe.what());
         return (NULL);
-    } catch (isc::dns::MessageTooShort mts) {
+    } catch (const MessageTooShort& mts) {
         PyErr_SetString(po_MessageTooShort, mts.what());
         return (NULL);
     }

Modified: branches/trac232/src/lib/dns/python/messagerenderer_python.cc
==============================================================================
--- branches/trac232/src/lib/dns/python/messagerenderer_python.cc (original)
+++ branches/trac232/src/lib/dns/python/messagerenderer_python.cc Wed Sep  1 00:35:07 2010
@@ -133,9 +133,9 @@
 
 static PyObject*
 MessageRenderer_getData(s_MessageRenderer* self) {
-    return Py_BuildValue("y#",
+    return (Py_BuildValue("y#",
                          self->messagerenderer->getData(),
-                         self->messagerenderer->getLength());
+                          self->messagerenderer->getLength()));
 }
 
 static PyObject*

Modified: branches/trac232/src/lib/dns/python/name_python.cc
==============================================================================
--- branches/trac232/src/lib/dns/python/name_python.cc (original)
+++ branches/trac232/src/lib/dns/python/name_python.cc Wed Sep  1 00:35:07 2010
@@ -291,26 +291,26 @@
 
             self->name = new Name(n, downcase == Py_True);
             self->position = 0;
-        } catch (EmptyLabel) {
+        } catch (const EmptyLabel&) {
             PyErr_SetString(po_EmptyLabel, "EmptyLabel");
             return (-1);
-        } catch (TooLongLabel) {
+        } catch (const TooLongLabel&) {
             PyErr_SetString(po_TooLongLabel, "TooLongLabel");
             return (-1);
-        } catch (BadLabelType) {
+        } catch (const BadLabelType&) {
             PyErr_SetString(po_BadLabelType, "BadLabelType");
             return (-1);
-        } catch (BadEscape) {
+        } catch (const BadEscape&) {
             PyErr_SetString(po_BadEscape, "BadEscape");
             return (-1);
-        } catch (TooLongName) {
+        } catch (const TooLongName&) {
             PyErr_SetString(po_TooLongName, "TooLongName");
             return (-1);
-        } catch (IncompleteName) {
+        } catch (const IncompleteName&) {
             PyErr_SetString(po_IncompleteName, "IncompleteName");
             return (-1);
 #ifdef CATCHMEMERR
-        } catch (std::bad_alloc) {
+        } catch (const std::bad_alloc&) {
             PyErr_NoMemory();
             return (-1);
 #endif
@@ -338,11 +338,11 @@
             buffer.setPosition(position);
             self->name = new Name(buffer, downcase == Py_True);
             self->position = buffer.getPosition();
-        } catch (InvalidBufferPosition) {
+        } catch (const InvalidBufferPosition&) {
             PyErr_SetString(po_InvalidBufferPosition,
                             "InvalidBufferPosition");
             return (-1);
-        } catch (DNSMessageFORMERR) {
+        } catch (const DNSMessageFORMERR&) {
             PyErr_SetString(po_DNSMessageFORMERR, "DNSMessageFORMERR");
             return (-1);
         } catch (...) {
@@ -373,7 +373,7 @@
     }
     try {
         return (Py_BuildValue("I", self->name->at(pos)));
-    } catch (isc::OutOfRange oor) {
+    } catch (const isc::OutOfRange&) {
         PyErr_SetString(PyExc_IndexError,
                         "name index out of range");
         return (NULL);
@@ -400,9 +400,9 @@
     // Simply call the to_text method we already defined
     // str() is not defined in the c++ version, only to_text
     // and we already have a wrapper for that one.
-    return PyObject_CallMethod(self,
+    return (PyObject_CallMethod(self,
                                const_cast<char*>("to_text"),
-                               const_cast<char*>(""));
+                                const_cast<char*>("")));
 }
 
 static PyObject*
@@ -472,7 +472,7 @@
             ret->name = NULL;
             try {
                 ret->name = new Name(self->name->split(first, n));
-            } catch(isc::OutOfRange oor) {
+            } catch(const isc::OutOfRange& oor) {
                 PyErr_SetString(PyExc_IndexError, oor.what());
                 ret->name = NULL;
             }
@@ -487,7 +487,7 @@
             ret->name = NULL;
             try {
                 ret->name = new Name(self->name->split(n));
-            } catch(isc::OutOfRange oor) {
+            } catch(const isc::OutOfRange& oor) {
                 PyErr_SetString(PyExc_IndexError, oor.what());
                 ret->name = NULL;
             }
@@ -572,7 +572,7 @@
     if (ret != NULL) {
         try {
             ret->name = new Name(self->name->concatenate(*other->name));
-        } catch (isc::dns::TooLongName tln) {
+        } catch (const TooLongName& tln) {
             PyErr_SetString(po_TooLongName, tln.what());
             return (NULL);
         }

Modified: branches/trac232/src/lib/dns/python/question_python.cc
==============================================================================
--- branches/trac232/src/lib/dns/python/question_python.cc (original)
+++ branches/trac232/src/lib/dns/python/question_python.cc Wed Sep  1 00:35:07 2010
@@ -156,15 +156,15 @@
             self->question = QuestionPtr(new Question(inbuf));
             return (0);
         }
-    } catch (isc::dns::DNSMessageFORMERR dmfe) {
+    } catch (const DNSMessageFORMERR& dmfe) {
         PyErr_Clear();
         PyErr_SetString(po_DNSMessageFORMERR, dmfe.what());
         return (-1);
-    } catch (isc::dns::IncompleteRRClass irc) {
+    } catch (const IncompleteRRClass& irc) {
         PyErr_Clear();
         PyErr_SetString(po_IncompleteRRClass, irc.what());
         return (-1);
-    } catch (isc::dns::IncompleteRRType irt) {
+    } catch (const IncompleteRRType& irt) {
         PyErr_Clear();
         PyErr_SetString(po_IncompleteRRType, irt.what());
         return (-1);
@@ -231,9 +231,9 @@
 static PyObject*
 Question_str(PyObject* self) {
     // Simply call the to_text method we already defined
-    return PyObject_CallMethod(self,
+    return (PyObject_CallMethod(self,
                                const_cast<char*>("to_text"),
-                               const_cast<char*>(""));
+                                const_cast<char*>("")));
 }
 
 static PyObject*

Modified: branches/trac232/src/lib/dns/python/rdata_python.cc
==============================================================================
--- branches/trac232/src/lib/dns/python/rdata_python.cc (original)
+++ branches/trac232/src/lib/dns/python/rdata_python.cc Wed Sep  1 00:35:07 2010
@@ -174,9 +174,9 @@
 static PyObject*
 Rdata_str(PyObject* self) {
     // Simply call the to_text method we already defined
-    return PyObject_CallMethod(self,
+    return (PyObject_CallMethod(self,
                                const_cast<char*>("to_text"),
-                               const_cast<char*>(""));
+                                const_cast<char*>("")));
 }
 
 static PyObject*

Modified: branches/trac232/src/lib/dns/python/rrclass_python.cc
==============================================================================
--- branches/trac232/src/lib/dns/python/rrclass_python.cc (original)
+++ branches/trac232/src/lib/dns/python/rrclass_python.cc Wed Sep  1 00:35:07 2010
@@ -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);
@@ -188,7 +188,7 @@
         }
     // Incomplete is never thrown, a type error would have already been raised
     //when we try to read the 2 bytes above
-    } catch (InvalidRRClass ic) {
+    } catch (const InvalidRRClass& ic) {
         PyErr_Clear();
         PyErr_SetString(po_InvalidRRClass, ic.what());
         return (-1);
@@ -201,8 +201,7 @@
 
 static void
 RRClass_destroy(s_RRClass* self) {
-    if (self->rrclass != NULL)
-        delete self->rrclass;
+    delete self->rrclass;
     self->rrclass = NULL;
     Py_TYPE(self)->tp_free(self);
 }
@@ -216,9 +215,9 @@
 static PyObject*
 RRClass_str(PyObject* self) {
     // Simply call the to_text method we already defined
-    return PyObject_CallMethod(self,
+    return (PyObject_CallMethod(self,
                                const_cast<char*>("to_text"),
-                               const_cast<char*>(""));
+                                const_cast<char*>("")));
 }
 
 static PyObject*

Modified: branches/trac232/src/lib/dns/python/rrset_python.cc
==============================================================================
--- branches/trac232/src/lib/dns/python/rrset_python.cc (original)
+++ branches/trac232/src/lib/dns/python/rrset_python.cc Wed Sep  1 00:35:07 2010
@@ -284,7 +284,7 @@
 RRset_toText(s_RRset* self) {
     try {
         return (Py_BuildValue("s", self->rrset->toText().c_str()));
-    } catch (EmptyRRset ers) {
+    } catch (const EmptyRRset& ers) {
         PyErr_SetString(po_EmptyRRset, ers.what());
         return (NULL);
     }
@@ -293,9 +293,9 @@
 static PyObject*
 RRset_str(PyObject* self) {
     // Simply call the to_text method we already defined
-    return PyObject_CallMethod(self,
+    return (PyObject_CallMethod(self,
                                const_cast<char*>("to_text"),
-                               const_cast<char*>(""));
+                                const_cast<char*>("")));
 }
 
 static PyObject*
@@ -321,7 +321,7 @@
             // None returns
             Py_RETURN_NONE;
         }
-    } catch (EmptyRRset ers) {
+    } catch (const EmptyRRset& ers) {
         PyErr_Clear();
         PyErr_SetString(po_EmptyRRset, ers.what());
         return (NULL);
@@ -341,7 +341,7 @@
     try {
         self->rrset->addRdata(*rdata->rdata);
         Py_RETURN_NONE;
-    } catch (std::bad_cast) {
+    } catch (const std::bad_cast&) {
         PyErr_Clear();
         PyErr_SetString(PyExc_TypeError,
                         "Rdata type to add must match type of RRset");

Modified: branches/trac232/src/lib/dns/python/rrttl_python.cc
==============================================================================
--- branches/trac232/src/lib/dns/python/rrttl_python.cc (original)
+++ branches/trac232/src/lib/dns/python/rrttl_python.cc Wed Sep  1 00:35:07 2010
@@ -177,7 +177,7 @@
             PyErr_Clear();
             return (0);
         }
-    } catch (IncompleteRRTTL icc) {
+    } catch (const IncompleteRRTTL& icc) {
         // Ok so one of our functions has thrown a C++ exception.
         // We need to translate that to a Python Exception
         // First clear any existing error that was set
@@ -186,7 +186,7 @@
         PyErr_SetString(po_IncompleteRRTTL, icc.what());
         // And return negative
         return (-1);
-    } catch (InvalidRRTTL ic) {
+    } catch (const InvalidRRTTL& ic) {
         PyErr_Clear();
         PyErr_SetString(po_InvalidRRTTL, ic.what());
         return (-1);
@@ -199,8 +199,7 @@
 
 static void
 RRTTL_destroy(s_RRTTL* self) {
-    if (self->rrttl != NULL)
-        delete self->rrttl;
+    delete self->rrttl;
     self->rrttl = NULL;
     Py_TYPE(self)->tp_free(self);
 }
@@ -214,9 +213,9 @@
 static PyObject*
 RRTTL_str(PyObject* self) {
     // Simply call the to_text method we already defined
-    return PyObject_CallMethod(self,
+    return (PyObject_CallMethod(self,
                                const_cast<char*>("to_text"),
-                               const_cast<char*>(""));
+                                const_cast<char*>("")));
 }
 
 static PyObject*

Modified: branches/trac232/src/lib/dns/python/rrtype_python.cc
==============================================================================
--- branches/trac232/src/lib/dns/python/rrtype_python.cc (original)
+++ branches/trac232/src/lib/dns/python/rrtype_python.cc Wed Sep  1 00:35:07 2010
@@ -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);
@@ -217,7 +217,7 @@
             PyErr_Clear();
             return (0);
         }
-    } catch (IncompleteRRType icc) {
+    } catch (const IncompleteRRType& icc) {
         // Ok so one of our functions has thrown a C++ exception.
         // We need to translate that to a Python Exception
         // First clear any existing error that was set
@@ -226,7 +226,7 @@
         PyErr_SetString(po_IncompleteRRType, icc.what());
         // And return negative
         return (-1);
-    } catch (InvalidRRType ic) {
+    } catch (const InvalidRRType& ic) {
         PyErr_Clear();
         PyErr_SetString(po_InvalidRRType, ic.what());
         return (-1);
@@ -239,8 +239,7 @@
 
 static void
 RRType_destroy(s_RRType* self) {
-    if (self->rrtype != NULL)
-        delete self->rrtype;
+    delete self->rrtype;
     self->rrtype = NULL;
     Py_TYPE(self)->tp_free(self);
 }
@@ -254,8 +253,8 @@
 static PyObject*
 RRType_str(PyObject* self) {
     // Simply call the to_text method we already defined
-    return PyObject_CallMethod(self, const_cast<char*>("to_text"),
-                                     const_cast<char*>(""));
+    return (PyObject_CallMethod(self, const_cast<char*>("to_text"),
+                                const_cast<char*>("")));
 }
 
 static PyObject*

Modified: branches/trac232/src/lib/dns/python/tests/Makefile.am
==============================================================================
--- branches/trac232/src/lib/dns/python/tests/Makefile.am (original)
+++ branches/trac232/src/lib/dns/python/tests/Makefile.am Wed Sep  1 00:35:07 2010
@@ -10,6 +10,13 @@
 
 EXTRA_DIST = $(PYTESTS)
 
+# If necessary (rare cases), explicitly specify paths to dynamic libraries
+# required by loadable python modules.
+LIBRARY_PATH_PLACEHOLDER =
+if SET_ENV_LIBRARY_PATH
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
+endif
+
 # later will have configure option to choose this, like: coverage run --branch
 PYCOVERAGE = $(PYTHON)
 # test using command-line arguments, so use check-local target instead of TESTS
@@ -18,5 +25,6 @@
 	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 \
 	TESTDATA_PATH=$(abs_top_srcdir)/src/lib/dns/tests/testdata \
-	$(PYCOVERAGE) $(abs_srcdir)/$$pytest ; \
+	$(LIBRARY_PATH_PLACEHOLDER) \
+	$(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
 	done

Modified: branches/trac232/src/lib/dns/python/tests/rrset_python_test.py
==============================================================================
--- branches/trac232/src/lib/dns/python/tests/rrset_python_test.py (original)
+++ branches/trac232/src/lib/dns/python/tests/rrset_python_test.py Wed Sep  1 00:35:07 2010
@@ -87,7 +87,8 @@
                          "test.example.com. 3600 IN A 192.0.2.2\n",
                          str(self.rrset_a));
 
-        self.assertRaises(EmptyRRset, self.rrset_a_empty.to_text)
+        # TODO re-enable? or is this now obsolete as a test case
+        #self.assertRaises(EmptyRRset, self.rrset_a_empty.to_text)
 
     def test_to_wire_buffer(self):
         exp_buffer = bytearray(b'\x04test\x07example\x03com\x00\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xc0\x00\x02\x01\x04test\x07example\x03com\x00\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xc0\x00\x02\x02')
@@ -95,7 +96,8 @@
         self.rrset_a.to_wire(buffer)
         self.assertEqual(exp_buffer, buffer)
 
-        self.assertRaises(EmptyRRset, self.rrset_a_empty.to_wire, buffer);
+        # TODO re-enable? or is this now obsolete as a test case
+        #self.assertRaises(EmptyRRset, self.rrset_a_empty.to_wire, buffer);
         self.assertRaises(TypeError, self.rrset_a.to_wire, 1)
 
     def test_to_wire_renderer(self):

Modified: branches/trac232/src/lib/dns/rdata/generic/dnskey_48.cc
==============================================================================
--- branches/trac232/src/lib/dns/rdata/generic/dnskey_48.cc (original)
+++ branches/trac232/src/lib/dns/rdata/generic/dnskey_48.cc Wed Sep  1 00:35:07 2010
@@ -22,7 +22,7 @@
 #include <boost/lexical_cast.hpp>
 #include <boost/foreach.hpp>
 
-#include <dns/base64.h>
+#include <dns/util/base64.h>
 #include <dns/buffer.h>
 #include <dns/messagerenderer.h>
 #include <dns/name.h>

Modified: branches/trac232/src/lib/dns/rdata/generic/ds_43.cc
==============================================================================
--- branches/trac232/src/lib/dns/rdata/generic/ds_43.cc (original)
+++ branches/trac232/src/lib/dns/rdata/generic/ds_43.cc Wed Sep  1 00:35:07 2010
@@ -22,7 +22,7 @@
 #include <boost/lexical_cast.hpp>
 
 #include <dns/buffer.h>
-#include <dns/hex.h>
+#include <dns/util/hex.h>
 #include <dns/messagerenderer.h>
 #include <dns/name.h>
 #include <dns/rdata.h>
@@ -173,7 +173,7 @@
 
 uint16_t
 DS::getTag() const {
-    return impl_->tag_;
+    return (impl_->tag_);
 }
 
 // END_RDATA_NAMESPACE

Modified: branches/trac232/src/lib/dns/rdata/generic/nsec3_50.cc
==============================================================================
--- branches/trac232/src/lib/dns/rdata/generic/nsec3_50.cc (original)
+++ branches/trac232/src/lib/dns/rdata/generic/nsec3_50.cc Wed Sep  1 00:35:07 2010
@@ -22,10 +22,10 @@
 
 #include <boost/lexical_cast.hpp>
 
-#include <dns/base32.h>
+#include <dns/util/base32hex.h>
 #include <dns/buffer.h>
 #include <dns/exceptions.h>
-#include <dns/hex.h>
+#include <dns/util/hex.h>
 #include <dns/messagerenderer.h>
 #include <dns/name.h>
 #include <dns/rrtype.h>
@@ -88,7 +88,7 @@
     if (iss.bad() || iss.fail()) {
         isc_throw(InvalidRdataText, "Invalid NSEC3 hash algorithm");
     }
-    decodeBase32(nextstr, next);
+    decodeBase32Hex(nextstr, next);
 
     uint8_t bitmap[8 * 1024];       // 64k bits
     vector<uint8_t> typebits;
@@ -237,7 +237,7 @@
         " " + lexical_cast<string>(static_cast<int>(impl_->flags_)) +
         " " + lexical_cast<string>(static_cast<int>(impl_->iterations_)) +
         " " + encodeHex(impl_->salt_) +
-        " " + encodeBase32(impl_->next_) + s.str());
+        " " + encodeBase32Hex(impl_->next_) + s.str());
 }
 
 void
@@ -323,22 +323,22 @@
 
 uint8_t
 NSEC3::getHashalg() const {
-    return impl_->hashalg_;
+    return (impl_->hashalg_);
 }
 
 uint8_t
 NSEC3::getFlags() const {
-    return impl_->flags_;
+    return (impl_->flags_);
 }
 
 uint16_t
 NSEC3::getIterations() const {
-    return impl_->iterations_;
+    return (impl_->iterations_);
 }
 
 vector<uint8_t>&
 NSEC3::getSalt() const {
-    return impl_->salt_;
+    return (impl_->salt_);
 }
 
 // END_RDATA_NAMESPACE

Modified: branches/trac232/src/lib/dns/rdata/generic/nsec3param_51.cc
==============================================================================
--- branches/trac232/src/lib/dns/rdata/generic/nsec3param_51.cc (original)
+++ branches/trac232/src/lib/dns/rdata/generic/nsec3param_51.cc Wed Sep  1 00:35:07 2010
@@ -22,7 +22,7 @@
 #include <boost/lexical_cast.hpp>
 
 #include <dns/buffer.h>
-#include <dns/hex.h>
+#include <dns/util/hex.h>
 #include <dns/messagerenderer.h>
 #include <dns/name.h>
 #include <dns/rdata.h>

Modified: branches/trac232/src/lib/dns/rdata/generic/nsec_47.cc
==============================================================================
--- branches/trac232/src/lib/dns/rdata/generic/nsec_47.cc (original)
+++ branches/trac232/src/lib/dns/rdata/generic/nsec_47.cc Wed Sep  1 00:35:07 2010
@@ -19,7 +19,7 @@
 #include <sstream>
 #include <vector>
 
-#include <dns/base64.h>
+#include <dns/util/base64.h>
 #include <dns/buffer.h>
 #include <dns/exceptions.h>
 #include <dns/messagerenderer.h>

Modified: branches/trac232/src/lib/dns/rdata/generic/rrsig_46.cc
==============================================================================
--- branches/trac232/src/lib/dns/rdata/generic/rrsig_46.cc (original)
+++ branches/trac232/src/lib/dns/rdata/generic/rrsig_46.cc Wed Sep  1 00:35:07 2010
@@ -22,7 +22,7 @@
 
 #include <boost/lexical_cast.hpp>
 
-#include <dns/base64.h>
+#include <dns/util/base64.h>
 #include <dns/buffer.h>
 #include <dns/dnssectime.h>
 #include <dns/messagerenderer.h>

Modified: branches/trac232/src/lib/dns/rdata/generic/txt_16.cc
==============================================================================
--- branches/trac232/src/lib/dns/rdata/generic/txt_16.cc (original)
+++ branches/trac232/src/lib/dns/rdata/generic/txt_16.cc Wed Sep  1 00:35:07 2010
@@ -21,6 +21,7 @@
 #include <vector>
 
 #include <dns/buffer.h>
+#include <dns/exceptions.h>
 #include <dns/messagerenderer.h>
 #include <dns/rdata.h>
 #include <dns/rdataclass.h>

Modified: branches/trac232/src/lib/dns/rrsetlist.cc
==============================================================================
--- branches/trac232/src/lib/dns/rrsetlist.cc (original)
+++ branches/trac232/src/lib/dns/rrsetlist.cc Wed Sep  1 00:35:07 2010
@@ -68,10 +68,10 @@
     BOOST_FOREACH(RRsetPtr rrsetptr, rrsets_) {
         if ((rrsetptr->getClass() == rrclass) &&
             (rrsetptr->getType() == rrtype)) {
-            return rrsetptr;
+            return (rrsetptr);
         }
     }
-    return RRsetPtr();
+    return (RRsetPtr());
 }
 
 }

Modified: branches/trac232/src/lib/dns/rrtype-placeholder.h
==============================================================================
--- branches/trac232/src/lib/dns/rrtype-placeholder.h (original)
+++ branches/trac232/src/lib/dns/rrtype-placeholder.h Wed Sep  1 00:35:07 2010
@@ -221,7 +221,7 @@
     bool equals(const RRType& other) const
     { return (typecode_ == other.typecode_); }
     /// \brief Same as \c equals().
-    bool operator==(const RRType& other) const { return equals(other); }
+    bool operator==(const RRType& other) const { return (equals(other)); }
 
     /// \brief Return true iff two RRTypes are equal.
     ///
@@ -232,7 +232,7 @@
     bool nequals(const RRType& other) const 
     { return (typecode_ != other.typecode_); }
     /// \brief Same as \c nequals().
-    bool operator!=(const RRType& other) const { return nequals(other); }
+    bool operator!=(const RRType& other) const { return (nequals(other)); }
  
     /// \brief Less-than comparison for RRType against \c other
     ///

Modified: branches/trac232/src/lib/dns/tests/Makefile.am
==============================================================================
--- branches/trac232/src/lib/dns/tests/Makefile.am (original)
+++ branches/trac232/src/lib/dns/tests/Makefile.am Wed Sep  1 00:35:07 2010
@@ -2,6 +2,10 @@
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
 AM_CPPFLAGS += -DTEST_DATA_DIR=\"$(srcdir)/testdata\"
 AM_CXXFLAGS = $(B10_CXXFLAGS)
+
+if USE_STATIC_LINK
+AM_LDFLAGS = -static
+endif
 
 CLEANFILES = *.gcno *.gcda
 
@@ -31,7 +35,7 @@
 run_unittests_SOURCES += question_unittest.cc
 run_unittests_SOURCES += rrparamregistry_unittest.cc
 run_unittests_SOURCES += message_unittest.cc
-run_unittests_SOURCES += base32_unittest.cc
+run_unittests_SOURCES += base32hex_unittest.cc
 run_unittests_SOURCES += base64_unittest.cc
 run_unittests_SOURCES += hex_unittest.cc
 run_unittests_SOURCES += sha1_unittest.cc
@@ -40,8 +44,8 @@
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 run_unittests_LDADD = $(GTEST_LDADD)
-run_unittests_LDADD += $(top_builddir)/src/lib/dns/.libs/libdns++.a
-run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a
+run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
+run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 endif
 
 noinst_PROGRAMS = $(TESTS)

Modified: branches/trac232/src/lib/dns/tests/base64_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/base64_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/base64_unittest.cc Wed Sep  1 00:35:07 2010
@@ -18,11 +18,14 @@
 #include <utility>
 #include <vector>
 
-#include <dns/base64.h>
+#include <exceptions/exceptions.h>
+
+#include <dns/util/base64.h>
 
 #include <gtest/gtest.h>
 
 using namespace std;
+using namespace isc;
 using namespace isc::dns;
 
 namespace {
@@ -67,18 +70,18 @@
     decodeCheck("Zm9vYmE=\n", decoded_data, "fooba");
 
     // only up to 2 padding characters are allowed
-    EXPECT_THROW(decodeBase64("A===", decoded_data), BadBase64String);
-    EXPECT_THROW(decodeBase64("A= ==", decoded_data), BadBase64String);
+    EXPECT_THROW(decodeBase64("A===", decoded_data), BadValue);
+    EXPECT_THROW(decodeBase64("A= ==", decoded_data), BadValue);
 
     // intermediate padding isn't allowed
-    EXPECT_THROW(decodeBase64("YmE=YmE=", decoded_data), BadBase64String);
+    EXPECT_THROW(decodeBase64("YmE=YmE=", decoded_data), BadValue);
 
     // Non canonical form isn't allowed.
     // Z => 25(011001), m => 38(100110), 9 => 60(111101), so the padding
     // byte would be 0100 0000.
-    EXPECT_THROW(decodeBase64("Zm9=", decoded_data), BadBase64String);
+    EXPECT_THROW(decodeBase64("Zm9=", decoded_data), BadValue);
     // Same for the 1st padding byte.  This would make it 01100000.
-    EXPECT_THROW(decodeBase64("Zm==", decoded_data), BadBase64String);
+    EXPECT_THROW(decodeBase64("Zm==", decoded_data), BadValue);
 }
 
 TEST_F(Base64Test, encode) {

Modified: branches/trac232/src/lib/dns/tests/hex_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/hex_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/hex_unittest.cc Wed Sep  1 00:35:07 2010
@@ -19,25 +19,27 @@
 #include <vector>
 #include <string>
 
-#include <dns/hex.h>
+#include <exceptions/exceptions.h>
+
+#include <dns/util/hex.h>
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-
-using isc::UnitTestUtil;
 using namespace std;
+using namespace isc;
 using namespace isc::dns;
 
 namespace {
+const string hex_txt("DEADBEEFDECADE");
+const string hex_txt_space("DEAD BEEF DECADE");
+const string hex_txt_lower("deadbeefdecade");
+
 class HexTest : public ::testing::Test {
 protected:
-    HexTest() {}
+    HexTest() : encoding_chars("0123456789ABCDEF") {}
+    vector<uint8_t> decoded_data;
+    const string encoding_chars;
 };
-
-const std::string hex_txt("DEADBEEFDECADE");
-const std::string hex_txt_space("DEAD BEEF DECADE");
-const std::string hex_txt_lower("deadbeefdecade");
 
 TEST_F(HexTest, encodeHex) {
     std::vector<uint8_t> data;
@@ -53,8 +55,7 @@
 }
 
 void
-compareData(const std::vector<uint8_t>& data)
-{
+compareData(const std::vector<uint8_t>& data) {
     EXPECT_EQ(0xde, data[0]);
     EXPECT_EQ(0xad, data[1]);
     EXPECT_EQ(0xbe, data[2]);
@@ -82,7 +83,40 @@
 
     // Bogus input: should fail
     result.clear();
-    EXPECT_THROW(decodeHex("1x", result), BadHexString);
+    EXPECT_THROW(decodeHex("1x", result), BadValue);
+
+    // Bogus input: encoded string must have an even number of characters.
+    result.clear();
+    EXPECT_THROW(decodeHex("dea", result), BadValue);
+}
+
+// For Hex encode/decode we use handmade mappings, so it's prudent to test the
+// entire mapping table explicitly.
+TEST_F(HexTest, decodeMap) {
+    string input("00");       // input placeholder
+
+    // See Base32HexTest.decodeMap for details of the following tests.
+    for (int i = 0; i < 256; ++i) {
+        input[1] = i;
+
+        const char ch = toupper(i);
+        const size_t pos = encoding_chars.find(ch);
+        if (pos == string::npos) {
+            EXPECT_THROW(decodeHex(input, decoded_data), BadValue);
+        } else {
+            decodeHex(input, decoded_data);
+            EXPECT_EQ(1, decoded_data.size());
+            EXPECT_EQ(pos, decoded_data[0]);
+        }
+    }
+}
+
+TEST_F(HexTest, encodeMap) {
+    for (int i = 0; i < 16; ++i) {
+        decoded_data.clear();
+        decoded_data.push_back(i);
+        EXPECT_EQ(encoding_chars[i], encodeHex(decoded_data)[1]);
+    }
 }
 
 }

Modified: branches/trac232/src/lib/dns/tests/message_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/message_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/message_unittest.cc Wed Sep  1 00:35:07 2010
@@ -28,7 +28,7 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac232/src/lib/dns/tests/messagerenderer_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/messagerenderer_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/messagerenderer_unittest.cc Wed Sep  1 00:35:07 2010
@@ -20,7 +20,7 @@
 #include <dns/name.h>
 #include <dns/messagerenderer.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 #include <gtest/gtest.h>
 

Modified: branches/trac232/src/lib/dns/tests/name_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/name_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/name_unittest.cc Wed Sep  1 00:35:07 2010
@@ -26,7 +26,7 @@
 #include <dns/name.h>
 #include <dns/messagerenderer.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 #include <gtest/gtest.h>
 

Modified: branches/trac232/src/lib/dns/tests/question_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/question_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/question_unittest.cc Wed Sep  1 00:35:07 2010
@@ -29,7 +29,7 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac232/src/lib/dns/tests/rdata_cname_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rdata_cname_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rdata_cname_unittest.cc Wed Sep  1 00:35:07 2010
@@ -24,8 +24,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac232/src/lib/dns/tests/rdata_dname_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rdata_dname_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rdata_dname_unittest.cc Wed Sep  1 00:35:07 2010
@@ -24,8 +24,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac232/src/lib/dns/tests/rdata_dnskey_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rdata_dnskey_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rdata_dnskey_unittest.cc Wed Sep  1 00:35:07 2010
@@ -16,7 +16,8 @@
 
 #include <string>
 
-#include <dns/base64.h>
+#include <exceptions/exceptions.h>
+
 #include <dns/buffer.h>
 #include <dns/messagerenderer.h>
 #include <dns/rdata.h>
@@ -26,11 +27,12 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;
+using namespace isc;
 using namespace isc::dns;
 using namespace isc::dns::rdata;
 
@@ -48,21 +50,18 @@
                   "7+ysyLKOOedS39Z7SDmsn2eA0FKtQpwA6LXeG2w+jxmw3oA"
                   "8lVUgEf/rzeC/bByBNsO70aEFTd");
 
-TEST_F(Rdata_DNSKEY_Test, fromText)
-{
+TEST_F(Rdata_DNSKEY_Test, fromText) {
     generic::DNSKEY rdata_dnskey(dnskey_txt);
     EXPECT_EQ(dnskey_txt, rdata_dnskey.toText());
 }
 
-TEST_F(Rdata_DNSKEY_Test, assign)
-{
+TEST_F(Rdata_DNSKEY_Test, assign) {
     generic::DNSKEY rdata_dnskey(dnskey_txt);
     generic::DNSKEY rdata_dnskey2 = rdata_dnskey;
     EXPECT_EQ(0, rdata_dnskey.compare(rdata_dnskey2));
 }
 
-TEST_F(Rdata_DNSKEY_Test, badText)
-{
+TEST_F(Rdata_DNSKEY_Test, badText) {
     EXPECT_THROW(generic::DNSKEY("257 3 5"),
                  InvalidRdataText);
     EXPECT_THROW(generic::DNSKEY("99999 3 5 BAAAAAAAAAAAD"),
@@ -71,9 +70,10 @@
                  InvalidRdataText);
     EXPECT_THROW(generic::DNSKEY("257 3 500 BAAAAAAAAAAAD"),
                  InvalidRdataText);
-    EXPECT_THROW(generic::DNSKEY("257 3 5 BAAAAAAAAAAAD"),
-                 BadBase64String);
-#if 0
+    EXPECT_THROW(generic::DNSKEY("257 3 5 BAAAAAAAAAAAD"), BadValue);
+}
+
+TEST_F(Rdata_DNSKEY_Test, DISABLED_badText) {
     // Should this be allowed?  Probably not.  But the test currently fails.
     EXPECT_THROW(generic::DNSKEY("257 3 5BEAAEFTd"),
                  InvalidRdataText);
@@ -81,11 +81,9 @@
     // it could be ambiguous '51 EAAA' vs '5 1EAA..'
     EXPECT_THROW(generic::DNSKEY("257 3 51EAAEFTd"),
                  InvalidRdataText);
-#endif
 }
 
-TEST_F(Rdata_DNSKEY_Test, toWireRenderer)
-{
+TEST_F(Rdata_DNSKEY_Test, toWireRenderer) {
     renderer.skip(2);
     generic::DNSKEY rdata_dnskey(dnskey_txt);
     rdata_dnskey.toWire(renderer);
@@ -97,34 +95,29 @@
                         obuffer.getLength() - 2, &data[2], data.size() - 2);
 }
 
-TEST_F(Rdata_DNSKEY_Test, toWireBuffer)
-{
+TEST_F(Rdata_DNSKEY_Test, toWireBuffer) {
     generic::DNSKEY rdata_dnskey(dnskey_txt);
     rdata_dnskey.toWire(obuffer);
 }
 
-TEST_F(Rdata_DNSKEY_Test, createFromWire)
-{
+TEST_F(Rdata_DNSKEY_Test, createFromWire) {
     generic::DNSKEY rdata_dnskey(dnskey_txt);
     EXPECT_EQ(0, rdata_dnskey.compare(
                   *rdataFactoryFromFile(RRType("DNSKEY"), RRClass("IN"),
                                         "rdata_dnskey_fromWire")));
 }
 
-TEST_F(Rdata_DNSKEY_Test, getTag)
-{
+TEST_F(Rdata_DNSKEY_Test, getTag) {
     generic::DNSKEY rdata_dnskey(dnskey_txt);
     EXPECT_EQ(12892, rdata_dnskey.getTag());
 }
 
-TEST_F(Rdata_DNSKEY_Test, getAlgorithm)
-{
+TEST_F(Rdata_DNSKEY_Test, getAlgorithm) {
     generic::DNSKEY rdata_dnskey(dnskey_txt);
     EXPECT_EQ(5, rdata_dnskey.getAlgorithm());
 }
 
-TEST_F(Rdata_DNSKEY_Test, getFlags)
-{
+TEST_F(Rdata_DNSKEY_Test, getFlags) {
     generic::DNSKEY rdata_dnskey(dnskey_txt);
     EXPECT_EQ(257, rdata_dnskey.getFlags());
 }

Modified: branches/trac232/src/lib/dns/tests/rdata_ds_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rdata_ds_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rdata_ds_unittest.cc Wed Sep  1 00:35:07 2010
@@ -25,8 +25,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac232/src/lib/dns/tests/rdata_in_a_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rdata_in_a_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rdata_in_a_unittest.cc Wed Sep  1 00:35:07 2010
@@ -24,8 +24,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac232/src/lib/dns/tests/rdata_in_aaaa_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rdata_in_aaaa_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rdata_in_aaaa_unittest.cc Wed Sep  1 00:35:07 2010
@@ -24,8 +24,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac232/src/lib/dns/tests/rdata_mx_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rdata_mx_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rdata_mx_unittest.cc Wed Sep  1 00:35:07 2010
@@ -23,8 +23,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;
@@ -38,14 +38,12 @@
 
 const generic::MX rdata_mx(10, Name("mx.example.com"));
 
-TEST_F(Rdata_MX_Test, createFromText)
-{
+TEST_F(Rdata_MX_Test, createFromText) {
     const generic::MX rdata_mx2("10 mx.example.com");
     EXPECT_EQ(0, rdata_mx2.compare(rdata_mx));
 }
 
-TEST_F(Rdata_MX_Test, badText)
-{
+TEST_F(Rdata_MX_Test, badText) {
     EXPECT_THROW(const generic::MX rdata_mx("99999999 mx."), InvalidRdataText);
     EXPECT_THROW(const generic::MX rdata_mx("10"), InvalidRdataText);
     EXPECT_THROW(const generic::MX rdata_mx("SPOON"), InvalidRdataText);
@@ -53,22 +51,19 @@
                  InvalidRdataText);
 }
 
-TEST_F(Rdata_MX_Test, copy)
-{
+TEST_F(Rdata_MX_Test, copy) {
     const generic::MX rdata_mx2(rdata_mx);
     EXPECT_EQ(0, rdata_mx.compare(rdata_mx2));
 }
 
-TEST_F(Rdata_MX_Test, createFromWire)
-{
+TEST_F(Rdata_MX_Test, createFromWire) {
     EXPECT_EQ(0, rdata_mx.compare(
                   *rdataFactoryFromFile(RRType("MX"), RRClass("IN"),
                                         "rdata_mx_fromWire")));
     // TBD: more tests
 }
 
-TEST_F(Rdata_MX_Test, toWireRenderer)
-{
+TEST_F(Rdata_MX_Test, toWireRenderer) {
     renderer.writeName(Name("example.com"));
     rdata_mx.toWire(renderer);
 
@@ -78,37 +73,32 @@
                         obuffer.getLength(), &data[0], data.size());
 }
 
-TEST_F(Rdata_MX_Test, toWireBuffer)
-{
+TEST_F(Rdata_MX_Test, toWireBuffer) {
     renderer.writeName(Name("example.com"));
     rdata_mx.toWire(obuffer);
+}
 
-#if 0
+TEST_F(Rdata_MX_Test, DISABLED_toWireBuffer) {
 // XXX: does not pass
     vector<unsigned char> data;
     UnitTestUtil::readWireData("rdata_mx_toWire1", data);
     EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, obuffer.getData(),
                         obuffer.getLength(), &data[0], data.size());
-#endif
 }
 
-TEST_F(Rdata_MX_Test, toText)
-{
+TEST_F(Rdata_MX_Test, toText) {
     EXPECT_EQ("10 mx.example.com.", rdata_mx.toText());
 }
 
-TEST_F(Rdata_MX_Test, getMXName)
-{
+TEST_F(Rdata_MX_Test, getMXName) {
     EXPECT_EQ(Name("mx.example.com."), rdata_mx.getMXName());
 }
 
-TEST_F(Rdata_MX_Test, getMXPref)
-{
+TEST_F(Rdata_MX_Test, getMXPref) {
     EXPECT_EQ(10, rdata_mx.getMXPref());
 }
 
-TEST_F(Rdata_MX_Test, compare)
-{
+TEST_F(Rdata_MX_Test, compare) {
     generic::MX small1(1, Name("mx.example.com"));
     generic::MX small2(10, Name("mx.example.com"));
     generic::MX large1(65535, Name("mx.example.com"));

Modified: branches/trac232/src/lib/dns/tests/rdata_ns_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rdata_ns_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rdata_ns_unittest.cc Wed Sep  1 00:35:07 2010
@@ -24,8 +24,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac232/src/lib/dns/tests/rdata_nsec3_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rdata_nsec3_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rdata_nsec3_unittest.cc Wed Sep  1 00:35:07 2010
@@ -16,10 +16,11 @@
 
 #include <string>
 
-#include <dns/base32.h>
+#include <exceptions/exceptions.h>
+
 #include <dns/buffer.h>
 #include <dns/exceptions.h>
-#include <dns/hex.h>
+#include <dns/util/hex.h>
 #include <dns/messagerenderer.h>
 #include <dns/rdata.h>
 #include <dns/rdataclass.h>
@@ -28,60 +29,64 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;
+using namespace isc;
 using namespace isc::dns;
 using namespace isc::dns::rdata;
 
 namespace {
 class Rdata_NSEC3_Test : public RdataTest {
     // there's nothing to specialize
+public:
+    Rdata_NSEC3_Test() :
+        nsec3_txt("1 1 1 D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6 "
+                  "NS SOA RRSIG DNSKEY NSEC3PARAM") {}
+    string nsec3_txt;
 };
-string nsec3_txt("1 1 1 D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6 "
-                 "NS SOA RRSIG DNSKEY NSEC3PARAM");
 
-
-TEST_F(Rdata_NSEC3_Test, toText)
-{
+TEST_F(Rdata_NSEC3_Test, toText) {
     const generic::NSEC3 rdata_nsec3(nsec3_txt);
     EXPECT_EQ(nsec3_txt, rdata_nsec3.toText());
 }
 
-TEST_F(Rdata_NSEC3_Test, badText)
-{
-    EXPECT_THROW(generic::NSEC3 rdata_nsec3("1 1 1 ADDAFEE "
+TEST_F(Rdata_NSEC3_Test, badText) {
+    EXPECT_THROW(generic::NSEC3 rdata_nsec3("1 1 1 ADDAFEEE "
                                             "0123456789ABCDEFGHIJKLMNOPQRSTUV "
                                             "BIFF POW SPOON"),
                  InvalidRdataText);
     EXPECT_THROW(generic::NSEC3 rdata_nsec3("1 1 1 ADDAFEE "
                                             "WXYZWXYZWXYZ=WXYZWXYZ==WXYZWXYZW "
                                             "A NS SOA"),
-                 BadBase32String);
-    EXPECT_THROW(generic::NSEC3 rdata_nsec3("1000000 1 1 ADDAFEE "
+                 BadValue);     // bad hex
+    EXPECT_THROW(generic::NSEC3 rdata_nsec3("1 1 1 ADDAFEEE "
+                                            "WXYZWXYZWXYZ=WXYZWXYZ==WXYZWXYZW "
+                                            "A NS SOA"),
+                 BadValue);     // bad base32hex
+    EXPECT_THROW(generic::NSEC3 rdata_nsec3("1000000 1 1 ADDAFEEE "
                                             "0123456789ABCDEFGHIJKLMNOPQRSTUV "
                                             "A NS SOA"),
                  InvalidRdataText);
-    EXPECT_THROW(generic::NSEC3 rdata_nsec3("1 1000000 1 ADDAFEE "
+    EXPECT_THROW(generic::NSEC3 rdata_nsec3("1 1000000 1 ADDAFEEE "
                                             "0123456789ABCDEFGHIJKLMNOPQRSTUV "
                                             "A NS SOA"),
                  InvalidRdataText);
-    EXPECT_THROW(generic::NSEC3 rdata_nsec3("1 1 1000000 ADDAFEE "
+    EXPECT_THROW(generic::NSEC3 rdata_nsec3("1 1 1000000 ADDAFEEE "
                                             "0123456789ABCDEFGHIJKLMNOPQRSTUV "
                                             "A NS SOA"),
                  InvalidRdataText);
+}
 
-#if 0 // this currently fails
+TEST_F(Rdata_NSEC3_Test, DISABLED_badText) { // this currently fails
     EXPECT_THROW(generic::NSEC3(
                      "1 1 1D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6 "
                      "NS SOA RRSIG DNSKEY NSEC3PARAM"), InvalidRdataText);
-#endif
 }
 
-TEST_F(Rdata_NSEC3_Test, createFromWire)
-{
+TEST_F(Rdata_NSEC3_Test, createFromWire) {
     const generic::NSEC3 rdata_nsec3(nsec3_txt);
     EXPECT_EQ(0, rdata_nsec3.compare(
                   *rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
@@ -98,8 +103,7 @@
                  DNSMessageFORMERR);
 }
 
-TEST_F(Rdata_NSEC3_Test, toWireRenderer)
-{
+TEST_F(Rdata_NSEC3_Test, toWireRenderer) {
     renderer.skip(2);
     const generic::NSEC3 rdata_nsec3(nsec3_txt);
     rdata_nsec3.toWire(renderer);
@@ -111,14 +115,12 @@
                         obuffer.getLength() - 2, &data[2], data.size() - 2);
 }
 
-TEST_F(Rdata_NSEC3_Test, toWireBuffer)
-{
+TEST_F(Rdata_NSEC3_Test, toWireBuffer) {
     const generic::NSEC3 rdata_nsec3(nsec3_txt);
     rdata_nsec3.toWire(obuffer);
 }
 
-TEST_F(Rdata_NSEC3_Test, assign)
-{
+TEST_F(Rdata_NSEC3_Test, assign) {
     generic::NSEC3 rdata_nsec3(nsec3_txt);
     generic::NSEC3 other_nsec3 = rdata_nsec3;
     EXPECT_EQ(0, rdata_nsec3.compare(other_nsec3));

Modified: branches/trac232/src/lib/dns/tests/rdata_nsec3param_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rdata_nsec3param_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rdata_nsec3param_unittest.cc Wed Sep  1 00:35:07 2010
@@ -16,9 +16,11 @@
 
 #include <string>
 
-#include <dns/base32.h>
+#include <exceptions/exceptions.h>
+
+#include <dns/util/base32hex.h>
 #include <dns/buffer.h>
-#include <dns/hex.h>
+#include <dns/util/hex.h>
 #include <dns/messagerenderer.h>
 #include <dns/rdata.h>
 #include <dns/rdataclass.h>
@@ -27,11 +29,12 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;
+using namespace isc;
 using namespace isc::dns;
 using namespace isc::dns::rdata;
 
@@ -41,35 +44,32 @@
 };
 string nsec3param_txt("1 0 1 D399EAAB");
 
-TEST_F(Rdata_NSEC3PARAM_Test, toText)
-{
+TEST_F(Rdata_NSEC3PARAM_Test, toText) {
     const generic::NSEC3PARAM rdata_nsec3param(nsec3param_txt);
     EXPECT_EQ(nsec3param_txt, rdata_nsec3param.toText());
 }
 
-TEST_F(Rdata_NSEC3PARAM_Test, badText)
-{
-    EXPECT_THROW(generic::NSEC3PARAM("1 1 1 SPORK"), BadHexString);
+TEST_F(Rdata_NSEC3PARAM_Test, badText) {
+    EXPECT_THROW(generic::NSEC3PARAM("1 1 1 SPORK"), BadValue); // bad hex
     EXPECT_THROW(generic::NSEC3PARAM("100000 1 1 ADDAFEE"), InvalidRdataText);
     EXPECT_THROW(generic::NSEC3PARAM("1 100000 1 ADDAFEE"), InvalidRdataText);
     EXPECT_THROW(generic::NSEC3PARAM("1 1 100000 ADDAFEE"), InvalidRdataText);
     EXPECT_THROW(generic::NSEC3PARAM("1"), InvalidRdataText);
-
-#if 0                           // this currently fails
-    EXPECT_THROW(generic::NSEC3PARAM("1 0 1D399EAAB"), InvalidRdataText);
-#endif
 }
 
-TEST_F(Rdata_NSEC3PARAM_Test, createFromWire)
-{
+TEST_F(Rdata_NSEC3PARAM_Test, DISABLED_badText) {
+    // this currently fails
+    EXPECT_THROW(generic::NSEC3PARAM("1 0 1D399EAAB"), InvalidRdataText);
+}
+
+TEST_F(Rdata_NSEC3PARAM_Test, createFromWire) {
     const generic::NSEC3PARAM rdata_nsec3param(nsec3param_txt);
     EXPECT_EQ(0, rdata_nsec3param.compare(
                   *rdataFactoryFromFile(RRType::NSEC3PARAM(), RRClass::IN(),
                                        "rdata_nsec3param_fromWire1")));
 }
 
-TEST_F(Rdata_NSEC3PARAM_Test, toWireRenderer)
-{
+TEST_F(Rdata_NSEC3PARAM_Test, toWireRenderer) {
     renderer.skip(2);
     const generic::NSEC3PARAM rdata_nsec3param(nsec3param_txt);
     rdata_nsec3param.toWire(renderer);
@@ -81,14 +81,12 @@
                         obuffer.getLength() - 2, &data[2], data.size() - 2);
 }
 
-TEST_F(Rdata_NSEC3PARAM_Test, toWireBuffer)
-{
+TEST_F(Rdata_NSEC3PARAM_Test, toWireBuffer) {
     const generic::NSEC3PARAM rdata_nsec3param(nsec3param_txt);
     rdata_nsec3param.toWire(obuffer);
 }
 
-TEST_F(Rdata_NSEC3PARAM_Test, assign)
-{
+TEST_F(Rdata_NSEC3PARAM_Test, assign) {
     generic::NSEC3PARAM rdata_nsec3param(nsec3param_txt);
     generic::NSEC3PARAM other_nsec3param = rdata_nsec3param;
     EXPECT_EQ(0, rdata_nsec3param.compare(other_nsec3param));

Modified: branches/trac232/src/lib/dns/tests/rdata_nsec_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rdata_nsec_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rdata_nsec_unittest.cc Wed Sep  1 00:35:07 2010
@@ -26,8 +26,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac232/src/lib/dns/tests/rdata_opt_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rdata_opt_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rdata_opt_unittest.cc Wed Sep  1 00:35:07 2010
@@ -23,8 +23,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac232/src/lib/dns/tests/rdata_ptr_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rdata_ptr_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rdata_ptr_unittest.cc Wed Sep  1 00:35:07 2010
@@ -24,8 +24,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac232/src/lib/dns/tests/rdata_rrsig_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rdata_rrsig_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rdata_rrsig_unittest.cc Wed Sep  1 00:35:07 2010
@@ -14,7 +14,8 @@
 
 // $Id$
 
-#include <dns/base64.h>
+#include <exceptions/exceptions.h>
+
 #include <dns/buffer.h>
 #include <dns/dnssectime.h>
 #include <dns/messagerenderer.h>
@@ -25,11 +26,12 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;
+using namespace isc;
 using namespace isc::dns;
 using namespace isc::dns::rdata;
 
@@ -38,8 +40,7 @@
     // there's nothing to specialize
 };
 
-TEST_F(Rdata_RRSIG_Test, fromText)
-{
+TEST_F(Rdata_RRSIG_Test, fromText) {
     string rrsig_txt("A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
                      "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
                      "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
@@ -50,8 +51,7 @@
 
 }
 
-TEST_F(Rdata_RRSIG_Test, badText)
-{
+TEST_F(Rdata_RRSIG_Test, badText) {
     EXPECT_THROW(const generic::RRSIG sig("SPORK"), InvalidRdataText);
     EXPECT_THROW(const generic::RRSIG sig("A 555 4 43200 "
                      "20100223214617 20100222214617 8496 isc.org. "
@@ -83,20 +83,21 @@
                      "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
                      "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
                      "f49t+sXKPzbipN9g+s1ZPiIyofc="), InvalidRdataText);
-    EXPECT_THROW(const generic::RRSIG sig("A 5 4 43200 "
+    EXPECT_THROW(const generic::RRSIG sig(
+                     "A 5 4 43200 "
                      "20100223214617 20100222214617 8496 isc.org. "
                      "EEeeeeeeEEEeeeeeeGaaahAAAAAAAAHHHHHHHHHHH!="),
-                     BadBase64String);
+                 BadValue);     // bad base64 input
+}
 
-#if 0                           // this currently fails
+TEST_F(Rdata_RRSIG_Test, DISABLED_badText) {
+    // this currently fails
     // no space between the tag and signer
     EXPECT_THROW(generic::RRSIG("A 5 4 43200 20100223214617 20100222214617 "
                                 "8496isc.org. ofc="), InvalidRdataText);
-#endif
 }
 
-TEST_F(Rdata_RRSIG_Test, toWireRenderer)
-{
+TEST_F(Rdata_RRSIG_Test, toWireRenderer) {
     string rrsig_txt("A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
                      "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
                      "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
@@ -106,8 +107,7 @@
     rdata_rrsig.toWire(renderer);
 }
 
-TEST_F(Rdata_RRSIG_Test, toWireBuffer)
-{
+TEST_F(Rdata_RRSIG_Test, toWireBuffer) {
     string rrsig_txt("A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
                      "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
                      "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
@@ -117,8 +117,7 @@
     rdata_rrsig.toWire(obuffer);
 }
 
-TEST_F(Rdata_RRSIG_Test, createFromWire)
-{
+TEST_F(Rdata_RRSIG_Test, createFromWire) {
     string rrsig_txt("A 5 2 43200 20100327070149 20100225070149 2658 isc.org. "
                 "HkJk/xZTvzePU8NENl/ley8bbUumhk1hXciyqhLnz1VQFzkDooej6neX"
                 "ZgWZzQKeTKPOYWrnYtdZW4PnPQFeUl3orgLev7F8J6FZlDn0y/J/ThR5"

Modified: branches/trac232/src/lib/dns/tests/rdata_soa_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rdata_soa_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rdata_soa_unittest.cc Wed Sep  1 00:35:07 2010
@@ -23,8 +23,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac232/src/lib/dns/tests/rdata_txt_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rdata_txt_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rdata_txt_unittest.cc Wed Sep  1 00:35:07 2010
@@ -24,8 +24,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac232/src/lib/dns/tests/rdata_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rdata_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rdata_unittest.cc Wed Sep  1 00:35:07 2010
@@ -27,8 +27,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac232/src/lib/dns/tests/rrclass_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rrclass_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rrclass_unittest.cc Wed Sep  1 00:35:07 2010
@@ -20,7 +20,7 @@
 #include <dns/messagerenderer.h>
 #include <dns/rrclass.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 using namespace std;
 using namespace isc;

Modified: branches/trac232/src/lib/dns/tests/rrparamregistry_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rrparamregistry_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rrparamregistry_unittest.cc Wed Sep  1 00:35:07 2010
@@ -107,11 +107,11 @@
 class TestRdataFactory : public AbstractRdataFactory {
 public:
     virtual RdataPtr create(const string& rdata_str) const
-    { return RdataPtr(new in::A(rdata_str)); }
+    { return (RdataPtr(new in::A(rdata_str))); }
     virtual RdataPtr create(InputBuffer& buffer, size_t rdata_len) const
-    { return RdataPtr(new in::A(buffer, rdata_len)); }
+    { return (RdataPtr(new in::A(buffer, rdata_len))); }
     virtual RdataPtr create(const Rdata& source) const
-    { return RdataPtr(new in::A(dynamic_cast<const in::A&>(source))); }
+    { return (RdataPtr(new in::A(dynamic_cast<const in::A&>(source)))); }
 };
 
 TEST_F(RRParamRegistryTest, addRemoveFactory)

Modified: branches/trac232/src/lib/dns/tests/rrset_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rrset_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rrset_unittest.cc Wed Sep  1 00:35:07 2010
@@ -28,7 +28,7 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 using isc::UnitTestUtil;
 

Modified: branches/trac232/src/lib/dns/tests/rrttl_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rrttl_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rrttl_unittest.cc Wed Sep  1 00:35:07 2010
@@ -20,7 +20,7 @@
 #include <dns/messagerenderer.h>
 #include <dns/rrttl.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 using namespace std;
 using namespace isc;

Modified: branches/trac232/src/lib/dns/tests/rrtype_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rrtype_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rrtype_unittest.cc Wed Sep  1 00:35:07 2010
@@ -20,7 +20,7 @@
 #include <dns/messagerenderer.h>
 #include <dns/rrtype.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 using namespace std;
 using namespace isc;

Modified: branches/trac232/src/lib/dns/tests/run_unittests.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/run_unittests.cc (original)
+++ branches/trac232/src/lib/dns/tests/run_unittests.cc Wed Sep  1 00:35:07 2010
@@ -16,7 +16,7 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 int
 main(int argc, char* argv[]) {

Modified: branches/trac232/src/lib/dns/tests/sha1_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/sha1_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/sha1_unittest.cc Wed Sep  1 00:35:07 2010
@@ -17,11 +17,11 @@
 #include <stdint.h>
 #include <string>
 
-#include <dns/sha1.h>
+#include <dns/util/sha1.h>
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac232/src/lib/dns/tests/tsig_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/tsig_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/tsig_unittest.cc Wed Sep  1 00:35:07 2010
@@ -18,7 +18,7 @@
 
 #include <dns/tsig.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac232/src/lib/dns/tests/unittest_util.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/unittest_util.cc (original)
+++ branches/trac232/src/lib/dns/tests/unittest_util.cc Wed Sep  1 00:35:07 2010
@@ -26,7 +26,7 @@
 #include <gtest/gtest.h>
 
 #include <dns/name.h>
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 using namespace std;
 
@@ -158,7 +158,7 @@
             << "Expected: " << len2 << "\n";
         return (::testing::AssertionFailure(msg));
     }
-    return ::testing::AssertionSuccess();
+    return (::testing::AssertionSuccess());
 }
 
 ::testing::AssertionResult
@@ -177,5 +177,5 @@
             << "Other: " << name2 << "\n";
         return (::testing::AssertionFailure(msg));
     }
-    return ::testing::AssertionSuccess();
+    return (::testing::AssertionSuccess());
 }

Modified: branches/trac232/src/lib/exceptions/Makefile.am
==============================================================================
--- branches/trac232/src/lib/exceptions/Makefile.am (original)
+++ branches/trac232/src/lib/exceptions/Makefile.am Wed Sep  1 00:35:07 2010
@@ -1,3 +1,6 @@
+SUBDIRS = . tests
+
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CXXFLAGS=$(B10_CXXFLAGS)
 
 lib_LTLIBRARIES = libexceptions.la
@@ -5,17 +8,5 @@
 
 CLEANFILES = *.gcno *.gcda
 
-TESTS =
-if HAVE_GTEST
-TESTS += run_unittests
-run_unittests_SOURCES = run_unittests.cc
-run_unittests_SOURCES += exceptions_unittest.cc
-run_unittests_CPPFLAGS = $(GTEST_INCLUDES)
-run_unittests_LDFLAGS = $(GTEST_LDFLAGS)
-run_unittests_LDADD = .libs/libexceptions.a $(GTEST_LDADD)
-endif
-
-noinst_PROGRAMS = $(TESTS)
-
 libexceptions_includedir = $(includedir)/exceptions
 libexceptions_include_HEADERS = exceptions.h

Modified: branches/trac232/src/lib/exceptions/exceptions.cc
==============================================================================
--- branches/trac232/src/lib/exceptions/exceptions.cc (original)
+++ branches/trac232/src/lib/exceptions/exceptions.cc Wed Sep  1 00:35:07 2010
@@ -16,7 +16,7 @@
 
 #include <string>
 
-#include "exceptions.h"
+#include <exceptions/exceptions.h>
 
 using isc::Exception;
 

Modified: branches/trac232/src/lib/exceptions/exceptions.h
==============================================================================
--- branches/trac232/src/lib/exceptions/exceptions.h (original)
+++ branches/trac232/src/lib/exceptions/exceptions.h Wed Sep  1 00:35:07 2010
@@ -104,7 +104,7 @@
 };
 
 ///
-/// \brief A standard DNS module exception that is thrown if a parameter give
+/// \brief A generic exception that is thrown if a parameter given
 /// to a method would refer to or modify out-of-range data.
 ///
 class OutOfRange : public Exception {
@@ -114,7 +114,17 @@
 };
 
 ///
-/// \brief A standard DNS module exception that is thrown when an unexpected
+/// \brief A generic exception that is thrown if a parameter given
+/// to a method is considered invalid in that context.
+///
+class BadValue : public Exception {
+public:
+    BadValue(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+///
+/// \brief A generic exception that is thrown when an unexpected
 /// error condition occurs.
 ///
 class Unexpected : public Exception {

Modified: branches/trac232/src/lib/python/isc/Makefile.am
==============================================================================
--- branches/trac232/src/lib/python/isc/Makefile.am (original)
+++ branches/trac232/src/lib/python/isc/Makefile.am Wed Sep  1 00:35:07 2010
@@ -1,4 +1,4 @@
-SUBDIRS = datasrc cc config log # Util
+SUBDIRS = datasrc cc config log notify # Util
 
 python_PYTHON = __init__.py
 

Modified: branches/trac232/src/lib/python/isc/cc/data.py
==============================================================================
--- branches/trac232/src/lib/python/isc/cc/data.py (original)
+++ branches/trac232/src/lib/python/isc/cc/data.py Wed Sep  1 00:35:07 2010
@@ -20,7 +20,7 @@
 # (int, real, bool, string, list and dict respectively)
 #
 
-import ast
+import json
 
 class DataNotFoundError(Exception): pass
 class DataTypeError(Exception): pass
@@ -134,7 +134,7 @@
     if type(value_str) != str:
         return None
     try:
-        return ast.literal_eval(value_str)
+        return json.loads(value_str)
     except ValueError as ve:
         # simply return the string itself
         return value_str

Modified: branches/trac232/src/lib/python/isc/cc/session.py
==============================================================================
--- branches/trac232/src/lib/python/isc/cc/session.py (original)
+++ branches/trac232/src/lib/python/isc/cc/session.py Wed Sep  1 00:35:07 2010
@@ -29,6 +29,10 @@
 class Session:
     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
@@ -44,7 +48,6 @@
                 self.socket_file = bind10_config.BIND10_MSGQ_SOCKET_FILE
         else:
             self.socket_file = socket_file
-        
 
         try:
             self._socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
@@ -123,6 +126,10 @@
             self._socket.setblocking(0)
         else:
             self._socket.setblocking(1)
+            if self._socket_timeout == 0.0:
+                self._socket.settimeout(None)
+            else:
+                self._socket.settimeout(self._socket_timeout)
 
         if self._recvlength == 0:
             length = 4
@@ -208,6 +215,15 @@
         }, isc.cc.message.to_wire(msg))
         return seq
 
+    def set_timeout(self, milliseconds):
+        """Sets the socket timeout for blocking reads to the given
+           number of milliseconds"""
+        self._socket_timeout = milliseconds / 1000.0
+
+    def get_timeout(self):
+        """Returns the current timeout for blocking reads (in milliseconds)"""
+        return self._socket_timeout * 1000.0
+
 if __name__ == "__main__":
     import doctest
     doctest.testmod()

Modified: branches/trac232/src/lib/python/isc/cc/tests/Makefile.am
==============================================================================
--- branches/trac232/src/lib/python/isc/cc/tests/Makefile.am (original)
+++ branches/trac232/src/lib/python/isc/cc/tests/Makefile.am Wed Sep  1 00:35:07 2010
@@ -11,5 +11,6 @@
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python \
-	$(PYCOVERAGE) $(abs_srcdir)/$$pytest ; \
+	BIND10_TEST_SOCKET_FILE=$(builddir)/test_socket.sock \
+	$(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
 	done

Modified: branches/trac232/src/lib/python/isc/cc/tests/data_test.py
==============================================================================
--- branches/trac232/src/lib/python/isc/cc/tests/data_test.py (original)
+++ branches/trac232/src/lib/python/isc/cc/tests/data_test.py Wed Sep  1 00:35:07 2010
@@ -137,13 +137,13 @@
         
     def test_parse_value_str(self):
         self.assertEqual(data.parse_value_str("1"), 1)
-        self.assertEqual(data.parse_value_str("True"), True)
-        self.assertEqual(data.parse_value_str("None"), None)
+        self.assertEqual(data.parse_value_str("true"), True)
+        self.assertEqual(data.parse_value_str("null"), None)
         self.assertEqual(data.parse_value_str("1.1"), 1.1)
         self.assertEqual(data.parse_value_str("[]"), [])
-        self.assertEqual(data.parse_value_str("[ 1, None, 'asdf' ]"), [ 1, None, "asdf" ])
+        self.assertEqual(data.parse_value_str("[ 1, null, \"asdf\" ]"), [ 1, None, "asdf" ])
         self.assertEqual(data.parse_value_str("{}"), {})
-        self.assertEqual(data.parse_value_str("{ 'a': 'b', 'c': 1 }"), { 'a': 'b', 'c': 1 })
+        self.assertEqual(data.parse_value_str("{ \"a\": \"b\", \"c\": 1 }"), { 'a': 'b', 'c': 1 })
         self.assertEqual(data.parse_value_str("[ a c"), "[ a c")
 
 if __name__ == '__main__':

Modified: branches/trac232/src/lib/python/isc/cc/tests/session_test.py
==============================================================================
--- branches/trac232/src/lib/python/isc/cc/tests/session_test.py (original)
+++ branches/trac232/src/lib/python/isc/cc/tests/session_test.py Wed Sep  1 00:35:07 2010
@@ -89,13 +89,20 @@
         if msg:
             self.recvqueue.extend(msg)
 
+    def settimeout(self, val):
+        pass
+
+    def gettimeout(self):
+        return 0
+
 #
 # We subclass the Session class we're testing here, only
 # to override the __init__() method, which wants a socket,
 # and we need to use our fake socket
 class MySession(Session):
-    def __init__(self, port=9912):
+    def __init__(self, port=9912, s=None):
         self._socket = None
+        self._socket_timeout = 1
         self._lname = None
         self._recvbuffer = bytearray()
         self._recvlength = 0
@@ -104,13 +111,16 @@
         self._queue = []
         self._lock = threading.RLock()
 
-        try:
-            self._socket = MySocket(socket.AF_INET, socket.SOCK_STREAM)
-            self._socket.connect(tuple(['127.0.0.1', port]))
-            self._lname = "test_name"
-            # testing getlname here isn't useful, code removed
-        except socket.error as se:
-                raise SessionError(se)
+        if s is not None:
+            self._socket = s
+        else:
+            try:
+                self._socket = MySocket(socket.AF_INET, socket.SOCK_STREAM)
+                self._socket.connect(tuple(['127.0.0.1', port]))
+                self._lname = "test_name"
+                # testing getlname here isn't useful, code removed
+            except socket.error as se:
+                    raise SessionError(se)
 
 class testSession(unittest.TestCase):
 
@@ -323,8 +333,32 @@
         sess.group_reply({ 'from': 'me', 'group': 'our_group', 'instance': 'other_instance', 'seq': 9}, {"hello": "a"})
         sent = sess._socket.readsentmsg();
         self.assertEqual(sent, b'\x00\x00\x00\x8b\x00{{"from": "test_name", "seq": 3, "to": "me", "instance": "other_instance", "reply": 9, "group": "our_group", "type": "send"}{"hello": "a"}')
-        
-        
+
+    def test_timeout(self):
+        if "BIND10_TEST_SOCKET_FILE" not in os.environ:
+            self.assertEqual("", "This test can only run if the value BIND10_TEST_SOCKET_FILE is set in the environment")
+        TEST_SOCKET_FILE = os.environ["BIND10_TEST_SOCKET_FILE"]
+
+        # create a read domain socket to pass into the session
+        s1 = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+        if os.path.exists(TEST_SOCKET_FILE):
+            os.remove(TEST_SOCKET_FILE)
+        s1.bind(TEST_SOCKET_FILE)
+
+        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)
+            env, msg = sess.group_recvmsg(False)
+            self.assertEqual(None, env)
+            self.assertEqual(None, msg)
+        finally:
+            os.remove(TEST_SOCKET_FILE)
+
 if __name__ == "__main__":
     unittest.main()
 

Modified: branches/trac232/src/lib/python/isc/config/ccsession.py
==============================================================================
--- branches/trac232/src/lib/python/isc/config/ccsession.py (original)
+++ branches/trac232/src/lib/python/isc/config/ccsession.py Wed Sep  1 00:35:07 2010
@@ -37,7 +37,7 @@
 """
 
 from isc.cc import Session
-from isc.config.config_data import ConfigData, MultiConfigData
+from isc.config.config_data import ConfigData, MultiConfigData, BIND10_CONFIG_DATA_VERSION
 import isc
 
 class ModuleCCSessionError(Exception): pass
@@ -333,7 +333,7 @@
         """Requests the current configuration from the configuration
            manager through b10-cmdctl, and stores those as CURRENT"""
         config = self._conn.send_GET('/config_data')
-        if 'version' not in config or config['version'] != 1:
+        if 'version' not in config or config['version'] != BIND10_CONFIG_DATA_VERSION:
             raise ModuleCCSessionError("Bad config version")
         self._set_current_config(config)
 

Modified: branches/trac232/src/lib/python/isc/config/cfgmgr.py
==============================================================================
--- branches/trac232/src/lib/python/isc/config/cfgmgr.py (original)
+++ branches/trac232/src/lib/python/isc/config/cfgmgr.py Wed Sep  1 00:35:07 2010
@@ -22,12 +22,12 @@
 import isc
 import signal
 import ast
-import pprint
 import os
 import copy
 import tempfile
+import json
 from isc.cc import data
-from isc.config import ccsession
+from isc.config import ccsession, config_data
 
 class ConfigManagerDataReadError(Exception):
     """This exception is thrown when there is an error while reading
@@ -42,8 +42,6 @@
 class ConfigManagerData:
     """This class hold the actual configuration information, and
        reads it from and writes it to persistent storage"""
-
-    CONFIG_VERSION = 1
 
     def __init__(self, data_path, file_name = "b10-config.db"):
         """Initialize the data for the configuration manager, and
@@ -51,7 +49,7 @@
            this does not yet read the database, a call to
            read_from_file is needed for that."""
         self.data = {}
-        self.data['version'] = ConfigManagerData.CONFIG_VERSION
+        self.data['version'] = config_data.BIND10_CONFIG_DATA_VERSION
         self.data_path = data_path
         self.db_filename = data_path + os.sep + file_name
 
@@ -65,21 +63,36 @@
            the second exception, the best way is probably to report the
            error and stop loading the system."""
         config = ConfigManagerData(data_path, file_name)
+        file = None
         try:
             file = open(config.db_filename, 'r')
-            file_config = ast.literal_eval(file.read())
-            if 'version' in file_config and \
-                file_config['version'] == ConfigManagerData.CONFIG_VERSION:
-                config.data = file_config
-            else:
-                # We can put in a migration path here for old data
-                raise ConfigManagerDataReadError("[b10-cfgmgr] Old version of data found")
-            file.close()
+            file_config = json.loads(file.read())
+            # handle different versions here
+            # If possible, we automatically convert to the new
+            # scheme and update the configuration
+            # If not, we raise an exception
+            if 'version' in file_config:
+                if file_config['version'] == config_data.BIND10_CONFIG_DATA_VERSION:
+                    config.data = file_config
+                elif file_config['version'] == 1:
+                    # only format change, no other changes necessary
+                    file_config['version'] = 2
+                    print("[b10-cfgmgr] Updating configuration database version from 1 to 2")
+                    config.data = file_config
+                else:
+                    if config_data.BIND10_CONFIG_DATA_VERSION > file_config['version']:
+                        raise ConfigManagerDataReadError("Cannot load configuration file: version %d no longer supported" % file_config['version'])
+                    else:
+                        raise ConfigManagerDataReadError("Cannot load configuration file: version %d not yet supported" % file_config['version'])
+            else:
+                raise ConfigManagerDataReadError("No version information in configuration file " + config.db_filename)
         except IOError as ioe:
-            raise ConfigManagerDataEmpty("No config file found")
-        except:
-            raise ConfigManagerDataReadError("Config file unreadable")
-
+            raise ConfigManagerDataEmpty("No configuration file found")
+        except ValueError:
+            raise ConfigManagerDataReadError("Configuration file out of date or corrupt, please update or remove " + config.db_filename)
+        finally:
+            if file:
+                file.close();
         return config
         
     def write_to_file(self, output_file_name = None):
@@ -93,9 +106,7 @@
                                                dir=self.data_path,
                                                delete=False)
             filename = file.name
-            pp = pprint.PrettyPrinter(indent=4)
-            s = pp.pformat(self.data)
-            file.write(s)
+            file.write(json.dumps(self.data))
             file.write("\n")
             file.close()
             if output_file_name:
@@ -104,11 +115,11 @@
                 os.rename(filename, self.db_filename)
         except IOError as ioe:
             # TODO: log this (level critical)
-            print("[b10-cfgmgr] Unable to write config file; configuration not stored: " + str(ioe))
+            print("[b10-cfgmgr] Unable to write configuration file; configuration not stored: " + str(ioe))
             # TODO: debug option to keep file?
         except OSError as ose:
             # TODO: log this (level critical)
-            print("[b10-cfgmgr] Unable to write config file; configuration not stored: " + str(ose))
+            print("[b10-cfgmgr] Unable to write configuration file; configuration not stored: " + str(ose))
         try:
             if filename and os.path.exists(filename):
                 os.remove(filename)
@@ -245,7 +256,7 @@
             except data.DataNotFoundError as dnfe:
                 # no data is ok, that means we have nothing that
                 # deviates from default values
-                return ccsession.create_answer(0, { 'version': self.config.CONFIG_VERSION })
+                return ccsession.create_answer(0, { 'version': config_data.BIND10_CONFIG_DATA_VERSION })
         else:
             return ccsession.create_answer(1, "Bad module_name in get_config command")
 
@@ -384,8 +395,9 @@
         self.running = True
         while (self.running):
             msg, env = self.cc.group_recvmsg(False)
-            if msg and not 'result' in msg:
+            # ignore 'None' value (current result of timeout)
+            # and messages that are answers to questions we did
+            # not ask
+            if msg is not None and not 'result' in msg:
                 answer = self.handle_msg(msg);
                 self.cc.group_reply(env, answer)
-            else:
-                self.running = False

Modified: branches/trac232/src/lib/python/isc/config/config_data.py
==============================================================================
--- branches/trac232/src/lib/python/isc/config/config_data.py (original)
+++ branches/trac232/src/lib/python/isc/config/config_data.py Wed Sep  1 00:35:07 2010
@@ -24,6 +24,8 @@
 import isc.config.module_spec
 
 class ConfigDataError(Exception): pass
+
+BIND10_CONFIG_DATA_VERSION = 2
 
 def check_type(spec_part, value):
     """Does nothing if the value is of the correct type given the
@@ -250,6 +252,11 @@
         """Removes the specification with the given module name. Does nothing if it wasn't there."""
         if module_name in self._specifications:
             del self._specifications[module_name]
+
+    def have_specification(self, module_name):
+        """Returns True if we have a specification for the module with the given name.
+           Returns False if we do not."""
+        return module_name in self._specifications
 
     def get_module_spec(self, module):
         """Returns the ModuleSpec for the module with the given name.

Modified: branches/trac232/src/lib/python/isc/config/module_spec.py
==============================================================================
--- branches/trac232/src/lib/python/isc/config/module_spec.py (original)
+++ branches/trac232/src/lib/python/isc/config/module_spec.py Wed Sep  1 00:35:07 2010
@@ -21,7 +21,8 @@
    set of data against the specification
 """
 
-import ast
+import json
+import sys
 
 import isc.cc.data
 
@@ -37,19 +38,30 @@
 def module_spec_from_file(spec_file, check = True):
     """Returns a ModuleSpec object defined by the file at spec_file.
        If check is True, the contents are verified. If there is an error
-       in those contents, a ModuleSpecError is raised."""
+       in those contents, a ModuleSpecError is raised.
+       A ModuleSpecError is also raised if the file cannot be read, or
+       if it is not valid JSON."""
     module_spec = None
-    if hasattr(spec_file, 'read'):
-        module_spec = ast.literal_eval(spec_file.read(-1))
-    elif type(spec_file) == str:
-        file = open(spec_file)
-        module_spec = ast.literal_eval(file.read(-1))
-        file.close()
-    else:
-        raise ModuleSpecError("spec_file not a str or file-like object")
+    try:
+        if hasattr(spec_file, 'read'):
+            json_str = spec_file.read()
+            module_spec = json.loads(json_str)
+        elif type(spec_file) == str:
+            file = open(spec_file)
+            json_str = file.read()
+            print("[XX] LOADING: " + spec_file)
+            module_spec = json.loads(json_str)
+            file.close()
+        else:
+            raise ModuleSpecError("spec_file not a str or file-like object")
+    except ValueError as ve:
+        raise ModuleSpecError("JSON parse error: " + str(ve))
+    except IOError as ioe:
+        raise ModuleSpecError("JSON read error: " + str(ioe))
+
     if 'module_spec' not in module_spec:
         raise ModuleSpecError("Data definition has no module_spec element")
-        
+
     result = ModuleSpec(module_spec['module_spec'], check)
     return result
 

Modified: branches/trac232/src/lib/python/isc/config/tests/Makefile.am
==============================================================================
--- branches/trac232/src/lib/python/isc/config/tests/Makefile.am (original)
+++ branches/trac232/src/lib/python/isc/config/tests/Makefile.am Wed Sep  1 00:35:07 2010
@@ -11,5 +11,6 @@
 	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 \
-	$(PYCOVERAGE) $(abs_srcdir)/$$pytest ; \
+	CONFIG_WR_TESTDATA_PATH=$(abs_top_builddir)/src/lib/config/testdata \
+	$(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
 	done

Modified: branches/trac232/src/lib/python/isc/config/tests/ccsession_test.py
==============================================================================
--- branches/trac232/src/lib/python/isc/config/tests/ccsession_test.py (original)
+++ branches/trac232/src/lib/python/isc/config/tests/ccsession_test.py Wed Sep  1 00:35:07 2010
@@ -22,6 +22,7 @@
 import unittest
 import os
 from isc.config.ccsession import *
+from isc.config.config_data import BIND10_CONFIG_DATA_VERSION
 from unittest_fakesession import FakeModuleCCSession
 
 class TestHelperFunctions(unittest.TestCase):
@@ -442,20 +443,20 @@
     def create_uccs2(self, fake_conn):
         module_spec = isc.config.module_spec_from_file(self.spec_file("spec2.spec"))
         fake_conn.set_get_answer('/module_spec', { module_spec.get_module_name(): module_spec.get_full_spec()})
-        fake_conn.set_get_answer('/config_data', { 'version': 1 })
+        fake_conn.set_get_answer('/config_data', { 'version': BIND10_CONFIG_DATA_VERSION })
         return UIModuleCCSession(fake_conn)
 
     def test_init(self):
         fake_conn = fakeUIConn()
         fake_conn.set_get_answer('/module_spec', {})
-        fake_conn.set_get_answer('/config_data', { 'version': 1 })
+        fake_conn.set_get_answer('/config_data', { 'version': BIND10_CONFIG_DATA_VERSION })
         uccs = UIModuleCCSession(fake_conn)
         self.assertEqual({}, uccs._specifications)
-        self.assertEqual({ 'version': 1}, uccs._current_config)
+        self.assertEqual({ 'version': BIND10_CONFIG_DATA_VERSION}, uccs._current_config)
 
         module_spec = isc.config.module_spec_from_file(self.spec_file("spec2.spec"))
         fake_conn.set_get_answer('/module_spec', { module_spec.get_module_name(): module_spec.get_full_spec()})
-        fake_conn.set_get_answer('/config_data', { 'version': 1 })
+        fake_conn.set_get_answer('/config_data', { 'version': BIND10_CONFIG_DATA_VERSION })
         uccs = UIModuleCCSession(fake_conn)
         self.assertEqual(module_spec._module_spec, uccs._specifications['Spec2']._module_spec)
 

Modified: branches/trac232/src/lib/python/isc/config/tests/cfgmgr_test.py
==============================================================================
--- branches/trac232/src/lib/python/isc/config/tests/cfgmgr_test.py (original)
+++ branches/trac232/src/lib/python/isc/config/tests/cfgmgr_test.py Wed Sep  1 00:35:07 2010
@@ -22,24 +22,26 @@
 import unittest
 import os
 from isc.config.cfgmgr import *
+from isc.config import config_data
 from unittest_fakesession import FakeModuleCCSession
 
 class TestConfigManagerData(unittest.TestCase):
     def setUp(self):
         self.data_path = os.environ['CONFIG_TESTDATA_PATH']
-        self.config_manager_data = ConfigManagerData(self.data_path)
+        self.writable_data_path = os.environ['CONFIG_WR_TESTDATA_PATH']
+        self.config_manager_data = ConfigManagerData(self.writable_data_path)
         self.assert_(self.config_manager_data)
 
     def test_init(self):
         self.assertEqual(self.config_manager_data.data['version'],
-                         ConfigManagerData.CONFIG_VERSION)
+                         config_data.BIND10_CONFIG_DATA_VERSION)
         self.assertEqual(self.config_manager_data.data_path,
-                         self.data_path)
+                         self.writable_data_path)
         self.assertEqual(self.config_manager_data.db_filename,
-                         self.data_path + os.sep + "b10-config.db")
+                         self.writable_data_path + os.sep + "b10-config.db")
 
     def test_read_from_file(self):
-        ConfigManagerData.read_from_file(self.data_path)
+        ConfigManagerData.read_from_file(self.writable_data_path)
         self.assertRaises(ConfigManagerDataEmpty,
                           ConfigManagerData.read_from_file,
                           "doesnotexist")
@@ -52,12 +54,16 @@
         self.assertRaises(ConfigManagerDataReadError,
                           ConfigManagerData.read_from_file,
                           self.data_path, "b10-config-bad3.db")
+        self.assertRaises(ConfigManagerDataReadError,
+                          ConfigManagerData.read_from_file,
+                          self.data_path, "b10-config-bad4.db")
 
     def test_write_to_file(self):
-        output_file_name = "b10-config-write-test";
+        output_file_name = "b10-config-write-test"
         self.config_manager_data.write_to_file(output_file_name)
         new_config = ConfigManagerData(self.data_path, output_file_name)
         self.assertEqual(self.config_manager_data, new_config)
+        os.remove(output_file_name)
 
     def test_equality(self):
         # tests the __eq__ function. Equality is only defined
@@ -79,14 +85,15 @@
 
     def setUp(self):
         self.data_path = os.environ['CONFIG_TESTDATA_PATH']
+        self.writable_data_path = os.environ['CONFIG_WR_TESTDATA_PATH']
         self.fake_session = FakeModuleCCSession()
-        self.cm = ConfigManager(self.data_path, self.fake_session)
+        self.cm = ConfigManager(self.writable_data_path, self.fake_session)
         self.name = "TestModule"
         self.spec = isc.config.module_spec_from_file(self.data_path + os.sep + "/spec2.spec")
     
     def test_init(self):
         self.assert_(self.cm.module_specs == {})
-        self.assert_(self.cm.data_path == self.data_path)
+        self.assert_(self.cm.data_path == self.writable_data_path)
         self.assert_(self.cm.config != None)
         self.assert_(self.fake_session.has_subscription("ConfigManager"))
         self.assert_(self.fake_session.has_subscription("Boss", "ConfigManager"))
@@ -161,13 +168,13 @@
         self.assertEqual(commands_spec['Spec2'], module_spec.get_commands_spec())
 
     def test_read_config(self):
-        self.assertEqual(self.cm.config.data, {'version': 1})
+        self.assertEqual(self.cm.config.data, {'version': config_data.BIND10_CONFIG_DATA_VERSION})
         self.cm.read_config()
         # due to what get written, the value here is what the last set_config command in test_handle_msg does
-        self.assertEqual(self.cm.config.data, {'TestModule': {'test': 125}, 'version': 1})
+        self.assertEqual(self.cm.config.data, {'TestModule': {'test': 125}, 'version': config_data.BIND10_CONFIG_DATA_VERSION})
         self.cm.data_path = "/no_such_path"
         self.cm.read_config()
-        self.assertEqual(self.cm.config.data, {'version': 1})
+        self.assertEqual(self.cm.config.data, {'version': config_data.BIND10_CONFIG_DATA_VERSION})
 
     def test_write_config(self):
         # tested in ConfigManagerData tests
@@ -190,9 +197,9 @@
                                 {'result': [1, 'Bad get_module_spec command, argument not a dict']})
         self._handle_msg_helper({ "command": [ "get_module_spec", { } ] },
                                 {'result': [1, 'Bad module_name in get_module_spec command']})
-        self._handle_msg_helper({ "command": [ "get_config" ] }, { 'result': [ 0, { 'version': 1} ]})
+        self._handle_msg_helper({ "command": [ "get_config" ] }, { 'result': [ 0, { 'version': config_data.BIND10_CONFIG_DATA_VERSION } ]})
         self._handle_msg_helper({ "command": [ "get_config", { "module_name": "nosuchmodule" } ] },
-                                {'result': [0, { 'version': 1 }]})
+                                {'result': [0, { 'version': config_data.BIND10_CONFIG_DATA_VERSION }]})
         self._handle_msg_helper({ "command": [ "get_config", 1 ] },
                                 {'result': [1, 'Bad get_config command, argument not a dict']})
         self._handle_msg_helper({ "command": [ "get_config", { } ] },
@@ -282,13 +289,14 @@
 
     def test_run(self):
         self.fake_session.group_sendmsg({ "command": [ "get_commands_spec" ] }, "ConfigManager")
+        self.fake_session.group_sendmsg({ "command": [ "shutdown" ] }, "ConfigManager")
         self.cm.run()
         pass
 
 
 if __name__ == '__main__':
-    if not 'CONFIG_TESTDATA_PATH' in os.environ:
-        print("You need to set the environment variable CONFIG_TESTDATA_PATH to point to the directory containing the test data files")
+    if not 'CONFIG_TESTDATA_PATH' in os.environ or not 'CONFIG_WR_TESTDATA_PATH' in os.environ:
+        print("You need to set the environment variable CONFIG_TESTDATA_PATH and CONFIG_WR_TESTDATA_PATH to point to the directory containing the test data files")
         exit(1)
     unittest.main()
 

Modified: branches/trac232/src/lib/python/isc/config/tests/config_data_test.py
==============================================================================
--- branches/trac232/src/lib/python/isc/config/tests/config_data_test.py (original)
+++ branches/trac232/src/lib/python/isc/config/tests/config_data_test.py Wed Sep  1 00:35:07 2010
@@ -267,12 +267,16 @@
         self.assertEqual({}, self.mcd._current_config)
         self.assertEqual({}, self.mcd._local_changes)
 
-    def test_set_specification(self):
+    def test_set_remove_specification(self):
         module_spec = isc.config.module_spec_from_file(self.data_path + os.sep + "spec1.spec")
-        self.mcd.set_specification(module_spec)
+        self.assertFalse(self.mcd.have_specification(module_spec.get_module_name()))
+        self.mcd.set_specification(module_spec)
+        self.assertTrue(self.mcd.have_specification(module_spec.get_module_name()))
         self.assert_(module_spec.get_module_name() in self.mcd._specifications)
         self.assertEquals(module_spec, self.mcd._specifications[module_spec.get_module_name()])
         self.assertRaises(ConfigDataError, self.mcd.set_specification, "asdf")
+        self.mcd.remove_specification(module_spec.get_module_name())
+        self.assertFalse(self.mcd.have_specification(module_spec.get_module_name()))
 
     def test_get_module_spec(self):
         module_spec = isc.config.module_spec_from_file(self.data_path + os.sep + "spec1.spec")

Modified: branches/trac232/src/lib/python/isc/config/tests/module_spec_test.py
==============================================================================
--- branches/trac232/src/lib/python/isc/config/tests/module_spec_test.py (original)
+++ branches/trac232/src/lib/python/isc/config/tests/module_spec_test.py Wed Sep  1 00:35:07 2010
@@ -54,6 +54,13 @@
 
     def test_open_bad_file_obj(self):
         self.assertRaises(ModuleSpecError, isc.config.module_spec_from_file, 1)
+        # contains single quotes which json parser does not accept
+        
+        self.assertRaises(ModuleSpecError, isc.config.module_spec_from_file, self.spec_file("spec28.spec"), False)
+        my_spec_file = open(self.spec_file("spec28.spec"))
+        self.assertRaises(ModuleSpecError, isc.config.module_spec_from_file, my_spec_file, False)
+
+        self.assertRaises(ModuleSpecError, isc.config.module_spec_from_file, self.spec_file("does_not_exist"), False)
 
     def test_bad_specfiles(self):
         self.assertRaises(ModuleSpecError, self.read_spec_file, "spec3.spec")

Modified: branches/trac232/src/lib/python/isc/config/tests/unittest_fakesession.py
==============================================================================
--- branches/trac232/src/lib/python/isc/config/tests/unittest_fakesession.py (original)
+++ branches/trac232/src/lib/python/isc/config/tests/unittest_fakesession.py Wed Sep  1 00:35:07 2010
@@ -1,4 +1,19 @@
+# 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$
 
 #
 # We can probably use a more general version of this

Modified: branches/trac232/src/lib/python/isc/datasrc/sqlite3_ds.py
==============================================================================
--- branches/trac232/src/lib/python/isc/datasrc/sqlite3_ds.py (original)
+++ branches/trac232/src/lib/python/isc/datasrc/sqlite3_ds.py Wed Sep  1 00:35:07 2010
@@ -17,6 +17,13 @@
 
 import sqlite3, re, random
 import isc
+
+
+#define the index of different part of one record
+RR_TYPE_INDEX = 5
+RR_NAME_INDEX = 2
+RR_TTL_INDEX = 4
+RR_RDATA_INDEX = 7
 
 #########################################################################
 # define exceptions
@@ -86,10 +93,10 @@
 
     return conn, cur
 
-
 #########################################################################
 # get_zone_datas
-#   returns all the records for one zone with the given zone name. 
+#   a generator function producing an iterable set of 
+#   the records in the zone with the given zone name.
 #########################################################################
 def get_zone_datas(zonename, dbfile):
     conn, cur = open(dbfile)
@@ -119,6 +126,39 @@
     conn.close()
 
     return datas
+
+
+#########################################################################
+# get_zone_rrset
+#   returns the rrset of the zone with the given zone name, rrset name 
+#   and given rd type. 
+#   If the zone doesn't exist or rd type doesn't exist, return an empty list. 
+#########################################################################
+def get_zone_rrset(zonename, rr_name, rdtype, dbfile):
+    conn, cur = open(dbfile)
+    id = get_zoneid(zonename, cur)
+    cur.execute("SELECT * FROM records WHERE name = ? and zone_id = ? and rdtype = ?", 
+                [rr_name, id, rdtype])
+    datas = cur.fetchall()
+    cur.close()
+    conn.close()
+    return datas
+
+
+#########################################################################
+# get_zones_info:
+#   returns all the zones' information.
+#########################################################################
+def get_zones_info(db_file):
+    conn, cur = open(db_file)
+    cur.execute("SELECT name, rdclass FROM zones")
+    info = cur.fetchone()
+    while info:
+        yield info
+        info = cur.fetchone()
+
+    cur.close()
+    conn.close()
 
 #########################################################################
 # get_zoneid:
@@ -132,7 +172,7 @@
         return row[0]
     else:
         return ''
-
+    
 #########################################################################
 # reverse_name:
 #   reverse the labels of a DNS name.  (for example,

Modified: branches/trac232/src/lib/python/isc/log/tests/Makefile.am
==============================================================================
--- branches/trac232/src/lib/python/isc/log/tests/Makefile.am (original)
+++ branches/trac232/src/lib/python/isc/log/tests/Makefile.am Wed Sep  1 00:35:07 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/trac232/src/lib/python/isc/log/tests/log_test.py
==============================================================================
--- branches/trac232/src/lib/python/isc/log/tests/log_test.py (original)
+++ branches/trac232/src/lib/python/isc/log/tests/log_test.py Wed Sep  1 00:35:07 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/trac232/src/lib/xfr/fd_share.cc
==============================================================================
--- branches/trac232/src/lib/xfr/fd_share.cc (original)
+++ branches/trac232/src/lib/xfr/fd_share.cc Wed Sep  1 00:35:07 2010
@@ -21,7 +21,7 @@
 #include <sys/socket.h>
 #include <sys/uio.h>
 #include <stdlib.h>             // for malloc and free
-#include "fd_share.h"
+#include <xfr/fd_share.h>
 
 namespace isc {
 namespace xfr {

Modified: branches/trac232/src/lib/xfr/fdshare_python.cc
==============================================================================
--- branches/trac232/src/lib/xfr/fdshare_python.cc (original)
+++ branches/trac232/src/lib/xfr/fdshare_python.cc Wed Sep  1 00:35:07 2010
@@ -18,30 +18,28 @@
 #include <Python.h>
 #include <structmember.h>
 
-#include "config.h"
+#include <config.h>
 
-#include "fd_share.h"
+#include <xfr/fd_share.h>
 
 static PyObject*
-fdshare_recv_fd(PyObject *self UNUSED_PARAM, PyObject *args)
-{
+fdshare_recv_fd(PyObject *self UNUSED_PARAM, PyObject *args) {
     int sock, fd;
     if (!PyArg_ParseTuple(args, "i", &sock)) {
-        return NULL;
+        return (NULL);
     }
     fd = isc::xfr::recv_fd(sock);
-    return Py_BuildValue("i", fd);
+    return (Py_BuildValue("i", fd));
 }
 
 static PyObject*
-fdshare_send_fd(PyObject *self UNUSED_PARAM, PyObject *args)
-{
+fdshare_send_fd(PyObject *self UNUSED_PARAM, PyObject *args) {
     int sock, fd, result;
     if (!PyArg_ParseTuple(args, "ii", &sock, &fd)) {
-        return NULL;
+        return (NULL);
     }
     result = isc::xfr::send_fd(sock, fd);
-    return Py_BuildValue("i", result);
+    return (Py_BuildValue("i", result));
 }
 
 static PyMethodDef fdshare_Methods[] = {
@@ -64,13 +62,12 @@
 };
 
 PyMODINIT_FUNC
-PyInit_libxfr_python(void)
-{
+PyInit_libxfr_python(void) {
     PyObject *mod = PyModule_Create(&bind10_fdshare_python);
     if (mod == NULL) {
-        return NULL;
+        return (NULL);
     }
 
-    return mod;
+    return (mod);
 }
 

Modified: branches/trac232/src/lib/xfr/python_xfr.cc
==============================================================================
--- branches/trac232/src/lib/xfr/python_xfr.cc (original)
+++ branches/trac232/src/lib/xfr/python_xfr.cc Wed Sep  1 00:35:07 2010
@@ -23,7 +23,7 @@
 #include <boost/python/copy_const_reference.hpp>
 #include <boost/shared_ptr.hpp>
 
-#include "fd_share.h"
+#include <xfr/fd_share.h>
 
 using namespace isc::xfr;
 using namespace boost::python;

Modified: branches/trac232/src/lib/xfr/xfrout_client.cc
==============================================================================
--- branches/trac232/src/lib/xfr/xfrout_client.cc (original)
+++ branches/trac232/src/lib/xfr/xfrout_client.cc Wed Sep  1 00:35:07 2010
@@ -22,8 +22,8 @@
 #include <unistd.h>
 #include <asio.hpp>
 
-#include "fd_share.h"
-#include "xfrout_client.h"
+#include <xfr/fd_share.h>
+#include <xfr/xfrout_client.h>
 
 using namespace std;
 using asio::local::stream_protocol;
@@ -54,24 +54,36 @@
 
 void
 XfroutClient::connect() {
-    impl_->socket_.connect(stream_protocol::endpoint(impl_->file_path_));
+    asio::error_code err;
+    impl_->socket_.connect(stream_protocol::endpoint(impl_->file_path_), err);
+    if (err) {
+        isc_throw(XfroutError, "socket connect failed: " << err.message());
+    }
 }
 
 void
 XfroutClient::disconnect() {
-    impl_->socket_.close();
+    asio::error_code err;
+    impl_->socket_.close(err);
+    if (err) {
+        isc_throw(XfroutError, "close socket failed: " << err.message());
+    }
 }
 
 int 
-XfroutClient::sendXfroutRequestInfo(const int tcp_sock, uint8_t* msg_data,
+XfroutClient::sendXfroutRequestInfo(const int tcp_sock,
+                                    const void* const msg_data,
                                     const uint16_t msg_len)
 {
     if (-1 == send_fd(impl_->socket_.native(), tcp_sock)) {
         isc_throw(XfroutError,
-                  "Fail to send the socket file descriptor to xfrout module");
+                  "Failed to send the socket file descriptor "
+                  "to xfrout module");
     }
 
-    // XXX: this shouldn't be blocking send, even though it's unlikely to block.
+    // TODO: this shouldn't be blocking send, even though it's unlikely to
+    // block.
+    // converting the 16-bit word to network byte order.
     const uint8_t lenbuf[2] = { msg_len >> 8, msg_len & 0xff };
     if (send(impl_->socket_.native(), lenbuf, sizeof(lenbuf), 0) !=
         sizeof(lenbuf)) {
@@ -89,7 +101,7 @@
                   "xfr query hasn't been processed properly by xfrout module");
     }
 
-    return 0;
+    return (0);
 }
 
 } // End for xfr

Modified: branches/trac232/src/lib/xfr/xfrout_client.h
==============================================================================
--- branches/trac232/src/lib/xfr/xfrout_client.h (original)
+++ branches/trac232/src/lib/xfr/xfrout_client.h Wed Sep  1 00:35:07 2010
@@ -34,7 +34,39 @@
         isc::Exception(file, line, what) {}
 };
 
-class XfroutClient {
+/// \brief The AbstractXfroutClient class is an abstract base class that
+/// defines the interfaces of XfroutClient.
+///
+/// The intended primary usage of abstraction is to allow tests for the
+/// user class of XfroutClient without requiring actual communication.
+class AbstractXfroutClient {
+    ///
+    /// \name Constructors, Assignment Operator and Destructor.
+    ///
+    /// Note: The copy constructor and the assignment operator are
+    /// intentionally defined as private to make it explicit that this is a
+    /// pure base class.
+    //@{
+private:
+    AbstractXfroutClient(const AbstractXfroutClient& source);
+    AbstractXfroutClient& operator=(const AbstractXfroutClient& source);
+protected:
+    /// \brief The default constructor.
+    ///
+    /// This is intentionally defined as \c protected as this base class should
+    /// never be instantiated (except as part of a derived class).
+    AbstractXfroutClient() {}
+public:
+    /// \brief The destructor.
+    virtual ~AbstractXfroutClient() {}
+    //@}
+    virtual void connect() = 0;
+    virtual void disconnect() = 0;
+    virtual int sendXfroutRequestInfo(int tcp_sock, const void* msg_data,
+                                      uint16_t msg_len) = 0;
+};
+
+class XfroutClient : public AbstractXfroutClient {
 public:
     XfroutClient(const std::string& file);
     ~XfroutClient();
@@ -43,10 +75,10 @@
     XfroutClient(const XfroutClient& source);
     XfroutClient& operator=(const XfroutClient& source);
 public:
-    void connect();
-    void disconnect();
-    int sendXfroutRequestInfo(int tcp_sock, uint8_t* msg_data,
-                              uint16_t msg_len);
+    virtual void connect();
+    virtual void disconnect();
+    virtual int sendXfroutRequestInfo(int tcp_sock, const void* msg_data,
+                                      uint16_t msg_len);
 private:
     XfroutClientImpl* impl_;
 };




More information about the bind10-changes mailing list