mirror of https://github.com/Icinga/icinga2.git
Refactored the Component class.
This commit is contained in:
parent
bcb1b23d9f
commit
4814fed13a
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -21,14 +21,152 @@
|
|||
|
||||
using namespace icinga;
|
||||
|
||||
map<string, Component::Ptr> 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<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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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. */
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue