]> granicus.if.org Git - icinga2/commitdiff
Make attribute lookups O(1).
authorGunnar Beutner <gunnar.beutner@netways.de>
Tue, 26 Feb 2013 09:13:54 +0000 (10:13 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Tue, 26 Feb 2013 09:13:54 +0000 (10:13 +0100)
36 files changed:
components/checker/checkercomponent.cpp
components/compat/compatcomponent.cpp
components/delegation/delegationcomponent.cpp
components/replication/replicationcomponent.cpp
configure.ac
lib/base/dynamicobject.cpp
lib/base/dynamicobject.h
lib/base/dynamictype.cpp
lib/base/dynamictype.h
lib/base/eventqueue.cpp
lib/base/eventqueue.h
lib/base/logger.cpp
lib/base/logger.h
lib/base/script.cpp
lib/base/script.h
lib/base/timer.cpp
lib/icinga/host.cpp
lib/icinga/host.h
lib/icinga/hostgroup.cpp
lib/icinga/hostgroup.h
lib/icinga/icingaapplication.cpp
lib/icinga/icingaapplication.h
lib/icinga/notification.cpp
lib/icinga/notification.h
lib/icinga/service-check.cpp
lib/icinga/service-comment.cpp
lib/icinga/service-downtime.cpp
lib/icinga/service-notification.cpp
lib/icinga/service.cpp
lib/icinga/service.h
lib/icinga/servicegroup.cpp
lib/icinga/servicegroup.h
lib/icinga/user.cpp
lib/icinga/user.h
lib/remoting/endpoint.cpp
lib/remoting/endpoint.h

index 565d52ad116ad377a82d1f8e6d74238d1b9323f1..4ac847a9c263a992d11d4eb653e0a2b5e1e3f460 100644 (file)
@@ -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())
index eede038b0d39d2c253a4a8c00266f8f95d014b6c..bf4490be75e25551a5fa1589711c250a9ffbcf1a 100644 (file)
@@ -534,12 +534,14 @@ void CompatComponent::StatusTimerHandler(void)
        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();
        }
 
@@ -547,6 +549,7 @@ void CompatComponent::StatusTimerHandler(void)
                HostGroup::Ptr hg = static_pointer_cast<HostGroup>(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<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();
        }
 
@@ -581,6 +586,7 @@ void CompatComponent::StatusTimerHandler(void)
                ServiceGroup::Ptr sg = static_pointer_cast<ServiceGroup>(object);
 
                stringstream tempobjectfp;
+               tempobjectfp << std::fixed;
 
                {
                        ObjectLock olock(sg);
index 1191bce94f13c5c930d93444f47842127fca117b..fa928cb9b8675b9397c1c113b836c1d6ec579e11 100644 (file)
@@ -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;
index de1c1b4e014c74e7315ecb11f8f6bb94e2d19ba4..414827b73273031659863f13e17fea96c1bf29ba 100644 (file)
@@ -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);
index ec762f669fa850eb497e5532b25dfef67c1498cc..4d2f38cf4e1144de0778f850a4b99043e38cc0de 100644 (file)
@@ -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)
 
index 3a985c7d6fca09f539a9682eb817355a83e9aa7c..bf30a339ab55acddd082efc83f4f5c11490cabf7 100644 (file)
@@ -35,12 +35,12 @@ signals2::signal<void (const DynamicObject::Ptr&)> 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<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);
        }
@@ -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<DynamicAttributeType>(type));
+                               RegisterAttribute(it->first, static_cast<AttributeType>(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<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)
@@ -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<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.
@@ -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<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);
index 9a84949ba1ee3a536c39fad9d06f24cdcda8db32..c15dd07ad004dcd042432bec0d42a33a97e53182 100644 (file)
@@ -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<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;
@@ -74,7 +200,7 @@ public:
        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;
 
@@ -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<void (const DynamicObject::Ptr&)> OnRegistered;
        static signals2::signal<void (const DynamicObject::Ptr&)> OnUnregistered;
@@ -150,6 +278,13 @@ private:
        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;
index f7ebce4e0ff69d9b730f9bd087620fb2c8de23ec..4e753b0b55ff893274d7439916f68099cb71e1f2 100644 (file)
@@ -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;
 }
index 952e518aa0f1a44d9fd33b6238a33e45f8f93c76..5db714be42712824c13f571d9a303f5f6c9f7ae8 100644 (file)
@@ -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<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);
 
