Commit 646a4738 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[3036] Merge branch 'master' into trac3036

Conflicts:
	src/bin/dhcp6/dhcp6_messages.mes
	src/bin/dhcp6/dhcp6_srv.cc
	src/bin/dhcp6/dhcp6_srv.h
	src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
	src/lib/dhcp_ddns/tests/ncr_unittests.cc
	src/lib/dhcpsrv/alloc_engine.cc
	src/lib/dhcpsrv/alloc_engine.h
	src/lib/dhcpsrv/tests/alloc_engine_unittest.cc
parents 2babc7e3 598e458c
656. [func] tomek
Additional hooks (buffer6_receive, lease6_renew,
lease6_release, buffer6_send) added to the DHCPv6 server.
(Trac #2984, git 540dd0449121094a56f294c500c2ed811f6016b6)
655. [func] tmark
Added D2UpdateMgr class to b10-dhcp-ddns. This class is the b10-dhcp-ddns
task master, instantiating and supervising transactions that carry out the
DNS updates needed to fulfill the requests (NameChangeRequests) received
from b10-dhcp-ddns clients (e.g. DHCP servers).
(Trac #3059 git d72675617d6b60e3eb6160305738771f015849ba)
654. [bug] stephen
Always clear "skip" flag before calling any callouts on a hook.
(Trac# 3050, git ff0b9b45869b1d9a4b99e785fbce421e184c2e93)
653. [func] tmark
Added initial implementation of D2QueueMgr to
b10-dhcp-ddns. This class manages the receipt and
queueing of requests received by b10-dhcp-ddns from
its clients (e.g. DHCP servers)
(Trac# 3052, git a970f6c5255e000c053a2dc47926cea7cec2761c)
652. [doc] stephen
Added the "Hook Developer's Guide" to the BIND 10 developer
documentation.
(Trac# 2982, git 26a805c7e49a9ec85ee825f179cda41a2358f4c6)
651. [bug] muks
A race condition when creating cmdctl certificates caused corruption
of these certificates in rare cases. This has now been fixed.
(Trac# 2962, git 09f557d871faef090ed444ebeee7f13e142184a0)
650. [func] muks
The DomainTree rebalancing code has been updated to be more
understandable. This ChangeLog entry is made just to make a note
of this change. The change should not cause any observable
difference whatsoever.
(Trac# 2811, git 7c0bad1643af13dedf9356e9fb3a51264b7481de)
649. [func] muks
The default b10-xfrout also_notify port has been changed from
0 to 53.
(Trac# 2925, git 8acbf043daf590a9f2ad003e715cd4ffb0b3f979)
648. [func] tmark
Moved classes pertaining to sending and receiving
NameChangeRequests from src/bin/d2 into their own library,
libdhcp_ddns, in src/lib/dhcp_ddns. This allows the
classes to be shared between DHDCP-DDNS and its clients,
such as the DHCP servers.
(Trac# 3065, git 3d39bccaf3f0565152ef73ec3e2cd03e77572c56)
647. [func] tmark
Added initial implementation of classes for sending
and receiving NameChangeRequests between DHCP-DDNS
and its clients such as DHCP. This includes both
abstract classes and a derivation which traffics
requests across UDP sockets.
(Trac #3008, git b54530b4539cec4476986442e72c047dddba7b48)
646. [func] stephen
Extended the hooks framework to add a "validate libraries" function.
This will be used to check libraries specified during BIND 10
configuration.
(Trac #3054, git 0f845ed94f462dee85b67f056656b2a197878b04)
645. [func] tomek
Added initial set of hooks (pkt4_receive, subnet4_select,
lease4_select, pkt4_send) to the DHCPv6 server.
(Trac #2994, git be65cfba939a6a7abd3c93931ce35c33d3e8247b)
644. [func] marcin
b10-dhcp4, b10-dhcp6: Implemented selection of the interfaces
that server listens on, using Configuration Manager. It is
possible to specify interface names explicitly or use asterisk
to specify that server should listen on all available interfaces.
Sockets are reopened according to the new configuration as
soon as it is committed.
(Trac #1555, git f48a3bff3fbbd15584d788a264d5966154394f04)
643. [bug] muks
When running some unittests as root that depended on insufficient
file permissions, the tests used to fail because the root user
could still access such files. Such tests are now skipped when
they are run as the root user.
(Trac #3056, git 92ebabdbcf6168666b03d7f7fbb31f899be39322)
642. [func] tomek
Added initial set of hooks (pkt6_receive, subnet6_select,
lease6_select, pkt6_send) to the DHCPv6 server.
(Trac #2995, git d6de376f97313ba40fef989e4a437d184fdf70cc)
641. [func] stephen
Added the hooks framework. This allows shared libraries of
user-written functions to be loaded at run-time and the
......@@ -23,13 +116,13 @@
structure of per-zone statistics.
(Trac #2884, git c0153581c3533ef045a92e68e0464aab00947cbb)
637. [func] [tmark]
637. [func] tmark
Added initial implementation of NameChangeRequest,
which embodies DNS update requests sent to DHCP-DDNS
by its clients.
(trac3007 git f33bdd59c6a8c8ea883f11578b463277d01c2b70)
636. [func] [tmark]
636. [func] tmark
Added the initial implementation of configuration parsing for
DCHP-DDNS.
(Trac #2957, git c04fb71fa44c2a458aac57ae54eeb1711c017a49)
......
......@@ -129,7 +129,7 @@ AC_SUBST(WARNING_NO_MISSING_FIELD_INITIALIZERS_CFLAG)
# gcc specific settings:
if test "X$GXX" = "Xyes"; then
B10_CXXFLAGS="$B10_CXXFLAGS -Wall -Wextra -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare"
B10_CXXFLAGS="$B10_CXXFLAGS -Wall -Wextra -Wnon-virtual-dtor -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare"
case "$host" in
*-solaris*)
MULTITHREADING_FLAG=-pthreads
......@@ -912,6 +912,17 @@ if test "x$use_shared_memory" = "xyes"; then
fi
AC_SUBST(BOOST_MAPPED_FILE_CXXFLAG)
if test "$BOOST_OFFSET_PTR_OLD" = "yes" -a "$use_shared_memory" = "yes" ; then
AC_MSG_ERROR([You're trying to compile against boost older than 1.48 with
shared memory. Older versions of boost have a bug which causes segfaults in
offset_ptr implementation when compiled by GCC with optimisations enabled.
See ticket no. 3025 for details.
Either update boost to newer version or use --without-shared-memory.
Note that most users likely don't need shared memory support.
])
fi
# Add some default CPP flags needed for Boost, identified by the AX macro.
CPPFLAGS="$CPPFLAGS $CPPFLAGS_BOOST_THREADCONF"
......@@ -1132,6 +1143,11 @@ if test "x$enable_generate_docs" != xno ; then
fi
AC_MSG_RESULT(yes)
fi
AC_PATH_PROG([ELINKS], [elinks])
if test -z "$ELINKS"; then
AC_MSG_ERROR("elinks not found; it is required for --enable-generate-docs")
fi
fi
......@@ -1295,6 +1311,7 @@ AC_CONFIG_FILES([Makefile
src/lib/python/isc/ddns/tests/Makefile
src/lib/python/isc/memmgr/Makefile
src/lib/python/isc/memmgr/tests/Makefile
src/lib/python/isc/memmgr/tests/testdata/Makefile
src/lib/python/isc/xfrin/Makefile
src/lib/python/isc/xfrin/tests/Makefile
src/lib/python/isc/server_common/Makefile
......@@ -1316,6 +1333,8 @@ AC_CONFIG_FILES([Makefile
src/lib/dns/benchmarks/Makefile
src/lib/dhcp/Makefile
src/lib/dhcp/tests/Makefile
src/lib/dhcp_ddns/Makefile
src/lib/dhcp_ddns/tests/Makefile
src/lib/dhcpsrv/Makefile
src/lib/dhcpsrv/tests/Makefile
src/lib/exceptions/Makefile
......
......@@ -661,36 +661,37 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = ../src/lib/exceptions \
INPUT = ../src/bin/auth \
../src/bin/d2 \
../src/bin/dhcp4 \
../src/bin/dhcp6 \
../src/bin/resolver \
../src/bin/sockcreator \
../src/lib/acl \
../src/lib/asiolink \
../src/lib/bench \
../src/lib/cache \
../src/lib/cc \
../src/lib/config \
../src/lib/cryptolink \
../src/lib/dns \
../src/lib/datasrc \
../src/lib/datasrc/memory \
../src/bin/auth \
../src/bin/resolver \
../src/lib/bench \
../src/lib/dhcp \
../src/lib/dhcp_ddns \
../src/lib/dhcpsrv \
../src/lib/dns \
../src/lib/exceptions \
../src/lib/hooks \
../src/lib/log \
../src/lib/log/compiler \
../src/lib/asiolink/ \
../src/lib/nsas \
../src/lib/testutils \
../src/lib/cache \
../src/lib/server_common/ \
../src/bin/sockcreator/ \
../src/lib/hooks/ \
../src/lib/util/ \
../src/lib/util/io/ \
../src/lib/util/threads/ \
../src/lib/resolve \
../src/lib/acl \
../src/lib/server_common \
../src/lib/statistics \
../src/bin/dhcp6 \
../src/lib/dhcp \
../src/lib/dhcpsrv \
../src/bin/dhcp4 \
../src/bin/d2 \
../src/lib/testutils \
../src/lib/util \
../src/lib/util/io \
../src/lib/util/threads \
../tests/tools/perfdhcp \
devel
......@@ -777,7 +778,7 @@ EXAMPLE_RECURSIVE = NO
# directories that contain image that are included in the documentation (see
# the \image command).
IMAGE_PATH = ../doc/images
IMAGE_PATH = ../doc/images ../src/lib/hooks/images
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
......
......@@ -236,7 +236,8 @@ image::auth-mapped.png[Sequence diagram for auth server using mapped memory segm
argument and the segment mode of `READ_ONLY`.
Note that the auth module handles the command argument as mostly
opaque data; it's not expected to deal with details of segment
type-specific behavior.
type-specific behavior. If the reset fails, auth aborts (as there's
no clear way to handle the failure).
6. `ConfigurableClientList::resetMemorySegment()` subsequently calls
`reset()` method on the corresponding `ZoneTableSegment` with the
......@@ -254,7 +255,8 @@ image::auth-mapped.png[Sequence diagram for auth server using mapped memory segm
underlying memory segment is swapped with a new one. The old
memory segment object is destroyed. Note that
this "destroy" just means unmapping the memory region; the data
stored in the file are intact.
stored in the file are intact. Again, if mapping fails, auth
aborts.
8. If the auth module happens to receive a reload command from other
module, it could call
......
......@@ -36,6 +36,9 @@
* Regardless of your field of expertise, you are encouraged to visit
* <a href="http://bind10.isc.org/">BIND10 webpage (http://bind10.isc.org)</a>
* @section hooksFramework Hooks Framework
* - @subpage hooksdgDevelopersGuide
* - @subpage dhcpv4Hooks
* - @subpage dhcpv6Hooks
* - @subpage hooksComponentDeveloperGuide
*
* @section dnsMaintenanceGuide DNS Maintenance Guide
......@@ -48,10 +51,12 @@
* - @subpage dhcpv4Session
* - @subpage dhcpv4ConfigParser
* - @subpage dhcpv4ConfigInherit
* - @subpage dhcpv4Other
* - @subpage dhcp6
* - @subpage dhcpv6Session
* - @subpage dhcpv6ConfigParser
* - @subpage dhcpv6ConfigInherit
* - @subpage dhcpv6Other
* - @subpage libdhcp
* - @subpage libdhcpIntro
* - @subpage libdhcpRelay
......@@ -62,6 +67,7 @@
* - @subpage allocengine
* - @subpage dhcpDatabaseBackends
* - @subpage perfdhcpInternals
* - @subpage libdhcp_ddns
*
* @section miscellaneousTopics Miscellaneous topics
* - @subpage LoggingApi
......
/bind10-guide.html
/bind10-guide.txt
/bind10-messages.html
/bind10-messages.xml
......@@ -21,10 +21,8 @@ bind10-guide.html: bind10-guide.xml
http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl \
$(srcdir)/bind10-guide.xml
HTML2TXT = elinks -dump -no-numbering -no-references
bind10-guide.txt: bind10-guide.html
$(HTML2TXT) bind10-guide.html > $@
@ELINKS@ -dump -no-numbering -no-references bind10-guide.html > $@
bind10-messages.html: bind10-messages.xml
@XSLTPROC@ --novalid --xinclude --nonet \
......
This diff is collapsed.
......@@ -31,6 +31,12 @@ dnl It is of no use if "WOULDFAIL" is yes.
dnl BOOST_STATIC_ASSERT_WOULDFAIL set to "yes" if BOOST_STATIC_ASSERT would
dnl cause build error; otherwise set to "no"
dnl BOOST_OFFSET_PTR_OLD set to "yes" if the version of boost is older than
dnl 1.48. Older versions of boost have a bug which
dnl causes segfaults in offset_ptr implementation when
dnl compiled by GCC with optimisations enabled.
dnl See ticket no. 3025 for details.
AC_DEFUN([AX_BOOST_FOR_BIND10], [
AC_LANG_SAVE
AC_LANG([C++])
......@@ -106,9 +112,21 @@ if test "X$GXX" = "Xyes"; then
BOOST_NUMERIC_CAST_WOULDFAIL=yes])
CXXFLAGS="$CXXFLAGS_SAVED"
AC_MSG_CHECKING([Boost rbtree is old])
AC_TRY_COMPILE([
#include <boost/version.hpp>
#if BOOST_VERSION < 104800
#error Too old
#endif
],,[AC_MSG_RESULT(no)
BOOST_OFFSET_PTR_OLD=no
],[AC_MSG_RESULT(yes)
BOOST_OFFSET_PTR_OLD=yes])
else
# This doesn't matter for non-g++
BOOST_NUMERIC_CAST_WOULDFAIL=no
BOOST_OFFSET_PTR_OLD=no
fi
# Boost interprocess::managed_mapped_file is highly system dependent and
......
......@@ -145,6 +145,30 @@ reconfigure, and has now started this process.
The thread for maintaining data source clients has finished reconfiguring
the data source clients, and is now running with the new configuration.
% AUTH_DATASRC_CLIENTS_BUILDER_SEGMENT_BAD_CLASS invalid RRclass %1 at segment update
A memory segment update message was sent to the authoritative
server. But the class contained there is invalid. This means that the
system is in an inconsistent state and the authoritative server aborts
to minimize the problem. This is likely caused by a bug in the code.
% AUTH_DATASRC_CLIENTS_BUILDER_SEGMENT_ERROR error updating the memory segment: %1
The authoritative server tried to update the memory segment, but the update
failed. The authoritative server aborts to avoid system inconsistency. This is
likely caused by a bug in the code.
% AUTH_DATASRC_CLIENTS_BUILDER_SEGMENT_NO_DATASRC there's no data source named %2 in class %1
The authoritative server was asked to update the memory segment of the
given data source, but no data source by that name was found. The
authoritative server aborts because this indicates that the system is in
an inconsistent state. This is likely caused by a bug in the code.
% AUTH_DATASRC_CLIENTS_BUILDER_SEGMENT_UNKNOWN_CLASS unknown class %1 at segment update
A memory segment update message was sent to the authoritative
server. The class name for which the update should happen is valid, but
no client lists are configured for that class. The system is in an
inconsistent state and the authoritative server aborts. This may be
caused by a bug in the code.
% AUTH_DATASRC_CLIENTS_BUILDER_STARTED data source builder thread started
A separate thread for maintaining data source clients has been started.
......
......@@ -306,6 +306,8 @@ public:
MessageAttributes& stats_attrs,
const bool done);
/// Are we currently subscribed to the SegmentReader group?
bool readers_group_subscribed_;
private:
bool xfrout_connected_;
AbstractXfroutClient& xfrout_client_;
......@@ -322,6 +324,7 @@ AuthSrvImpl::AuthSrvImpl(AbstractXfroutClient& xfrout_client,
datasrc_clients_mgr_(io_service_),
ddns_base_forwarder_(ddns_forwarder),
ddns_forwarder_(NULL),
readers_group_subscribed_(false),
xfrout_connected_(false),
xfrout_client_(xfrout_client)
{}
......@@ -372,28 +375,11 @@ public:
{}
};
// This is a derived class of \c SimpleCallback, to serve
// as a callback in the asiolink module. It checks for queued
// configuration messages, and executes them if found.
class ConfigChecker : public SimpleCallback {
public:
ConfigChecker(AuthSrv* srv) : server_(srv) {}
virtual void operator()(const IOMessage&) const {
ModuleCCSession* cfg_session = server_->getConfigSession();
if (cfg_session != NULL && cfg_session->hasQueuedMsgs()) {
cfg_session->checkCommand();
}
}
private:
AuthSrv* server_;
};
AuthSrv::AuthSrv(isc::xfr::AbstractXfroutClient& xfrout_client,
isc::util::io::BaseSocketSessionForwarder& ddns_forwarder) :
dnss_(NULL)
{
impl_ = new AuthSrvImpl(xfrout_client, ddns_forwarder);
checkin_ = new ConfigChecker(this);
dns_lookup_ = new MessageLookup(this);
dns_answer_ = new MessageAnswer(this);
}
......@@ -405,7 +391,6 @@ AuthSrv::stop() {
AuthSrv::~AuthSrv() {
delete impl_;
delete checkin_;
delete dns_lookup_;
delete dns_answer_;
}
......@@ -939,3 +924,64 @@ void
AuthSrv::setTCPRecvTimeout(size_t timeout) {
dnss_->setTCPRecvTimeout(timeout);
}
namespace {
bool
hasMappedSegment(auth::DataSrcClientsMgr& mgr) {
auth::DataSrcClientsMgr::Holder holder(mgr);
const std::vector<dns::RRClass>& classes(holder.getClasses());
BOOST_FOREACH(const dns::RRClass& rrclass, classes) {
const boost::shared_ptr<datasrc::ConfigurableClientList>&
list(holder.findClientList(rrclass));
const std::vector<DataSourceStatus>& states(list->getStatus());
BOOST_FOREACH(const datasrc::DataSourceStatus& status, states) {
if (status.getSegmentState() != datasrc::SEGMENT_UNUSED &&
status.getSegmentType() == "mapped")
// We use some segment and it's not a local one, so it
// must be remote.
return true;
}
}
// No remote segment found in any of the lists
return false;
}
}
void
AuthSrv::listsReconfigured() {
const bool has_remote = hasMappedSegment(impl_->datasrc_clients_mgr_);
if (has_remote && !impl_->readers_group_subscribed_) {
impl_->config_session_->subscribe("SegmentReader");
impl_->config_session_->
setUnhandledCallback(boost::bind(&AuthSrv::foreignCommand, this,
_1, _2, _3));
impl_->readers_group_subscribed_ = true;
} else if (!has_remote && impl_->readers_group_subscribed_) {
impl_->config_session_->unsubscribe("SegmentReader");
impl_->config_session_->
setUnhandledCallback(isc::config::ModuleCCSession::
UnhandledCallback());
impl_->readers_group_subscribed_ = false;
}
}
void
AuthSrv::reconfigureDone(ConstElementPtr params) {
// ACK the segment
impl_->config_session_->
groupSendMsg(isc::config::createCommand("segment_info_update_ack",
params), "MemMgr");
}
void
AuthSrv::foreignCommand(const std::string& command, const std::string&,
const ConstElementPtr& params)
{
if (command == "segment_info_update") {
impl_->datasrc_clients_mgr_.
segmentInfoUpdate(params, boost::bind(&AuthSrv::reconfigureDone,
this, params));
}
}
......@@ -190,9 +190,6 @@ public:
/// \brief Return pointer to the DNS Answer callback function
isc::asiodns::DNSAnswer* getDNSAnswerProvider() const { return (dns_answer_); }
/// \brief Return pointer to the Checkin callback function
isc::asiolink::SimpleCallback* getCheckinProvider() const { return (checkin_); }
/// \brief Return data source clients manager.
///
/// \throw None
......@@ -273,9 +270,19 @@ public:
/// open forever.
void setTCPRecvTimeout(size_t timeout);
/// \brief Notify the authoritative server that the client lists were
/// reconfigured.
///
/// This is to be called when the work thread finishes reconfiguration
/// of the data sources. It involeves some book keeping and asking the
/// memory manager for segments, if some are remotely mapped.
void listsReconfigured();
private:
void reconfigureDone(isc::data::ConstElementPtr request);
void foreignCommand(const std::string& command, const std::string&,
const isc::data::ConstElementPtr& params);
AuthSrvImpl* impl_;
isc::asiolink::SimpleCallback* checkin_;
isc::asiodns::DNSLookup* dns_lookup_;
isc::asiodns::DNSAnswer* dns_answer_;
isc::asiodns::DNSServiceBase* dnss_;
......
......@@ -20,7 +20,7 @@
<refentry>
<refentryinfo>
<date>May 22, 2013</date>
<date>July 16, 2013</date>
</refentryinfo>
<refmeta>
......@@ -81,8 +81,8 @@
<varlistentry>
<term><option>-v</option></term>
<listitem><para>
Enable verbose logging mode. This enables logging of
diagnostic messages at the maximum debug level.
Enable verbose logging mode. This enables logging of
diagnostic messages at the maximum debug level.
</para></listitem>
</varlistentry>
......@@ -250,15 +250,24 @@
</para>
<para>
The <quote>qryrecursion</quote> counter is limited to queries
(requests of opcode 0) even though the RD bit is not specific
to queries. In practice, this bit is generally just ignored for
other types of requests, while DNS servers behave differently
for queries depending on this bit. It is also known that
some authoritative-only servers receive a non negligible
number of queries with the RD bit being set, so it would be
of particular interest to have a specific counters for such
requests.
The <quote>qryrecursion</quote> counter is limited to queries
(requests of opcode 0) even though the RD bit is not specific
to queries. In practice, this bit is generally just ignored for
other types of requests, while DNS servers behave differently
for queries depending on this bit. It is also known that
some authoritative-only servers receive a non negligible
number of queries with the RD bit being set, so it would be
of particular interest to have a specific counters for such
requests.
</para>
<para>
There are two request counters related to EDNS:
<quote>request.edns0</quote> and <quote>request.badednsver</quote>.
The latter is a counter of requests with unsupported EDNS version:
other than version 0 in the current implementation. Therefore, total
number of requests with EDNS is a sum of <quote>request.edns0</quote>
and <quote>request.badednsver</quote>.
</para>
</note>
......
......@@ -81,6 +81,7 @@ enum CommandID {
LOADZONE, ///< Load a new version of zone into a memory,
/// the argument to the command is a map containing 'class'
/// and 'origin' elements, both should have been validated.
SEGMENT_INFO_UPDATE, ///< The memory manager sent an update about segments.
SHUTDOWN, ///< Shutdown the builder; no argument
NUM_COMMANDS
};
......@@ -212,6 +213,24 @@ public:
return (it->second);
}
}
/// \brief Return list of classes that are present.
///
/// Get the list of classes for which there's a client list. It is
/// returned in form of a vector, copied from the internals. As the
/// number of classes in there is expected to be small, it is not
/// a performance issue.
///
/// \return The list of classes.
/// \throw std::bad_alloc for problems allocating the result.
std::vector<dns::RRClass> getClasses() const {
std::vector<dns::RRClass> result;
for (ClientListsMap::const_iterator it =
mgr_.clients_map_->begin(); it != mgr_.clients_map_->end();
++it) {
result.push_back(it->first);
}
return (result);
}
private:
DataSrcClientsMgrBase& mgr_;
typename MutexType::Locker locker_;
......@@ -381,6 +400,36 @@ public:
sendCommand(datasrc_clientmgr_internal::LOADZONE, args, callback);
}
void segmentInfoUpdate(const data::ConstElementPtr& args,
const datasrc_clientmgr_internal::FinishedCallback&
callback =
datasrc_clientmgr_internal::FinishedCallback()) {
// Some minimal validation
if (!args) {
isc_throw(CommandError, "segmentInfoUpdate argument empty");
}
if (args->getType() != isc::data::Element::map) {
isc_throw(CommandError, "segmentInfoUpdate argument not a map");
}
const char* params[] = {
"data-source-name",
"data-source-class",
"segment-params",
NULL
};
for (const char** param = params; *param; ++param) {
if (!args->contains(*param)) {
isc_throw(CommandError,
"segmentInfoUpdate argument has no '" << param <<
"' value");
}
}
sendCommand(datasrc_clientmgr_inte