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 \
condvar.cpp \
condvar.h \
configcollection.cpp \
configcollection.h \
confighive.cpp \
confighive.h \
configobject.cpp \

View File

@ -14,6 +14,7 @@
<ClCompile Include="application.cpp" />
<ClCompile Include="component.cpp" />
<ClCompile Include="condvar.cpp" />
<ClCompile Include="configcollection.cpp" />
<ClCompile Include="confighive.cpp" />
<ClCompile Include="configobject.cpp" />
<ClCompile Include="exception.cpp" />
@ -34,6 +35,7 @@
<ClInclude Include="application.h" />
<ClInclude Include="component.h" />
<ClInclude Include="condvar.h" />
<ClInclude Include="configcollection.h" />
<ClInclude Include="confighive.h" />
<ClInclude Include="configobject.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)
{
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()));
string name = object->GetName();
ti->second[name] = object;
ConfigHiveEventArgs::Ptr ea = make_shared<ConfigHiveEventArgs>();
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<ConfigHiveEventArgs>();
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<ConfigCollection>();
ci = Collections.find(collection);
}
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
{
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
{
public:
typedef shared_ptr<ConfigHive> Ptr;
typedef weak_ptr<ConfigHive> WeakPtr;
typedef map< string, map<string, ConfigObject::Ptr> >::iterator TypeIterator;
typedef map<string, ConfigObject::Ptr>::iterator ObjectIterator;
map< string, map<string, ConfigObject::Ptr> > Objects;
typedef map<string, ConfigCollection::Ptr>::iterator CollectionIterator;
map<string, ConfigCollection::Ptr> 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<ConfigHiveEventArgs::Ptr> OnObjectCreated;
event<ConfigHiveEventArgs::Ptr> OnObjectRemoved;
event<ConfigHiveEventArgs::Ptr> OnPropertyChanged;
void ForEachObject(const string& type, function<int (ConfigObjectEventArgs::Ptr)> callback);
event<ConfigObjectEventArgs::Ptr> OnObjectCreated;
event<ConfigObjectEventArgs::Ptr> OnObjectRemoved;
event<ConfigObjectEventArgs::Ptr> OnPropertyChanged;
};
}

View File

@ -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<ConfigHiveEventArgs>();
ea->Source = hive;
ea->Object = static_pointer_cast<ConfigObject>(shared_from_this());
if (hive) {
ConfigObjectEventArgs::Ptr ea = make_shared<ConfigObjectEventArgs>();
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);
}
}

View File

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

View File

@ -37,9 +37,11 @@ using namespace std::placeholders;
#else
# include <tr1/memory>
# include <tr1/functional>
# 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"

View File

@ -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<ConfigObject>();
cfgobj->SetName(name);
cfgobj->SetType(type);
ConfigObject::Ptr cfgobj = make_shared<ConfigObject>(type, name);
for (cJSON *property = object->child; property != NULL; property = property->next) {
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);
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<ConfigObject>(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<ConfigObject>(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<ConfigObject>(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();

View File

@ -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);

View File

@ -30,15 +30,32 @@ int IcingaApplication::Main(const vector<string>& 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<int (ConfigObjectEventArgs::Ptr)> 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<ConfigObject>();
fileComponentConfig->SetName("configfilecomponent");
fileComponentConfig->SetType("component");
function<int (ConfigObjectEventArgs::Ptr)> DeletedComponentHandler;
DeletedComponentHandler = bind_weak(&IcingaApplication::DeletedComponentHandler, shared_from_this());
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]);
GetConfigHive()->AddObject(fileComponentConfig);
ConfigCollection::Ptr collection = GetConfigHive()->GetCollection("rpclistener");
RunEventLoop();
return EXIT_SUCCESS;
@ -54,14 +71,14 @@ 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;
ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(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";
#endif /* _WIN32 */
@ -69,17 +86,40 @@ int IcingaApplication::ConfigObjectCreatedHandler(ConfigHiveEventArgs::Ptr ea)
// TODO: try to figure out where the component is located */
}
LoadComponent(path, ea->Object);
}
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<ConfigObject>(ea->Source);
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;
}

View File

@ -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<IcingaApplication> Ptr;