BIND 10 trac2989, updated. d2fb636f00a32c1544b460d1f3aed3d8e9f22cf1 [2989] Pass configuration to the notification thread
BIND 10 source code commits
bind10-changes at lists.isc.org
Wed Jul 24 08:53:34 UTC 2013
The branch, trac2989 has been updated
via d2fb636f00a32c1544b460d1f3aed3d8e9f22cf1 (commit)
via 5e25b5ec96692182a34f055ee8843587438fb9a9 (commit)
from 17a2fab7ec8ccc6886e887f9d9bff9e51fe080a9 (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 d2fb636f00a32c1544b460d1f3aed3d8e9f22cf1
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Wed Jul 24 10:52:51 2013 +0200
[2989] Pass configuration to the notification thread
commit 5e25b5ec96692182a34f055ee8843587438fb9a9
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Wed Jul 24 09:22:05 2013 +0200
[2989] Rename variable
We'll be sending different things over that wire, so have a more
descriptive constant variable name.
-----------------------------------------------------------------------
Summary of changes:
src/lib/python/isc/notify/notify_out.py | 56 ++++++++++++++++++--
src/lib/python/isc/notify/tests/notify_out_test.py | 35 +++++++++++-
2 files changed, 85 insertions(+), 6 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/python/isc/notify/notify_out.py b/src/lib/python/isc/notify/notify_out.py
index 39c6708..0394e80 100644
--- a/src/lib/python/isc/notify/notify_out.py
+++ b/src/lib/python/isc/notify/notify_out.py
@@ -53,7 +53,8 @@ _BAD_OPCODE = 3
_BAD_QR = 4
_BAD_REPLY_PACKET = 5
-SOCK_DATA = b's'
+SHUTDOWN_DATA = b's'
+CONFIG_DATA = b'c'
# borrowed from xfrin.py @ #1298. We should eventually unify it.
def format_zone_str(zone_name, zone_class):
@@ -144,6 +145,9 @@ class NotifyOut:
# If there are no notifying zones, clear the event bit and wait.
self._nonblock_event = threading.Event()
self._counters = Counters()
+ # For passing the datasource configuration to the right thread
+ self._datasource_config = None
+ self._datasource_config_mutex = threading.Lock()
def _init_notify_out(self, datasrc_file):
'''Get all the zones name and its notify target's address.
@@ -258,7 +262,7 @@ class NotifyOut:
if not self._nonblock_event.isSet():
# set self._nonblock_event to stop waiting for new notifying zones.
self._nonblock_event.set()
- self._write_sock.send(SOCK_DATA) # make self._read_sock be readable.
+ self._write_sock.send(SHUTDOWN_DATA) # make self._read_sock be readable.
# Wait for it
self._thread.join()
@@ -270,6 +274,24 @@ class NotifyOut:
self._read_sock = None
self._thread = None
+ def datasource_update(self, config):
+ """
+ Update the configuration of the data sources used by the notification
+ thread.
+
+ This only posts the update to the thread. The method may return before
+ the update is applied.
+ """
+ # Place the configuration there to be picked up.
+ with self._datasource_config_mutex:
+ self._datasource_config = config
+
+ if not self._nonblock_event.isSet():
+ # set self._nonblock_event to stop waiting for new notifying zones.
+ self._nonblock_event.set()
+ # Send a wake-up signal
+ self._write_sock.send(CONFIG_DATA)
+
def _get_rdata_data(self, rr):
return rr[7].strip()
@@ -390,6 +412,9 @@ class NotifyOut:
# Currently, there is no notifying zones, waiting for zones to send notify
if block_timeout is None:
+ # FIXME: This use does indeed look like a race contition. If shutdown
+ # or reconfiguration of data source is called before the clear(), we'll
+ # block for a long time on the wait()
self._nonblock_event.clear()
self._nonblock_event.wait()
# has new notifying zone, check immediately
@@ -404,8 +429,11 @@ class NotifyOut:
if self._read_sock in r_fds: # user has called shutdown()
try:
# Noone should write anything else than shutdown
- assert self._read_sock.recv(len(SOCK_DATA)) == SOCK_DATA
- return {}, {}
+ data = self._read_sock.recv(len(SHUTDOWN_DATA))
+ if data == SHUTDOWN_DATA:
+ return {}, {}
+ else:
+ assert data == CONFIG_DATA
except socket.error as e: # Workaround around rare linux bug
if e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK:
raise
@@ -420,6 +448,26 @@ class NotifyOut:
return replied_zones, not_replied_zones
+ def _reconfigure_datasrc(self, new_config):
+ """
+ Rebuild the data source lists from the new configuration.
+ """
+ assert 0
+
+ def _check_datasrc(self):
+ """
+ Check (in thread-safe) manner if there's new configuration
+ for the data sources and update it if there is.
+ """
+ # First extract the config, inside a mutex
+ config = None
+ with self._datasource_config_mutex:
+ config = self._datasource_config
+ self._datasource_config = None
+ # Do the reconfiguration
+ if config is not None:
+ self._reconfigure_datasrc(config)
+
def _zone_notify_handler(self, zone_notify_info, event_type):
"""Notify handler for one zone.
diff --git a/src/lib/python/isc/notify/tests/notify_out_test.py b/src/lib/python/isc/notify/tests/notify_out_test.py
index 7097f01..e14c82e 100644
--- a/src/lib/python/isc/notify/tests/notify_out_test.py
+++ b/src/lib/python/isc/notify/tests/notify_out_test.py
@@ -19,7 +19,7 @@ import os
import tempfile
import time
import socket
-from isc.notify import notify_out, SOCK_DATA
+from isc.notify import notify_out, SHUTDOWN_DATA
import isc.log
from isc.dns import *
@@ -241,7 +241,7 @@ class TestNotifyOut(unittest.TestCase):
if self._notify._write_sock is not None:
self._notify._write_sock.close()
self._notify._read_sock, self._notify._write_sock = socket.socketpair()
- self._notify._write_sock.send(SOCK_DATA)
+ self._notify._write_sock.send(SHUTDOWN_DATA)
replied_zones, timeout_zones = self._notify._wait_for_notify_reply()
self.assertEqual(0, len(replied_zones))
self.assertEqual(0, len(timeout_zones))
@@ -510,6 +510,37 @@ class TestNotifyOut(unittest.TestCase):
self.assertIn(1, valid_fds)
self.assertIn(2, valid_fds)
+ def test_send_config(self):
+ """
+ Test sending the configuration data to the thread.
+
+ The thread is not actually running in this test.
+ """
+ self._notify.datasource_update('Just some data')
+ self.assertEqual('Just some data', self._notify._datasource_config)
+ # We disable the clearing of the event, as we are unable to synchronize
+ # that properly without the second thread.
+ self._notify._nonblock_event.clear = lambda: None
+ # This should terminate right away.
+ rep, nrep = self._notify._wait_for_notify_reply()
+ self.assertEqual({}, rep)
+ self.assertEqual({}, nrep)
+ # Check that checking for the data uses that config
+ self.__param = None
+ self.__called = False
+ def reconfigure(config):
+ self.__param = config
+ self.__called = True
+ self._notify._reconfigure_datasrc = reconfigure
+ self._notify._check_datasrc()
+ self.assertEqual('Just some data', self.__param)
+ self.assertTrue(self.__called)
+ self.assertEqual(None, self._notify._datasource_config)
+ # Calling again does nothing
+ self.__called = False
+ self._notify._check_datasrc()
+ self.assertFalse(self.__called)
+
def test_shutdown(self):
thread = self._notify.dispatcher()
self.assertTrue(thread.is_alive())
More information about the bind10-changes
mailing list