From c3142ed5935a0ec71b82e15d75ddd8b1e9c7c0a8 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Wed, 4 Apr 2012 10:04:38 +0200 Subject: [PATCH] Refactored config handling to support observing individual config object types more easily. --- base/Makefile.am | 2 + base/base.vcxproj | 2 + base/configcollection.cpp | 62 ++++++++++++++++ base/configcollection.h | 37 ++++++++++ base/confighive.cpp | 64 +++++++---------- base/confighive.h | 26 +++---- base/configobject.cpp | 14 ++-- base/configobject.h | 13 +++- base/i2-base.h | 5 +- configfilecomponent/configfilecomponent.cpp | 4 +- configrpccomponent/configrpccomponent.cpp | 23 +++--- configrpccomponent/configrpccomponent.h | 6 +- icinga/icingaapplication.cpp | 78 ++++++++++++++++----- icinga/icingaapplication.h | 7 +- 14 files changed, 245 insertions(+), 98 deletions(-) create mode 100644 base/configcollection.cpp create mode 100644 base/configcollection.h diff --git a/base/Makefile.am b/base/Makefile.am index 3113fbc85..d49f67638 100644 --- a/base/Makefile.am +++ b/base/Makefile.am @@ -11,6 +11,8 @@ libbase_la_SOURCES = \ component.h \ condvar.cpp \ condvar.h \ + configcollection.cpp \ + configcollection.h \ confighive.cpp \ confighive.h \ configobject.cpp \ diff --git a/base/base.vcxproj b/base/base.vcxproj index 3cea6d1ee..5564b5393 100644 --- a/base/base.vcxproj +++ b/base/base.vcxproj @@ -14,6 +14,7 @@ + @@ -34,6 +35,7 @@ + diff --git a/base/configcollection.cpp b/base/configcollection.cpp new file mode 100644 index 000000000..585b09db6 --- /dev/null +++ b/base/configcollection.cpp @@ -0,0 +1,62 @@ +#include "i2-base.h" + +using namespace icinga; + +void ConfigCollection::SetHive(const ConfigHive::WeakPtr& hive) +{ + m_Hive = hive; +} + +ConfigHive::WeakPtr ConfigCollection::GetHive(void) const +{ + return m_Hive; +} + +void ConfigCollection::AddObject(const ConfigObject::Ptr& object) +{ + Objects[object->GetName()] = object; + + ConfigObjectEventArgs::Ptr ea = make_shared(); + ea->Source = object; + OnObjectCreated(ea); + + ConfigHive::Ptr hive = m_Hive.lock(); + if (hive) + hive->OnObjectCreated(ea); +} + +void ConfigCollection::RemoveObject(const ConfigObject::Ptr& object) +{ + ObjectIterator oi = Objects.find(object->GetName()); + + if (oi != Objects.end()) { + Objects.erase(oi); + + ConfigObjectEventArgs::Ptr ea = make_shared(); + ea->Source = object; + OnObjectRemoved(ea); + + ConfigHive::Ptr hive = m_Hive.lock(); + if (hive) + hive->OnObjectRemoved(ea); + } +} + +ConfigObject::Ptr ConfigCollection::GetObject(const string& name) +{ + ObjectIterator oi = Objects.find(name); + + if (oi == Objects.end()) + return ConfigObject::Ptr(); + + return oi->second; +} + +void ConfigCollection::ForEachObject(function callback) +{ + for (ObjectIterator oi = Objects.begin(); oi != Objects.end(); oi++) { + ConfigObjectEventArgs::Ptr ea = make_shared(); + ea->Source = oi->second; + callback(ea); + } +} diff --git a/base/configcollection.h b/base/configcollection.h new file mode 100644 index 000000000..6d30b3a59 --- /dev/null +++ b/base/configcollection.h @@ -0,0 +1,37 @@ +#ifndef CONFIGCOLLECTION_H +#define CONFIGCOLLECTION_H + +namespace icinga +{ + +class ConfigHive; + +class ConfigCollection : public Object +{ +private: + weak_ptr m_Hive; + +public: + typedef shared_ptr Ptr; + typedef weak_ptr WeakPtr; + + typedef map::iterator ObjectIterator; + map Objects; + + void SetHive(const weak_ptr& hive); + weak_ptr GetHive(void) const; + + void AddObject(const ConfigObject::Ptr& object); + void RemoveObject(const ConfigObject::Ptr& object); + ConfigObject::Ptr GetObject(const string& name = string()); + + void ForEachObject(function callback); + + event OnObjectCreated; + event OnObjectRemoved; + event OnPropertyChanged; +}; + +} + +#endif /* CONFIGCOLLECTION_H */ diff --git a/base/confighive.cpp b/base/confighive.cpp index a76734a8a..93bd49e5a 100644 --- a/base/confighive.cpp +++ b/base/confighive.cpp @@ -4,52 +4,38 @@ using namespace icinga; void ConfigHive::AddObject(const ConfigObject::Ptr& 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::Ptr ea = make_shared(); - ea->Source = shared_from_this(); - ea->Object = object; - OnObjectCreated(ea); + GetCollection(object->GetType())->AddObject(object); } void ConfigHive::RemoveObject(const ConfigObject::Ptr& object) { - string type = object->GetType(); - TypeIterator ti = Objects.find(type); - - if (ti == Objects.end()) - return; - - ti->second.erase(object->GetName()); - - ConfigHiveEventArgs::Ptr ea = make_shared(); - ea->Source = shared_from_this(); - ea->Object = object; - OnObjectRemoved(ea); + GetCollection(object->GetType())->RemoveObject(object); } ConfigObject::Ptr ConfigHive::GetObject(const string& type, const string& name) { - ConfigHive::TypeIterator ti = Objects.find(type); - - if (ti == Objects.end()) - return ConfigObject::Ptr(); - - ConfigHive::ObjectIterator oi = ti->second.find(name); - - if (oi == ti->second.end()) - return ConfigObject::Ptr(); - - return oi->second; + return GetCollection(type)->GetObject(name); +} + +ConfigCollection::Ptr ConfigHive::GetCollection(const string& collection) +{ + CollectionIterator ci = Collections.find(collection); + + if (ci == Collections.end()) { + Collections[collection] = make_shared(); + ci = Collections.find(collection); + } + + return ci->second; +} + +void ConfigHive::ForEachObject(const string& type, function callback) +{ + CollectionIterator ci = Collections.find(type); + + if (ci == Collections.end()) + return; + + ci->second->ForEachObject(callback); } diff --git a/base/confighive.h b/base/confighive.h index 6e5d527e0..8a6fb58df 100644 --- a/base/confighive.h +++ b/base/confighive.h @@ -4,33 +4,25 @@ namespace icinga { -struct ConfigHiveEventArgs : public EventArgs -{ - typedef shared_ptr Ptr; - typedef weak_ptr WeakPtr; - - ConfigObject::Ptr Object; - string Property; - string OldValue; -}; - class ConfigHive : public Object { public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; - typedef map< string, map >::iterator TypeIterator; - typedef map::iterator ObjectIterator; - map< string, map > Objects; + typedef map::iterator CollectionIterator; + map Collections; void AddObject(const ConfigObject::Ptr& object); void RemoveObject(const ConfigObject::Ptr& object); - ConfigObject::Ptr GetObject(const string& type, const string& name = string()); + ConfigObject::Ptr GetObject(const string& collection, const string& name = string()); + ConfigCollection::Ptr GetCollection(const string& collection); - event OnObjectCreated; - event OnObjectRemoved; - event OnPropertyChanged; + void ForEachObject(const string& type, function callback); + + event OnObjectCreated; + event OnObjectRemoved; + event OnPropertyChanged; }; } diff --git a/base/configobject.cpp b/base/configobject.cpp index 35b9a0df7..b301d5304 100644 --- a/base/configobject.cpp +++ b/base/configobject.cpp @@ -2,6 +2,12 @@ using namespace icinga; +ConfigObject::ConfigObject(const string& type, const string& name) +{ + m_Type = type; + m_Name = name; +} + void ConfigObject::SetHive(const ConfigHive::WeakPtr& hive) { m_Hive = hive; @@ -37,16 +43,16 @@ void ConfigObject::SetProperty(const string& name, const string& value) Properties[name] = value; ConfigHive::Ptr hive = m_Hive.lock(); - if (hive.get() != NULL) { - ConfigHiveEventArgs::Ptr ea = make_shared(); - ea->Source = hive; - ea->Object = static_pointer_cast(shared_from_this()); + if (hive) { + ConfigObjectEventArgs::Ptr ea = make_shared(); + ea->Source = shared_from_this(); ea->Property = name; string oldValue; if (GetProperty(name, &oldValue)) ea->OldValue = oldValue; + hive->GetCollection(m_Type)->OnPropertyChanged(ea); hive->OnPropertyChanged(ea); } } diff --git a/base/configobject.h b/base/configobject.h index fbe993868..be4882185 100644 --- a/base/configobject.h +++ b/base/configobject.h @@ -8,6 +8,15 @@ namespace icinga class ConfigHive; +struct ConfigObjectEventArgs : public EventArgs +{ + typedef shared_ptr Ptr; + typedef weak_ptr WeakPtr; + + string Property; + string OldValue; +}; + class ConfigObject : public Object { private: @@ -23,7 +32,9 @@ public: typedef map::iterator ParameterIterator; map Properties; - void SetHive(const weak_ptr& name); + ConfigObject(const string& type, const string& name); + + void SetHive(const weak_ptr& hive); weak_ptr GetHive(void) const; void SetName(const string& name); diff --git a/base/i2-base.h b/base/i2-base.h index b86e05505..2b9626175 100644 --- a/base/i2-base.h +++ b/base/i2-base.h @@ -37,9 +37,11 @@ using namespace std::placeholders; #else # include # include -# include "cxx11-compat.h" + using namespace std::tr1; using namespace std::tr1::placeholders; + +# include "cxx11-compat.h" #endif #define PLATFORM_WINDOWS 1 @@ -68,6 +70,7 @@ using namespace std::tr1::placeholders; #include "tcpclient.h" #include "tcpserver.h" #include "configobject.h" +#include "configcollection.h" #include "confighive.h" #include "application.h" #include "component.h" diff --git a/configfilecomponent/configfilecomponent.cpp b/configfilecomponent/configfilecomponent.cpp index 30f166256..467ebee76 100644 --- a/configfilecomponent/configfilecomponent.cpp +++ b/configfilecomponent/configfilecomponent.cpp @@ -51,9 +51,7 @@ void ConfigFileComponent::Start(void) for (cJSON *object = typeobj->child; object != NULL; object = object->next) { string name = object->string; - ConfigObject::Ptr cfgobj = make_shared(); - cfgobj->SetName(name); - cfgobj->SetType(type); + ConfigObject::Ptr cfgobj = make_shared(type, name); for (cJSON *property = object->child; property != NULL; property = property->next) { string key = property->string; diff --git a/configrpccomponent/configrpccomponent.cpp b/configrpccomponent/configrpccomponent.cpp index 43aeebc79..d28e25324 100644 --- a/configrpccomponent/configrpccomponent.cpp +++ b/configrpccomponent/configrpccomponent.cpp @@ -65,8 +65,10 @@ int ConfigRpcComponent::FetchObjectsHandler(NewMessageEventArgs::Ptr ea) JsonRpcClient::Ptr client = static_pointer_cast(ea->Source); ConfigHive::Ptr configHive = GetIcingaApplication()->GetConfigHive(); - for (ConfigHive::TypeIterator ti = configHive->Objects.begin(); ti != configHive->Objects.end(); ti++) { - for (ConfigHive::ObjectIterator oi = ti->second.begin(); oi != ti->second.end(); oi++) { + for (ConfigHive::CollectionIterator ci = configHive->Collections.begin(); ci != configHive->Collections.end(); ci++) { + ConfigCollection::Ptr collection = ci->second; + + for (ConfigCollection::ObjectIterator oi = collection->Objects.begin(); oi != collection->Objects.end(); oi++) { JsonRpcMessage::Ptr msg = MakeObjectMessage(oi->second, "config::ObjectCreated", true); client->SendMessage(msg); } @@ -75,29 +77,32 @@ int ConfigRpcComponent::FetchObjectsHandler(NewMessageEventArgs::Ptr ea) return 0; } -int ConfigRpcComponent::LocalObjectCreatedHandler(ConfigHiveEventArgs::Ptr ea) +int ConfigRpcComponent::LocalObjectCreatedHandler(ConfigObjectEventArgs::Ptr ea) { + ConfigObject::Ptr object = static_pointer_cast(ea->Source); ConnectionManager::Ptr connectionManager = GetIcingaApplication()->GetConnectionManager(); - connectionManager->SendMessage(MakeObjectMessage(ea->Object, "config::ObjectCreated", true)); + connectionManager->SendMessage(MakeObjectMessage(object, "config::ObjectCreated", true)); return 0; } -int ConfigRpcComponent::LocalObjectRemovedHandler(ConfigHiveEventArgs::Ptr ea) +int ConfigRpcComponent::LocalObjectRemovedHandler(ConfigObjectEventArgs::Ptr ea) { + ConfigObject::Ptr object = static_pointer_cast(ea->Source); ConnectionManager::Ptr connectionManager = GetIcingaApplication()->GetConnectionManager(); - connectionManager->SendMessage(MakeObjectMessage(ea->Object, "config::ObjectRemoved", false)); + connectionManager->SendMessage(MakeObjectMessage(object, "config::ObjectRemoved", false)); return 0; } -int ConfigRpcComponent::LocalPropertyChangedHandler(ConfigHiveEventArgs::Ptr ea) +int ConfigRpcComponent::LocalPropertyChangedHandler(ConfigObjectEventArgs::Ptr ea) { - JsonRpcMessage::Ptr msg = MakeObjectMessage(ea->Object, "config::ObjectRemoved", false); + ConfigObject::Ptr object = static_pointer_cast(ea->Source); + JsonRpcMessage::Ptr msg = MakeObjectMessage(object, "config::ObjectRemoved", false); cJSON *params = msg->GetParams(); cJSON_AddStringToObject(params, "property", ea->Property.c_str()); string value; - ea->Object->GetProperty(ea->Property, &value); + object->GetProperty(ea->Property, &value); cJSON_AddStringToObject(params, "value", value.c_str()); ConnectionManager::Ptr connectionManager = GetIcingaApplication()->GetConnectionManager(); diff --git a/configrpccomponent/configrpccomponent.h b/configrpccomponent/configrpccomponent.h index 7be55a0b4..dc24516bf 100644 --- a/configrpccomponent/configrpccomponent.h +++ b/configrpccomponent/configrpccomponent.h @@ -11,9 +11,9 @@ private: int FetchObjectsHandler(NewMessageEventArgs::Ptr ea); - int LocalObjectCreatedHandler(ConfigHiveEventArgs::Ptr ea); - int LocalObjectRemovedHandler(ConfigHiveEventArgs::Ptr ea); - int LocalPropertyChangedHandler(ConfigHiveEventArgs::Ptr ea); + int LocalObjectCreatedHandler(ConfigObjectEventArgs::Ptr ea); + int LocalObjectRemovedHandler(ConfigObjectEventArgs::Ptr ea); + int LocalPropertyChangedHandler(ConfigObjectEventArgs::Ptr ea); int RemoteObjectCreatedHandler(NewMessageEventArgs::Ptr ea); int RemoteObjectRemovedHandler(NewMessageEventArgs::Ptr ea); diff --git a/icinga/icingaapplication.cpp b/icinga/icingaapplication.cpp index 344cebfa5..a807d1db3 100644 --- a/icinga/icingaapplication.cpp +++ b/icinga/icingaapplication.cpp @@ -30,15 +30,32 @@ int IcingaApplication::Main(const vector& args) string componentDirectory = GetExeDirectory() + "/../lib/icinga"; AddComponentSearchDir(componentDirectory); - GetConfigHive()->OnObjectCreated += bind_weak(&IcingaApplication::ConfigObjectCreatedHandler, shared_from_this()); - GetConfigHive()->OnObjectRemoved += bind_weak(&IcingaApplication::ConfigObjectRemovedHandler, shared_from_this()); + function NewComponentHandler; + NewComponentHandler = bind_weak(&IcingaApplication::NewComponentHandler, shared_from_this()); + ConfigCollection::Ptr componentCollection = GetConfigHive()->GetCollection("component"); + componentCollection->OnObjectCreated += NewComponentHandler; + componentCollection->ForEachObject(NewComponentHandler); - ConfigObject::Ptr fileComponentConfig = make_shared(); - fileComponentConfig->SetName("configfilecomponent"); - fileComponentConfig->SetType("component"); + function DeletedComponentHandler; + DeletedComponentHandler = bind_weak(&IcingaApplication::DeletedComponentHandler, shared_from_this()); + componentCollection->OnObjectRemoved += DeletedComponentHandler; + + function NewRpcListenerHandler; + NewRpcListenerHandler = bind_weak(&IcingaApplication::NewRpcListenerHandler, shared_from_this()); + ConfigCollection::Ptr listenerCollection = GetConfigHive()->GetCollection("rpclistener"); + listenerCollection->OnObjectCreated += NewRpcListenerHandler; + listenerCollection->ForEachObject(NewRpcListenerHandler); + + function DeletedRpcListenerHandler; + DeletedRpcListenerHandler = bind_weak(&IcingaApplication::DeletedRpcListenerHandler, shared_from_this()); + listenerCollection->OnObjectRemoved += DeletedRpcListenerHandler; + + ConfigObject::Ptr fileComponentConfig = make_shared("component", "configfilecomponent"); fileComponentConfig->SetProperty("configFilename", args[1]); GetConfigHive()->AddObject(fileComponentConfig); + ConfigCollection::Ptr collection = GetConfigHive()->GetCollection("rpclistener"); + RunEventLoop(); return EXIT_SUCCESS; @@ -54,32 +71,55 @@ ConnectionManager::Ptr IcingaApplication::GetConnectionManager(void) return m_ConnectionManager; } -int IcingaApplication::ConfigObjectCreatedHandler(ConfigHiveEventArgs::Ptr ea) +int IcingaApplication::NewComponentHandler(ConfigObjectEventArgs::Ptr ea) { - if (ea->Object->GetType() == "component") { - string path; + string path; + ConfigObject::Ptr object = static_pointer_cast(ea->Source); - if (!ea->Object->GetProperty("path", &path)) { + if (!object->GetProperty("path", &path)) { #ifdef _WIN32 - path = ea->Object->GetName() + ".dll"; + path = object->GetName() + ".dll"; #else /* _WIN32 */ - path = "lib" + ea->Object->GetName() + ".la"; + path = "lib" + ea->Object->GetName() + ".la"; #endif /* _WIN32 */ - // TODO: try to figure out where the component is located */ - } - - LoadComponent(path, ea->Object); + // TODO: try to figure out where the component is located */ } + LoadComponent(path, object); + return 0; } -int IcingaApplication::ConfigObjectRemovedHandler(ConfigHiveEventArgs::Ptr ea) +int IcingaApplication::DeletedComponentHandler(ConfigObjectEventArgs::Ptr ea) { - if (ea->Object->GetType() == "component") { - UnloadComponent(ea->Object->GetName()); - } + ConfigObject::Ptr object = static_pointer_cast(ea->Source); + UnloadComponent(object->GetName()); + + return 0; +} + +int IcingaApplication::NewRpcListenerHandler(ConfigObjectEventArgs::Ptr ea) +{ + ConfigObject::Ptr object = static_pointer_cast(ea->Source); + int port; + + if (!object->GetPropertyInteger("port", &port)) + throw Exception("Parameter 'port' is required for 'rpclistener' objects."); + + Log("Creating JSON-RPC listener on port %d", port); + + JsonRpcServer::Ptr server = make_shared(); + server->Bind(port); + server->Start(); + GetConnectionManager()->RegisterServer(server); + + return 0; +} + +int IcingaApplication::DeletedRpcListenerHandler(ConfigObjectEventArgs::Ptr ea) +{ + throw Exception("Unsupported operation."); return 0; } diff --git a/icinga/icingaapplication.h b/icinga/icingaapplication.h index f924121e9..a6f691def 100644 --- a/icinga/icingaapplication.h +++ b/icinga/icingaapplication.h @@ -9,8 +9,11 @@ class IcingaApplication : public Application private: ConnectionManager::Ptr m_ConnectionManager; - int ConfigObjectCreatedHandler(ConfigHiveEventArgs::Ptr ea); - int ConfigObjectRemovedHandler(ConfigHiveEventArgs::Ptr ea); + int NewComponentHandler(ConfigObjectEventArgs::Ptr ea); + int DeletedComponentHandler(ConfigObjectEventArgs::Ptr ea); + + int NewRpcListenerHandler(ConfigObjectEventArgs::Ptr ea); + int DeletedRpcListenerHandler(ConfigObjectEventArgs::Ptr ea); public: typedef shared_ptr Ptr;