Implemented DynamicType support.

Fixes #3477
This commit is contained in:
Gunnar Beutner 2012-12-04 08:42:24 +01:00
parent 6a03ab5220
commit 83772d4386
29 changed files with 441 additions and 250 deletions

View File

@ -248,7 +248,7 @@ void CompatComponent::StatusTimerHandler(void)
map<String, vector<String> > hostgroups;
DynamicObject::Ptr object;
BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Host")) {
BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Host")->GetObjects()) {
const Host::Ptr& host = static_pointer_cast<Host>(object);
Dictionary::Ptr dict;
@ -290,7 +290,7 @@ void CompatComponent::StatusTimerHandler(void)
map<String, vector<Service::Ptr> > servicegroups;
BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Service")) {
BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Service")->GetObjects()) {
Service::Ptr service = static_pointer_cast<Service>(object);
Dictionary::Ptr dict;

View File

@ -740,7 +740,7 @@ void CompatIdoComponent::DumpConfigObjects(void)
map<String, vector<String> > hostgroups;
DynamicObject::Ptr object;
BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Host")) {
BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Host")->GetObjects()) {
const Host::Ptr& host = static_pointer_cast<Host>(object);
Dictionary::Ptr dict;
@ -785,7 +785,7 @@ void CompatIdoComponent::DumpConfigObjects(void)
/* services and servicegroups */
map<String, vector<Service::Ptr> > servicegroups;
BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Service")) {
BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Service")->GetObjects()) {
Service::Ptr service = static_pointer_cast<Service>(object);
Dictionary::Ptr dict;
@ -854,7 +854,7 @@ void CompatIdoComponent::DumpStatusData(void)
{
/* hosts */
DynamicObject::Ptr object;
BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Host")) {
BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Host")->GetObjects()) {
const Host::Ptr& host = static_pointer_cast<Host>(object);
DumpHostStatus(host);
@ -862,7 +862,7 @@ void CompatIdoComponent::DumpStatusData(void)
/* services */
BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Service")) {
BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Service")->GetObjects()) {
Service::Ptr service = static_pointer_cast<Service>(object);
DumpServiceStatus(service);

View File

@ -41,7 +41,7 @@ vector<Endpoint::Ptr> DelegationComponent::GetCheckerCandidates(const Service::P
vector<Endpoint::Ptr> candidates;
DynamicObject::Ptr object;
BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Endpoint")) {
BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Endpoint")->GetObjects()) {
Endpoint::Ptr endpoint = dynamic_pointer_cast<Endpoint>(object);
String myIdentity = EndpointManager::GetInstance()->GetIdentity();
@ -73,7 +73,7 @@ void DelegationComponent::DelegationTimerHandler(void)
map<Endpoint::Ptr, int> histogram;
DynamicObject::Ptr object;
BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Endpoint")) {
BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Endpoint")->GetObjects()) {
Endpoint::Ptr endpoint = dynamic_pointer_cast<Endpoint>(object);
histogram[endpoint] = 0;
@ -82,7 +82,7 @@ void DelegationComponent::DelegationTimerHandler(void)
vector<Service::Ptr> services;
/* build "checker -> service count" histogram */
BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Service")) {
BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Service")->GetObjects()) {
Service::Ptr service = dynamic_pointer_cast<Service>(object);
if (!service)

View File

@ -85,11 +85,10 @@ void ReplicationComponent::EndpointConnectedHandler(const Endpoint::Ptr& endpoin
endpoint->RegisterSubscription("config::ObjectUpdate");
endpoint->RegisterSubscription("config::ObjectRemoved");
pair<DynamicObject::TypeMap::iterator, DynamicObject::TypeMap::iterator> trange = DynamicObject::GetTypes();
DynamicObject::TypeMap::iterator tt;
for (tt = trange.first; tt != trange.second; tt++) {
DynamicType::Ptr type;
BOOST_FOREACH(tie(tuples::ignore, type), DynamicType::GetTypes()) {
DynamicObject::Ptr object;
BOOST_FOREACH(tie(tuples::ignore, object), tt->second) {
BOOST_FOREACH(tie(tuples::ignore, object), type->GetObjects()) {
if (!ShouldReplicateObject(object))
continue;
@ -186,12 +185,13 @@ void ReplicationComponent::RemoteObjectUpdateHandler(const Endpoint::Ptr& sender
if (!params.Get("update", &update))
return;
DynamicObject::Ptr object = DynamicObject::GetObject(type, name);
DynamicType::Ptr dtype = DynamicType::GetByName(type);
DynamicObject::Ptr object = dtype->GetObject(name);
// TODO: sanitize update, disallow __local
if (!object) {
object = DynamicObject::Create(type, update);
object = dtype->CreateObject(update);
if (source == EndpointManager::GetInstance()->GetIdentity()) {
/* the peer sent us an object that was originally created by us -

View File

@ -16,6 +16,8 @@ libbase_la_SOURCES = \
dictionary.h \
dynamicobject.cpp \
dynamicobject.h \
dynamictype.cpp \
dynamictype.h \
event.cpp \
event.h \
exception.cpp \

View File

@ -122,7 +122,7 @@ void Application::RunEventLoop(void)
#ifdef _DEBUG
if (nextProfile < Utility::GetTime()) {
stringstream msgbuf;
msgbuf << "Active objects: " << Object::GetAliveObjects();
msgbuf << "Active objects: " << Object::GetAliveObjectsCount();
Logger::Write(LogInformation, "base", msgbuf.str());
Object::PrintMemoryProfile();

View File

@ -24,6 +24,7 @@
<ClCompile Include="connection.cpp" />
<ClCompile Include="dynamicobject.cpp" />
<ClCompile Include="dictionary.cpp" />
<ClCompile Include="dynamictype.cpp" />
<ClCompile Include="event.cpp" />
<ClCompile Include="exception.cpp" />
<ClCompile Include="fifo.cpp" />
@ -61,6 +62,7 @@
<ClInclude Include="connection.h" />
<ClInclude Include="dynamicobject.h" />
<ClInclude Include="dictionary.h" />
<ClInclude Include="dynamictype.h" />
<ClInclude Include="event.h" />
<ClInclude Include="fifo.h" />
<ClInclude Include="stdiostream.h" />

View File

@ -88,6 +88,9 @@
<ClCompile Include="stdiostream.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="dynamictype.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="application.h">
@ -186,6 +189,9 @@
<ClInclude Include="stdiostream.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="dynamictype.h">
<Filter>Headerdateien</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Quelldateien">

View File

@ -24,7 +24,7 @@
using namespace icinga;
REGISTER_CLASS(Component);
REGISTER_TYPE(Component, NULL);
/**
* Constructor for the component class.

View File

@ -219,9 +219,10 @@ void DynamicObject::ClearAttributesByType(DynamicAttributeType type)
}
}
String DynamicObject::GetType(void) const
DynamicType::Ptr DynamicObject::GetType(void) const
{
return Get("__type");
String name = Get("__type");
return DynamicType::GetByName(name);
}
String DynamicObject::GetName(void) const
@ -263,13 +264,11 @@ void DynamicObject::Register(void)
{
assert(Application::IsMainThread());
DynamicObject::Ptr dobj = GetObject(GetType(), GetName());
DynamicObject::Ptr dobj = GetType()->GetObject(GetName());
DynamicObject::Ptr self = GetSelf();
assert(!dobj || dobj == self);
pair<DynamicObject::TypeMap::iterator, bool> ti;
ti = GetAllObjects().insert(make_pair(GetType(), DynamicObject::NameMap()));
ti.first->second.insert(make_pair(GetName(), GetSelf()));
GetType()->RegisterObject(self);
OnRegistered(GetSelf());
@ -285,51 +284,14 @@ void DynamicObject::Unregister(void)
{
assert(Application::IsMainThread());
DynamicObject::TypeMap::iterator tt;
tt = GetAllObjects().find(GetType());
if (tt == GetAllObjects().end())
if (GetType()->GetObject(GetName()))
return;
DynamicObject::NameMap::iterator nt = tt->second.find(GetName());
if (nt == tt->second.end())
return;
tt->second.erase(nt);
GetType()->UnregisterObject(GetSelf());
OnUnregistered(GetSelf());
}
DynamicObject::Ptr DynamicObject::GetObject(const String& type, const String& name)
{
DynamicObject::TypeMap::iterator tt;
tt = GetAllObjects().find(type);
if (tt == GetAllObjects().end())
return DynamicObject::Ptr();
DynamicObject::NameMap::iterator nt = tt->second.find(name);
if (nt == tt->second.end())
return DynamicObject::Ptr();
return nt->second;
}
pair<DynamicObject::TypeMap::iterator, DynamicObject::TypeMap::iterator> DynamicObject::GetTypes(void)
{
return make_pair(GetAllObjects().begin(), GetAllObjects().end());
}
pair<DynamicObject::NameMap::iterator, DynamicObject::NameMap::iterator> DynamicObject::GetObjects(const String& type)
{
pair<DynamicObject::TypeMap::iterator, bool> ti;
ti = GetAllObjects().insert(make_pair(type, DynamicObject::NameMap()));
return make_pair(ti.first->second.begin(), ti.first->second.end());
}
ScriptTask::Ptr DynamicObject::InvokeMethod(const String& method,
const vector<Value>& arguments, ScriptTask::CompletionCallback callback)
{
@ -370,12 +332,10 @@ void DynamicObject::DumpObjects(const String& filename)
StdioStream::Ptr sfp = boost::make_shared<StdioStream>(&fp, false);
sfp->Start();
DynamicObject::TypeMap::iterator tt;
for (tt = GetAllObjects().begin(); tt != GetAllObjects().end(); tt++) {
DynamicObject::NameMap::iterator nt;
for (nt = tt->second.begin(); nt != tt->second.end(); nt++) {
DynamicObject::Ptr object = nt->second;
DynamicType::Ptr type;
BOOST_FOREACH(tie(tuples::ignore, type), DynamicType::GetTypes()) {
DynamicObject::Ptr object;
BOOST_FOREACH(tie(tuples::ignore, object), type->GetObjects()) {
if (object->IsLocal())
continue;
@ -449,10 +409,15 @@ void DynamicObject::RestoreObjects(const String& filename)
bool hasConfig = update->Contains("configTx");
DynamicObject::Ptr object = GetObject(type, name);
DynamicType::Ptr dt = DynamicType::GetByName(type);
if (!dt)
throw_exception(invalid_argument("Invalid type: " + type));
DynamicObject::Ptr object = dt->GetObject(name);
if (hasConfig && !object) {
object = Create(type, update);
object = dt->CreateObject(update);
object->Register();
} else if (object) {
object->ApplyUpdate(update, Attribute_All);
@ -464,11 +429,11 @@ void DynamicObject::RestoreObjects(const String& filename)
void DynamicObject::DeactivateObjects(void)
{
DynamicObject::TypeMap::iterator tt;
for (tt = GetAllObjects().begin(); tt != GetAllObjects().end(); tt++) {
DynamicObject::NameMap::iterator nt;
DynamicType::TypeMap::iterator tt;
for (tt = DynamicType::GetTypes().begin(); tt != DynamicType::GetTypes().end(); tt++) {
DynamicType::NameMap::iterator nt;
while ((nt = tt->second.begin()) != tt->second.end()) {
while ((nt = tt->second->GetObjects().begin()) != tt->second->GetObjects().end()) {
DynamicObject::Ptr object = nt->second;
object->Unregister();
@ -476,52 +441,6 @@ void DynamicObject::DeactivateObjects(void)
}
}
DynamicObject::TypeMap& DynamicObject::GetAllObjects(void)
{
static TypeMap objects;
return objects;
}
DynamicObject::ClassMap& DynamicObject::GetClasses(void)
{
static ClassMap classes;
return classes;
}
bool DynamicObject::ClassExists(const String& name)
{
return (GetClasses().find(name) != GetClasses().end());
}
void DynamicObject::RegisterClass(const String& type, DynamicObject::Factory factory)
{
if (GetObjects(type).first != GetObjects(type).second)
throw_exception(runtime_error("Cannot register class for type '" +
type + "': Objects of this type already exist."));
GetClasses()[type] = factory;
}
DynamicObject::Ptr DynamicObject::Create(const String& type, const Dictionary::Ptr& serializedUpdate)
{
DynamicObject::ClassMap::iterator ct;
ct = GetClasses().find(type);
DynamicObject::Ptr obj;
if (ct != GetClasses().end()) {
obj = ct->second(serializedUpdate);
} else {
obj = boost::make_shared<DynamicObject>(serializedUpdate);
Logger::Write(LogCritical, "base", "Creating generic DynamicObject for type '" + type + "'");
}
/* apply the object's non-config attributes */
obj->ApplyUpdate(serializedUpdate, Attribute_All & ~Attribute_Config);
return obj;
}
double DynamicObject::GetCurrentTx(void)
{
assert(m_CurrentTx != 0);
@ -545,3 +464,8 @@ void DynamicObject::FinishTx(void)
void DynamicObject::OnAttributeChanged(const String&, const Value&)
{ }
DynamicObject::Ptr DynamicObject::GetObject(const String& type, const String& name)
{
DynamicType::Ptr dtype = DynamicType::GetByName(type);
return dtype->GetObject(name);
}

View File

@ -60,6 +60,8 @@ struct DynamicAttribute
double Tx; /**< The timestamp of the last value change. */
};
class DynamicType;
/**
* A dynamic object that can be instantiated from the configuration file
* and that supports attribute replication to remote application instances.
@ -72,12 +74,6 @@ public:
typedef shared_ptr<DynamicObject> Ptr;
typedef weak_ptr<DynamicObject> WeakPtr;
typedef function<DynamicObject::Ptr (const Dictionary::Ptr&)> Factory;
typedef map<String, Factory, string_iless> ClassMap;
typedef map<String, DynamicObject::Ptr, string_iless> NameMap;
typedef map<String, NameMap, string_iless> TypeMap;
typedef map<String, DynamicAttribute, string_iless> AttributeMap;
typedef AttributeMap::iterator AttributeIterator;
typedef AttributeMap::const_iterator AttributeConstIterator;
@ -104,7 +100,7 @@ public:
ScriptTask::Ptr InvokeMethod(const String& method,
const vector<Value>& arguments, ScriptTask::CompletionCallback callback);
String GetType(void) const;
shared_ptr<DynamicType> GetType(void) const;
String GetName(void) const;
bool IsLocal(void) const;
@ -122,17 +118,11 @@ public:
virtual void Start(void);
static DynamicObject::Ptr GetObject(const String& type, const String& name);
static pair<TypeMap::iterator, TypeMap::iterator> GetTypes(void);
static pair<NameMap::iterator, NameMap::iterator> GetObjects(const String& type);
static void DumpObjects(const String& filename);
static void RestoreObjects(const String& filename);
static void DeactivateObjects(void);
static void RegisterClass(const String& type, Factory factory);
static bool ClassExists(const String& type);
static DynamicObject::Ptr Create(const String& type, const Dictionary::Ptr& serializedUpdate);
static double GetCurrentTx(void);
static void BeginTx(void);
static void FinishTx(void);
@ -144,9 +134,6 @@ private:
void InternalSetAttribute(const String& name, const Value& data, double tx, bool suppressEvent = false);
Value InternalGetAttribute(const String& name) const;
static ClassMap& GetClasses(void);
static TypeMap& GetAllObjects(void);
AttributeMap m_Attributes;
double m_ConfigTx;
@ -157,38 +144,6 @@ private:
void InternalApplyUpdate(const Dictionary::Ptr& serializedUpdate, int allowedTypes, bool suppressEvents);
};
/**
* Helper class for registering DynamicObject implementation classes.
*
* @ingroup base
*/
class RegisterClassHelper
{
public:
RegisterClassHelper(const String& name, DynamicObject::Factory factory)
{
if (!DynamicObject::ClassExists(name))
DynamicObject::RegisterClass(name, factory);
}
};
/**
* Factory function for DynamicObject-based classes.
*
* @ingroup base
*/
template<typename T>
shared_ptr<T> DynamicObjectFactory(const Dictionary::Ptr& serializedUpdate)
{
return boost::make_shared<T>(serializedUpdate);
}
#define REGISTER_CLASS_ALIAS(klass, alias) \
static RegisterClassHelper g_Register ## klass(alias, DynamicObjectFactory<klass>)
#define REGISTER_CLASS(klass) \
REGISTER_CLASS_ALIAS(klass, #klass)
}
#endif /* DYNAMICOBJECT_H */

118
lib/base/dynamictype.cpp Normal file
View File

@ -0,0 +1,118 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#include "i2-base.h"
using namespace icinga;
DynamicType::DynamicType(const String& name, const DynamicType::ObjectFactory& factory)
: m_Name(name), m_ObjectFactory(factory)
{ }
DynamicType::Ptr DynamicType::GetByName(const String& name)
{
DynamicType::TypeMap::const_iterator tt = GetTypes().find(name);
if (tt == GetTypes().end())
return DynamicType::Ptr();
return tt->second;
}
DynamicType::TypeMap& DynamicType::GetTypes(void)
{
static DynamicType::TypeMap types;
return types;
}
DynamicType::NameMap& DynamicType::GetObjects(void)
{
return m_Objects;
}
String DynamicType::GetName(void) const
{
return m_Name;
}
void DynamicType::RegisterObject(const DynamicObject::Ptr& object)
{
m_Objects[object->GetName()] = object;
}
void DynamicType::UnregisterObject(const DynamicObject::Ptr& object)
{
m_Objects.erase(object->GetName());
}
DynamicObject::Ptr DynamicType::GetObject(const String& name) const
{
DynamicType::NameMap::const_iterator nt = m_Objects.find(name);
if (nt == m_Objects.end())
return DynamicObject::Ptr();
return nt->second;
}
void DynamicType::RegisterType(const DynamicType::Ptr& type)
{
if (GetByName(type->GetName()))
throw_exception(runtime_error("Cannot register class for type '" +
type->GetName() + "': Objects of this type already exist."));
GetTypes()[type->GetName()] = type;
}
DynamicObject::Ptr DynamicType::CreateObject(const Dictionary::Ptr& serializedUpdate) const
{
DynamicObject::Ptr obj = m_ObjectFactory(serializedUpdate);
/* register attributes */
String name;
DynamicAttributeType type;
BOOST_FOREACH(tuples::tie(name, type), m_Attributes)
obj->RegisterAttribute(name, type);
/* apply the object's non-config attributes */
obj->ApplyUpdate(serializedUpdate, Attribute_All & ~Attribute_Config);
return obj;
}
bool DynamicType::TypeExists(const String& name)
{
return (GetByName(name));
}
void DynamicType::AddAttribute(const String& name, DynamicAttributeType type)
{
m_Attributes[name] = type;
}
void DynamicType::RemoveAttribute(const String& name)
{
m_Attributes.erase(name);
}
void DynamicType::AddAttributes(const AttributeDescription *attributes, int attributeCount)
{
for (int i = 0; i < attributeCount; i++)
AddAttribute(attributes[i].Name, attributes[i].Type);
}

110
lib/base/dynamictype.h Normal file
View File

@ -0,0 +1,110 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#ifndef DYNAMICTYPE_H
#define DYNAMICTYPE_H
namespace icinga
{
struct AttributeDescription
{
String Name;
DynamicAttributeType Type;
};
class I2_BASE_API DynamicType : public Object
{
public:
typedef shared_ptr<DynamicType> Ptr;
typedef weak_ptr<DynamicType> WeakPtr;
typedef function<DynamicObject::Ptr (const Dictionary::Ptr&)> ObjectFactory;
typedef map<String, DynamicType::Ptr, string_iless> TypeMap;
typedef map<String, DynamicObject::Ptr, string_iless> NameMap;
DynamicType(const String& name, const ObjectFactory& factory);
String GetName(void) const;
static DynamicType::Ptr GetByName(const String& name);
static void RegisterType(const DynamicType::Ptr& type);
static bool TypeExists(const String& name);
DynamicObject::Ptr CreateObject(const Dictionary::Ptr& serializedUpdate) const;
DynamicObject::Ptr GetObject(const String& name) const;
void RegisterObject(const DynamicObject::Ptr& object);
void UnregisterObject(const DynamicObject::Ptr& object);
static TypeMap& GetTypes(void);
NameMap& GetObjects(void);
void AddAttribute(const String& name, DynamicAttributeType type);
void RemoveAttribute(const String& name);
void AddAttributes(const AttributeDescription *attributes, int attributeCount);
private:
String m_Name;
ObjectFactory m_ObjectFactory;
map<String, DynamicAttributeType> m_Attributes;
NameMap m_Objects;
};
/**
* Helper class for registering DynamicObject implementation classes.
*
* @ingroup base
*/
class RegisterTypeHelper
{
public:
RegisterTypeHelper(const String& name, const DynamicType::ObjectFactory& factory, const AttributeDescription* attributes, int attributeCount)
{
if (!DynamicType::TypeExists(name)) {
DynamicType::Ptr type = boost::make_shared<DynamicType>(name, factory);
type->AddAttributes(attributes, attributeCount);
DynamicType::RegisterType(type);
}
}
};
/**
* Factory function for DynamicObject-based classes.
*
* @ingroup base
*/
template<typename T>
shared_ptr<T> DynamicObjectFactory(const Dictionary::Ptr& serializedUpdate)
{
return boost::make_shared<T>(serializedUpdate);
}
#define REGISTER_TYPE_ALIAS(type, alias, attributeDesc) \
static RegisterTypeHelper g_Register ## type(alias, DynamicObjectFactory<type>, attributeDesc, (attributeDesc == NULL) ? 0 : sizeof(attributeDesc) / sizeof((static_cast<AttributeDescription *>(attributeDesc))[0]))
#define REGISTER_TYPE(type, attributeDesc) \
REGISTER_TYPE_ALIAS(type, #type, attributeDesc)
}
#endif /* DYNAMICTYPE_H */

View File

@ -192,6 +192,7 @@ namespace tuples = boost::tuples;
#include "scriptfunction.h"
#include "scripttask.h"
#include "dynamicobject.h"
#include "dynamictype.h"
#include "logger.h"
#include "application.h"
#include "component.h"

View File

@ -21,7 +21,13 @@
using namespace icinga;
REGISTER_CLASS(Logger);
static AttributeDescription loggerAttributes[] = {
{ "type", Attribute_Config },
{ "path", Attribute_Config },
{ "severity", Attribute_Config }
};
REGISTER_TYPE(Logger, loggerAttributes);
/**
* Constructor for the Logger class.
@ -31,10 +37,6 @@ REGISTER_CLASS(Logger);
Logger::Logger(const Dictionary::Ptr& properties)
: DynamicObject(properties)
{
RegisterAttribute("type", Attribute_Config);
RegisterAttribute("path", Attribute_Config);
RegisterAttribute("severity", Attribute_Config);
if (!IsLocal())
throw_exception(runtime_error("Logger objects must be local."));
@ -111,8 +113,10 @@ void Logger::ForwardLogEntry(const LogEntry& entry)
{
bool processed = false;
DynamicType::Ptr dt = DynamicType::GetByName("Logger");
DynamicObject::Ptr object;
BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Logger")) {
BOOST_FOREACH(tie(tuples::ignore, object), dt->GetObjects()) {
Logger::Ptr logger = dynamic_pointer_cast<Logger>(object);
if (entry.Severity >= logger->GetMinSeverity())

View File

@ -21,20 +21,14 @@
using namespace icinga;
boost::mutex Object::m_Mutex;
vector<Object::Ptr> Object::m_HeldObjects;
#ifdef _DEBUG
set<Object *> Object::m_AliveObjects;
#endif /* _DEBUG */
/**
* Default constructor for the Object class.
*/
Object::Object(void)
{
#ifdef _DEBUG
boost::mutex::scoped_lock lock(m_Mutex);
m_AliveObjects.insert(this);
boost::mutex::scoped_lock lock(GetMutex());
GetAliveObjects().insert(this);
#endif /* _DEBUG */
}
@ -44,8 +38,8 @@ Object::Object(void)
Object::~Object(void)
{
#ifdef _DEBUG
boost::mutex::scoped_lock lock(m_Mutex);
m_AliveObjects.erase(this);
boost::mutex::scoped_lock lock(GetMutex());
GetAliveObjects().erase(this);
#endif /* _DEBUG */
}
@ -56,8 +50,8 @@ Object::~Object(void)
*/
void Object::Hold(void)
{
boost::mutex::scoped_lock lock(m_Mutex);
m_HeldObjects.push_back(GetSelf());
boost::mutex::scoped_lock lock(GetMutex());
GetHeldObjects().push_back(GetSelf());
}
/**
@ -65,8 +59,8 @@ void Object::Hold(void)
*/
void Object::ClearHeldObjects(void)
{
boost::mutex::scoped_lock lock(m_Mutex);
m_HeldObjects.clear();
boost::mutex::scoped_lock lock(GetMutex());
GetHeldObjects().clear();
}
/**
@ -85,10 +79,10 @@ Object::SharedPtrHolder Object::GetSelf(void)
*
* @returns The number of alive objects.
*/
int Object::GetAliveObjects(void)
int Object::GetAliveObjectsCount(void)
{
boost::mutex::scoped_lock lock(m_Mutex);
return m_AliveObjects.size();
boost::mutex::scoped_lock lock(GetMutex());
return GetAliveObjects().size();
}
/**
@ -101,9 +95,9 @@ void Object::PrintMemoryProfile(void)
ofstream dictfp("dictionaries.dump.tmp");
{
boost::mutex::scoped_lock lock(m_Mutex);
boost::mutex::scoped_lock lock(GetMutex());
set<Object *>::iterator it;
BOOST_FOREACH(Object *obj, m_AliveObjects) {
BOOST_FOREACH(Object *obj, GetAliveObjects()) {
pair<map<String, int>::iterator, bool> tt;
tt = types.insert(make_pair(Utility::GetTypeName(typeid(*obj)), 1));
if (!tt.second)
@ -130,4 +124,40 @@ void Object::PrintMemoryProfile(void)
std::cerr << type << ": " << count << std::endl;
}
}
/**
* Returns currently active objects.
*
* @returns currently active objects
*/
set<Object *>& Object::GetAliveObjects(void)
{
static set<Object *> aliveObjects;
return aliveObjects;
}
#endif /* _DEBUG */
/**
* Returns the mutex used for accessing static members.
*
* @returns a mutex
*/
boost::mutex& Object::GetMutex(void)
{
static boost::mutex mutex;
return mutex;
}
/**
* Returns currently held objects. The caller must be
* holding the mutex returned by GetMutex().
*
* @returns currently held objects
*/
vector<Object::Ptr>& Object::GetHeldObjects(void)
{
static vector<Object::Ptr> heldObjects;
return heldObjects;
}

View File

@ -97,7 +97,7 @@ public:
SharedPtrHolder GetSelf(void);
#ifdef _DEBUG
static int GetAliveObjects(void);
static int GetAliveObjectsCount(void);
static void PrintMemoryProfile(void);
#endif /* _DEBUG */
@ -109,14 +109,9 @@ private:
Object(const Object& other);
Object& operator=(const Object& rhs);
static boost::mutex m_Mutex; /**< Mutex which protects static members
of the Object class. */
static vector<Object::Ptr> m_HeldObjects; /**< Currently held
objects. */
#ifdef _DEBUG
static set<Object *> m_AliveObjects; /**< Currently alive objects -
for debugging purposes. */
#endif /* _DEBUG */
static boost::mutex& GetMutex(void);
static set<Object *>& GetAliveObjects(void);
static vector<Object::Ptr>& GetHeldObjects(void);
};
/**

View File

@ -37,6 +37,9 @@ Socket::Socket(void)
*/
Socket::~Socket(void)
{
m_SendQueue->Close();
m_RecvQueue->Close();
Close();
}

View File

@ -215,6 +215,9 @@ void TlsStream::Close(void)
if (m_SSL)
SSL_shutdown(m_SSL.get());
m_SendQueue->Close();
m_RecvQueue->Close();
Stream::Close();
}

View File

@ -148,11 +148,13 @@ DynamicObject::Ptr ConfigItem::Commit(void)
update->Set("attrs", attrs);
update->Set("configTx", DynamicObject::GetCurrentTx());
if (!dobj)
dobj = DynamicObject::GetObject(GetType(), GetName());
DynamicType::Ptr dtype = DynamicType::GetByName(GetType());
if (!dobj)
dobj = DynamicObject::Create(GetType(), update);
dobj = dtype->GetObject(GetName());
if (!dobj)
dobj = dtype->CreateObject(update);
else
dobj->ApplyUpdate(update, Attribute_Config);

View File

@ -21,7 +21,12 @@
using namespace icinga;
REGISTER_CLASS(Host);
static AttributeDescription hostAttributes[] = {
{ "alias", Attribute_Config },
{ "hostgroups", Attribute_Config }
};
REGISTER_TYPE(Host, hostAttributes);
bool Host::m_InitializerDone = false;
@ -34,9 +39,6 @@ Host::Host(const Dictionary::Ptr& properties)
m_InitializerDone = true;
}
RegisterAttribute("alias", Attribute_Config);
RegisterAttribute("hostgroups", Attribute_Config);
}
String Host::GetAlias(void) const

View File

@ -21,7 +21,13 @@
using namespace icinga;
REGISTER_CLASS(HostGroup);
static AttributeDescription hostGroupAttributes[] = {
{ "alias", Attribute_Config },
{ "notes_url", Attribute_Config },
{ "action_url", Attribute_Config }
};
REGISTER_TYPE(HostGroup, hostGroupAttributes);
String HostGroup::GetAlias(void) const
{

View File

@ -21,13 +21,25 @@
#include <iostream>
#include "i2-icinga.h"
using namespace icinga;
static AttributeDescription icingaApplicationAttributes[] = {
{ "cert_path", Attribute_Config },
{ "ca_path", Attribute_Config },
{ "node", Attribute_Config },
{ "service", Attribute_Config },
{ "pid_path", Attribute_Config },
{ "state_path", Attribute_Config },
{ "macros", Attribute_Config }
};
REGISTER_TYPE(IcingaApplication, icingaApplicationAttributes);
#ifndef _WIN32
# include "icinga-version.h"
# define ICINGA_VERSION GIT_MESSAGE
#endif /* _WIN32 */
using namespace icinga;
const String IcingaApplication::DefaultPidPath = "icinga2.pid";
const String IcingaApplication::DefaultStatePath = "icinga2.state";

View File

@ -64,8 +64,6 @@ private:
void DumpProgramState(void);
};
REGISTER_CLASS(IcingaApplication);
}
#endif /* ICINGAAPPLICATION_H */

View File

@ -21,7 +21,30 @@
using namespace icinga;
REGISTER_CLASS(Service);
static AttributeDescription serviceAttributes[] = {
{ "alias", Attribute_Config },
{ "host_name", Attribute_Config },
{ "macros", Attribute_Config },
{ "check_command", Attribute_Config },
{ "max_check_attempts", Attribute_Config },
{ "check_interval", Attribute_Config },
{ "retry_interval", Attribute_Config },
{ "dependencies", Attribute_Config },
{ "servicegroups", Attribute_Config },
{ "checkers", Attribute_Config },
{ "scheduling_offset", Attribute_Transient },
{ "next_check", Attribute_Replicated },
{ "checker", Attribute_Replicated },
{ "check_attempt", Attribute_Replicated },
{ "state", Attribute_Replicated },
{ "state_type", Attribute_Replicated },
{ "last_result", Attribute_Replicated },
{ "last_state_change", Attribute_Replicated },
{ "last_hard_state_change", Attribute_Replicated }
};
REGISTER_TYPE(Service, serviceAttributes);
const int Service::DefaultMaxCheckAttempts = 3;
const int Service::DefaultCheckInterval = 5 * 60;
@ -33,28 +56,7 @@ boost::signal<void (const Service::Ptr&, const String&)> Service::OnCheckerChang
Service::Service(const Dictionary::Ptr& serializedObject)
: DynamicObject(serializedObject)
{
RegisterAttribute("alias", Attribute_Config);
RegisterAttribute("host_name", Attribute_Config);
RegisterAttribute("macros", Attribute_Config);
RegisterAttribute("check_command", Attribute_Config);
RegisterAttribute("max_check_attempts", Attribute_Config);
RegisterAttribute("check_interval", Attribute_Config);
RegisterAttribute("retry_interval", Attribute_Config);
RegisterAttribute("dependencies", Attribute_Config);
RegisterAttribute("servicegroups", Attribute_Config);
RegisterAttribute("checkers", Attribute_Config);
RegisterAttribute("scheduling_offset", Attribute_Transient);
RegisterAttribute("next_check", Attribute_Replicated);
RegisterAttribute("checker", Attribute_Replicated);
RegisterAttribute("check_attempt", Attribute_Replicated);
RegisterAttribute("state", Attribute_Replicated);
RegisterAttribute("state_type", Attribute_Replicated);
RegisterAttribute("last_result", Attribute_Replicated);
RegisterAttribute("last_state_change", Attribute_Replicated);
RegisterAttribute("last_hard_state_change", Attribute_Replicated);
}
{ }
String Service::GetAlias(void) const
{

View File

@ -21,7 +21,13 @@
using namespace icinga;
REGISTER_CLASS(ServiceGroup);
static AttributeDescription serviceGroupAttributes[] = {
{ "alias", Attribute_Config },
{ "notes_url", Attribute_Config },
{ "action_url", Attribute_Config }
};
REGISTER_TYPE(ServiceGroup, serviceGroupAttributes);
String ServiceGroup::GetAlias(void) const
{

View File

@ -21,7 +21,15 @@
using namespace icinga;
REGISTER_CLASS(Endpoint);
static AttributeDescription endpointAttributes[] = {
{ "node", Attribute_Replicated },
{ "service", Attribute_Replicated },
{ "local", Attribute_Config },
{ "subscriptions", Attribute_Replicated },
{ "client", Attribute_Transient }
};
REGISTER_TYPE(Endpoint, endpointAttributes);
boost::signal<void (const Endpoint::Ptr&)> Endpoint::OnConnected;
boost::signal<void (const Endpoint::Ptr&)> Endpoint::OnDisconnected;
@ -35,13 +43,7 @@ boost::signal<void (const Endpoint::Ptr&, const String& topic)> Endpoint::OnSubs
*/
Endpoint::Endpoint(const Dictionary::Ptr& serializedUpdate)
: DynamicObject(serializedUpdate)
{
RegisterAttribute("node", Attribute_Replicated);
RegisterAttribute("service", Attribute_Replicated);
RegisterAttribute("local", Attribute_Config);
RegisterAttribute("subscriptions", Attribute_Replicated);
RegisterAttribute("client", Attribute_Transient);
}
{ }
/**
* Checks whether an endpoint with the specified name exists.

View File

@ -151,6 +151,7 @@ void EndpointManager::NewClientHandler(const Socket::Ptr& client, TlsRole role)
m_PendingClients.insert(tlsStream);
tlsStream->OnConnected.connect(boost::bind(&EndpointManager::ClientConnectedHandler, this, _1, peerAddress));
tlsStream->OnClosed.connect(boost::bind(&EndpointManager::ClientClosedHandler, this, _1));
client->Start();
}
@ -177,6 +178,12 @@ void EndpointManager::ClientConnectedHandler(const Stream::Ptr& client, const St
endpoint->SetClient(jclient);
}
void EndpointManager::ClientClosedHandler(const Stream::Ptr& client)
{
TlsStream::Ptr tlsStream = static_pointer_cast<TlsStream>(client);
m_PendingClients.erase(tlsStream);
}
/**
* Sends a unicast message to the specified recipient.
*
@ -213,7 +220,7 @@ void EndpointManager::SendAnycastMessage(const Endpoint::Ptr& sender,
vector<Endpoint::Ptr> candidates;
DynamicObject::Ptr object;
BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Endpoint")) {
BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Endpoint")->GetObjects()) {
Endpoint::Ptr endpoint = dynamic_pointer_cast<Endpoint>(object);
/* don't forward messages between non-local endpoints */
if (!sender->IsLocal() && !endpoint->IsLocal())
@ -249,7 +256,7 @@ void EndpointManager::SendMulticastMessage(const Endpoint::Ptr& sender,
throw_exception(invalid_argument("Message is missing the 'method' property."));
DynamicObject::Ptr object;
BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Endpoint")) {
BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Endpoint")->GetObjects()) {
Endpoint::Ptr recipient = dynamic_pointer_cast<Endpoint>(object);
/* don't forward messages back to the sender */
@ -297,7 +304,7 @@ void EndpointManager::SubscriptionTimerHandler(void)
Dictionary::Ptr subscriptions = boost::make_shared<Dictionary>();
DynamicObject::Ptr object;
BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Endpoint")) {
BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Endpoint")->GetObjects()) {
Endpoint::Ptr endpoint = dynamic_pointer_cast<Endpoint>(object);
if (!endpoint->IsLocalEndpoint())
@ -316,7 +323,7 @@ void EndpointManager::SubscriptionTimerHandler(void)
void EndpointManager::ReconnectTimerHandler(void)
{
DynamicObject::Ptr object;
BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Endpoint")) {
BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Endpoint")->GetObjects()) {
Endpoint::Ptr endpoint = dynamic_pointer_cast<Endpoint>(object);
if (endpoint->IsConnected() || endpoint == m_Endpoint)

View File

@ -103,6 +103,7 @@ private:
void NewClientHandler(const Socket::Ptr& client, TlsRole rol);
void ClientConnectedHandler(const Stream::Ptr& client, const String& peerAddress);
void ClientClosedHandler(const Stream::Ptr& client);
};
}