2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-30 21:45:37 +00:00

[2855] Add a basic builder thread that understands the shutdown command

This commit is contained in:
Mukund Sivaraman
2013-06-21 20:20:49 +05:30
parent 4afd4b896c
commit a4ff0d97db
4 changed files with 106 additions and 1 deletions

View File

@@ -19,6 +19,8 @@ import copy
import os
import sys
import signal
import socket
import threading
sys.path.append('@@PYTHONPATH@@')
import isc.log
@@ -28,6 +30,7 @@ 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.builder import MemorySegmentBuilder
import isc.util.process
MODULE_NAME = 'memmgr'
@@ -58,6 +61,10 @@ class Memmgr(BIND10Server):
# active configuration generations. Allow tests to inspec it.
self._datasrc_info_list = []
self._builder_setup = False
self._builder_command_queue = []
self._builder_response_queue = []
def _config_handler(self, new_config):
"""Configuration handler, called via BIND10Server.
@@ -117,6 +124,46 @@ 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 __create_builder_thread(self):
(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._builder_cv = threading.Condition()
self._builder_lock = threading.Lock()
self._builder = MemorySegmentBuilder(self._builder_sock,
self._builder_cv,
self._builder_lock,
self._builder_command_queue,
self._builder_response_queue)
self._builder_thread = threading.Thread(target=self._builder.run)
self._builder_thread.start()
self._builder_setup = True
def __shutdown_builder_thread(self):
if not self._builder_setup:
return
self._builder_setup = False
with self._builder_cv:
with self._builder_lock:
self._builder_command_queue.append('shutdown')
self._builder_cv.notify_all()
self._builder_thread.join()
self._master_sock.close()
self._builder_sock.close()
def _setup_module(self):
"""Module specific initialization for BIND10Server."""
try:
@@ -130,6 +177,12 @@ class Memmgr(BIND10Server):
logger.error(MEMMGR_NO_DATASRC_CONF, ex)
raise BIND10ServerFatal('failed to setup memmgr module')
self.__create_builder_thread()
def _shutdown_module(self):
"""Module specific finalization."""
self.__shutdown_builder_thread()
def _datasrc_config_handler(self, new_config, config_data):
"""Callback of data_sources configuration update.

View File

@@ -74,6 +74,10 @@ class TestMemmgr(unittest.TestCase):
self.__orig_isdir = os.path.isdir
def tearDown(self):
self.__mgr._shutdown_module()
self.assertEqual(len(self.__mgr._builder_command_queue), 0)
# Restore faked values
os.access = self.__orig_os_access
os.path.isdir = self.__orig_isdir

View File

@@ -1,6 +1,6 @@
SUBDIRS = . tests
python_PYTHON = __init__.py datasrc_info.py
python_PYTHON = __init__.py builder.py datasrc_info.py
pythondir = $(pyexecdir)/isc/memmgr

View File

@@ -0,0 +1,48 @@
# Copyright (C) 2013 Internet Systems Consortium.
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
class MemorySegmentBuilder:
"""The builder runs in a different thread in the memory manager. It
waits for commands from the memory manager, and then executes them
in the given order sequentially.
"""
def __init__(self, sock, cv, lock, command_queue, response_queue):
self._sock = sock
self._cv = cv
self._lock = lock
self._command_queue = command_queue
self._response_queue = response_queue
self._shutdown = False
def run(self):
with self._cv:
while not self._shutdown:
while len(self._command_queue) == 0:
self._cv.wait()
# move the queue content to a local queue
with self._lock:
local_command_queue = self._command_queue.copy()
self._command_queue.clear()
# run commands in the queue in the given order. For
# now, it only supports the "shutdown" command, which
# just exits the thread.
for command in local_command_queue:
if command == 'shutdown':
self._shutdown = True
break
raise Exception('Unknown command passed to ' +
'MemorySegmentBuilder: ' + command)