Browse Source

Merge branch 'master' into trac2171

Mukund Sivaraman 12 years ago
parent
commit
ab4d20907a

+ 1 - 0
.gitignore

@@ -35,3 +35,4 @@ TAGS
 /coverage-cpp-html
 /dns++.pc
 /report.info
+/logger_lockfile

+ 14 - 1
ChangeLog

@@ -1,3 +1,16 @@
+458.	[build]*	jinmei
+	BIND 10 now relies on Boost offset_ptr, which caused some new
+	portability issues.  Such issues are detected at ./configure time.
+	If ./configure stops due to this, try the following workaround:
+	- If it's about the use of mutable for a reference with clang++,
+	  upgrade Boost version to 1.44 or higher, or try a different
+	  compiler (e.g. g++ generally seems to be free from this issue)
+	- If it's about the use of "variadic templates", specify
+	  --without-werror so the warning won't be promoted to an error.
+	  Specifying BOOST_NO_USER_CONFIG in CXXFLAGS may also work
+	  (which would be the case if Boost is installed via pkgsrc)
+	(Trac #2147, git 30061d1139aad8716e97d6b620c259752fd0a3cd)
+
 457.	[build]*	muks
 	BIND 10 library names now have a "b10-" prefix. This is to avoid
 	clashes with other similarly named libraries on the system.
@@ -32,7 +45,7 @@
 	(Trac #1986, git bd6b0a5ed3481f78fb4e5cb0b18c7b6e5920f9f8)
 
 452.	[func]*		muks
-	b10-showtech: An initial implementation of the b10-showtech tool
+	isc-sysinfo: An initial implementation of the isc-sysinfo tool
 	is now available. It gathers and outputs system information which
 	can be used by future tech support staff.
 	(Trac #2062, git 144e80212746f8d55e6a59edcf689fec9f32ae95)

+ 13 - 2
configure.ac

@@ -809,6 +809,17 @@ AC_TRY_COMPILE([
  CPPFLAGS_BOOST_THREADCONF="-DBOOST_DISABLE_THREADS=1"],
 [AC_MSG_RESULT(yes)])
 
+# Boost offset_ptr is required in one library (not optional right now), and
+# it's known it doesn't compile on some platforms, depending on boost version,
+# its local configuration, and compiler.
+AC_MSG_CHECKING([Boost offset_ptr compiles])
+AC_TRY_COMPILE([
+#include <boost/interprocess/offset_ptr.hpp>
+],,
+[AC_MSG_RESULT(yes)],
+[AC_MSG_RESULT(no)
+ AC_MSG_ERROR([Failed to compile a required header file.  Try upgrading Boost to 1.44 or higher (when using clang++) or specifying --without-werror.  See the ChangeLog entry for Trac no. 2147 for more details.])])
+
 CPPFLAGS="$CPPFLAGS_SAVES $CPPFLAGS_BOOST_THREADCONF"
 AC_SUBST(BOOST_INCLUDES)
 
@@ -1078,7 +1089,7 @@ AC_CONFIG_FILES([Makefile
                  src/bin/dhcp4/tests/Makefile
                  src/bin/resolver/Makefile
                  src/bin/resolver/tests/Makefile
-                 src/bin/showtech/Makefile
+                 src/bin/sysinfo/Makefile
                  src/bin/sockcreator/Makefile
                  src/bin/sockcreator/tests/Makefile
                  src/bin/xfrin/Makefile
@@ -1216,7 +1227,7 @@ AC_OUTPUT([doc/version.ent
            src/bin/zonemgr/zonemgr.spec.pre
            src/bin/zonemgr/tests/zonemgr_test
            src/bin/zonemgr/run_b10-zonemgr.sh
-           src/bin/showtech/showtech.py
+           src/bin/sysinfo/sysinfo.py
            src/bin/stats/stats.py
            src/bin/stats/stats_httpd.py
            src/bin/bind10/bind10_src.py

+ 123 - 103
doc/guide/bind10-guide.xml

@@ -1485,134 +1485,154 @@ can use various data source backends.
 
     </section>
 
-    <section>
+    <section id='datasrc'>
       <title>Data Source Backends</title>
 
+      <para>
+        Bind 10 has the concept of data sources. A data source is a place
+        where authoritative zone data reside and where they can be served
+        from. This can be a master file, a database or something completely
+        different.
+      </para>
+
+      <para>
+        Once a query arrives, <command>b10-auth</command> goes through a
+        configured list of data sources and finds the one containing a best
+        matching zone. From the equally good ones, the first one is taken.
+        This data source is then used to answer the query.
+      </para>
+
       <note><para>
-        For the development prototype release, <command>b10-auth</command>
-        supports a SQLite3 data source backend and in-memory data source
-        backend.
+        In the development prototype release, <command>b10-auth</command>
+        can serve data from a SQLite3 data source backend and from master
+        files.
         Upcoming versions will be able to use multiple different
         data sources, such as MySQL and Berkeley DB.
       </para></note>
 
-
       <para>
-        By default, the SQLite3 backend uses the data file located at
+        The configuration is located in data_sources/classes. Each item there
+        represents one RR class and a list used to answer queries for that
+        class. The default contains two classes. The CH class contains a static
+        data source &mdash; one that serves things like
+        <quote>AUTHORS.BIND.</quote>. The IN class contains single SQLite3
+        data source with database file located at
         <filename>/usr/local/var/bind10-devel/zone.sqlite3</filename>.
-        (The full path is what was defined at build configure time for
-        <option>--localstatedir</option>.
-        The default is <filename>/usr/local/var/</filename>.)
-	This data file location may be changed by defining the
-	<quote>database_file</quote> configuration.
       </para>
 
-      <section id="in-memory-datasource">
-	<title>In-memory Data Source</title>
-
-	<para>
-<!--	  How to configure it. -->
-	  The following commands to <command>bindctl</command>
-	  provide an example of configuring an in-memory data
-	  source containing the <quote>example.com</quote> zone
-	  with the zone file named <quote>example.com.zone</quote>:
-
-<!--
-	  <screen>&gt; <userinput> config set Auth/datasources/ [{"type": "memory", "zones": [{"origin": "example.com", "file": "example.com.zone"}]}]</userinput></screen>
--->
-
-          <screen>&gt; <userinput>config add Auth/datasources</userinput>
-&gt; <userinput>config set Auth/datasources[0]/type "<option>memory</option>"</userinput>
-&gt; <userinput>config add Auth/datasources[0]/zones</userinput>
-&gt; <userinput>config set Auth/datasources[0]/zones[0]/origin "<option>example.com</option>"</userinput>
-&gt; <userinput>config set Auth/datasources[0]/zones[0]/file "<option>example.com.zone</option>"</userinput>
-&gt; <userinput>config commit</userinput></screen>
-
-	  The authoritative server will begin serving it immediately
-	  after the zone data is loaded from the master text file.
-	</para>
-
-      </section>
-
-      <section id="in-memory-datasource-with-sqlite3-backend">
-	<title>In-memory Data Source with SQLite3 Backend</title>
-
-	<para>
-<!--	  How to configure it. -->
-	  The following commands to <command>bindctl</command>
-	  provide an example of configuring an in-memory data
-	  source containing the <quote>example.org</quote> zone
-	  with a SQLite3 backend file named <quote>example.org.sqlite3</quote>:
-
-<!--
-	  <screen>&gt; <userinput> config set Auth/datasources/ [{"type": "memory", "zones": [{"origin": "example.org", "file": "example.org.sqlite3", "filetype": "sqlite3"}]}]</userinput></screen>
--->
-
-          <screen>&gt; <userinput>config add Auth/datasources</userinput>
-&gt; <userinput>config set Auth/datasources[1]/type "<option>memory</option>"</userinput>
-&gt; <userinput>config add Auth/datasources[1]/zones</userinput>
-&gt; <userinput>config set Auth/datasources[1]/zones[0]/origin "<option>example.org</option>"</userinput>
-&gt; <userinput>config set Auth/datasources[1]/zones[0]/file "<option>example.org.sqlite3</option>"</userinput>
-&gt; <userinput>config set Auth/datasources[1]/zones[0]/filetype "<option>sqlite3</option>"</userinput>
-&gt; <userinput>config commit</userinput></screen>
-
-	  The authoritative server will begin serving it immediately
-	  after the zone data is loaded from the database file.
-	</para>
-
-      </section>
-
-      <section id="in-memory-datasource-loading">
-	<title>Reloading an In-memory Data Source</title>
-
-	<para>
-	  Use the <command>Auth loadzone</command> command in
-	  <command>bindctl</command> to reload a changed master
-	  file into memory; for example:
+      <para>
+        Each data source has several options. The first one is
+        <varname>type</varname>, which specifies the type of data source to
+        use. Valid types include the ones listed below, but bind10 uses
+        dynamically loaded modules for them, so there may be more in your
+        case. This option is mandatory.
+      </para>
 
-	  <screen>&gt; <userinput>Auth loadzone origin="example.com"</userinput>
-</screen>
+      <para>
+        Another option is <varname>params</varname>. This option is type
+        specific; it holds different data depending on the type
+        above. Also, depending on the type, it could be possible to omit it.
+      </para>
 
-	</para>
+      <para>
+        There are two options related to the so-called cache. If you enable
+        cache, zone data from the data source are loaded into memory.
+        Then, when answering a query, <command>b10-auth</command> looks
+        into the memory only instead of the data source, which speeds
+        answering up. The first option is <varname>cache-enable</varname>,
+        a boolean value turning the cache on and off (off is the default).
+        The second one, <varname>cache-zones</varname>, is a list of zone
+        origins to load into in-memory. Remember that zones in the data source
+        not listed here will not be loaded and will not be available at all.
+      </para>
 
-<!--
+      <section id='datasource-types'>
+        <title>Data source types</title>
         <para>
-          The <varname>file</varname> may be an absolute path to the
-          master zone file or it is relative to the directory BIND 10 is
-          started from.
-	</para>
--->
+          As mentioned, the type used by default is <quote>sqlite3</quote>.
+          It has single configuration option inside <varname>params</varname>
+          &mdash; <varname>database_file</varname>, which contains the path
+          to the sqlite3 file containing the data.
+        </para>
 
+        <para>
+          Another type is called <quote>MasterFiles</quote>. This one is
+          slightly special. The data are stored in RFC1034 master files.
+          Because answering directly from them would be impractical,
+          this type mandates the cache to be enabled. Also, the list of
+          zones (<varname>cache-zones</varname>) should be omitted. The
+          <varname>params</varname> is a dictionary mapping from zone
+          origins to the files they reside in.
+        </para>
       </section>
-      <section id="in-memory-datasource-disabling">
-	<title>Disabling In-memory Data Sources</title>
 
+      <section id='datasrc-examples'>
+        <title>Examples</title>
         <para>
-	By default, the memory data source is disabled; it must be
-	configured explicitly.  To disable all the in-memory zones,
-	specify a null list for <varname>Auth/datasources</varname>:
+          As this is one of the more complex configurations of Bind10,
+          we show some examples. They all assume they start with default
+          configuration.
+        </para>
 
-<!-- TODO: this assumes that Auth/datasources is for memory only -->
+        <para>
+          First, let's disable the static data source
+          (<quote>VERSION.BIND</quote> and friends). As it is the only
+          data source in the CH class, we can remove the whole class.
 
-	  <screen>&gt; <userinput>config set Auth/datasources/ []</userinput>
+          <screen>&gt; <userinput>config remove data_sources/classes CH</userinput>
 &gt; <userinput>config commit</userinput></screen>
-	</para>
+        </para>
 
-	<para>
-          The following example stops serving a specific zone:
+        <para>
+          Another one, let's say our default data source contains zones
+          <quote>example.org.</quote> and <quote>example.net.</quote>.
+          We want them to be served from memory to make the answering
+          faster.
 
-	  <screen>&gt; <userinput>config remove Auth/datasources[<option>0</option>]/zones[<option>0</option>]</userinput>
+          <screen>&gt; <userinput>config set data_sources/classes/IN[0]/cache-enable true</userinput>
+&gt; <userinput>config add data_sources/classes/IN[0]/cache-zones example.org.</userinput>
+&gt; <userinput>config add data_sources/classes/IN[0]/cache-zones example.net.</userinput>
 &gt; <userinput>config commit</userinput></screen>
 
-	  (Replace the list number(s) in
-	  <varname>datasources[<replaceable>0</replaceable>]</varname>
-	  and/or <varname>zones[<replaceable>0</replaceable>]</varname>
-	  for the relevant zone as needed.)
+          Now every time the zone in the data source is changed by the
+          operator, Bind10 needs to be told to reload it, by
+          <screen>&gt; <userinput>Auth loadzone example.org</userinput></screen>
+          You don't need to do this when the zone is modified by
+          XfrIn, it does so automatically.
+        </para>
+
+        <para>
+          Now, the last example is when there are master files we want to
+          serve in addition to whatever is inside the sqlite3 database.
 
-	</para>
+          <screen>&gt; <userinput>config add data_sources/classes/IN</userinput>
+&gt; <userinput>config set data_sources/classes/IN[1]/type MasterFiles</userinput>
+&gt; <userinput>config set data_sources/classes/IN[1]/cache-enable true</userinput>
+&gt; <userinput>config set data_sources/classes/IN[1]/params { "example.org": "/path/to/example.org", "example.com": "/path/to/example.com" }</userinput>
+&gt; <userinput>config commit</userinput></screen>
 
+          Unfortunately, due to current technical limitations, the params must
+          be set as one JSON blob, it can't be edited in
+          <command>bindctl</command>. To reload a zone, you the same command
+          as above.
+        </para>
       </section>
 
+      <note>
+      <para>
+        There's also <varname>Auth/database_file</varname> configuration
+        variable, pointing to a sqlite3 database file. This is no longer
+        used by <command>b10-auth</command>, but it is left in place for
+        now, since other modules use it. Once <command>b10-xfrin</command>,
+        <command>b10-xfrout</command> and <command>b10-ddns</command>
+        are ported to the new configuration, this will disappear. But for
+        now, make sure that if you use any of these modules, the new
+        and old configuration correspond. The defaults are consistent, so
+        unless you tweaked either the new or the old configuration, you're
+        good.
+      </para>
+      </note>
+
     </section>
 
     <section>
@@ -1854,7 +1874,7 @@ http://bind10.isc.org/wiki/ScalableZoneLoadDesign#a7.2UpdatingaZone
 	The administrator doesn't have to do anything for
 	<command>b10-auth</command> to serve the new version of the
 	zone, except for the configuration such as the one described in
-	<xref linkend="in-memory-datasource-with-sqlite3-backend" />.
+	<xref linkend="datasrc" />.
       </para>
     </section>
 
@@ -1965,11 +1985,11 @@ what is XfroutClient xfr_client??
       notify <command>b10-xfrout</command> so that other secondary
       servers will be notified via the DNS NOTIFY protocol.
       In addition, if <command>b10-auth</command> serves the updated
-      zone from its in-memory cache (as described in
-      <xref linkend="in-memory-datasource-with-sqlite3-backend" />),
+      zone (as described in
+      <xref linkend="datasrc" />),
       <command>b10-ddns</command> will also
       notify <command>b10-auth</command> so that <command>b10-auth</command>
-      will re-cache the updated zone content.
+      will re-cache the updated zone content if necessary.
     </para>
 
     <para>
@@ -2548,7 +2568,7 @@ const std::string HARDCODED_SERVER_ID = "192.0.2.1";</screen>
     </section>
 
     <section id="dhcp4-limit">
-      <title>DHCPv4 Server Limitations</title> 
+      <title>DHCPv4 Server Limitations</title>
       <para>These are the current limitations of the DHCPv4 server
       software. Most of them are reflections of the early stage of
       development and should be treated as <quote>not implemented

File diff suppressed because it is too large
+ 1 - 1
doc/guide/bind10-messages.html


+ 1 - 1
src/bin/Makefile.am

@@ -1,5 +1,5 @@
 SUBDIRS = bind10 bindctl cfgmgr ddns loadzone msgq host cmdctl auth xfrin \
 	xfrout usermgr zonemgr stats tests resolver sockcreator dhcp4 dhcp6 \
-	dbutil showtech
+	dbutil sysinfo
 
 check-recursive: all-recursive

+ 13 - 4
src/bin/bindctl/bindctl.1

@@ -9,6 +9,15 @@
 .\"
 .TH "BINDCTL" "1" "June 20, 2012" "BIND10" "BIND10"
 .\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
 .\" disable hyphenation
@@ -54,7 +63,7 @@ The PEM formatted server certificate validation chain file\&.
 .PP
 \fB\-\-csv\-file\-dir\fR\fIfile\fR
 .RS 4
-The directory name in which the user/password CSV file is stored (see AUTHENTICATION)\&. By default this option doesn\'t have any value, in which case the "\&.bind10" directory under the user\'s home directory will be used\&.
+The directory name in which the user/password CSV file is stored (see AUTHENTICATION)\&. By default this option doesn\*(Aqt have any value, in which case the "\&.bind10" directory under the user\*(Aqs home directory will be used\&.
 .RE
 .PP
 \fB\-h\fR, \fB\-\-help\fR
@@ -105,17 +114,17 @@ prompt shows
 \fIparam1 = value1 , \fR\fI\fIparam2 = value2\fR\fR
 .PP
 
-\fBbindctl\fR\'s interactive interface provides command\-line completion and hints\&. Press the Tab key to get a hint for the module, command, and/or parameters\&.
+\fBbindctl\fR\*(Aqs interactive interface provides command\-line completion and hints\&. Press the Tab key to get a hint for the module, command, and/or parameters\&.
 The arrow keys and Emacs\-style editing keys may be used to edit and recall previous lines\&.
 .PP
 You can use the
 \fBhelp\fR
-keyword to receive usage assistance for a module or a module\'s command\&.
+keyword to receive usage assistance for a module or a module\*(Aqs command\&.
 .PP
 The
 \fBquit\fR
 command is used to exit
-\fBbindctl\fR\&. (It doesn\'t stop the BIND 10 services\&.)
+\fBbindctl\fR\&. (It doesn\*(Aqt stop the BIND 10 services\&.)
 .PP
 The following module is available by default:
 \fBconfig\fR

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

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

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

@@ -8,6 +8,14 @@
                 "item_type": "named_set",
                 "item_optional": false,
                 "item_default": {
+                    "IN": [
+                        {
+                            "type": "sqlite3",
+                            "params": {
+                                "database_file": "@@LOCALSTATEDIR@@/@PACKAGE@/zone.sqlite3"
+                            }
+                        }
+                    ],
                     "CH": [
                         {
                             "type": "static",

+ 9 - 0
src/bin/cmdctl/b10-cmdctl.8

@@ -9,6 +9,15 @@
 .\"
 .TH "B10\-CMDCTL" "8" "February 28, 2012" "BIND10" "BIND10"
 .\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
 .\" disable hyphenation

+ 9 - 0
src/bin/resolver/b10-resolver.8

@@ -9,6 +9,15 @@
 .\"
 .TH "B10\-RESOLVER" "8" "February 28, 2012" "BIND10" "BIND10"
 .\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
 .\" disable hyphenation

+ 0 - 2
src/bin/showtech/.gitignore

@@ -1,2 +0,0 @@
-/b10-showtech
-/showtech.py

+ 2 - 0
src/bin/sysinfo/.gitignore

@@ -0,0 +1,2 @@
+/isc-sysinfo
+/sysinfo.py

+ 5 - 5
src/bin/showtech/Makefile.am

@@ -1,14 +1,14 @@
-bin_SCRIPTS = b10-showtech
+bin_SCRIPTS = isc-sysinfo
 
-CLEANFILES = b10-showtech showtech.pyc
+CLEANFILES = isc-sysinfo sysinfo.pyc
 
 # this is done here since configure.ac AC_OUTPUT doesn't expand exec_prefix
-b10-showtech: showtech.py
-	$(SED) -e "s|@@PYTHONPATH@@|@pyexecdir@|" showtech.py >$@
+isc-sysinfo: sysinfo.py
+	$(SED) -e "s|@@PYTHONPATH@@|@pyexecdir@|" sysinfo.py >$@
 	chmod a+x $@
 
 MAN1_FILES = \
-	b10-showtech.xml
+	isc-sysinfo.xml
 
 man_MANS = \
 	$(MAN1_FILES:.xml=.1)

+ 9 - 9
src/bin/showtech/b10-showtech.1

@@ -1,13 +1,13 @@
 '\" t
-.\"     Title: b10-showtech
+.\"     Title: isc-sysinfo
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.76.1 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
 .\"      Date: June 26, 2012
 .\"    Manual: BIND10
 .\"    Source: BIND10
 .\"  Language: English
 .\"
-.TH "B10\-SHOWTECH" "1" "June 26, 2012" "BIND10" "BIND10"
+.TH "ISC\-SYSINFO" "1" "June 26, 2012" "BIND10" "BIND10"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -28,14 +28,14 @@
 .\" * MAIN CONTENT STARTS HERE *
 .\" -----------------------------------------------------------------
 .SH "NAME"
-b10-showtech \- BIND 10 system information display tool
+isc-sysinfo \- BIND 10 system information display tool
 .SH "SYNOPSIS"
-.HP \w'\fBb10\-showtech\fR\ 'u
-\fBb10\-showtech\fR
+.HP \w'\fBisc\-sysinfo\fR\ 'u
+\fBisc\-sysinfo\fR
 .SH "DESCRIPTION"
 .PP
 The
-\fBb10\-showtech\fR
+\fBisc\-sysinfo\fR
 program collects and outputs a variety of information about the system that BIND 10 is running on\&. This information can be useful to people involved in debugging and technical support\&.
 .SH "ARGUMENTS"
 .PP
@@ -47,7 +47,7 @@ Displays usage instructions\&.
 \-o \fIoutput\-file\fR
 .RS 4
 If an output file is specified, the output of
-\fBb10\-showtech\fR
+\fBisc\-sysinfo\fR
 is written to this file\&. By default, the output is written to standard output\&.
 .RE
 .SH "SEE ALSO"
@@ -58,7 +58,7 @@ BIND 10 Guide\&.
 .SH "HISTORY"
 .PP
 The
-\fBb10\-showtech\fR
+\fBisc\-sysinfo\fR
 daemon was initially implemented by ISC staff in June, 2012\&.
 .SH "COPYRIGHT"
 .br

+ 6 - 6
src/bin/showtech/b10-showtech.xml

@@ -24,13 +24,13 @@
   </refentryinfo>
 
   <refmeta>
-    <refentrytitle>b10-showtech</refentrytitle>
+    <refentrytitle>isc-sysinfo</refentrytitle>
     <manvolnum>1</manvolnum>
     <refmiscinfo>BIND10</refmiscinfo>
   </refmeta>
 
   <refnamediv>
-    <refname>b10-showtech</refname>
+    <refname>isc-sysinfo</refname>
     <refpurpose>BIND 10 system information display tool</refpurpose>
   </refnamediv>
 
@@ -43,14 +43,14 @@
 
   <refsynopsisdiv>
     <cmdsynopsis>
-      <command>b10-showtech</command>
+      <command>isc-sysinfo</command>
     </cmdsynopsis>
   </refsynopsisdiv>
 
   <refsect1>
     <title>DESCRIPTION</title>
     <para>
-      The <command>b10-showtech</command> program collects and outputs a
+      The <command>isc-sysinfo</command> program collects and outputs a
       variety of information about the system that BIND 10 is running
       on. This information can be useful to people involved in debugging
       and technical support.
@@ -73,7 +73,7 @@
         <term>-o <replaceable class="parameter">output-file</replaceable></term>
         <listitem><para>
           If an output file is specified, the output
-          of <command>b10-showtech</command> is written to this file. By
+          of <command>isc-sysinfo</command> is written to this file. By
           default, the output is written to standard output.
         </para></listitem>
       </varlistentry>
@@ -95,7 +95,7 @@
   <refsect1>
     <title>HISTORY</title>
     <para>
-      The <command>b10-showtech</command> daemon was initially
+      The <command>isc-sysinfo</command> daemon was initially
       implemented by ISC staff in June, 2012.
     </para>
   </refsect1>

+ 1 - 1
src/bin/showtech/showtech.py.in

@@ -16,7 +16,7 @@
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 """
-BIND 10 showtech program.
+ISC sysinfo program.
 
 """
 

+ 10 - 1
src/bin/zonemgr/b10-zonemgr.8

@@ -9,6 +9,15 @@
 .\"
 .TH "B10\-ZONEMGR" "8" "February 28, 2012" "BIND10" "BIND10"
 .\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
 .\" disable hyphenation
@@ -92,7 +101,7 @@ The configuration commands are:
 (sent by
 \fBb10-auth\fR(8)) tells
 \fBb10\-zonemgr\fR
-the zone name and class, and the IP address for the master (source of the NOTIFY message)\&. This will set the zone\'s refresh time to now\&.
+the zone name and class, and the IP address for the master (source of the NOTIFY message)\&. This will set the zone\*(Aqs refresh time to now\&.
 This is an internal command and not exposed to the administrator\&.
 .PP
 

+ 2 - 1
src/lib/datasrc/tests/testdata/.gitignore

@@ -1 +1,2 @@
-/*.sqlite3.copied
+/*.copied
+

+ 1 - 1
src/lib/dhcp/pkt6.h

@@ -139,7 +139,7 @@ public:
     /// Returns value of transaction-id field
     ///
     /// @return transaction-id
-    uint32_t getTransid() { return (transid_); };
+    uint32_t getTransid() const { return (transid_); };
 
     /// Adds an option to this packet.
     ///

+ 1 - 0
src/lib/testutils/testdata/.gitignore

@@ -1,5 +1,6 @@
 /auth_test.sqlite3.copied
 /badExampleQuery_fromWire.wire
+/does-not-exist.sqlite3
 /examplequery_fromWire.wire
 /iquery_fromWire.wire
 /iquery_response_fromWire.wire

+ 3 - 0
tests/lettuce/configurations/bindctl/bindctl.config.orig

@@ -14,6 +14,9 @@
             "address": "127.0.0.1"
         } ]
     },
+    "data_sources": {
+        "classes": {}
+    },
     "Boss": {
         "components": {
             "b10-cmdctl": { "special": "cmdctl", "kind": "needed" }

+ 3 - 0
tests/lettuce/configurations/bindctl_commands.config.orig

@@ -14,6 +14,9 @@
             "address": "127.0.0.1"
         } ]
     },
+    "data_sources": {
+        "classes": {}
+    },
     "StatsHttpd": {
         "listen_on": [ {
             "port": 47811,

+ 2 - 0
tests/tools/perfdhcp/Makefile.am

@@ -24,8 +24,10 @@ libb10_perfdhcp___la_SOURCES += localized_option.h
 libb10_perfdhcp___la_SOURCES += perf_pkt6.cc perf_pkt6.h
 libb10_perfdhcp___la_SOURCES += perf_pkt4.cc perf_pkt4.h
 libb10_perfdhcp___la_SOURCES += pkt_transform.cc pkt_transform.h
+libb10_perfdhcp___la_SOURCES += stats_mgr.h
 
 libb10_perfdhcp___la_CXXFLAGS = $(AM_CXXFLAGS)
+
 if USE_CLANGPP
 # Disable unused parameter warning caused by some of the
 # Boost headers when compiling with clang.

File diff suppressed because it is too large
+ 1137 - 0
tests/tools/perfdhcp/stats_mgr.h


+ 1 - 0
tests/tools/perfdhcp/tests/Makefile.am

@@ -21,6 +21,7 @@ run_unittests_SOURCES += command_options_unittest.cc
 run_unittests_SOURCES += perf_pkt6_unittest.cc
 run_unittests_SOURCES += perf_pkt4_unittest.cc
 run_unittests_SOURCES += localized_option_unittest.cc
+run_unittests_SOURCES += stats_mgr_unittest.cc
 run_unittests_SOURCES += $(top_builddir)/tests/tools/perfdhcp/command_options.cc
 run_unittests_SOURCES += $(top_builddir)/tests/tools/perfdhcp/pkt_transform.cc
 run_unittests_SOURCES += $(top_builddir)/tests/tools/perfdhcp/perf_pkt6.cc

+ 450 - 0
tests/tools/perfdhcp/tests/stats_mgr_unittest.cc

@@ -0,0 +1,450 @@
+// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <boost/shared_ptr.hpp>
+
+#include <exceptions/exceptions.h>
+#include <dhcp/dhcp4.h>
+#include <dhcp/dhcp6.h>
+#include <dhcp/pkt4.h>
+#include <dhcp/pkt6.h>
+
+#include <gtest/gtest.h>
+
+#include "../stats_mgr.h"
+
+using namespace std;
+using namespace isc;
+using namespace isc::dhcp;
+using namespace isc::perfdhcp;
+
+namespace {
+
+typedef StatsMgr<dhcp::Pkt4> StatsMgr4;
+typedef StatsMgr<dhcp::Pkt6> StatsMgr6;
+
+const uint32_t common_transid = 123;
+
+class StatsMgrTest : public ::testing::Test {
+public:
+    StatsMgrTest() {
+    }
+
+    /// \brief Create DHCPv4 packet.
+    ///
+    /// Method creates DHCPv4 packet and updates its timestamp.
+    ///
+    /// \param msg_type DHCPv4 message type.
+    /// \param transid transaction id for the packet.
+    /// \return DHCPv4 packet.
+    Pkt4* createPacket4(const uint8_t msg_type,
+                        const uint32_t transid) {
+        Pkt4* pkt = new Pkt4(msg_type, transid);
+        // Packet timestamp is normally updated by interface
+        // manager on packets reception or send. Unit tests
+        // do not use interface manager so we need to do it
+        // ourselfs.
+        pkt->updateTimestamp();
+        return pkt;
+    }
+
+    /// \brief Create DHCPv6 packet.
+    ///
+    /// Method creates DHCPv6 packet and updates its timestamp.
+    ///
+    /// \param msg_type DHCPv6 message type.
+    /// \param transid transaction id.
+    /// \return DHCPv6 packet.
+    Pkt6* createPacket6(const uint8_t msg_type,
+                        const uint32_t transid) {
+        Pkt6* pkt = new Pkt6(msg_type, transid);
+        // Packet timestamp is normally updated by interface
+        // manager on packets reception or send. Unit tests
+        // do not use interface manager so we need to do it
+        // ourselfs.
+        pkt->updateTimestamp();
+        return pkt;
+    }
+
+    /// \brief Pass multiple DHCPv6 packets to Statistics Manager.
+    ///
+    /// Method simulates sending or receiving  multiple DHCPv6 packets.
+    ///
+    /// \param stats_mgr Statistics Manager instance to be used.
+    /// \param xchg_type packet exchange types.
+    /// \param packet_type DHCPv6 packet type.
+    /// \param num_packets packets to be passed to Statistics Manager.
+    /// \param receive simulated packets are received (if true)
+    /// or sent (if false)
+    void passMultiplePackets6(const boost::shared_ptr<StatsMgr6> stats_mgr,
+                              const StatsMgr6::ExchangeType xchg_type,
+                              const uint8_t packet_type,
+                              const int num_packets,
+                              const bool receive = false) {
+        for (int i = 0; i < num_packets; ++i) {
+            boost::shared_ptr<Pkt6>
+                packet(createPacket6(packet_type, i));
+
+            if (receive) {
+                ASSERT_NO_THROW(
+                    stats_mgr->passRcvdPacket(xchg_type, packet);
+                );
+            } else {
+                ASSERT_NO_THROW(
+                    stats_mgr->passSentPacket(xchg_type, packet)
+                );
+            }
+        }
+    }
+
+    /// \brief Simulate DHCPv4 DISCOVER-OFFER with delay.
+    ///
+    /// Method simulates DHCPv4 DISCOVER-OFFER exchange. The OFFER packet
+    /// creation is delayed by the specified number of seconds. This imposes
+    /// different packet timestamps and affects delay counters in Statistics
+    /// Manager.
+    ///
+    /// \param stats_mgr Statistics Manager instance.
+    /// \param delay delay in seconds between DISCOVER and OFFER packets.
+    void passDOPacketsWithDelay(const boost::shared_ptr<StatsMgr4> stats_mgr,
+                                unsigned int delay,
+                                uint32_t transid) {
+        boost::shared_ptr<Pkt4> sent_packet(createPacket4(DHCPDISCOVER,
+                                                      transid));
+        ASSERT_NO_THROW(
+            stats_mgr->passSentPacket(StatsMgr4::XCHG_DO, sent_packet)
+        );
+
+        // There is way to differentiate timstamps of two packets other than
+        // sleep for before we create another packet. Packet is using current
+        // time to update its timestamp.
+        // Sleeping for X seconds will guarantee that delay between packets
+        // will be greater than 1 second. Note that posix time value is
+        // transformed to double value and it makes it hard to determine
+        // actual value to expect.
+        std::cout << "Sleeping for " << delay << "s to test packet delays"
+                  << std::endl;
+        sleep(delay);
+
+        boost::shared_ptr<Pkt4> rcvd_packet(createPacket4(DHCPOFFER,
+                                                      transid));
+        ASSERT_NO_THROW(
+            stats_mgr->passRcvdPacket(StatsMgr4::XCHG_DO, rcvd_packet);
+        );
+
+        // Calculate period between packets.
+        boost::posix_time::ptime sent_time = sent_packet->getTimestamp();
+        boost::posix_time::ptime rcvd_time = rcvd_packet->getTimestamp();
+
+        ASSERT_FALSE(sent_time.is_not_a_date_time());
+        ASSERT_FALSE(rcvd_time.is_not_a_date_time());
+    }
+
+};
+
+TEST_F(StatsMgrTest, Constructor) {
+    boost::scoped_ptr<StatsMgr4> stats_mgr(new StatsMgr4());
+    stats_mgr->addExchangeStats(StatsMgr4::XCHG_DO);
+    EXPECT_DOUBLE_EQ(
+        std::numeric_limits<double>::max(),
+        stats_mgr->getMinDelay(StatsMgr4::XCHG_DO)
+    );
+    EXPECT_DOUBLE_EQ(0, stats_mgr->getMaxDelay(StatsMgr4::XCHG_DO));
+    EXPECT_EQ(0, stats_mgr->getOrphans(StatsMgr4::XCHG_DO));
+    EXPECT_EQ(0, stats_mgr->getOrderedLookups(StatsMgr4::XCHG_DO));
+    EXPECT_EQ(0, stats_mgr->getUnorderedLookups(StatsMgr4::XCHG_DO));
+    EXPECT_EQ(0, stats_mgr->getSentPacketsNum(StatsMgr4::XCHG_DO));
+    EXPECT_EQ(0, stats_mgr->getRcvdPacketsNum(StatsMgr4::XCHG_DO));
+
+    EXPECT_THROW(stats_mgr->getAvgDelay(StatsMgr4::XCHG_DO), InvalidOperation);
+    EXPECT_THROW(stats_mgr->getStdDevDelay(StatsMgr4::XCHG_DO),
+                 InvalidOperation);
+    EXPECT_THROW(stats_mgr->getAvgUnorderedLookupSetSize(StatsMgr4::XCHG_DO),
+                 InvalidOperation);
+}
+
+TEST_F(StatsMgrTest, Exchange) {
+    boost::scoped_ptr<StatsMgr4> stats_mgr(new StatsMgr4());
+    boost::shared_ptr<Pkt4> sent_packet(createPacket4(DHCPDISCOVER,
+                                                      common_transid));
+    boost::shared_ptr<Pkt4> rcvd_packet(createPacket4(DHCPOFFER,
+                                                      common_transid));
+    // This is expected to throw because XCHG_DO was not yet
+    // added to Stats Manager for tracking.
+    EXPECT_THROW(
+        stats_mgr->passSentPacket(StatsMgr4::XCHG_DO, sent_packet),
+        BadValue
+    );
+    EXPECT_THROW(
+        stats_mgr->passRcvdPacket(StatsMgr4::XCHG_DO, rcvd_packet),
+        BadValue
+    );
+
+    // Adding DISCOVER-OFFER exchanges to be tracked by Stats Manager.
+    stats_mgr->addExchangeStats(StatsMgr4::XCHG_DO);
+    // The following two attempts are expected to throw because
+    // invalid exchange types are passed (XCHG_RA instead of XCHG_DO)
+    EXPECT_THROW(
+        stats_mgr->passSentPacket(StatsMgr4::XCHG_RA, sent_packet),
+        BadValue
+    );
+    EXPECT_THROW(
+        stats_mgr->passRcvdPacket(StatsMgr4::XCHG_RA, rcvd_packet),
+        BadValue
+    );
+
+    // The following two attempts are expected to run fine because
+    // right exchange type is specified.
+    EXPECT_NO_THROW(
+        stats_mgr->passSentPacket(StatsMgr4::XCHG_DO, sent_packet)
+    );
+    EXPECT_NO_THROW(
+        stats_mgr->passRcvdPacket(StatsMgr4::XCHG_DO, rcvd_packet)
+    );
+}
+
+TEST_F(StatsMgrTest, MultipleExchanges) {
+    boost::shared_ptr<StatsMgr6> stats_mgr(new StatsMgr6());
+    stats_mgr->addExchangeStats(StatsMgr6::XCHG_SA);
+    stats_mgr->addExchangeStats(StatsMgr6::XCHG_RR);
+
+    // Simulate sending number of solicit packets.
+    const int solicit_packets_num = 10;
+    passMultiplePackets6(stats_mgr, StatsMgr6::XCHG_SA, DHCPV6_SOLICIT,
+                         solicit_packets_num);
+
+    // Simulate sending number of request packets. It is important that
+    // number of request packets is different then number of solicit
+    // packets. We can now check if right number packets went to
+    // the right exchange type group.
+    const int request_packets_num = 5;
+    passMultiplePackets6(stats_mgr, StatsMgr6::XCHG_RR, DHCPV6_REQUEST,
+                         request_packets_num);
+
+    // Check if all packets are successfuly passed to packet lists.
+    EXPECT_EQ(solicit_packets_num,
+              stats_mgr->getSentPacketsNum(StatsMgr6::XCHG_SA));
+    EXPECT_EQ(request_packets_num,
+              stats_mgr->getSentPacketsNum(StatsMgr6::XCHG_RR));
+
+    // Simulate reception of multiple packets for both SOLICIT-ADVERTISE
+    // and REQUEST-REPLY exchanges. Assume no packet drops.
+    const bool receive_packets = true;
+    passMultiplePackets6(stats_mgr, StatsMgr6::XCHG_SA, DHCPV6_ADVERTISE,
+                         solicit_packets_num, receive_packets);
+
+    passMultiplePackets6(stats_mgr, StatsMgr6::XCHG_RR, DHCPV6_REPLY,
+                         request_packets_num, receive_packets);
+
+    // Verify that all received packets are counted.
+    EXPECT_EQ(solicit_packets_num,
+              stats_mgr->getRcvdPacketsNum(StatsMgr6::XCHG_SA));
+    EXPECT_EQ(request_packets_num,
+              stats_mgr->getRcvdPacketsNum(StatsMgr6::XCHG_RR));
+}
+
+TEST_F(StatsMgrTest, SendReceiveSimple) {
+    boost::scoped_ptr<StatsMgr4> stats_mgr(new StatsMgr4());
+    boost::shared_ptr<Pkt4> sent_packet(createPacket4(DHCPDISCOVER,
+                                                      common_transid));
+    boost::shared_ptr<Pkt4> rcvd_packet(createPacket4(DHCPOFFER,
+                                                      common_transid));
+    stats_mgr->addExchangeStats(StatsMgr4::XCHG_DO);
+    // The following attempt is expected to pass becase the right
+    // exchange type is used.
+    ASSERT_NO_THROW(
+        stats_mgr->passSentPacket(StatsMgr4::XCHG_DO, sent_packet)
+    );
+    // It is ok, to pass to received packets here. First one will
+    // be matched with sent packet. The latter one will not be
+    // matched with sent packet but orphans counter will simply
+    // increase.
+    ASSERT_NO_THROW(
+        stats_mgr->passRcvdPacket(StatsMgr4::XCHG_DO, rcvd_packet)
+    );
+    ASSERT_NO_THROW(
+        stats_mgr->passRcvdPacket(StatsMgr4::XCHG_DO, rcvd_packet)
+    );
+    EXPECT_EQ(1, stats_mgr->getOrphans(StatsMgr4::XCHG_DO));
+}
+
+TEST_F(StatsMgrTest, SendReceiveUnordered) {
+    const int packets_num = 10;
+    boost::scoped_ptr<StatsMgr4> stats_mgr(new StatsMgr4());
+    stats_mgr->addExchangeStats(StatsMgr4::XCHG_DO);
+
+    // Transaction ids of 10 packets to be sent and received.
+    uint32_t transid[packets_num] =
+        { 1, 1024, 2, 1025, 3, 1026, 4, 1027, 5, 1028 };
+    for (int i = 0; i < packets_num; ++i) {
+        boost::shared_ptr<Pkt4> sent_packet(createPacket4(DHCPDISCOVER,
+                                                          transid[i]));
+        ASSERT_NO_THROW(
+            stats_mgr->passSentPacket(StatsMgr4::XCHG_DO, sent_packet)
+        );
+    }
+
+    // We are simulating that received packets are coming in reverse order:
+    // 1028, 5, 1027 ....
+    for (int i = 0; i < packets_num; ++i) {
+        boost::shared_ptr<Pkt4>
+            rcvd_packet(createPacket4(DHCPDISCOVER,
+                                      transid[packets_num - 1 - i]));
+        ASSERT_NO_THROW(
+            stats_mgr->passRcvdPacket(StatsMgr4::XCHG_DO, rcvd_packet);
+        );
+    }
+    // All packets are expected to match (we did not drop any)
+    EXPECT_EQ(0, stats_mgr->getOrphans(StatsMgr4::XCHG_DO));
+    // Most of the time we have to do unordered lookups except for the last
+    // one. Packets are removed from the sent list every time we have a match
+    // so eventually we come up with the single packet that caching iterator
+    // is pointing to. This is counted as ordered lookup.
+    EXPECT_EQ(1, stats_mgr->getOrderedLookups(StatsMgr4::XCHG_DO));
+    EXPECT_EQ(9, stats_mgr->getUnorderedLookups(StatsMgr4::XCHG_DO));
+}
+
+TEST_F(StatsMgrTest, Orphans) {
+    const int packets_num = 6;
+    boost::scoped_ptr<StatsMgr4> stats_mgr(new StatsMgr4());
+    stats_mgr->addExchangeStats(StatsMgr4::XCHG_DO);
+
+    // We skip every second packet to simulate drops.
+    for (int i = 0; i < packets_num; i += 2) {
+        boost::shared_ptr<Pkt4> sent_packet(createPacket4(DHCPDISCOVER, i));
+        ASSERT_NO_THROW(
+            stats_mgr->passSentPacket(StatsMgr4::XCHG_DO, sent_packet)
+        );
+    }
+    // We pass all received packets.
+    for (int i = 0; i < packets_num; ++i) {
+        boost::shared_ptr<Pkt4> rcvd_packet(createPacket4(DHCPOFFER, i));
+        ASSERT_NO_THROW(
+            stats_mgr->passRcvdPacket(StatsMgr4::XCHG_DO, rcvd_packet);
+        );
+    }
+    // The half of received packets are expected not to have matching
+    // sent packet.
+    EXPECT_EQ(packets_num / 2, stats_mgr->getOrphans(StatsMgr4::XCHG_DO));
+}
+
+TEST_F(StatsMgrTest, Delays) {
+
+    boost::shared_ptr<StatsMgr4> stats_mgr(new StatsMgr4());
+    stats_mgr->addExchangeStats(StatsMgr4::XCHG_DO);
+
+    // Send DISCOVER, wait 2s and receive OFFER. This will affect
+    // counters in Stats Manager.
+    const unsigned int delay1 = 2;
+    passDOPacketsWithDelay(stats_mgr, 2, common_transid);
+
+    // Initially min delay is equal to MAX_DOUBLE. After first packets
+    // are passed, it is expected to set to actual value.
+    EXPECT_LT(stats_mgr->getMinDelay(StatsMgr4::XCHG_DO),
+              std::numeric_limits<double>::max());
+    EXPECT_GT(stats_mgr->getMinDelay(StatsMgr4::XCHG_DO), 1);
+
+    // Max delay is supposed to the same value as mininimum
+    // or maximum delay.
+    EXPECT_GT(stats_mgr->getMaxDelay(StatsMgr4::XCHG_DO), 1);
+
+    // Delay sums are now the same as minimum or maximum delay.
+    EXPECT_GT(stats_mgr->getAvgDelay(StatsMgr4::XCHG_DO), 1);
+
+    // Simulate another DISCOVER-OFFER exchange with delay between
+    // sent and received packets. Delay is now shorter than earlier
+    // so standard deviation of delay will now increase.
+    const unsigned int delay2 = 1;
+    passDOPacketsWithDelay(stats_mgr, delay2, common_transid + 1);
+    // Standard deviation is expected to be non-zero.
+    EXPECT_GT(stats_mgr->getStdDevDelay(StatsMgr4::XCHG_DO), 0);
+}
+
+TEST_F(StatsMgrTest, CustomCounters) {
+    boost::scoped_ptr<StatsMgr4> stats_mgr(new StatsMgr4());
+
+    // Specify counter keys and names.
+    const std::string too_short_key("tooshort");
+    const std::string too_short_name("Too short packets");
+    const std::string too_late_key("toolate");
+    const std::string too_late_name("Packets sent too late");
+
+    // Add two custom counters.
+    stats_mgr->addCustomCounter(too_short_key, too_short_name);
+    stats_mgr->addCustomCounter(too_late_key, too_late_name);
+
+    // Increment one of the counters 10 times.
+    const uint64_t tooshort_num = 10;
+    for (uint64_t i = 0; i < tooshort_num; ++i) {
+        stats_mgr->IncrementCounter(too_short_key);
+    }
+
+    // Increment another counter by 5 times.
+    const uint64_t toolate_num = 5;
+    for (uint64_t i = 0; i < toolate_num; ++i) {
+        stats_mgr->IncrementCounter(too_late_key);
+    }
+
+    // Check counter's current value and name.
+    StatsMgr4::CustomCounterPtr tooshort_counter =
+        stats_mgr->getCounter(too_short_key);
+    EXPECT_EQ(too_short_name, tooshort_counter->getName());
+    EXPECT_EQ(tooshort_num, tooshort_counter->getValue());
+
+    // Check counter's current value and name.
+    StatsMgr4::CustomCounterPtr toolate_counter =
+        stats_mgr->getCounter(too_late_key);
+    EXPECT_EQ(too_late_name, toolate_counter->getName());
+    EXPECT_EQ(toolate_num, toolate_counter->getValue());
+
+}
+
+TEST_F(StatsMgrTest, PrintStats) {
+    std::cout << "This unit test is checking statistics printing "
+              << "capabilities. It is expected that some counters "
+              << "will be printed during this test. It may also "
+              << "cause spurious errors." << std::endl;
+    boost::shared_ptr<StatsMgr6> stats_mgr(new StatsMgr6());
+    stats_mgr->addExchangeStats(StatsMgr6::XCHG_SA);
+
+    // Simulate sending and receiving one packet. Otherwise printing
+    // functions will complain about lack of packets.
+    const int packets_num = 1;
+    passMultiplePackets6(stats_mgr, StatsMgr6::XCHG_SA, DHCPV6_SOLICIT,
+                         packets_num);
+    passMultiplePackets6(stats_mgr, StatsMgr6::XCHG_SA, DHCPV6_ADVERTISE,
+                         packets_num, true);
+
+    // This function will print statistics even if packets are not
+    // archived because it relies on counters. There is at least one
+    // exchange needed to count the average delay and std deviation.
+    EXPECT_NO_THROW(stats_mgr->printStats());
+
+    // Printing timestamps is expected to fail because by default we
+    // disable packets archiving mode. Without packets we can't get
+    // timestamps.
+    EXPECT_THROW(stats_mgr->printTimestamps(), isc::InvalidOperation);
+
+    // Now, we create another statistics manager instance and enable
+    // packets archiving mode.
+    const bool archive_packets = true;
+    boost::shared_ptr<StatsMgr6> stats_mgr2(new StatsMgr6(archive_packets));
+    stats_mgr2->addExchangeStats(StatsMgr6::XCHG_SA);
+
+    // Timestamps should now get printed because packets have been preserved.
+    EXPECT_NO_THROW(stats_mgr2->printTimestamps());
+}
+
+
+}