From: Gunnar Beutner Date: Sat, 31 Mar 2012 13:18:09 +0000 (+0200) Subject: Added support for configuration and loadable components. X-Git-Tag: v0.0.1~687 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5273e09d24a824079325795457d3101c606b0aaa;p=icinga2 Added support for configuration and loadable components. --- diff --git a/base/application.cpp b/base/application.cpp index efd6badf4..fa96db001 100644 --- a/base/application.cpp +++ b/base/application.cpp @@ -12,6 +12,7 @@ Application::Application(void) #endif m_ShuttingDown = false; + m_ConfigHive = new_object(); } Application::~Application(void) @@ -22,6 +23,10 @@ Application::~Application(void) #ifdef _WIN32 WSACleanup(); #endif + + for (map::iterator i = m_Components.begin(); i != m_Components.end(); i++) { + i->second->Stop(); + } } void Application::RunEventLoop(void) @@ -156,3 +161,62 @@ void Application::Shutdown(void) { m_ShuttingDown = true; } + +ConfigHive::RefType Application::GetConfigHive(void) +{ + return m_ConfigHive; +} + +Component::RefType Application::LoadComponent(string name) +{ + Component::RefType component; + Component *(*pCreateComponent)(); + + ConfigObject::RefType componentConfig = m_ConfigHive->GetObject("component", name); + + if (componentConfig.get() == NULL) { + componentConfig = new_object(); + componentConfig->SetName(name); + componentConfig->SetType("component"); + m_ConfigHive->AddObject(componentConfig); + } + + string path = componentConfig->GetProperty("path", name); + +#ifdef _WIN32 + HMODULE hModule = LoadLibrary(path.c_str()); + + if (hModule == INVALID_HANDLE_VALUE) + throw exception(/*"Could not load module"*/); + + pCreateComponent = (Component *(*)())GetProcAddress(hModule, "CreateComponent"); + + if (pCreateComponent == NULL) + throw exception(/*"Module does not contain CreateComponent function"*/); + +#else /* _WIN32 */ + // TODO: implement +#endif /* _WIN32 */ + + component = Component::RefType(pCreateComponent()); + component->SetApplication(static_pointer_cast(shared_from_this())); + m_Components[component->GetName()] = component; + + component->Start(componentConfig); + + return component; +} + +void Application::UnloadComponent(string name) +{ + map::iterator ci = m_Components.find(name); + + if (ci == m_Components.end()) + return; + + Component::RefType component = ci->second; + component->Stop(); + m_Components.erase(ci); + + // TODO: unload DLL +} diff --git a/base/application.h b/base/application.h index d665319de..110f5dd08 100644 --- a/base/application.h +++ b/base/application.h @@ -1,14 +1,21 @@ #ifndef I2_APPLICATION_H #define I2_APPLICATION_H +#include + namespace icinga { using std::vector; +using std::map; using std::string; +class Component; + class Application : public Object { private: bool m_ShuttingDown; + ConfigHive::RefType m_ConfigHive; + map< string, shared_ptr > m_Components; public: typedef shared_ptr RefType; @@ -24,6 +31,12 @@ public: void RunEventLoop(void); bool Daemonize(void); void Shutdown(void); + + ConfigHive::RefType GetConfigHive(void); + + shared_ptr LoadComponent(string name); + void UnloadComponent(string name); + shared_ptr GetComponent(string name); }; template diff --git a/base/base.vcxproj b/base/base.vcxproj index a22f34a74..e78a762b6 100644 --- a/base/base.vcxproj +++ b/base/base.vcxproj @@ -12,17 +12,27 @@ + + + + + + + + + + @@ -33,10 +43,14 @@ + + + + {9C92DA90-FD53-43A9-A244-90F2E8AF9677} Win32Proj @@ -46,12 +60,12 @@ StaticLibrary true - Unicode + MultiByte false true - Unicode + MultiByte StaticLibrary diff --git a/base/component.cpp b/base/component.cpp new file mode 100644 index 000000000..d18d9a26a --- /dev/null +++ b/base/component.cpp @@ -0,0 +1,13 @@ +#include "i2-base.h" + +using namespace icinga; + +void Component::SetApplication(Application::WeakRefType application) +{ + m_Application = application; +} + +Application::RefType Component::GetApplication(void) +{ + return m_Application.lock(); +} diff --git a/base/component.h b/base/component.h new file mode 100644 index 000000000..9b979e997 --- /dev/null +++ b/base/component.h @@ -0,0 +1,32 @@ +#ifndef I2_COMPONENT_H +#define I2_COMPONENT_H + +namespace icinga +{ + +class Component : public Object +{ +private: + Application::WeakRefType m_Application; + +public: + typedef shared_ptr RefType; + typedef weak_ptr WeakRefType; + + void SetApplication(Application::WeakRefType application); + Application::RefType GetApplication(void); + + virtual string GetName(void) = 0; + virtual void Start(ConfigObject::RefType componentConfig) = 0; + virtual void Stop(void) = 0; +}; + +#define EXPORT_COMPONENT(klass) \ + extern "C" I2_EXPORT icinga::Component *CreateComponent(void) \ + { \ + return new klass(); \ + } + +} + +#endif /* I2_COMPONENT_H */ diff --git a/base/confighive.cpp b/base/confighive.cpp new file mode 100644 index 000000000..7c454a1f1 --- /dev/null +++ b/base/confighive.cpp @@ -0,0 +1,55 @@ +#include "i2-base.h" + +using namespace icinga; + +void ConfigHive::AddObject(ConfigObject::RefType object) +{ + string type = object->GetType(); + TypeIterator ti = Objects.find(type); + + if (ti == Objects.end()) { + Objects[type] = map(); + ti = Objects.find(type); + } + + object->SetHive(static_pointer_cast(shared_from_this())); + + string name = object->GetName(); + ti->second[name] = object; + + ConfigHiveEventArgs::RefType ea = new_object(); + ea->Source = shared_from_this(); + ea->ConfigObject = object; + OnObjectCreated(ea); +} + +void ConfigHive::RemoveObject(ConfigObject::RefType object) +{ + string type = object->GetType(); + TypeIterator ti = Objects.find(type); + + if (ti == Objects.end()) + return; + + ti->second.erase(object->GetName()); + + ConfigHiveEventArgs::RefType ea = new_object(); + ea->Source = shared_from_this(); + ea->ConfigObject = object; + OnObjectRemoved(ea); +} + +ConfigObject::RefType ConfigHive::GetObject(const string& type, const string& name) +{ + ConfigHive::TypeIterator ti = Objects.find(type); + + if (ti == Objects.end()) + return ConfigObject::RefType(); + + ConfigHive::ObjectIterator oi = ti->second.find(name); + + if (oi == ti->second.end()) + return ConfigObject::RefType(); + + return oi->second; +} diff --git a/base/confighive.h b/base/confighive.h new file mode 100644 index 000000000..5286077e9 --- /dev/null +++ b/base/confighive.h @@ -0,0 +1,42 @@ +#ifndef I2_CONFIGHIVE_H +#define I2_CONFIGHIVE_H + +#include + +namespace icinga +{ + +using std::map; + +struct ConfigHiveEventArgs : public EventArgs +{ + typedef shared_ptr RefType; + typedef weak_ptr WeakRefType; + + ConfigObject::RefType ConfigObject; + string Property; + string OldValue; +}; + +class ConfigHive : public Object +{ +public: + typedef shared_ptr RefType; + typedef weak_ptr WeakRefType; + + typedef map< string, map >::iterator TypeIterator; + typedef map::iterator ObjectIterator; + map< string, map > Objects; + + void AddObject(ConfigObject::RefType object); + void RemoveObject(ConfigObject::RefType object); + ConfigObject::RefType GetObject(const string& type, const string& name = string()); + + event OnObjectCreated; + event OnObjectRemoved; + event OnPropertyChanged; +}; + +} + +#endif /* I2_CONFIGHIVE_H */ diff --git a/base/configobject.cpp b/base/configobject.cpp new file mode 100644 index 000000000..94834f0e1 --- /dev/null +++ b/base/configobject.cpp @@ -0,0 +1,74 @@ +#include "i2-base.h" + +using namespace icinga; + +void ConfigObject::SetHive(const ConfigHive::WeakRefType& hive) +{ + m_Hive = hive; +} + +ConfigHive::WeakRefType ConfigObject::GetHive(void) const +{ + return m_Hive; +} + +void ConfigObject::SetName(const string& name) +{ + m_Name = name; +} + +string ConfigObject::GetName(void) const +{ + return m_Name; +} + +void ConfigObject::SetType(const string& type) +{ + m_Type = type; +} + +string ConfigObject::GetType(void) const +{ + return m_Type; +} + +void ConfigObject::SetProperty(const string& name, const string& value) +{ + string oldValue = GetProperty(name); + + Properties[name] = value; + + ConfigHive::RefType hive = m_Hive.lock(); + if (hive.get() != NULL) { + ConfigHiveEventArgs::RefType ea = new_object(); + ea->Source = hive; + ea->ConfigObject = static_pointer_cast(shared_from_this()); + ea->Property = name; + ea->OldValue = oldValue; + hive->OnPropertyChanged(ea); + } +} + +string ConfigObject::GetProperty(const string& name, const string& default) const +{ + map::const_iterator vi = Properties.find(name); + if (vi == Properties.end()) + return default; + return vi->second; +} + +int ConfigObject::GetPropertyInteger(const string& name, int default) const +{ + string value = GetProperty(name); + if (value == string()) + return default; + return strtol(value.c_str(), NULL, 10); +} + +double ConfigObject::GetPropertyDouble(const string& name, double default) const +{ + string value = GetProperty(name); + if (value == string()) + return default; + return strtod(value.c_str(), NULL); +} diff --git a/base/configobject.h b/base/configobject.h new file mode 100644 index 000000000..939af74d0 --- /dev/null +++ b/base/configobject.h @@ -0,0 +1,49 @@ +#ifndef I2_CONFIGOBJECT_H +#define I2_CONFIGOBJECT_H + +#include + +namespace icinga +{ + +using std::map; +using std::string; + +class ConfigHive; + +class ConfigObject : public Object +{ +private: + weak_ptr m_Hive; + + string m_Name; + string m_Type; + +public: + typedef shared_ptr RefType; + typedef weak_ptr WeakRefType; + + typedef map::iterator ParameterIterator; + map Properties; + + void SetHive(const weak_ptr& name); + weak_ptr GetHive(void) const; + + void SetName(const string& name); + string GetName(void) const; + + void SetType(const string& type); + string GetType(void) const; + + void SetProperty(const string& name, const string& value); + void SetPropertyInteger(const string& name, int value); + void SetPropertyDouble(const string& name, double value); + + string GetProperty(const string& name, const string& default = string()) const; + int GetPropertyInteger(const string& name, int default = 0) const; + double GetPropertyDouble(const string& name, double default = 0.0f) const; +}; + +} + +#endif /* I2_CONFIGOBJECT_H */ diff --git a/base/delegate.h b/base/delegate.h index 3d86c89fc..232291abb 100644 --- a/base/delegate.h +++ b/base/delegate.h @@ -14,7 +14,7 @@ int delegate_fwd(int (TObject::*function)(TArgs), weak_ptr wref, const { shared_ptr ref = wref.lock(); - if (ref == NULL) + if (ref.get() == NULL) return -1; return (ref.get()->*function)(args); diff --git a/base/i2-base.h b/base/i2-base.h index c0c302a6f..d26671604 100644 --- a/base/i2-base.h +++ b/base/i2-base.h @@ -46,6 +46,9 @@ #include "tcpsocket.h" #include "tcpclient.h" #include "tcpserver.h" +#include "configobject.h" +#include "confighive.h" #include "application.h" +#include "component.h" #endif /* I2_BASE_H */ \ No newline at end of file diff --git a/base/unix.h b/base/unix.h index 507e18a99..f9d9e88b0 100644 --- a/base/unix.h +++ b/base/unix.h @@ -25,4 +25,8 @@ inline void closesocket(int fd) #define ioctlsocket ioctl +/* default visibility takes care of exported symbols */ +#define I2_EXPORT +#define I2_IMPORT + #endif /* I2_UNIX_H */ \ No newline at end of file diff --git a/base/win32.h b/base/win32.h index 4554b1c68..a75c521a6 100644 --- a/base/win32.h +++ b/base/win32.h @@ -1,9 +1,13 @@ #ifndef I2_WIN32_H #define I2_WIN32_H +#define NOGDI #include #include typedef int socklen_t; +#define I2_EXPORT __declspec(dllexport) +#define I2_IMPORT __declspec(dllimport) + #endif /* I2_WIN32_H */ \ No newline at end of file