@@ -66,7 +66,7 @@ public:
 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;
index 8cb4864648817c0da44df902b2f25bf240f154f3..4564f46714acc5da7a84c3ff103263e683eb2e5c 100644 (file)
@@ -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<Timer>();
+       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));
 }
index c92e3934ff8f3a04d3578a9efaead4743f6082c9..f6edf989ff9bdea3adf8e42e9cd285c05feab621 100644 (file)
@@ -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<Timer> m_ReportTimer;
+
        bool m_Stopped;
        vector<Callback> m_Events;
 
        void QueueThreadProc(void);
+       void ReportTimerHandler(void);
 };
 
 }
index 622ae9840bdc56a5bf8c845b47010b4c8a87ec1b..8fa1329ed7300e77b148f2b6dfd09f6360811b84 100644 (file)
@@ -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
index 58eeae57fc1042c01987af123a7e456ab9f4d39e..2a99877cee0ace72b6bc0e10e35a1d6d67c8e8f2 100644 (file)
@@ -98,6 +98,10 @@ public:
        LogSeverity GetMinSeverity(void) const;
 
 private:
+       Attribute<String> m_Type;
+       Attribute<String> m_Path;
+       Attribute<String> m_Severity;
+
        LogSeverity m_MinSeverity;
        ILogger::Ptr m_Impl;
 
index ee7026a51e2a91b05e053709cd11b03f04da3c6f..12050aea549576c71fe233097623f0616b954c43 100644 (file)
@@ -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)
index 58d5cf97c59815184700bf7b6b497fae319f3887..34e748eab742e6a711e73acc1ce33ffee3771858 100644 (file)
@@ -46,6 +46,9 @@ protected:
        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);
index 9d3098560204fb257adde96e1ac5d2acfaa29ee0..704d28c34ff8f54748b9b5d1af2a570fb5219f03 100644 (file)
@@ -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));
        }
index 095147b604befe6ee1e916143b8e0d5a4911798a..56f8a602202bfe61495c9f07bdc78fb587dc0fed 100644 (file)
 
 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();
                }
        }
@@ -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>();
 
-       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<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);
@@ -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<Service::Ptr> 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<Service::Ptr> Host::GetServices(void) const
 {
        set<Service::Ptr> services;
 
+       boost::mutex::scoped_lock lock(m_Mutex);
+
        ValidateServicesCache();
 
        Service::WeakPtr wservice;
@@ -336,10 +352,14 @@ set<Service::Ptr> 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<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;
@@ -411,15 +447,20 @@ void Host::ValidateServiceDictionary(const ScriptTask::Ptr& task, const vector<V
 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);
@@ -452,17 +493,7 @@ set<Host::Ptr> 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<Service::Ptr> Host::GetParentServices(void) const
index 2308f1d23bcd5a4ebddb35803f69c3fba73f335c..47cf6cfd1e496d0f86dea4e969f1b8423f1ca1a2 100644 (file)
@@ -71,12 +71,23 @@ protected:
        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;
 };
 
 }
index a8d2b7004d0f1e679f5469b2df78ee8398eafcf1..9928a4e3f65fc4f0961c48f6451d3c3b015fcc6c 100644 (file)
@@ -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;
 }
 
 /**
index faa81b73ae44a2088ff370317f5e9850fc39d353..8074510a7f9c1e38fe64a799aea67e07ed80ab28 100644 (file)
@@ -47,6 +47,10 @@ public:
        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;
index 73c36e3ebb3642fbf9148128f70c45c30dcab295..e1b92a663c9290888f951413949ad885ee94277e 100644 (file)
@@ -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
index fb294655be69591dc1df84558eb60f48cf931d3a..5d39a3ea8570898eb4ee43f1e1f2ef5b788f2512 100644 (file)
@@ -54,6 +54,14 @@ public:
        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;
index 0625f7f6f1366673d3ce138c05758e45c8b52ba6..6b1a1b6287213d7b8fae60cc8f2c33b3ce16b11c 100644 (file)
@@ -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<User::Ptr> Notification::GetUsers(void) const
 {
        set<User::Ptr> result;
 
-       Dictionary::Ptr users = Get("users");
+       Dictionary::Ptr users = m_Users;
 
        if (users) {
                String name;
index 0a989c65c32b22a98dda7150c4a831556207a50f..0443927bef4faca9c12f739fc2d297e92463c2b5 100644 (file)
@@ -71,6 +71,12 @@ protected:
        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);
index 2f2759e97df2e7ce5845845fa5e405ad5c9fdb53..175d1799660b886da695ef1115d527d4a6a84e7b 100644 (file)
@@ -30,96 +30,64 @@ signals2::signal<void (const Service::Ptr&, const Value&)> 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<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)
@@ -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<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)
@@ -429,7 +391,7 @@ void Service::BeginExecuteCheck(const Service::Ptr& self, const function<void (v
        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 */
