From 4814fed13a5249c38bfc2c69abc5384113356120 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Mon, 23 Jul 2012 10:24:27 +0200 Subject: [PATCH] Refactored the Component class. --- base/application.cpp | 121 +------------------------- base/application.h | 9 -- base/component.cpp | 162 ++++++++++++++++++++++++++++++++++- base/component.h | 28 +++++- icinga/icingaapplication.cpp | 16 +--- 5 files changed, 187 insertions(+), 149 deletions(-) diff --git a/base/application.cpp b/base/application.cpp index e521460ad..7cc670cc7 100644 --- a/base/application.cpp +++ b/base/application.cpp @@ -60,14 +60,6 @@ Application::~Application(void) { m_ShuttingDown = true; - /* stop all components */ - Component::Ptr component; - BOOST_FOREACH(tie(tuples::ignore, component), m_Components) { - component->Stop(); - } - - m_Components.clear(); - #ifdef _WIN32 WSACleanup(); #endif /* _WIN32 */ @@ -101,6 +93,8 @@ void Application::RunEventLoop(void) Event::ProcessEvents(boost::get_system_time() + boost::posix_time::seconds(sleep)); } + + Component::UnloadAll(); } /** @@ -112,103 +106,6 @@ void Application::Shutdown(void) m_ShuttingDown = true; } -/** - * Loads a component from a shared library. - * - * @param path The path of the component library. - * @param componentConfig The configuration for the component. - * @returns The component. - */ -Component::Ptr Application::LoadComponent(const string& path, - const ConfigObject::Ptr& componentConfig) -{ - Component::Ptr component; - Component *(*pCreateComponent)(); - - assert(Application::IsMainThread()); - - Logger::Write(LogInformation, "base", "Loading component '" + path + "'"); - -#ifdef _WIN32 - HMODULE hModule = LoadLibrary(path.c_str()); - - if (hModule == NULL) - throw_exception(Win32Exception("LoadLibrary('" + path + "') failed", GetLastError())); -#else /* _WIN32 */ - lt_dlhandle hModule = lt_dlopen(path.c_str()); - - if (hModule == NULL) { - throw_exception(runtime_error("Could not load module '" + path + "': " + lt_dlerror())); - } -#endif /* _WIN32 */ - -#ifdef _WIN32 - pCreateComponent = (CreateComponentFunction)GetProcAddress(hModule, - "CreateComponent"); -#else /* _WIN32 */ -# ifdef __GNUC__ - /* suppress compiler warning for void * cast */ - __extension__ -# endif - pCreateComponent = (CreateComponentFunction)lt_dlsym(hModule, - "CreateComponent"); -#endif /* _WIN32 */ - - if (pCreateComponent == NULL) - throw_exception(runtime_error("Loadable module does not contain " - "CreateComponent function")); - - component = Component::Ptr(pCreateComponent()); - component->SetConfig(componentConfig); - RegisterComponent(component); - return component; -} - -/** - * Registers a component object and starts it. - * - * @param component The component. - */ -void Application::RegisterComponent(const Component::Ptr& component) -{ - m_Components[component->GetName()] = component; - - component->Start(); -} - -/** - * Unregisters a component object and stops it. - * - * @param component The component. - */ -void Application::UnregisterComponent(const Component::Ptr& component) -{ - string name = component->GetName(); - - Logger::Write(LogInformation, "base", "Unloading component '" + name + "'"); - map::iterator i = m_Components.find(name); - if (i != m_Components.end()) - m_Components.erase(i); - - component->Stop(); -} - -/** - * Finds a loaded component by name. - * - * @param name The name of the component. - * @returns The component or a null pointer if the component could not be found. - */ -Component::Ptr Application::GetComponent(const string& name) const -{ - map::const_iterator i = m_Components.find(name); - - if (i == m_Components.end()) - return Component::Ptr(); - - return i->second; -} - /** * Retrieves the full path of the executable. * @@ -276,20 +173,6 @@ string Application::GetExePath(void) const return result; } -/** - * Adds a directory to the component search path. - * - * @param componentDirectory The directory. - */ -void Application::AddComponentSearchDir(const string& componentDirectory) -{ -#ifdef _WIN32 - SetDllDirectory(componentDirectory.c_str()); -#else /* _WIN32 */ - lt_dladdsearchdir(componentDirectory.c_str()); -#endif /* _WIN32 */ -} - /** * Retrieves the debugging mode of the application. * diff --git a/base/application.h b/base/application.h index 4f370606b..664879aa8 100644 --- a/base/application.h +++ b/base/application.h @@ -45,13 +45,6 @@ public: static void Shutdown(void); - shared_ptr LoadComponent(const string& path, - const ConfigObject::Ptr& componentConfig); - void RegisterComponent(const shared_ptr& component); - void UnregisterComponent(const shared_ptr& component); - shared_ptr GetComponent(const string& name) const; - void AddComponentSearchDir(const string& componentDirectory); - static bool IsDebugging(void); static bool IsMainThread(void); @@ -68,8 +61,6 @@ private: static bool m_ShuttingDown; /**< Whether the application is in the process of shutting down. */ - map< string, shared_ptr > m_Components; /**< Components that - were loaded by the application. */ vector m_Arguments; /**< Command-line arguments */ FILE *m_PidFile; /**< The PID file */ static bool m_Debugging; /**< Whether debugging is enabled. */ diff --git a/base/component.cpp b/base/component.cpp index dcea19ef7..d2ebd2877 100644 --- a/base/component.cpp +++ b/base/component.cpp @@ -21,14 +21,152 @@ using namespace icinga; +map Component::m_Components; + /** - * Sets the configuration for this component. + * Loads a component from a shared library. * - * @param componentConfig The configuration. + * @param name The name of the component. + * @param componentConfig The configuration for the component. */ -void Component::SetConfig(const ConfigObject::Ptr& componentConfig) +void Component::Load(const string& name, const ConfigObject::Ptr& config) { - m_Config = componentConfig; + assert(Application::IsMainThread()); + + string path; +#ifdef _WIN32 + path = name + ".dll"; +#else /* _WIN32 */ + path = name + ".la"; +#endif /* _WIN32 */ + + Logger::Write(LogInformation, "base", "Loading component '" + name + "' (using library '" + path + "')"); + +#ifdef _WIN32 + HMODULE hModule = LoadLibrary(path.c_str()); + + if (hModule == NULL) + throw_exception(Win32Exception("LoadLibrary('" + path + "') failed", GetLastError())); +#else /* _WIN32 */ + lt_dlhandle hModule = lt_dlopen(path.c_str()); + + if (hModule == NULL) { + throw_exception(runtime_error("Could not load module '" + path + "': " + lt_dlerror())); + } +#endif /* _WIN32 */ + + CreateComponentFunction pCreateComponent; + +#ifdef _WIN32 + pCreateComponent = (CreateComponentFunction)GetProcAddress(hModule, + "CreateComponent"); +#else /* _WIN32 */ +# ifdef __GNUC__ + /* suppress compiler warning for void * cast */ + __extension__ +# endif + pCreateComponent = (CreateComponentFunction)lt_dlsym(hModule, + "CreateComponent"); +#endif /* _WIN32 */ + + Component::Ptr component; + + try { + if (pCreateComponent == NULL) + throw_exception(runtime_error("Loadable module does not contain " + "CreateComponent function")); + + component = Component::Ptr(pCreateComponent()); + + if (!component) + throw_exception(runtime_error("CreateComponent function returned NULL.")); + } catch (...) { +#ifdef _WIN32 + FreeLibrary(hModule); +#else /* _WIN32 */ + lt_dlclose(hModule); +#endif /* _WIN32 */ + throw; + } + + component->m_Name = name; + component->m_Config = config; + component->m_ModuleHandle = hModule; + + try { + m_Components[name] = component; + component->Start(); + } catch (...) { + m_Components.erase(name); + throw; + } +} + +void Component::Unload(const string& componentName) +{ + map::iterator it; + + it = m_Components.find(componentName); + + if (it == m_Components.end()) + return; + + Logger::Write(LogInformation, "base", "Unloading component '" + componentName + "'"); + + Component::Ptr component = it->second; + component->Stop(); + + m_Components.erase(it); + + /** Unfortunatelly we can't safely unload the DLL/shared library + * here because there could still be objects that use the library. */ +} + +void Component::UnloadAll(void) +{ + Logger::Write(LogInformation, "base", "Unloading all components"); + + while (!m_Components.empty()) { + string name = m_Components.begin()->first; + Unload(name); + } +} + +/** + * Adds a directory to the component search path. + * + * @param componentDirectory The directory. + */ +void Component::AddSearchDir(const string& componentDirectory) +{ +#ifdef _WIN32 + SetDllDirectory(componentDirectory.c_str()); +#else /* _WIN32 */ + lt_dladdsearchdir(componentDirectory.c_str()); +#endif /* _WIN32 */ +} + +/** + * Constructor for the Component class. + */ +Component::Component(void) + : m_ModuleHandle(0) +{ } + +/** + * Destructor for the Component class. + */ +Component::~Component(void) +{ } + +/** + * Retrieves the name of the component. + * + * @returns Name of the component. + */ +string Component::GetName(void) const +{ + return m_Name; } /** @@ -40,3 +178,19 @@ ConfigObject::Ptr Component::GetConfig(void) const { return m_Config; } + +/** + * Starts the component. + */ +void Component::Start(void) +{ + /* Nothing to do in the default implementation. */ +} + +/** + * Stops the component. + */ +void Component::Stop(void) +{ + /* Nothing to do in the default implementation. */ +} diff --git a/base/component.h b/base/component.h index e879f390d..e39d9dab1 100644 --- a/base/component.h +++ b/base/component.h @@ -35,15 +35,35 @@ public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; - void SetConfig(const ConfigObject::Ptr& componentConfig); + Component(void); + virtual ~Component(void); + ConfigObject::Ptr GetConfig(void) const; - virtual string GetName(void) const = 0; - virtual void Start(void) = 0; - virtual void Stop(void) = 0; + virtual void Start(void); + virtual void Stop(void); + + string GetName(void) const; + + static void Load(const string& name, const ConfigObject::Ptr& config); + static void Unload(const Component::Ptr& component); + static void Unload(const string& componentName); + static void UnloadAll(void); + static Component::Ptr GetByName(const string& name); + static void AddSearchDir(const string& componentDirectory); private: + string m_Name; ConfigObject::Ptr m_Config; + +#ifdef _WIN32 + HMODULE m_ModuleHandle; +#else /* _WIN32 */ + lt_dlhandle m_ModuleHandle; +#endif /* _WIN32 */ + + static map m_Components; /**< Components that + were loaded by the application. */ }; typedef Component *(*CreateComponentFunction)(void); diff --git a/icinga/icingaapplication.cpp b/icinga/icingaapplication.cpp index 7ba9ca121..21d1132e0 100644 --- a/icinga/icingaapplication.cpp +++ b/icinga/icingaapplication.cpp @@ -133,7 +133,7 @@ int IcingaApplication::Main(const vector& args) } string componentDirectory = Utility::DirName(GetExePath()) + "/../lib/icinga2"; - AddComponentSearchDir(componentDirectory); + Component::AddSearchDir(componentDirectory); /* register handler for 'component' config objects */ static ConfigObject::Set::Ptr componentObjects = boost::make_shared(ConfigObject::GetAllObjects(), ConfigObject::MakeTypePredicate("component")); @@ -219,16 +219,7 @@ void IcingaApplication::NewComponentHandler(const ConfigObject::Ptr& object) if (!object->IsLocal()) throw_exception(runtime_error("'component' objects must be 'local'")); - string path; - if (!object->GetProperty("path", &path)) { -#ifdef _WIN32 - path = object->GetName() + ".dll"; -#else /* _WIN32 */ - path = object->GetName() + ".la"; -#endif /* _WIN32 */ - } - - LoadComponent(path, object); + Component::Load(object->GetName(), object); } void IcingaApplication::NewLogHandler(const ConfigObject::Ptr& object) @@ -290,8 +281,7 @@ IcingaApplication::Ptr IcingaApplication::GetInstance(void) void IcingaApplication::DeletedComponentHandler(const ConfigObject::Ptr& object) { - Component::Ptr component = GetComponent(object->GetName()); - UnregisterComponent(component); + Component::Unload(object->GetName()); } string IcingaApplication::GetCertificateFile(void) const