diff --git a/components/compat/compatcomponent.cpp b/components/compat/compatcomponent.cpp index 7ee2cdfd6..578cc0a05 100644 --- a/components/compat/compatcomponent.cpp +++ b/components/compat/compatcomponent.cpp @@ -91,7 +91,7 @@ String CompatComponent::GetCommandPath(void) const void CompatComponent::Start(void) { m_StatusTimer = boost::make_shared(); - m_StatusTimer->SetInterval(15); + m_StatusTimer->SetInterval(5); m_StatusTimer->OnTimerExpired.connect(boost::bind(&CompatComponent::StatusTimerHandler, this)); m_StatusTimer->Start(); m_StatusTimer->Reschedule(0); @@ -450,10 +450,18 @@ void CompatComponent::StatusTimerHandler(void) << "\t" << "}" << "\n" << "\n"; + double startTime; + + { + IcingaApplication::Ptr app = IcingaApplication::GetInstance(); + ObjectLock olock(app); + startTime = app->GetStartTime(); + } + statusfp << "programstatus {" << "\n" << "icinga_pid=" << Utility::GetPid() << "\n" << "\t" << "daemon_mode=1" << "\n" - << "\t" << "program_start=" << IcingaApplication::GetInstance()->GetStartTime() << "\n" + << "\t" << "program_start=" << startTime << "\n" << "\t" << "active_service_checks_enabled=1" << "\n" << "\t" << "passive_service_checks_enabled=1" << "\n" << "\t" << "active_host_checks_enabled=0" << "\n" @@ -478,85 +486,61 @@ void CompatComponent::StatusTimerHandler(void) << "# This file is auto-generated. Do not modify this file." << "\n" << "\n"; - { - DynamicType::Ptr dt = DynamicType::GetByName("Host"); - ObjectLock dlock(dt); + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Host")) { + Host::Ptr host = static_pointer_cast(object); - DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), dt->GetObjects()) { - Host::Ptr host = static_pointer_cast(object); - - DumpHostStatus(statusfp, host); - DumpHostObject(objectfp, host); - } + DumpHostStatus(statusfp, host); + DumpHostObject(objectfp, host); } - { - DynamicType::Ptr dt = DynamicType::GetByName("Host"); - ObjectLock dlock(dt); + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("HostGroup")) { + HostGroup::Ptr hg = static_pointer_cast(object); + ObjectLock olock(hg); - DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), dt->GetObjects()) { - HostGroup::Ptr hg = static_pointer_cast(object); - ObjectLock olock(hg); + objectfp << "define hostgroup {" << "\n" + << "\t" << "hostgroup_name" << "\t" << hg->GetName() << "\n" + << "\t" << "notes_url" << "\t" << hg->GetNotesUrl() << "\n" + << "\t" << "action_url" << "\t" << hg->GetActionUrl() << "\n"; - objectfp << "define hostgroup {" << "\n" - << "\t" << "hostgroup_name" << "\t" << hg->GetName() << "\n" - << "\t" << "notes_url" << "\t" << hg->GetNotesUrl() << "\n" - << "\t" << "action_url" << "\t" << hg->GetActionUrl() << "\n"; - - objectfp << "\t" << "members" << "\t"; - DumpNameList(objectfp, hg->GetMembers()); - objectfp << "\n" - << "}" << "\n"; - } + objectfp << "\t" << "members" << "\t"; + DumpNameList(objectfp, hg->GetMembers()); + objectfp << "\n" + << "}" << "\n"; } - { - DynamicType::Ptr dt = DynamicType::GetByName("Service"); - ObjectLock dlock(dt); + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) { + Service::Ptr service = static_pointer_cast(object); - DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), dt->GetObjects()) { - Service::Ptr service = static_pointer_cast(object); - - DumpServiceStatus(statusfp, service); - DumpServiceObject(objectfp, service); - } + DumpServiceStatus(statusfp, service); + DumpServiceObject(objectfp, service); } - { - DynamicType::Ptr dt = DynamicType::GetByName("ServiceGroup"); - ObjectLock dlock(dt); + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("ServiceGroup")) { + ServiceGroup::Ptr sg = static_pointer_cast(object); + ObjectLock olock(sg); - DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), dt->GetObjects()) { - ServiceGroup::Ptr sg = static_pointer_cast(object); - ObjectLock olock(sg); + objectfp << "define servicegroup {" << "\n" + << "\t" << "servicegroup_name" << "\t" << sg->GetName() << "\n" + << "\t" << "notes_url" << "\t" << sg->GetNotesUrl() << "\n" + << "\t" << "action_url" << "\t" << sg->GetActionUrl() << "\n"; - objectfp << "define servicegroup {" << "\n" - << "\t" << "servicegroup_name" << "\t" << sg->GetName() << "\n" - << "\t" << "notes_url" << "\t" << sg->GetNotesUrl() << "\n" - << "\t" << "action_url" << "\t" << sg->GetActionUrl() << "\n"; + objectfp << "\t" << "members" << "\t"; - objectfp << "\t" << "members" << "\t"; + vector sglist; + BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) { + ObjectLock slock(service); + Host::Ptr host = service->GetHost(); - vector sglist; - BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) { - ObjectLock slock(service); - Host::Ptr host = service->GetHost(); + ObjectLock hlock(host); + sglist.push_back(host->GetName()); - ObjectLock hlock(host); - sglist.push_back(host->GetName()); - - sglist.push_back(service->GetShortName()); - } - - DumpStringList(objectfp, sglist); - - objectfp << "\n" - << "}" << "\n"; + sglist.push_back(service->GetShortName()); } + + DumpStringList(objectfp, sglist); + + objectfp << "\n" + << "}" << "\n"; } statusfp.close(); diff --git a/components/compatido/compatidocomponent.cpp b/components/compatido/compatidocomponent.cpp index 894fba0d1..3132b8994 100644 --- a/components/compatido/compatidocomponent.cpp +++ b/components/compatido/compatidocomponent.cpp @@ -85,7 +85,7 @@ double CompatIdoComponent::GetReconnectInterval(void) const if (interval.IsEmpty()) return DefaultReconnectInterval; - else + else return interval; } @@ -174,7 +174,7 @@ void CompatIdoComponent::OpenIdoSocket(void) #define COMPATIDO_PROTOCOL 2 #define COMPATIDO_NAME "ICINGA2 COMPATIDO" #define COMPATIDO_RELEASE_VERSION "2.0" - + /* connection is always TCP */ /* connecttype is always initial */ stringstream msgHello; @@ -340,7 +340,7 @@ void CompatIdoComponent::DisableServiceObject(const Service::Ptr& service) << 53 << "=" << service->GetHost()->GetName() << "\n" /* host */ << 114 << "=" << service->GetShortName() << "\n" /* service */ << 999 << "\n\n"; /* enddata */ - + m_IdoConnection->SendMessage(message.str()); } @@ -442,7 +442,7 @@ void CompatIdoComponent::DumpHostStatus(const Host::Ptr& host) state = 2; /* unreachable */ else if (!host->IsUp()) state = 1; /* down */ - else + else state = 0; /* up */ stringstream message; @@ -581,7 +581,7 @@ void CompatIdoComponent::DumpServiceObject(const Service::Ptr& service) * dump service status to ido * * @param service Pointer to Service object - */ + */ void CompatIdoComponent::DumpServiceStatus(const Service::Ptr& service) { stringstream log; @@ -673,7 +673,7 @@ void CompatIdoComponent::DumpServiceStatus(const Service::Ptr& service) } -/** +/** * dumps programstatus to ido */ void CompatIdoComponent::DumpProgramStatusData(void) @@ -738,7 +738,7 @@ void CompatIdoComponent::DumpConfigObjects(void) /* hosts and hostgroups */ DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Host")->GetObjects()) { + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Host")) { const Host::Ptr& host = static_pointer_cast(object); DumpHostObject(host); @@ -746,7 +746,7 @@ void CompatIdoComponent::DumpConfigObjects(void) //DisableHostObject(host); } - BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("HostGroup")->GetObjects()) { + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("HostGroup")) { const HostGroup::Ptr& hg = static_pointer_cast(object); /* dump the hostgroup and its attributes/members to ido */ @@ -764,14 +764,14 @@ void CompatIdoComponent::DumpConfigObjects(void) } SendMessageList(message, hglist, 171); /* hostgroupmember */ - + message << 999 << "\n\n"; /* enddata */ m_IdoConnection->SendMessage(message.str()); } /* services and servicegroups */ - BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Service")->GetObjects()) { + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) { Service::Ptr service = static_pointer_cast(object); DumpServiceObject(service); @@ -779,7 +779,7 @@ void CompatIdoComponent::DumpConfigObjects(void) //DisableServiceObject(service); } - BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("ServiceGroup")->GetObjects()) { + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("ServiceGroup")) { const ServiceGroup::Ptr& sg = static_pointer_cast(object); /* dump the servicegroup and its attributes/members to ido */ @@ -797,7 +797,7 @@ void CompatIdoComponent::DumpConfigObjects(void) sglist.push_back(service->GetHost()->GetName()); sglist.push_back(service->GetShortName()); } - + SendMessageList(message, sglist, 219); /* servicegroupmember */ message << 999 << "\n\n"; /* enddata */ @@ -817,13 +817,13 @@ void CompatIdoComponent::DumpConfigObjects(void) } /** - * process and dump all status data + * process and dump all status data */ void CompatIdoComponent::DumpStatusData(void) { /* hosts */ DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Host")->GetObjects()) { + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Host")) { const Host::Ptr& host = static_pointer_cast(object); DumpHostStatus(host); @@ -831,7 +831,7 @@ void CompatIdoComponent::DumpStatusData(void) /* services */ - BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Service")->GetObjects()) { + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) { Service::Ptr service = static_pointer_cast(object); DumpServiceStatus(service); diff --git a/components/delegation/delegationcomponent.cpp b/components/delegation/delegationcomponent.cpp index 5485291ba..09836eb1e 100644 --- a/components/delegation/delegationcomponent.cpp +++ b/components/delegation/delegationcomponent.cpp @@ -52,11 +52,7 @@ set DelegationComponent::GetCheckerCandidates(const Service::Ptr& { set candidates; - DynamicType::Ptr dt = DynamicType::GetByName("Endpoint"); - ObjectLock dlock(dt); - - DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), dt->GetObjects()) { + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Endpoint")) { Endpoint::Ptr endpoint = dynamic_pointer_cast(object); ObjectLock olock(endpoint); @@ -88,46 +84,34 @@ void DelegationComponent::DelegationTimerHandler(void) { map histogram; - { - DynamicType::Ptr dt = DynamicType::GetByName("Endpoint"); - ObjectLock dlock(dt); + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Endpoint")) { + Endpoint::Ptr endpoint = dynamic_pointer_cast(object); - DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), dt->GetObjects()) { - Endpoint::Ptr endpoint = dynamic_pointer_cast(object); - - histogram[endpoint] = 0; - } + histogram[endpoint] = 0; } vector services; - { - /* build "checker -> service count" histogram */ - DynamicType::Ptr dt = DynamicType::GetByName("Service"); - ObjectLock dlock(dt); + /* build "checker -> service count" histogram */ + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) { + Service::Ptr service = dynamic_pointer_cast(object); - DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), dt->GetObjects()) { - Service::Ptr service = dynamic_pointer_cast(object); + if (!service) + continue; - if (!service) - continue; + services.push_back(service); - services.push_back(service); + ObjectLock olock(service); + String checker = service->GetChecker(); + if (checker.IsEmpty()) + continue; - ObjectLock olock(service); - String checker = service->GetChecker(); - if (checker.IsEmpty()) - continue; + if (!Endpoint::Exists(checker)) + continue; - if (!Endpoint::Exists(checker)) - continue; + Endpoint::Ptr endpoint = Endpoint::GetByName(checker); - Endpoint::Ptr endpoint = Endpoint::GetByName(checker); - - histogram[endpoint]++; - } + histogram[endpoint]++; } //std::random_shuffle(services.begin(), services.end()); diff --git a/components/replication/replicationcomponent.cpp b/components/replication/replicationcomponent.cpp index 218ca7ada..e8a65767b 100644 --- a/components/replication/replicationcomponent.cpp +++ b/components/replication/replicationcomponent.cpp @@ -75,23 +75,40 @@ void ReplicationComponent::CheckResultRequestHandler(const RequestMessage& reque void ReplicationComponent::EndpointConnectedHandler(const Endpoint::Ptr& endpoint) { - /* no need to sync the config with local endpoints */ - if (endpoint->IsLocalEndpoint()) - return; + { + ObjectLock olock(endpoint); - /* we just assume the other endpoint wants object updates */ - endpoint->RegisterSubscription("config::ObjectUpdate"); - endpoint->RegisterSubscription("config::ObjectRemoved"); + /* no need to sync the config with local endpoints */ + if (endpoint->IsLocalEndpoint()) + return; + + /* we just assume the other endpoint wants object updates */ + endpoint->RegisterSubscription("config::ObjectUpdate"); + endpoint->RegisterSubscription("config::ObjectRemoved"); + } DynamicType::Ptr type; - BOOST_FOREACH(tie(tuples::ignore, type), DynamicType::GetTypes()) { - DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), type->GetObjects()) { + BOOST_FOREACH(const DynamicType::Ptr& dt, DynamicType::GetTypes()) { + set objects; + + { + ObjectLock olock(dt); + objects = dt->GetObjects(); + } + + BOOST_FOREACH(const DynamicObject::Ptr& object, objects) { if (!ShouldReplicateObject(object)) continue; RequestMessage request = MakeObjectMessage(object, "config::ObjectUpdate", 0, true); - EndpointManager::GetInstance()->SendUnicastMessage(m_Endpoint, endpoint, request); + + EndpointManager::Ptr em = EndpointManager::GetInstance(); + + { + ObjectLock elock(em); + em->SendUnicastMessage(m_Endpoint, endpoint, request); + } + } } } diff --git a/itl/standalone.conf b/itl/standalone.conf index 023c7b10f..174a071cf 100644 --- a/itl/standalone.conf +++ b/itl/standalone.conf @@ -19,8 +19,6 @@ local object Component "checker" {} -local object Component "delegation" { - delegation_interval = 120 -} +local object Component "delegation" {} local object Component "notification" {} diff --git a/lib/base/application.cpp b/lib/base/application.cpp index b0e139e5a..99218a524 100644 --- a/lib/base/application.cpp +++ b/lib/base/application.cpp @@ -24,7 +24,6 @@ using namespace icinga; Application *Application::m_Instance = NULL; bool Application::m_ShuttingDown = false; bool Application::m_Debugging = false; -boost::thread::id Application::m_MainThreadID; String Application::m_PrefixDir; String Application::m_LocalStateDir; String Application::m_PkgLibDir; @@ -402,6 +401,7 @@ void Application::InstallExceptionHandlers(void) * Runs the application. * * @returns The application's exit code. + * @threadsafety Always. */ int Application::Run(void) { diff --git a/lib/base/application.h b/lib/base/application.h index e4213882a..dd6679122 100644 --- a/lib/base/application.h +++ b/lib/base/application.h @@ -93,7 +93,6 @@ private: static char **m_ArgV; /**< Command-line arguments. */ FILE *m_PidFile; /**< The PID file */ static bool m_Debugging; /**< Whether debugging is enabled. */ - static boost::thread::id m_MainThreadID; /**< ID of the main thread. */ static String m_PrefixDir; /**< The installation prefix. */ static String m_LocalStateDir; /**< The local state dir. */ static String m_PkgLibDir; /**< The package lib dir. */ diff --git a/lib/base/dynamicobject.cpp b/lib/base/dynamicobject.cpp index 359830ac5..d66a3426c 100644 --- a/lib/base/dynamicobject.cpp +++ b/lib/base/dynamicobject.cpp @@ -32,7 +32,7 @@ signals2::signal DynamicObject::OnUnregistered signals2::signal&)> DynamicObject::OnTransactionClosing; DynamicObject::DynamicObject(const Dictionary::Ptr& serializedObject) - : m_ConfigTx(0) + : m_Events(false), m_ConfigTx(0) { RegisterAttribute("__name", Attribute_Config); RegisterAttribute("__type", Attribute_Config); @@ -41,13 +41,20 @@ DynamicObject::DynamicObject(const Dictionary::Ptr& serializedObject) RegisterAttribute("__source", Attribute_Local); RegisterAttribute("methods", Attribute_Config); - if (!serializedObject->Contains("configTx")) - BOOST_THROW_EXCEPTION(invalid_argument("Serialized object must contain a config snapshot.")); + { + ObjectLock olock(serializedObject); + + if (!serializedObject->Contains("configTx")) + BOOST_THROW_EXCEPTION(invalid_argument("Serialized object must contain a config snapshot.")); + } /* apply config state from the config item/remote update; * The DynamicObject::Create function takes care of restoring * non-config state after the object has been fully constructed */ - ApplyUpdate(serializedObject, Attribute_Config); + { + ObjectLock olock(this); + ApplyUpdate(serializedObject, Attribute_Config); + } boost::call_once(m_TransactionOnce, &DynamicObject::Initialize); } @@ -75,9 +82,12 @@ void DynamicObject::Initialize(void) */ void DynamicObject::SendLocalUpdateEvents(void) { - map::iterator it; - for (it = m_ModifiedAttributes.begin(); it != m_ModifiedAttributes.end(); it++) { - OnAttributeChanged(it->first, it->second); + /* Check if it's safe to send events. */ + if (GetEvents()) { + map::iterator it; + for (it = m_ModifiedAttributes.begin(); it != m_ModifiedAttributes.end(); it++) { + OnAttributeChanged(it->first, it->second); + } } m_ModifiedAttributes.clear(); @@ -124,39 +134,50 @@ Dictionary::Ptr DynamicObject::BuildUpdate(double sinceTx, int attributeTypes) c void DynamicObject::ApplyUpdate(const Dictionary::Ptr& serializedUpdate, int allowedTypes) { - double configTx = 0; - if ((allowedTypes & Attribute_Config) != 0 && - serializedUpdate->Contains("configTx")) { - configTx = serializedUpdate->Get("configTx"); + Dictionary::Ptr attrs; - if (configTx > m_ConfigTx) - ClearAttributesByType(Attribute_Config); + { + ObjectLock olock(serializedUpdate); + + double configTx = 0; + if ((allowedTypes & Attribute_Config) != 0 && + serializedUpdate->Contains("configTx")) { + configTx = serializedUpdate->Get("configTx"); + + if (configTx > m_ConfigTx) + ClearAttributesByType(Attribute_Config); + } + + attrs = serializedUpdate->Get("attrs"); } - Dictionary::Ptr attrs = serializedUpdate->Get("attrs"); + { + ObjectLock olock(attrs); - Dictionary::Iterator it; - for (it = attrs->Begin(); it != attrs->End(); it++) { - if (!it->second.IsObjectType()) - continue; + Dictionary::Iterator it; + for (it = attrs->Begin(); it != attrs->End(); it++) { + if (!it->second.IsObjectType()) + continue; - Dictionary::Ptr attr = it->second; + Dictionary::Ptr attr = it->second; + ObjectLock alock(attr); - int type = attr->Get("type"); + int type = attr->Get("type"); - if ((type & ~allowedTypes) != 0) - continue; + if ((type & ~allowedTypes) != 0) + continue; - Value data = attr->Get("data"); - double tx = attr->Get("tx"); + Value data = attr->Get("data"); + double tx = attr->Get("tx"); - if (type & Attribute_Config) - RegisterAttribute(it->first, Attribute_Config); + if (type & Attribute_Config) + RegisterAttribute(it->first, Attribute_Config); - if (!HasAttribute(it->first)) - RegisterAttribute(it->first, static_cast(type)); + if (!HasAttribute(it->first)) + RegisterAttribute(it->first, static_cast(type)); - InternalSetAttribute(it->first, data, tx, true); + InternalSetAttribute(it->first, data, tx, true); + } } } @@ -296,13 +317,18 @@ String DynamicObject::GetSource(void) const void DynamicObject::Register(void) { - DynamicType::Ptr dtype = GetType(); + { + DynamicType::Ptr dtype = GetType(); + ObjectLock olock(dtype); - DynamicObject::Ptr dobj = dtype->GetObject(GetName()); - DynamicObject::Ptr self = GetSelf(); - assert(!dobj || dobj == self); + DynamicObject::Ptr dobj = dtype->GetObject(GetName()); - dtype->RegisterObject(self); + DynamicObject::Ptr self = GetSelf(); + assert(!dobj || dobj == self); + + if (!dobj) + dtype->RegisterObject(self); + } OnRegistered(GetSelf()); @@ -375,10 +401,9 @@ void DynamicObject::DumpObjects(const String& filename) StdioStream::Ptr sfp = boost::make_shared(&fp, false); sfp->Start(); - DynamicType::Ptr type; - BOOST_FOREACH(tie(tuples::ignore, type), DynamicType::GetTypes()) { - DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), type->GetObjects()) { + ; + BOOST_FOREACH(const DynamicType::Ptr& type, DynamicType::GetTypes()) { + BOOST_FOREACH(const DynamicObject::Ptr& object, type->GetObjects()) { if (object->IsLocal()) continue; @@ -472,13 +497,16 @@ void DynamicObject::RestoreObjects(const String& filename) void DynamicObject::DeactivateObjects(void) { - DynamicType::TypeMap::iterator tt; - for (tt = DynamicType::GetTypes().begin(); tt != DynamicType::GetTypes().end(); tt++) { - DynamicType::NameMap::iterator nt; + BOOST_FOREACH(const DynamicType::Ptr& dt, DynamicType::GetTypes()) { + set objects; - while ((nt = tt->second->GetObjects().begin()) != tt->second->GetObjects().end()) { - DynamicObject::Ptr object = nt->second; + { + ObjectLock olock(dt); + objects = dt->GetObjects(); + } + BOOST_FOREACH(const DynamicObject::Ptr& object, objects) { + ObjectLock olock(object); object->Unregister(); } } @@ -543,3 +571,13 @@ const DynamicObject::AttributeMap& DynamicObject::GetAttributes(void) const { return m_Attributes; } + +void DynamicObject::SetEvents(bool events) +{ + m_Events = events; +} + +bool DynamicObject::GetEvents(void) const +{ + return m_Events; +} diff --git a/lib/base/dynamicobject.h b/lib/base/dynamicobject.h index dc8ddeea6..385d4a19d 100644 --- a/lib/base/dynamicobject.h +++ b/lib/base/dynamicobject.h @@ -122,6 +122,9 @@ public: const AttributeMap& GetAttributes(void) const; + void SetEvents(bool events); + bool GetEvents(void) const; + static DynamicObject::Ptr GetObject(const String& type, const String& name); static void DumpObjects(const String& filename); @@ -144,6 +147,8 @@ private: map m_ModifiedAttributes; double m_ConfigTx; + bool m_Events; + static double m_CurrentTx; /* This has to be a set of raw pointers because the DynamicObject diff --git a/lib/base/dynamictype.cpp b/lib/base/dynamictype.cpp index dc26d1be3..144e9069f 100644 --- a/lib/base/dynamictype.cpp +++ b/lib/base/dynamictype.cpp @@ -32,9 +32,9 @@ DynamicType::Ptr DynamicType::GetByName(const String& name) { boost::mutex::scoped_lock lock(GetStaticMutex()); - DynamicType::TypeMap::const_iterator tt = GetTypes().find(name); + DynamicType::TypeMap::const_iterator tt = InternalGetTypeMap().find(name); - if (tt == GetTypes().end()) + if (tt == InternalGetTypeMap().end()) return DynamicType::Ptr(); return tt->second; @@ -43,18 +43,34 @@ DynamicType::Ptr DynamicType::GetByName(const String& name) /** * @threadsafety Caller must hold DynamicType::GetStaticMutex() while using the map. */ -DynamicType::TypeMap& DynamicType::GetTypes(void) +DynamicType::TypeMap& DynamicType::InternalGetTypeMap(void) { - static DynamicType::TypeMap types; - return types; + static DynamicType::TypeMap typemap; + return typemap; } -/** - * @threadsafety Caller must hold DynamicType::GetStaticMutex() while using the map. - */ -DynamicType::NameMap& DynamicType::GetObjects(void) +DynamicType::TypeSet& DynamicType::InternalGetTypeSet(void) { - return m_Objects; + static DynamicType::TypeSet typeset; + return typeset; +} + +DynamicType::TypeSet DynamicType::GetTypes(void) +{ + boost::mutex::scoped_lock lock(GetStaticMutex()); + return InternalGetTypeSet(); /* Making a copy of the set here. */ +} + +set DynamicType::GetObjects(const String& type) +{ + DynamicType::Ptr dt = GetByName(type); + ObjectLock olock(dt); + return dt->GetObjects(); +} + +set DynamicType::GetObjects(void) const +{ + return m_ObjectSet; /* Making a copy of the set here. */ } String DynamicType::GetName(void) const @@ -64,19 +80,30 @@ String DynamicType::GetName(void) const void DynamicType::RegisterObject(const DynamicObject::Ptr& object) { - m_Objects[object->GetName()] = object; + ObjectLock olock(object); + object->SetEvents(true); + + if (m_ObjectMap.find(object->GetName()) != m_ObjectMap.end()) + BOOST_THROW_EXCEPTION(runtime_error("RegisterObject() found existing object with the same name: " + object->GetName())); + + m_ObjectMap[object->GetName()] = object; + m_ObjectSet.insert(object); } void DynamicType::UnregisterObject(const DynamicObject::Ptr& object) { - m_Objects.erase(object->GetName()); + ObjectLock olock(object); + object->SetEvents(false); + + m_ObjectMap.erase(object->GetName()); + m_ObjectSet.erase(object); } DynamicObject::Ptr DynamicType::GetObject(const String& name) const { - DynamicType::NameMap::const_iterator nt = m_Objects.find(name); + DynamicType::ObjectMap::const_iterator nt = m_ObjectMap.find(name); - if (nt == m_Objects.end()) + if (nt == m_ObjectMap.end()) return DynamicObject::Ptr(); return nt->second; @@ -89,18 +116,20 @@ void DynamicType::RegisterType(const DynamicType::Ptr& type) { boost::mutex::scoped_lock lock(GetStaticMutex()); - DynamicType::TypeMap::const_iterator tt = GetTypes().find(type->GetName()); + DynamicType::TypeMap::const_iterator tt = InternalGetTypeMap().find(type->GetName()); - if (tt != GetTypes().end()) + if (tt != InternalGetTypeMap().end()) BOOST_THROW_EXCEPTION(runtime_error("Cannot register class for type '" + type->GetName() + "': Objects of this type already exist.")); - GetTypes()[type->GetName()] = type; + InternalGetTypeMap()[type->GetName()] = type; + InternalGetTypeSet().insert(type); } DynamicObject::Ptr DynamicType::CreateObject(const Dictionary::Ptr& serializedUpdate) const { DynamicObject::Ptr obj = m_ObjectFactory(serializedUpdate); + ObjectLock olock(obj); /* register attributes */ String name; diff --git a/lib/base/dynamictype.h b/lib/base/dynamictype.h index 5a46b4552..952e518aa 100644 --- a/lib/base/dynamictype.h +++ b/lib/base/dynamictype.h @@ -36,8 +36,6 @@ public: typedef weak_ptr WeakPtr; typedef function ObjectFactory; - typedef map TypeMap; - typedef map NameMap; DynamicType(const String& name, const ObjectFactory& factory); @@ -54,8 +52,10 @@ public: void RegisterObject(const DynamicObject::Ptr& object); void UnregisterObject(const DynamicObject::Ptr& object); - /* TODO(thread) make private */ static TypeMap& GetTypes(void); - /* TODO(thread) make private */ NameMap& GetObjects(void); + static set GetTypes(void); + set GetObjects(void) const; + + static set GetObjects(const String& type); void AddAttribute(const String& name, DynamicAttributeType type); void RemoveAttribute(const String& name); @@ -68,8 +68,17 @@ private: ObjectFactory m_ObjectFactory; map m_Attributes; - NameMap m_Objects; + typedef map ObjectMap; + typedef set ObjectSet; + ObjectMap m_ObjectMap; + ObjectSet m_ObjectSet; + + typedef map TypeMap; + typedef set TypeSet; + + static TypeMap& InternalGetTypeMap(void); + static TypeSet& InternalGetTypeSet(void); static boost::mutex& GetStaticMutex(void); }; diff --git a/lib/base/logger.cpp b/lib/base/logger.cpp index 56d245bdb..622ae9840 100644 --- a/lib/base/logger.cpp +++ b/lib/base/logger.cpp @@ -107,24 +107,17 @@ void Logger::ForwardLogEntry(const LogEntry& entry) { bool processed = false; - DynamicType::Ptr dt = DynamicType::GetByName("Logger"); + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Logger")) { + Logger::Ptr logger = dynamic_pointer_cast(object); - DynamicObject::Ptr object; + { + ObjectLock llock(logger); - { - ObjectLock olock(dt); - BOOST_FOREACH(tie(tuples::ignore, object), dt->GetObjects()) { - Logger::Ptr logger = dynamic_pointer_cast(object); - - { - ObjectLock llock(logger); - - if (entry.Severity >= logger->GetMinSeverity()) - logger->m_Impl->ProcessLogEntry(entry); - } - - processed = true; + if (entry.Severity >= logger->GetMinSeverity()) + logger->m_Impl->ProcessLogEntry(entry); } + + processed = true; } LogSeverity defaultLogLevel; diff --git a/lib/base/object.h b/lib/base/object.h index 1d6e63904..d898a0c3d 100644 --- a/lib/base/object.h +++ b/lib/base/object.h @@ -112,35 +112,22 @@ private: struct ObjectLock { public: ObjectLock(const Object::Ptr& object) -#ifdef _DEBUG - : m_Lock(), m_Object(object) -#endif /* _DEBUG */ + : m_Lock() { if (object) m_Lock = recursive_mutex::scoped_lock(object->GetMutex()); } ObjectLock(const Object *object) -#ifdef _DEBUG - : m_Lock(), m_Object(object->GetSelf()) -#endif /* _DEBUG */ + : m_Lock() { if (object) m_Lock = recursive_mutex::scoped_lock(object->GetMutex()); } -#ifdef _DEBUG - ~ObjectLock(void) - { - assert(m_Object.lock()); - } -#endif /* _DEBUG */ private: recursive_mutex::scoped_lock m_Lock; -#ifdef _DEBUG - Object::WeakPtr m_Object; -#endif /* _DEBUG */ }; /** diff --git a/lib/base/ringbuffer.cpp b/lib/base/ringbuffer.cpp index cc8d559bd..15a844971 100644 --- a/lib/base/ringbuffer.cpp +++ b/lib/base/ringbuffer.cpp @@ -13,7 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * aRingBuffer::SizeType with this program; if not, write to the Free Software Foundation * + * along with this program; if not, write to the Free Software Foundation * * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ******************************************************************************/ @@ -22,7 +22,7 @@ using namespace icinga; RingBuffer::RingBuffer(RingBuffer::SizeType slots) - : m_Slots(slots, 0), m_Offset(0) + : m_Slots(slots, 0), m_TimeValue(0) { } RingBuffer::SizeType RingBuffer::GetLength(void) const @@ -34,17 +34,23 @@ void RingBuffer::InsertValue(RingBuffer::SizeType tv, int num) { vector::size_type offsetTarget = tv % m_Slots.size(); - /* walk towards the target offset, resetting slots to 0 */ - while (m_Offset != offsetTarget) { - m_Offset++; + if (tv > m_TimeValue) { + vector::size_type offset = m_TimeValue % m_Slots.size(); - if (m_Offset >= m_Slots.size()) - m_Offset = 0; + /* walk towards the target offset, resetting slots to 0 */ + while (offset != offsetTarget) { + offset++; - m_Slots[m_Offset] = 0; + if (offset >= m_Slots.size()) + offset = 0; + + m_Slots[offset] = 0; + } + + m_TimeValue = tv; } - m_Slots[m_Offset] += num; + m_Slots[offsetTarget] += num; } int RingBuffer::GetValues(RingBuffer::SizeType span) const @@ -52,7 +58,7 @@ int RingBuffer::GetValues(RingBuffer::SizeType span) const if (span > m_Slots.size()) span = m_Slots.size(); - int off = m_Offset; + int off = m_TimeValue % m_Slots.size();; int sum = 0; while (span > 0) { sum += m_Slots[off]; diff --git a/lib/base/ringbuffer.h b/lib/base/ringbuffer.h index 217788246..392d6a1d5 100644 --- a/lib/base/ringbuffer.h +++ b/lib/base/ringbuffer.h @@ -41,7 +41,7 @@ public: private: vector m_Slots; - SizeType m_Offset; + int m_TimeValue; }; } diff --git a/lib/base/scripttask.cpp b/lib/base/scripttask.cpp index 5ef9030b5..e771001fd 100644 --- a/lib/base/scripttask.cpp +++ b/lib/base/scripttask.cpp @@ -29,5 +29,6 @@ ScriptTask::ScriptTask(const ScriptFunction::Ptr& function, void ScriptTask::Run(void) { + ObjectLock olock(this); m_Function->Invoke(GetSelf(), m_Arguments); } diff --git a/lib/config/configcompilercontext.cpp b/lib/config/configcompilercontext.cpp index a6fdf29dc..44bd2fc02 100644 --- a/lib/config/configcompilercontext.cpp +++ b/lib/config/configcompilercontext.cpp @@ -111,14 +111,20 @@ void ConfigCompilerContext::Validate(void) SetContext(this); BOOST_FOREACH(const ConfigItem::Ptr& item, m_Items) { - ConfigType::Ptr ctype = GetType(item->GetType()); + ConfigType::Ptr ctype; - if (!ctype) { - AddError(true, "No validation type found for object '" + item->GetName() + "' of type '" + item->GetType() + "'"); + { + ObjectLock olock(item); + ctype = GetType(item->GetType()); - continue; + if (!ctype) { + AddError(true, "No validation type found for object '" + item->GetName() + "' of type '" + item->GetType() + "'"); + + continue; + } } + ObjectLock olock(ctype); ctype->ValidateItem(item); } @@ -131,7 +137,7 @@ void ConfigCompilerContext::ActivateItems(void) Logger::Write(LogInformation, "config", "Activating config items in compilation unit '" + m_Unit + "'"); BOOST_FOREACH(const ConfigItem::Ptr& item, m_Items) { + ObjectLock olock(item); item->Commit(); } } - diff --git a/lib/config/configtype.cpp b/lib/config/configtype.cpp index 0f6abe805..3ea192c1c 100644 --- a/lib/config/configtype.cpp +++ b/lib/config/configtype.cpp @@ -132,7 +132,11 @@ void ConfigType::ValidateDictionary(const Dictionary::Ptr& dictionary, ScriptTask::Ptr task = boost::make_shared(func, arguments); task->Start(); task->Wait(); - task->GetResult(); + + { + ObjectLock olock(task); + task->GetResult(); + } } } diff --git a/lib/icinga/host.cpp b/lib/icinga/host.cpp index 09a93ccde..554d22da3 100644 --- a/lib/icinga/host.cpp +++ b/lib/icinga/host.cpp @@ -311,8 +311,7 @@ void Host::ValidateServicesCache(void) m_ServicesCache.clear(); - DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Service")->GetObjects()) { + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) { const Service::Ptr& service = static_pointer_cast(object); // TODO: assert for duplicate short_names diff --git a/lib/icinga/hostgroup.cpp b/lib/icinga/hostgroup.cpp index 48b6cdfb8..a41dfef2d 100644 --- a/lib/icinga/hostgroup.cpp +++ b/lib/icinga/hostgroup.cpp @@ -21,6 +21,7 @@ using namespace icinga; +boost::mutex HostGroup::m_Mutex; map > HostGroup::m_MembersCache; bool HostGroup::m_MembersCacheValid = true; @@ -77,13 +78,16 @@ set HostGroup::GetMembers(void) const ValidateMembersCache(); - BOOST_FOREACH(const Host::WeakPtr& hst, m_MembersCache[GetName()]) { - Host::Ptr host = hst.lock(); + { + boost::mutex::scoped_lock lock(m_Mutex); + BOOST_FOREACH(const Host::WeakPtr& hst, m_MembersCache[GetName()]) { + Host::Ptr host = hst.lock(); - if (!host) - continue; + if (!host) + continue; - hosts.insert(host); + hosts.insert(host); + } } return hosts; @@ -91,25 +95,29 @@ set HostGroup::GetMembers(void) const void HostGroup::InvalidateMembersCache(void) { + boost::mutex::scoped_lock lock(m_Mutex); m_MembersCacheValid = false; m_MembersCache.clear(); } void HostGroup::ValidateMembersCache(void) { + boost::mutex::scoped_lock lock(m_Mutex); + if (m_MembersCacheValid) return; m_MembersCache.clear(); - DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Host")->GetObjects()) { + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Host")) { const Host::Ptr& host = static_pointer_cast(object); + ObjectLock olock(host); Dictionary::Ptr dict; dict = host->GetGroups(); if (dict) { + ObjectLock mlock(dict); Value hostgroup; BOOST_FOREACH(tie(tuples::ignore, hostgroup), dict) { if (!HostGroup::Exists(hostgroup)) diff --git a/lib/icinga/hostgroup.h b/lib/icinga/hostgroup.h index 178544356..a5d08384d 100644 --- a/lib/icinga/hostgroup.h +++ b/lib/icinga/hostgroup.h @@ -47,6 +47,7 @@ public: static void InvalidateMembersCache(void); private: + static boost::mutex m_Mutex; static map > > m_MembersCache; static bool m_MembersCacheValid; diff --git a/lib/icinga/service-comment.cpp b/lib/icinga/service-comment.cpp index d75fde7f0..c7be98320 100644 --- a/lib/icinga/service-comment.cpp +++ b/lib/icinga/service-comment.cpp @@ -167,8 +167,7 @@ void Service::ValidateCommentsCache(void) m_CommentsCache.clear(); m_LegacyCommentsCache.clear(); - DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Service")->GetObjects()) { + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) { Service::Ptr service = dynamic_pointer_cast(object); service->AddCommentsToCache(); } @@ -210,11 +209,7 @@ void Service::RemoveExpiredComments(void) void Service::CommentsExpireTimerHandler(void) { - DynamicType::Ptr dt = DynamicType::GetByName("Service"); - ObjectLock dlock(dt); - - DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), dt->GetObjects()) { + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) { Service::Ptr service = dynamic_pointer_cast(object); ObjectLock olock(service); service->RemoveExpiredComments(); diff --git a/lib/icinga/service-downtime.cpp b/lib/icinga/service-downtime.cpp index 0d98fac6a..b3ceb35c0 100644 --- a/lib/icinga/service-downtime.cpp +++ b/lib/icinga/service-downtime.cpp @@ -232,8 +232,7 @@ void Service::ValidateDowntimesCache(void) m_DowntimesCache.clear(); m_LegacyDowntimesCache.clear(); - DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Service")->GetObjects()) { + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) { Service::Ptr service = dynamic_pointer_cast(object); service->AddDowntimesToCache(); } @@ -275,11 +274,7 @@ void Service::RemoveExpiredDowntimes(void) void Service::DowntimesExpireTimerHandler(void) { - DynamicType::Ptr dt = DynamicType::GetByName("Service"); - ObjectLock dlock(dt); - - DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), dt->GetObjects()) { + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) { Service::Ptr service = dynamic_pointer_cast(object); ObjectLock slock(service); service->RemoveExpiredDowntimes(); diff --git a/lib/icinga/service-notification.cpp b/lib/icinga/service-notification.cpp index 1d5fa9e9f..7e684e4ff 100644 --- a/lib/icinga/service-notification.cpp +++ b/lib/icinga/service-notification.cpp @@ -68,8 +68,7 @@ void Service::ValidateNotificationsCache(void) m_NotificationsCache.clear(); - DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Notification")->GetObjects()) { + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Notification")) { const Notification::Ptr& notification = static_pointer_cast(object); m_NotificationsCache[notification->GetService()->GetName()].insert(notification); diff --git a/lib/icinga/servicegroup.cpp b/lib/icinga/servicegroup.cpp index c07e940cf..fd168886b 100644 --- a/lib/icinga/servicegroup.cpp +++ b/lib/icinga/servicegroup.cpp @@ -21,6 +21,7 @@ using namespace icinga; +boost::mutex ServiceGroup::m_Mutex; map > ServiceGroup::m_MembersCache; bool ServiceGroup::m_MembersCacheValid; @@ -77,13 +78,16 @@ set ServiceGroup::GetMembers(void) const ValidateMembersCache(); - BOOST_FOREACH(const Service::WeakPtr& svc, m_MembersCache[GetName()]) { - Service::Ptr service = svc.lock(); + { + boost::mutex::scoped_lock lock(m_Mutex); + BOOST_FOREACH(const Service::WeakPtr& svc, m_MembersCache[GetName()]) { + Service::Ptr service = svc.lock(); - if (!service) - continue; + if (!service) + continue; - services.insert(service); + services.insert(service); + } } return services; @@ -91,25 +95,29 @@ set ServiceGroup::GetMembers(void) const void ServiceGroup::InvalidateMembersCache(void) { + boost::mutex::scoped_lock lock(m_Mutex); m_MembersCacheValid = false; m_MembersCache.clear(); } void ServiceGroup::ValidateMembersCache(void) { + boost::mutex::scoped_lock lock(m_Mutex); + if (m_MembersCacheValid) return; m_MembersCache.clear(); - DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Service")->GetObjects()) { + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) { const Service::Ptr& service = static_pointer_cast(object); + ObjectLock olock(service); Dictionary::Ptr dict; dict = service->GetGroups(); if (dict) { + ObjectLock mlock(dict); Value servicegroup; BOOST_FOREACH(tie(tuples::ignore, servicegroup), dict) { if (!ServiceGroup::Exists(servicegroup)) diff --git a/lib/icinga/servicegroup.h b/lib/icinga/servicegroup.h index 631f943f9..f9d8b01e5 100644 --- a/lib/icinga/servicegroup.h +++ b/lib/icinga/servicegroup.h @@ -47,6 +47,7 @@ public: static void InvalidateMembersCache(void); private: + static boost::mutex m_Mutex; static map > > m_MembersCache; static bool m_MembersCacheValid; diff --git a/lib/remoting/endpointmanager.cpp b/lib/remoting/endpointmanager.cpp index 3d122a7cf..16cc00492 100644 --- a/lib/remoting/endpointmanager.cpp +++ b/lib/remoting/endpointmanager.cpp @@ -232,8 +232,8 @@ void EndpointManager::SendAnycastMessage(const Endpoint::Ptr& sender, BOOST_THROW_EXCEPTION(invalid_argument("Message is missing the 'method' property.")); vector candidates; - DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Endpoint")->GetObjects()) { + + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Endpoint")) { Endpoint::Ptr endpoint = dynamic_pointer_cast(object); /* don't forward messages between non-local endpoints */ if ((sender && !sender->IsLocal()) && !endpoint->IsLocal()) @@ -279,8 +279,7 @@ void EndpointManager::SendMulticastMessage(const Endpoint::Ptr& sender, if (!message.GetMethod(&method)) BOOST_THROW_EXCEPTION(invalid_argument("Message is missing the 'method' property.")); - DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Endpoint")->GetObjects()) { + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Endpoint")) { Endpoint::Ptr recipient = dynamic_pointer_cast(object); /* don't forward messages back to the sender */ @@ -327,8 +326,7 @@ void EndpointManager::SubscriptionTimerHandler(void) { Dictionary::Ptr subscriptions = boost::make_shared(); - DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Endpoint")->GetObjects()) { + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Endpoint")) { Endpoint::Ptr endpoint = dynamic_pointer_cast(object); /* don't copy subscriptions from non-local endpoints or the identity endpoint */ @@ -349,8 +347,7 @@ void EndpointManager::SubscriptionTimerHandler(void) void EndpointManager::ReconnectTimerHandler(void) { - DynamicObject::Ptr object; - BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Endpoint")->GetObjects()) { + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Endpoint")) { Endpoint::Ptr endpoint = dynamic_pointer_cast(object); if (endpoint->IsConnected() || endpoint == m_Endpoint)