BIND 10 trac1751, updated. 65d2a83510c3abf2f2cc3fb082ce56c99be32dfb [1751] change of #1751 entry to the simpler text for the users according to reviewing
BIND 10 source code commits
bind10-changes at lists.isc.org
Fri Mar 16 05:05:18 UTC 2012
The branch, trac1751 has been updated
via 65d2a83510c3abf2f2cc3fb082ce56c99be32dfb (commit)
via b24200598f331f9b46805e04b92c23dd7018f2d4 (commit)
via b28f331a0299014773151ec3bd652f3e59557e5d (commit)
from 6fde5a92a9e7610e4bd6612221239fe686c3c004 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 65d2a83510c3abf2f2cc3fb082ce56c99be32dfb
Author: Naoki Kambe <kambe at jprs.co.jp>
Date: Fri Mar 16 13:42:28 2012 +0900
[1751] change of #1751 entry to the simpler text for the users according to reviewing
commit b24200598f331f9b46805e04b92c23dd7018f2d4
Author: Naoki Kambe <kambe at jprs.co.jp>
Date: Thu Mar 15 20:46:29 2012 +0900
[1751] addition of notes, rearrangement for reading easily, and removal of unnecessary updates of the statistics_data variable
commit b28f331a0299014773151ec3bd652f3e59557e5d
Author: Naoki Kambe <kambe at jprs.co.jp>
Date: Thu Mar 15 20:47:50 2012 +0900
[1751] addition of a check of statistics data after a running auth is killed
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 10 +--
src/bin/stats/stats.py.in | 142 +++++++++++++++++++--------------
src/bin/stats/tests/b10-stats_test.py | 15 ++++
src/bin/stats/tests/test_utils.py | 9 +-
4 files changed, 104 insertions(+), 72 deletions(-)
-----------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index 3d2f9cf..c670d3b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,11 +1,7 @@
xxx. [bug] naokikambe
- Fix inconsistent statistics counts of Auth via bindctl or
- b10-stats-httpd while multiple b10-auth instances are running. Each
- count of Auth is accumulated across the instances except an inactive
- instances. Introduce a pid argument into the set command of b10-stats
- so that b10-stats identifies which instance sends by the PID which the
- b10-auth instance sends together with statistics data. Also add a
- regression check into systest against that inconsistency.
+ The statistic counters are now properly accumulated across multiple
+ instances of b10-auth (if there are multiple instances), instead of
+ providing result for random instance.
(Trac #1751, git TBD)
401. [func]* jinmei
diff --git a/src/bin/stats/stats.py.in b/src/bin/stats/stats.py.in
index 58716e4..fd59c3c 100755
--- a/src/bin/stats/stats.py.in
+++ b/src/bin/stats/stats.py.in
@@ -279,55 +279,66 @@ class Stats:
instance sends statistics data in the situation that multiple
instances are working.
"""
- self.update_modules()
- statistics_data = {}
- for (name, module) in self.modules.items():
- value = get_spec_defaults(module.get_statistics_spec())
- if module.validate_statistics(True, value):
- statistics_data[name] = value
- for (name, value) in self.statistics_data.items():
- if name in statistics_data:
- statistics_data[name].update(value)
- else:
- statistics_data[name] = value
- self.statistics_data = statistics_data
- def _sum_bymodule(statistics_data_bypid):
- # sum recursively each value under each
- # element
- def _sum(a, b):
+ # Note:
+ # The fix of #1751 is for multiple instances working. It is
+ # assumed here that they send different statistics data with
+ # each PID. Stats should save their statistics data by
+ # PID. The statistics data, which is the existing variable, is
+ # preserved by accumlating from statistics data by PID. This
+ # is an ad-hoc fix because administrators can not see
+ # statistics by each instance via bindctl or HTTP/XML. These
+ # interfaces aren't changed in this fix.
+
+ def _accum_bymodule(statistics_data_bypid):
+ # This is an internal function for the superordinate
+ # function. It accumulates statistics data of each PID by
+ # module. It returns the accumulation result.
+ def _accum(a, b):
+ # If the first arg is dict or list type, two values
+ # would be merged and accumlated.
if type(a) is dict:
- return dict([ (k, _sum(v, b[k])) if k in b else (k, v) \
+ return dict([ (k, _accum(v, b[k])) \
+ if k in b else (k, v) \
for (k, v) in a.items() ] \
- + [ (k, v) for (k, v) in b.items() \
+ + [ (k, v) \
+ for (k, v) in b.items() \
if k not in a ])
elif type(a) is list:
- return [ _sum(a[i], b[i]) if len(b) > i else a[i] \
+ return [ _accum(a[i], b[i]) \
+ if len(b) > i else a[i] \
for i in range(len(a)) ] \
- + [ b[i] for i in range(len(b)) \
+ + [ b[i] \
+ for i in range(len(b)) \
if len(a) <= i ]
- elif type(a) is float or type(a) is int:
+ # If the first arg is integer or float type, two
+ # values are just added.
+ elif type(a) is int or type(a) is float:
return a + b
- # If str or other types than above, then
- # just replace with the newer value.
+ # If the first arg is str or other types than above,
+ # then it just returns the first arg which is assumed
+ # to be the newer value.
return a
ret = {}
for data in statistics_data_bypid.values():
- ret.update(_sum(data, ret))
+ ret.update(_accum(data, ret))
return ret
+
+ # Firstly, it gets default statistics data in each spec file.
+ self.update_modules()
+ statistics_data = {}
+ for (name, module) in self.modules.items():
+ value = get_spec_defaults(module.get_statistics_spec())
+ if module.validate_statistics(True, value):
+ statistics_data[name] = value
+ self.statistics_data = statistics_data
+
+ # If the "owner" and "data" arguments in this function are
+ # specified, then the variable of statistics data of each pid
+ # would be updated.
+ errors = []
if owner and data:
- errors = []
try:
if self.modules[owner].validate_statistics(False, data, errors):
- # This is for multiple instances working. It is
- # assumed here that they send different statistics
- # data with each pid. Stats should save their
- # statistics data by pid. The statistics data,
- # which is the existing variable, is preserved by
- # summarizing from statistics data by pid. This is
- # an ad-hoc fix because administrators can not see
- # statistics by each instance via bindctl or
- # HTTP/XML. These interfaces aren't changed in
- # this fix.
if owner in self.statistics_data_bypid:
if pid in self.statistics_data_bypid[owner]:
self.statistics_data_bypid[owner][pid].update(data)
@@ -335,13 +346,16 @@ class Stats:
self.statistics_data_bypid[owner][pid] = data
else:
self.statistics_data_bypid[owner] = { pid : data }
- self.statistics_data[owner].update(
- _sum_bymodule(self.statistics_data_bypid[owner]))
except KeyError:
errors.append("unknown module name: " + str(owner))
- if errors: return errors
- # Find dead instances by invoking "show_processes" to Boss,
- # then remove their statistics data if there are ones
+
+ # If there are inactive instances, which was actually running
+ # on the system before, their statistics data would be
+ # removed. To find inactive instances, it invokes the
+ # "show_processes" command to Boss via the cc session. Then it
+ # gets active instance list and compares its PIDs with PIDs in
+ # statistics data which it already has. If inactive instances
+ # are found, it would remove their statistics data.
seq = self.cc_session.group_sendmsg(
isc.config.ccsession.create_command("show_processes", None),
"Boss")
@@ -349,27 +363,33 @@ class Stats:
if answer:
(rcode, value) = isc.config.ccsession.parse_answer(answer)
if rcode == 0:
- if type(value) is not list:
- return
- for v in value:
- if type(v) is not list or len(v) < 2:
- return
- mlist = [ k for k in self.statistics_data_bypid.keys() ]
- for m in mlist:
- plist1 = [ p for p in self.statistics_data_bypid[m].keys() ]
- plist2 = [ v[0] for v in value \
- if v[1].lower().find(m.lower()) >= 0 ] \
- + [-1] # add the default pid
- # set object difference: nplist = plist1 - plist2
- nplist = set(plist1).difference(set(plist2))
- for p in nplist:
- self.statistics_data_bypid[m].pop(p)
- if self.statistics_data_bypid[m]:
- if m in self.statistics_data:
- self.statistics_data[m].update(
- _sum_bymodule(self.statistics_data_bypid[m]))
- else:
- self.statistics_data_bypid.pop(m)
+ if type(value) is list and len(value) > 0 \
+ and type(value[0]) is list and len(value[0]) > 1:
+ mlist = [ k for k in self.statistics_data_bypid.keys() ]
+ for m in mlist:
+ # PID list which it has before except for -1
+ plist1 = [ p for p in self.statistics_data_bypid[m]\
+ .keys() if p != -1]
+ # PID list of active instances which is
+ # received from Boss
+ plist2 = [ v[0] for v in value \
+ if v[1].lower().find(m.lower()) \
+ >= 0 ]
+ # get inactive instance list by the difference
+ # between plist1 and plist2
+ nplist = set(plist1).difference(set(plist2))
+ for p in nplist:
+ self.statistics_data_bypid[m].pop(p)
+ if self.statistics_data_bypid[m]:
+ if m in self.statistics_data:
+ self.statistics_data[m].update(
+ _accum_bymodule(
+ self.statistics_data_bypid[m]))
+ # remove statistics data of the module with no
+ # PID
+ else:
+ self.statistics_data_bypid.pop(m)
+ if errors: return errors
def command_status(self):
"""
diff --git a/src/bin/stats/tests/b10-stats_test.py b/src/bin/stats/tests/b10-stats_test.py
index d34c998..5262b8a 100644
--- a/src/bin/stats/tests/b10-stats_test.py
+++ b/src/bin/stats/tests/b10-stats_test.py
@@ -400,6 +400,21 @@ class TestStats(unittest.TestCase):
self.assertEqual(self.stats.statistics_data_bypid['Auth'][9999]['queries.tcp'], 1001)
self.assertEqual(self.stats.statistics_data_bypid,
{'Auth': {9999: {'queries.tcp': 1001}}})
+ # kill running Auth, then statistics is reset
+ self.assertEqual(self.base.boss.server.pid_list[0][0], 9999)
+ killed = self.base.boss.server.pid_list.pop(0)
+ self.stats.update_statistics_data()
+ self.assertTrue('Auth' in self.stats.statistics_data)
+ self.assertTrue('queries.tcp' in self.stats.statistics_data['Auth'])
+ self.assertTrue('queries.udp' in self.stats.statistics_data['Auth'])
+ self.assertEqual(self.stats.statistics_data['Auth']['queries.tcp'], 0)
+ self.assertEqual(self.stats.statistics_data['Auth']['queries.udp'], 0)
+ self.assertFalse('Auth' in self.stats.statistics_data_bypid)
+ # restore statistics data of killed auth
+ self.base.boss.server.pid_list = [ killed ] + self.base.boss.server.pid_list[:]
+ self.stats.update_statistics_data(owner='Auth',
+ pid=9999,
+ **{'queries.tcp':1001})
# another pid of Auth
self.stats.update_statistics_data(owner='Auth',
pid=9998,
diff --git a/src/bin/stats/tests/test_utils.py b/src/bin/stats/tests/test_utils.py
index 8d9ed50..d91c1f2 100644
--- a/src/bin/stats/tests/test_utils.py
+++ b/src/bin/stats/tests/test_utils.py
@@ -185,6 +185,10 @@ class MockBoss:
self.spec_file.close()
self.cc_session = self.mccs._session
self.got_command_name = ''
+ self.pid_list = [[ 9999, "b10-auth" ],
+ [ 9998, "b10-auth-2" ],
+ [ 9997, "b10-auth-3" ],
+ [ 9996, "b10-auth-4" ]]
def run(self):
self.mccs.start()
@@ -218,10 +222,7 @@ class MockBoss:
elif command == 'show_processes':
# Return dummy pids
return isc.config.create_answer(
- 0, [[ 9999, "b10-auth" ],
- [ 9998, "b10-auth-2" ],
- [ 9997, "b10-auth-3" ],
- [ 9996, "b10-auth-4" ]])
+ 0, self.pid_list)
return isc.config.create_answer(1, "Unknown Command")
class MockAuth:
More information about the bind10-changes
mailing list