}
service->SetForceNextCheck(false);
- service->SetFirstCheck(false);
Logger::Write(LogDebug, "checker", "Executing service check for '" + service->GetName() + "'");
boost::mutex::scoped_lock lock(m_Mutex);
ObjectLock olock(service); /* also required for the key extractor */
- String checker = service->GetChecker();
+ String checker = service->GetCurrentChecker();
if (checker == EndpointManager::GetInstance()->GetIdentity() || checker == m_Endpoint->GetName()) {
if (m_PendingServices.find(service) != m_PendingServices.end())
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Host")) {
Host::Ptr host = static_pointer_cast<Host>(object);
- stringstream tempstatusfp, tempobjectfp;
-
+ stringstream tempstatusfp;
+ tempstatusfp << std::fixed;
DumpHostStatus(tempstatusfp, host);
- DumpHostObject(tempobjectfp, host);
-
statusfp << tempstatusfp.str();
+
+ stringstream tempobjectfp;
+ tempobjectfp << std::fixed;
+ DumpHostObject(tempobjectfp, host);
objectfp << tempobjectfp.str();
}
HostGroup::Ptr hg = static_pointer_cast<HostGroup>(object);
stringstream tempobjectfp;
+ tempobjectfp << std::fixed;
{
ObjectLock olock(hg);
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) {
Service::Ptr service = static_pointer_cast<Service>(object);
- stringstream tempstatusfp, tempobjectfp;
-
- DumpServiceStatus(statusfp, service);
- DumpServiceObject(objectfp, service);
-
+ stringstream tempstatusfp;
+ tempstatusfp << std::fixed;
+ DumpServiceStatus(tempstatusfp, service);
statusfp << tempstatusfp.str();
+
+ stringstream tempobjectfp;
+ tempobjectfp << std::fixed;
+ DumpServiceObject(tempobjectfp, service);
objectfp << tempobjectfp.str();
}
ServiceGroup::Ptr sg = static_pointer_cast<ServiceGroup>(object);
stringstream tempobjectfp;
+ tempobjectfp << std::fixed;
{
ObjectLock olock(sg);
services.push_back(service);
ObjectLock olock(service);
- String checker = service->GetChecker();
+ String checker = service->GetCurrentChecker();
if (checker.IsEmpty())
continue;
BOOST_FOREACH(const Service::Ptr& service, services) {
ObjectLock olock(service);
- String checker = service->GetChecker();
+ String checker = service->GetCurrentChecker();
Endpoint::Ptr oldEndpoint;
if (Endpoint::Exists(checker))
/* clear the service's current checker */
if (!checker.IsEmpty()) {
- service->SetChecker("");
+ service->SetCurrentChecker("");
if (oldEndpoint)
histogram[oldEndpoint]--;
continue;
ObjectLock clock(candidate);
- service->SetChecker(candidate->GetName());
+ service->SetCurrentChecker(candidate->GetName());
histogram[candidate]++;
/* reschedule the service; this avoids "check floods"
continue;
}
- assert(!service->GetChecker().IsEmpty());
+ assert(!service->GetCurrentChecker().IsEmpty());
}
Endpoint::Ptr endpoint;
if (!cr)
return;
- if (cr->Contains("checker") && cr->Get("checker") == EndpointManager::GetInstance()->GetIdentity())
+ if (cr->Contains("current_checker") && cr->Get("current_checker") == EndpointManager::GetInstance()->GetIdentity())
return;
Service::UpdateStatistics(cr);
AC_MSG_CHECKING(whether to enable debugging)
AC_ARG_ENABLE(debug, [ --enable-debug=[no/yes] turn on debugging (default=no)],, enable_debug=no)
if test "x$enable_debug" = "xyes"; then
- CFLAGS="$CFLAGS -g -O0 -rdynamic"
- CXXFLAGS="$CXXFLAGS -g -O0 -rdynamic"
+ CFLAGS="$CFLAGS -g -O0 -D_DEBUG"
+ CXXFLAGS="$CXXFLAGS -g -O0 -D_DEBUG"
+else
+ CFLAGS="$CFLAGS -DNDEBUG"
+ CXXFLAGS="$CXXFLAGS -DNDEBUG"
fi
AC_MSG_RESULT($enable_debug)
DynamicObject::DynamicObject(const Dictionary::Ptr& serializedObject)
: m_EventSafe(false), m_ConfigTx(0)
{
- RegisterAttribute("__name", Attribute_Config);
- RegisterAttribute("__type", Attribute_Config);
- RegisterAttribute("__local", Attribute_Config);
- RegisterAttribute("__abstract", Attribute_Config);
- RegisterAttribute("__source", Attribute_Local);
- RegisterAttribute("methods", Attribute_Config);
+ RegisterAttribute("__name", Attribute_Config, &m_Name);
+ RegisterAttribute("__type", Attribute_Config, &m_Type);
+ RegisterAttribute("__local", Attribute_Config, &m_Local);
+ RegisterAttribute("__abstract", Attribute_Config, &m_Abstract);
+ RegisterAttribute("__source", Attribute_Local, &m_Source);
+ RegisterAttribute("methods", Attribute_Config, &m_Methods);
{
ObjectLock olock(serializedObject);
}
/* apply config state from the config item/remote update;
- * The DynamicObject::Create function takes care of restoring
+ * The DynamicType::CreateObject function takes care of restoring
* non-config state after the object has been fully constructed */
{
ObjectLock olock(this);
Dictionary::Ptr attrs = boost::make_shared<Dictionary>();
for (it = m_Attributes.begin(); it != m_Attributes.end(); it++) {
- if (it->second.Type == Attribute_Transient)
+ if (it->second.GetType() == Attribute_Transient)
continue;
- if ((it->second.Type & attributeTypes) == 0)
+ if ((it->second.GetType() & attributeTypes) == 0)
continue;
- if (it->second.Tx == 0)
+ if (it->second.GetTx() == 0)
continue;
- if (it->second.Tx < sinceTx && !(it->second.Type == Attribute_Config && m_ConfigTx >= sinceTx))
+ if (it->second.GetTx() < sinceTx && !(it->second.GetType() == Attribute_Config && m_ConfigTx >= sinceTx))
continue;
Dictionary::Ptr attr = boost::make_shared<Dictionary>();
- attr->Set("data", it->second.Data);
- attr->Set("type", it->second.Type);
- attr->Set("tx", it->second.Tx);
+ attr->Set("data", it->second.GetValue());
+ attr->Set("type", it->second.GetType());
+ attr->Set("tx", it->second.GetTx());
attrs->Set(it->first, attr);
}
RegisterAttribute(it->first, Attribute_Config);
if (!HasAttribute(it->first))
- RegisterAttribute(it->first, static_cast<DynamicAttributeType>(type));
+ RegisterAttribute(it->first, static_cast<AttributeType>(type));
InternalSetAttribute(it->first, data, tx, true);
}
}
void DynamicObject::RegisterAttribute(const String& name,
- DynamicAttributeType type)
+ AttributeType type, AttributeBase *boundAttribute)
{
- DynamicAttribute attr;
- attr.Type = type;
- attr.Tx = 0;
+ AttributeHolder attr(type, boundAttribute);
pair<DynamicObject::AttributeIterator, bool> tt;
tt = m_Attributes.insert(make_pair(name, attr));
- if (!tt.second)
- tt.first->second.Type = type;
+ if (!tt.second) {
+ tt.first->second.SetType(type);
+
+ if (boundAttribute)
+ tt.first->second.Bind(boundAttribute);
+ }
}
void DynamicObject::Set(const String& name, const Value& data)
void DynamicObject::InternalSetAttribute(const String& name, const Value& data,
double tx, bool allowEditConfig)
{
- DynamicAttribute attr;
- attr.Type = Attribute_Transient;
- attr.Data = data;
- attr.Tx = tx;
-
- pair<DynamicObject::AttributeIterator, bool> tt;
- tt = m_Attributes.insert(make_pair(name, attr));
+ DynamicObject::AttributeIterator it;
+ it = m_Attributes.find(name);
Value oldValue;
- if (!allowEditConfig && (tt.first->second.Type & Attribute_Config))
- BOOST_THROW_EXCEPTION(runtime_error("Config properties are immutable: '" + name + "'."));
+ if (it == m_Attributes.end()) {
+ AttributeHolder attr(Attribute_Transient);
+ attr.SetValue(tx, data);
- if (!tt.second && tx >= tt.first->second.Tx) {
- oldValue = tt.first->second.Data;
- tt.first->second.Data = data;
- tt.first->second.Tx = tx;
- }
+ m_Attributes.insert(make_pair(name, attr));
+ } else {
+ if (!allowEditConfig && (it->second.GetType() & Attribute_Config))
+ BOOST_THROW_EXCEPTION(runtime_error("Config properties are immutable: '" + name + "'."));
+
+ oldValue = it->second.GetValue();
+ it->second.SetValue(tx, data);
- if (tt.first->second.Type & Attribute_Config)
- m_ConfigTx = tx;
+ if (it->second.GetType() & Attribute_Config)
+ m_ConfigTx = tx;
+ }
if (GetEventSafe()) {
/* We can't call GetSelf() in the constructor or destructor.
if (it == m_Attributes.end())
return Empty;
- return it->second.Data;
+ return it->second.GetValue();
}
bool DynamicObject::HasAttribute(const String& name) const
return (m_Attributes.find(name) != m_Attributes.end());
}
-void DynamicObject::ClearAttributesByType(DynamicAttributeType type)
+void DynamicObject::ClearAttributesByType(AttributeType type)
{
DynamicObject::AttributeIterator at;
for (at = m_Attributes.begin(); at != m_Attributes.end(); at++) {
- if (at->second.Type != type)
+ if (at->second.GetType() != type)
continue;
- at->second.Tx = 0;
- at->second.Data = Empty;
+ at->second.SetValue(0, Empty);
}
}
DynamicType::Ptr DynamicObject::GetType(void) const
{
- String name = Get("__type");
- return DynamicType::GetByName(name);
+ return DynamicType::GetByName(m_Type);
}
String DynamicObject::GetName(void) const
{
- return Get("__name");
+ return m_Name;
}
bool DynamicObject::IsLocal(void) const
{
- Value value = Get("__local");
-
- if (value.IsEmpty())
- return false;
-
- return (value != 0);
+ return m_Local;
}
bool DynamicObject::IsAbstract(void) const
{
- Value value = Get("__abstract");
-
- if (value.IsEmpty())
- return false;
-
- return (value != 0);
+ return m_Abstract;
}
void DynamicObject::SetSource(const String& value)
{
- Set("__source", value);
+ m_Source = value;
+ Touch("__source");
}
String DynamicObject::GetSource(void) const
{
- return Get("__source");
+ return m_Source;
}
void DynamicObject::Register(void)
ScriptTask::Ptr DynamicObject::MakeMethodTask(const String& method,
const vector<Value>& arguments)
{
- Value value = Get("methods");
-
- if (!value.IsObjectType<Dictionary>())
- return ScriptTask::Ptr();
-
String funcName;
- Dictionary::Ptr methods = value;
+
+ Dictionary::Ptr methods = m_Methods;
{
ObjectLock olock(methods);
*
* @ingroup base
*/
-enum DynamicAttributeType
+enum AttributeType
{
Attribute_Transient = 1,
Attribute_All = Attribute_Transient | Attribute_Local | Attribute_Replicated | Attribute_Config
};
+class AttributeBase
+{
+public:
+ AttributeBase(void)
+ : m_Value()
+ { }
+
+ void InternalSet(const Value& value)
+ {
+ m_Value = value;
+ }
+
+ const Value& InternalGet(void) const
+ {
+ return m_Value;
+ }
+
+ operator Value(void) const
+ {
+ return InternalGet();
+ }
+
+ bool IsEmpty(void) const
+ {
+ return InternalGet().IsEmpty();
+ }
+
+private:
+ Value m_Value;
+};
+
+template<typename T>
+class Attribute : public AttributeBase
+{
+public:
+ void Set(const T& value)
+ {
+ InternalSet(value);
+ }
+
+ Attribute<T>& operator=(const T& rhs)
+ {
+ Set(rhs);
+ }
+
+ T Get(void) const
+ {
+ if (IsEmpty())
+ return T();
+
+ return InternalGet();
+ }
+
+ operator T(void) const
+ {
+ return Get();
+ }
+};
+
/**
* An attribute for a DynamicObject.
*
* @ingroup base
*/
-struct DynamicAttribute
+struct AttributeHolder
{
- Value Data; /**< The current value of the attribute. */
- DynamicAttributeType Type; /**< The type of the attribute. */
- double Tx; /**< The timestamp of the last value change. */
+ AttributeType m_Type; /**< The type of the attribute. */
+ double m_Tx; /**< The timestamp of the last value change. */
+ bool m_OwnsAttribute; /**< Whether we own the Data pointer. */
+ AttributeBase *m_Attribute; /**< The current value of the attribute. */
+
+ AttributeHolder(AttributeType type, AttributeBase *boundAttribute = NULL)
+ : m_Type(type), m_Tx(0)
+ {
+ if (boundAttribute) {
+ m_Attribute = boundAttribute;
+ m_OwnsAttribute = false;
+ } else {
+ m_Attribute = new Attribute<Value>();
+ m_OwnsAttribute = true;
+ }
+ }
+
+ AttributeHolder(const AttributeHolder& other)
+ {
+ m_Type = other.m_Type;
+ m_Tx = other.m_Tx;
+ m_OwnsAttribute = other.m_OwnsAttribute;
+
+ if (other.m_OwnsAttribute) {
+ m_Attribute = new Attribute<Value>();
+ m_Attribute->InternalSet(other.m_Attribute->InternalGet());
+ } else {
+ m_Attribute = other.m_Attribute;
+ }
+ }
+
+ ~AttributeHolder(void)
+ {
+ if (m_OwnsAttribute)
+ delete m_Attribute;
+ }
+
+ void Bind(AttributeBase *boundAttribute)
+ {
+ assert(m_OwnsAttribute);
+ boundAttribute->InternalSet(m_Attribute->InternalGet());
+ m_Attribute = boundAttribute;
+ m_OwnsAttribute = false;
+ }
+
+ void SetValue(double tx, const Value& value)
+ {
+ m_Tx = tx;
+ m_Attribute->InternalSet(value);
+ }
+
+ Value GetValue(void) const
+ {
+ return m_Attribute->InternalGet();
+ }
+
+ void SetType(AttributeType type)
+ {
+ m_Type = type;
+ }
+
+ AttributeType GetType(void) const
+ {
+ return m_Type;
+ }
+
+ double GetTx(void) const
+ {
+ return m_Tx;
+ }
};
class DynamicType;
typedef shared_ptr<DynamicObject> Ptr;
typedef weak_ptr<DynamicObject> WeakPtr;
- typedef map<String, DynamicAttribute, string_iless> AttributeMap;
+ typedef map<String, AttributeHolder, string_iless> AttributeMap;
typedef AttributeMap::iterator AttributeIterator;
typedef AttributeMap::const_iterator AttributeConstIterator;
Dictionary::Ptr BuildUpdate(double sinceTx, int attributeTypes) const;
void ApplyUpdate(const Dictionary::Ptr& serializedUpdate, int allowedTypes);
- void RegisterAttribute(const String& name, DynamicAttributeType type);
+ void RegisterAttribute(const String& name, AttributeType type, AttributeBase *boundAttribute = NULL);
void Set(const String& name, const Value& data);
void Touch(const String& name);
bool HasAttribute(const String& name) const;
- void ClearAttributesByType(DynamicAttributeType type);
+ void BindAttribute(const String& name, Value *boundValue);
+
+ void ClearAttributesByType(AttributeType type);
static signals2::signal<void (const DynamicObject::Ptr&)> OnRegistered;
static signals2::signal<void (const DynamicObject::Ptr&)> OnUnregistered;
map<String, Value, string_iless> m_ModifiedAttributes;
double m_ConfigTx;
+ Attribute<String> m_Name;
+ Attribute<String> m_Type;
+ Attribute<bool> m_Local;
+ Attribute<bool> m_Abstract;
+ Attribute<String> m_Source;
+ Attribute<Dictionary::Ptr> m_Methods;
+
bool m_EventSafe;
static double m_CurrentTx;
/* notify the object that it's been registered */
object->OnRegistrationCompleted();
+
+ {
+ ObjectLock olock(object);
+ object->Flush();
+ }
+
}
void DynamicType::UnregisterObject(const DynamicObject::Ptr& object)
/* register attributes */
String name;
- DynamicAttributeType type;
+ AttributeType type;
BOOST_FOREACH(tuples::tie(name, type), m_Attributes)
object->RegisterAttribute(name, type);
return (GetByName(name));
}
-void DynamicType::AddAttribute(const String& name, DynamicAttributeType type)
+void DynamicType::AddAttribute(const String& name, AttributeType type)
{
m_Attributes[name] = type;
}
struct AttributeDescription
{
String Name;
- DynamicAttributeType Type;
+ AttributeType Type;
};
class I2_BASE_API DynamicType : public Object
static set<DynamicObject::Ptr> GetObjects(const String& type);
- void AddAttribute(const String& name, DynamicAttributeType type);
+ void AddAttribute(const String& name, AttributeType type);
void RemoveAttribute(const String& name);
bool HasAttribute(const String& name);
private:
String m_Name;
ObjectFactory m_ObjectFactory;
- map<String, DynamicAttributeType> m_Attributes;
+ map<String, AttributeType> m_Attributes;
typedef map<String, DynamicObject::Ptr, string_iless> ObjectMap;
typedef set<DynamicObject::Ptr> ObjectSet;
for (int i = 0; i < thread_count; i++)
m_Threads.create_thread(boost::bind(&EventQueue::QueueThreadProc, this));
+
+ m_ReportTimer = boost::make_shared<Timer>();
+ m_ReportTimer->OnTimerExpired.connect(boost::bind(&EventQueue::ReportTimerHandler, this));
+ m_ReportTimer->SetInterval(5);
+ m_ReportTimer->Start();
}
/**
*/
EventQueue::~EventQueue(void)
{
+ m_ReportTimer->Stop();
+
Stop();
Join();
}
boost::mutex::scoped_lock lock(m_Mutex);
m_Events.push_back(callback);
m_CV.notify_one();
+}
- int pending = m_Events.size();
- double now = Utility::GetTime();
- if (pending > 1000 && now - m_LastReport > 5) {
- Logger::Write(LogCritical, "base", "More than 1000 pending events: " + Convert::ToString(pending));
- m_LastReport = now;
+void EventQueue::ReportTimerHandler(void)
+{
+ int pending;
+
+ {
+ boost::mutex::scoped_lock lock(m_Mutex);
+ pending = m_Events.size();
}
+
+ if (pending > 1000)
+ Logger::Write(LogCritical, "base", "More than 1000 pending events: " + Convert::ToString(pending));
}
namespace icinga
{
+class Timer;
+
/**
* An event queue.
*
condition_variable m_CV;
double m_LastReport;
+ shared_ptr<Timer> m_ReportTimer;
+
bool m_Stopped;
vector<Callback> m_Events;
void QueueThreadProc(void);
+ void ReportTimerHandler(void);
};
}
Logger::Logger(const Dictionary::Ptr& properties)
: DynamicObject(properties)
{
+ RegisterAttribute("type", Attribute_Config, &m_Type);
+ RegisterAttribute("path", Attribute_Config, &m_Path);
+ RegisterAttribute("severity", Attribute_Config, &m_Severity);
+
if (!IsLocal())
BOOST_THROW_EXCEPTION(runtime_error("Logger objects must be local."));
- String type = Get("type");
+ String type = m_Type;
if (type.IsEmpty())
BOOST_THROW_EXCEPTION(runtime_error("Logger objects must have a 'type' property."));
BOOST_THROW_EXCEPTION(invalid_argument("Syslog is not supported on Windows."));
#endif /* _WIN32 */
} else if (type == "file") {
- String path = Get("path");
+ String path = m_Path;
if (path.IsEmpty())
BOOST_THROW_EXCEPTION(invalid_argument("'log' object of type 'file' must have a 'path' property"));
*/
LogSeverity Logger::GetMinSeverity(void) const
{
- String severity = Get("severity");
+ String severity = m_Severity;
if (severity.IsEmpty())
return LogInformation;
else
LogSeverity GetMinSeverity(void) const;
private:
+ Attribute<String> m_Type;
+ Attribute<String> m_Path;
+ Attribute<String> m_Severity;
+
LogSeverity m_MinSeverity;
ILogger::Ptr m_Impl;
*/
Script::Script(const Dictionary::Ptr& properties)
: DynamicObject(properties)
-{ }
+{
+ RegisterAttribute("language", Attribute_Config, &m_Language);
+ RegisterAttribute("code", Attribute_Config, &m_Code);
+}
void Script::OnRegistrationCompleted(void)
{
String Script::GetLanguage(void) const
{
- return Get("language");
+ return m_Language;
}
String Script::GetCode(void) const
{
- return Get("code");
+ return m_Code;
}
void Script::OnAttributeUpdate(const String& name, const Value& oldValue)
virtual void OnAttributeUpdate(const String& name, const Value& oldValue);
private:
+ Attribute<String> m_Language;
+ Attribute<String> m_Code;
+
shared_ptr<ScriptInterpreter> m_Interpreter;
void SpawnInterpreter(void);
timer->m_Started = false;
m_Timers.erase(timer);
+ lock.unlock();
+
/* Asynchronously call the timer. */
Application::GetEQ().Post(boost::bind(&Timer::Call, timer));
}
using namespace icinga;
+boost::mutex Host::m_Mutex;
map<String, map<String, weak_ptr<Service> > > Host::m_ServicesCache;
bool Host::m_ServicesCacheValid = true;
REGISTER_SCRIPTFUNCTION("ValidateServiceDictionary", &Host::ValidateServiceDictionary);
-static AttributeDescription hostAttributes[] = {
- { "slave_services", Attribute_Transient }
-};
-
-REGISTER_TYPE(Host, hostAttributes);
+REGISTER_TYPE(Host, NULL);
Host::Host(const Dictionary::Ptr& properties)
: DynamicObject(properties)
-{ }
+{
+ RegisterAttribute("display_name", Attribute_Config, &m_DisplayName);
+ RegisterAttribute("hostgroups", Attribute_Config, &m_HostGroups);
+ RegisterAttribute("macros", Attribute_Config, &m_Macros);
+ RegisterAttribute("hostdependencies", Attribute_Config, &m_HostDependencies);
+ RegisterAttribute("servicedependencies", Attribute_Config, &m_ServiceDependencies);
+ RegisterAttribute("hostcheck", Attribute_Config, &m_HostCheck);
+
+}
void Host::OnRegistrationCompleted(void)
{
DynamicObject::OnRegistrationCompleted();
HostGroup::InvalidateMembersCache();
-
- {
- ObjectLock olock(this);
- UpdateSlaveServices();
- }
+ Host::UpdateSlaveServices(GetSelf());
}
Host::~Host(void)
{
HostGroup::InvalidateMembersCache();
- Dictionary::Ptr services = Get("slave_services");
-
- if (services) {
+ if (m_SlaveServices) {
ConfigItem::Ptr service;
- BOOST_FOREACH(tie(tuples::ignore, service), services) {
+ BOOST_FOREACH(tie(tuples::ignore, service), m_SlaveServices) {
service->Unregister();
}
}
String Host::GetDisplayName(void) const
{
- String value = Get("display_name");
- if (!value.IsEmpty())
- return value;
+ if (!m_DisplayName.IsEmpty())
+ return m_DisplayName;
else
return GetName();
}
Dictionary::Ptr Host::GetGroups(void) const
{
- return Get("hostgroups");
+ return m_HostGroups;;
}
Dictionary::Ptr Host::GetMacros(void) const
{
- return Get("macros");
+ return m_Macros;
}
Dictionary::Ptr Host::GetHostDependencies(void) const
{
- return Get("hostdependencies");
+ return m_HostDependencies;;
}
Dictionary::Ptr Host::GetServiceDependencies(void) const
{
- return Get("servicedependencies");
+ return m_ServiceDependencies;
}
String Host::GetHostCheck(void) const
{
- return Get("hostcheck");
+ return m_HostCheck;
}
bool Host::IsReachable(const Host::Ptr& self)
}
}
-void Host::UpdateSlaveServices(void)
+void Host::UpdateSlaveServices(const Host::Ptr& self)
{
- ConfigItem::Ptr item = ConfigItem::GetObject("Host", GetName());
+ ConfigItem::Ptr item;
+ Dictionary::Ptr oldServices, newServices, serviceDescs;
+ String host_name;
- /* Don't create slave services unless we own this object
- * and it's not a template. */
- if (!item || IsAbstract())
- return;
+ {
+ ObjectLock olock(self);
+
+ host_name = self->GetName();
+
+ item = ConfigItem::GetObject("Host", host_name);
- Dictionary::Ptr oldServices = Get("slave_services");
+ /* Don't create slave services unless we own this object
+ * and it's not a template. */
+ if (!item || self->IsAbstract())
+ return;
+
+ oldServices = self->m_SlaveServices;
+ serviceDescs = self->Get("services");
+ }
- Dictionary::Ptr newServices;
newServices = boost::make_shared<Dictionary>();
- Dictionary::Ptr serviceDescs = Get("services");
+ DebugInfo debug_info;
+
+ {
+ ObjectLock olock(item);
+ debug_info = item->GetDebugInfo();
+ }
if (serviceDescs) {
String svcname;
svcname = svcdesc;
stringstream namebuf;
- namebuf << GetName() << "-" << svcname;
+ namebuf << host_name << "-" << svcname;
String name = namebuf.str();
- ConfigItemBuilder::Ptr builder = boost::make_shared<ConfigItemBuilder>(item->GetDebugInfo());
+ ConfigItemBuilder::Ptr builder = boost::make_shared<ConfigItemBuilder>(debug_info);
builder->SetType("Service");
builder->SetName(name);
- builder->AddExpression("host_name", OperatorSet, GetName());
+ builder->AddExpression("host_name", OperatorSet, host_name);
builder->AddExpression("display_name", OperatorSet, svcname);
builder->AddExpression("short_name", OperatorSet, svcname);
- CopyServiceAttributes<false>(this, builder);
+ CopyServiceAttributes<false>(self, builder);
if (svcdesc.IsScalar()) {
builder->AddParent(svcdesc);
}
ConfigItem::Ptr serviceItem = builder->Compile();
- ConfigItem::Commit(serviceItem);
+ DynamicObject::Ptr dobj = ConfigItem::Commit(serviceItem);
newServices->Set(name, serviceItem);
}
newServices->Seal();
- Set("slave_services", newServices);
+ self->Set("slave_services", newServices);
}
void Host::OnAttributeChanged(const String& name, const Value&)
if (name == "hostgroups")
HostGroup::InvalidateMembersCache();
else if (name == "services") {
- ObjectLock olock(this);
- UpdateSlaveServices();
+ UpdateSlaveServices(GetSelf());
} else if (name == "notifications") {
set<Service::Ptr> services;
}
BOOST_FOREACH(const Service::Ptr& service, services) {
- ObjectLock olock(service);
- service->UpdateSlaveNotifications();
+ Service::UpdateSlaveNotifications(service);
}
+ } else if (name == "hostcheck") {
+ ObjectLock olock(this);
+ m_HostCheckService = GetServiceByShortName(GetHostCheck());
}
}
{
set<Service::Ptr> services;
+ boost::mutex::scoped_lock lock(m_Mutex);
+
ValidateServicesCache();
Service::WeakPtr wservice;
void Host::InvalidateServicesCache(void)
{
+ boost::mutex::scoped_lock lock(m_Mutex);
m_ServicesCacheValid = false;
m_ServicesCache.clear();
}
+/**
+ * @threadsafety Caller must hold m_Mutex.
+ */
void Host::ValidateServicesCache(void)
{
if (m_ServicesCacheValid)
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) {
const Service::Ptr& service = static_pointer_cast<Service>(object);
+ Host::Ptr host;
+ String short_name;
+
+ {
+ ObjectLock olock(service);
+ host = service->GetHost();
+ short_name = service->GetShortName();
+ }
+
+ String host_name;
+
+ {
+ ObjectLock olock(host);
+ host_name = host->GetName();
+ }
+
// TODO: assert for duplicate short_names
- m_ServicesCache[service->GetHost()->GetName()][service->GetShortName()] = service;
+ m_ServicesCache[host_name][short_name] = service;
}
m_ServicesCacheValid = true;
Service::Ptr Host::GetServiceByShortName(const Value& name) const
{
if (name.IsScalar()) {
- ValidateServicesCache();
- map<String, weak_ptr<Service> >& services = m_ServicesCache[GetName()];
- map<String, weak_ptr<Service> >::iterator it = services.find(name);
+ {
+ boost::mutex::scoped_lock lock(m_Mutex);
+
+ ValidateServicesCache();
+
+ map<String, weak_ptr<Service> >& services = m_ServicesCache[GetName()];
+ map<String, weak_ptr<Service> >::iterator it = services.find(name);
- if (it != services.end()) {
- Service::Ptr service = it->second.lock();
- assert(service);
- return service;
+ if (it != services.end()) {
+ Service::Ptr service = it->second.lock();
+ assert(service);
+ return service;
+ }
}
return Service::GetByName(name);
Service::Ptr Host::GetHostCheckService(void) const
{
- String hostcheck = GetHostCheck();
-
- if (hostcheck.IsEmpty())
- return Service::Ptr();
-
- Service::Ptr service = GetServiceByShortName(hostcheck);
-
- if (service->GetHost()->GetName() != GetName())
- BOOST_THROW_EXCEPTION(runtime_error("Hostcheck service refers to another host's service."));
-
- return service;
+ return m_HostCheckService.lock();
}
set<Service::Ptr> Host::GetParentServices(void) const
void OnAttributeChanged(const String& name, const Value& oldValue);
private:
+ Attribute<String> m_DisplayName;
+ Attribute<Dictionary::Ptr> m_HostGroups;
+ Attribute<Dictionary::Ptr> m_Macros;
+ Attribute<Dictionary::Ptr> m_HostDependencies;
+ Attribute<Dictionary::Ptr> m_ServiceDependencies;
+ Attribute<String> m_HostCheck;
+ Dictionary::Ptr m_SlaveServices;
+
+ static boost::mutex m_Mutex;
static map<String, map<String, weak_ptr<Service> > > m_ServicesCache;
static bool m_ServicesCacheValid;
- void UpdateSlaveServices(void);
+ static void UpdateSlaveServices(const Host::Ptr& self);
static void ValidateServicesCache(void);
+
+ weak_ptr<Service> m_HostCheckService;
};
}
HostGroup::HostGroup(const Dictionary::Ptr& properties)
: DynamicObject(properties)
-{ }
+{
+ RegisterAttribute("display_name", Attribute_Config, &m_DisplayName);
+ RegisterAttribute("notes_url", Attribute_Config, &m_NotesUrl);
+ RegisterAttribute("action_url", Attribute_Config, &m_ActionUrl);
+}
String HostGroup::GetDisplayName(void) const
{
- String value = Get("display_name");
-
- if (!value.IsEmpty())
- return value;
+ if (!m_DisplayName.IsEmpty())
+ return m_DisplayName;
else
return GetName();
}
String HostGroup::GetNotesUrl(void) const
{
- return Get("notes_url");
+ return m_NotesUrl;
}
String HostGroup::GetActionUrl(void) const
{
- return Get("action_url");
+ return m_ActionUrl;
}
/**
static void InvalidateMembersCache(void);
private:
+ Attribute<String> m_DisplayName;
+ Attribute<String> m_NotesUrl;
+ Attribute<String> m_ActionUrl;
+
static boost::mutex m_Mutex;
static map<String, vector<weak_ptr<Host> > > m_MembersCache;
static bool m_MembersCacheValid;
IcingaApplication::IcingaApplication(const Dictionary::Ptr& serializedUpdate)
: Application(serializedUpdate)
-{ }
+{
+ RegisterAttribute("cert_path", Attribute_Config, &m_CertPath);
+ RegisterAttribute("ca_path", Attribute_Config, &m_CAPath);
+ RegisterAttribute("node", Attribute_Config, &m_Node);
+ RegisterAttribute("service", Attribute_Config, &m_Service);
+ RegisterAttribute("pid_path", Attribute_Config, &m_PidPath);
+ RegisterAttribute("state_path", Attribute_Config, &m_StatePath);
+ RegisterAttribute("macros", Attribute_Config, &m_Macros);
+}
/**
* The entry point for the Icinga application.
String IcingaApplication::GetCertificateFile(void) const
{
- return Get("cert_path");
+ return m_CertPath;
}
String IcingaApplication::GetCAFile(void) const
{
- return Get("ca_path");
+ return m_CAPath;
}
String IcingaApplication::GetNode(void) const
{
- return Get("node");
+ return m_Node;
}
String IcingaApplication::GetService(void) const
{
- return Get("service");
+ return m_Service;
}
String IcingaApplication::GetPidPath(void) const
{
- Value pidPath = Get("pid_path");
-
- if (pidPath.IsEmpty())
- pidPath = Application::GetLocalStateDir() + "/run/icinga2.pid";
-
- return pidPath;
+ if (m_PidPath.IsEmpty())
+ return Application::GetLocalStateDir() + "/run/icinga2.pid";
+ else
+ return m_PidPath;
}
String IcingaApplication::GetStatePath(void) const
{
- Value statePath = Get("state_path");
-
- if (statePath.IsEmpty())
- statePath = Application::GetLocalStateDir() + "/lib/icinga2/icinga2.state";
-
- return statePath;
+ if (m_PidPath.IsEmpty())
+ return Application::GetLocalStateDir() + "/lib/icinga2/icinga2.state";
+ else
+ return m_PidPath;
}
Dictionary::Ptr IcingaApplication::GetMacros(void) const
{
- return Get("macros");
+ return m_Macros;
}
double IcingaApplication::GetStartTime(void) const
static Dictionary::Ptr CalculateDynamicMacros(const IcingaApplication::Ptr& self);
private:
+ Attribute<String> m_CertPath;
+ Attribute<String> m_CAPath;
+ Attribute<String> m_Node;
+ Attribute<String> m_Service;
+ Attribute<String> m_PidPath;
+ Attribute<String> m_StatePath;
+ Attribute<Dictionary::Ptr> m_Macros;
+
shared_ptr<SSL_CTX> m_SSLContext;
double m_StartTime;
Notification::Notification(const Dictionary::Ptr& properties)
: DynamicObject(properties)
{
+ RegisterAttribute("notification_command", Attribute_Config, &m_NotificationCommand);
+ RegisterAttribute("macros", Attribute_Config, &m_Macros);
+ RegisterAttribute("users", Attribute_Config, &m_Users);
+ RegisterAttribute("host_name", Attribute_Config, &m_HostName);
+ RegisterAttribute("service", Attribute_Config, &m_Service);
+
Service::InvalidateNotificationsCache();
}
Service::Ptr Notification::GetService(void) const
{
- Host::Ptr host = Host::GetByName(Get("host_name"));
- String service = Get("service");
+ Host::Ptr host = Host::GetByName(m_HostName);
- if (service.IsEmpty())
+ if (m_Service.IsEmpty())
return host->GetHostCheckService();
else
- return host->GetServiceByShortName(service);
+ return host->GetServiceByShortName(m_Service);
}
Value Notification::GetNotificationCommand(void) const
{
- return Get("notification_command");
+ return m_NotificationCommand;
}
Dictionary::Ptr Notification::GetMacros(void) const
{
- return Get("macros");
+ return m_Macros;
}
set<User::Ptr> Notification::GetUsers(void) const
{
set<User::Ptr> result;
- Dictionary::Ptr users = Get("users");
+ Dictionary::Ptr users = m_Users;
if (users) {
String name;
void OnAttributeChanged(const String& name, const Value& oldValue);
private:
+ Attribute<Value> m_NotificationCommand;
+ Attribute<Dictionary::Ptr> m_Macros;
+ Attribute<Dictionary::Ptr> m_Users;
+ Attribute<String> m_HostName;
+ Attribute<String> m_Service;
+
set<ScriptTask::Ptr> m_Tasks;
void NotificationCompletedHandler(const ScriptTask::Ptr& task);
Value Service::GetCheckCommand(void) const
{
- return Get("check_command");
+ return m_CheckCommand;
}
long Service::GetMaxCheckAttempts(void) const
{
- Value value = Get("max_check_attempts");
-
- if (value.IsEmpty())
+ if (m_MaxCheckAttempts.IsEmpty())
return DefaultMaxCheckAttempts;
- return value;
+ return m_MaxCheckAttempts;
}
double Service::GetCheckInterval(void) const
{
- Value value = Get("check_interval");
-
- if (value.IsEmpty())
+ if (m_CheckInterval.IsEmpty())
return DefaultCheckInterval;
- return value;
+ return m_CheckInterval;
}
double Service::GetRetryInterval(void) const
{
- Value value = Get("retry_interval");
-
- if (value.IsEmpty())
+ if (m_RetryInterval.IsEmpty())
return GetCheckInterval() / CheckIntervalDivisor;
- return value;
+ return m_RetryInterval;
}
Dictionary::Ptr Service::GetCheckers(void) const
{
- return Get("checkers");
+ return m_Checkers;
}
void Service::SetSchedulingOffset(long offset)
{
- Set("scheduling_offset", offset);
+ m_SchedulingOffset = offset;
}
long Service::GetSchedulingOffset(void)
{
- Value value = Get("scheduling_offset");
-
- if (value.IsEmpty()) {
- value = rand();
- SetSchedulingOffset(value);
- }
-
- return value;
-}
-
-void Service::SetFirstCheck(bool first)
-{
- Set("first_check", first ? 1 : 0);
+ return m_SchedulingOffset;
}
-bool Service::GetFirstCheck(void) const
-{
- Value value = Get("first_check");
-
- if (value.IsEmpty())
- return true;
-
- return static_cast<long>(value);
-}
-
-
void Service::SetNextCheck(double nextCheck)
{
- Set("next_check", nextCheck);
+ m_NextCheck = nextCheck;
+ Touch("next_check");
}
double Service::GetNextCheck(void)
{
- Value value = Get("next_check");
-
- if (value.IsEmpty()) {
+ if (m_NextCheck.IsEmpty()) {
UpdateNextCheck();
- value = Get("next_check");
-
- if (value.IsEmpty())
+ if (m_NextCheck.IsEmpty())
BOOST_THROW_EXCEPTION(runtime_error("Failed to schedule next check."));
}
- return value;
+ return m_NextCheck;
}
void Service::UpdateNextCheck(void)
SetNextCheck(now - adj + interval);
}
-void Service::SetChecker(const String& checker)
+void Service::SetCurrentChecker(const String& checker)
{
- Set("checker", checker);
+ m_CurrentChecker = checker;
+ Touch("current_checker");
}
-String Service::GetChecker(void) const
+String Service::GetCurrentChecker(void) const
{
- return Get("checker");
+ return m_CurrentChecker;
}
void Service::SetCurrentCheckAttempt(long attempt)
{
- Set("check_attempt", attempt);
+ m_CheckAttempt = attempt;
+ Touch("check_attempt");
}
long Service::GetCurrentCheckAttempt(void) const
{
- Value value = Get("check_attempt");
-
- if (value.IsEmpty())
+ if (m_CheckAttempt.IsEmpty())
return 1;
- return value;
+ return m_CheckAttempt;
}
void Service::SetState(ServiceState state)
{
- Set("state", static_cast<long>(state));
+ m_State = static_cast<long>(state);
+ Touch("state");
}
ServiceState Service::GetState(void) const
{
- Value value = Get("state");
-
- if (value.IsEmpty())
+ if (m_State.IsEmpty())
return StateUnknown;
- int ivalue = static_cast<int>(value);
+ int ivalue = static_cast<int>(m_State);
return static_cast<ServiceState>(ivalue);
}
void Service::SetStateType(ServiceStateType type)
{
- Set("state_type", static_cast<long>(type));
+ m_StateType = static_cast<long>(type);
+ Touch("state_type");
}
ServiceStateType Service::GetStateType(void) const
{
- Value value = Get("state_type");
-
- if (value.IsEmpty())
+ if (m_StateType.IsEmpty())
return StateTypeSoft;
- int ivalue = static_cast<int>(value);
+ int ivalue = static_cast<int>(m_StateType);
return static_cast<ServiceStateType>(ivalue);
}
void Service::SetLastCheckResult(const Dictionary::Ptr& result)
{
- Set("last_result", result);
+ m_LastResult = result;
+ Touch("last_result");
}
Dictionary::Ptr Service::GetLastCheckResult(void) const
{
- return Get("last_result");
+ return m_LastResult;
}
void Service::SetLastStateChange(double ts)
{
- Set("last_state_change", static_cast<long>(ts));
+ m_LastStateChange = ts;
+ Touch("last_state_change");
}
double Service::GetLastStateChange(void) const
{
- Value value = Get("last_state_change");
-
- if (value.IsEmpty())
+ if (m_LastStateChange.IsEmpty())
return IcingaApplication::GetInstance()->GetStartTime();
- return value;
+ return m_LastStateChange;
}
void Service::SetLastHardStateChange(double ts)
{
- Set("last_hard_state_change", ts);
+ m_LastHardStateChange = ts;
+ Touch("last_hard_state_change");
}
double Service::GetLastHardStateChange(void) const
{
- Value value = Get("last_hard_state_change");
-
- if (value.IsEmpty())
- value = IcingaApplication::GetInstance()->GetStartTime();
+ if (m_LastHardStateChange.IsEmpty())
+ return IcingaApplication::GetInstance()->GetStartTime();
- return value;
+ return m_LastHardStateChange;
}
bool Service::GetEnableActiveChecks(void) const
{
- Value value = Get("enable_active_checks");
-
- if (value.IsEmpty())
+ if (m_EnableActiveChecks.IsEmpty())
return true;
- return static_cast<bool>(value);
+ return static_cast<bool>(m_EnableActiveChecks);
}
void Service::SetEnableActiveChecks(bool enabled)
{
- Set("enable_active_checks", enabled ? 1 : 0);
+ m_EnableActiveChecks = enabled ? 1 : 0;
+ Touch("enable_active_checks");
}
bool Service::GetEnablePassiveChecks(void) const
{
- Value value = Get("enable_passive_checks");
-
- if (value.IsEmpty())
+ if (m_EnablePassiveChecks.IsEmpty())
return true;
- return static_cast<bool>(value);
+ return static_cast<bool>(m_EnablePassiveChecks);
}
void Service::SetEnablePassiveChecks(bool enabled)
{
- Set("enable_passive_checks", enabled ? 1 : 0);
+ m_EnablePassiveChecks = enabled ? 1 : 0;
+ Touch("enable_passive_checks");
}
bool Service::GetForceNextCheck(void) const
{
- Value value = Get("force_next_check");
-
- if (value.IsEmpty())
+ if (m_ForceNextCheck.IsEmpty())
return false;
- return static_cast<bool>(value);
+ return static_cast<bool>(m_ForceNextCheck);
}
void Service::SetForceNextCheck(bool forced)
{
- Set("force_next_check", forced ? 1 : 0);
+ m_ForceNextCheck = forced ? 1 : 0;
+ Touch("force_next_check");
}
void Service::ApplyCheckResult(const Dictionary::Ptr& cr)
ObjectLock slock(self);
/* don't run another check if there is one pending */
- if (!self->Get("current_task").IsEmpty()) {
+ if (self->m_CurrentTask) {
slock.Unlock();
/* we need to call the callback anyway */
{
ObjectLock olock(self);
task = self->MakeMethodTask("check", arguments);
- self->Set("current_task", task);
+ self->m_CurrentTask = task;
}
task->Start(boost::bind(&Service::CheckCompletedHandler, self, checkInfo, _1, callback));
if (!result->Contains("active"))
result->Set("active", 1);
- if (!result->Contains("checker")) {
+ if (!result->Contains("current_checker")) {
EndpointManager::Ptr em = EndpointManager::GetInstance();
ObjectLock olock(em);
- result->Set("checker", em->GetIdentity());
+ result->Set("current_checker", em->GetIdentity());
}
}
if (result)
ProcessCheckResult(result);
- Set("current_task", Empty);
+ m_CurrentTask.reset();
/* figure out when the next check is for this service; the call to
* ApplyCheckResult() should've already done this but lets do it again
Dictionary::Ptr Service::GetComments(void) const
{
- Service::ValidateCommentsCache();
-
- return Get("comments");
+ return m_Comments;
}
String Service::AddComment(CommentType entryType, const String& author,
comment->Set("expire_time", expireTime);
comment->Set("legacy_id", m_NextCommentID++);
- Dictionary::Ptr comments = Get("comments");
+ Dictionary::Ptr comments = m_Comments;
if (!comments)
comments = boost::make_shared<Dictionary>();
String id = Utility::NewUUID();
comments->Set(id, comment);
- Set("comments", comments);
+
+ m_Comments = comments;
+ Touch("comments");
return id;
}
if (!owner)
return;
- Dictionary::Ptr comments = owner->Get("comments");
+ Dictionary::Ptr comments = owner->m_Comments;
if (comments) {
comments->Remove(id);
if (!owner)
return Dictionary::Ptr();
- Dictionary::Ptr comments = owner->Get("comments");
+ Dictionary::Ptr comments = owner->m_Comments;
if (comments) {
Dictionary::Ptr comment = comments->Get(id);
void Service::AddCommentsToCache(void)
{
- Dictionary::Ptr comments = Get("comments");
+ Dictionary::Ptr comments = m_Comments;
if (!comments)
return;
void Service::RemoveExpiredComments(void)
{
- Dictionary::Ptr comments = Get("comments");
+ Dictionary::Ptr comments = m_Comments;
if (!comments)
return;
Dictionary::Ptr Service::GetDowntimes(void) const
{
- Service::ValidateDowntimesCache();
-
- return Get("downtimes");
+ return m_Downtimes;
}
String Service::AddDowntime(const String& author, const String& comment,
otherOwner->Touch("downtimes");
}
- Dictionary::Ptr downtimes = Get("downtimes");
+ Dictionary::Ptr downtimes = m_Downtimes;
if (!downtimes)
downtimes = boost::make_shared<Dictionary>();
String id = Utility::NewUUID();
downtimes->Set(id, downtime);
- Set("downtimes", downtimes);
+
+ m_Downtimes = downtimes;
+ Touch("downtimes");
return id;
}
if (!owner)
return;
- Dictionary::Ptr downtimes = owner->Get("downtimes");
+ Dictionary::Ptr downtimes = owner->m_Downtimes;
if (!downtimes)
return;
void Service::TriggerDowntimes(void)
{
- Dictionary::Ptr downtimes = Get("downtimes");
+ Dictionary::Ptr downtimes = m_Downtimes;
if (!downtimes)
return;
if (!owner)
return Dictionary::Ptr();
- Dictionary::Ptr downtimes = owner->Get("downtimes");
+ Dictionary::Ptr downtimes = owner->m_Downtimes;
if (downtimes) {
Dictionary::Ptr downtime = downtimes->Get(id);
void Service::AddDowntimesToCache(void)
{
- Dictionary::Ptr downtimes = Get("downtimes");
+ Dictionary::Ptr downtimes = m_Downtimes;
if (!downtimes)
return;
void Service::RemoveExpiredDowntimes(void)
{
- Dictionary::Ptr downtimes = Get("downtimes");
+ Dictionary::Ptr downtimes = m_Downtimes;
if (!downtimes)
return;
builder->AddExpression("notification_interval", OperatorSet, notificationInterval);*/
}
-void Service::UpdateSlaveNotifications(void)
+void Service::UpdateSlaveNotifications(const Service::Ptr& self)
{
- ConfigItem::Ptr item = ConfigItem::GetObject("Service", GetName());
+ Dictionary::Ptr oldNotifications;
+ Host::Ptr host;
+ vector<Dictionary::Ptr> notificationDescsList;
+ String service_name;
+ ConfigItem::Ptr item;
- /* Don't create slave notifications unless we own this object
- * and it's not a template. */
- if (!item || IsAbstract())
- return;
+ {
+ ObjectLock olock(self);
+
+ item = ConfigItem::GetObject("Service", self->GetName());
+
+ /* Don't create slave notifications unless we own this object
+ * and it's not a template. */
+ if (!item || self->IsAbstract())
+ return;
- Dictionary::Ptr oldNotifications = Get("slave_notifications");
+ service_name = self->GetName();
+ oldNotifications = self->m_SlaveNotifications;
+ host = self->GetHost();
+
+ notificationDescsList.push_back(self->Get("notifications"));
+ }
+
+ DebugInfo debug_info;
+
+ {
+ ObjectLock ilock(item);
+ debug_info = item->GetDebugInfo();
+ }
Dictionary::Ptr newNotifications;
newNotifications = boost::make_shared<Dictionary>();
- vector<Dictionary::Ptr> notificationDescsList;
-
String host_name;
{
- Host::Ptr host = GetHost();
ObjectLock olock(host);
notificationDescsList.push_back(host->Get("notifications"));
host_name = host->GetName();
}
- notificationDescsList.push_back(Get("notifications"));
-
BOOST_FOREACH(const Dictionary::Ptr& notificationDescs, notificationDescsList) {
if (!notificationDescs)
continue;
+ ObjectLock olock(notificationDescs);
+
String nfcname;
Value nfcdesc;
BOOST_FOREACH(tie(nfcname, nfcdesc), notificationDescs) {
nfcname = nfcdesc;
stringstream namebuf;
- namebuf << GetName() << "-" << nfcname;
+ namebuf << service_name << "-" << nfcname;
String name = namebuf.str();
- ConfigItemBuilder::Ptr builder = boost::make_shared<ConfigItemBuilder>(item->GetDebugInfo());
+ ConfigItemBuilder::Ptr builder = boost::make_shared<ConfigItemBuilder>(debug_info);
builder->SetType("Notification");
builder->SetName(name);
builder->AddExpression("host_name", OperatorSet, host_name);
- builder->AddExpression("service", OperatorSet, GetName());
+ builder->AddExpression("service", OperatorSet, service_name);
- CopyNotificationAttributes(this, builder);
+ CopyNotificationAttributes(self, builder);
if (nfcdesc.IsScalar()) {
builder->AddParent(nfcdesc);
} else if (nfcdesc.IsObjectType<Dictionary>()) {
Dictionary::Ptr notification = nfcdesc;
+ ObjectLock nlock(notification);
Dictionary::Ptr templates = notification->Get("templates");
}
}
- Set("slave_notifications", newNotifications);
+ {
+ ObjectLock olock(self);
+ self->m_SlaveNotifications = newNotifications;
+ }
}
double Service::GetLastNotification(void) const
{
- Value value = Get("last_notification");
+ Value value = m_LastNotification;
if (value.IsEmpty())
value = 0;
void Service::SetLastNotification(double time)
{
- Set("last_notification", time);
+ m_LastNotification = time;
+ Touch("last_notification");
}
double Service::GetNextNotification(void) const
{
- Value value = Get("next_notification");
+ Value value = m_NextNotification;
if (value.IsEmpty())
value = 0;
void Service::SetNextNotification(double time)
{
- Set("next_notification", time);
+ m_NextNotification = time;
+ Touch("next_notification");
}
using namespace icinga;
-static AttributeDescription serviceAttributes[] = {
- { "scheduling_offset", Attribute_Transient },
- { "first_check", 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 },
- { "enable_active_checks", Attribute_Replicated },
- { "enable_passive_checks", Attribute_Replicated },
- { "force_next_check", Attribute_Replicated },
- { "acknowledgement", Attribute_Replicated },
- { "acknowledgement_expiry", Attribute_Replicated },
- { "downtimes", Attribute_Replicated },
- { "comments", Attribute_Replicated },
- { "last_notification", Attribute_Replicated },
- { "next_notification", Attribute_Replicated }
-};
-
-REGISTER_TYPE(Service, serviceAttributes);
+REGISTER_TYPE(Service, NULL);
Service::Service(const Dictionary::Ptr& serializedObject)
: DynamicObject(serializedObject)
-{ }
+{
+
+ RegisterAttribute("display_name", Attribute_Config, &m_DisplayName);
+ RegisterAttribute("macros", Attribute_Config, &m_Macros);
+ RegisterAttribute("hostdependencies", Attribute_Config, &m_HostDependencies);
+ RegisterAttribute("servicedependencies", Attribute_Config, &m_ServiceDependencies);
+ RegisterAttribute("servicegroups", Attribute_Config, &m_ServiceGroups);
+
+ RegisterAttribute("check_command", Attribute_Config, &m_CheckCommand);
+ RegisterAttribute("max_check_attempts", Attribute_Config, &m_MaxCheckAttempts);
+ RegisterAttribute("check_interval", Attribute_Config, &m_CheckInterval);
+ RegisterAttribute("retry_interval", Attribute_Config, &m_RetryInterval);
+ RegisterAttribute("checkers", Attribute_Config, &m_Checkers);
+
+ RegisterAttribute("next_check", Attribute_Replicated, &m_NextCheck);
+ RegisterAttribute("current_checker", Attribute_Replicated, &m_CurrentChecker);
+ RegisterAttribute("check_attempt", Attribute_Replicated, &m_CheckAttempt);
+ RegisterAttribute("state", Attribute_Replicated, &m_State);
+ RegisterAttribute("state_type", Attribute_Replicated, &m_StateType);
+ RegisterAttribute("last_result", Attribute_Replicated, &m_LastResult);
+ RegisterAttribute("last_state_change", Attribute_Replicated, &m_LastStateChange);
+ RegisterAttribute("last_hard_state_change", Attribute_Replicated, &m_LastHardStateChange);
+ RegisterAttribute("enable_active_checks", Attribute_Replicated, &m_EnableActiveChecks);
+ RegisterAttribute("enable_passive_checks", Attribute_Replicated, &m_EnablePassiveChecks);
+ RegisterAttribute("force_next_check", Attribute_Replicated, &m_ForceNextCheck);
+
+ RegisterAttribute("short_name", Attribute_Config, &m_ShortName);
+ RegisterAttribute("host_name", Attribute_Config, &m_HostName);
+
+ RegisterAttribute("acknowledgement", Attribute_Replicated, &m_Acknowledgement);
+ RegisterAttribute("acknowledgement_expiry", Attribute_Replicated, &m_AcknowledgementExpiry);
+
+ RegisterAttribute("comments", Attribute_Replicated, &m_Comments);
+
+ RegisterAttribute("downtimes", Attribute_Replicated, &m_Downtimes);
+
+ RegisterAttribute("last_notification", Attribute_Replicated, &m_LastNotification);
+ RegisterAttribute("next_notification", Attribute_Replicated, &m_NextNotification);
+
+ SetSchedulingOffset(rand());
+}
void Service::OnRegistrationCompleted(void)
{
{
ObjectLock olock(this);
- UpdateSlaveNotifications();
+ m_Host = Host::GetByName(GetHostName());
}
}
String Service::GetDisplayName(void) const
{
- String value = Get("display_name");
-
- if (value.IsEmpty())
+ if (m_DisplayName.IsEmpty())
return GetShortName();
-
- return value;
+ else
+ return m_DisplayName;
}
/**
Host::Ptr Service::GetHost(void) const
{
- String hostname = Get("host_name");
-
- if (hostname.IsEmpty())
- BOOST_THROW_EXCEPTION(runtime_error("Service object is missing the 'host_name' property."));
-
- return Host::GetByName(hostname);
+ return m_Host;
}
Dictionary::Ptr Service::GetMacros(void) const
{
- return Get("macros");
+ return m_Macros;
}
Dictionary::Ptr Service::GetHostDependencies(void) const
{
- return Get("hostdependencies");
+ return m_HostDependencies;
}
Dictionary::Ptr Service::GetServiceDependencies(void) const
{
- return Get("servicedependencies");
+ return m_ServiceDependencies;
}
Dictionary::Ptr Service::GetGroups(void) const
{
- return Get("servicegroups");
+ return m_ServiceGroups;
}
-String Service::GetShortName(void) const
+String Service::GetHostName(void) const
{
- Value value = Get("short_name");
+ return m_HostName;
+}
- if (value.IsEmpty())
+String Service::GetShortName(void) const
+{
+ if (m_ShortName.IsEmpty())
return GetName();
-
- return value;
+ else
+ return m_ShortName;
}
bool Service::IsReachable(const Service::Ptr& self)
AcknowledgementType Service::GetAcknowledgement(void)
{
- Value value = Get("acknowledgement");
-
- if (value.IsEmpty())
+ if (m_Acknowledgement.IsEmpty())
return AcknowledgementNone;
- int ivalue = static_cast<int>(value);
+ int ivalue = static_cast<int>(m_Acknowledgement);
AcknowledgementType avalue = static_cast<AcknowledgementType>(ivalue);
if (avalue != AcknowledgementNone) {
void Service::SetAcknowledgement(AcknowledgementType acknowledgement)
{
- Set("acknowledgement", static_cast<long>(acknowledgement));
+ m_Acknowledgement = acknowledgement;
+ Touch("acknowledgement");
}
bool Service::IsAcknowledged(void)
double Service::GetAcknowledgementExpiry(void) const
{
- Value value = Get("acknowledgement_expiry");
-
- if (value.IsEmpty())
+ if (m_AcknowledgementExpiry.IsEmpty())
return 0;
- return static_cast<double>(value);
+ return static_cast<double>(m_AcknowledgementExpiry);
}
void Service::SetAcknowledgementExpiry(double timestamp)
{
- Set("acknowledgement_expiry", timestamp);
+ m_AcknowledgementExpiry = timestamp;
+ Touch("acknowledgement_expiry");
}
void Service::AcknowledgeProblem(AcknowledgementType type, double expiry)
void Service::OnAttributeChanged(const String& name, const Value& oldValue)
{
- if (name == "checker")
+ if (name == "current_checker")
OnCheckerChanged(GetSelf(), oldValue);
else if (name == "next_check")
OnNextCheckChanged(GetSelf(), oldValue);
else if (name == "host_name" || name == "short_name") {
Host::InvalidateServicesCache();
- {
- ObjectLock olock(this);
- UpdateSlaveNotifications();
- }
+ UpdateSlaveNotifications(GetSelf());
+
+ if (name == "host_name")
+ m_Host = Host::GetByName(GetHostName());
} else if (name == "downtimes")
Service::InvalidateDowntimesCache();
else if (name == "comments")
Service::InvalidateCommentsCache();
else if (name == "notifications")
- UpdateSlaveNotifications();
+ UpdateSlaveNotifications(GetSelf());
else if (name == "check_interval") {
ObjectLock(this);
ConfigItem::Ptr item = ConfigItem::GetObject("Service", GetName());
Dictionary::Ptr GetHostDependencies(void) const;
Dictionary::Ptr GetServiceDependencies(void) const;
Dictionary::Ptr GetGroups(void) const;
+ String GetHostName(void) const;
String GetShortName(void) const;
static Dictionary::Ptr CalculateDynamicMacros(const Service::Ptr& self);
long GetSchedulingOffset(void);
void SetSchedulingOffset(long offset);
- void SetFirstCheck(bool first);
- bool GetFirstCheck(void) const;
-
void SetNextCheck(double nextCheck);
double GetNextCheck(void);
void UpdateNextCheck(void);
- void SetChecker(const String& checker);
- String GetChecker(void) const;
+ void SetCurrentChecker(const String& checker);
+ String GetCurrentChecker(void) const;
bool IsAllowedChecker(const String& checker) const;
set<Notification::Ptr> GetNotifications(void) const;
- void UpdateSlaveNotifications(void);
+ static void UpdateSlaveNotifications(const Service::Ptr& self);
double GetLastNotification(void) const;
void SetLastNotification(double time);
virtual void OnAttributeChanged(const String& name, const Value& oldValue);
private:
+ Host::Ptr m_Host;
+ Dictionary::Ptr m_SlaveNotifications;
+
+ Attribute<String> m_DisplayName;
+ Attribute<Dictionary::Ptr> m_Macros;
+ Attribute<Dictionary::Ptr> m_HostDependencies;
+ Attribute<Dictionary::Ptr> m_ServiceDependencies;
+ Attribute<Dictionary::Ptr> m_ServiceGroups;
+ Attribute<String> m_ShortName;
+ Attribute<long> m_Acknowledgement;
+ Attribute<double> m_AcknowledgementExpiry;
+ Attribute<String> m_HostName;
+
+ /* Checks */
+ Attribute<Value> m_CheckCommand;
+ Attribute<long> m_MaxCheckAttempts;
+ Attribute<double> m_CheckInterval;
+ Attribute<double> m_RetryInterval;
+ Attribute<double> m_NextCheck;
+ Attribute<Dictionary::Ptr> m_Checkers;
+ Attribute<String> m_CurrentChecker;
+ Attribute<long> m_CheckAttempt;
+ Attribute<long> m_State;
+ Attribute<long> m_StateType;
+ Attribute<Dictionary::Ptr> m_LastResult;
+ Attribute<double> m_LastStateChange;
+ Attribute<double> m_LastHardStateChange;
+ Attribute<bool> m_EnableActiveChecks;
+ Attribute<bool> m_EnablePassiveChecks;
+ Attribute<bool> m_ForceNextCheck;
+
+ ScriptTask::Ptr m_CurrentTask;
+ long m_SchedulingOffset;
+
void CheckCompletedHandler(const Dictionary::Ptr& checkInfo,
const ScriptTask::Ptr& task, const function<void (void)>& callback);
/* Downtimes */
+ Attribute<Dictionary::Ptr> m_Downtimes;
+
static int m_NextDowntimeID;
static map<int, String> m_LegacyDowntimesCache;
void RemoveExpiredDowntimes(void);
/* Comments */
+ Attribute<Dictionary::Ptr> m_Comments;
+
static int m_NextCommentID;
static map<int, String> m_LegacyCommentsCache;
void RemoveExpiredComments(void);
/* Notifications */
+ Attribute<double> m_LastNotification;
+ Attribute<double> m_NextNotification;
+
static map<String, set<Notification::WeakPtr> > m_NotificationsCache;
static bool m_NotificationsCacheValid;
};
ServiceGroup::ServiceGroup(const Dictionary::Ptr& properties)
: DynamicObject(properties)
-{ }
+{
+ RegisterAttribute("display_name", Attribute_Config, &m_DisplayName);
+ RegisterAttribute("notes_url", Attribute_Config, &m_NotesUrl);
+ RegisterAttribute("action_url", Attribute_Config, &m_ActionUrl);
+}
String ServiceGroup::GetDisplayName(void) const
{
- String value = Get("display_name");
-
- if (!value.IsEmpty())
- return value;
+ if (!m_DisplayName.Get().IsEmpty())
+ return m_DisplayName;
else
return GetName();
}
String ServiceGroup::GetNotesUrl(void) const
{
- return Get("notes_url");
+ return m_NotesUrl;
}
String ServiceGroup::GetActionUrl(void) const
{
- return Get("action_url");
+ return m_ActionUrl;
}
/**
static void InvalidateMembersCache(void);
private:
+ Attribute<String> m_DisplayName;
+ Attribute<String> m_NotesUrl;
+ Attribute<String> m_ActionUrl;
+
static boost::mutex m_Mutex;
static map<String, vector<weak_ptr<Service> > > m_MembersCache;
static bool m_MembersCacheValid;
User::User(const Dictionary::Ptr& properties)
: DynamicObject(properties)
-{ }
+{
+ RegisterAttribute("macros", Attribute_Config, &m_Macros);
+}
bool User::Exists(const String& name)
{
Dictionary::Ptr User::GetMacros(void) const
{
- return Get("macros");
+ return m_Macros;
}
Dictionary::Ptr User::CalculateDynamicMacros(const User::Ptr& self)
Dictionary::Ptr GetMacros(void) const;
static Dictionary::Ptr CalculateDynamicMacros(const User::Ptr& self);
+
+private:
+ Attribute<Dictionary::Ptr> m_Macros;
};
}
using namespace icinga;
-static AttributeDescription endpointAttributes[] = {
- { "node", Attribute_Replicated },
- { "service", Attribute_Replicated },
- { "subscriptions", Attribute_Replicated },
- { "client", Attribute_Transient }
-};
-
-REGISTER_TYPE(Endpoint, endpointAttributes);
+REGISTER_TYPE(Endpoint, NULL);
signals2::signal<void (const Endpoint::Ptr&)> Endpoint::OnConnected;
signals2::signal<void (const Endpoint::Ptr&)> Endpoint::OnDisconnected;
*/
Endpoint::Endpoint(const Dictionary::Ptr& serializedUpdate)
: DynamicObject(serializedUpdate)
-{ }
+{
+ RegisterAttribute("local", Attribute_Config, &m_Local);
+
+ RegisterAttribute("node", Attribute_Replicated, &m_Node);
+ RegisterAttribute("service", Attribute_Replicated, &m_Service);
+ RegisterAttribute("subscriptions", Attribute_Replicated, &m_Subscriptions);
+}
/**
* Checks whether an endpoint with the specified name exists.
*/
bool Endpoint::IsLocalEndpoint(void) const
{
- Value value = Get("local");
-
- return (!value.IsEmpty() && value);
+ return m_Local;
}
/**
JsonRpcConnection::Ptr Endpoint::GetClient(void) const
{
- return Get("client");
+ return m_Client;
}
void Endpoint::SetClient(const JsonRpcConnection::Ptr& client)
{
- Set("client", client);
+ m_Client = client;
client->OnNewMessage.connect(boost::bind(&Endpoint::NewMessageHandler, this, _2));
client->OnClosed.connect(boost::bind(&Endpoint::ClientClosedHandler, this));
*/
void Endpoint::ClearSubscriptions(void)
{
- Set("subscriptions", Empty);
+ m_Subscriptions = Empty;
+ Touch("subscriptions");
}
Dictionary::Ptr Endpoint::GetSubscriptions(void) const
{
- return Get("subscriptions");
+ return m_Subscriptions;
}
void Endpoint::SetSubscriptions(const Dictionary::Ptr& subscriptions)
{
- Set("subscriptions", subscriptions);
+ m_Subscriptions = subscriptions;
+ Touch("subscriptions");
}
void Endpoint::RegisterTopicHandler(const String& topic, const function<Endpoint::Callback>& callback)
// timer for that, once we have a TTL property for the topics)
ClearSubscriptions();
- Set("client", Empty);
+ m_Client.reset();
OnDisconnected(GetSelf());
}
*/
String Endpoint::GetNode(void) const
{
- return Get("node");
+ return m_Node;
}
/**
*/
String Endpoint::GetService(void) const
{
- return Get("service");
+ return m_Service;
}
static signals2::signal<void (const Endpoint::Ptr&, const String& topic)> OnSubscriptionUnregistered;
private:
+ Attribute<bool> m_Local;
+ Attribute<Dictionary::Ptr> m_Subscriptions;
+ Attribute<String> m_Node;
+ Attribute<String> m_Service;
+
+ JsonRpcConnection::Ptr m_Client;
+
bool m_ReceivedWelcome; /**< Have we received a welcome message
from this endpoint? */
bool m_SentWelcome; /**< Have we sent a welcome message to this