Refactored config handling to support observing individual config object types more easily.

This commit is contained in:
Gunnar Beutner 2012-04-04 10:04:38 +02:00
parent bfcb5019d5
commit c3142ed593
14 changed files with 245 additions and 98 deletions

View File

@ -11,6 +11,8 @@ libbase_la_SOURCES = \
component.h \ component.h \
condvar.cpp \ condvar.cpp \
condvar.h \ condvar.h \
configcollection.cpp \
configcollection.h \
confighive.cpp \ confighive.cpp \
confighive.h \ confighive.h \
configobject.cpp \ configobject.cpp \

View File

@ -14,6 +14,7 @@
<ClCompile Include="application.cpp" /> <ClCompile Include="application.cpp" />
<ClCompile Include="component.cpp" /> <ClCompile Include="component.cpp" />
<ClCompile Include="condvar.cpp" /> <ClCompile Include="condvar.cpp" />
<ClCompile Include="configcollection.cpp" />
<ClCompile Include="confighive.cpp" /> <ClCompile Include="confighive.cpp" />
<ClCompile Include="configobject.cpp" /> <ClCompile Include="configobject.cpp" />
<ClCompile Include="exception.cpp" /> <ClCompile Include="exception.cpp" />
@ -34,6 +35,7 @@
<ClInclude Include="application.h" /> <ClInclude Include="application.h" />
<ClInclude Include="component.h" /> <ClInclude Include="component.h" />
<ClInclude Include="condvar.h" /> <ClInclude Include="condvar.h" />
<ClInclude Include="configcollection.h" />
<ClInclude Include="confighive.h" /> <ClInclude Include="confighive.h" />
<ClInclude Include="configobject.h" /> <ClInclude Include="configobject.h" />
<ClInclude Include="cxx11-compat.h" /> <ClInclude Include="cxx11-compat.h" />

62
base/configcollection.cpp Normal file
View File

@ -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<ConfigObjectEventArgs>();
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<ConfigObjectEventArgs>();
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<int (ConfigObjectEventArgs::Ptr)> callback)
{
for (ObjectIterator oi = Objects.begin(); oi != Objects.end(); oi++) {
ConfigObjectEventArgs::Ptr ea = make_shared<ConfigObjectEventArgs>();
ea->Source = oi->second;
callback(ea);
}
}

37
base/configcollection.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef CONFIGCOLLECTION_H
#define CONFIGCOLLECTION_H
namespace icinga
{
class ConfigHive;
class ConfigCollection : public Object
{
private:
weak_ptr<ConfigHive> m_Hive;
public:
typedef shared_ptr<ConfigCollection> Ptr;
typedef weak_ptr<ConfigCollection> WeakPtr;
typedef map<string, ConfigObject::Ptr>::iterator ObjectIterator;
map<string, ConfigObject::Ptr> Objects;
void SetHive(const weak_ptr<ConfigHive>& hive);
weak_ptr<ConfigHive> 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<int (ConfigObjectEventArgs::Ptr)> callback);
event<ConfigObjectEventArgs::Ptr> OnObjectCreated;
event<ConfigObjectEventArgs::Ptr> OnObjectRemoved;
event<ConfigObjectEventArgs::Ptr> OnPropertyChanged;
};
}
#endif /* CONFIGCOLLECTION_H */

View File

