From 35c79a76c15d616b1c5c2a424bbb1ba08031334a Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Tue, 26 Feb 2013 10:13:54 +0100 Subject: [PATCH] Make attribute lookups O(1). --- components/checker/checkercomponent.cpp | 3 +- components/compat/compatcomponent.cpp | 24 ++- components/delegation/delegationcomponent.cpp | 10 +- .../replication/replicationcomponent.cpp | 2 +- configure.ac | 7 +- lib/base/dynamicobject.cpp | 116 ++++++------- lib/base/dynamicobject.h | 151 ++++++++++++++++- lib/base/dynamictype.cpp | 10 +- lib/base/dynamictype.h | 6 +- lib/base/eventqueue.cpp | 23 ++- lib/base/eventqueue.h | 5 + lib/base/logger.cpp | 10 +- lib/base/logger.h | 4 + lib/base/script.cpp | 9 +- lib/base/script.h | 3 + lib/base/timer.cpp | 2 + lib/icinga/host.cpp | 153 ++++++++++------- lib/icinga/host.h | 13 +- lib/icinga/hostgroup.cpp | 16 +- lib/icinga/hostgroup.h | 4 + lib/icinga/icingaapplication.cpp | 40 +++-- lib/icinga/icingaapplication.h | 8 + lib/icinga/notification.cpp | 19 ++- lib/icinga/notification.h | 6 + lib/icinga/service-check.cpp | 160 +++++++----------- lib/icinga/service-comment.cpp | 18 +- lib/icinga/service-downtime.cpp | 20 +-- lib/icinga/service-notification.cpp | 66 +++++--- lib/icinga/service.cpp | 134 ++++++++------- lib/icinga/service.h | 51 +++++- lib/icinga/servicegroup.cpp | 16 +- lib/icinga/servicegroup.h | 4 + lib/icinga/user.cpp | 6 +- lib/icinga/user.h | 3 + lib/remoting/endpoint.cpp | 39 +++-- lib/remoting/endpoint.h | 7 + 36 files changed, 731 insertions(+), 437 deletions(-) diff --git a/components/checker/checkercomponent.cpp b/components/checker/checkercomponent.cpp index 565d52ad1..4ac847a9c 100644 --- a/components/checker/checkercomponent.cpp +++ b/components/checker/checkercomponent.cpp @@ -121,7 +121,6 @@ void CheckerComponent::CheckThreadProc(void) } service->SetForceNextCheck(false); - service->SetFirstCheck(false); Logger::Write(LogDebug, "checker", "Executing service check for '" + service->GetName() + "'"); @@ -177,7 +176,7 @@ void CheckerComponent::CheckerChangedHandler(const Service::Ptr& service) 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()) diff --git a/components/compat/compatcomponent.cpp b/components/compat/compatcomponent.cpp index eede038b0..bf4490be7 100644 --- a/components/compat/compatcomponent.cpp +++ b/components/compat/compatcomponent.cpp @@ -534,12 +534,14 @@ void CompatComponent::StatusTimerHandler(void) BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Host")) { Host::Ptr host = static_pointer_cast(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(); } @@ -547,6 +549,7 @@ void CompatComponent::StatusTimerHandler(void) HostGroup::Ptr hg = static_pointer_cast(object); stringstream tempobjectfp; + tempobjectfp << std::fixed; { ObjectLock olock(hg); @@ -568,12 +571,14 @@ void CompatComponent::StatusTimerHandler(void) BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) { Service::Ptr service = static_pointer_cast(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(); } @@ -581,6 +586,7 @@ void CompatComponent::StatusTimerHandler(void) ServiceGroup::Ptr sg = static_pointer_cast(object); stringstream tempobjectfp; + tempobjectfp << std::fixed; { ObjectLock olock(sg); diff --git a/components/delegation/delegationcomponent.cpp b/components/delegation/delegationcomponent.cpp index 1191bce94..fa928cb9b 100644 --- a/components/delegation/delegationcomponent.cpp +++ b/components/delegation/delegationcomponent.cpp @@ -102,7 +102,7 @@ void DelegationComponent::DelegationTimerHandler(void) services.push_back(service); ObjectLock olock(service); - String checker = service->GetChecker(); + String checker = service->GetCurrentChecker(); if (checker.IsEmpty()) continue; @@ -122,7 +122,7 @@ void DelegationComponent::DelegationTimerHandler(void) 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)) @@ -160,7 +160,7 @@ void DelegationComponent::DelegationTimerHandler(void) /* clear the service's current checker */ if (!checker.IsEmpty()) { - service->SetChecker(""); + service->SetCurrentChecker(""); if (oldEndpoint) histogram[oldEndpoint]--; @@ -173,7 +173,7 @@ void DelegationComponent::DelegationTimerHandler(void) continue; ObjectLock clock(candidate); - service->SetChecker(candidate->GetName()); + service->SetCurrentChecker(candidate->GetName()); histogram[candidate]++; /* reschedule the service; this avoids "check floods" @@ -207,7 +207,7 @@ void DelegationComponent::DelegationTimerHandler(void) continue; } - assert(!service->GetChecker().IsEmpty()); + assert(!service->GetCurrentChecker().IsEmpty()); } Endpoint::Ptr endpoint; diff --git a/components/replication/replicationcomponent.cpp b/components/replication/replicationcomponent.cpp index de1c1b4e0..414827b73 100644 --- a/components/replication/replicationcomponent.cpp +++ b/components/replication/replicationcomponent.cpp @@ -68,7 +68,7 @@ void ReplicationComponent::CheckResultRequestHandler(const RequestMessage& reque 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); diff --git a/configure.ac b/configure.ac index ec762f669..4d2f38cf4 100644 --- a/configure.ac +++ b/configure.ac @@ -75,8 +75,11 @@ AC_CHECK_FUNCS([backtrace_symbols execvpe pipe2]) 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) diff --git a/lib/base/dynamicobject.cpp b/lib/base/dynamicobject.cpp index 3a985c7d6..bf30a339a 100644 --- a/lib/base/dynamicobject.cpp +++ b/lib/base/dynamicobject.cpp @@ -35,12 +35,12 @@ signals2::signal DynamicObject::OnFlushObject; 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); @@ -50,7 +50,7 @@ DynamicObject::DynamicObject(const Dictionary::Ptr& 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); @@ -102,22 +102,22 @@ Dictionary::Ptr DynamicObject::BuildUpdate(double sinceTx, int attributeTypes) c Dictionary::Ptr attrs = boost::make_shared(); 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(); - 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); } @@ -180,7 +180,7 @@ void DynamicObject::ApplyUpdate(const Dictionary::Ptr& serializedUpdate, RegisterAttribute(it->first, Attribute_Config); if (!HasAttribute(it->first)) - RegisterAttribute(it->first, static_cast(type)); + RegisterAttribute(it->first, static_cast(type)); InternalSetAttribute(it->first, data, tx, true); } @@ -188,17 +188,19 @@ void DynamicObject::ApplyUpdate(const Dictionary::Ptr& serializedUpdate, } 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 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) @@ -219,27 +221,26 @@ Value DynamicObject::Get(const String& name) const 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 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. @@ -269,7 +270,7 @@ Value DynamicObject::InternalGetAttribute(const String& name) const if (it == m_Attributes.end()) return Empty; - return it->second.Data; + return it->second.GetValue(); } bool DynamicObject::HasAttribute(const String& name) const @@ -277,57 +278,46 @@ 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) @@ -371,13 +361,9 @@ void DynamicObject::Unregister(void) ScriptTask::Ptr DynamicObject::MakeMethodTask(const String& method, const vector& arguments) { - Value value = Get("methods"); - - if (!value.IsObjectType()) - return ScriptTask::Ptr(); - String funcName; - Dictionary::Ptr methods = value; + + Dictionary::Ptr methods = m_Methods; { ObjectLock olock(methods); diff --git a/lib/base/dynamicobject.h b/lib/base/dynamicobject.h index 9a84949ba..c15dd07ad 100644 --- a/lib/base/dynamicobject.h +++ b/lib/base/dynamicobject.h @@ -28,7 +28,7 @@ namespace icinga * * @ingroup base */ -enum DynamicAttributeType +enum AttributeType { Attribute_Transient = 1, @@ -48,16 +48,142 @@ enum DynamicAttributeType 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 +class Attribute : public AttributeBase +{ +public: + void Set(const T& value) + { + InternalSet(value); + } + + Attribute& 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(); + 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(); + 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; @@ -74,7 +200,7 @@ public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; - typedef map AttributeMap; + typedef map AttributeMap; typedef AttributeMap::iterator AttributeIterator; typedef AttributeMap::const_iterator AttributeConstIterator; @@ -86,7 +212,7 @@ public: 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); @@ -94,7 +220,9 @@ public: bool HasAttribute(const String& name) const; - void ClearAttributesByType(DynamicAttributeType type); + void BindAttribute(const String& name, Value *boundValue); + + void ClearAttributesByType(AttributeType type); static signals2::signal OnRegistered; static signals2::signal OnUnregistered; @@ -150,6 +278,13 @@ private: map m_ModifiedAttributes; double m_ConfigTx; + Attribute m_Name; + Attribute m_Type; + Attribute m_Local; + Attribute m_Abstract; + Attribute m_Source; + Attribute m_Methods; + bool m_EventSafe; static double m_CurrentTx; diff --git a/lib/base/dynamictype.cpp b/lib/base/dynamictype.cpp index f7ebce4e0..4e753b0b5 100644 --- a/lib/base/dynamictype.cpp +++ b/lib/base/dynamictype.cpp @@ -101,6 +101,12 @@ void DynamicType::RegisterObject(const DynamicObject::Ptr& object) /* notify the object that it's been registered */ object->OnRegistrationCompleted(); + + { + ObjectLock olock(object); + object->Flush(); + } + } void DynamicType::UnregisterObject(const DynamicObject::Ptr& object) @@ -148,7 +154,7 @@ DynamicObject::Ptr DynamicType::CreateObject(const Dictionary::Ptr& serializedUp /* register attributes */ String name; - DynamicAttributeType type; + AttributeType type; BOOST_FOREACH(tuples::tie(name, type), m_Attributes) object->RegisterAttribute(name, type); @@ -169,7 +175,7 @@ bool DynamicType::TypeExists(const String& name) return (GetByName(name)); } -void DynamicType::AddAttribute(const String& name, DynamicAttributeType type) +void DynamicType::AddAttribute(const String& name, AttributeType type) { m_Attributes[name] = type; } diff --git a/lib/base/dynamictype.h b/lib/base/dynamictype.h index 952e518aa..5db714be4 100644 --- a/lib/base/dynamictype.h +++ b/lib/base/dynamictype.h @@ -26,7 +26,7 @@ namespace icinga struct AttributeDescription { String Name; - DynamicAttributeType Type; + AttributeType Type; }; class I2_BASE_API DynamicType : public Object @@ -57,7 +57,7 @@ public: static set 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); @@ -66,7 +66,7 @@ public: private: String m_Name; ObjectFactory m_ObjectFactory; - map m_Attributes; + map m_Attributes; typedef map ObjectMap; typedef set ObjectSet; diff --git a/lib/base/eventqueue.cpp b/lib/base/eventqueue.cpp index 8cb486464..4564f4671 100644 --- a/lib/base/eventqueue.cpp +++ b/lib/base/eventqueue.cpp @@ -34,6 +34,11 @@ EventQueue::EventQueue(void) for (int i = 0; i < thread_count; i++) m_Threads.create_thread(boost::bind(&EventQueue::QueueThreadProc, this)); + + m_ReportTimer = boost::make_shared(); + m_ReportTimer->OnTimerExpired.connect(boost::bind(&EventQueue::ReportTimerHandler, this)); + m_ReportTimer->SetInterval(5); + m_ReportTimer->Start(); } /** @@ -41,6 +46,8 @@ EventQueue::EventQueue(void) */ EventQueue::~EventQueue(void) { + m_ReportTimer->Stop(); + Stop(); Join(); } @@ -114,11 +121,17 @@ void EventQueue::Post(const EventQueue::Callback& callback) 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)); } diff --git a/lib/base/eventqueue.h b/lib/base/eventqueue.h index c92e3934f..f6edf989f 100644 --- a/lib/base/eventqueue.h +++ b/lib/base/eventqueue.h @@ -23,6 +23,8 @@ namespace icinga { +class Timer; + /** * An event queue. * @@ -48,10 +50,13 @@ private: condition_variable m_CV; double m_LastReport; + shared_ptr m_ReportTimer; + bool m_Stopped; vector m_Events; void QueueThreadProc(void); + void ReportTimerHandler(void); }; } diff --git a/lib/base/logger.cpp b/lib/base/logger.cpp index 622ae9840..8fa1329ed 100644 --- a/lib/base/logger.cpp +++ b/lib/base/logger.cpp @@ -31,10 +31,14 @@ REGISTER_TYPE(Logger, NULL); 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.")); @@ -47,7 +51,7 @@ Logger::Logger(const Dictionary::Ptr& properties) 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")); @@ -91,7 +95,7 @@ void Logger::Write(LogSeverity severity, const String& facility, */ LogSeverity Logger::GetMinSeverity(void) const { - String severity = Get("severity"); + String severity = m_Severity; if (severity.IsEmpty()) return LogInformation; else diff --git a/lib/base/logger.h b/lib/base/logger.h index 58eeae57f..2a99877ce 100644 --- a/lib/base/logger.h +++ b/lib/base/logger.h @@ -98,6 +98,10 @@ public: LogSeverity GetMinSeverity(void) const; private: + Attribute m_Type; + Attribute m_Path; + Attribute m_Severity; + LogSeverity m_MinSeverity; ILogger::Ptr m_Impl; diff --git a/lib/base/script.cpp b/lib/base/script.cpp index ee7026a51..12050aea5 100644 --- a/lib/base/script.cpp +++ b/lib/base/script.cpp @@ -30,7 +30,10 @@ REGISTER_TYPE(Script, NULL); */ Script::Script(const Dictionary::Ptr& properties) : DynamicObject(properties) -{ } +{ + RegisterAttribute("language", Attribute_Config, &m_Language); + RegisterAttribute("code", Attribute_Config, &m_Code); +} void Script::OnRegistrationCompleted(void) { @@ -41,12 +44,12 @@ 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) diff --git a/lib/base/script.h b/lib/base/script.h index 58d5cf97c..34e748eab 100644 --- a/lib/base/script.h +++ b/lib/base/script.h @@ -46,6 +46,9 @@ protected: virtual void OnAttributeUpdate(const String& name, const Value& oldValue); private: + Attribute m_Language; + Attribute m_Code; + shared_ptr m_Interpreter; void SpawnInterpreter(void); diff --git a/lib/base/timer.cpp b/lib/base/timer.cpp index 9d3098560..704d28c34 100644 --- a/lib/base/timer.cpp +++ b/lib/base/timer.cpp @@ -270,6 +270,8 @@ void Timer::TimerThreadProc(void) timer->m_Started = false; m_Timers.erase(timer); + lock.unlock(); + /* Asynchronously call the timer. */ Application::GetEQ().Post(boost::bind(&Timer::Call, timer)); } diff --git a/lib/icinga/host.cpp b/lib/icinga/host.cpp index 095147b60..56f8a6022 100644 --- a/lib/icinga/host.cpp +++ b/lib/icinga/host.cpp @@ -21,42 +21,41 @@ using namespace icinga; +boost::mutex Host::m_Mutex; map > > 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(); } } @@ -64,9 +63,8 @@ Host::~Host(void) 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(); } @@ -94,27 +92,27 @@ Host::Ptr Host::GetByName(const String& name) 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) @@ -213,21 +211,36 @@ static void CopyServiceAttributes(TDict serviceDesc, const ConfigItemBuilder::Pt } } -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::Ptr serviceDescs = Get("services"); + DebugInfo debug_info; + + { + ObjectLock olock(item); + debug_info = item->GetDebugInfo(); + } if (serviceDescs) { String svcname; @@ -237,17 +250,17 @@ void Host::UpdateSlaveServices(void) svcname = svcdesc; stringstream namebuf; - namebuf << GetName() << "-" << svcname; + namebuf << host_name << "-" << svcname; String name = namebuf.str(); - ConfigItemBuilder::Ptr builder = boost::make_shared(item->GetDebugInfo()); + ConfigItemBuilder::Ptr builder = boost::make_shared(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(this, builder); + CopyServiceAttributes(self, builder); if (svcdesc.IsScalar()) { builder->AddParent(svcdesc); @@ -271,7 +284,7 @@ void Host::UpdateSlaveServices(void) } ConfigItem::Ptr serviceItem = builder->Compile(); - ConfigItem::Commit(serviceItem); + DynamicObject::Ptr dobj = ConfigItem::Commit(serviceItem); newServices->Set(name, serviceItem); } @@ -290,7 +303,7 @@ void Host::UpdateSlaveServices(void) newServices->Seal(); - Set("slave_services", newServices); + self->Set("slave_services", newServices); } void Host::OnAttributeChanged(const String& name, const Value&) @@ -298,8 +311,7 @@ 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 services; @@ -309,9 +321,11 @@ void Host::OnAttributeChanged(const String& name, const Value&) } 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()); } } @@ -319,6 +333,8 @@ set Host::GetServices(void) const { set services; + boost::mutex::scoped_lock lock(m_Mutex); + ValidateServicesCache(); Service::WeakPtr wservice; @@ -336,10 +352,14 @@ set Host::GetServices(void) const 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) @@ -350,9 +370,25 @@ void Host::ValidateServicesCache(void) BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) { const Service::Ptr& service = static_pointer_cast(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; @@ -411,15 +447,20 @@ void Host::ValidateServiceDictionary(const ScriptTask::Ptr& task, const vector >& services = m_ServicesCache[GetName()]; - map >::iterator it = services.find(name); + { + boost::mutex::scoped_lock lock(m_Mutex); + + ValidateServicesCache(); + + map >& services = m_ServicesCache[GetName()]; + map >::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); @@ -452,17 +493,7 @@ set Host::GetParentHosts(void) const 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 Host::GetParentServices(void) const diff --git a/lib/icinga/host.h b/lib/icinga/host.h index 2308f1d23..47cf6cfd1 100644 --- a/lib/icinga/host.h +++ b/lib/icinga/host.h @@ -71,12 +71,23 @@ protected: void OnAttributeChanged(const String& name, const Value& oldValue); private: + Attribute m_DisplayName; + Attribute m_HostGroups; + Attribute m_Macros; + Attribute m_HostDependencies; + Attribute m_ServiceDependencies; + Attribute m_HostCheck; + Dictionary::Ptr m_SlaveServices; + + static boost::mutex m_Mutex; static map > > m_ServicesCache; static bool m_ServicesCacheValid; - void UpdateSlaveServices(void); + static void UpdateSlaveServices(const Host::Ptr& self); static void ValidateServicesCache(void); + + weak_ptr m_HostCheckService; }; } diff --git a/lib/icinga/hostgroup.cpp b/lib/icinga/hostgroup.cpp index a8d2b7004..9928a4e3f 100644 --- a/lib/icinga/hostgroup.cpp +++ b/lib/icinga/hostgroup.cpp @@ -29,26 +29,28 @@ REGISTER_TYPE(HostGroup, NULL); 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; } /** diff --git a/lib/icinga/hostgroup.h b/lib/icinga/hostgroup.h index faa81b73a..8074510a7 100644 --- a/lib/icinga/hostgroup.h +++ b/lib/icinga/hostgroup.h @@ -47,6 +47,10 @@ public: static void InvalidateMembersCache(void); private: + Attribute m_DisplayName; + Attribute m_NotesUrl; + Attribute m_ActionUrl; + static boost::mutex m_Mutex; static map > > m_MembersCache; static bool m_MembersCacheValid; diff --git a/lib/icinga/icingaapplication.cpp b/lib/icinga/icingaapplication.cpp index 73c36e3eb..e1b92a663 100644 --- a/lib/icinga/icingaapplication.cpp +++ b/lib/icinga/icingaapplication.cpp @@ -30,7 +30,15 @@ REGISTER_TYPE(IcingaApplication, NULL); 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. @@ -96,47 +104,43 @@ IcingaApplication::Ptr IcingaApplication::GetInstance(void) 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 diff --git a/lib/icinga/icingaapplication.h b/lib/icinga/icingaapplication.h index fb294655b..5d39a3ea8 100644 --- a/lib/icinga/icingaapplication.h +++ b/lib/icinga/icingaapplication.h @@ -54,6 +54,14 @@ public: static Dictionary::Ptr CalculateDynamicMacros(const IcingaApplication::Ptr& self); private: + Attribute m_CertPath; + Attribute m_CAPath; + Attribute m_Node; + Attribute m_Service; + Attribute m_PidPath; + Attribute m_StatePath; + Attribute m_Macros; + shared_ptr m_SSLContext; double m_StartTime; diff --git a/lib/icinga/notification.cpp b/lib/icinga/notification.cpp index 0625f7f6f..6b1a1b628 100644 --- a/lib/icinga/notification.cpp +++ b/lib/icinga/notification.cpp @@ -26,6 +26,12 @@ REGISTER_TYPE(Notification, NULL); 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(); } @@ -51,30 +57,29 @@ Notification::Ptr Notification::GetByName(const String& name) 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 Notification::GetUsers(void) const { set result; - Dictionary::Ptr users = Get("users"); + Dictionary::Ptr users = m_Users; if (users) { String name; diff --git a/lib/icinga/notification.h b/lib/icinga/notification.h index 0a989c65c..0443927be 100644 --- a/lib/icinga/notification.h +++ b/lib/icinga/notification.h @@ -71,6 +71,12 @@ protected: void OnAttributeChanged(const String& name, const Value& oldValue); private: + Attribute m_NotificationCommand; + Attribute m_Macros; + Attribute m_Users; + Attribute m_HostName; + Attribute m_Service; + set m_Tasks; void NotificationCompletedHandler(const ScriptTask::Ptr& task); diff --git a/lib/icinga/service-check.cpp b/lib/icinga/service-check.cpp index 2f2759e97..175d17996 100644 --- a/lib/icinga/service-check.cpp +++ b/lib/icinga/service-check.cpp @@ -30,96 +30,64 @@ signals2::signal Service::OnNextCheckC 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(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) @@ -140,146 +108,140 @@ 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(state)); + m_State = static_cast(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(value); + int ivalue = static_cast(m_State); return static_cast(ivalue); } void Service::SetStateType(ServiceStateType type) { - Set("state_type", static_cast(type)); + m_StateType = static_cast(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(value); + int ivalue = static_cast(m_StateType); return static_cast(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(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(value); + return static_cast(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(value); + return static_cast(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(value); + return static_cast(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) @@ -429,7 +391,7 @@ void Service::BeginExecuteCheck(const Service::Ptr& self, const functionGet("current_task").IsEmpty()) { + if (self->m_CurrentTask) { slock.Unlock(); /* we need to call the callback anyway */ @@ -481,7 +443,7 @@ void Service::BeginExecuteCheck(const Service::Ptr& self, const functionMakeMethodTask("check", arguments); - self->Set("current_task", task); + self->m_CurrentTask = task; } task->Start(boost::bind(&Service::CheckCompletedHandler, self, checkInfo, _1, callback)); @@ -537,11 +499,11 @@ void Service::CheckCompletedHandler(const Dictionary::Ptr& checkInfo, 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()); } } @@ -550,7 +512,7 @@ void Service::CheckCompletedHandler(const Dictionary::Ptr& checkInfo, 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 diff --git a/lib/icinga/service-comment.cpp b/lib/icinga/service-comment.cpp index c7be98320..6e18c84ab 100644 --- a/lib/icinga/service-comment.cpp +++ b/lib/icinga/service-comment.cpp @@ -34,9 +34,7 @@ int Service::GetNextCommentID(void) Dictionary::Ptr Service::GetComments(void) const { - Service::ValidateCommentsCache(); - - return Get("comments"); + return m_Comments; } String Service::AddComment(CommentType entryType, const String& author, @@ -50,14 +48,16 @@ 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(); String id = Utility::NewUUID(); comments->Set(id, comment); - Set("comments", comments); + + m_Comments = comments; + Touch("comments"); return id; } @@ -74,7 +74,7 @@ void Service::RemoveComment(const String& id) if (!owner) return; - Dictionary::Ptr comments = owner->Get("comments"); + Dictionary::Ptr comments = owner->m_Comments; if (comments) { comments->Remove(id); @@ -106,7 +106,7 @@ Dictionary::Ptr Service::GetCommentByID(const String& 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); @@ -132,7 +132,7 @@ void Service::InvalidateCommentsCache(void) void Service::AddCommentsToCache(void) { - Dictionary::Ptr comments = Get("comments"); + Dictionary::Ptr comments = m_Comments; if (!comments) return; @@ -184,7 +184,7 @@ void Service::ValidateCommentsCache(void) void Service::RemoveExpiredComments(void) { - Dictionary::Ptr comments = Get("comments"); + Dictionary::Ptr comments = m_Comments; if (!comments) return; diff --git a/lib/icinga/service-downtime.cpp b/lib/icinga/service-downtime.cpp index b3ceb35c0..d63195580 100644 --- a/lib/icinga/service-downtime.cpp +++ b/lib/icinga/service-downtime.cpp @@ -34,9 +34,7 @@ int Service::GetNextDowntimeID(void) Dictionary::Ptr Service::GetDowntimes(void) const { - Service::ValidateDowntimesCache(); - - return Get("downtimes"); + return m_Downtimes; } String Service::AddDowntime(const String& author, const String& comment, @@ -65,14 +63,16 @@ 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(); String id = Utility::NewUUID(); downtimes->Set(id, downtime); - Set("downtimes", downtimes); + + m_Downtimes = downtimes; + Touch("downtimes"); return id; } @@ -84,7 +84,7 @@ void Service::RemoveDowntime(const String& id) if (!owner) return; - Dictionary::Ptr downtimes = owner->Get("downtimes"); + Dictionary::Ptr downtimes = owner->m_Downtimes; if (!downtimes) return; @@ -95,7 +95,7 @@ void Service::RemoveDowntime(const String& id) void Service::TriggerDowntimes(void) { - Dictionary::Ptr downtimes = Get("downtimes"); + Dictionary::Ptr downtimes = m_Downtimes; if (!downtimes) return; @@ -155,7 +155,7 @@ Dictionary::Ptr Service::GetDowntimeByID(const String& id) 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); @@ -198,7 +198,7 @@ void Service::InvalidateDowntimesCache(void) void Service::AddDowntimesToCache(void) { - Dictionary::Ptr downtimes = Get("downtimes"); + Dictionary::Ptr downtimes = m_Downtimes; if (!downtimes) return; @@ -249,7 +249,7 @@ void Service::ValidateDowntimesCache(void) void Service::RemoveExpiredDowntimes(void) { - Dictionary::Ptr downtimes = Get("downtimes"); + Dictionary::Ptr downtimes = m_Downtimes; if (!downtimes) return; diff --git a/lib/icinga/service-notification.cpp b/lib/icinga/service-notification.cpp index e2a97ff6a..a19180ed2 100644 --- a/lib/icinga/service-notification.cpp +++ b/lib/icinga/service-notification.cpp @@ -123,38 +123,56 @@ static void CopyNotificationAttributes(TDict notificationDesc, const ConfigItemB 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 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(); - vector 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) { @@ -162,21 +180,22 @@ void Service::UpdateSlaveNotifications(void) nfcname = nfcdesc; stringstream namebuf; - namebuf << GetName() << "-" << nfcname; + namebuf << service_name << "-" << nfcname; String name = namebuf.str(); - ConfigItemBuilder::Ptr builder = boost::make_shared(item->GetDebugInfo()); + ConfigItemBuilder::Ptr builder = boost::make_shared(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::Ptr notification = nfcdesc; + ObjectLock nlock(notification); Dictionary::Ptr templates = notification->Get("templates"); @@ -212,12 +231,15 @@ void Service::UpdateSlaveNotifications(void) } } - 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; @@ -227,12 +249,13 @@ double Service::GetLastNotification(void) const 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; @@ -242,5 +265,6 @@ double Service::GetNextNotification(void) const void Service::SetNextNotification(double time) { - Set("next_notification", time); + m_NextNotification = time; + Touch("next_notification"); } diff --git a/lib/icinga/service.cpp b/lib/icinga/service.cpp index dd12b62fc..a5410e549 100644 --- a/lib/icinga/service.cpp +++ b/lib/icinga/service.cpp @@ -21,33 +21,51 @@ 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) { @@ -60,7 +78,7 @@ void Service::OnRegistrationCompleted(void) { ObjectLock olock(this); - UpdateSlaveNotifications(); + m_Host = Host::GetByName(GetHostName()); } } @@ -74,12 +92,10 @@ Service::~Service(void) 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; } /** @@ -119,42 +135,40 @@ Service::Ptr Service::GetByNamePair(const String& hostName, const String& servic 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) @@ -212,12 +226,10 @@ 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(value); + int ivalue = static_cast(m_Acknowledgement); AcknowledgementType avalue = static_cast(ivalue); if (avalue != AcknowledgementNone) { @@ -235,7 +247,8 @@ AcknowledgementType Service::GetAcknowledgement(void) void Service::SetAcknowledgement(AcknowledgementType acknowledgement) { - Set("acknowledgement", static_cast(acknowledgement)); + m_Acknowledgement = acknowledgement; + Touch("acknowledgement"); } bool Service::IsAcknowledged(void) @@ -245,17 +258,16 @@ 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(value); + return static_cast(m_AcknowledgementExpiry); } void Service::SetAcknowledgementExpiry(double timestamp) { - Set("acknowledgement_expiry", timestamp); + m_AcknowledgementExpiry = timestamp; + Touch("acknowledgement_expiry"); } void Service::AcknowledgeProblem(AcknowledgementType type, double expiry) @@ -274,7 +286,7 @@ void Service::ClearAcknowledgement(void) 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); @@ -283,16 +295,16 @@ void Service::OnAttributeChanged(const String& name, const Value& 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()); diff --git a/lib/icinga/service.h b/lib/icinga/service.h index 9ff744fe2..705eb1c2a 100644 --- a/lib/icinga/service.h +++ b/lib/icinga/service.h @@ -104,6 +104,7 @@ public: 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); @@ -126,15 +127,12 @@ public: 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; @@ -245,7 +243,7 @@ public: set GetNotifications(void) const; - void UpdateSlaveNotifications(void); + static void UpdateSlaveNotifications(const Service::Ptr& self); double GetLastNotification(void) const; void SetLastNotification(double time); @@ -258,10 +256,46 @@ protected: virtual void OnAttributeChanged(const String& name, const Value& oldValue); private: + Host::Ptr m_Host; + Dictionary::Ptr m_SlaveNotifications; + + Attribute m_DisplayName; + Attribute m_Macros; + Attribute m_HostDependencies; + Attribute m_ServiceDependencies; + Attribute m_ServiceGroups; + Attribute m_ShortName; + Attribute m_Acknowledgement; + Attribute m_AcknowledgementExpiry; + Attribute m_HostName; + + /* Checks */ + Attribute m_CheckCommand; + Attribute m_MaxCheckAttempts; + Attribute m_CheckInterval; + Attribute m_RetryInterval; + Attribute m_NextCheck; + Attribute m_Checkers; + Attribute m_CurrentChecker; + Attribute m_CheckAttempt; + Attribute m_State; + Attribute m_StateType; + Attribute m_LastResult; + Attribute m_LastStateChange; + Attribute m_LastHardStateChange; + Attribute m_EnableActiveChecks; + Attribute m_EnablePassiveChecks; + Attribute m_ForceNextCheck; + + ScriptTask::Ptr m_CurrentTask; + long m_SchedulingOffset; + void CheckCompletedHandler(const Dictionary::Ptr& checkInfo, const ScriptTask::Ptr& task, const function& callback); /* Downtimes */ + Attribute m_Downtimes; + static int m_NextDowntimeID; static map m_LegacyDowntimesCache; @@ -275,6 +309,8 @@ private: void RemoveExpiredDowntimes(void); /* Comments */ + Attribute m_Comments; + static int m_NextCommentID; static map m_LegacyCommentsCache; @@ -288,6 +324,9 @@ private: void RemoveExpiredComments(void); /* Notifications */ + Attribute m_LastNotification; + Attribute m_NextNotification; + static map > m_NotificationsCache; static bool m_NotificationsCacheValid; }; diff --git a/lib/icinga/servicegroup.cpp b/lib/icinga/servicegroup.cpp index 049491e17..d96b4e255 100644 --- a/lib/icinga/servicegroup.cpp +++ b/lib/icinga/servicegroup.cpp @@ -29,26 +29,28 @@ REGISTER_TYPE(ServiceGroup, NULL); 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; } /** diff --git a/lib/icinga/servicegroup.h b/lib/icinga/servicegroup.h index 2230f4663..c75508117 100644 --- a/lib/icinga/servicegroup.h +++ b/lib/icinga/servicegroup.h @@ -47,6 +47,10 @@ public: static void InvalidateMembersCache(void); private: + Attribute m_DisplayName; + Attribute m_NotesUrl; + Attribute m_ActionUrl; + static boost::mutex m_Mutex; static map > > m_MembersCache; static bool m_MembersCacheValid; diff --git a/lib/icinga/user.cpp b/lib/icinga/user.cpp index 5c5ba8502..177aaf6bb 100644 --- a/lib/icinga/user.cpp +++ b/lib/icinga/user.cpp @@ -25,7 +25,9 @@ REGISTER_TYPE(User, NULL); User::User(const Dictionary::Ptr& properties) : DynamicObject(properties) -{ } +{ + RegisterAttribute("macros", Attribute_Config, &m_Macros); +} bool User::Exists(const String& name) { @@ -44,7 +46,7 @@ User::Ptr User::GetByName(const String& name) Dictionary::Ptr User::GetMacros(void) const { - return Get("macros"); + return m_Macros; } Dictionary::Ptr User::CalculateDynamicMacros(const User::Ptr& self) diff --git a/lib/icinga/user.h b/lib/icinga/user.h index 70dad242f..857d702ab 100644 --- a/lib/icinga/user.h +++ b/lib/icinga/user.h @@ -41,6 +41,9 @@ public: Dictionary::Ptr GetMacros(void) const; static Dictionary::Ptr CalculateDynamicMacros(const User::Ptr& self); + +private: + Attribute m_Macros; }; } diff --git a/lib/remoting/endpoint.cpp b/lib/remoting/endpoint.cpp index 7da12f97f..702e9862e 100644 --- a/lib/remoting/endpoint.cpp +++ b/lib/remoting/endpoint.cpp @@ -21,14 +21,7 @@ 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 Endpoint::OnConnected; signals2::signal Endpoint::OnDisconnected; @@ -42,7 +35,13 @@ signals2::signal Endpoint::OnS */ 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. @@ -98,9 +97,7 @@ Endpoint::Ptr Endpoint::MakeEndpoint(const String& name, bool replicated, bool l */ bool Endpoint::IsLocalEndpoint(void) const { - Value value = Get("local"); - - return (!value.IsEmpty() && value); + return m_Local; } /** @@ -121,12 +118,12 @@ bool Endpoint::IsConnected(void) const 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)); @@ -186,17 +183,19 @@ bool Endpoint::HasSubscription(const String& topic) const */ 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& callback) @@ -336,7 +335,7 @@ void Endpoint::ClientClosedHandler(void) // timer for that, once we have a TTL property for the topics) ClearSubscriptions(); - Set("client", Empty); + m_Client.reset(); OnDisconnected(GetSelf()); } @@ -348,7 +347,7 @@ void Endpoint::ClientClosedHandler(void) */ String Endpoint::GetNode(void) const { - return Get("node"); + return m_Node; } /** @@ -358,5 +357,5 @@ String Endpoint::GetNode(void) const */ String Endpoint::GetService(void) const { - return Get("service"); + return m_Service; } diff --git a/lib/remoting/endpoint.h b/lib/remoting/endpoint.h index 2d337f16f..25e8db2d8 100644 --- a/lib/remoting/endpoint.h +++ b/lib/remoting/endpoint.h @@ -78,6 +78,13 @@ public: static signals2::signal OnSubscriptionUnregistered; private: + Attribute m_Local; + Attribute m_Subscriptions; + Attribute m_Node; + Attribute 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 -- 2.40.0