|
@@ -29,7 +29,7 @@ from isc.log_messages.memmgr_messages import *
|
|
|
from isc.server_common.bind10_server import BIND10Server, BIND10ServerFatal
|
|
|
from isc.server_common.datasrc_clients_mgr \
|
|
|
import DataSrcClientsMgr, ConfigError
|
|
|
-from isc.memmgr.datasrc_info import DataSrcInfo
|
|
|
+from isc.memmgr.datasrc_info import DataSrcInfo, SegmentInfo
|
|
|
from isc.memmgr.builder import MemorySegmentBuilder
|
|
|
import isc.util.process
|
|
|
|
|
@@ -124,18 +124,51 @@ class Memmgr(BIND10Server):
|
|
|
# All copy, switch to the new configuration.
|
|
|
self._config_params = new_config_params
|
|
|
|
|
|
- def __notify_from_builder(self):
|
|
|
- # Nothing is implemented here for now. This method should have
|
|
|
- # code to handle responses from the builder in
|
|
|
- # self._builder_response_queue[]. Access must be synchronized
|
|
|
- # using self._builder_lock.
|
|
|
- pass
|
|
|
+ def _cmd_to_builder(self, cmd):
|
|
|
+ """
|
|
|
+ Send a command to the builder, with proper synchronization.
|
|
|
+ """
|
|
|
+ assert isinstance(cmd, tuple)
|
|
|
+ with self._builder_cv:
|
|
|
+ self._builder_command_queue.append(cmd)
|
|
|
+ self._builder_cv.notify_all()
|
|
|
+
|
|
|
+ def _notify_from_builder(self):
|
|
|
+ """
|
|
|
+ Read the notifications from the builder thread.
|
|
|
+ """
|
|
|
+ self._master_sock.recv(1) # Clear the wake-up data
|
|
|
+ notifications = None
|
|
|
+ with self._builder_lock:
|
|
|
+ # Copy the notifications out and clear them from the
|
|
|
+ # original list. We may not assign [] to
|
|
|
+ # self._builder_response_queue to clear it, because there's
|
|
|
+ # another reference to it from the other thread and it would
|
|
|
+ # not keep the original list.
|
|
|
+ notifications = self._builder_response_queue[:]
|
|
|
+ del self._builder_response_queue[:]
|
|
|
+ for notification in notifications:
|
|
|
+ notif_name = notification[0]
|
|
|
+ if notif_name == 'load-completed':
|
|
|
+ (_, dsrc_info, rrclass, dsrc_name) = notification
|
|
|
+ sgmt_info = dsrc_info.segment_info_map[(rrclass, dsrc_name)]
|
|
|
+ cmd = sgmt_info.complete_update()
|
|
|
+ # It may return another load command on the same data source.
|
|
|
+ # If it is so, we execute it too, before we start
|
|
|
+ # synchronizing with the readers.
|
|
|
+ if cmd is not None:
|
|
|
+ self._cmd_to_builder(cmd)
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ # TODO: Send to the readers, #2858
|
|
|
+ else:
|
|
|
+ raise ValueError('Unknown notification name: ' + notif_name)
|
|
|
|
|
|
def __create_builder_thread(self):
|
|
|
# We get responses from the builder thread on this socket pair.
|
|
|
(self._master_sock, self._builder_sock) = \
|
|
|
socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
|
- self.watch_fileno(self._master_sock, rcallback=self.__notify_from_builder)
|
|
|
+ self.watch_fileno(self._master_sock, rcallback=self._notify_from_builder)
|
|
|
|
|
|
# See the documentation for MemorySegmentBuilder on how the
|
|
|
# following are used.
|
|
@@ -161,9 +194,7 @@ class Memmgr(BIND10Server):
|
|
|
|
|
|
# This makes the MemorySegmentBuilder exit its main loop. It
|
|
|
# should make the builder thread joinable.
|
|
|
- with self._builder_cv:
|
|
|
- self._builder_command_queue.append(('shutdown',))
|
|
|
- self._builder_cv.notify_all()
|
|
|
+ self._cmd_to_builder(('shutdown',))
|
|
|
|
|
|
self._builder_thread.join()
|
|
|
|
|
@@ -202,13 +233,25 @@ class Memmgr(BIND10Server):
|
|
|
genid, clients_map = self._datasrc_clients_mgr.get_clients_map()
|
|
|
datasrc_info = DataSrcInfo(genid, clients_map, self._config_params)
|
|
|
self._datasrc_info_list.append(datasrc_info)
|
|
|
+ self._init_segments(datasrc_info)
|
|
|
|
|
|
# Full datasrc reconfig will be rare, so would be worth logging
|
|
|
# at the info level.
|
|
|
logger.info(MEMMGR_DATASRC_RECONFIGURED, genid)
|
|
|
+
|
|
|
except isc.server_common.datasrc_clients_mgr.ConfigError as ex:
|
|
|
logger.error(MEMMGR_DATASRC_CONFIG_ERROR, ex)
|
|
|
|
|
|
+ def _init_segments(self, datasrc_info):
|
|
|
+ for key, sgmt_info in datasrc_info.segment_info_map.items():
|
|
|
+ rrclass, dsrc_name = key
|
|
|
+ cmd = ('load', None, datasrc_info, rrclass, dsrc_name)
|
|
|
+ sgmt_info.add_event(cmd)
|
|
|
+ send_cmd = sgmt_info.start_update()
|
|
|
+ assert cmd == send_cmd and sgmt_info.get_state() == \
|
|
|
+ SegmentInfo.UPDATING
|
|
|
+ self._cmd_to_builder(cmd)
|
|
|
+
|
|
|
if '__main__' == __name__:
|
|
|
mgr = Memmgr()
|
|
|
sys.exit(mgr.run(MODULE_NAME))
|