Fine-grained locks (WIP, Part 7).

This commit is contained in:
Gunnar Beutner 2013-02-20 19:52:25 +01:00
parent 997ca3a77a
commit 5e91f6c54d
28 changed files with 241 additions and 146 deletions

View File

@ -60,6 +60,7 @@ void CheckerComponent::Stop(void)
void CheckerComponent::CheckThreadProc(void)
{
for (;;) {
vector<Service::Ptr> services;
Service::Ptr service;
{
@ -142,6 +143,11 @@ void CheckerComponent::CheckThreadProc(void)
m_PendingServices.insert(service);
}
double rwait = service->GetNextCheck() - Utility::GetTime();
if (abs(rwait - wait) > 5)
Logger::Write(LogWarning, "checker", "Check delayed: " + Convert::ToString(-rwait) + ",planned wait: " + Convert::ToString(-wait));
try {
service->BeginExecuteCheck(boost::bind(&CheckerComponent::CheckCompletedHandler, this, service));
} catch (const exception& ex) {

View File

@ -91,7 +91,7 @@ String CompatComponent::GetCommandPath(void) const
void CompatComponent::Start(void)
{
m_StatusTimer = boost::make_shared<Timer>();
m_StatusTimer->SetInterval(5);
m_StatusTimer->SetInterval(30);
m_StatusTimer->OnTimerExpired.connect(boost::bind(&CompatComponent::StatusTimerHandler, this));
m_StatusTimer->Start();
m_StatusTimer->Reschedule(0);
@ -544,22 +544,19 @@ void CompatComponent::StatusTimerHandler(void)
}
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("HostGroup")) {
set<Host::Ptr> members;
HostGroup::Ptr hg = static_pointer_cast<HostGroup>(object);
{
HostGroup::Ptr hg = static_pointer_cast<HostGroup>(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";
members = hg->GetMembers();
}
objectfp << "\t" << "members" << "\t";
DumpNameList(objectfp, members);
DumpNameList(objectfp, HostGroup::GetMembers(hg));
objectfp << "\n"
<< "}" << "\n";
}
@ -572,24 +569,21 @@ void CompatComponent::StatusTimerHandler(void)
}
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("ServiceGroup")) {
set<Service::Ptr> members;
ServiceGroup::Ptr sg = static_pointer_cast<ServiceGroup>(object);
{
ServiceGroup::Ptr sg = static_pointer_cast<ServiceGroup>(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";
members = sg->GetMembers();
}
objectfp << "\t" << "members" << "\t";
vector<String> sglist;
BOOST_FOREACH(const Service::Ptr& service, members) {
BOOST_FOREACH(const Service::Ptr& service, ServiceGroup::GetMembers(sg)) {
Host::Ptr host;
String host_name, short_name;

View File

@ -759,7 +759,7 @@ void CompatIdoComponent::DumpConfigObjects(void)
vector<String> hglist;
BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
BOOST_FOREACH(const Host::Ptr& host, HostGroup::GetMembers(hg)) {
hglist.push_back(host->GetName());
}
@ -793,7 +793,7 @@ void CompatIdoComponent::DumpConfigObjects(void)
vector<String> sglist;
vector<Service::Ptr>::iterator vt;
BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
BOOST_FOREACH(const Service::Ptr& service, ServiceGroup::GetMembers(sg)) {
sglist.push_back(service->GetHost()->GetName());
sglist.push_back(service->GetShortName());
}

View File

@ -33,7 +33,7 @@ signals2::signal<void (double, const set<DynamicObject::WeakPtr>&)> DynamicObjec
signals2::signal<void (const DynamicObject::Ptr&)> DynamicObject::OnFlushObject;
DynamicObject::DynamicObject(const Dictionary::Ptr& serializedObject)
: m_Events(false), m_ConfigTx(0)
: m_EventSafe(false), m_ConfigTx(0)
{
RegisterAttribute("__name", Attribute_Config);
RegisterAttribute("__type", Attribute_Config);
@ -88,7 +88,7 @@ void DynamicObject::SendLocalUpdateEvents(void)
}
/* Check if it's safe to send events. */
if (GetEvents()) {
if (GetEventSafe()) {
map<String, Value, string_iless>::iterator it;
for (it = attrs.begin(); it != attrs.end(); it++)
OnAttributeChanged(it->first, it->second);
@ -237,19 +237,14 @@ void DynamicObject::InternalSetAttribute(const String& name, const Value& data,
if (tt.first->second.Type & Attribute_Config)
m_ConfigTx = tx;
DynamicObject::Ptr self;
try {
self = GetSelf();
} catch (const boost::bad_weak_ptr& ex) {
/* We're being called from the constructor. Ignore
* the exception. The OnInitCompleted() function
* will take care of adding this object to the list
* of modified objects. */
}
if (GetEventSafe()) {
/* We can't call GetSelf() in the constructor or destructor.
* The OnConstructionCompleted() function will take care of adding this
* object to the list of modified objects later on if we can't
* do it here. */
if (self) {
boost::mutex::scoped_lock lock(m_TransactionMutex);
m_ModifiedObjects.insert(self);
m_ModifiedObjects.insert(GetSelf());
}
/* Use insert() rather than [] so we don't overwrite
@ -570,8 +565,11 @@ void DynamicObject::NewTx(void)
OnTransactionClosing(tx, objects);
}
void DynamicObject::OnInitCompleted(void)
void DynamicObject::OnConstructionCompleted(void)
{
/* It's now safe to send us attribute events. */
SetEventSafe(true);
/* Add this new object to the list of modified objects.
* We're doing this here because we can't construct
* a while WeakPtr from within the object's constructor. */
@ -579,6 +577,9 @@ void DynamicObject::OnInitCompleted(void)
m_ModifiedObjects.insert(GetSelf());
}
void DynamicObject::OnRegistrationCompleted(void)
{ }
void DynamicObject::OnAttributeChanged(const String&, const Value&)
{ }
@ -600,12 +601,12 @@ const DynamicObject::AttributeMap& DynamicObject::GetAttributes(void) const
return m_Attributes;
}
void DynamicObject::SetEvents(bool events)
void DynamicObject::SetEventSafe(bool safe)
{
m_Events = events;
m_EventSafe = safe;
}
bool DynamicObject::GetEvents(void) const
bool DynamicObject::GetEventSafe(void) const
{
return m_Events;
return m_EventSafe;
}

View File

@ -125,8 +125,8 @@ public:
const AttributeMap& GetAttributes(void) const;
void SetEvents(bool events);
bool GetEvents(void) const;
void SetEventSafe(bool initialized);
bool GetEventSafe(void) const;
static DynamicObject::Ptr GetObject(const String& type, const String& name);
@ -137,7 +137,8 @@ public:
static double GetCurrentTx(void);
protected:
virtual void OnInitCompleted(void);
virtual void OnConstructionCompleted(void);
virtual void OnRegistrationCompleted(void);
virtual void OnAttributeChanged(const String& name, const Value& oldValue);
private:
@ -149,7 +150,7 @@ private:
map<String, Value, string_iless> m_ModifiedAttributes;
double m_ConfigTx;
bool m_Events;
bool m_EventSafe;
static double m_CurrentTx;

View File

@ -80,29 +80,33 @@ String DynamicType::GetName(void) const
void DynamicType::RegisterObject(const DynamicObject::Ptr& object)
{
ObjectLock olock(object);
object->SetEvents(true);
String name;
ObjectMap::iterator it = m_ObjectMap.find(object->GetName());
{
ObjectLock olock(object);
name = object->GetName();
}
ObjectMap::iterator it = m_ObjectMap.find(name);
if (it != m_ObjectMap.end()) {
if (it->second == object)
return;
BOOST_THROW_EXCEPTION(runtime_error("RegisterObject() found existing object with the same name: " + object->GetName()));
BOOST_THROW_EXCEPTION(runtime_error("RegisterObject() found existing object with the same name: " + name));
}
m_ObjectMap[object->GetName()] = object;
m_ObjectMap[name] = object;
m_ObjectSet.insert(object);
/* notify the object that it's been fully initialized */
object->OnInitCompleted();
/* notify the object that it's been registered */
object->OnRegistrationCompleted();
}
void DynamicType::UnregisterObject(const DynamicObject::Ptr& object)
{
ObjectLock olock(object);
object->SetEvents(false);
object->SetEventSafe(false);
m_ObjectMap.erase(object->GetName());
m_ObjectSet.erase(object);
@ -138,16 +142,21 @@ void DynamicType::RegisterType(const DynamicType::Ptr& type)
DynamicObject::Ptr DynamicType::CreateObject(const Dictionary::Ptr& serializedUpdate) const
{
DynamicObject::Ptr object = m_ObjectFactory(serializedUpdate);
ObjectLock olock(object);
/* register attributes */
String name;
DynamicAttributeType type;
BOOST_FOREACH(tuples::tie(name, type), m_Attributes)
object->RegisterAttribute(name, type);
{
ObjectLock olock(object);
/* apply the object's non-config attributes */
object->ApplyUpdate(serializedUpdate, Attribute_All & ~Attribute_Config);
/* register attributes */
String name;
DynamicAttributeType type;
BOOST_FOREACH(tuples::tie(name, type), m_Attributes)
object->RegisterAttribute(name, type);
/* apply the object's non-config attributes */
object->ApplyUpdate(serializedUpdate, Attribute_All & ~Attribute_Config);
}
object->OnConstructionCompleted();
return object;
}

View File

@ -25,15 +25,13 @@ using namespace icinga;
* @threadsafety Always.
*/
EventQueue::EventQueue(void)
: m_Stopped(false)
: m_Stopped(false), m_LastReport(0)
{
int thread_count = thread::hardware_concurrency();
if (thread_count < 4)
thread_count = 4;
thread_count *= 4;
for (int i = 0; i < thread_count; i++)
m_Threads.create_thread(boost::bind(&EventQueue::QueueThreadProc, this));
}
@ -116,4 +114,11 @@ 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(LogWarning, "base", "More than 1000 pending events: " + Convert::ToString(pending));
m_LastReport = now;
}
}

View File

@ -47,6 +47,7 @@ private:
boost::mutex m_Mutex;
condition_variable m_CV;
double m_LastReport;
bool m_Stopped;
vector<Callback> m_Events;

View File

@ -24,6 +24,7 @@ using namespace icinga;
boost::once_flag Process::m_ThreadOnce;
boost::mutex Process::m_Mutex;
deque<Process::Ptr> Process::m_Tasks;
double Process::m_LastReport = 0;
Process::Process(const vector<String>& arguments, const Dictionary::Ptr& extraEnvironment)
: AsyncTask<Process, ProcessResult>(), m_Arguments(arguments), m_ExtraEnvironment(extraEnvironment)
@ -65,9 +66,18 @@ vector<String> Process::SplitCommand(const Value& command)
void Process::Run(void)
{
int count;
{
boost::mutex::scoped_lock lock(m_Mutex);
m_Tasks.push_back(GetSelf());
count = m_Tasks.size();
}
if (count > 50 && Utility::GetTime() - m_LastReport > 5) {
Logger::Write(LogInformation, "base", "More than 50 pending Process tasks: " +
Convert::ToString(count));
m_LastReport = Utility::GetTime();
}
NotifyWorker();

View File

@ -48,7 +48,7 @@ public:
typedef shared_ptr<Process> Ptr;
typedef weak_ptr<Process> WeakPtr;
static const deque<Process::Ptr>::size_type MaxTasksPerThread = 512;
static const deque<Process::Ptr>::size_type MaxTasksPerThread = 128;
Process(const vector<String>& arguments, const Dictionary::Ptr& extraEnvironment = Dictionary::Ptr());
@ -69,6 +69,7 @@ private:
virtual void Run(void);
static boost::mutex m_Mutex;
static double m_LastReport;
static deque<Process::Ptr> m_Tasks;
#ifndef _WIN32
static int m_TaskFd;

View File

@ -32,9 +32,9 @@ Script::Script(const Dictionary::Ptr& properties)
: DynamicObject(properties)
{ }
void Script::OnInitCompleted(void)
void Script::OnRegistrationCompleted(void)
{
DynamicObject::OnInitCompleted();
DynamicObject::OnRegistrationCompleted();
SpawnInterpreter();
}

View File

@ -42,7 +42,7 @@ public:
String GetCode(void) const;
protected:
virtual void OnInitCompleted(void);
virtual void OnRegistrationCompleted(void);
virtual void OnAttributeUpdate(const String& name, const Value& oldValue);
private:

View File

@ -79,7 +79,10 @@ void StreamLogger::ProcessLogEntry(ostream& stream, bool tty, const LogEntry& en
char timestamp[100];
time_t ts = entry.Timestamp;
tm tmnow = *localtime(&ts);
tm tmnow;
if (localtime_r(&ts, &tmnow) == NULL)
BOOST_THROW_EXCEPTION(PosixException("localtime_r() failed.", errno));
strftime(timestamp, sizeof(timestamp), "%Y/%m/%d %H:%M:%S %z", &tmnow);
@ -98,7 +101,7 @@ void StreamLogger::ProcessLogEntry(ostream& stream, bool tty, const LogEntry& en
}
}
stream << "[" << timestamp << "] "
stream << "[" << timestamp << "] <" << boost::this_thread::get_id() << "> "
<< Logger::SeverityToString(entry.Severity) << "/" << entry.Facility << ": "
<< entry.Message;

View File

@ -137,7 +137,6 @@ 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();
ConfigItem::Commit(item);
}
}

View File

@ -103,6 +103,11 @@ vector<String> ConfigItem::GetParents(void) const
return m_Parents;
}
set<ConfigItem::WeakPtr> ConfigItem::GetChildren(void) const
{
return m_ChildObjects;
}
Dictionary::Ptr ConfigItem::Link(void) const
{
Dictionary::Ptr attrs = boost::make_shared<Dictionary>();
@ -151,42 +156,70 @@ void ConfigItem::InternalLink(const Dictionary::Ptr& dictionary) const
*
* @returns The DynamicObject that was created/updated.
*/
DynamicObject::Ptr ConfigItem::Commit(void)
DynamicObject::Ptr ConfigItem::Commit(const ConfigItem::Ptr& self)
{
Logger::Write(LogDebug, "base", "Commit called for ConfigItem Type=" + GetType() + ", Name=" + GetName());
String type, name;
DynamicObject::Ptr dobj;
vector<String> parents;
Dictionary::Ptr properties;
{
ObjectLock olock(self);
type = self->GetType();
name = self->GetName();
dobj = self->GetDynamicObject();
parents = self->GetParents();
properties = self->Link();
}
Logger::Write(LogDebug, "base", "Commit called for ConfigItem Type=" + type + ", Name=" + name);
/* Make sure the type is valid. */
DynamicType::Ptr dtype = DynamicType::GetByName(GetType());
DynamicType::Ptr dtype = DynamicType::GetByName(type);
if (!dtype)
BOOST_THROW_EXCEPTION(runtime_error("Type '" + GetType() + "' does not exist."));
BOOST_THROW_EXCEPTION(runtime_error("Type '" + type + "' does not exist."));
/* Try to find an existing item with the same type and name. */
pair<String, String> ikey = make_pair(GetType(), GetName());
ItemMap::iterator it = m_Items.find(ikey);
{
boost::mutex::scoped_lock lock(m_Mutex);
if (it != m_Items.end()) {
/* Unregister the old item from its parents. */
ConfigItem::Ptr oldItem = it->second;
ObjectLock olock(oldItem);
oldItem->UnregisterFromParents();
/* Try to find an existing item with the same type and name. */
pair<String, String> ikey = make_pair(type, name);
ItemMap::iterator it = m_Items.find(ikey);
/* Steal the old item's children. */
m_ChildObjects = oldItem->m_ChildObjects;
set<ConfigItem::WeakPtr> children;
if (it != m_Items.end()) {
/* Unregister the old item from its parents. */
ConfigItem::Ptr oldItem = it->second;
ObjectLock olock(oldItem);
oldItem->UnregisterFromParents();
/* Steal the old item's children. */
children = oldItem->GetChildren();
}
{
ObjectLock olock(self);
self->m_ChildObjects = children;
}
/* Register this item. */
m_Items[ikey] = self;
}
if (!dobj) {
ObjectLock olock(dtype);
dobj = dtype->GetObject(name);
}
/* Register this item with its parents. */
BOOST_FOREACH(const String& parentName, m_Parents) {
ConfigItem::Ptr parent = GetObject(GetType(), parentName);
BOOST_FOREACH(const String& parentName, parents) {
ConfigItem::Ptr parent = GetObject(type, parentName);
ObjectLock olock(parent);
parent->RegisterChild(GetSelf());
parent->RegisterChild(self);
}
/* Register this item. */
m_Items[ikey] = GetSelf();
Dictionary::Ptr properties = Link();
/* Create a fake update in the format that
* DynamicObject::ApplyUpdate expects. */
Dictionary::Ptr attrs = boost::make_shared<Dictionary>();
@ -206,13 +239,6 @@ DynamicObject::Ptr ConfigItem::Commit(void)
update->Set("configTx", DynamicObject::GetCurrentTx());
/* Update or create the object and apply the configuration settings. */
DynamicObject::Ptr dobj = m_DynamicObject.lock();
if (!dobj) {
ObjectLock dlock(dtype);
dobj = dtype->GetObject(GetName());
}
bool was_null = false;
if (!dobj) {
@ -227,7 +253,7 @@ DynamicObject::Ptr ConfigItem::Commit(void)
if (!was_null)
dobj->ApplyUpdate(update, Attribute_Config);
m_DynamicObject = dobj;
self->m_DynamicObject = dobj;
if (dobj->IsAbstract())
dobj->Unregister();
@ -237,7 +263,12 @@ DynamicObject::Ptr ConfigItem::Commit(void)
/* We need to make a copy of the child objects because the
* OnParentCommitted() handler is going to update the list. */
set<ConfigItem::WeakPtr> children = m_ChildObjects;
set<ConfigItem::WeakPtr> children;
{
ObjectLock olock(self);
children = self->m_ChildObjects;
}
/* notify our children of the update */
BOOST_FOREACH(const ConfigItem::WeakPtr wchild, children) {
@ -246,11 +277,10 @@ DynamicObject::Ptr ConfigItem::Commit(void)
if (!child)
continue;
ObjectLock olock(child);
child->OnParentCommitted();
}
OnCommitted(GetSelf());
OnCommitted(self);
return dobj;
}
@ -305,8 +335,17 @@ void ConfigItem::UnregisterFromParents(void)
*/
void ConfigItem::OnParentCommitted(void)
{
if (GetObject(GetType(), GetName()) == static_cast<ConfigItem::Ptr>(GetSelf()))
Commit();
ConfigItem::Ptr self;
{
ObjectLock olock(this);
self = GetSelf();
if (GetObject(self->GetType(), self->GetName()) != self)
return;
}
Commit(self);
}
/**

View File

@ -43,10 +43,11 @@ public:
String GetUnit(void) const;
vector<String> GetParents(void) const;
set<ConfigItem::WeakPtr> GetChildren(void) const;
ExpressionList::Ptr GetExpressionList(void) const;
DynamicObject::Ptr Commit(void);
static DynamicObject::Ptr Commit(const ConfigItem::Ptr& self);
void Unregister(void);
void Dump(ostream& fp) const;

View File

@ -403,7 +403,7 @@ void ExternalCommandProcessor::EnableHostgroupSvcChecks(double, const vector<Str
HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
BOOST_FOREACH(const Host::Ptr& host, HostGroup::GetMembers(hg)) {
BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
Logger::Write(LogInformation, "icinga", "Enabling active checks for service '" + service->GetName() + "'");
service->SetEnableActiveChecks(true);
@ -418,7 +418,7 @@ void ExternalCommandProcessor::DisableHostgroupSvcChecks(double, const vector<St
HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
BOOST_FOREACH(const Host::Ptr& host, HostGroup::GetMembers(hg)) {
BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
Logger::Write(LogInformation, "icinga", "Disabling active checks for service '" + service->GetName() + "'");
service->SetEnableActiveChecks(false);
@ -433,7 +433,7 @@ void ExternalCommandProcessor::EnableServicegroupSvcChecks(double, const vector<
ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
BOOST_FOREACH(const Service::Ptr& service, ServiceGroup::GetMembers(sg)) {
Logger::Write(LogInformation, "icinga", "Enabling active checks for service '" + service->GetName() + "'");
service->SetEnableActiveChecks(true);
}
@ -446,7 +446,7 @@ void ExternalCommandProcessor::DisableServicegroupSvcChecks(double, const vector
ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
BOOST_FOREACH(const Service::Ptr& service, ServiceGroup::GetMembers(sg)) {
Logger::Write(LogInformation, "icinga", "Disabling active checks for service '" + service->GetName() + "'");
service->SetEnableActiveChecks(false);
}
@ -481,7 +481,7 @@ void ExternalCommandProcessor::EnableServicegroupPassiveSvcChecks(double, const
ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
BOOST_FOREACH(const Service::Ptr& service, ServiceGroup::GetMembers(sg)) {
Logger::Write(LogInformation, "icinga", "Enabling passive checks for service '" + service->GetName() + "'");
service->SetEnablePassiveChecks(true);
}
@ -494,7 +494,7 @@ void ExternalCommandProcessor::DisableServicegroupPassiveSvcChecks(double, const
ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
BOOST_FOREACH(const Service::Ptr& service, ServiceGroup::GetMembers(sg)) {
Logger::Write(LogInformation, "icinga", "Disabling passive checks for service '" + service->GetName() + "'");
service->SetEnablePassiveChecks(true);
}
@ -507,7 +507,7 @@ void ExternalCommandProcessor::EnableHostgroupPassiveSvcChecks(double, const vec
HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
BOOST_FOREACH(const Host::Ptr& host, HostGroup::GetMembers(hg)) {
BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
Logger::Write(LogInformation, "icinga", "Enabling passive checks for service '" + service->GetName() + "'");
service->SetEnablePassiveChecks(true);
@ -522,7 +522,7 @@ void ExternalCommandProcessor::DisableHostgroupPassiveSvcChecks(double, const ve
HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
BOOST_FOREACH(const Host::Ptr& host, HostGroup::GetMembers(hg)) {
BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
Logger::Write(LogInformation, "icinga", "Disabling passive checks for service '" + service->GetName() + "'");
service->SetEnablePassiveChecks(false);
@ -657,7 +657,7 @@ void ExternalCommandProcessor::ScheduleHostgroupHostDowntime(double, const vecto
if (triggeredByLegacy != 0)
triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy);
BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
BOOST_FOREACH(const Host::Ptr& host, HostGroup::GetMembers(hg)) {
Logger::Write(LogInformation, "icinga", "Creating downtime for host " + host->GetName());
Service::Ptr service = host->GetHostCheckService();
if (service) {
@ -686,7 +686,7 @@ void ExternalCommandProcessor::ScheduleHostgroupSvcDowntime(double, const vector
set<Service::Ptr> services;
BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
BOOST_FOREACH(const Host::Ptr& host, HostGroup::GetMembers(hg)) {
BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
services.insert(service);
}
@ -718,7 +718,7 @@ void ExternalCommandProcessor::ScheduleServicegroupHostDowntime(double, const ve
set<Service::Ptr> services;
BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
BOOST_FOREACH(const Service::Ptr& service, ServiceGroup::GetMembers(sg)) {
Host::Ptr host = service->GetHost();
Service::Ptr hcService = host->GetHostCheckService();
if (hcService)
@ -745,7 +745,7 @@ void ExternalCommandProcessor::ScheduleServicegroupSvcDowntime(double, const vec
if (triggeredByLegacy != 0)
triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy);
BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
BOOST_FOREACH(const Service::Ptr& service, ServiceGroup::GetMembers(sg)) {
Logger::Write(LogInformation, "icinga", "Creating downtime for service " + service->GetName());
(void) service->AddDowntime(arguments[6], arguments[7],
Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),

View File

@ -34,13 +34,18 @@ REGISTER_TYPE(Host, hostAttributes);
Host::Host(const Dictionary::Ptr& properties)
: DynamicObject(properties)
{
HostGroup::InvalidateMembersCache();
}
{ }
void Host::OnInitCompleted(void)
void Host::OnRegistrationCompleted(void)
{
UpdateSlaveServices();
DynamicObject::OnRegistrationCompleted();
HostGroup::InvalidateMembersCache();
{
ObjectLock olock(this);
UpdateSlaveServices();
}
}
Host::~Host(void)
@ -264,7 +269,7 @@ void Host::UpdateSlaveServices(void)
}
ConfigItem::Ptr serviceItem = builder->Compile();
serviceItem->Commit();
ConfigItem::Commit(serviceItem);
newServices->Set(name, serviceItem);
}

View File

@ -67,7 +67,7 @@ public:
const std::vector<icinga::Value>& arguments);
protected:
void OnInitCompleted(void);
void OnRegistrationCompleted(void);
void OnAttributeChanged(const String& name, const Value& oldValue);
private:

View File

@ -72,15 +72,23 @@ HostGroup::Ptr HostGroup::GetByName(const String& name)
return dynamic_pointer_cast<HostGroup>(configObject);
}
set<Host::Ptr> HostGroup::GetMembers(void) const
set<Host::Ptr> HostGroup::GetMembers(const HostGroup::Ptr& self)
{
set<Host::Ptr> hosts;
String name;
ValidateMembersCache();
{
ObjectLock olock(self);
name = self->GetName();
}
set<Host::Ptr> hosts;
{
boost::mutex::scoped_lock lock(m_Mutex);
BOOST_FOREACH(const Host::WeakPtr& hst, m_MembersCache[GetName()]) {
ValidateMembersCache();
BOOST_FOREACH(const Host::WeakPtr& hst, m_MembersCache[name]) {
Host::Ptr host = hst.lock();
if (!host)
@ -100,10 +108,11 @@ void HostGroup::InvalidateMembersCache(void)
m_MembersCache.clear();
}
/**
* @threadsafety Caller must hold m_Mutex.
*/
void HostGroup::ValidateMembersCache(void)
{
boost::mutex::scoped_lock lock(m_Mutex);
if (m_MembersCacheValid)
return;

View File

@ -43,7 +43,7 @@ public:
String GetNotesUrl(void) const;
String GetActionUrl(void) const;
set<Host::Ptr> GetMembers(void) const;
static set<Host::Ptr> GetMembers(const HostGroup::Ptr& self);
static void InvalidateMembersCache(void);
private:

View File

@ -77,12 +77,11 @@ void PluginCheckTask::ProcessFinishedHandler(PluginCheckTask ct)
ProcessResult pr;
try {
ObjectLock olock(ct.m_Process);
pr = ct.m_Process->GetResult();
} catch (...) {
{
ObjectLock olock(ct.m_Task);
ct.m_Task->FinishException(boost::current_exception());
}
ObjectLock olock(ct.m_Task);
ct.m_Task->FinishException(boost::current_exception());
return;
}
@ -94,10 +93,8 @@ void PluginCheckTask::ProcessFinishedHandler(PluginCheckTask ct)
result->Set("execution_start", pr.ExecutionStart);
result->Set("execution_end", pr.ExecutionEnd);
{
ObjectLock olock(ct.m_Task);
ct.m_Task->FinishResult(result);
}
ObjectLock olock(ct.m_Task);
ct.m_Task->FinishResult(result);
}
ServiceState PluginCheckTask::ExitStatusToState(int exitStatus)

View File

@ -182,7 +182,7 @@ void Service::UpdateSlaveNotifications(void)
}
ConfigItem::Ptr notificationItem = builder->Compile();
notificationItem->Commit();
ConfigItem::Commit(notificationItem);
newNotifications->Set(name, notificationItem);
}

View File

@ -47,16 +47,21 @@ REGISTER_TYPE(Service, serviceAttributes);
Service::Service(const Dictionary::Ptr& serializedObject)
: DynamicObject(serializedObject)
{ }
void Service::OnRegistrationCompleted(void)
{
DynamicObject::OnRegistrationCompleted();
ServiceGroup::InvalidateMembersCache();
Host::InvalidateServicesCache();
Service::InvalidateDowntimesCache();
Service::InvalidateCommentsCache();
}
void Service::OnInitCompleted(void)
{
UpdateSlaveNotifications();
{
ObjectLock olock(this);
UpdateSlaveNotifications();
}
}
Service::~Service(void)

View File

@ -248,7 +248,7 @@ public:
void SetNextNotification(double time);
protected:
virtual void OnInitCompleted(void);
virtual void OnRegistrationCompleted(void);
virtual void OnAttributeChanged(const String& name, const Value& oldValue);
private:

View File

@ -72,15 +72,23 @@ ServiceGroup::Ptr ServiceGroup::GetByName(const String& name)
return dynamic_pointer_cast<ServiceGroup>(configObject);
}
set<Service::Ptr> ServiceGroup::GetMembers(void) const
set<Service::Ptr> ServiceGroup::GetMembers(const ServiceGroup::Ptr& self)
{
set<Service::Ptr> services;
String name;
ValidateMembersCache();
{
ObjectLock olock(self);
name = self->GetName();
}
set<Service::Ptr> services;
{
boost::mutex::scoped_lock lock(m_Mutex);
BOOST_FOREACH(const Service::WeakPtr& svc, m_MembersCache[GetName()]) {
ValidateMembersCache();
BOOST_FOREACH(const Service::WeakPtr& svc, m_MembersCache[name]) {
Service::Ptr service = svc.lock();
if (!service)
@ -100,10 +108,11 @@ void ServiceGroup::InvalidateMembersCache(void)
m_MembersCache.clear();
}
/**
* @threadsafety Caller must hold m_Mutex.
*/
void ServiceGroup::ValidateMembersCache(void)
{
boost::mutex::scoped_lock lock(m_Mutex);
if (m_MembersCacheValid)
return;

View File

@ -43,7 +43,7 @@ public:
String GetNotesUrl(void) const;
String GetActionUrl(void) const;
set<Service::Ptr> GetMembers(void) const;
static set<Service::Ptr> GetMembers(const ServiceGroup::Ptr& self);
static void InvalidateMembersCache(void);
private:

View File

@ -87,7 +87,7 @@ Endpoint::Ptr Endpoint::MakeEndpoint(const String& name, bool replicated, bool l
endpointConfig->SetLocal(!replicated);
endpointConfig->AddExpression("local", OperatorSet, local);
DynamicObject::Ptr object = endpointConfig->Compile()->Commit();
DynamicObject::Ptr object = ConfigItem::Commit(endpointConfig->Compile());
return dynamic_pointer_cast<Endpoint>(object);
}