]> granicus.if.org Git - icinga2/commitdiff
Refactored the Component class.
authorGunnar Beutner <gunnar@beutner.name>
Mon, 23 Jul 2012 08:24:27 +0000 (10:24 +0200)
committerGunnar Beutner <gunnar@beutner.name>
Mon, 23 Jul 2012 08:24:27 +0000 (10:24 +0200)
base/application.cpp
base/application.h
base/component.cpp
base/component.h
icinga/icingaapplication.cpp

index e521460add7a5f5263b4306dbf2b3c8cc2b43e0e..7cc670cc72aa460e97295ab330a7ec411b6cbd0e 100644 (file)
@@ -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<string, Component::Ptr>::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<string, Component::Ptr>::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.
  *
index 4f370606b7853adf3df6b6981470efe49fbdfc3d..664879aa8c6ca7a05bb0dfccf1d1f76eea569499 100644 (file)
@@ -45,13 +45,6 @@ public:
 
        static void Shutdown(void);
 
-       shared_ptr<Component> LoadComponent(const string& path,
-           const ConfigObject::Ptr& componentConfig);
-       void RegisterComponent(const shared_ptr<Component>& component);
-       void UnregisterComponent(const shared_ptr<Component>& component);
-       shared_ptr<Component> 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<Component> > m_Components; /**< Components that
-                                       were loaded by the application. */
        vector<string> m_Arguments; /**< Command-line arguments */
        FILE *m_PidFile; /**< The PID file */
        static bool m_Debugging; /**< Whether debugging is enabled. */
index dcea19ef71a59b1fed5a0df76c740055457e2345..d2ebd2877202767b141c2916d65513a08c1c4294 100644 (file)
 
 using namespace icinga;
 
+map<string, Component::Ptr> Component::m_Components;
+
+/**
+ * Loads a component from a shared library.
+ *
+ * @param name The name of the component.
+ * @param componentConfig The configuration for the component.
+ */
+void Component::Load(const string& name, const ConfigObject::Ptr& config)
+{
+       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<string, Component::Ptr>::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);
+       }
+}
+
 /**
- * Sets the configuration for this component.
+ * Adds a directory to the component search path.
  *
- * @param componentConfig The configuration.
+ * @param componentDirectory The directory.
  */
-void Component::SetConfig(const ConfigObject::Ptr& componentConfig)
+void Component::AddSearchDir(const string& componentDirectory)
 {
-       m_Config = componentConfig;
+#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. */
+}
index e879f390d47af834cb50155f8aa2998b5209d33f..e39d9dab119ea8acc21b47cc5ade2598f6291139 100644 (file)
@@ -35,15 +35,35 @@ public:
        typedef shared_ptr<Component> Ptr;
        typedef weak_ptr<Component> 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<string, Component::Ptr> m_Components; /**< Components that
+                                       were loaded by the application. */
 };
 
 typedef Component *(*CreateComponentFunction)(void);
index 7ba9ca12104f9d8416ac5a7c7c8c350f43d1ab84..21d1132e0bd89dbb553e91fff8f91eec1bccbc21 100644 (file)
@@ -133,7 +133,7 @@ int IcingaApplication::Main(const vector<string>& 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::Set>(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