[svn] commit: r1248 - in /branches/jinmei-asio: ./ src/bin/ src/bin/bind10/ src/bin/bind10/tests/ src/bin/cmdctl/ src/bin/loadzone/ src/bin/xfrin/ src/lib/auth/ src/lib/auth/testdata/ src/lib/cc/ src/lib/config/ src/lib/dns/ src/lib/dns/rdata/generic/ src/lib/python/isc/ src/lib/python/isc/Util/ src/lib/python/isc/auth/ src/lib/python/isc/cc/ src/lib/python/isc/config/
BIND 10 source code commits
bind10-changes at lists.isc.org
Tue Mar 9 22:42:40 UTC 2010
Author: jinmei
Date: Tue Mar 9 22:42:40 2010
New Revision: 1248
Log:
sync with trunk
Added:
branches/jinmei-asio/src/bin/bind10/tests/
- copied from r1247, trunk/src/bin/bind10/tests/
branches/jinmei-asio/src/bin/cmdctl/b10-cmdctl.xml
- copied unchanged from r1247, trunk/src/bin/cmdctl/b10-cmdctl.xml
branches/jinmei-asio/src/bin/loadzone/b10-loadzone.xml
- copied unchanged from r1247, trunk/src/bin/loadzone/b10-loadzone.xml
branches/jinmei-asio/src/bin/xfrin/
- copied from r1247, trunk/src/bin/xfrin/
branches/jinmei-asio/src/lib/auth/testdata/root.zone
- copied unchanged from r1247, trunk/src/lib/auth/testdata/root.zone
branches/jinmei-asio/src/lib/auth/testdata/test-root.sqlite3
- copied unchanged from r1247, trunk/src/lib/auth/testdata/test-root.sqlite3
branches/jinmei-asio/src/lib/dns/Makefile.dat
- copied unchanged from r1247, trunk/src/lib/dns/Makefile.dat
branches/jinmei-asio/src/lib/dns/message_python.cc
- copied unchanged from r1247, trunk/src/lib/dns/message_python.cc
branches/jinmei-asio/src/lib/dns/message_test.py
- copied unchanged from r1247, trunk/src/lib/dns/message_test.py
branches/jinmei-asio/src/lib/python/isc/auth/TODO
- copied unchanged from r1247, trunk/src/lib/python/isc/auth/TODO
Removed:
branches/jinmei-asio/src/bin/bind10/bind10_test.in
branches/jinmei-asio/src/bin/bind10/bind10_test.py
Modified:
branches/jinmei-asio/ (props changed)
branches/jinmei-asio/configure.ac
branches/jinmei-asio/src/bin/ (props changed)
branches/jinmei-asio/src/bin/Makefile.am
branches/jinmei-asio/src/bin/bind10/Makefile.am
branches/jinmei-asio/src/bin/bind10/TODO
branches/jinmei-asio/src/bin/bind10/bind10.py.in
branches/jinmei-asio/src/bin/bind10/run_bind10.sh.in
branches/jinmei-asio/src/bin/cmdctl/Makefile.am
branches/jinmei-asio/src/bin/loadzone/b10-loadzone.py.in
branches/jinmei-asio/src/lib/auth/data_source_sqlite3.cc
branches/jinmei-asio/src/lib/auth/data_source_sqlite3.h
branches/jinmei-asio/src/lib/auth/data_source_sqlite3_unittest.cc
branches/jinmei-asio/src/lib/cc/ (props changed)
branches/jinmei-asio/src/lib/config/ccsession.cc
branches/jinmei-asio/src/lib/config/ccsession.h
branches/jinmei-asio/src/lib/dns/ (props changed)
branches/jinmei-asio/src/lib/dns/rdata/generic/rrsig_46.cc (props changed)
branches/jinmei-asio/src/lib/python/isc/Makefile.am
branches/jinmei-asio/src/lib/python/isc/Util/Makefile.am
branches/jinmei-asio/src/lib/python/isc/__init__.py
branches/jinmei-asio/src/lib/python/isc/auth/Makefile.am
branches/jinmei-asio/src/lib/python/isc/auth/master.py
branches/jinmei-asio/src/lib/python/isc/auth/sqlite3_ds.py
branches/jinmei-asio/src/lib/python/isc/cc/Makefile.am
branches/jinmei-asio/src/lib/python/isc/cc/message.py
branches/jinmei-asio/src/lib/python/isc/config/Makefile.am
branches/jinmei-asio/src/lib/python/isc/config/ccsession.py
branches/jinmei-asio/src/lib/python/isc/config/cfgmgr.py
Modified: branches/jinmei-asio/configure.ac
==============================================================================
--- branches/jinmei-asio/configure.ac (original)
+++ branches/jinmei-asio/configure.ac Tue Mar 9 22:42:40 2010
@@ -200,6 +200,7 @@
src/bin/loadzone/Makefile
src/bin/msgq/Makefile
src/bin/auth/Makefile
+ src/bin/xfrin/Makefile
src/lib/Makefile
src/lib/cc/Makefile
src/lib/python/Makefile
@@ -218,8 +219,11 @@
src/bin/cmdctl/cmdctl.py
src/bin/cmdctl/run_b10-cmdctl.sh
src/bin/cmdctl/unittest/cmdctl_test
+ src/bin/xfrin/unittest/xfrin_test
+ src/bin/xfrin/xfrin.py
+ src/bin/xfrin/run_b10-xfrin.sh
src/bin/bind10/bind10.py
- src/bin/bind10/bind10_test
+ src/bin/bind10/tests/bind10_test
src/bin/bind10/run_bind10.sh
src/bin/bindctl/bindctl
src/bin/bindctl/unittest/bindctl_test
@@ -235,8 +239,10 @@
src/lib/dns/tests/testdata/gen-wiredata.py
], [
chmod +x src/bin/cmdctl/run_b10-cmdctl.sh
+ chmod +x src/bin/xfrin/run_b10-xfrin.sh
chmod +x src/bin/bind10/run_bind10.sh
chmod +x src/bin/cmdctl/unittest/cmdctl_test
+ chmod +x src/bin/xfrin/unittest/xfrin_test
chmod +x src/bin/bindctl/unittest/bindctl_test
chmod +x src/bin/bindctl/bindctl
chmod +x src/bin/loadzone/run_loadzone
Modified: branches/jinmei-asio/src/bin/Makefile.am
==============================================================================
--- branches/jinmei-asio/src/bin/Makefile.am (original)
+++ branches/jinmei-asio/src/bin/Makefile.am Tue Mar 9 22:42:40 2010
@@ -1,1 +1,1 @@
-SUBDIRS = bind10 bindctl cfgmgr loadzone msgq host cmdctl auth
+SUBDIRS = bind10 bindctl cfgmgr loadzone msgq host cmdctl auth xfrin
Modified: branches/jinmei-asio/src/bin/bind10/Makefile.am
==============================================================================
--- branches/jinmei-asio/src/bin/bind10/Makefile.am (original)
+++ branches/jinmei-asio/src/bin/bind10/Makefile.am Tue Mar 9 22:42:40 2010
@@ -12,3 +12,6 @@
$(SED) -e "s|@@PYTHONPATH@@|@pyexecdir@|" \
-e "s|@@LIBEXECDIR@@|$(pkglibexecdir)|" bind10.py >$@
chmod a+x $@
+
+pytest:
+ $(SHELL) tests/bind10_test
Modified: branches/jinmei-asio/src/bin/bind10/TODO
==============================================================================
--- branches/jinmei-asio/src/bin/bind10/TODO (original)
+++ branches/jinmei-asio/src/bin/bind10/TODO Tue Mar 9 22:42:40 2010
@@ -8,7 +8,6 @@
- Force-stop a component
- Mechanism to wait for child to start before continuing
- Way to ask a child to die politely
-- Back-off mechanism for restarting failed processes
- Start statistics daemon
- Statistics interaction (?)
- Use .spec file to define comands
Modified: branches/jinmei-asio/src/bin/bind10/bind10.py.in
==============================================================================
--- branches/jinmei-asio/src/bin/bind10/bind10.py.in (original)
+++ branches/jinmei-asio/src/bin/bind10/bind10.py.in Tue Mar 9 22:42:40 2010
@@ -2,6 +2,8 @@
import sys; sys.path.append ('@@PYTHONPATH@@')
import os
+import time
+import random
"""\
This file implements the Boss of Bind (BoB, or bob) program.
@@ -50,10 +52,53 @@
import isc
# This is the version that gets displayed to the user.
-__version__ = "v20100225"
+__version__ = "v20100309"
# Nothing at all to do with the 1990-12-10 article here:
# http://www.subgenius.com/subg-digest/v2/0056.html
+
+class RestartSchedule:
+ """
+Keeps state when restarting something (in this case, a process).
+
+When a process dies unexpectedly, we need to restart it. However, if
+it fails to restart for some reason, then we should not simply keep
+restarting it at high speed.
+
+A more sophisticated algorithm can be developed, but for now we choose
+a simple set of rules:
+
+ * If a process was been running for >=10 seconds, we restart it
+ right away.
+ * If a process was running for <10 seconds, we wait until 10 seconds
+ after it was started.
+
+To avoid programs getting into lockstep, we use a normal distribution
+to avoid being restarted at exactly 10 seconds."""
+
+ def __init__(self, restart_frequency=10.0):
+ self.restart_frequency = restart_frequency
+ self.run_start_time = None
+ self.run_stop_time = None
+ self.restart_time = None
+
+ def set_run_start_time(self, when=None):
+ if when is None:
+ when = time.time()
+ self.run_start_time = when
+ sigma = self.restart_frequency * 0.05
+ self.restart_time = when + random.normalvariate(self.restart_frequency,
+ sigma)
+
+ def set_run_stop_time(self, when=None):
+ if when is None:
+ when = time.time()
+ self.run_stop_time = when
+
+ def get_restart_time(self, when=None):
+ if when is None:
+ when = time.time()
+ return max(when, self.restart_time)
class ProcessInfo:
"""Information about a process"""
@@ -82,12 +127,14 @@
close_fds=True,
env=spawn_env,)
self.pid = self.process.pid
+ self.restart_schedule.set_run_start_time()
def __init__(self, name, args, env={}, dev_null_stdout=False):
self.name = name
self.args = args
self.env = env
self.dev_null_stdout = dev_null_stdout
+ self.restart_schedule = RestartSchedule()
self._spawn()
def respawn(self):
@@ -229,6 +276,20 @@
if self.verbose:
sys.stdout.write("Started b10-auth (PID %d)\n" % auth.pid)
+ # start the b10-xfrin
+ if self.verbose:
+ sys.stdout.write("Starting b10-xfrin\n")
+ try:
+ xfrind = ProcessInfo("b10-xfrin", ['b10-xfrin'])
+ except Exception as e:
+ c_channel.process.kill()
+ bind_cfgd.process.kill()
+ auth.process.kill()
+ return "Unable to start b10-xfrin; " + str(e)
+ self.processes[xfrind.pid] = xfrind
+ if self.verbose:
+ sys.stdout.write("Started b10-xfrin (PID %d)\n" % xfrind.pid)
+
# start the b10-cmdctl
# XXX: we hardcode port 8080
if self.verbose:
@@ -239,6 +300,7 @@
c_channel.process.kill()
bind_cfgd.process.kill()
auth.process.kill()
+ xfrind.process.kill()
return "Unable to start b10-cmdctl; " + str(e)
self.processes[cmd_ctrld.pid] = cmd_ctrld
if self.verbose:
@@ -317,6 +379,7 @@
if pid == 0: break
if pid in self.processes:
proc_info = self.processes.pop(pid)
+ proc_info.restart_schedule.set_run_stop_time()
self.dead_processes[proc_info.pid] = proc_info
if self.verbose:
sys.stdout.write("Process %s (PID %d) died.\n" %
@@ -386,26 +449,39 @@
def restart_processes(self):
"""Restart any dead processes."""
- # XXX: this needs a back-off algorithm
+ next_restart = None
# if we're shutting down, then don't restart
if not self.runnable:
- return
+ return next_restart
# otherwise look through each dead process and try to restart
still_dead = {}
+ now = time.time()
for proc_info in self.dead_processes.values():
- if self.verbose:
- sys.stdout.write("Resurrecting dead %s process...\n" %
- proc_info.name)
- try:
- proc_info.respawn()
- self.processes[proc_info.pid] = proc_info
+ restart_time = proc_info.restart_schedule.get_restart_time(now)
+ if restart_time > now:
+# if self.verbose:
+# sys.stdout.write("Dead %s process waiting %.1f seconds "\
+# "for resurrection\n" %
+# (proc_info.name, (restart_time-now)))
+ if (next_restart is None) or (next_restart > restart_time):
+ next_restart = restart_time
+ still_dead[proc_info.pid] = proc_info
+ else:
if self.verbose:
- sys.stdout.write("Resurrected %s (PID %d)\n" %
- (proc_info.name, proc_info.pid))
- except:
- still_dead[proc_info.pid] = proc_info
+ sys.stdout.write("Resurrecting dead %s process...\n" %
+ proc_info.name)
+ try:
+ proc_info.respawn()
+ self.processes[proc_info.pid] = proc_info
+ if self.verbose:
+ sys.stdout.write("Resurrected %s (PID %d)\n" %
+ (proc_info.name, proc_info.pid))
+ except:
+ still_dead[proc_info.pid] = proc_info
# remember any processes that refuse to be resurrected
self.dead_processes = still_dead
+ # return the time when the next process is ready to be restarted
+ return next_restart
def reaper(signal_number, stack_frame):
"""A child process has died (SIGCHLD received)."""
@@ -484,15 +560,18 @@
while boss_of_bind.runnable:
# clean up any processes that exited
boss_of_bind.reap_children()
- boss_of_bind.restart_processes()
-
- # XXX: get time for next restart for timeout
+ next_restart = boss_of_bind.restart_processes()
+ if next_restart is None:
+ wait_time = None
+ else:
+ wait_time = max(next_restart - time.time(), 0)
# select() can raise EINTR when a signal arrives,
# even if they are resumable, so we have to catch
# the exception
try:
- (rlist, wlist, xlist) = select.select([wakeup_fd, ccs_fd], [], [])
+ (rlist, wlist, xlist) = select.select([wakeup_fd, ccs_fd], [], [],
+ wait_time)
except select.error as err:
if err.args[0] == errno.EINTR:
(rlist, wlist, xlist) = ([], [], [])
Modified: branches/jinmei-asio/src/bin/bind10/run_bind10.sh.in
==============================================================================
--- branches/jinmei-asio/src/bin/bind10/run_bind10.sh.in (original)
+++ branches/jinmei-asio/src/bin/bind10/run_bind10.sh.in Tue Mar 9 22:42:40 2010
@@ -5,7 +5,7 @@
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:$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:$PATH
export PATH
PYTHONPATH=@abs_top_builddir@/src/lib/python
Modified: branches/jinmei-asio/src/bin/cmdctl/Makefile.am
==============================================================================
--- branches/jinmei-asio/src/bin/cmdctl/Makefile.am (original)
+++ branches/jinmei-asio/src/bin/cmdctl/Makefile.am Tue Mar 9 22:42:40 2010
@@ -3,12 +3,17 @@
pkglibexec_SCRIPTS = b10-cmdctl
b10_cmdctldir = $(DESTDIR)$(pkgdatadir)
+# TODO: this is dangerous -- will overwrite!
b10_cmdctl_DATA = passwd.csv b10-cmdctl.pem
-CLEANFILES= cmdctl.py
+CLEANFILES= b10-cmdctl
# TODO: does this need $$(DESTDIR) also?
# this is done here since configure.ac AC_OUTPUT doesn't expand exec_prefix
b10-cmdctl: cmdctl.py
$(SED) "s|@@PYTHONPATH@@|@pyexecdir@|" cmdctl.py >$@
chmod a+x $@
+
+install-data-local:
+ chmod go-rwx $(DESTDIR)$(pkgdatadir)/passwd.csv
+ chmod go-rwx $(DESTDIR)$(pkgdatadir)/b10-cmdctl.pem
Modified: branches/jinmei-asio/src/bin/loadzone/b10-loadzone.py.in
==============================================================================
--- branches/jinmei-asio/src/bin/loadzone/b10-loadzone.py.in (original)
+++ branches/jinmei-asio/src/bin/loadzone/b10-loadzone.py.in Tue Mar 9 22:42:40 2010
@@ -40,11 +40,13 @@
exit(2)
dbfile = '/tmp/zone.sqlite3'
- initial_origin = '.'
+ initial_origin = ''
for o, a in opts:
if o in ("-d", "--dbfile"):
dbfile = a
elif o in ("-o", "--origin"):
+ if a[-1] != '.':
+ a += '.'
initial_origin = a
elif o in ("-h", "--help"):
usage()
@@ -68,7 +70,6 @@
exit(1)
try:
-
isc.auth.sqlite3_ds.load(dbfile, zone, isc.auth.master.zonedata, zf)
except Exception as e:
print("Error loading database: " + str(e))
Modified: branches/jinmei-asio/src/lib/auth/data_source_sqlite3.cc
==============================================================================
--- branches/jinmei-asio/src/lib/auth/data_source_sqlite3.cc (original)
+++ branches/jinmei-asio/src/lib/auth/data_source_sqlite3.cc Tue Mar 9 22:42:40 2010
@@ -185,10 +185,15 @@
RRsetList& target, const Name* zonename,
const Mode mode, uint32_t& flags) const
{
- const string s_name = name.toText();
- const char* const c_name = s_name.c_str();
+ flags = 0;
+ int zone_id = (zonename == NULL) ? findClosest(name, NULL) :
+ findClosest(*zonename, NULL);
+ if (zone_id < 0) {
+ flags = NO_SUCH_ZONE;
+ return (0);
+ }
+
sqlite3_stmt* query;
-
switch (mode) {
case ADDRESS:
query = q_addrs;
@@ -204,15 +209,6 @@
}
break;
}
-
- flags = 0;
-
- int zone_id = (zonename == NULL) ? findClosest(c_name, NULL) :
- findClosest(zonename->toText().c_str(), NULL);
- if (zone_id < 0) {
- flags = NO_SUCH_ZONE;
- return (0);
- }
sqlite3_reset(query);
sqlite3_clear_bindings(query);
@@ -222,7 +218,8 @@
if (rc != SQLITE_OK) {
throw("Could not bind 1 (query)");
}
- rc = sqlite3_bind_text(query, 2, c_name, -1, SQLITE_STATIC);
+ const string s_name = name.toText();
+ rc = sqlite3_bind_text(query, 2, s_name.c_str(), -1, SQLITE_STATIC);
if (rc != SQLITE_OK) {
throw("Could not bind 2 (query)");
}
@@ -282,29 +279,22 @@
// longest match found.
//
int
-Sqlite3DataSrc::findClosest(const char* const name,
- const char** position) const
-{
- const char* current = name;
-
- while (*current != 0) {
- const int rc = hasExactZone(current);
+Sqlite3DataSrc::findClosest(const Name& name, unsigned int* position) const {
+ const unsigned int nlabels = name.getLabelCount();
+ for (unsigned int i = 0; i < nlabels; ++i) {
+ Name matchname(name.split(i, nlabels - i));
+ const int rc = hasExactZone(matchname.toText().c_str());
if (rc >= 0) {
if (position != NULL) {
- *position = current;
+ *position = i;
}
return (rc);
}
- while (*current != '.' && *current != 0) {
- ++current;
- }
- if (*current == '.') {
- ++current;
- }
}
return (-1);
}
+
void
Sqlite3DataSrc::loadVersion(void) {
@@ -498,18 +488,20 @@
void
Sqlite3DataSrc::findClosestEnclosure(NameMatch& match,
- const RRClass& qclass) const {
- const char* position = NULL;
-
+ const RRClass& qclass) const
+{
if (qclass != getClass()) {
return;
}
- if (findClosest(match.qname().toText().c_str(), &position) == -1) {
+ unsigned int position;
+ if (findClosest(match.qname(), &position) == -1) {
return;
}
- match.update(*this, Name(position));
+ match.update(*this, match.qname().split(position,
+ match.qname().getLabelCount() -
+ position));
}
DataSrc::Result
@@ -519,8 +511,8 @@
const Name* zonename) const
{
int zone_id = (zonename == NULL) ?
- findClosest(qname.toText().c_str(), NULL) :
- findClosest(zonename->toText().c_str(), NULL);
+ findClosest(qname, NULL) :
+ findClosest(*zonename, NULL);
if (zone_id < 0) {
return (ERROR);
@@ -557,7 +549,7 @@
string& hashstr,
RRsetList& target) const
{
- int zone_id = findClosest(zonename.toText().c_str(), NULL);
+ int zone_id = findClosest(zonename, NULL);
if (zone_id < 0) {
return (ERROR);
}
Modified: branches/jinmei-asio/src/lib/auth/data_source_sqlite3.h
==============================================================================
--- branches/jinmei-asio/src/lib/auth/data_source_sqlite3.h (original)
+++ branches/jinmei-asio/src/lib/auth/data_source_sqlite3.h Tue Mar 9 22:42:40 2010
@@ -121,7 +121,7 @@
int findRecords(const isc::dns::Name& name, const isc::dns::RRType& rdtype,
isc::dns::RRsetList& target, const isc::dns::Name* zonename,
const Mode mode, uint32_t& flags) const;
- int findClosest(const char *name, const char **position) const;
+ int findClosest(const isc::dns::Name& name, unsigned int* position) const;
void loadVersion(void);
void setupPreparedStatements(void);
void execSetupQuery(const char *query);
Modified: branches/jinmei-asio/src/lib/auth/data_source_sqlite3_unittest.cc
==============================================================================
--- branches/jinmei-asio/src/lib/auth/data_source_sqlite3_unittest.cc (original)
+++ branches/jinmei-asio/src/lib/auth/data_source_sqlite3_unittest.cc Tue Mar 9 22:42:40 2010
@@ -46,7 +46,9 @@
"{ \"database_file\": \"testdata/test.sqlite3\"}");
static ElementPtr SQLITE_DBFILE_EXAMPLE2 = Element::createFromString(
"{ \"database_file\": \"testdata/test2.sqlite3\"}");
-// The following file must be non existent and mutt be "creatable";
+static ElementPtr SQLITE_DBFILE_EXAMPLE_ROOT = Element::createFromString(
+ "{ \"database_file\": \"testdata/test-root.sqlite3\"}");
+// The following file must be non existent and must be non"creatable";
// the sqlite3 library will try to create a new DB file if it doesn't exist,
// so to test a failure case the create operation should also fail.
// The "nodir", a non existent directory, is inserted for this purpose.
@@ -342,9 +344,9 @@
answers.push_back(&expected_data);
signatures.push_back(expected_sig_data);
- checkFind(mode, data_source, query, expected_name, zone_name, expected_class,
- expected_type, ttls, expected_flags, types, answers,
- signatures);
+ checkFind(mode, data_source, query, expected_name, zone_name,
+ expected_class, expected_type, ttls, expected_flags, types,
+ answers, signatures);
}
TEST_F(Sqlite3DataSourceTest, close) {
@@ -355,11 +357,10 @@
// Replace the data with a totally different zone. This should succeed,
// and shouldn't match any names in the previously managed domains.
EXPECT_EQ(DataSrc::SUCCESS, data_source.close());
-
EXPECT_EQ(DataSrc::SUCCESS, data_source.init(SQLITE_DBFILE_EXAMPLE2));
NameMatch name_match(www_name);
- data_source.findClosestEnclosure(name_match, RRClass::IN());
+ data_source.findClosestEnclosure(name_match, rrclass);
EXPECT_EQ(NULL, name_match.closestName());
EXPECT_EQ(NULL, name_match.bestDataSrc());
}
@@ -371,8 +372,18 @@
TEST_F(Sqlite3DataSourceTest, findClosestEnclosure) {
NameMatch name_match(www_name);
- data_source.findClosestEnclosure(name_match, RRClass::IN());
+ data_source.findClosestEnclosure(name_match, rrclass);
EXPECT_EQ(zone_name, *name_match.closestName());
+ EXPECT_EQ(&data_source, name_match.bestDataSrc());
+}
+
+TEST_F(Sqlite3DataSourceTest, findClosestEnclosureMatchRoot) {
+ EXPECT_EQ(DataSrc::SUCCESS, data_source.close());
+ EXPECT_EQ(DataSrc::SUCCESS, data_source.init(SQLITE_DBFILE_EXAMPLE_ROOT));
+
+ NameMatch name_match(Name("org."));
+ data_source.findClosestEnclosure(name_match, rrclass);
+ EXPECT_EQ(Name("."), *name_match.closestName());
EXPECT_EQ(&data_source, name_match.bestDataSrc());
}
@@ -380,14 +391,14 @@
// The search name exists both in the parent and child zones, but
// child has a better match.
NameMatch name_match(child_name);
- data_source.findClosestEnclosure(name_match, RRClass::IN());
+ data_source.findClosestEnclosure(name_match, rrclass);
EXPECT_EQ(child_name, *name_match.closestName());
EXPECT_EQ(&data_source, name_match.bestDataSrc());
}
TEST_F(Sqlite3DataSourceTest, findClosestEnclosureNoMatch) {
NameMatch name_match(nomatch_name);
- data_source.findClosestEnclosure(name_match, RRClass::IN());
+ data_source.findClosestEnclosure(name_match, rrclass);
EXPECT_EQ(NULL, name_match.closestName());
EXPECT_EQ(NULL, name_match.bestDataSrc());
}
@@ -696,7 +707,7 @@
data_source.findCoveringNSEC3(*query, nsec3_zonename,
hashstr, result_sets));
RRsetList::iterator it = result_sets.begin();
- checkRRset(*it, Name(hashstr).concatenate(nsec3_zonename), RRClass::IN(),
+ checkRRset(*it, Name(hashstr).concatenate(nsec3_zonename), rrclass,
RRType::NSEC3(), RRTTL(7200), nsec3_data, &nsec3_sig_data);
++it;
EXPECT_TRUE(it == result_sets.end());
Modified: branches/jinmei-asio/src/lib/config/ccsession.cc
==============================================================================
--- branches/jinmei-asio/src/lib/config/ccsession.cc (original)
+++ branches/jinmei-asio/src/lib/config/ccsession.cc Tue Mar 9 22:42:40 2010
@@ -42,7 +42,6 @@
#include <cc/session.h>
#include <exceptions/exceptions.h>
-//#include "common.h"
#include "ccsession.h"
#include "config.h"
@@ -143,10 +142,11 @@
return "";
}
-void
+ModuleSpec
ModuleCCSession::read_module_specification(const std::string& filename) {
std::ifstream file;
-
+ ModuleSpec module_spec;
+
// this file should be declared in a @something@ directive
file.open(filename.c_str());
if (!file) {
@@ -155,7 +155,7 @@
}
try {
- module_specification_ = moduleSpecFromFile(file, true);
+ module_spec = moduleSpecFromFile(file, true);
} catch (ParseError pe) {
cout << "Error parsing module specification file: " << pe.what() << endl;
exit(1);
@@ -164,6 +164,7 @@
exit(1);
}
file.close();
+ return module_spec;
}
#ifdef HAVE_BOOSTLIB
@@ -211,7 +212,7 @@
const std::string& command, const isc::data::ElementPtr args)
) throw (isc::cc::SessionError)
{
- read_module_specification(spec_file_name);
+ module_specification_ = read_module_specification(spec_file_name);
sleep(1);
module_name_ = module_specification_.getFullSpec()->get("module_name")->stringValue();
@@ -295,6 +296,7 @@
{
ElementPtr 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")) {
@@ -304,7 +306,16 @@
std::string cmd_str = parseCommand(arg, data);
ElementPtr answer;
if (cmd_str == "config_update") {
- answer = handleConfigUpdate(arg);
+ std::string target_module = routing->get("group")->stringValue();
+ if (target_module == module_name_) {
+ answer = handleConfigUpdate(arg);
+ } else {
+ // ok this update is not for us, if we have this module
+ // in our remote config list, update that
+ updateRemoteConfig(target_module, arg);
+ // we're not supposed to answer to this, so return
+ return 0;
+ }
} else {
if (command_handler_) {
answer = command_handler_(cmd_str, arg);
@@ -318,5 +329,69 @@
return 0;
}
-}
-}
+std::string
+ModuleCCSession::addRemoteConfig(const std::string& spec_file_name)
+{
+ ModuleSpec rmod_spec = read_module_specification(spec_file_name);
+ std::string module_name = rmod_spec.getFullSpec()->get("module_name")->stringValue();
+ ConfigData rmod_config = ConfigData(rmod_spec);
+ session_.subscribe(module_name);
+
+ // Get the current configuration values for that module
+ ElementPtr cmd = Element::createFromString("{ \"command\": [\"get_config\", {\"module_name\":\"" + module_name + "\"} ] }");
+ ElementPtr env, answer;
+ int rcode;
+
+ session_.group_sendmsg(cmd, "ConfigManager");
+ session_.group_recvmsg(env, answer, false);
+ ElementPtr new_config = parseAnswer(rcode, answer);
+ if (rcode == 0) {
+ rmod_config.setLocalConfig(new_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;
+}
+
+void
+ModuleCCSession::removeRemoteConfig(const std::string& module_name)
+{
+ std::map<std::string, ConfigData>::iterator it;
+
+ it = remote_module_configs_.find(module_name);
+ if (it != remote_module_configs_.end()) {
+ remote_module_configs_.erase(it);
+ session_.unsubscribe(module_name);
+ }
+}
+
+ElementPtr
+ModuleCCSession::getRemoteConfigValue(const std::string& module_name, const std::string& identifier)
+{
+ std::map<std::string, ConfigData>::iterator it;
+
+ it = remote_module_configs_.find(module_name);
+ if (it != remote_module_configs_.end()) {
+ return remote_module_configs_[module_name].getValue(identifier);
+ } else {
+ isc_throw(CCSessionError, "Remote module " + module_name + " not found.");
+ }
+}
+
+void
+ModuleCCSession::updateRemoteConfig(const std::string& module_name, ElementPtr new_config)
+{
+ std::map<std::string, ConfigData>::iterator it;
+
+ it = remote_module_configs_.find(module_name);
+ if (it != remote_module_configs_.end()) {
+ ElementPtr rconf = (*it).second.getLocalConfig();
+ isc::data::merge(rconf, new_config);
+ }
+}
+
+}
+}
Modified: branches/jinmei-asio/src/lib/config/ccsession.h
==============================================================================
--- branches/jinmei-asio/src/lib/config/ccsession.h (original)
+++ branches/jinmei-asio/src/lib/config/ccsession.h Tue Mar 9 22:42:40 2010
@@ -101,6 +101,44 @@
*/
void set_command_handler(isc::data::ElementPtr(*command_handler)(const std::string& command, const isc::data::ElementPtr args)) { command_handler_ = command_handler; };
+ /**
+ * Gives access to the configuration values of a different module
+ * Once this function has been called with the name of the specification
+ * file of the module you want the configuration of, you can use
+ * \c getRemoteConfigValue() to get a specific setting.
+ * Changes are automatically updated, but you cannot specify handlers
+ * for those changes, must use \c getRemoteConfigValue() to get a value
+ * This function will subscribe to the relevant module channel.
+ *
+ * \param spec_file_name The path to the specification file of
+ * the module we want to have configuration
+ * values from
+ * \return The name of the module specified in the given specification
+ * file
+ */
+ std::string addRemoteConfig(const std::string& spec_file_name);
+
+ /**
+ * Removes the module with the given name from the remote config
+ * settings. If the module was not added with \c addRemoteConfig(),
+ * nothing happens.
+ */
+ void removeRemoteConfig(const std::string& module_name);
+
+ /**
+ * Returns the current configuration value for the given module
+ * name at the given identifier. See \c ConfigData::getValue() for
+ * more details.
+ * Raises a ModuleCCSessionError if the module name is unknown
+ * Raises a DataNotFoundError if the identifier does not exist
+ * in the specification.
+ *
+ * \param module_name The name of the module to get a config value for
+ * \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);
+
private:
void init(
std::string spec_file_name,
@@ -109,7 +147,7 @@
isc::data::ElementPtr(*command_handler)(
const std::string& command, const isc::data::ElementPtr args)
) throw (isc::cc::SessionError);
- void read_module_specification(const std::string& filename);
+ ModuleSpec read_module_specification(const std::string& filename);
void startCheck();
std::string module_name_;
@@ -120,6 +158,9 @@
isc::data::ElementPtr(*config_handler_)(isc::data::ElementPtr new_config);
isc::data::ElementPtr(*command_handler_)(const std::string& command, const isc::data::ElementPtr args);
+
+ std::map<std::string, ConfigData> remote_module_configs_;
+ void updateRemoteConfig(const std::string& module_name, ElementPtr new_config);
};
ElementPtr createAnswer(const int rcode);
Modified: branches/jinmei-asio/src/lib/python/isc/Makefile.am
==============================================================================
--- branches/jinmei-asio/src/lib/python/isc/Makefile.am (original)
+++ branches/jinmei-asio/src/lib/python/isc/Makefile.am Tue Mar 9 22:42:40 2010
@@ -1,8 +1,5 @@
-SUBDIRS = auth cc Util config
+SUBDIRS = auth cc config # Util
-PY_MODULES= __init__.py
+python_PYTHON = __init__.py
-install-data-local:
- $(mkinstalldirs) $(DESTDIR)$(pyexecdir)/isc
- @(for _foo_ in $(PY_MODULES) ; \
- do $(INSTALL) -m 0644 $(top_srcdir)/src/lib/python/isc/$$_foo_ $(DESTDIR)$(pyexecdir)/isc/ ; done)
+pythondir = $(pyexecdir)/isc
Modified: branches/jinmei-asio/src/lib/python/isc/Util/Makefile.am
==============================================================================
--- branches/jinmei-asio/src/lib/python/isc/Util/Makefile.am (original)
+++ branches/jinmei-asio/src/lib/python/isc/Util/Makefile.am Tue Mar 9 22:42:40 2010
@@ -1,6 +1,3 @@
-PY_MODULES= __init__.py hexdump.py
+python_PYTHON = __init__.py hexdump.py
-install-data-local:
- $(mkinstalldirs) $(DESTDIR)$(pyexecdir)/isc/Util
- @(for _foo_ in $(PY_MODULES) ; \
- do $(INSTALL) -m 0644 $(top_srcdir)/src/lib/python/isc/Util/$$_foo_ $(DESTDIR)$(pyexecdir)/isc/Util/ ; done)
+pythondir = $(pyexecdir)/isc/Util
Modified: branches/jinmei-asio/src/lib/python/isc/__init__.py
==============================================================================
--- branches/jinmei-asio/src/lib/python/isc/__init__.py (original)
+++ branches/jinmei-asio/src/lib/python/isc/__init__.py Tue Mar 9 22:42:40 2010
@@ -1,4 +1,3 @@
import isc.auth
import isc.cc
-import isc.Util
import isc.config
Modified: branches/jinmei-asio/src/lib/python/isc/auth/Makefile.am
==============================================================================
--- branches/jinmei-asio/src/lib/python/isc/auth/Makefile.am (original)
+++ branches/jinmei-asio/src/lib/python/isc/auth/Makefile.am Tue Mar 9 22:42:40 2010
@@ -1,6 +1,3 @@
-PY_MODULES= __init__.py master.py sqlite3_ds.py
+python_PYTHON = __init__.py master.py sqlite3_ds.py
-install-data-local:
- $(mkinstalldirs) $(DESTDIR)$(pyexecdir)/isc/auth
- @(for _foo_ in $(PY_MODULES) ; \
- do $(INSTALL) -m 0644 $(top_srcdir)/src/lib/python/isc/auth/$$_foo_ $(DESTDIR)$(pyexecdir)/isc/auth/; done)
+pythondir = $(pyexecdir)/isc/auth
Modified: branches/jinmei-asio/src/lib/python/isc/auth/master.py
==============================================================================
--- branches/jinmei-asio/src/lib/python/isc/auth/master.py (original)
+++ branches/jinmei-asio/src/lib/python/isc/auth/master.py Tue Mar 9 22:42:40 2010
@@ -90,8 +90,11 @@
#########################################################################
def pop(line):
list = line.split()
- first = list[0]
- rest = ' '.join(list[1:])
+ first, rest = '', ''
+ if len(list) != 0:
+ first = list[0]
+ if len(list) > 1:
+ rest = ' '.join(list[1:])
return first, rest
#########################################################################
@@ -133,7 +136,7 @@
name_regex = re.compile('[-\w\$\d\/*]+(?:\.[-\w\$\d\/]+)*\.?')
def isname(s):
global name_regex
- if name_regex.match(s):
+ if s == '.' or name_regex.match(s):
return True
else:
return False
@@ -190,18 +193,20 @@
first, more = pop(s)
second, more = pop(more)
if re.match('\$origin', first, re.I):
- if not isname(second):
+ if not second or not isname(second):
raise MasterFileError('Invalid $ORIGIN')
if more:
raise MasterFileError('Invalid $ORIGIN')
- if second[-1] == '.':
+ if second == '.':
+ origin = ''
+ elif second[-1] == '.':
origin = second
else:
origin = second + '.' + origin
return True
elif re.match('\$ttl', first, re.I):
- if not isttl(second):
- raise MasterFileError('Invalid $TTL: ' + second)
+ if not second or not isttl(second):
+ raise MasterFileError('Invalid TTL: "' + second + '"')
if more:
raise MasterFileError('Invalid $TTL statement')
defttl = parse_ttl(second)
@@ -335,17 +340,20 @@
#########################################################################
def reset():
global defttl, origin
- defttl = -1
- origin=''
+ defttl = ''
+ origin = ''
#########################################################################
# openzone: open a zone master file, set initial origin, return descriptor
#########################################################################
-def openzone(filename, initial_origin = '.'):
+def openzone(filename, initial_origin = ''):
+ global origin
try:
zf = open(filename, 'r')
except:
- return
+ raise MasterFileError("Could not open " + filename)
+ if initial_origin == '.':
+ initial_origin = ''
origin = initial_origin
return zf
@@ -370,10 +378,13 @@
sub.close()
continue
- first = record.split()[0]
- if first == '@':
- name = origin
- at, record = pop(record)
+ # replace @ with origin
+ rl = record.split()
+ if rl[0] == '@':
+ rl[0] = origin
+ if not origin:
+ rl[0] = '.'
+ record = ' '.join(rl)
result = four(record, name)
@@ -398,15 +409,31 @@
if rrclass.upper() != 'IN':
raise MasterFileError("CH and HS zones not supported")
- # add origin to rdata if necessary
- if rrtype.lower() in ('cname', 'dname', 'ns'):
+ if not ttl:
+ raise MasterFileError("No TTL specified; zone rejected")
+
+ # add origin to rdata containing names, if necessary
+ if rrtype.lower() in ('cname', 'dname', 'ns', 'ptr'):
if not isname(rdata):
raise MasterFileError("Invalid " + rrtype + ": " + rdata)
if rdata[-1] != '.':
rdata += '.' + origin
-
- if (ttl == -1):
- raise MasterFileError("No TTL specified; zone rejected")
+ if rrtype.lower() == 'soa':
+ soa = rdata.split()
+ if len(soa) < 2 or not isname(soa[0]) or not isname(soa[1]):
+ raise MasterFileError("Invalid " + rrtype + ": " + rdata)
+ if soa[0][-1] != '.':
+ soa[0] += '.' + origin
+ if soa[1][-1] != '.':
+ soa[1] += '.' + origin
+ rdata = ' '.join(soa)
+ if rrtype.lower() == 'mx':
+ mx = rdata.split()
+ if len(mx) != 2 or not isname(mx[1]):
+ raise MasterFileError("Invalid " + rrtype + ": " + rdata)
+ if mx[1][-1] != '.':
+ mx[1] += '.' + origin
+ rdata = ' '.join(mx)
yield (name, ttl, rrclass, rrtype, rdata)
@@ -414,9 +441,11 @@
# zonename: scans zone data for an SOA record, returns its name, restores
# the zone file to its prior state
#########################################################################
-def zonename(zone, initial_origin = '.'):
+def zonename(zone, initial_origin = ''):
global origin
old_origin = origin
+ if initial_origin == '.':
+ initial_origin = ''
origin = initial_origin
old_location = zone.tell()
zone.seek(0)
Modified: branches/jinmei-asio/src/lib/python/isc/auth/sqlite3_ds.py
==============================================================================
--- branches/jinmei-asio/src/lib/python/isc/auth/sqlite3_ds.py (original)
+++ branches/jinmei-asio/src/lib/python/isc/auth/sqlite3_ds.py Tue Mar 9 22:42:40 2010
@@ -129,29 +129,34 @@
cur.execute("INSERT INTO zones (name, rdclass) VALUES (?, 'IN')", [temp])
new_zone_id = cur.lastrowid
- for name, ttl, rdclass, rdtype, rdata in reader(file):
- sigtype = ''
- if rdtype.lower() == 'rrsig':
- sigtype = rdata.split()[0]
+ try:
+ for name, ttl, rdclass, rdtype, rdata in reader(file):
+ sigtype = ''
+ if rdtype.lower() == 'rrsig':
+ sigtype = rdata.split()[0]
- if rdtype.lower() == 'nsec3' or sigtype.lower() == 'nsec3':
- hash = name.split('.')[0]
- cur.execute("""INSERT INTO nsec3
- (zone_id, hash, owner, ttl, rdtype, rdata)
- VALUES (?, ?, ?, ?, ?, ?)""",
- [new_zone_id, hash, name, ttl, rdtype, rdata])
- elif rdtype.lower() == 'rrsig':
- cur.execute("""INSERT INTO records
- (zone_id, name, rname, ttl, rdtype, sigtype, rdata)
- VALUES (?, ?, ?, ?, ?, ?, ?)""",
- [new_zone_id, name, reverse_name(name), ttl,
- rdtype, sigtype, rdata])
- else:
- cur.execute("""INSERT INTO records
- (zone_id, name, rname, ttl, rdtype, rdata)
- VALUES (?, ?, ?, ?, ?, ?)""",
- [new_zone_id, name, reverse_name(name), ttl,
- rdtype, rdata])
+ if rdtype.lower() == 'nsec3' or sigtype.lower() == 'nsec3':
+ hash = name.split('.')[0]
+ cur.execute("""INSERT INTO nsec3
+ (zone_id, hash, owner, ttl, rdtype, rdata)
+ VALUES (?, ?, ?, ?, ?, ?)""",
+ [new_zone_id, hash, name, ttl, rdtype, rdata])
+ elif rdtype.lower() == 'rrsig':
+ cur.execute("""INSERT INTO records
+ (zone_id, name, rname, ttl,
+ rdtype, sigtype, rdata)
+ VALUES (?, ?, ?, ?, ?, ?, ?)""",
+ [new_zone_id, name, reverse_name(name), ttl,
+ rdtype, sigtype, rdata])
+ else:
+ cur.execute("""INSERT INTO records
+ (zone_id, name, rname, ttl, rdtype, rdata)
+ VALUES (?, ?, ?, ?, ?, ?)""",
+ [new_zone_id, name, reverse_name(name), ttl,
+ rdtype, rdata])
+ except Exception as e:
+ fail = "Error while loading " + zone + ": " + e.args[0]
+ raise Sqlite3DSError(fail)
if old_zone_id:
cur.execute("DELETE FROM zones WHERE id=?", [old_zone_id])
Modified: branches/jinmei-asio/src/lib/python/isc/cc/Makefile.am
==============================================================================
--- branches/jinmei-asio/src/lib/python/isc/cc/Makefile.am (original)
+++ branches/jinmei-asio/src/lib/python/isc/cc/Makefile.am Tue Mar 9 22:42:40 2010
@@ -1,6 +1,3 @@
-PY_MODULES= __init__.py data.py session.py message.py
+python_PYTHON = __init__.py data.py session.py message.py
-install-data-local:
- $(mkinstalldirs) $(DESTDIR)$(pyexecdir)/isc/cc
- @(for _foo_ in $(PY_MODULES) ; \
- do $(INSTALL) -m 0644 $(top_srcdir)/src/lib/python/isc/cc/$$_foo_ $(DESTDIR)$(pyexecdir)/isc/cc/ ; done)
+pythondir = $(pyexecdir)/isc/cc
Modified: branches/jinmei-asio/src/lib/python/isc/cc/message.py
==============================================================================
--- branches/jinmei-asio/src/lib/python/isc/cc/message.py (original)
+++ branches/jinmei-asio/src/lib/python/isc/cc/message.py Tue Mar 9 22:42:40 2010
@@ -12,9 +12,6 @@
# 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.
-
-# XXX
-import isc.Util
import sys
import struct
Modified: branches/jinmei-asio/src/lib/python/isc/config/Makefile.am
==============================================================================
--- branches/jinmei-asio/src/lib/python/isc/config/Makefile.am (original)
+++ branches/jinmei-asio/src/lib/python/isc/config/Makefile.am Tue Mar 9 22:42:40 2010
@@ -1,6 +1,3 @@
-PY_MODULES= __init__.py ccsession.py cfgmgr.py config_data.py module_spec.py
+python_PYTHON = __init__.py ccsession.py cfgmgr.py config_data.py module_spec.py
-install-data-local:
- $(mkinstalldirs) $(DESTDIR)$(pyexecdir)/isc/config
- @(for _foo_ in $(PY_MODULES) ; \
- do $(INSTALL) -m 0644 $(top_srcdir)/src/lib/python/isc/config/$$_foo_ $(DESTDIR)$(pyexecdir)/isc/config/; done)
+pythondir = $(pyexecdir)/isc/config
Modified: branches/jinmei-asio/src/lib/python/isc/config/ccsession.py
==============================================================================
--- branches/jinmei-asio/src/lib/python/isc/config/ccsession.py (original)
+++ branches/jinmei-asio/src/lib/python/isc/config/ccsession.py Tue Mar 9 22:42:40 2010
@@ -195,8 +195,6 @@
newc = self._remote_module_configs[module_name].get_local_config()
isc.cc.data.merge(newc, new_config)
self._remote_module_configs[module_name].set_local_config(newc)
- print("[XX] updated remote config value: ")
- print(newc)
return
# ok, so apparently this update is for us.
Modified: branches/jinmei-asio/src/lib/python/isc/config/cfgmgr.py
==============================================================================
--- branches/jinmei-asio/src/lib/python/isc/config/cfgmgr.py (original)
+++ branches/jinmei-asio/src/lib/python/isc/config/cfgmgr.py Tue Mar 9 22:42:40 2010
@@ -267,8 +267,10 @@
got_error = False
err_list = []
for module in self.config.data:
- if module != "version":
+ if module != "version" and self.config.data[module] != old_data[module]:
update_cmd = isc.config.ccsession.create_command(isc.config.ccsession.COMMAND_CONFIG_UPDATE, self.config.data[module])
+ print("[XX] send update: " + str(update_cmd))
+ print("[XX] to: " + str(module))
self.cc.group_sendmsg(update_cmd, module)
answer, env = self.cc.group_recvmsg(False)
if answer == None:
More information about the bind10-changes
mailing list