mirror of https://github.com/Icinga/icinga2.git
Implement support for tracking dependencies between config objects
refs #9096
This commit is contained in:
parent
7eca257784
commit
f45f6ccd82
|
@ -26,7 +26,7 @@ set(base_SOURCES
|
|||
application.cpp application.thpp application-version.cpp array.cpp
|
||||
array-script.cpp boolean.cpp boolean-script.cpp console.cpp context.cpp
|
||||
convert.cpp debuginfo.cpp dictionary.cpp dictionary-script.cpp
|
||||
configobject.cpp configobject.thpp configobject-script.cpp configtype.cpp
|
||||
configobject.cpp configobject.thpp configobject-script.cpp configtype.cpp dependencygraph.cpp
|
||||
exception.cpp fifo.cpp filelogger.cpp filelogger.thpp initialize.cpp json.cpp
|
||||
json-script.cpp loader.cpp logger.cpp logger.thpp math-script.cpp
|
||||
netstring.cpp networkstream.cpp number.cpp number-script.cpp object.cpp
|
||||
|
|
|
@ -102,7 +102,7 @@ void Application::Stop(void)
|
|||
} else
|
||||
ClosePidFile(true);
|
||||
|
||||
ConfigObject::Stop();
|
||||
ObjectImpl<Application>::Stop();
|
||||
}
|
||||
|
||||
Application::~Application(void)
|
||||
|
|
|
@ -231,6 +231,8 @@ void ConfigObject::Unregister(void)
|
|||
|
||||
void ConfigObject::Start(void)
|
||||
{
|
||||
ObjectImpl<ConfigObject>::Start();
|
||||
|
||||
ASSERT(!OwnsLock());
|
||||
ObjectLock olock(this);
|
||||
|
||||
|
@ -260,6 +262,8 @@ void ConfigObject::Activate(void)
|
|||
|
||||
void ConfigObject::Stop(void)
|
||||
{
|
||||
ObjectImpl<ConfigObject>::Stop();
|
||||
|
||||
ASSERT(!OwnsLock());
|
||||
ObjectLock olock(this);
|
||||
|
||||
|
@ -501,5 +505,7 @@ void ConfigObject::DumpModifiedAttributes(const boost::function<void(const Confi
|
|||
ConfigObject::Ptr ConfigObject::GetObject(const String& type, const String& name)
|
||||
{
|
||||
ConfigType::Ptr dtype = ConfigType::GetByName(type);
|
||||
if (!dtype)
|
||||
return ConfigObject::Ptr();
|
||||
return dtype->GetObject(name);
|
||||
}
|
||||
|
|
|
@ -64,8 +64,8 @@ public:
|
|||
void Deactivate(void);
|
||||
void SetAuthority(bool authority);
|
||||
|
||||
virtual void Start(void);
|
||||
virtual void Stop(void);
|
||||
virtual void Start(void) override;
|
||||
virtual void Stop(void) override;
|
||||
|
||||
virtual void Pause(void);
|
||||
virtual void Resume(void);
|
||||
|
@ -83,6 +83,8 @@ public:
|
|||
return static_pointer_cast<T>(object);
|
||||
}
|
||||
|
||||
static ConfigObject::Ptr GetObject(const String& type, const String& name);
|
||||
|
||||
static void DumpObjects(const String& filename, int attributeTypes = FAState);
|
||||
static void RestoreObjects(const String& filename, int attributeTypes = FAState);
|
||||
static void StopObjects(void);
|
||||
|
@ -95,7 +97,6 @@ protected:
|
|||
explicit ConfigObject(void);
|
||||
|
||||
private:
|
||||
static ConfigObject::Ptr GetObject(const String& type, const String& name);
|
||||
static void RestoreObject(const String& message, int attributeTypes);
|
||||
};
|
||||
|
||||
|
|
|
@ -55,6 +55,12 @@ public:
|
|||
m_DebugInfo = di;
|
||||
}
|
||||
|
||||
inline virtual void Start(void)
|
||||
{ }
|
||||
|
||||
inline virtual void Stop(void)
|
||||
{ }
|
||||
|
||||
private:
|
||||
DebugInfo m_DebugInfo;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/******************************************************************************
|
||||
* Icinga 2 *
|
||||
* Copyright (C) 2012-2015 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 "base/dependencygraph.hpp"
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
boost::mutex DependencyGraph::m_Mutex;
|
||||
std::map<Object *, std::map<Object *, int> > DependencyGraph::m_Dependencies;
|
||||
|
||||
void DependencyGraph::AddDependency(Object *parent, Object *child)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_Mutex);
|
||||
m_Dependencies[child][parent]++;
|
||||
}
|
||||
|
||||
void DependencyGraph::RemoveDependency(Object *parent, Object *child)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_Mutex);
|
||||
m_Dependencies[child][parent]--;
|
||||
}
|
||||
|
||||
std::vector<Object::Ptr> DependencyGraph::GetParents(const Object::Ptr& child)
|
||||
{
|
||||
std::vector<Object::Ptr> objects;
|
||||
|
||||
boost::mutex::scoped_lock lock(m_Mutex);
|
||||
std::map<Object *, std::map<Object *, int> >::const_iterator it = m_Dependencies.find(child.get());
|
||||
|
||||
if (it != m_Dependencies.end()) {
|
||||
typedef std::pair<Object *, int> kv_pair;
|
||||
BOOST_FOREACH(const kv_pair& kv, it->second) {
|
||||
objects.push_back(kv.first);
|
||||
}
|
||||
}
|
||||
|
||||
return objects;
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/******************************************************************************
|
||||
* Icinga 2 *
|
||||
* Copyright (C) 2012-2015 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 DEPENDENCYGRAPH_H
|
||||
#define DEPENDENCYGRAPH_H
|
||||
|
||||
#include "base/i2-base.hpp"
|
||||
#include "base/object.hpp"
|
||||
#include <map>
|
||||
|
||||
namespace icinga {
|
||||
|
||||
/**
|
||||
* A graph that tracks dependencies between objects.
|
||||
*
|
||||
* @ingroup base
|
||||
*/
|
||||
class I2_BASE_API DependencyGraph
|
||||
{
|
||||
public:
|
||||
static void AddDependency(Object *parent, Object *child);
|
||||
static void RemoveDependency(Object *parent, Object *child);
|
||||
static std::vector<Object::Ptr> GetParents(const Object::Ptr& child);
|
||||
|
||||
private:
|
||||
DependencyGraph(void);
|
||||
|
||||
static boost::mutex m_Mutex;
|
||||
static std::map<Object *, std::map<Object *, int> > m_Dependencies;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* DEPENDENCYGRAPH_H */
|
|
@ -46,7 +46,7 @@ void FileLogger::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
|
|||
*/
|
||||
void FileLogger::Start(void)
|
||||
{
|
||||
StreamLogger::Start();
|
||||
ObjectImpl<FileLogger>::Start();
|
||||
|
||||
ReopenLogFile();
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ void Logger::StaticInitialize(void)
|
|||
*/
|
||||
void Logger::Start(void)
|
||||
{
|
||||
ConfigObject::Start();
|
||||
ObjectImpl<Logger>::Start();
|
||||
|
||||
boost::mutex::scoped_lock lock(m_Mutex);
|
||||
m_Loggers.insert(this);
|
||||
|
@ -67,7 +67,7 @@ void Logger::Stop(void)
|
|||
m_Loggers.erase(this);
|
||||
}
|
||||
|
||||
ConfigObject::Stop();
|
||||
ObjectImpl<Logger>::Stop();
|
||||
}
|
||||
|
||||
std::set<Logger::Ptr> Logger::GetLoggers(void)
|
||||
|
|
|
@ -92,6 +92,11 @@ Value Object::GetField(int id) const
|
|||
BOOST_THROW_EXCEPTION(std::runtime_error("Invalid field ID."));
|
||||
}
|
||||
|
||||
void Object::Validate(int types, const ValidationUtils& utils)
|
||||
{
|
||||
/* Nothing to do here. */
|
||||
}
|
||||
|
||||
void Object::ValidateField(int id, const Value& value, const ValidationUtils& utils)
|
||||
{
|
||||
/* Nothing to do here. */
|
||||
|
|
|
@ -103,6 +103,8 @@ public:
|
|||
|
||||
virtual intrusive_ptr<Type> GetReflectionType(void) const;
|
||||
|
||||
virtual void Validate(int types, const ValidationUtils& utils);
|
||||
|
||||
virtual void SetField(int id, const Value& value, bool suppress_events = false, const Value& cookie = Empty);
|
||||
virtual Value GetField(int id) const;
|
||||
virtual void ValidateField(int id, const Value& value, const ValidationUtils& utils);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "base/objectlock.hpp"
|
||||
#include "base/configtype.hpp"
|
||||
#include "base/application.hpp"
|
||||
#include "base/dependencygraph.hpp"
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <algorithm>
|
||||
|
@ -57,6 +58,7 @@ REGISTER_SAFE_SCRIPTFUNCTION(get_time, &Utility::GetTime);
|
|||
REGISTER_SAFE_SCRIPTFUNCTION(basename, &Utility::BaseName);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(dirname, &Utility::DirName);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(msi_get_component_path, &ScriptUtils::MsiGetComponentPathShim);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(track_parents, &ScriptUtils::TrackParents);
|
||||
|
||||
String ScriptUtils::CastString(const Value& value)
|
||||
{
|
||||
|
@ -304,3 +306,9 @@ String ScriptUtils::MsiGetComponentPathShim(const String& component)
|
|||
return String();
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
|
||||
Array::Ptr ScriptUtils::TrackParents(const Object::Ptr& child)
|
||||
{
|
||||
return Array::FromVector(DependencyGraph::GetParents(child));
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ public:
|
|||
static Array::Ptr GetObjects(const Type::Ptr& type);
|
||||
static void Assert(const Value& arg);
|
||||
static String MsiGetComponentPathShim(const String& component);
|
||||
static Array::Ptr TrackParents(const Object::Ptr& parent);
|
||||
|
||||
private:
|
||||
ScriptUtils(void);
|
||||
|
|
|
@ -39,7 +39,7 @@ StreamLogger::StreamLogger(void)
|
|||
|
||||
void StreamLogger::Stop(void)
|
||||
{
|
||||
Logger::Stop();
|
||||
ObjectImpl<StreamLogger>::Stop();
|
||||
|
||||
// make sure we flush the log data on shutdown, even if we don't call the destructor
|
||||
if (m_Stream)
|
||||
|
|
|
@ -159,9 +159,9 @@ int TypeType::GetFieldId(const String& name) const
|
|||
Field TypeType::GetFieldInfo(int id) const
|
||||
{
|
||||
if (id == 0)
|
||||
return Field(0, "Object", "prototype", NULL, 0);
|
||||
return Field(0, "Object", "prototype", NULL, 0, 0);
|
||||
else if (id == 1)
|
||||
return Field(1, "Object", "base", NULL, 0);
|
||||
return Field(1, "Object", "base", NULL, 0, 0);
|
||||
|
||||
throw std::runtime_error("Invalid field ID.");
|
||||
}
|
||||
|
|
|
@ -49,9 +49,10 @@ struct Field
|
|||
const char *Name;
|
||||
const char *RefTypeName;
|
||||
int Attributes;
|
||||
int ArrayRank;
|
||||
|
||||
Field(int id, const char *type, const char *name, const char *reftype, int attributes)
|
||||
: ID(id), TypeName(type), Name(name), RefTypeName(reftype), Attributes(attributes)
|
||||
Field(int id, const char *type, const char *name, const char *reftype, int attributes, int arrayRank)
|
||||
: ID(id), TypeName(type), Name(name), RefTypeName(reftype), Attributes(attributes), ArrayRank(arrayRank)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ void CheckerComponent::OnConfigLoaded(void)
|
|||
|
||||
void CheckerComponent::Start(void)
|
||||
{
|
||||
ConfigObject::Start();
|
||||
ObjectImpl<CheckerComponent>::Start();
|
||||
|
||||
m_Thread = boost::thread(boost::bind(&CheckerComponent::CheckThreadProc, this));
|
||||
|
||||
|
@ -97,7 +97,7 @@ void CheckerComponent::Stop(void)
|
|||
m_ResultTimer->Stop();
|
||||
m_Thread.join();
|
||||
|
||||
ConfigObject::Stop();
|
||||
ObjectImpl<CheckerComponent>::Stop();
|
||||
}
|
||||
|
||||
void CheckerComponent::CheckThreadProc(void)
|
||||
|
|
|
@ -59,7 +59,7 @@ void CompatLogger::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
|
|||
*/
|
||||
void CompatLogger::Start(void)
|
||||
{
|
||||
ConfigObject::Start();
|
||||
ObjectImpl<CompatLogger>::Start();
|
||||
|
||||
Checkable::OnNewCheckResult.connect(bind(&CompatLogger::CheckResultHandler, this, _1, _2));
|
||||
Checkable::OnNotificationSentToUser.connect(bind(&CompatLogger::NotificationSentHandler, this, _1, _2, _3, _4, _5, _6, _7, _8));
|
||||
|
|
|
@ -48,7 +48,7 @@ void ExternalCommandListener::StatsFunc(const Dictionary::Ptr& status, const Arr
|
|||
*/
|
||||
void ExternalCommandListener::Start(void)
|
||||
{
|
||||
ConfigObject::Start();
|
||||
ObjectImpl<ExternalCommandListener>::Start();
|
||||
|
||||
#ifndef _WIN32
|
||||
m_CommandThread = boost::thread(boost::bind(&ExternalCommandListener::CommandPipeThread, this, GetCommandPath()));
|
||||
|
|
|
@ -72,7 +72,7 @@ void StatusDataWriter::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr
|
|||
*/
|
||||
void StatusDataWriter::Start(void)
|
||||
{
|
||||
ConfigObject::Start();
|
||||
ObjectImpl<StatusDataWriter>::Start();
|
||||
|
||||
m_StatusTimer = new Timer();
|
||||
m_StatusTimer->SetInterval(GetUpdateInterval());
|
||||
|
|
|
@ -58,7 +58,7 @@ void DbConnection::OnConfigLoaded(void)
|
|||
|
||||
void DbConnection::Start(void)
|
||||
{
|
||||
ConfigObject::Start();
|
||||
ObjectImpl<DbConnection>::Start();
|
||||
|
||||
DbObject::OnQuery.connect(boost::bind(&DbConnection::ExecuteQuery, this, _1));
|
||||
ConfigObject::OnActiveChanged.connect(boost::bind(&DbConnection::UpdateObject, this, _1));
|
||||
|
|
|
@ -35,7 +35,7 @@ REGISTER_APIFUNCTION(HelloWorld, demo, &Demo::DemoMessageHandler);
|
|||
*/
|
||||
void Demo::Start(void)
|
||||
{
|
||||
ConfigObject::Start();
|
||||
ObjectImpl<Demo>::Start();
|
||||
|
||||
m_DemoTimer = new Timer();
|
||||
m_DemoTimer->SetInterval(5);
|
||||
|
|
|
@ -47,7 +47,7 @@ void Checkable::Start(void)
|
|||
if (GetNextCheck() < now + 300)
|
||||
UpdateNextCheck();
|
||||
|
||||
ConfigObject::Start();
|
||||
ObjectImpl<Checkable>::Start();
|
||||
}
|
||||
|
||||
void Checkable::OnStateLoaded(void)
|
||||
|
|
|
@ -82,7 +82,7 @@ void Dependency::OnConfigLoaded(void)
|
|||
|
||||
void Dependency::OnAllConfigLoaded(void)
|
||||
{
|
||||
ConfigObject::OnAllConfigLoaded();
|
||||
ObjectImpl<Dependency>::OnAllConfigLoaded();
|
||||
|
||||
Host::Ptr childHost = Host::GetByName(GetChildHostName());
|
||||
|
||||
|
@ -125,7 +125,7 @@ void Dependency::OnAllConfigLoaded(void)
|
|||
|
||||
void Dependency::Stop(void)
|
||||
{
|
||||
ConfigObject::Stop();
|
||||
ObjectImpl<Dependency>::Stop();
|
||||
|
||||
GetChild()->RemoveDependency(this);
|
||||
GetParent()->RemoveReverseDependency(this);
|
||||
|
@ -232,3 +232,4 @@ void Dependency::ValidateStates(const Array::Ptr& value, const ValidationUtils&
|
|||
if (!GetParentServiceName().IsEmpty() && (sfilter & ~(StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0)
|
||||
BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("states"), "State filter is invalid for service dependency."));
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "icinga/customvarobject.hpp"
|
||||
#include "icinga/checkable.hpp"
|
||||
#impl_include "icinga/service.hpp"
|
||||
|
||||
library icinga;
|
||||
|
||||
|
@ -40,14 +41,38 @@ class Dependency : CustomVarObject < DependencyNameComposer
|
|||
load_after Service;
|
||||
|
||||
[config, required] name(Host) child_host_name;
|
||||
[config] String child_service_name;
|
||||
[config] String child_service_name {
|
||||
track {{{
|
||||
if (!oldValue.IsEmpty()) {
|
||||
Service::Ptr service = Service::GetByNamePair(GetParentHostName(), oldValue);
|
||||
DependencyGraph::RemoveDependency(this, service.get());
|
||||
}
|
||||
|
||||
if (!newValue.IsEmpty()) {
|
||||
Service::Ptr service = Service::GetByNamePair(GetParentHostName(), newValue);
|
||||
DependencyGraph::RemoveDependency(this, service.get());
|
||||
}
|
||||
}}}
|
||||
};
|
||||
|
||||
[config, required] name(Host) parent_host_name;
|
||||
[config] String parent_service_name;
|
||||
[config] String parent_service_name {
|
||||
track {{{
|
||||
if (!oldValue.IsEmpty()) {
|
||||
Service::Ptr service = Service::GetByNamePair(GetParentHostName(), oldValue);
|
||||
DependencyGraph::RemoveDependency(this, service.get());
|
||||
}
|
||||
|
||||
if (!newValue.IsEmpty()) {
|
||||
Service::Ptr service = Service::GetByNamePair(GetParentHostName(), newValue);
|
||||
DependencyGraph::RemoveDependency(this, service.get());
|
||||
}
|
||||
}}}
|
||||
};
|
||||
|
||||
[config] name(TimePeriod) period (PeriodRaw);
|
||||
|
||||
[config] Array::Ptr states;
|
||||
[config] array(double) states;
|
||||
int state_filter_real (StateFilter);
|
||||
|
||||
[config] bool ignore_soft_states {
|
||||
|
@ -60,10 +85,4 @@ class Dependency : CustomVarObject < DependencyNameComposer
|
|||
};
|
||||
};
|
||||
|
||||
validator Dependency {
|
||||
Array states {
|
||||
Number "*";
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ REGISTER_TYPE(Host);
|
|||
|
||||
void Host::OnAllConfigLoaded(void)
|
||||
{
|
||||
Checkable::OnAllConfigLoaded();
|
||||
ObjectImpl<Host>::OnAllConfigLoaded();
|
||||
|
||||
HostGroup::EvaluateObjectRules(this);
|
||||
|
||||
|
@ -73,7 +73,7 @@ void Host::CreateChildObjects(const Type::Ptr& childType)
|
|||
|
||||
void Host::Stop(void)
|
||||
{
|
||||
Checkable::Stop();
|
||||
ObjectImpl<Host>::Stop();
|
||||
|
||||
Array::Ptr groups = GetGroups();
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace icinga
|
|||
|
||||
class Host : Checkable
|
||||
{
|
||||
[config] Array::Ptr groups {
|
||||
[config] array(name(HostGroup)) groups {
|
||||
default {{{ return new Array(); }}}
|
||||
};
|
||||
|
||||
|
@ -55,10 +55,4 @@ class Host : Checkable
|
|||
|
||||
};
|
||||
|
||||
validator Host {
|
||||
Array groups {
|
||||
name(HostGroup) "*";
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -35,16 +35,10 @@ class HostGroup : CustomVarObject
|
|||
}}}
|
||||
};
|
||||
|
||||
[config] Array::Ptr groups;
|
||||
[config] array(name(HostGroup)) groups;
|
||||
[config] String notes;
|
||||
[config] String notes_url;
|
||||
[config] String action_url;
|
||||
};
|
||||
|
||||
validator HostGroup {
|
||||
Array groups {
|
||||
name(HostGroup) "*";
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ void IcingaStatusWriter::StatsFunc(const Dictionary::Ptr& status, const Array::P
|
|||
*/
|
||||
void IcingaStatusWriter::Start(void)
|
||||
{
|
||||
ConfigObject::Start();
|
||||
ObjectImpl<IcingaStatusWriter>::Start();
|
||||
|
||||
m_StatusTimer = new Timer();
|
||||
m_StatusTimer->SetInterval(GetUpdateInterval());
|
||||
|
|
|
@ -115,7 +115,7 @@ void Notification::OnAllConfigLoaded(void)
|
|||
|
||||
void Notification::Start(void)
|
||||
{
|
||||
ConfigObject::Start();
|
||||
ObjectImpl<Notification>::Start();
|
||||
|
||||
Checkable::Ptr obj = GetCheckable();
|
||||
|
||||
|
@ -125,7 +125,7 @@ void Notification::Start(void)
|
|||
|
||||
void Notification::Stop(void)
|
||||
{
|
||||
ConfigObject::Stop();
|
||||
ObjectImpl<Notification>::Stop();
|
||||
|
||||
Checkable::Ptr obj = GetCheckable();
|
||||
|
||||
|
@ -676,3 +676,4 @@ Endpoint::Ptr Notification::GetCommandEndpoint(void) const
|
|||
{
|
||||
return Endpoint::GetByName(GetCommandEndpointRaw());
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
******************************************************************************/
|
||||
|
||||
#include "icinga/customvarobject.hpp"
|
||||
#impl_include "icinga/service.hpp"
|
||||
|
||||
library icinga;
|
||||
|
||||
|
@ -43,15 +44,27 @@ class Notification : CustomVarObject < NotificationNameComposer
|
|||
default {{{ return 1800; }}}
|
||||
};
|
||||
[config] name(TimePeriod) period (PeriodRaw);
|
||||
[config, protected] Array::Ptr users (UsersRaw);
|
||||
[config, protected] Array::Ptr user_groups (UserGroupsRaw);
|
||||
[config, protected] array(name(User)) users (UsersRaw);
|
||||
[config, protected] array(name(UserGroup)) user_groups (UserGroupsRaw);
|
||||
[config] Dictionary::Ptr times;
|
||||
[config] Array::Ptr types;
|
||||
[config] array(double) types;
|
||||
int type_filter_real (TypeFilter);
|
||||
[config] Array::Ptr states;
|
||||
[config] array(double) states;
|
||||
int state_filter_real (StateFilter);
|
||||
[config, protected, required] name(Host) host_name;
|
||||
[config, protected] String service_name;
|
||||
[config, protected] String service_name {
|
||||
track {{{
|
||||
if (!oldValue.IsEmpty()) {
|
||||
Service::Ptr service = Service::GetByNamePair(GetHostName(), oldValue);
|
||||
DependencyGraph::RemoveDependency(this, service.get());
|
||||
}
|
||||
|
||||
if (!newValue.IsEmpty()) {
|
||||
Service::Ptr service = Service::GetByNamePair(GetHostName(), newValue);
|
||||
DependencyGraph::RemoveDependency(this, service.get());
|
||||
}
|
||||
}}}
|
||||
};
|
||||
|
||||
[state] Array::Ptr notified_users {
|
||||
default {{{ return new Array(); }}}
|
||||
|
@ -66,26 +79,10 @@ class Notification : CustomVarObject < NotificationNameComposer
|
|||
};
|
||||
|
||||
validator Notification {
|
||||
Array users {
|
||||
name(User) "*";
|
||||
};
|
||||
|
||||
Array user_groups {
|
||||
name(UserGroup) "*";
|
||||
};
|
||||
|
||||
Dictionary times {
|
||||
Number begin;
|
||||
Number end;
|
||||
};
|
||||
|
||||
Array types {
|
||||
Number "*";
|
||||
};
|
||||
|
||||
Array states {
|
||||
Number "*";
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ void ScheduledDowntime::StaticInitialize(void)
|
|||
|
||||
void ScheduledDowntime::OnAllConfigLoaded(void)
|
||||
{
|
||||
CustomVarObject::OnAllConfigLoaded();
|
||||
ObjectImpl<ScheduledDowntime>::OnAllConfigLoaded();
|
||||
|
||||
if (!GetCheckable())
|
||||
BOOST_THROW_EXCEPTION(ScriptError("ScheduledDowntime '" + GetName() + "' references a host/service which doesn't exist.", GetDebugInfo()));
|
||||
|
@ -98,7 +98,7 @@ void ScheduledDowntime::OnAllConfigLoaded(void)
|
|||
|
||||
void ScheduledDowntime::Start(void)
|
||||
{
|
||||
ConfigObject::Start();
|
||||
ObjectImpl<ScheduledDowntime>::Start();
|
||||
|
||||
CreateNextDowntime();
|
||||
}
|
||||
|
@ -231,3 +231,4 @@ void ScheduledDowntime::ValidateRanges(const Dictionary::Ptr& value, const Valid
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
******************************************************************************/
|
||||
|
||||
#include "icinga/customvarobject.hpp"
|
||||
#impl_include "icinga/service.hpp"
|
||||
|
||||
library icinga;
|
||||
|
||||
|
@ -39,7 +40,19 @@ class ScheduledDowntime : CustomVarObject < ScheduledDowntimeNameComposer
|
|||
load_after Service;
|
||||
|
||||
[config, protected, required] name(Host) host_name;
|
||||
[config, protected] String service_name;
|
||||
[config, protected] String service_name {
|
||||
track {{{
|
||||
if (!oldValue.IsEmpty()) {
|
||||
Service::Ptr service = Service::GetByNamePair(GetHostName(), oldValue);
|
||||
DependencyGraph::RemoveDependency(this, service.get());
|
||||
}
|
||||
|
||||
if (!newValue.IsEmpty()) {
|
||||
Service::Ptr service = Service::GetByNamePair(GetHostName(), newValue);
|
||||
DependencyGraph::RemoveDependency(this, service.get());
|
||||
}
|
||||
}}}
|
||||
};
|
||||
|
||||
[config, required] String author;
|
||||
[config, required] String comment;
|
||||
|
|
|
@ -61,7 +61,7 @@ Dictionary::Ptr ServiceNameComposer::ParseName(const String& name) const
|
|||
|
||||
void Service::OnAllConfigLoaded(void)
|
||||
{
|
||||
Checkable::OnAllConfigLoaded();
|
||||
ObjectImpl<Service>::OnAllConfigLoaded();
|
||||
|
||||
m_Host = Host::GetByName(GetHostName());
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ class Service : Checkable < ServiceNameComposer
|
|||
{
|
||||
load_after Host;
|
||||
|
||||
[config] Array::Ptr groups {
|
||||
[config] array(name(ServiceGroup)) groups {
|
||||
default {{{ return new Array(); }}}
|
||||
};
|
||||
|
||||
|
@ -70,10 +70,4 @@ class Service : Checkable < ServiceNameComposer
|
|||
};
|
||||
};
|
||||
|
||||
validator Service {
|
||||
Array groups {
|
||||
name(ServiceGroup) "*";
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -35,16 +35,10 @@ class ServiceGroup : CustomVarObject
|
|||
}}}
|
||||
};
|
||||
|
||||
[config] Array::Ptr groups;
|
||||
[config] array(name(ServiceGroup)) groups;
|
||||
[config] String notes;
|
||||
[config] String notes_url;
|
||||
[config] String action_url;
|
||||
};
|
||||
|
||||
validator ServiceGroup {
|
||||
Array groups {
|
||||
name(ServiceGroup) "*";
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ void TimePeriod::StaticInitialize(void)
|
|||
|
||||
void TimePeriod::Start(void)
|
||||
{
|
||||
ConfigObject::Start();
|
||||
ObjectImpl<TimePeriod>::Start();
|
||||
|
||||
/* Pre-fill the time period for the next 24 hours. */
|
||||
double now = Utility::GetTime();
|
||||
|
|
|
@ -32,7 +32,7 @@ REGISTER_TYPE(User);
|
|||
|
||||
void User::OnConfigLoaded(void)
|
||||
{
|
||||
ConfigObject::OnConfigLoaded();
|
||||
ObjectImpl<User>::OnConfigLoaded();
|
||||
|
||||
SetTypeFilter(FilterArrayToInt(GetTypes(), ~0));
|
||||
SetStateFilter(FilterArrayToInt(GetStates(), ~0));
|
||||
|
@ -40,7 +40,7 @@ void User::OnConfigLoaded(void)
|
|||
|
||||
void User::OnAllConfigLoaded(void)
|
||||
{
|
||||
ConfigObject::OnAllConfigLoaded();
|
||||
ObjectImpl<User>::OnAllConfigLoaded();
|
||||
|
||||
UserGroup::EvaluateObjectRules(this);
|
||||
|
||||
|
@ -62,7 +62,7 @@ void User::OnAllConfigLoaded(void)
|
|||
|
||||
void User::Stop(void)
|
||||
{
|
||||
ConfigObject::Stop();
|
||||
ObjectImpl<User>::Stop();
|
||||
|
||||
Array::Ptr groups = GetGroups();
|
||||
|
||||
|
|
|
@ -35,13 +35,13 @@ class User : CustomVarObject
|
|||
return m_DisplayName;
|
||||
}}}
|
||||
};
|
||||
[config] Array::Ptr groups {
|
||||
[config] array(name(UserGroup)) groups {
|
||||
default {{{ return new Array(); }}}
|
||||
};
|
||||
[config] name(TimePeriod) period (PeriodRaw);
|
||||
[config] Array::Ptr types;
|
||||
[config] array(double) types;
|
||||
int type_filter_real (TypeFilter);
|
||||
[config] Array::Ptr states;
|
||||
[config] array(double) states;
|
||||
int state_filter_real (StateFilter);
|
||||
|
||||
[config] String email;
|
||||
|
@ -54,18 +54,4 @@ class User : CustomVarObject
|
|||
[state] double last_notification;
|
||||
};
|
||||
|
||||
validator User {
|
||||
Array groups {
|
||||
name(UserGroup) "*";
|
||||
};
|
||||
|
||||
Array types {
|
||||
Number "*";
|
||||
};
|
||||
|
||||
Array states {
|
||||
Number "*";
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -35,13 +35,7 @@ class UserGroup : CustomVarObject
|
|||
}}}
|
||||
};
|
||||
|
||||
[config] Array::Ptr groups;
|
||||
};
|
||||
|
||||
validator UserGroup {
|
||||
Array groups {
|
||||
name(UserGroup) "*";
|
||||
};
|
||||
[config] array(name(UserGroup)) groups;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ void LivestatusListener::StatsFunc(const Dictionary::Ptr& status, const Array::P
|
|||
*/
|
||||
void LivestatusListener::Start(void)
|
||||
{
|
||||
ConfigObject::Start();
|
||||
ObjectImpl<LivestatusListener>::Start();
|
||||
|
||||
if (GetSocketType() == "tcp") {
|
||||
TcpSocket::Ptr socket = new TcpSocket();
|
||||
|
@ -121,7 +121,7 @@ void LivestatusListener::Start(void)
|
|||
|
||||
void LivestatusListener::Stop(void)
|
||||
{
|
||||
ConfigObject::Stop();
|
||||
ObjectImpl<LivestatusListener>::Stop();
|
||||
|
||||
m_Listener->Close();
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ void NotificationComponent::StatsFunc(const Dictionary::Ptr& status, const Array
|
|||
*/
|
||||
void NotificationComponent::Start(void)
|
||||
{
|
||||
ConfigObject::Start();
|
||||
ObjectImpl<NotificationComponent>::Start();
|
||||
|
||||
Checkable::OnNotificationsRequested.connect(boost::bind(&NotificationComponent::SendNotificationsHandler, this, _1,
|
||||
_2, _3, _4, _5));
|
||||
|
|
|
@ -40,7 +40,7 @@ REGISTER_TYPE(GelfWriter);
|
|||
|
||||
void GelfWriter::Start(void)
|
||||
{
|
||||
ConfigObject::Start();
|
||||
ObjectImpl<GelfWriter>::Start();
|
||||
|
||||
m_ReconnectTimer = new Timer();
|
||||
m_ReconnectTimer->SetInterval(10);
|
||||
|
|
|
@ -60,7 +60,7 @@ void GraphiteWriter::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
|
|||
|
||||
void GraphiteWriter::Start(void)
|
||||
{
|
||||
ConfigObject::Start();
|
||||
ObjectImpl<GraphiteWriter>::Start();
|
||||
|
||||
m_ReconnectTimer = new Timer();
|
||||
m_ReconnectTimer->SetInterval(10);
|
||||
|
|
|
@ -60,7 +60,7 @@ void OpenTsdbWriter::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
|
|||
|
||||
void OpenTsdbWriter::Start(void)
|
||||
{
|
||||
ConfigObject::Start();
|
||||
ObjectImpl<OpenTsdbWriter>::Start();
|
||||
|
||||
m_ReconnectTimer = new Timer();
|
||||
m_ReconnectTimer->SetInterval(10);
|
||||
|
|
|
@ -51,7 +51,7 @@ void PerfdataWriter::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
|
|||
|
||||
void PerfdataWriter::Start(void)
|
||||
{
|
||||
ConfigObject::Start();
|
||||
ObjectImpl<PerfdataWriter>::Start();
|
||||
|
||||
Checkable::OnNewCheckResult.connect(boost::bind(&PerfdataWriter::CheckResultHandler, this, _1, _2));
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ void ApiListener::Start(void)
|
|||
return;
|
||||
}
|
||||
|
||||
ConfigObject::Start();
|
||||
ObjectImpl<ApiListener>::Start();
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock(m_LogLock);
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "remote/httputility.hpp"
|
||||
#include "remote/filterutility.hpp"
|
||||
#include "base/serializer.hpp"
|
||||
#include "base/dependencygraph.hpp"
|
||||
#include "base/configtype.hpp"
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <set>
|
||||
|
||||
|
@ -72,11 +74,16 @@ bool StatusQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re
|
|||
}
|
||||
|
||||
BOOST_FOREACH(const ConfigObject::Ptr& obj, objs) {
|
||||
Dictionary::Ptr result1 = new Dictionary();
|
||||
results->Add(result1);
|
||||
|
||||
Dictionary::Ptr resultAttrs = new Dictionary();
|
||||
result1->Set("attrs", resultAttrs);
|
||||
|
||||
BOOST_FOREACH(const String& joinType, joinTypes) {
|
||||
String prefix = joinType;
|
||||
boost::algorithm::to_lower(prefix);
|
||||
|
||||
Dictionary::Ptr result1 = new Dictionary();
|
||||
for (int fid = 0; fid < type->GetFieldCount(); fid++) {
|
||||
Field field = type->GetFieldInfo(fid);
|
||||
String aname = prefix + "." + field.Name;
|
||||
|
@ -85,9 +92,23 @@ bool StatusQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re
|
|||
|
||||
Value val = static_cast<Object::Ptr>(obj)->GetField(fid);
|
||||
Value sval = Serialize(val, FAConfig | FAState);
|
||||
result1->Set(aname, sval);
|
||||
resultAttrs->Set(aname, sval);
|
||||
}
|
||||
results->Add(result1);
|
||||
}
|
||||
|
||||
Array::Ptr used_by = new Array();
|
||||
result1->Set("used_by", used_by);
|
||||
|
||||
BOOST_FOREACH(const Object::Ptr& pobj, DependencyGraph::GetParents((obj))) {
|
||||
ConfigObject::Ptr configObj = dynamic_pointer_cast<ConfigObject>(pobj);
|
||||
|
||||
if (!configObj)
|
||||
continue;
|
||||
|
||||
Dictionary::Ptr refInfo = new Dictionary();
|
||||
refInfo->Set("type", configObj->GetType()->GetName());
|
||||
refInfo->Set("name", configObj->GetName());
|
||||
used_by->Add(refInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,14 +27,8 @@ namespace icinga
|
|||
class Zone : ConfigObject
|
||||
{
|
||||
[config] name(Zone) parent (ParentRaw);
|
||||
[config] Array::Ptr endpoints (EndpointsRaw);
|
||||
[config] array(name(Endpoint)) endpoints (EndpointsRaw);
|
||||
[config] bool global;
|
||||
};
|
||||
|
||||
validator Zone {
|
||||
Array endpoints {
|
||||
name(Endpoint) "*";
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -130,6 +130,7 @@ static char *lb_steal(lex_buf *lb)
|
|||
[ \t\r\n] /* ignore whitespace */
|
||||
|
||||
#include { return T_INCLUDE; }
|
||||
#impl_include { return T_IMPL_INCLUDE; }
|
||||
class { return T_CLASS; }
|
||||
namespace { return T_NAMESPACE; }
|
||||
code { return T_CODE; }
|
||||
|
@ -147,9 +148,11 @@ no_storage { yylval->num = FANoStorage; return T_FIELD_ATTRIBUTE; }
|
|||
validator { return T_VALIDATOR; }
|
||||
required { return T_REQUIRED; }
|
||||
name { return T_NAME; }
|
||||
array { return T_ARRAY; }
|
||||
default { yylval->num = FTDefault; return T_FIELD_ACCESSOR_TYPE; }
|
||||
get { yylval->num = FTGet; return T_FIELD_ACCESSOR_TYPE; }
|
||||
set { yylval->num = FTSet; return T_FIELD_ACCESSOR_TYPE; }
|
||||
track { yylval->num = FTTrack; return T_FIELD_ACCESSOR_TYPE; }
|
||||
\"[^\"]+\" { yylval->text = strdup(yytext + 1); yylval->text[strlen(yylval->text) - 1] = '\0'; return T_STRING; }
|
||||
\<[^>]+\> { yylval->text = strdup(yytext + 1); yylval->text[strlen(yylval->text) - 1] = '\0'; return T_ANGLE_STRING; }
|
||||
[a-zA-Z_][:a-zA-Z0-9\-_]* { yylval->text = strdup(yytext); return T_IDENTIFIER; }
|
||||
|
|
|
@ -56,7 +56,8 @@ using namespace icinga;
|
|||
Validator *validator;
|
||||
}
|
||||
|
||||
%token T_INCLUDE "include (T_INCLUDE)"
|
||||
%token T_INCLUDE "#include (T_INCLUDE)"
|
||||
%token T_IMPL_INCLUDE "#impl_include (T_IMPL_INCLUDE)"
|
||||
%token T_CLASS "class (T_CLASS)"
|
||||
%token T_CODE "code (T_CODE)"
|
||||
%token T_LOAD_AFTER "load_after (T_LOAD_AFTER)"
|
||||
|
@ -65,6 +66,7 @@ using namespace icinga;
|
|||
%token T_VALIDATOR "validator (T_VALIDATOR)"
|
||||
%token T_REQUIRED "required (T_REQUIRED)"
|
||||
%token T_NAME "name (T_NAME)"
|
||||
%token T_ARRAY "array (T_ARRAY)"
|
||||
%token T_STRING "string (T_STRING)"
|
||||
%token T_ANGLE_STRING "angle_string (T_ANGLE_STRING)"
|
||||
%token T_FIELD_ATTRIBUTE "field_attribute (T_FIELD_ATTRIBUTE)"
|
||||
|
@ -83,6 +85,8 @@ using namespace icinga;
|
|||
%type <text> type_base_specifier
|
||||
%type <text> include
|
||||
%type <text> angle_include
|
||||
%type <text> impl_include
|
||||
%type <text> angle_impl_include
|
||||
%type <text> code
|
||||
%type <num> T_FIELD_ATTRIBUTE
|
||||
%type <num> field_attribute
|
||||
|
@ -147,6 +151,16 @@ statement: include
|
|||
context->HandleAngleInclude($1, yylloc);
|
||||
std::free($1);
|
||||
}
|
||||
| impl_include
|
||||
{
|
||||
context->HandleImplInclude($1, yylloc);
|
||||
std::free($1);
|
||||
}
|
||||
| angle_impl_include
|
||||
{
|
||||
context->HandleAngleImplInclude($1, yylloc);
|
||||
std::free($1);
|
||||
}
|
||||
| class
|
||||
{
|
||||
context->HandleClass(*$1, yylloc);
|
||||
|
@ -178,6 +192,18 @@ angle_include: T_INCLUDE T_ANGLE_STRING
|
|||
}
|
||||
;
|
||||
|
||||
impl_include: T_IMPL_INCLUDE T_STRING
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
;
|
||||
|
||||
angle_impl_include: T_IMPL_INCLUDE T_ANGLE_STRING
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
;
|
||||
|
||||
namespace: T_NAMESPACE identifier '{'
|
||||
{
|
||||
context->HandleNamespaceBegin($2, yylloc);
|
||||
|
@ -290,8 +316,14 @@ field_type: identifier
|
|||
$$ = new FieldType();
|
||||
$$->IsName = true;
|
||||
$$->TypeName = $3;
|
||||
$$->ArrayRank = 0;
|
||||
free($3);
|
||||
}
|
||||
| T_ARRAY '(' field_type ')'
|
||||
{
|
||||
$$ = $3;
|
||||
$$->ArrayRank++;
|
||||
}
|
||||
;
|
||||
|
||||
class_field: field_attribute_list field_type identifier alternative_name_specifier field_accessor_list ';'
|
||||
|
@ -328,7 +360,10 @@ class_field: field_attribute_list field_type identifier alternative_name_specifi
|
|||
case FTDefault:
|
||||
field->DefaultAccessor = it->Accessor;
|
||||
break;
|
||||
}
|
||||
case FTTrack:
|
||||
field->TrackAccessor = it->Accessor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete $5;
|
||||
|
|
|
@ -73,6 +73,16 @@ void ClassCompiler::HandleAngleInclude(const std::string& path, const ClassDebug
|
|||
m_Header << "#include <" << path << ">" << std::endl << std::endl;
|
||||
}
|
||||
|
||||
void ClassCompiler::HandleImplInclude(const std::string& path, const ClassDebugInfo&)
|
||||
{
|
||||
m_Impl << "#include \"" << path << "\"" << std::endl << std::endl;
|
||||
}
|
||||
|
||||
void ClassCompiler::HandleAngleImplInclude(const std::string& path, const ClassDebugInfo&)
|
||||
{
|
||||
m_Impl << "#include <" << path << ">" << std::endl << std::endl;
|
||||
}
|
||||
|
||||
void ClassCompiler::HandleNamespaceBegin(const std::string& name, const ClassDebugInfo&)
|
||||
{
|
||||
m_Header << "namespace " << name << std::endl
|
||||
|
@ -356,7 +366,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
|
|||
nameref = "NULL";
|
||||
|
||||
m_Impl << "\t\t" << "case " << num << ":" << std::endl
|
||||
<< "\t\t\t" << "return Field(" << num << ", \"" << ftype << "\", \"" << it->Name << "\", " << nameref << ", " << it->Attributes << ");" << std::endl;
|
||||
<< "\t\t\t" << "return Field(" << num << ", \"" << ftype << "\", \"" << it->Name << "\", " << nameref << ", " << it->Attributes << ", " << it->Type.ArrayRank << ");" << std::endl;
|
||||
num++;
|
||||
}
|
||||
|
||||
|
@ -454,7 +464,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
|
|||
m_Impl << "template class ObjectImpl<" << klass.Name << ">;" << std::endl << std::endl;
|
||||
|
||||
/* Validate */
|
||||
m_Header << "\t" << "virtual void Validate(int types, const ValidationUtils& utils);" << std::endl;
|
||||
m_Header << "\t" << "virtual void Validate(int types, const ValidationUtils& utils) override;" << std::endl;
|
||||
|
||||
m_Impl << "void ObjectImpl<" << klass.Name << ">::Validate(int types, const ValidationUtils& utils)" << std::endl
|
||||
<< "{" << std::endl;
|
||||
|
@ -488,10 +498,21 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
|
|||
}
|
||||
|
||||
if (field.Type.IsName) {
|
||||
m_Impl << "\t" << "String ref = value;" << std::endl
|
||||
<< "\t" << "if (!ref.IsEmpty() && !utils.ValidateName(\"" << field.Type.TypeName << "\", ref))" << std::endl
|
||||
if (field.Type.ArrayRank > 0) {
|
||||
m_Impl << "\t" << "if (value) {" << std::endl
|
||||
<< "\t\t" << "ObjectLock olock(value);" << std::endl
|
||||
<< "\t\t" << "BOOST_FOREACH(const String& ref, value) {" << std::endl;
|
||||
} else
|
||||
m_Impl << "\t" << "String ref = value;" << std::endl;
|
||||
|
||||
m_Impl << "\t" << "if (!ref.IsEmpty() && !utils.ValidateName(\"" << field.Type.TypeName << "\", ref))" << std::endl
|
||||
<< "\t\t" << "BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), boost::assign::list_of(\"" << field.Name << "\"), \"Object '\" + ref + \"' of type '" << field.Type.TypeName
|
||||
<< "' does not exist.\"));" << std::endl;
|
||||
|
||||
if (field.Type.ArrayRank > 0) {
|
||||
m_Impl << "\t\t" << "}" << std::endl
|
||||
<< "\t" << "}" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -521,7 +542,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
|
|||
|
||||
/* SetField */
|
||||
m_Header << "protected:" << std::endl
|
||||
<< "\t" << "virtual void SetField(int id, const Value& value, bool suppress_events = false, const Value& cookie = Empty);" << std::endl;
|
||||
<< "\t" << "virtual void SetField(int id, const Value& value, bool suppress_events = false, const Value& cookie = Empty) override;" << std::endl;
|
||||
|
||||
m_Impl << "void ObjectImpl<" << klass.Name << ">::SetField(int id, const Value& value, bool suppress_events, const Value& cookie)" << std::endl
|
||||
<< "{" << std::endl;
|
||||
|
@ -565,7 +586,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
|
|||
|
||||
/* GetField */
|
||||
m_Header << "protected:" << std::endl
|
||||
<< "\t" << "virtual Value GetField(int id) const;" << std::endl;
|
||||
<< "\t" << "virtual Value GetField(int id) const override;" << std::endl;
|
||||
|
||||
m_Impl << "Value ObjectImpl<" << klass.Name << ">::GetField(int id) const" << std::endl
|
||||
<< "{" << std::endl;
|
||||
|
@ -598,7 +619,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
|
|||
|
||||
/* ValidateField */
|
||||
m_Header << "protected:" << std::endl
|
||||
<< "\t" << "virtual void ValidateField(int id, const Value& value, const ValidationUtils& utils);" << std::endl;
|
||||
<< "\t" << "virtual void ValidateField(int id, const Value& value, const ValidationUtils& utils) override;" << std::endl;
|
||||
|
||||
m_Impl << "void ObjectImpl<" << klass.Name << ">::ValidateField(int id, const Value& value, const ValidationUtils& utils)" << std::endl
|
||||
<< "{" << std::endl;
|
||||
|
@ -642,7 +663,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
|
|||
|
||||
/* NotifyField */
|
||||
m_Header << "protected:" << std::endl
|
||||
<< "\t" << "virtual void NotifyField(int id, const Value& cookie = Empty);" << std::endl;
|
||||
<< "\t" << "virtual void NotifyField(int id, const Value& cookie = Empty) override;" << std::endl;
|
||||
|
||||
m_Impl << "void ObjectImpl<" << klass.Name << ">::NotifyField(int id, const Value& cookie)" << std::endl
|
||||
<< "{" << std::endl;
|
||||
|
@ -723,17 +744,105 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
|
|||
m_Impl << "void ObjectImpl<" << klass.Name << ">::Set" << it->GetFriendlyName() << "(" << it->Type.GetArgumentType() << " value, bool suppress_events, const Value& cookie)" << std::endl
|
||||
<< "{" << std::endl;
|
||||
|
||||
if (it->Type.IsName || !it->TrackAccessor.empty())
|
||||
m_Impl << "\t" << "Value oldValue = Get" << it->GetFriendlyName() << "();" << std::endl;
|
||||
|
||||
|
||||
if (it->SetAccessor.empty() && !(it->Attributes & FANoStorage))
|
||||
m_Impl << "\t" << "m_" << it->GetFriendlyName() << " = value;" << std::endl;
|
||||
else
|
||||
m_Impl << it->SetAccessor << std::endl << std::endl;
|
||||
|
||||
|
||||
if (it->Type.IsName || !it->TrackAccessor.empty()) {
|
||||
m_Impl << "\t" << "ConfigObject *dobj = dynamic_cast<ConfigObject *>(this);" << std::endl;
|
||||
|
||||
if (it->Name != "active") {
|
||||
m_Impl << "\t" << "if (!dobj || dobj->IsActive())" << std::endl
|
||||
<< "\t";
|
||||
}
|
||||
|
||||
m_Impl << "\t" << "Track" << it->GetFriendlyName() << "(oldValue, value);" << std::endl;
|
||||
}
|
||||
|
||||
m_Impl << "\t" << "if (!suppress_events)" << std::endl
|
||||
<< "\t\t" << "Notify" << it->GetFriendlyName() << "(cookie);" << std::endl
|
||||
<< "}" << std::endl << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
m_Header << "protected:" << std::endl;
|
||||
|
||||
bool needs_tracking = false;
|
||||
|
||||
/* tracking */
|
||||
for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
|
||||
if (!it->Type.IsName && it->TrackAccessor.empty())
|
||||
continue;
|
||||
|
||||
needs_tracking = true;
|
||||
|
||||
m_Header << "\t" << "virtual void Track" << it->GetFriendlyName() << "(" << it->Type.GetArgumentType() << " oldValue, " << it->Type.GetArgumentType() << " newValue);";
|
||||
|
||||
m_Impl << "void ObjectImpl<" << klass.Name << ">::Track" << it->GetFriendlyName() << "(" << it->Type.GetArgumentType() << " oldValue, " << it->Type.GetArgumentType() << " newValue)" << std::endl
|
||||
<< "{" << std::endl;
|
||||
|
||||
if (!it->TrackAccessor.empty())
|
||||
m_Impl << "\t" << it->TrackAccessor << std::endl;
|
||||
|
||||
if (it->Type.ArrayRank > 0) {
|
||||
m_Impl << "\t" << "if (oldValue) {" << std::endl
|
||||
<< "\t\t" << "ObjectLock olock(oldValue);" << std::endl
|
||||
<< "\t\t" << "BOOST_FOREACH(const String& ref, oldValue) {" << std::endl
|
||||
<< "\t\t\t" << "DependencyGraph::RemoveDependency(this, ConfigObject::GetObject(\"" << it->Type.TypeName << "\", ref).get());" << std::endl
|
||||
<< "\t\t" << "}" << std::endl
|
||||
<< "\t" << "}" << std::endl
|
||||
<< "\t" << "if (newValue) {" << std::endl
|
||||
<< "\t\t" << "ObjectLock olock(newValue);" << std::endl
|
||||
<< "\t\t" << "BOOST_FOREACH(const String& ref, newValue) {" << std::endl
|
||||
<< "\t\t\t" << "DependencyGraph::AddDependency(this, ConfigObject::GetObject(\"" << it->Type.TypeName << "\", ref).get());" << std::endl
|
||||
<< "\t\t" << "}" << std::endl
|
||||
<< "\t" << "}" << std::endl;
|
||||
} else {
|
||||
m_Impl << "\t" << "if (!oldValue.IsEmpty())" << std::endl
|
||||
<< "\t\t" << "DependencyGraph::RemoveDependency(this, ConfigObject::GetObject(\"" << it->Type.TypeName << "\", oldValue).get());" << std::endl
|
||||
<< "\t" << "if (!newValue.IsEmpty())" << std::endl
|
||||
<< "\t\t" << "DependencyGraph::AddDependency(this, ConfigObject::GetObject(\"" << it->Type.TypeName << "\", newValue).get());" << std::endl;
|
||||
}
|
||||
|
||||
m_Impl << "}" << std::endl << std::endl;
|
||||
}
|
||||
|
||||
/* start/stop */
|
||||
if (needs_tracking) {
|
||||
m_Header << "virtual void Start(void) override;" << std::endl
|
||||
<< "virtual void Stop(void) override;" << std::endl;
|
||||
|
||||
m_Impl << "void ObjectImpl<" << klass.Name << ">::Start(void)" << std::endl
|
||||
<< "{" << std::endl
|
||||
<< "\t" << klass.Parent << "::Start();" << std::endl << std::endl;
|
||||
|
||||
for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
|
||||
if (!(it->Type.IsName))
|
||||
continue;
|
||||
|
||||
m_Impl << "\t" << "Track" << it->GetFriendlyName() << "(Empty, Get" << it->GetFriendlyName() << "());" << std::endl;
|
||||
}
|
||||
|
||||
m_Impl << "}" << std::endl << std::endl
|
||||
<< "void ObjectImpl<" << klass.Name << ">::Stop(void)" << std::endl
|
||||
<< "{" << std::endl
|
||||
<< "\t" << klass.Parent << "::Stop();" << std::endl << std::endl;
|
||||
|
||||
for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
|
||||
if (!(it->Type.IsName))
|
||||
continue;
|
||||
|
||||
m_Impl << "\t" << "Track" << it->GetFriendlyName() << "(Get" << it->GetFriendlyName() << "(), Empty);" << std::endl;
|
||||
}
|
||||
|
||||
m_Impl << "}" << std::endl << std::endl;
|
||||
}
|
||||
|
||||
/* notify */
|
||||
for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
|
||||
std::string prot;
|
||||
|
@ -787,8 +896,10 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
|
|||
m_Header << "private:" << std::endl;
|
||||
|
||||
for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
|
||||
if (!(it->Attributes & FANoStorage))
|
||||
m_Header << "\t" << it->Type.GetRealType() << " m_" << it->GetFriendlyName() << ";" << std::endl;
|
||||
if (it->Attributes & FANoStorage)
|
||||
continue;
|
||||
|
||||
m_Header << "\t" << it->Type.GetRealType() << " m_" << it->GetFriendlyName() << ";" << std::endl;
|
||||
}
|
||||
|
||||
/* signal */
|
||||
|
@ -1178,6 +1289,7 @@ void ClassCompiler::CompileStream(const std::string& path, std::istream& input,
|
|||
<< "#include \"base/objectlock.hpp\"" << std::endl
|
||||
<< "#include \"base/utility.hpp\"" << std::endl
|
||||
<< "#include \"base/convert.hpp\"" << std::endl
|
||||
<< "#include \"base/dependencygraph.hpp\"" << std::endl
|
||||
<< "#include <boost/foreach.hpp>" << std::endl
|
||||
<< "#include <boost/assign/list_of.hpp>" << std::endl
|
||||
<< "#ifdef _MSC_VER" << std::endl
|
||||
|
|
|
@ -42,7 +42,8 @@ enum FieldAccessorType
|
|||
{
|
||||
FTGet,
|
||||
FTSet,
|
||||
FTDefault
|
||||
FTDefault,
|
||||
FTTrack
|
||||
};
|
||||
|
||||
struct FieldAccessor
|
||||
|
@ -75,13 +76,21 @@ struct FieldType
|
|||
{
|
||||
bool IsName;
|
||||
std::string TypeName;
|
||||
int ArrayRank;
|
||||
|
||||
FieldType(void)
|
||||
: IsName(false), ArrayRank(0)
|
||||
{ }
|
||||
|
||||
inline std::string GetRealType(void) const
|
||||
{
|
||||
if (ArrayRank > 0)
|
||||
return "Array::Ptr";
|
||||
|
||||
if (IsName)
|
||||
return "String";
|
||||
else
|
||||
return TypeName;
|
||||
|
||||
return TypeName;
|
||||
}
|
||||
|
||||
inline std::string GetArgumentType(void) const
|
||||
|
@ -106,6 +115,7 @@ struct Field
|
|||
std::string SetAccessor;
|
||||
bool PureSetAccessor;
|
||||
std::string DefaultAccessor;
|
||||
std::string TrackAccessor;
|
||||
|
||||
Field(void)
|
||||
: Attributes(0), PureGetAccessor(false), PureSetAccessor(false)
|
||||
|
@ -203,6 +213,8 @@ public:
|
|||
|
||||
void HandleInclude(const std::string& path, const ClassDebugInfo& locp);
|
||||
void HandleAngleInclude(const std::string& path, const ClassDebugInfo& locp);
|
||||
void HandleImplInclude(const std::string& path, const ClassDebugInfo& locp);
|
||||
void HandleAngleImplInclude(const std::string& path, const ClassDebugInfo& locp);
|
||||
void HandleClass(const Klass& klass, const ClassDebugInfo& locp);
|
||||
void HandleValidator(const Validator& validator, const ClassDebugInfo& locp);
|
||||
void HandleNamespaceBegin(const std::string& name, const ClassDebugInfo& locp);
|
||||
|
|
Loading…
Reference in New Issue