@@ -481,7 +443,7 @@ void Service::BeginExecuteCheck(const Service::Ptr& self, const function<void (v
        {
                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));
@@ -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
index c7be98320f60ba507657a76bf6558b08d1c37384..6e18c84ab6c19b48759864fcb7c0145a92d94e9e 100644 (file)
@@ -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<Dictionary>();
 
        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;
index b3ceb35c04a3233535f93cd1b162596ec7108a88..d63195580119168a2759a42519623e8f6524d70d 100644 (file)
@@ -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<Dictionary>();
 
        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;
index e2a97ff6a834e307af57df1ff66e364f4f269222..a19180ed204a1f7c72ab9fb7a34346bc765dc7d3 100644 (file)
@@ -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<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) {
@@ -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<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");
 
@@ -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");
 }
index dd12b62fc6a49ba74aaca1a59a2e06f357b02ec1..a5410e549b3409624f0e91bb36f04e43d27d2cea 100644 (file)
 
 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<int>(value);
+       int ivalue = static_cast<int>(m_Acknowledgement);
        AcknowledgementType avalue = static_cast<AcknowledgementType>(ivalue);
 
        if (avalue != AcknowledgementNone) {
@@ -235,7 +247,8 @@ AcknowledgementType Service::GetAcknowledgement(void)
 
 void Service::SetAcknowledgement(AcknowledgementType acknowledgement)
 {
-       Set("acknowledgement", static_cast<long>(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<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)
@@ -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());
index 9ff744fe2bc2eafced7756835c0b5c092424ceb5..705eb1c2ac6bfb911252099fb8201e1f3ff8d9aa 100644 (file)
@@ -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<Notification::Ptr> 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<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;
@@ -275,6 +309,8 @@ private:
        void RemoveExpiredDowntimes(void);
 
        /* Comments */
+       Attribute<Dictionary::Ptr> m_Comments;
+
        static int m_NextCommentID;
 
        static map<int, String> m_LegacyCommentsCache;
@@ -288,6 +324,9 @@ private:
        void RemoveExpiredComments(void);
 
        /* Notifications */
+       Attribute<double> m_LastNotification;
+       Attribute<double> m_NextNotification;
+
        static map<String, set<Notification::WeakPtr> > m_NotificationsCache;
        static bool m_NotificationsCacheValid;
 };
index 049491e17938c64948331025d0b43f2b64baed25..d96b4e2552966a812ed4b0836d63f989940cf15b 100644 (file)
@@ -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;
 }
 
 /**
index 2230f46635c602a7aecb9a77eea53b7e8ffed068..c7550811791f0712082718c34c1c00814a891523 100644 (file)
@@ -47,6 +47,10 @@ public:
        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;
index 5c5ba85024824bfbde3d492d291eaa84ba60e55b..177aaf6bb8a6dabb625731f3699caeb50af4114f 100644 (file)
@@ -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)
index 70dad242f7da4376b134ecfe0f4b5c95958c0812..857d702abab315ba8b6ab09b94dfd9e79493e790 100644 (file)
@@ -41,6 +41,9 @@ public:
 
        Dictionary::Ptr GetMacros(void) const;
        static Dictionary::Ptr CalculateDynamicMacros(const User::Ptr& self);
+
+private:
+       Attribute<Dictionary::Ptr> m_Macros;
 };
 
 }
index 7da12f97fc3531820b5ce79a4900e3fd5614fdfb..702e9862e1403403847e4366a61beb6fdd3d041f 100644 (file)
 
 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;
@@ -42,7 +35,13 @@ signals2::signal<void (const Endpoint::Ptr&, const String& topic)> 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<Endpoint::Callback>& 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;
 }
index 2d337f16fa714c5507aa308ccbbbe982e8602af1..25e8db2d83c61ad55da2e51ddaf664ae76ca5168 100644 (file)
@@ -78,6 +78,13 @@ public:
        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