@ -4,52 +4,38 @@ using namespace icinga;
void ConfigHive::AddObject(const ConfigObject::Ptr& object) void ConfigHive::AddObject(const ConfigObject::Ptr& object)
{ {
string type = object->GetType();
TypeIterator ti = Objects.find(type);
if (ti == Objects.end()) {
Objects[type] = map<string, ConfigObject::Ptr>();
ti = Objects.find(type);
}
object->SetHive(static_pointer_cast<ConfigHive>(shared_from_this())); object->SetHive(static_pointer_cast<ConfigHive>(shared_from_this()));
GetCollection(object->GetType())->AddObject(object);
string name = object->GetName();
ti->second[name] = object;
ConfigHiveEventArgs::Ptr ea = make_shared<ConfigHiveEventArgs>();
ea->Source = shared_from_this();
ea->Object = object;
OnObjectCreated(ea);
} }
void ConfigHive::RemoveObject(const ConfigObject::Ptr& object) void ConfigHive::RemoveObject(const ConfigObject::Ptr& object)
{ {
string type = object->GetType(); GetCollection(object->GetType())->RemoveObject(object);
TypeIterator ti = Objects.find(type);
if (ti == Objects.end())
return;
ti->second.erase(object->GetName());
ConfigHiveEventArgs::Ptr ea = make_shared<ConfigHiveEventArgs>();
ea->Source = shared_from_this();
ea->Object = object;
OnObjectRemoved(ea);
} }
ConfigObject::Ptr ConfigHive::GetObject(const string& type, const string& name) ConfigObject::Ptr ConfigHive::GetObject(const string& type, const string& name)
{ {
ConfigHive::TypeIterator ti = Objects.find(type); return GetCollection(type)->GetObject(name);
}
if (ti == Objects.end())
return ConfigObject::Ptr(); ConfigCollection::Ptr ConfigHive::GetCollection(const string& collection)
{
ConfigHive::ObjectIterator oi = ti->second.find(name); CollectionIterator ci = Collections.find(collection);
if (oi == ti->second.end()) if (ci == Collections.end()) {
return ConfigObject::Ptr(); Collections[collection] = make_shared<ConfigCollection>();
ci = Collections.find(collection);
return oi->second; }
return ci->second;
}
void ConfigHive::ForEachObject(const string& type, function<int (ConfigObjectEventArgs::Ptr)> callback)
{
CollectionIterator ci = Collections.find(type);
if (ci == Collections.end())
return;
ci->second->ForEachObject(callback);
} }

View File

