Commit b34b4edc authored by Jerry's avatar Jerry
Browse files

Provide customizable configurations for lowerbound_refresh, lowerbound_retry,

max_transfer_timeout and jitter_scope.(func, #340)


git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@3205 e5f2f494-b856-4b98-b285-d166d9295462
parent c85ab277
108. [func] jerry
src/bin/zonemgr: Provide customizable configurations for
lowerbound_refresh, lowerbound_retry, max_transfer_timeout and
jitter_scope. (Trac #340, r3205)
107. [func] zhang likun
Remove the parameter 'db_file' for command 'retransfer' of
xfrin module. xfrin.spec will not be generated by script.
......
......@@ -27,6 +27,11 @@ ZONE_NAME_CLASS3_IN = ("example.com", "IN")
ZONE_NAME_CLASS1_CH = ("sd.cn.", "CH")
ZONE_NAME_CLASS2_IN = ("tw.cn", "IN")
MAX_TRANSFER_TIMEOUT = 14400
LOWERBOUND_REFRESH = 10
LOWERBOUND_RETRY = 5
JITTER_SCOPE = 0.10
class ZonemgrTestException(Exception):
pass
......@@ -43,6 +48,10 @@ class MyZonemgrRefresh(ZonemgrRefresh):
self._cc = MySession()
self._db_file = "initdb.file"
current_time = time.time()
self._max_transfer_timeout = MAX_TRANSFER_TIMEOUT
self._lowerbound_refresh = LOWERBOUND_REFRESH
self._lowerbound_retry = LOWERBOUND_RETRY
self._jitter_scope = JITTER_SCOPE
self._zonemgr_refresh_info = {
('sd.cn.', 'IN'): {
'last_refresh_time': current_time,
......@@ -397,6 +406,19 @@ class TestZonemgrRefresh(unittest.TestCase):
self.assertTrue("refresh_timeout" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
self.assertTrue(zone_state == ZONE_REFRESHING)
def test_update_config_data(self):
config_data = {
"lowerbound_refresh" : 60,
"lowerbound_retry" : 30,
"max_transfer_timeout" : 19800,
"jitter_scope" : 0.25
}
self.zone_refresh.update_config_data(config_data)
self.assertEqual(60, self.zone_refresh._lowerbound_refresh)
self.assertEqual(30, self.zone_refresh._lowerbound_retry)
self.assertEqual(19800, self.zone_refresh._max_transfer_timeout)
self.assertEqual(0.25, self.zone_refresh._jitter_scope)
def tearDown(self):
sys.stdout = self.stdout_backup
......@@ -417,10 +439,16 @@ class MyZonemgr(Zonemgr):
def __init__(self):
self._db_file = "initdb.file"
self._zone_refresh = None
self._shutdown_event = threading.Event()
self._cc = MySession()
self._module_cc = MyCCSession()
self._config_data = {"zone_name" : "org.cn", "zone_class" : "CH", "master" : "127.0.0.1"}
self._config_data = {
"lowerbound_refresh" : 10,
"lowerbound_retry" : 5,
"max_transfer_timeout" : 14400,
"jitter_scope" : 0.1
}
def _start_zone_refresh_timer(self):
pass
......@@ -431,12 +459,21 @@ class TestZonemgr(unittest.TestCase):
self.zonemgr = MyZonemgr()
def test_config_handler(self):
config_data1 = {"zone_name" : "sd.cn.", "zone_class" : "CH", "master" : "192.168.1.1"}
config_data1 = {
"lowerbound_refresh" : 60,
"lowerbound_retry" : 30,
"max_transfer_timeout" : 14400,
"jitter_scope" : 0.1
}
self.zonemgr.config_handler(config_data1)
self.assertEqual(config_data1, self.zonemgr._config_data)
config_data2 = {"zone_name" : "sd.cn.", "port" : "53", "master" : "192.168.1.1"}
self.zonemgr.config_handler(config_data2)
self.assertEqual(config_data1, self.zonemgr._config_data)
# jitter should not be bigger than half of the original value
config_data3 = {"jitter_scope" : 0.7}
self.zonemgr.config_handler(config_data3)
self.assertEqual(0.5, self.zonemgr._config_data.get("jitter_scope"))
def test_get_db_file(self):
self.assertEqual("initdb.file", self.zonemgr.get_db_file())
......
......@@ -73,13 +73,6 @@ ZONE_OK = 0
ZONE_REFRESHING = 1
ZONE_EXPIRED = 2
# smallest refresh timeout
LOWERBOUND_REFRESH = 10
# smallest retry timeout
LOWERBOUND_RETRY = 5
# max zone transfer timeout
MAX_TRANSFER_TIMEOUT = 14400
# offsets of fields in the SOA RDATA
REFRESH_OFFSET = 3
RETRY_OFFSET = 4
......@@ -101,10 +94,11 @@ class ZonemgrRefresh:
do zone refresh.
"""
def __init__(self, cc, db_file, slave_socket):
def __init__(self, cc, db_file, slave_socket, config_data):
self._cc = cc
self._socket = slave_socket
self._db_file = db_file
self.update_config_data(config_data)
self._zonemgr_refresh_info = {}
self._build_zonemgr_refresh_info()
......@@ -122,25 +116,26 @@ class ZonemgrRefresh:
return time.time()
def _set_zone_timer(self, zone_name_class, max, jitter):
"""Set zone next refresh time."""
"""Set zone next refresh time.
jitter should not be bigger than half the original value."""
self._set_zone_next_refresh_time(zone_name_class, self._get_current_time() + \
self._random_jitter(max, jitter))
def _set_zone_refresh_timer(self, zone_name_class):
"""Set zone next refresh time after zone refresh success.
now + refresh*3/4 <= next_refresh_time <= now + refresh
now + refresh - jitter <= next_refresh_time <= now + refresh
"""
zone_refresh_time = float(self._get_zone_soa_rdata(zone_name_class).split(" ")[REFRESH_OFFSET])
zone_refresh_time = max(LOWERBOUND_REFRESH, zone_refresh_time)
self._set_zone_timer(zone_name_class, zone_refresh_time, (1 * zone_refresh_time) / 4)
zone_refresh_time = max(self._lowerbound_refresh, zone_refresh_time)
self._set_zone_timer(zone_name_class, zone_refresh_time, self._jitter_scope * zone_refresh_time)
def _set_zone_retry_timer(self, zone_name_class):
"""Set zone next refresh time after zone refresh fail.
now + retry*3/4 <= next_refresh_time <= now + retry
now + retry - jitter <= next_refresh_time <= now + retry
"""
zone_retry_time = float(self._get_zone_soa_rdata(zone_name_class).split(" ")[RETRY_OFFSET])
zone_retry_time = max(LOWERBOUND_RETRY, zone_retry_time)
self._set_zone_timer(zone_name_class, zone_retry_time, (1 * zone_retry_time) / 4)
zone_retry_time = max(self._lowerbound_retry, zone_retry_time)
self._set_zone_timer(zone_name_class, zone_retry_time, self._jitter_scope * zone_retry_time)
def _set_zone_notify_timer(self, zone_name_class):
"""Set zone next refresh time after receiving notify
......@@ -300,7 +295,7 @@ class ZonemgrRefresh:
"""Do zone refresh."""
log_msg("Do refresh for zone (%s, %s)." % zone_name_class)
self._set_zone_state(zone_name_class, ZONE_REFRESHING)
self._set_zone_refresh_timeout(zone_name_class, self._get_current_time() + MAX_TRANSFER_TIMEOUT)
self._set_zone_refresh_timeout(zone_name_class, self._get_current_time() + self._max_transfer_timeout)
notify_master = self._get_zone_notifier_master(zone_name_class)
# If the zone has notify master, send notify command to xfrin module
if notify_master:
......@@ -329,13 +324,13 @@ class ZonemgrRefresh:
while True:
# Zonemgr has no zone.
if self._zone_mgr_is_empty():
time.sleep(LOWERBOUND_RETRY) # A better time?
time.sleep(self._lowerbound_retry) # A better time?
continue
zone_need_refresh = self._find_need_do_refresh_zone()
# If don't get zone with minimum next refresh time, set timer timeout = LOWERBOUND_REFRESH
# If don't get zone with minimum next refresh time, set timer timeout = lowerbound_retry
if not zone_need_refresh:
timeout = LOWERBOUND_RETRY
timeout = self._lowerbound_retry
else:
timeout = self._get_zone_next_refresh_time(zone_need_refresh) - self._get_current_time()
if (timeout < 0):
......@@ -358,15 +353,23 @@ class ZonemgrRefresh:
raise ZonemgrException("[b10-zonemgr] Error with select(): %s\n" % e)
break
def update_config_data(self, new_config):
""" update ZonemgrRefresh config """
self._lowerbound_refresh = new_config.get('lowerbound_refresh')
self._lowerbound_retry = new_config.get('lowerbound_retry')
self._max_transfer_timeout = new_config.get('max_transfer_timeout')
self._jitter_scope = new_config.get('jitter_scope')
class Zonemgr:
"""Zone manager class."""
def __init__(self):
self._zone_refresh = None
self._setup_session()
self._db_file = self.get_db_file()
# Create socket pair for communicating between main thread and zonemgr timer thread
self._master_socket, self._slave_socket = socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM)
self._zone_refresh= ZonemgrRefresh(self._cc, self._db_file, self._slave_socket)
self._zone_refresh = ZonemgrRefresh(self._cc, self._db_file, self._slave_socket, self._config_data)
self._start_zone_refresh_timer()
self._lock = threading.Lock()
......@@ -388,6 +391,10 @@ class Zonemgr:
self.command_handler)
self._module_cc.add_remote_config(AUTH_SPECFILE_LOCATION)
self._config_data = self._module_cc.get_full_config()
# jitter should not be bigger than half of the original value
if self._config_data.get('jitter_scope') > 0.5:
self._config_data['jitter_scope'] = 0.5
log_msg("[b10-zonemgr] jitter_scope should not be bigger than 0.5.")
self._module_cc.start()
def get_db_file(self):
......@@ -414,13 +421,22 @@ class Zonemgr:
th.join()
def config_handler(self, new_config):
"""Update config data."""
""" Update config data. """
answer = create_answer(0)
for key in new_config:
if key not in self._config_data:
answer = create_answer(1, "Unknown config data: " + str(key))
continue
# jitter should not be bigger than half of the original value
if key == 'jitter_scope':
if new_config.get(key) > 0.5:
new_config[key] = 0.5
log_msg("[b10-zonemgr] jitter_scope should not be bigger than 0.5.")
self._config_data[key] = new_config[key]
if (self._zone_refresh):
self._zone_refresh.update_config_data(self._config_data)
return answer
def _parse_cmd_params(self, args, command):
......
......@@ -2,6 +2,30 @@
"module_spec": {
"module_name": "Zonemgr",
"config_data":[
{
"item_name": "lowerbound_refresh",
"item_type": "integer",
"item_optional": false,
"item_default": 10
},
{
"item_name": "lowerbound_retry",
"item_type": "integer",
"item_optional": false,
"item_default": 5
},
{
"item_name": "max_transfer_timeout",
"item_type": "integer",
"item_optional": false,
"item_default": 14400
},
{
"item_name": "jitter_scope",
"item_type": "real",
"item_optional": false,
"item_default": 0.25
}
],
"commands": [
{
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment