Parcourir la source

modify zonemgr code and unittest according to review opinions

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac289@2680 e5f2f494-b856-4b98-b285-d166d9295462
Jerry il y a 14 ans
Parent
commit
646dd51b96
2 fichiers modifiés avec 256 ajouts et 176 suppressions
  1. 167 132
      src/bin/zonemgr/tests/zonemgr_test.py
  2. 89 44
      src/bin/zonemgr/zonemgr.py.in

+ 167 - 132
src/bin/zonemgr/tests/zonemgr_test.py

@@ -13,7 +13,7 @@
 # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-'''Tests for the ZoneMgrRefreshInfo and ZoneMgr classes '''
+'''Tests for the ZonemgrRefresh and Zonemgr classes '''
 
 
 import unittest
@@ -21,9 +21,11 @@ import os
 import tempfile
 from zonemgr import *
 
-ZONE_NAME_CLASS1 = ("sd.cn.", "IN")
-ZONE_NAME_CLASS2 = ("tw.cn", "IN")
-ZONE_NAME_CLASS3 = ("example.com", "IN")
+ZONE_NAME_CLASS1_IN = ("sd.cn.", "IN")
+ZONE_NAME_CLASS2_CH = ("tw.cn", "CH")
+ZONE_NAME_CLASS3_IN = ("example.com", "IN")
+ZONE_NAME_CLASS1_CH = ("sd.cn.", "CH")
+ZONE_NAME_CLASS2_IN = ("tw.cn", "IN")
 
 class ZonemgrTestException(Exception):
     pass
@@ -36,7 +38,7 @@ class MySession():
         if module_name not in ("Auth", "Xfrin"):
             raise ZonemgrTestException("module name not exist")
 
-class MyZoneMgrRefreshInfo(ZoneMgrRefreshInfo):
+class MyZonemgrRefresh(ZonemgrRefresh):
     def __init__(self):
         self._cc = MySession()
         self._db_file = "initdb.file"
@@ -46,26 +48,28 @@ class MyZoneMgrRefreshInfo(ZoneMgrRefreshInfo):
          'next_refresh_time': 1280481598.822153, 
          'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600', 
          'zone_state': 0},
-         ('tw.cn', 'IN'): {
+         ('tw.cn', 'CH'): {
          'last_refresh_time': 1280474399.116421, 
          'next_refresh_time': 1280481599.116433, 
          'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600', 
          'zone_state': 0}
         } 
 
-class TestZoneMgrRefreshInfo(unittest.TestCase):
+class TestZonemgrRefresh(unittest.TestCase):
     def setUp(self):
         self.stdout_backup = sys.stdout
         sys.stdout = open(os.devnull, 'w')
-        self.zoneinfo = MyZoneMgrRefreshInfo()
+        self.zone_refresh = MyZonemgrRefresh()
 
     def test_random_jitter(self):
         max = 100025.120
         jitter = 0
-        self.assertEqual(max, self.zoneinfo._random_jitter(max, jitter))
+        self.assertEqual(max, self.zone_refresh._random_jitter(max, jitter))
         jitter = max / 4
-        self.assertTrue((3 * max / 4) <= self.zoneinfo._random_jitter(max, jitter)) 
-        self.assertTrue(self.zoneinfo._random_jitter(max, jitter) <= max) 
+        for i in range (0, 150):
+            self.assertTrue((3 * max / 4) <= self.zone_refresh._random_jitter(max, jitter)) 
+            self.assertTrue(self.zone_refresh._random_jitter(max, jitter) <= max) 
+            i += 1;
 
     def test_get_current_time(self):
         pass
@@ -74,37 +78,39 @@ class TestZoneMgrRefreshInfo(unittest.TestCase):
         max = 3600
         jitter = 900
         time1 = time.time()
-        self.zoneinfo._set_zone_timer(ZONE_NAME_CLASS1, 3600, 900)
+        self.zone_refresh._set_zone_timer(ZONE_NAME_CLASS1_IN, 3600, 900)
         time2 = time.time()
-        zone_timeout = float(self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["next_refresh_time"])
+        zone_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
         self.assertTrue((3600 - 900) <= (zone_timeout - time1))
         self.assertTrue((zone_timeout - time2) <= 3600)
 
     def test_set_zone_refresh_timer(self):
         time1 = time.time()
-        self.zoneinfo._set_zone_refresh_timer(ZONE_NAME_CLASS1)
-        zone_timeout = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["next_refresh_time"]
+        self.zone_refresh._set_zone_refresh_timer(ZONE_NAME_CLASS1_IN)
+        zone_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
         time2 = time.time()
         self.assertTrue((time1 + 7200 * 3 / 4) <= zone_timeout)
         self.assertTrue(zone_timeout <= time2 + 7200)
         
     def test_set_zone_retry_timer(self):
         time1 = time.time()
-        self.zoneinfo._set_zone_retry_timer(ZONE_NAME_CLASS1)
-        zone_timeout = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["next_refresh_time"]
+        self.zone_refresh._set_zone_retry_timer(ZONE_NAME_CLASS1_IN)
+        zone_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
         time2 = time.time()
         self.assertTrue((time1 + 3600 * 3 / 4) <= zone_timeout)
         self.assertTrue(zone_timeout <= time2 + 3600)
 
     def test_zone_not_exist(self):
-        self.assertFalse(self.zoneinfo._zone_not_exist(ZONE_NAME_CLASS1))
-        self.assertFalse(self.zoneinfo._zone_not_exist(ZONE_NAME_CLASS2))
-        self.assertTrue(self.zoneinfo._zone_not_exist(ZONE_NAME_CLASS3))
+        self.assertFalse(self.zone_refresh._zone_not_exist(ZONE_NAME_CLASS1_IN))
+        self.assertTrue(self.zone_refresh._zone_not_exist(ZONE_NAME_CLASS1_CH))
+        self.assertFalse(self.zone_refresh._zone_not_exist(ZONE_NAME_CLASS2_CH))
+        self.assertTrue(self.zone_refresh._zone_not_exist(ZONE_NAME_CLASS2_IN))
+        self.assertTrue(self.zone_refresh._zone_not_exist(ZONE_NAME_CLASS3_IN))
 
     def test_set_zone_notify_timer(self):
         time1 = time.time()
-        self.zoneinfo._set_zone_notify_timer(ZONE_NAME_CLASS1)
-        zone_timeout = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["next_refresh_time"]
+        self.zone_refresh._set_zone_notify_timer(ZONE_NAME_CLASS1_IN)
+        zone_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
         time2 = time.time()
         self.assertTrue(time1 <= zone_timeout)
         self.assertTrue(zone_timeout <= time2)
@@ -112,20 +118,22 @@ class TestZoneMgrRefreshInfo(unittest.TestCase):
     def test_zone_is_expired(self):
         current_time = time.time()
         zone_expired_time = 2419200
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["last_refresh_time"] = \
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["last_refresh_time"] = \
                                                   current_time - zone_expired_time - 1
-        self.assertTrue(self.zoneinfo._zone_is_expired(ZONE_NAME_CLASS1))
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["last_refresh_time"] = \
+        self.assertTrue(self.zone_refresh._zone_is_expired(ZONE_NAME_CLASS1_IN))
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["last_refresh_time"] = \
                                                   current_time - zone_expired_time + 1
-        self.assertFalse(self.zoneinfo._zone_is_expired(ZONE_NAME_CLASS1))
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"] = ZONE_EXPIRED
-        self.assertTrue(self.zoneinfo._zone_is_expired(ZONE_NAME_CLASS1))
+        self.assertFalse(self.zone_refresh._zone_is_expired(ZONE_NAME_CLASS1_IN))
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"] = ZONE_EXPIRED
+        self.assertTrue(self.zone_refresh._zone_is_expired(ZONE_NAME_CLASS1_IN))
 
     def test_get_zone_soa_rdata(self):
         soa_rdata1  = 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600' 
         soa_rdata2  = 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600' 
-        self.assertEqual(soa_rdata1, self.zoneinfo._get_zone_soa_rdata(ZONE_NAME_CLASS1))
-        self.assertEqual(soa_rdata2, self.zoneinfo._get_zone_soa_rdata(ZONE_NAME_CLASS2))
+        self.assertEqual(soa_rdata1, self.zone_refresh._get_zone_soa_rdata(ZONE_NAME_CLASS1_IN))
+        self.assertRaises(KeyError, self.zone_refresh._get_zone_soa_rdata, ZONE_NAME_CLASS1_CH)
+        self.assertEqual(soa_rdata2, self.zone_refresh._get_zone_soa_rdata(ZONE_NAME_CLASS2_CH))
+        self.assertRaises(KeyError, self.zone_refresh._get_zone_soa_rdata, ZONE_NAME_CLASS2_IN)
          
     def test_zonemgr_reload_zone(self):
         soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600'
@@ -134,82 +142,106 @@ class TestZoneMgrRefreshInfo(unittest.TestCase):
                     'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600')
         sqlite3_ds.get_zone_soa = get_zone_soa
 
-        self.zoneinfo._zonemgr_reload_zone(ZONE_NAME_CLASS1)
-        self.assertEqual(soa_rdata, self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_soa_rdata"])
+        self.zone_refresh.zonemgr_reload_zone(ZONE_NAME_CLASS1_IN)
+        self.assertEqual(soa_rdata, self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_soa_rdata"])
 
     def test_get_zone_notifier_master(self):
         notify_master = "192.168.1.1"
-        self.assertEqual(None, self.zoneinfo._get_zone_notifier_master(ZONE_NAME_CLASS1))
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["notify_master"] = notify_master
-        self.assertEqual(notify_master, self.zoneinfo._get_zone_notifier_master(ZONE_NAME_CLASS1))
+        self.assertEqual(None, self.zone_refresh._get_zone_notifier_master(ZONE_NAME_CLASS1_IN))
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["notify_master"] = notify_master
+        self.assertEqual(notify_master, self.zone_refresh._get_zone_notifier_master(ZONE_NAME_CLASS1_IN))
 
     def test_set_zone_notifier_master(self):
         notify_master = "192.168.1.1"
-        self.zoneinfo._set_zone_notifier_master(ZONE_NAME_CLASS1, notify_master)
-        self.assertEqual(self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]\
+        self.zone_refresh._set_zone_notifier_master(ZONE_NAME_CLASS1_IN, notify_master)
+        self.assertEqual(self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]\
                                                                 ["notify_master"], notify_master)
 
     def test_clear_zone_notifier_master(self):
         notify_master = "192.168.1.1"
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["notify_master"] = notify_master
-        self.zoneinfo._clear_zone_notifier_master(ZONE_NAME_CLASS1)
-        self.assertFalse("notify_master" in self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1].keys())
-        self.zoneinfo._clear_zone_notifier_master(ZONE_NAME_CLASS2)
-        self.assertFalse("notify_master" in self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS2].keys())
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["notify_master"] = notify_master
+        self.zone_refresh._clear_zone_notifier_master(ZONE_NAME_CLASS1_IN)
+        self.assertFalse("notify_master" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
+        self.zone_refresh._clear_zone_notifier_master(ZONE_NAME_CLASS2_CH)
+        self.assertFalse("notify_master" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS2_CH].keys())
 
     def test_get_zone_state(self):
-        self.assertEqual(ZONE_OK, self.zoneinfo._get_zone_state(ZONE_NAME_CLASS2))
-        self.assertEqual(ZONE_OK, self.zoneinfo._get_zone_state(ZONE_NAME_CLASS2))
+        self.assertEqual(ZONE_OK, self.zone_refresh._get_zone_state(ZONE_NAME_CLASS1_IN))
+        self.assertEqual(ZONE_OK, self.zone_refresh._get_zone_state(ZONE_NAME_CLASS2_CH))
 
     def test_set_zone_state(self):
-        self.zoneinfo._set_zone_state(ZONE_NAME_CLASS1, ZONE_REFRESHING)
-        self.zoneinfo._set_zone_state(ZONE_NAME_CLASS2, ZONE_EXPIRED)
+        self.zone_refresh._set_zone_state(ZONE_NAME_CLASS1_IN, ZONE_REFRESHING)
+        self.zone_refresh._set_zone_state(ZONE_NAME_CLASS2_CH, ZONE_EXPIRED)
         self.assertEqual(ZONE_REFRESHING, \
-                self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"])
+                self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"])
         self.assertEqual(ZONE_EXPIRED, \
-                self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS2]["zone_state"])
+                self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS2_CH]["zone_state"])
 
     def test_get_zone_refresh_timeout(self):
         current_time = time.time()
-        self.assertFalse("refresh_timeout" in self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1].keys())
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["refresh_timeout"] = current_time
-        self.assertEqual(current_time, self.zoneinfo._get_zone_refresh_timeout(ZONE_NAME_CLASS1))
+        self.assertFalse("refresh_timeout" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["refresh_timeout"] = current_time
+        self.assertEqual(current_time, self.zone_refresh._get_zone_refresh_timeout(ZONE_NAME_CLASS1_IN))
 
     def test_set_zone_refresh_timeout(self):
         current_time = time.time()
-        self.zoneinfo._set_zone_refresh_timeout(ZONE_NAME_CLASS1, current_time)
-        refresh_time = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["refresh_timeout"]
+        self.zone_refresh._set_zone_refresh_timeout(ZONE_NAME_CLASS1_IN, current_time)
+        refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["refresh_timeout"]
         self.assertEqual(current_time, refresh_time) 
 
     def test_get_zone_next_refresh_time(self):
         current_time = time.time()
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["next_refresh_time"] = current_time
-        self.assertEqual(current_time, self.zoneinfo._get_zone_next_refresh_time(ZONE_NAME_CLASS1))
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"] = current_time
+        self.assertEqual(current_time, self.zone_refresh._get_zone_next_refresh_time(ZONE_NAME_CLASS1_IN))
 
     def test_set_zone_next_refresh_time(self):
         current_time = time.time()
-        self.zoneinfo._set_zone_next_refresh_time(ZONE_NAME_CLASS1, current_time)
-        next_refresh_time = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["next_refresh_time"]
+        self.zone_refresh._set_zone_next_refresh_time(ZONE_NAME_CLASS1_IN, current_time)
+        next_refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
         self.assertEqual(current_time, next_refresh_time)
 
     def test_get_zone_last_refresh_time(self):
         current_time = time.time()
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["last_refresh_time"] = current_time
-        self.assertEqual(current_time, self.zoneinfo._get_zone_last_refresh_time(ZONE_NAME_CLASS1))
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["last_refresh_time"] = current_time
+        self.assertEqual(current_time, self.zone_refresh._get_zone_last_refresh_time(ZONE_NAME_CLASS1_IN))
 
     def test_set_zone_last_refresh_time(self):
         current_time = time.time()
-        self.zoneinfo._set_zone_last_refresh_time(ZONE_NAME_CLASS1, current_time)
-        last_refresh_time = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["last_refresh_time"]
+        self.zone_refresh._set_zone_last_refresh_time(ZONE_NAME_CLASS1_IN, current_time)
+        last_refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["last_refresh_time"]
         self.assertEqual(current_time, last_refresh_time) 
 
     def test_send_command(self):
-        self.assertRaises(ZonemgrTestException, self.zoneinfo._send_command, "Unknown", "Notify", None)
+        self.assertRaises(ZonemgrTestException, self.zone_refresh._send_command, "Unknown", "Notify", None)
 
     def test_zone_mgr_is_empty(self):
-        self.assertFalse(self.zoneinfo._zone_mgr_is_empty())
-        self.zoneinfo._zonemgr_refresh_info = {} 
-        self.assertTrue(self.zoneinfo._zone_mgr_is_empty())
+        self.assertFalse(self.zone_refresh._zone_mgr_is_empty())
+        self.zone_refresh._zonemgr_refresh_info = {} 
+        self.assertTrue(self.zone_refresh._zone_mgr_is_empty())
+
+    def test_zonemgr_add_zone(self):
+        soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600'
+
+        def get_zone_soa(zone_name, db_file):
+            return (1, 2, 'sd.cn.', 'cn.sd.', 21600, 'SOA', None, 
+                    'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600')
+
+        sqlite3_ds.get_zone_soa = get_zone_soa
+
+        self.zone_refresh._zonemgr_refresh_info = {}
+        self.zone_refresh.zonemgr_add_zone(ZONE_NAME_CLASS1_IN)
+        self.assertEqual(1, len(self.zone_refresh._zonemgr_refresh_info))
+        zone_soa_rdata = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_soa_rdata"]
+        self.assertEqual(soa_rdata, zone_soa_rdata) 
+        self.assertEqual(ZONE_OK, self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"])
+        self.assertTrue("last_refresh_time" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
+        self.assertTrue("next_refresh_time" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
+
+        def get_zone_soa2(zone_name, db_file):
+            return None
+        sqlite3_ds.get_zone_soa = get_zone_soa2
+        self.assertRaises(ZonemgrException, self.zone_refresh.zonemgr_add_zone, \
+                                          ZONE_NAME_CLASS1_IN)
 
     def test_build_zonemgr_refresh_info(self):
         soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600'
@@ -224,26 +256,26 @@ class TestZoneMgrRefreshInfo(unittest.TestCase):
         sqlite3_ds.get_zones_info = get_zones_info
         sqlite3_ds.get_zone_soa = get_zone_soa
 
-        self.zoneinfo._zonemgr_refresh_info = {}
-        self.zoneinfo._build_zonemgr_refresh_info()
-        self.assertEqual(1, len(self.zoneinfo._zonemgr_refresh_info))
-        zone_soa_rdata = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_soa_rdata"]
+        self.zone_refresh._zonemgr_refresh_info = {}
+        self.zone_refresh._build_zonemgr_refresh_info()
+        self.assertEqual(1, len(self.zone_refresh._zonemgr_refresh_info))
+        zone_soa_rdata = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_soa_rdata"]
         self.assertEqual(soa_rdata, zone_soa_rdata) 
-        self.assertEqual(ZONE_OK, self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"])
-        self.assertTrue("last_refresh_time" in self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1].keys())
-        self.assertTrue("next_refresh_time" in self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1].keys())
+        self.assertEqual(ZONE_OK, self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"])
+        self.assertTrue("last_refresh_time" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
+        self.assertTrue("next_refresh_time" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
 
     def test_zone_handle_notify(self):
-        self.zoneinfo.zone_handle_notify(ZONE_NAME_CLASS1,"127.0.0.1")
-        notify_master = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["notify_master"]
+        self.zone_refresh.zone_handle_notify(ZONE_NAME_CLASS1_IN,"127.0.0.1")
+        notify_master = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["notify_master"]
         self.assertEqual("127.0.0.1", notify_master) 
-        zone_timeout = float(self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["next_refresh_time"])
+        zone_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
         current_time = time.time()
         self.assertTrue(zone_timeout <= current_time)
-        self.assertRaises(ZonemgrException, self.zoneinfo.zone_handle_notify,\
-                          "org.cn.", "127.0.0.1")
-        self.assertRaises(ZonemgrException, self.zoneinfo.zone_handle_notify,\
-                          ZONE_NAME_CLASS3, "127.0.0.1")
+        self.assertRaises(ZonemgrException, self.zone_refresh.zone_handle_notify,\
+                          ("org.cn.", "IN"), "127.0.0.1")
+        self.assertRaises(ZonemgrException, self.zone_refresh.zone_handle_notify,\
+                          ZONE_NAME_CLASS3_IN, "127.0.0.1")
 
     def test_zone_refresh_success(self):
         soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600'
@@ -252,99 +284,103 @@ class TestZoneMgrRefreshInfo(unittest.TestCase):
                     'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600')
         sqlite3_ds.get_zone_soa = get_zone_soa
         time1 = time.time()
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"] = ZONE_REFRESHING
-        self.zoneinfo.zone_refresh_success(ZONE_NAME_CLASS1)
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"] = ZONE_REFRESHING
+        self.zone_refresh.zone_refresh_success(ZONE_NAME_CLASS1_IN)
         time2 = time.time()
-        zone_soa_rdata = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_soa_rdata"]
+        zone_soa_rdata = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_soa_rdata"]
         self.assertEqual(soa_rdata, zone_soa_rdata) 
-        next_refresh_time = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["next_refresh_time"]
+        next_refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
         self.assertTrue((time1 + 3 * 1800 / 4) <= next_refresh_time) 
         self.assertTrue(next_refresh_time <= time2 + 1800)
-        self.assertEqual(ZONE_OK, self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"])
-        last_refresh_time = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["last_refresh_time"]
+        self.assertEqual(ZONE_OK, self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"])
+        last_refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["last_refresh_time"]
         self.assertTrue(time1 <= last_refresh_time)
         self.assertTrue(last_refresh_time <= time2)
-        self.assertRaises(ZonemgrException, self.zoneinfo.zone_refresh_success, "org.cn.")
-        self.assertRaises(ZonemgrException, self.zoneinfo.zone_refresh_success, ZONE_NAME_CLASS3) 
+        self.assertRaises(ZonemgrException, self.zone_refresh.zone_refresh_success, ("org.cn.", "CH"))
+        self.assertRaises(ZonemgrException, self.zone_refresh.zone_refresh_success, ZONE_NAME_CLASS3_IN) 
 
     def test_zone_refresh_fail(self):
         soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600' 
         time1 = time.time()
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"] = ZONE_REFRESHING
-        self.zoneinfo.zone_refresh_fail(ZONE_NAME_CLASS1)
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"] = ZONE_REFRESHING
+        self.zone_refresh.zone_refresh_fail(ZONE_NAME_CLASS1_IN)
         time2 = time.time()
-        zone_soa_rdata = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_soa_rdata"]
+        zone_soa_rdata = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_soa_rdata"]
         self.assertEqual(soa_rdata, zone_soa_rdata)
-        next_refresh_time = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["next_refresh_time"]
+        next_refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
         self.assertTrue((time1 + 3 * 3600 / 4) <= next_refresh_time)
         self.assertTrue(next_refresh_time <= time2 + 3600)
-        self.assertEqual(ZONE_OK, self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"])
-        self.assertRaises(ZonemgrException, self.zoneinfo.zone_refresh_fail, "org.cn.")
-        self.assertRaises(ZonemgrException, self.zoneinfo.zone_refresh_fail, ZONE_NAME_CLASS3) 
+        self.assertEqual(ZONE_OK, self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"])
+        self.assertRaises(ZonemgrException, self.zone_refresh.zone_refresh_fail, ("org.cn.", "CH"))
+        self.assertRaises(ZonemgrException, self.zone_refresh.zone_refresh_fail, ZONE_NAME_CLASS3_IN) 
 
     def test_find_need_do_refresh_zone(self):
         time1 = time.time()
-        self.zoneinfo._zonemgr_refresh_info = { 
+        self.zone_refresh._zonemgr_refresh_info = { 
                 ("sd.cn.","IN"):{
                     'last_refresh_time': time1,
                     'next_refresh_time': time1 + 7200, 
                     'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600', 
                     'zone_state': ZONE_OK},
-                ("tw.cn","IN"):{
+                ("tw.cn","CH"):{
                     'last_refresh_time': time1 - 7200, 
                     'next_refresh_time': time1, 
                     'refresh_timeout': time1 + MAX_TRANSFER_TIMEOUT, 
                     'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600', 
                     'zone_state': ZONE_REFRESHING}
                 }
-        zone_need_refresh = self.zoneinfo._find_need_do_refresh_zone()
-        self.assertEqual(ZONE_NAME_CLASS1, zone_need_refresh)
+        zone_need_refresh = self.zone_refresh._find_need_do_refresh_zone()
+        self.assertEqual(ZONE_NAME_CLASS1_IN, zone_need_refresh)
 
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["last_refresh_time"] = time1 - 2419200
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"] = ZONE_EXPIRED
-        zone_need_refresh = self.zoneinfo._find_need_do_refresh_zone()
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["last_refresh_time"] = time1 - 2419200
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"] = ZONE_EXPIRED
+        zone_need_refresh = self.zone_refresh._find_need_do_refresh_zone()
         self.assertEqual(None, zone_need_refresh)
 
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"] = ZONE_REFRESHING
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["notify_master"] = "192.168.0.1"
-        zone_need_refresh = self.zoneinfo._find_need_do_refresh_zone()
-        self.assertEqual(ZONE_NAME_CLASS1, zone_need_refresh)
-        self.assertEqual(ZONE_EXPIRED, self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"])
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"] = ZONE_REFRESHING
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["notify_master"] = "192.168.0.1"
+        zone_need_refresh = self.zone_refresh._find_need_do_refresh_zone()
+        self.assertEqual(ZONE_NAME_CLASS1_IN, zone_need_refresh)
+        self.assertEqual(ZONE_EXPIRED, self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"])
 
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS2]["refresh_timeout"] = time1 
-        zone_need_refresh = self.zoneinfo._find_need_do_refresh_zone()
-        self.assertEqual(ZONE_NAME_CLASS2, zone_need_refresh)
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS2_CH]["refresh_timeout"] = time1 
+        zone_need_refresh = self.zone_refresh._find_need_do_refresh_zone()
+        self.assertEqual(ZONE_NAME_CLASS2_CH, zone_need_refresh)
 
     def test_do_refresh(self):
         time1 = time.time()
-        self.zoneinfo._zonemgr_refresh_info = {
+        self.zone_refresh._zonemgr_refresh_info = {
                 ("sd.cn.", "IN"):{
                     'last_refresh_time': time1 - 7200,
                     'next_refresh_time': time1 - 1, 
                     'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600', 
                     'zone_state': ZONE_OK}
                 }
-        self.zoneinfo._do_refresh(ZONE_NAME_CLASS1)
+        self.zone_refresh._do_refresh(ZONE_NAME_CLASS1_IN)
         time2 = time.time()
-        zone_state = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"]
+        zone_state = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"]
         self.assertEqual(ZONE_REFRESHING, zone_state)
-        refresh_timeout = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["refresh_timeout"] 
+        refresh_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["refresh_timeout"] 
         self.assertTrue(time1 + MAX_TRANSFER_TIMEOUT <= refresh_timeout)
         self.assertTrue(time2 + MAX_TRANSFER_TIMEOUT >= refresh_timeout) 
 
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["notify_master"] = "127.0.0.1"
-        self.zoneinfo._do_refresh(ZONE_NAME_CLASS1)
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["notify_master"] = "127.0.0.1"
+        self.zone_refresh._do_refresh(ZONE_NAME_CLASS1_IN)
         time2 = time.time()
-        zone_state = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"]
+        zone_state = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"]
         self.assertEqual(ZONE_REFRESHING, zone_state) 
-        refrsh_timeout = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["refresh_timeout"] 
+        refresh_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["refresh_timeout"] 
         self.assertTrue(time1 + MAX_TRANSFER_TIMEOUT <= refresh_timeout)
         self.assertTrue(time2 + MAX_TRANSFER_TIMEOUT >= refresh_timeout)
-        self.assertFalse("notify_master" in self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1].keys())
+        self.assertFalse("notify_master" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
 
     def test_run_timer(self):
+        """This case will run timer in daemon thread. 
+        The zone's next_refresh_time is less than now, so zonemgr will do zone refresh 
+        immediately. The zone's state will become "refreshing". 
+        Then closing the socket ,the timer will stop, and throw a ZonemgrException."""
         time1 = time.time()
-        self.zoneinfo._zonemgr_refresh_info = {
+        self.zone_refresh._zonemgr_refresh_info = {
                 ("sd.cn.", "IN"):{
                     'last_refresh_time': time1 - 7200,
                     'next_refresh_time': time1 - 1, 
@@ -352,17 +388,16 @@ class TestZoneMgrRefreshInfo(unittest.TestCase):
                     'zone_state': ZONE_OK}
                 }
         master_socket, slave_socket = socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM)
-        self.zoneinfo._socket = slave_socket
-        # Run timer in daemon thread
-        listener = threading.Thread(target = self.zoneinfo.run_timer, args = ())
+        self.zone_refresh._socket = slave_socket
+        listener = threading.Thread(target = self.zone_refresh.run_timer, args = ())
         listener.setDaemon(True)
         listener.start()
         slave_socket.close()
-        zone_state = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"]
-        self.assertTrue("refresh_timeout" in self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1].keys())
+        zone_state = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"]
+        self.assertTrue("refresh_timeout" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
         self.assertTrue(zone_state == ZONE_REFRESHING)
 
-        self.assertRaises(ZonemgrException, self.zoneinfo.run_timer)
+        self.assertRaises(ZonemgrException, self.zone_refresh.run_timer)
 
     def tearDown(self):
         sys.stdout = self.stdout_backup
@@ -386,7 +421,7 @@ class MyZonemgr(Zonemgr):
         self._shutdown_event = threading.Event()
         self._cc = MySession()
         self._module_cc = MyCCSession()
-        self._config_data = {"zone_name" : "org.cn", "zone_class" : "IN", "master" : "127.0.0.1"}
+        self._config_data = {"zone_name" : "org.cn", "zone_class" : "CH", "master" : "127.0.0.1"}
 
     def _start_zone_refresh_timer(self):
         pass
@@ -397,7 +432,7 @@ class TestZonemgr(unittest.TestCase):
         self.zonemgr = MyZonemgr()
 
     def test_config_handler(self):
-        config_data1 = {"zone_name" : "sd.cn.", "zone_class" : "IN", "master" : "192.168.1.1"}
+        config_data1 = {"zone_name" : "sd.cn.", "zone_class" : "CH", "master" : "192.168.1.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"}
@@ -408,14 +443,14 @@ class TestZonemgr(unittest.TestCase):
         self.assertEqual("initdb.file", self.zonemgr.get_db_file())
     
     def test_parse_cmd_params(self):
-        params1 = {"zone_name" : "org.cn", "zone_class" : "IN", "master" : "127.0.0.1"}
-        answer1 = (("org.cn", "IN"), "127.0.0.1")
+        params1 = {"zone_name" : "org.cn", "zone_class" : "CH", "master" : "127.0.0.1"}
+        answer1 = (("org.cn", "CH"), "127.0.0.1")
         self.assertEqual(answer1, self.zonemgr._parse_cmd_params(params1, ZONE_NOTIFY_COMMAND))
-        params2 = {"zone_name" : "org.cn", "zone_class" : "IN"}
-        answer2 = ("org.cn", "IN")
+        params2 = {"zone_name" : "org.cn", "zone_class" : "CH"}
+        answer2 = ("org.cn", "CH")
         self.assertEqual(answer2, self.zonemgr._parse_cmd_params(params2, ZONE_XFRIN_SUCCESS_COMMAND))
         self.assertRaises(ZonemgrException, self.zonemgr._parse_cmd_params, params2, ZONE_NOTIFY_COMMAND)
-        params1 = {"zone_class" : "IN"}
+        params1 = {"zone_class" : "CH"}
         self.assertRaises(ZonemgrException, self.zonemgr._parse_cmd_params, params2, ZONE_NOTIFY_COMMAND)
 
     def tearDown(self):

+ 89 - 44
src/bin/zonemgr/zonemgr.py.in

@@ -56,11 +56,13 @@ __version__ = "BIND10"
 # define module name
 XFRIN_MODULE_NAME = 'Xfrin'
 AUTH_MODULE_NAME = 'Auth'
+
 # define command name
 ZONE_XFRIN_FAILED_COMMAND = 'zone_xfrin_failed'
 ZONE_XFRIN_SUCCESS_COMMAND = 'zone_new_data_ready'
 ZONE_REFRESH_COMMAND = 'refresh_from_zonemgr'
 ZONE_NOTIFY_COMMAND = 'notify'
+
 # define zone state
 ZONE_OK = 0
 ZONE_REFRESHING = 1
@@ -73,11 +75,26 @@ LOWERBOUND_RETRY = 5
 # max zone transfer timeout
 MAX_TRANSFER_TIMEOUT = 14400
 
+# offsets of fields in the SOA RDATA
+REFRESH_OFFSET = 3
+RETRY_OFFSET = 4
+EXPIRED_OFFSET = 5
+
+# verbose mode
+VERBOSE_MODE = False
+
+def log_msg(msg):
+    if VERBOSE_MODE:
+        sys.stdout.write("[b10-zonemgr] %s\n" % str(msg))
+
 class ZonemgrException(Exception):
     pass
 
-class ZoneMgrRefreshInfo:
-    """This class will maintain and manage zone refresh info"""
+class ZonemgrRefresh:
+    """This class will maintain and manage zone refresh info.
+    It also provides methods to keep track of zone timers and 
+    do zone refresh.
+    """
 
     def __init__(self, cc, db_file, slave_socket):
         self._cc = cc
@@ -89,10 +106,12 @@ class ZoneMgrRefreshInfo:
     def _random_jitter(self, max, jitter):
         """Imposes some random jitters for refresh and
         retry timers to avoid many zones need to do refresh
-        at the same time."""
+        at the same time. 
+        The value should be between (max - jitter) and max.
+        """
         if 0 == jitter:
             return max
-        return max - random.normalvariate(max, jitter) % jitter
+        return random.uniform(max - jitter, max)
 
     def _get_current_time(self):
         return time.time()
@@ -106,18 +125,16 @@ class ZoneMgrRefreshInfo:
         """Set zone next refresh time after zone refresh success.
            now + refresh*3/4 <= next_refresh_time <= now + refresh
            """
-        zone_refresh_time = float(self._get_zone_soa_rdata(zone_name_class).split(" ")[3])
-        if (zone_refresh_time < LOWERBOUND_REFRESH):
-            zone_refresh_time = LOWERBOUND_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)
 
     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
            """
-        zone_retry_time = float(self._get_zone_soa_rdata(zone_name_class).split(" ")[4])
-        if (zone_retry_time < LOWERBOUND_RETRY):
-            zone_retry_time = LOWERBOUND_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)
 
     def _set_zone_notify_timer(self, zone_name_class):
@@ -135,10 +152,10 @@ class ZoneMgrRefreshInfo:
     def zone_refresh_success(self, zone_name_class):
         """Update zone info after zone refresh success"""
         if (self._zone_not_exist(zone_name_class)):
-            raise ZonemgrException("[b10-zonemgr] Zone %s doesn't \
-                                    belong to zonemgr" % zone_name_class[0])
+            raise ZonemgrException("[b10-zonemgr] Zone (%s, %s) doesn't \
+                                    belong to zonemgr" % zone_name_class)
             return
-        self._zonemgr_reload_zone(zone_name_class)
+        self.zonemgr_reload_zone(zone_name_class)
         self._set_zone_refresh_timer(zone_name_class)
         self._set_zone_state(zone_name_class, ZONE_OK)
         self._set_zone_last_refresh_time(zone_name_class, self._get_current_time())
@@ -146,8 +163,8 @@ class ZoneMgrRefreshInfo:
     def zone_refresh_fail(self, zone_name_class):
         """Update zone info after zone refresh fail"""
         if (self._zone_not_exist(zone_name_class)):
-            raise ZonemgrException("[b10-zonemgr] Zone %s doesn't \
-                                    belong to zonemgr" % zone_name_class[0])
+            raise ZonemgrException("[b10-zonemgr] Zone (%s, %s) doesn't \
+                                    belong to zonemgr" % zone_name_class)
             return
         self._set_zone_state(zone_name_class, ZONE_OK)
         self._set_zone_retry_timer(zone_name_class)
@@ -155,25 +172,41 @@ class ZoneMgrRefreshInfo:
     def zone_handle_notify(self, zone_name_class, master):
         """Handle zone notify"""
         if (self._zone_not_exist(zone_name_class)):
-            raise ZonemgrException("[b10-zonemgr] Notified zone %s doesn't \
-                                    belong to zonemgr" % zone_name_class[0])
+            raise ZonemgrException("[b10-zonemgr] Notified zone (%s, %s) doesn't \
+                                    belong to zonemgr" % zone_name_class)
             return
         self._set_zone_notifier_master(zone_name_class, master)
         self._set_zone_notify_timer(zone_name_class)
 
+    def zonemgr_reload_zone(self, zone_name_class):
+        """ Reload a zone."""
+        zone_soa = sqlite3_ds.get_zone_soa(str(zone_name_class[0]), self._db_file)
+        self._zonemgr_refresh_info[zone_name_class]["zone_soa_rdata"] = zone_soa[7]
+
+    def zonemgr_add_zone(self, zone_name_class):
+        """ Add a zone into zone manager."""
+        zone_info = {}
+        zone_soa = sqlite3_ds.get_zone_soa(str(zone_name_class[0]), self._db_file)
+        if not zone_soa:
+            raise ZonemgrException("[b10-zonemgr] zone (%s, %s) doesn't have soa." % zone_name_class)
+        zone_info["zone_soa_rdata"] = zone_soa[7]
+        zone_info["zone_state"] = ZONE_OK
+        zone_info["last_refresh_time"] = self._get_current_time() 
+        zone_info["next_refresh_time"] = self._get_current_time() + \
+                                         float(zone_soa[7].split(" ")[REFRESH_OFFSET])
+        self._zonemgr_refresh_info[zone_name_class] = zone_info
+
     def _build_zonemgr_refresh_info(self):
         """ Build zonemgr refresh info map."""
+        log_msg("Start loading zone into zonemgr.")
         for zone_name, zone_class in sqlite3_ds.get_zones_info(self._db_file):
-            zone_info = {}
-            zone_soa = sqlite3_ds.get_zone_soa(str(zone_name), self._db_file)
-            zone_info["zone_soa_rdata"] = zone_soa[7]
-            zone_info["zone_state"] = ZONE_OK
-            zone_info["last_refresh_time"] = self._get_current_time() 
-            zone_info["next_refresh_time"] = self._get_current_time() + float(zone_soa[7].split(" ")[3])
-            self._zonemgr_refresh_info[(zone_name, zone_class)] = zone_info
+            zone_name_class = (zone_name, zone_class)
+            self.zonemgr_add_zone(zone_name_class)
+        log_msg("Finish loading zone into zonemgr.")
 
     def _zone_is_expired(self, zone_name_class):
-        zone_expired_time = float(self._get_zone_soa_rdata(zone_name_class).split(" ")[5])
+        """Judge whether a zone is expired or not."""
+        zone_expired_time = float(self._get_zone_soa_rdata(zone_name_class).split(" ")[EXPIRED_OFFSET])
         zone_last_refresh_time = self._get_zone_last_refresh_time(zone_name_class)
         if (ZONE_EXPIRED == self._get_zone_state(zone_name_class) or
             zone_last_refresh_time + zone_expired_time <= self._get_current_time()):
@@ -184,10 +217,6 @@ class ZoneMgrRefreshInfo:
     def _get_zone_soa_rdata(self, zone_name_class):
         return self._zonemgr_refresh_info[zone_name_class]["zone_soa_rdata"]
 
-    def _zonemgr_reload_zone(self, zone_name_class):
-        zone_soa = sqlite3_ds.get_zone_soa(str(zone_name_class[0]), self._db_file)
-        self._zonemgr_refresh_info[zone_name_class]["zone_soa_rdata"] = zone_soa[7]
-
     def _get_zone_last_refresh_time(self, zone_name_class):
         return self._zonemgr_refresh_info[zone_name_class]["last_refresh_time"]
 
@@ -228,7 +257,10 @@ class ZoneMgrRefreshInfo:
     def _send_command(self, module_name, command_name, params):
         """Send command between modules."""
         msg = create_command(command_name, params)
-        self._cc.group_sendmsg(msg, module_name)
+        try:
+            self._cc.group_sendmsg(msg, module_name)
+        except socket.error:
+            std.err.write("[b10-zonemgr] Failed to send to module %s, the session has been closed." % module_name) 
 
     def _find_need_do_refresh_zone(self):
         """Find the first zone need do refresh, if no zone need
@@ -239,6 +271,7 @@ class ZoneMgrRefreshInfo:
             # Does the zone expired?
             if (ZONE_EXPIRED != self._get_zone_state(zone_name_class) and 
                 self._zone_is_expired(zone_name_class)):
+                log_msg("Zone (%s, %s) is expired." % zone_name_class)
                 self._set_zone_state(zone_name_class, ZONE_EXPIRED)
 
             zone_state = self._get_zone_state(zone_name_class)
@@ -247,7 +280,7 @@ class ZoneMgrRefreshInfo:
                 (not self._get_zone_notifier_master(zone_name_class))):
                 continue
 
-            # If hasn't received refresh response within refresh timeout, skip the zone
+            # If hasn't received refresh response but are within refresh timeout, skip the zone
             if (ZONE_REFRESHING == zone_state and
                 (self._get_zone_refresh_timeout(zone_name_class) > self._get_current_time())):
                 continue
@@ -267,6 +300,7 @@ class ZoneMgrRefreshInfo:
     
     def _do_refresh(self, zone_name_class):
         """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) 
         notify_master = self._get_zone_notifier_master(zone_name_class)
@@ -310,7 +344,6 @@ class ZoneMgrRefreshInfo:
                     self._do_refresh(zone_need_refresh)
                     continue
 
-
             """ Wait for the socket notification for a maximum time of timeout 
             in seconds (as float)."""
             try:
@@ -327,32 +360,35 @@ class ZoneMgrRefreshInfo:
                     raise ZonemgrException("[b10-zonemgr] Error with select(): %s\n" % err)
                     break
 
-class Zonemgr:
 
-    def __init__(self, verbose = False):
+class Zonemgr:
+    """Zone manager class."""
+    def __init__(self):
         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_info = ZoneMgrRefreshInfo(self._cc, self._db_file, self._slave_socket)
+        self._zone_refresh= ZonemgrRefresh(self._cc, self._db_file, self._slave_socket)
         self._start_zone_refresh_timer()
 
         self._lock = threading.Lock()
         self._shutdown_event = threading.Event()
-        self._verbose = verbose
 
     def _start_zone_refresh_timer(self):
         """Start a new thread to keep track of zone timers"""
-        listener = threading.Thread(target = self._zone_refresh_info.run_timer, args = ())
+        listener = threading.Thread(target = self._zone_refresh.run_timer, args = ())
         listener.setDaemon(True)
         listener.start()
 
     def _setup_session(self):
+        """Setup two sessions for zonemgr, one(self._module_cc) is used for receiving 
+        commands and config data sent from other modules, another one (self._cc)
+        is used to send commands to proper modules."""
         self._cc = isc.cc.Session()
         self._module_cc = isc.config.ModuleCCSession(SPECFILE_LOCATION,
                                                   self.config_handler,
                                                   self.command_handler)
-        self._module_cc.add_remote_config(AUTH_SPECFILE_LOCATION);
+        self._module_cc.add_remote_config(AUTH_SPECFILE_LOCATION)
         self._config_data = self._module_cc.get_full_config()
         self._module_cc.start()
 
@@ -366,7 +402,9 @@ class Zonemgr:
         return db_file
 
     def shutdown(self):
-
+        """Shutdown the zonemgr process. the thread which is keeping track of zone
+        timers should be terminated.
+        """ 
         self._slave_socket.close()
         self._master_socket.close()
 
@@ -378,6 +416,7 @@ class Zonemgr:
             th.join()
 
     def config_handler(self, new_config):
+        """Update config data."""
         answer = create_answer(0)
         for key in new_config:
             if key not in self._config_data:
@@ -393,7 +432,7 @@ class Zonemgr:
 
         zone_class = args.get("zone_class")
         if not zone_class:
-                raise ZonemgrException("zone class should be provided")
+            raise ZonemgrException("zone class should be provided")
 
         if (command != ZONE_NOTIFY_COMMAND):
             return (zone_name, zone_class)
@@ -406,27 +445,33 @@ class Zonemgr:
 
 
     def command_handler(self, command, args):
+        """Handle command receivd from command channel.
+        ZONE_NOTIFY_COMMAND is issued by Auth process; ZONE_XFRIN_SUCCESS_COMMAND 
+        and ZONE_XFRIN_FAILED_COMMAND are issued by Xfrin process; shutdown is issued
+        by a user or Boss process. """
         answer = create_answer(0)
         if command == ZONE_NOTIFY_COMMAND:
             """ Handle Auth notify command"""
+            # master is the source sender of the notify message.
             zone_name_class, master = self._parse_cmd_params(args, command)
+            log_msg("Received notify command for zone (%s, %s)." % zone_name_class)
             with self._lock:
-                self._zone_refresh_info.zone_handle_notify(zone_name_class, master)
+                self._zone_refresh.zone_handle_notify(zone_name_class, master)
             # Send notification to zonemgr timer thread
             self._master_socket.send(b" ")
 
         elif command == ZONE_XFRIN_SUCCESS_COMMAND:
-            """ Handle xfrin succes command"""
+            """ Handle xfrin success command"""
             zone_name_class = self._parse_cmd_params(args, command)
             with self._lock:
-                self._zone_refresh_info.zone_refresh_success(zone_name_class)
+                self._zone_refresh.zone_refresh_success(zone_name_class)
             self._master_socket.send(b" ")
 
         elif command == ZONE_XFRIN_FAILED_COMMAND:
             """ Handle xfrin fail command"""
             zone_name_class = self._parse_cmd_params(args, command)
             with self._lock:
-                self._zone_refresh_info.zone_refresh_fail(zone_name_class)
+                self._zone_refresh.zone_refresh_fail(zone_name_class)
             self._master_socket.send(b" ")
 
         elif command == "shutdown":