@ -4,33 +4,25 @@
namespace icinga namespace icinga
{ {
struct ConfigHiveEventArgs : public EventArgs
{
typedef shared_ptr<ConfigHiveEventArgs> Ptr;
typedef weak_ptr<ConfigHiveEventArgs> WeakPtr;
ConfigObject::Ptr Object;
string Property;
string OldValue;
};
class ConfigHive : public Object class ConfigHive : public Object
{ {
public: public:
typedef shared_ptr<ConfigHive> Ptr; typedef shared_ptr<ConfigHive> Ptr;
typedef weak_ptr<ConfigHive> WeakPtr; typedef weak_ptr<ConfigHive> WeakPtr;
typedef map< string, map<string, ConfigObject::Ptr> >::iterator TypeIterator; typedef map<string, ConfigCollection::Ptr>::iterator CollectionIterator;
typedef map<string, ConfigObject::Ptr>::iterator ObjectIterator; map<string, ConfigCollection::Ptr> Collections;
map< string, map<string, ConfigObject::Ptr> > Objects;
void AddObject(const ConfigObject::Ptr& object); void AddObject(const ConfigObject::Ptr& object);
void RemoveObject(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<ConfigHiveEventArgs::Ptr> OnObjectCreated; void ForEachObject(const string& type, function<int (ConfigObjectEventArgs::Ptr)> callback);
event<ConfigHiveEventArgs::Ptr> OnObjectRemoved;
event<ConfigHiveEventArgs::Ptr> OnPropertyChanged; event<ConfigObjectEventArgs::Ptr> OnObjectCreated;
event<ConfigObjectEventArgs::Ptr> OnObjectRemoved;
event<ConfigObjectEventArgs::Ptr> OnPropertyChanged;
}; };
} }

View File

@ -2,6 +2,12 @@
using namespace icinga; using namespace icinga;
ConfigObject::ConfigObject(const string& type, const string& name)
{
m_Type = type;
m_Name = name;
}
void ConfigObject::SetHive(const ConfigHive::WeakPtr& hive) void ConfigObject::SetHive(const ConfigHive::WeakPtr& hive)
{ {
m_Hive = hive; m_Hive = hive;
@ -37,16 +43,16 @@ void ConfigObject::SetProperty(const string& name, const string& value)
Properties[name] = value; Properties[name] = value;
ConfigHive::Ptr hive = m_Hive.lock(); ConfigHive::Ptr hive = m_Hive.lock();
if (hive.get() != NULL) { if (hive) {
ConfigHiveEventArgs::Ptr ea = make_shared<ConfigHiveEventArgs>(); ConfigObjectEventArgs::Ptr ea = make_shared<ConfigObjectEventArgs>();
ea->Source = hive; ea->Source = shared_from_this();
ea->Object = static_pointer_cast<ConfigObject>(shared_from_this());
ea->Property = name; ea->Property = name;
string oldValue; string oldValue;
if (GetProperty(name, &oldValue)) if (GetProperty(name, &oldValue))
ea->OldValue = oldValue; ea->OldValue = oldValue;
hive->GetCollection(m_Type)->OnPropertyChanged(ea);
hive->OnPropertyChanged(ea); hive->OnPropertyChanged(ea);
} }
} }

View File

@ -8,6 +8,15 @@ namespace icinga
class ConfigHive; class ConfigHive;
struct ConfigObjectEventArgs : public EventArgs
{
typedef shared_ptr<ConfigObjectEventArgs> Ptr;
typedef weak_ptr<ConfigObjectEventArgs> WeakPtr;
string Property;
string OldValue;
};
class ConfigObject : public Object class ConfigObject : public Object
{ {
private: private:
@ -23,7 +32,9 @@ public:
typedef map<string, string>::iterator ParameterIterator; typedef map<string, string>::iterator ParameterIterator;
map<string, string> Properties; map<string, string> Properties;
void SetHive(const weak_ptr<ConfigHive>& name); ConfigObject(const string& type, const string& name);
void SetHive(const weak_ptr<ConfigHive>& hive);
weak_ptr<ConfigHive> GetHive(void) const; weak_ptr<ConfigHive> GetHive(void) const;
void SetName(const string& name); void SetName(const string& name);

View File

@ -37,9 +37,11 @@ using namespace std::placeholders;
#else #else
# include <tr1/memory> # include <tr1/memory>
# include <tr1/functional> # include <tr1/functional>
# include "cxx11-compat.h"
using namespace std::tr1; using namespace std::tr1;
using namespace std::tr1::placeholders; using namespace std::tr1::placeholders;
# include "cxx11-compat.h"
#endif #endif
#define PLATFORM_WINDOWS 1 #define PLATFORM_WINDOWS 1
@ -68,6 +70,7 @@ using namespace std::tr1::placeholders;
#include "tcpclient.h" #include "tcpclient.h"
#include "tcpserver.h" #include "tcpserver.h"
#include "configobject.h" #include "configobject.h"
#include "configcollection.h"
#include "confighive.h" #include "confighive.h"
#include "application.h" #include "application.h"
#include "component.h" #include "component.h"

View File

@ -51,9 +51,7 @@ void ConfigFileComponent::Start(void)
for (cJSON *object = typeobj->child; object != NULL; object = object->next) { for (cJSON *object = typeobj->child; object != NULL; object = object->next) {
string name = object->string; string name = object->string;
ConfigObject::Ptr cfgobj = make_shared<ConfigObject>(); ConfigObject::Ptr cfgobj = make_shared<ConfigObject>(type, name);
cfgobj->SetName(name);
cfgobj->SetType(type);
for (cJSON *property = object->child; property != NULL; property = property->next) { for (cJSON *property = object->child; property != NULL; property = property->next) {
string key = property->string; string key = property->string;

View File

@ -65,8 +65,10 @@ int ConfigRpcComponent::FetchObjectsHandler(NewMessageEventArgs::Ptr ea)
JsonRpcClient::Ptr client = static_pointer_cast<JsonRpcClient>(ea->Source); JsonRpcClient::Ptr client = static_pointer_cast<JsonRpcClient>(ea->Source);
ConfigHive::Ptr configHive = GetIcingaApplication()->GetConfigHive(); ConfigHive::Ptr configHive = GetIcingaApplication()->GetConfigHive();
for (ConfigHive::TypeIterator ti = configHive->Objects.begin(); ti != configHive->Objects.end(); ti++) { for (ConfigHive::CollectionIterator ci = configHive->Collections.begin(); ci != configHive->Collections.end(); ci++) {
for (ConfigHive::ObjectIterator oi = ti->second.begin(); oi != ti->second.end(); oi++) { 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); JsonRpcMessage::Ptr msg = MakeObjectMessage(oi->second, "config::ObjectCreated", true);
client->SendMessage(msg); client->SendMessage(msg);
} }
@ -75,29 +77,32 @@ int ConfigRpcComponent::FetchObjectsHandler(NewMessageEventArgs::Ptr ea)
return 0; return 0;
} }
int ConfigRpcComponent::LocalObjectCreatedHandler(ConfigHiveEventArgs::Ptr ea) int ConfigRpcComponent::LocalObjectCreatedHandler(ConfigObjectEventArgs::Ptr ea)
{ {
ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea->Source);
ConnectionManager::Ptr connectionManager = GetIcingaApplication()->GetConnectionManager(); ConnectionManager::Ptr connectionManager = GetIcingaApplication()->GetConnectionManager();
connectionManager->SendMessage(MakeObjectMessage(ea->Object, "config::ObjectCreated", true)); connectionManager->SendMessage(MakeObjectMessage(object, "config::ObjectCreated", true));
return 0; return 0;
} }
int ConfigRpcComponent::LocalObjectRemovedHandler(ConfigHiveEventArgs::Ptr ea) int ConfigRpcComponent::LocalObjectRemovedHandler(ConfigObjectEventArgs::Ptr ea)
{ {
ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea->Source);
ConnectionManager::Ptr connectionManager = GetIcingaApplication()->GetConnectionManager(); ConnectionManager::Ptr connectionManager = GetIcingaApplication()->GetConnectionManager();
connectionManager->SendMessage(MakeObjectMessage(ea->Object, "config::ObjectRemoved", false)); connectionManager->SendMessage(MakeObjectMessage(object, "config::ObjectRemoved", false));
return 0; 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<ConfigObject>(ea->Source);
JsonRpcMessage::Ptr msg = MakeObjectMessage(object, "config::ObjectRemoved", false);
cJSON *params = msg->GetParams(); cJSON *params = msg->GetParams();
cJSON_AddStringToObject(params, "property", ea->Property.c_str()); cJSON_AddStringToObject(params, "property", ea->Property.c_str());
string value; string value;
ea->Object->GetProperty(ea->Property, &value); object->GetProperty(ea->Property, &value);
cJSON_AddStringToObject(params, "value", value.c_str()); cJSON_AddStringToObject(params, "value", value.c_str());
ConnectionManager::Ptr connectionManager = GetIcingaApplication()->GetConnectionManager(); ConnectionManager::Ptr connectionManager = GetIcingaApplication()->GetConnectionManager();

View File

@ -11,9 +11,9 @@ private:
int FetchObjectsHandler(NewMessageEventArgs::Ptr ea); int FetchObjectsHandler(NewMessageEventArgs::Ptr ea);
int LocalObjectCreatedHandler(ConfigHiveEventArgs::Ptr ea); int LocalObjectCreatedHandler(ConfigObjectEventArgs::Ptr ea);
int LocalObjectRemovedHandler(ConfigHiveEventArgs::Ptr ea); int LocalObjectRemovedHandler(ConfigObjectEventArgs::Ptr ea);
int LocalPropertyChangedHandler(ConfigHiveEventArgs::Ptr ea); int LocalPropertyChangedHandler(ConfigObjectEventArgs::Ptr ea);
int RemoteObjectCreatedHandler(NewMessageEventArgs::Ptr ea); int RemoteObjectCreatedHandler(NewMessageEventArgs::Ptr ea);
int RemoteObjectRemovedHandler(NewMessageEventArgs::Ptr ea); int RemoteObjectRemovedHandler(NewMessageEventArgs::Ptr ea);

View File

@ -30,15 +30,32 @@ int IcingaApplication::Main(const vector<string>& args)
string componentDirectory = GetExeDirectory() + "/../lib/icinga"; string componentDirectory = GetExeDirectory() + "/../lib/icinga";
AddComponentSearchDir(componentDirectory); AddComponentSearchDir(componentDirectory);
GetConfigHive()->OnObjectCreated += bind_weak(&IcingaApplication::ConfigObjectCreatedHandler, shared_from_this()); function<int (ConfigObjectEventArgs::Ptr)> NewComponentHandler;
GetConfigHive()->OnObjectRemoved += bind_weak(&IcingaApplication::ConfigObjectRemovedHandler, shared_from_this()); 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<ConfigObject>(); function<int (ConfigObjectEventArgs::Ptr)> DeletedComponentHandler;
fileComponentConfig->SetName("configfilecomponent"); DeletedComponentHandler = bind_weak(&IcingaApplication::DeletedComponentHandler, shared_from_this());
fileComponentConfig->SetType("component"); componentCollection->OnObjectRemoved += DeletedComponentHandler;
function<int (ConfigObjectEventArgs::Ptr)> NewRpcListenerHandler;
NewRpcListenerHandler = bind_weak(&IcingaApplication::NewRpcListenerHandler, shared_from_this());
ConfigCollection::Ptr listenerCollection = GetConfigHive()->GetCollection("rpclistener");
listenerCollection->OnObjectCreated += NewRpcListenerHandler;
listenerCollection->ForEachObject(NewRpcListenerHandler);
function<int (ConfigObjectEventArgs::Ptr)> DeletedRpcListenerHandler;
DeletedRpcListenerHandler = bind_weak(&IcingaApplication::DeletedRpcListenerHandler, shared_from_this());
listenerCollection->OnObjectRemoved += DeletedRpcListenerHandler;
ConfigObject::Ptr fileComponentConfig = make_shared<ConfigObject>("component", "configfilecomponent");
fileComponentConfig->SetProperty("configFilename", args[1]); fileComponentConfig->SetProperty("configFilename", args[1]);
GetConfigHive()->AddObject(fileComponentConfig); GetConfigHive()->AddObject(fileComponentConfig);
ConfigCollection::Ptr collection = GetConfigHive()->GetCollection("rpclistener");
RunEventLoop(); RunEventLoop();
return EXIT_SUCCESS; return EXIT_SUCCESS;
@ -54,14 +71,14 @@ ConnectionManager::Ptr IcingaApplication::GetConnectionManager(void)
return m_ConnectionManager; 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<ConfigObject>(ea->Source);
if (!ea->Object->GetProperty("path", &path)) { if (!object->GetProperty("path", &path)) {
#ifdef _WIN32 #ifdef _WIN32
path = ea->Object->GetName() + ".dll"; path = object->GetName() + ".dll";
#else /* _WIN32 */ #else /* _WIN32 */
path = "lib" + ea->Object->GetName() + ".la"; path = "lib" + ea->Object->GetName() + ".la";
#endif /* _WIN32 */ #endif /* _WIN32 */
@ -69,17 +86,40 @@ int IcingaApplication::ConfigObjectCreatedHandler(ConfigHiveEventArgs::Ptr ea)
// TODO: try to figure out where the component is located */ // TODO: try to figure out where the component is located */
} }
LoadComponent(path, ea->Object); LoadComponent(path, object);
}
return 0; return 0;
} }
int IcingaApplication::ConfigObjectRemovedHandler(ConfigHiveEventArgs::Ptr ea) int IcingaApplication::DeletedComponentHandler(ConfigObjectEventArgs::Ptr ea)
{ {
if (ea->Object->GetType() == "component") { ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea->Source);
UnloadComponent(ea->Object->GetName()); UnloadComponent(object->GetName());
}
return 0;
}
int IcingaApplication::NewRpcListenerHandler(ConfigObjectEventArgs::Ptr ea)
{
ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(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<JsonRpcServer>();
server->Bind(port);
server->Start();
GetConnectionManager()->RegisterServer(server);
return 0;
}
int IcingaApplication::DeletedRpcListenerHandler(ConfigObjectEventArgs::Ptr ea)
{
throw Exception("Unsupported operation.");
return 0; return 0;
} }

View File

@ -9,8 +9,11 @@ class IcingaApplication : public Application
private: private:
ConnectionManager::Ptr m_ConnectionManager; ConnectionManager::Ptr m_ConnectionManager;
int ConfigObjectCreatedHandler(ConfigHiveEventArgs::Ptr ea); int NewComponentHandler(ConfigObjectEventArgs::Ptr ea);
int ConfigObjectRemovedHandler(ConfigHiveEventArgs::Ptr ea); int DeletedComponentHandler(ConfigObjectEventArgs::Ptr ea);
int NewRpcListenerHandler(ConfigObjectEventArgs::Ptr ea);
int DeletedRpcListenerHandler(ConfigObjectEventArgs::Ptr ea);
public: public:
typedef shared_ptr<IcingaApplication> Ptr; typedef shared_ptr<IcingaApplication> Ptr;