Merge pull request #737 from zacikpa/functions-fix
Fix races occuring when two threads expand variables at the same time
This commit is contained in:
commit
374697b09f
8 changed files with 50 additions and 47 deletions
|
|
@ -2,13 +2,13 @@
|
|||
import argparse
|
||||
import os
|
||||
import inspect
|
||||
from tuned.utils.plugin_loader import PluginLoader
|
||||
from tuned.utils.class_loader import ClassLoader
|
||||
from tuned.plugins.base import Plugin
|
||||
|
||||
|
||||
class DocLoader(PluginLoader):
|
||||
class PluginDocLoader(ClassLoader):
|
||||
def __init__(self):
|
||||
super(DocLoader, self).__init__()
|
||||
super(PluginDocLoader, self).__init__()
|
||||
|
||||
def _set_loader_parameters(self):
|
||||
self._namespace = "tuned.plugins"
|
||||
|
|
@ -23,7 +23,7 @@ args = parser.parse_args()
|
|||
with open(args.intro, "r") as intro_file:
|
||||
intro = intro_file.read()
|
||||
|
||||
all_plugins = sorted(DocLoader().load_all_plugins(), key=lambda x: x.__module__)
|
||||
all_plugins = sorted(PluginDocLoader().load_all_classes(), key=lambda x: x.__module__)
|
||||
|
||||
with open(args.out, "w") as out_file:
|
||||
out_file.write(intro)
|
||||
|
|
|
|||
|
|
@ -291,12 +291,12 @@ class Daemon(object):
|
|||
|
||||
def get_all_plugins(self):
|
||||
"""Return all accessible plugin classes"""
|
||||
return self._unit_manager.plugins_repository.load_all_plugins()
|
||||
return self._unit_manager.plugins_repository.load_all_classes()
|
||||
|
||||
def get_plugin_documentation(self, plugin_name):
|
||||
"""Return plugin class docstring"""
|
||||
try:
|
||||
plugin_class = self._unit_manager.plugins_repository.load_plugin(
|
||||
plugin_class = self._unit_manager.plugins_repository.load_class(
|
||||
plugin_name
|
||||
)
|
||||
except ImportError:
|
||||
|
|
@ -313,7 +313,7 @@ class Daemon(object):
|
|||
dictionary -- {parameter_name: hint}
|
||||
"""
|
||||
try:
|
||||
plugin_class = self._unit_manager.plugins_repository.load_plugin(
|
||||
plugin_class = self._unit_manager.plugins_repository.load_class(
|
||||
plugin_name
|
||||
)
|
||||
except ImportError:
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import tuned.logs
|
||||
import tuned.monitors
|
||||
from tuned.utils.plugin_loader import PluginLoader
|
||||
from tuned.utils.class_loader import ClassLoader
|
||||
|
||||
log = tuned.logs.get()
|
||||
|
||||
__all__ = ["Repository"]
|
||||
|
||||
class Repository(PluginLoader):
|
||||
class Repository(ClassLoader):
|
||||
|
||||
def __init__(self):
|
||||
super(Repository, self).__init__()
|
||||
|
|
@ -23,7 +23,7 @@ class Repository(PluginLoader):
|
|||
|
||||
def create(self, plugin_name, devices):
|
||||
log.debug("creating monitor %s" % plugin_name)
|
||||
monitor_cls = self.load_plugin(plugin_name)
|
||||
monitor_cls = self.load_class(plugin_name)
|
||||
monitor_instance = monitor_cls(devices)
|
||||
self._monitors.add(monitor_instance)
|
||||
return monitor_instance
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from tuned.utils.plugin_loader import PluginLoader
|
||||
from tuned.utils.class_loader import ClassLoader
|
||||
import tuned.plugins.base
|
||||
import tuned.logs
|
||||
|
||||
|
|
@ -6,7 +6,7 @@ log = tuned.logs.get()
|
|||
|
||||
__all__ = ["Repository"]
|
||||
|
||||
class Repository(PluginLoader):
|
||||
class Repository(ClassLoader):
|
||||
|
||||
def __init__(self, monitor_repository, storage_factory, hardware_inventory, device_matcher, device_matcher_udev, plugin_instance_factory, global_cfg, variables):
|
||||
super(Repository, self).__init__()
|
||||
|
|
@ -31,7 +31,7 @@ class Repository(PluginLoader):
|
|||
|
||||
def create(self, plugin_name):
|
||||
log.debug("creating plugin %s" % plugin_name)
|
||||
plugin_cls = self.load_plugin(plugin_name)
|
||||
plugin_cls = self.load_class(plugin_name)
|
||||
plugin_instance = plugin_cls(self._monitor_repository, self._storage_factory, self._hardware_inventory, self._device_matcher,\
|
||||
self._device_matcher_udev, self._plugin_instance_factory, self._global_cfg, self._variables)
|
||||
self._plugins.add(plugin_instance)
|
||||
|
|
|
|||
|
|
@ -1,23 +1,18 @@
|
|||
import os
|
||||
import re
|
||||
import glob
|
||||
from . import repository
|
||||
import tuned.logs
|
||||
import tuned.consts as consts
|
||||
from tuned.utils.commands import commands
|
||||
|
||||
log = tuned.logs.get()
|
||||
|
||||
cmd = commands()
|
||||
|
||||
class Functions():
|
||||
class Parser():
|
||||
"""
|
||||
Built-in functions
|
||||
Parser used for expanding strings containing functions.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._repository = repository.Repository()
|
||||
self._parse_init()
|
||||
def __init__(self, repository):
|
||||
self._repository = repository
|
||||
|
||||
def _parse_init(self, s = ""):
|
||||
self._cnt = 0
|
||||
|
|
@ -1,12 +1,16 @@
|
|||
from tuned.utils.plugin_loader import PluginLoader
|
||||
from . import base
|
||||
from tuned.utils.class_loader import ClassLoader
|
||||
from tuned.profiles.functions.parser import Parser
|
||||
from tuned.profiles.functions.base import Function
|
||||
import tuned.logs
|
||||
import tuned.consts as consts
|
||||
from tuned.utils.commands import commands
|
||||
|
||||
log = tuned.logs.get()
|
||||
|
||||
class Repository(PluginLoader):
|
||||
class Repository(ClassLoader):
|
||||
"""
|
||||
Repository of functions used within TuneD profiles.
|
||||
The functions are loaded lazily (when first used).
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(Repository, self).__init__()
|
||||
|
|
@ -19,16 +23,16 @@ class Repository(PluginLoader):
|
|||
def _set_loader_parameters(self):
|
||||
self._namespace = "tuned.profiles.functions"
|
||||
self._prefix = consts.FUNCTION_PREFIX
|
||||
self._interface = tuned.profiles.functions.base.Function
|
||||
self._interface = Function
|
||||
|
||||
def create(self, function_name):
|
||||
log.debug("creating function %s" % function_name)
|
||||
function_cls = self.load_plugin(function_name)
|
||||
function_cls = self.load_class(function_name)
|
||||
function_instance = function_cls()
|
||||
self._functions[function_name] = function_instance
|
||||
return function_instance
|
||||
|
||||
# loads function from plugin file and return it
|
||||
# load a function from its file and return it
|
||||
# if it is already loaded, just return it, it is not loaded again
|
||||
def load_func(self, function_name):
|
||||
if not function_name in self._functions:
|
||||
|
|
@ -41,3 +45,6 @@ class Repository(PluginLoader):
|
|||
for k, v in list(self._functions.items()):
|
||||
if v == function:
|
||||
del self._functions[k]
|
||||
|
||||
def expand(self, s):
|
||||
return Parser(self).expand(s)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import os
|
||||
import re
|
||||
import tuned.logs
|
||||
from .functions import functions as functions
|
||||
import tuned.consts as consts
|
||||
from tuned.profiles import functions
|
||||
from tuned.utils.commands import commands
|
||||
from tuned.utils.config_parser import ConfigParser, Error
|
||||
|
||||
|
|
@ -17,7 +17,7 @@ class Variables():
|
|||
self._cmd = commands()
|
||||
self._lookup_re = {}
|
||||
self._lookup_env = {}
|
||||
self._functions = functions.Functions()
|
||||
self._functions = functions.Repository()
|
||||
|
||||
def _add_env_prefix(self, s, prefix):
|
||||
if s.find(prefix) == 0:
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import tuned.logs
|
||||
import os
|
||||
|
||||
__all__ = ["PluginLoader"]
|
||||
__all__ = ["ClassLoader"]
|
||||
|
||||
log = tuned.logs.get()
|
||||
|
||||
class PluginLoader(object):
|
||||
class ClassLoader(object):
|
||||
__slots__ = ["_namespace", "_prefix", "_interface"]
|
||||
|
||||
def _set_loader_parameters(self):
|
||||
|
|
@ -16,7 +16,7 @@ class PluginLoader(object):
|
|||
raise NotImplementedError()
|
||||
|
||||
def __init__(self):
|
||||
super(PluginLoader, self).__init__()
|
||||
super(ClassLoader, self).__init__()
|
||||
|
||||
self._namespace = None
|
||||
self._prefix = None
|
||||
|
|
@ -26,9 +26,9 @@ class PluginLoader(object):
|
|||
assert type(self._prefix) is str
|
||||
assert type(self._interface) is type and issubclass(self._interface, object)
|
||||
|
||||
def load_plugin(self, plugin_name):
|
||||
assert type(plugin_name) is str
|
||||
module_name = "%s.%s%s" % (self._namespace, self._prefix, plugin_name)
|
||||
def load_class(self, class_name):
|
||||
assert type(class_name) is str
|
||||
module_name = "%s.%s%s" % (self._namespace, self._prefix, class_name)
|
||||
return self._get_class(module_name)
|
||||
|
||||
def _get_class(self, module_name):
|
||||
|
|
@ -45,22 +45,23 @@ class PluginLoader(object):
|
|||
if type(cls) is type and issubclass(cls, self._interface):
|
||||
return cls
|
||||
|
||||
raise ImportError("Cannot find the plugin class.")
|
||||
raise ImportError("Cannot find the class %s." % module_name)
|
||||
|
||||
def load_all_plugins(self):
|
||||
plugins_package = __import__(self._namespace)
|
||||
plugin_clss = []
|
||||
for module_name in os.listdir(plugins_package.plugins.__path__[0]):
|
||||
def load_all_classes(self):
|
||||
package = __import__(self._namespace)
|
||||
basename = self._namespace.split(".")[-1]
|
||||
classes = []
|
||||
for module_name in os.listdir(getattr(package, basename).__path__[0]):
|
||||
try:
|
||||
module_name = os.path.splitext(module_name)[0]
|
||||
if not module_name.startswith("plugin_"):
|
||||
if not module_name.startswith(self._prefix):
|
||||
continue
|
||||
plugin_class = self._get_class(
|
||||
next_class = self._get_class(
|
||||
"%s.%s" % (self._namespace, module_name)
|
||||
)
|
||||
if plugin_class not in plugin_clss:
|
||||
plugin_clss.append(plugin_class)
|
||||
if next_class not in classes:
|
||||
classes.append(next_class)
|
||||
except ImportError:
|
||||
pass
|
||||
return plugin_clss
|
||||
return classes
|
||||
|
||||
Loading…
Reference in a new issue