Even more code refactoring.

This commit is contained in:
Gunnar Beutner 2013-03-04 15:52:42 +01:00
parent a6d26a2dc1
commit be95f3171d
53 changed files with 680 additions and 897 deletions

View File

@ -109,7 +109,10 @@ void CheckerComponent::CheckThreadProc(void)
continue; continue;
} }
service->SetForceNextCheck(false); {
ObjectLock olock(service);
service->SetForceNextCheck(false);
}
Logger::Write(LogDebug, "checker", "Executing service check for '" + service->GetName() + "'"); Logger::Write(LogDebug, "checker", "Executing service check for '" + service->GetName() + "'");
@ -118,7 +121,7 @@ void CheckerComponent::CheckThreadProc(void)
try { try {
CheckerComponent::Ptr self = GetSelf(); CheckerComponent::Ptr self = GetSelf();
Service::BeginExecuteCheck(service, boost::bind(&CheckerComponent::CheckCompletedHandler, self, service)); service->BeginExecuteCheck(boost::bind(&CheckerComponent::CheckCompletedHandler, self, service));
} catch (const exception& ex) { } catch (const exception& ex) {
Logger::Write(LogCritical, "checker", "Exception occured while checking service '" + service->GetName() + "': " + diagnostic_information(ex)); Logger::Write(LogCritical, "checker", "Exception occured while checking service '" + service->GetName() + "': " + diagnostic_information(ex));
} }

View File

@ -35,7 +35,14 @@ struct ServiceNextCheckExtractor
*/ */
double operator()(const Service::Ptr& service) double operator()(const Service::Ptr& service)
{ {
return service->GetNextCheck(); double next = service->GetNextCheck();
while (next == 0) {
service->UpdateNextCheck();
next = service->GetNextCheck();
}
return next;
} }
}; };

View File

@ -341,7 +341,7 @@ void CompatComponent::DumpHostObject(ostream& fp, const Host::Ptr& host)
void CompatComponent::DumpServiceStatusAttrs(ostream& fp, const Service::Ptr& service, CompatObjectType type) void CompatComponent::DumpServiceStatusAttrs(ostream& fp, const Service::Ptr& service, CompatObjectType type)
{ {
ObjectLock olock(service); assert(service->OwnsLock());
String output; String output;
String perfdata; String perfdata;
@ -413,7 +413,10 @@ void CompatComponent::DumpServiceStatus(ostream& fp, const Service::Ptr& service
<< "\t" << "host_name=" << host->GetName() << "\n" << "\t" << "host_name=" << host->GetName() << "\n"
<< "\t" << "service_description=" << service->GetShortName() << "\n"; << "\t" << "service_description=" << service->GetShortName() << "\n";
DumpServiceStatusAttrs(fp, service, CompatTypeService); {
ObjectLock olock(service);
DumpServiceStatusAttrs(fp, service, CompatTypeService);
}
fp << "\t" << "}" << "\n" fp << "\t" << "}" << "\n"
<< "\n"; << "\n";

View File

@ -144,7 +144,10 @@ void DelegationComponent::DelegationTimerHandler(void)
/* clear the service's current checker */ /* clear the service's current checker */
if (!checker.IsEmpty()) { if (!checker.IsEmpty()) {
service->SetCurrentChecker(""); {
ObjectLock olock(service);
service->SetCurrentChecker("");
}
if (oldEndpoint) if (oldEndpoint)
histogram[oldEndpoint]--; histogram[oldEndpoint]--;
@ -156,7 +159,11 @@ void DelegationComponent::DelegationTimerHandler(void)
if (histogram[candidate] > avg_services) if (histogram[candidate] > avg_services)
continue; continue;
service->SetCurrentChecker(candidate->GetName()); {
ObjectLock olock(service);
service->SetCurrentChecker(candidate->GetName());
}
histogram[candidate]++; histogram[candidate]++;
/* reschedule the service; this avoids "check floods" /* reschedule the service; this avoids "check floods"

View File

@ -222,7 +222,7 @@ void ReplicationComponent::RemoteObjectUpdateHandler(const RequestMessage& reque
// TODO: sanitize update, disallow __local // TODO: sanitize update, disallow __local
if (!object) { if (!object) {
object = DynamicType::CreateObject(dtype, update); object = dtype->CreateObject(update);
if (source == EndpointManager::GetInstance()->GetIdentity()) { if (source == EndpointManager::GetInstance()->GetIdentity()) {
/* the peer sent us an object that was originally created by us - /* the peer sent us an object that was originally created by us -

View File

@ -41,13 +41,14 @@ class IcingaSignalPrinter:
return '<SIGNAL>' return '<SIGNAL>'
def lookup_icinga_type(val): def lookup_icinga_type(val):
if str(val.type) == 'icinga::String': t = val.type.unqualified()
if str(t) == 'icinga::String':
return IcingaStringPrinter(val) return IcingaStringPrinter(val)
elif str(val.type) == 'icinga::Value': elif str(t) == 'icinga::Value':
return IcingaValuePrinter(val) return IcingaValuePrinter(val)
elif str(val.type) == 'icinga::AttributeBase' or re.match('^icinga::Attribute<.*>$', str(val.type)): elif str(t) == 'icinga::AttributeBase' or re.match('^icinga::Attribute<.*>$', str(t)):
return IcingaAttributePrinter(val) return IcingaAttributePrinter(val)
elif re.match('^boost::signals2::signal.*<.*>$', str(val.type)): elif re.match('^boost::signals2::signal.*<.*>$', str(t)):
return IcingaSignalPrinter(val) return IcingaSignalPrinter(val)
return None return None

View File

@ -8,6 +8,8 @@ libbase_la_SOURCES = \
application.cpp \ application.cpp \
application.h \ application.h \
asynctask.h \ asynctask.h \
attribute.cpp \
attribute.h \
component.cpp \ component.cpp \
component.h \ component.h \
connection.cpp \ connection.cpp \

View File

@ -410,9 +410,11 @@ int Application::Run(void)
*/ */
void Application::UpdatePidFile(const String& filename) void Application::UpdatePidFile(const String& filename)
{ {
assert(!OwnsLock());
ObjectLock olock(this); ObjectLock olock(this);
ClosePidFile(); if (m_PidFile != NULL)
fclose(m_PidFile);
/* There's just no sane way of getting a file descriptor for a /* There's just no sane way of getting a file descriptor for a
* C++ ofstream which is why we're using FILEs here. */ * C++ ofstream which is why we're using FILEs here. */
@ -442,6 +444,7 @@ void Application::UpdatePidFile(const String& filename)
*/ */
void Application::ClosePidFile(void) void Application::ClosePidFile(void)
{ {
assert(!OwnsLock());
ObjectLock olock(this); ObjectLock olock(this);
if (m_PidFile != NULL) if (m_PidFile != NULL)

151
lib/base/attribute.cpp Normal file
View File

@ -0,0 +1,151 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#include "i2-base.h"
using namespace icinga;
boost::mutex AttributeBase::m_Mutex;
AttributeBase::AttributeBase(void)
: m_Value()
{ }
/**
* @threadsafety Always.
*/
void AttributeBase::Set(const Value& value)
{
boost::mutex::scoped_lock lock(m_Mutex);
InternalSet(value);
}
/**
* @threadsafety Always.
*/
Value AttributeBase::Get(void) const
{
boost::mutex::scoped_lock lock(m_Mutex);
return InternalGet();
}
/**
* @threadsafety Always.
*/
AttributeBase::operator Value(void) const
{
boost::mutex::scoped_lock lock(m_Mutex);
return InternalGet();
}
/**
* @threadsafety Always.
*/
bool AttributeBase::IsEmpty(void) const
{
boost::mutex::scoped_lock lock(m_Mutex);
return InternalGet().IsEmpty();
}
/**
* @threadsafety Caller must hold m_Mutex;
*/
void AttributeBase::InternalSet(const Value& value)
{
m_Value = value;
}
/**
* @threadsafety Caller must hold m_Mutex.
*/
const Value& AttributeBase::InternalGet(void) const
{
return m_Value;
}
AttributeHolder::AttributeHolder(AttributeType type, AttributeBase *boundAttribute)
: m_Type(type), m_Tx(0)
{
if (boundAttribute) {
m_Attribute = boundAttribute;
m_OwnsAttribute = false;
} else {
m_Attribute = new Attribute<Value>();
m_OwnsAttribute = true;
}
}
AttributeHolder::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->Set(other.m_Attribute->Get());
} else {
m_Attribute = other.m_Attribute;
}
}
AttributeHolder::~AttributeHolder(void)
{
if (m_OwnsAttribute)
delete m_Attribute;
}
void AttributeHolder::Bind(AttributeBase *boundAttribute)
{
assert(m_OwnsAttribute);
boundAttribute->Set(m_Attribute->Get());
m_Attribute = boundAttribute;
m_OwnsAttribute = false;
}
void AttributeHolder::SetValue(double tx, const Value& value)
{
m_Tx = tx;
m_Attribute->Set(value);
}
Value AttributeHolder::GetValue(void) const
{
return m_Attribute->Get();
}
void AttributeHolder::SetType(AttributeType type)
{
m_Type = type;
}
AttributeType AttributeHolder::GetType(void) const
{
return m_Type;
}
void AttributeHolder::SetTx(double tx)
{
m_Tx = tx;
}
double AttributeHolder::GetTx(void) const
{
return m_Tx;
}

152
lib/base/attribute.h Normal file
View File

@ -0,0 +1,152 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#ifndef ATTRIBUTE_H
#define ATTRIBUTE_H
namespace icinga
{
/**
* The type of an attribute for a DynamicObject.
*
* @ingroup base
*/
enum AttributeType
{
Attribute_Transient = 1,
/* Unlike transient attributes local attributes are persisted
* in the program state file. */
Attribute_Local = 2,
/* Replicated attributes are sent to other daemons for which
* replication is enabled. */
Attribute_Replicated = 4,
/* Attributes read from the config file are implicitly marked
* as config attributes. */
Attribute_Config = 8,
/* Combination of all attribute types */
Attribute_All = Attribute_Transient | Attribute_Local | Attribute_Replicated | Attribute_Config
};
class I2_BASE_API AttributeBase
{
public:
AttributeBase(void);
void Set(const Value& value);
Value Get(void) const;
operator Value(void) const;
bool IsEmpty(void) const;
protected:
void InternalSet(const Value& value);
const Value& InternalGet(void) const;
static boost::mutex m_Mutex;
private:
Value m_Value;
AttributeBase(const AttributeBase& other);
AttributeBase& operator=(const AttributeBase& other);
};
template<typename T>
class Attribute : public AttributeBase
{
public:
/**
* @threadsafety Always.
*/
void Set(const T& value)
{
boost::mutex::scoped_lock lock(m_Mutex);
InternalSet(value);
}
/**
* @threadsafety Always.
*/
Attribute<T>& operator=(const T& rhs)
{
Set(rhs);
return *this;
}
T Get(void) const
{
Value value;
{
boost::mutex::scoped_lock lock(m_Mutex);
value = InternalGet();
}
if (value.IsEmpty())
return T();
return value;
}
/**
* @threadsafety Always.
*/
operator T(void) const
{
return Get();
}
};
/**
* An attribute for a DynamicObject.
*
* @ingroup base
*/
class I2_BASE_API AttributeHolder
{
public:
AttributeHolder(AttributeType type, AttributeBase *boundAttribute = NULL);
AttributeHolder(const AttributeHolder& other);
~AttributeHolder(void);
void Bind(AttributeBase *boundAttribute);
void SetValue(double tx, const Value& value);
Value GetValue(void) const;
void SetType(AttributeType type);
AttributeType GetType(void) const;
void SetTx(double tx);
double GetTx(void) const;
private:
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. */
};
}
#endif /* ATTRIBUTE_H */

View File

@ -74,8 +74,6 @@ Component::~Component(void)
*/ */
void Component::Start(void) void Component::Start(void)
{ {
ObjectLock olock(this);
m_Impl->SetConfig(GetSelf()); m_Impl->SetConfig(GetSelf());
m_Impl->Start(); m_Impl->Start();
} }
@ -104,8 +102,6 @@ void Component::AddSearchDir(const String& componentDirectory)
*/ */
DynamicObject::Ptr IComponent::GetConfig(void) const DynamicObject::Ptr IComponent::GetConfig(void) const
{ {
ObjectLock olock(this);
return m_Config.lock(); return m_Config.lock();
} }
@ -114,8 +110,6 @@ DynamicObject::Ptr IComponent::GetConfig(void) const
*/ */
void IComponent::SetConfig(const DynamicObject::Ptr& config) void IComponent::SetConfig(const DynamicObject::Ptr& config)
{ {
ObjectLock olock(this);
m_Config = config; m_Config = config;
} }

View File

@ -70,6 +70,7 @@ Dictionary::Dictionary(void)
*/ */
Value Dictionary::Get(const char *key) const Value Dictionary::Get(const char *key) const
{ {
assert(!OwnsLock());
ObjectLock olock(this); ObjectLock olock(this);
map<String, Value>::const_iterator it; map<String, Value>::const_iterator it;
@ -103,15 +104,16 @@ Value Dictionary::Get(const String& key) const
*/ */
void Dictionary::Set(const String& key, const Value& value) void Dictionary::Set(const String& key, const Value& value)
{ {
ObjectLock olock(this);
assert(!m_Sealed);
if (value.IsEmpty()) { if (value.IsEmpty()) {
Remove(key); Remove(key);
return; return;
} }
assert(!OwnsLock());
ObjectLock olock(this);
assert(!m_Sealed);
pair<map<String, Value>::iterator, bool> ret; pair<map<String, Value>::iterator, bool> ret;
ret = m_Data.insert(make_pair(key, value)); ret = m_Data.insert(make_pair(key, value));
if (!ret.second) if (!ret.second)
@ -127,11 +129,12 @@ void Dictionary::Set(const String& key, const Value& value)
*/ */
String Dictionary::Add(const Value& value) String Dictionary::Add(const Value& value)
{ {
assert(!OwnsLock());
ObjectLock olock(this); ObjectLock olock(this);
Dictionary::Iterator it; Dictionary::Iterator it;
String key; String key;
long index = GetLength(); long index = m_Data.size();
do { do {
stringstream s; stringstream s;
s << "_" << std::hex << std::setw(8) << std::setfill('0') << index; s << "_" << std::hex << std::setw(8) << std::setfill('0') << index;
@ -141,7 +144,11 @@ String Dictionary::Add(const Value& value)
it = m_Data.find(key); it = m_Data.find(key);
} while (it != m_Data.end()); } while (it != m_Data.end());
Set(key, value); pair<map<String, Value>::iterator, bool> ret;
ret = m_Data.insert(make_pair(key, value));
if (!ret.second)
ret.first->second = value;
return key; return key;
} }
@ -177,6 +184,7 @@ Dictionary::Iterator Dictionary::End(void)
*/ */
size_t Dictionary::GetLength(void) const size_t Dictionary::GetLength(void) const
{ {
assert(!OwnsLock());
ObjectLock olock(this); ObjectLock olock(this);
return m_Data.size(); return m_Data.size();
@ -191,6 +199,7 @@ size_t Dictionary::GetLength(void) const
*/ */
bool Dictionary::Contains(const String& key) const bool Dictionary::Contains(const String& key) const
{ {
assert(!OwnsLock());
ObjectLock olock(this); ObjectLock olock(this);
return (m_Data.find(key) != m_Data.end()); return (m_Data.find(key) != m_Data.end());
@ -204,6 +213,7 @@ bool Dictionary::Contains(const String& key) const
*/ */
void Dictionary::Remove(const String& key) void Dictionary::Remove(const String& key)
{ {
assert(!OwnsLock());
ObjectLock olock(this); ObjectLock olock(this);
Dictionary::Iterator it; Dictionary::Iterator it;
@ -222,6 +232,7 @@ void Dictionary::Remove(const String& key)
*/ */
void Dictionary::Remove(Dictionary::Iterator it) void Dictionary::Remove(Dictionary::Iterator it)
{ {
assert(!OwnsLock());
ObjectLock olock(this); ObjectLock olock(this);
String key = it->first; String key = it->first;
@ -234,6 +245,7 @@ void Dictionary::Remove(Dictionary::Iterator it)
*/ */
void Dictionary::Seal(void) void Dictionary::Seal(void)
{ {
assert(!OwnsLock());
ObjectLock olock(this); ObjectLock olock(this);
m_Sealed = true; m_Sealed = true;
@ -246,6 +258,7 @@ void Dictionary::Seal(void)
*/ */
bool Dictionary::IsSealed(void) const bool Dictionary::IsSealed(void) const
{ {
assert(!OwnsLock());
ObjectLock olock(this); ObjectLock olock(this);
return m_Sealed; return m_Sealed;
@ -259,6 +272,7 @@ bool Dictionary::IsSealed(void) const
*/ */
Dictionary::Ptr Dictionary::ShallowClone(void) const Dictionary::Ptr Dictionary::ShallowClone(void) const
{ {
assert(!OwnsLock());
ObjectLock olock(this); ObjectLock olock(this);
Dictionary::Ptr clone = boost::make_shared<Dictionary>(); Dictionary::Ptr clone = boost::make_shared<Dictionary>();

View File

@ -70,31 +70,35 @@ void DynamicObject::Initialize(void)
Dictionary::Ptr DynamicObject::BuildUpdate(double sinceTx, int attributeTypes) const Dictionary::Ptr DynamicObject::BuildUpdate(double sinceTx, int attributeTypes) const
{ {
assert(OwnsLock()); ObjectLock olock(this);
DynamicObject::AttributeConstIterator it; DynamicObject::AttributeConstIterator it;
Dictionary::Ptr attrs = boost::make_shared<Dictionary>(); Dictionary::Ptr attrs = boost::make_shared<Dictionary>();
for (it = m_Attributes.begin(); it != m_Attributes.end(); it++) { {
if (it->second.GetType() == Attribute_Transient) boost::mutex::scoped_lock lock(m_AttributeMutex);
continue;
if ((it->second.GetType() & attributeTypes) == 0) for (it = m_Attributes.begin(); it != m_Attributes.end(); it++) {
continue; if (it->second.GetType() == Attribute_Transient)
continue;
if (it->second.GetTx() == 0) if ((it->second.GetType() & attributeTypes) == 0)
continue; continue;
if (it->second.GetTx() < sinceTx && !(it->second.GetType() == Attribute_Config && m_ConfigTx >= sinceTx)) if (it->second.GetTx() == 0)
continue; continue;
Dictionary::Ptr attr = boost::make_shared<Dictionary>(); if (it->second.GetTx() < sinceTx && !(it->second.GetType() == Attribute_Config && m_ConfigTx >= sinceTx))
attr->Set("data", it->second.GetValue()); continue;
attr->Set("type", it->second.GetType());
attr->Set("tx", it->second.GetTx());
attrs->Set(it->first, attr); Dictionary::Ptr attr = boost::make_shared<Dictionary>();
attr->Set("data", it->second.GetValue());
attr->Set("type", it->second.GetType());
attr->Set("tx", it->second.GetTx());
attrs->Set(it->first, attr);
}
} }
attrs->Seal(); attrs->Seal();
@ -121,11 +125,20 @@ void DynamicObject::ApplyUpdate(const Dictionary::Ptr& serializedUpdate,
Value configTxValue = serializedUpdate->Get("configTx"); Value configTxValue = serializedUpdate->Get("configTx");
if ((allowedTypes & Attribute_Config) != 0 && !configTxValue.IsEmpty()) { boost::mutex::scoped_lock lock(m_AttributeMutex);
double configTx = configTxValue;
if (configTx > m_ConfigTx) if ((allowedTypes & Attribute_Config) != 0 && !configTxValue.IsEmpty()) {
ClearAttributesByType(Attribute_Config); double oldConfigTx, configTx = configTxValue;
if (configTx > m_ConfigTx) {
DynamicObject::AttributeIterator at;
for (at = m_Attributes.begin(); at != m_Attributes.end(); at++) {
if ((at->second.GetType() & Attribute_Config) == 0)
continue;
at->second.SetValue(0, Empty);
}
}
} }
Dictionary::Ptr attrs = serializedUpdate->Get("attrs"); Dictionary::Ptr attrs = serializedUpdate->Get("attrs");
@ -153,10 +166,10 @@ void DynamicObject::ApplyUpdate(const Dictionary::Ptr& serializedUpdate,
double tx = attr->Get("tx"); double tx = attr->Get("tx");
if (type & Attribute_Config) if (type & Attribute_Config)
RegisterAttribute(it->first, Attribute_Config); InternalRegisterAttribute(it->first, Attribute_Config);
if (!HasAttribute(it->first)) if (m_Attributes.find(it->first) == m_Attributes.end())
RegisterAttribute(it->first, static_cast<AttributeType>(type)); InternalRegisterAttribute(it->first, static_cast<AttributeType>(type));
InternalSetAttribute(it->first, data, tx, true); InternalSetAttribute(it->first, data, tx, true);
} }
@ -165,6 +178,20 @@ void DynamicObject::ApplyUpdate(const Dictionary::Ptr& serializedUpdate,
void DynamicObject::RegisterAttribute(const String& name, void DynamicObject::RegisterAttribute(const String& name,
AttributeType type, AttributeBase *boundAttribute) AttributeType type, AttributeBase *boundAttribute)
{
assert(!OwnsLock());
ObjectLock olock(this);
boost::mutex::scoped_lock lock(m_AttributeMutex);
InternalRegisterAttribute(name, type, boundAttribute);
}
/**
* @threadsafety Caller must hold m_AttributeMutex.
*/
void DynamicObject::InternalRegisterAttribute(const String& name,
AttributeType type, AttributeBase *boundAttribute)
{ {
assert(OwnsLock()); assert(OwnsLock());
@ -186,6 +213,11 @@ void DynamicObject::RegisterAttribute(const String& name,
*/ */
void DynamicObject::Set(const String& name, const Value& data) void DynamicObject::Set(const String& name, const Value& data)
{ {
assert(!OwnsLock());
ObjectLock olock(this);
boost::mutex::scoped_lock lock(m_AttributeMutex);
InternalSetAttribute(name, data, GetCurrentTx()); InternalSetAttribute(name, data, GetCurrentTx());
} }
@ -194,7 +226,23 @@ void DynamicObject::Set(const String& name, const Value& data)
*/ */
void DynamicObject::Touch(const String& name) void DynamicObject::Touch(const String& name)
{ {
InternalSetAttribute(name, InternalGetAttribute(name), GetCurrentTx()); assert(!OwnsLock());
boost::mutex::scoped_lock lock(m_AttributeMutex);
AttributeIterator it = m_Attributes.find(name);
if (it == m_Attributes.end())
BOOST_THROW_EXCEPTION(runtime_error("Touch() called for unknown attribute: " + name));
it->second.SetTx(GetCurrentTx());
m_ModifiedAttributes.insert(name);
{
boost::mutex::scoped_lock lock(m_TransactionMutex);
m_ModifiedObjects.insert(GetSelf());
}
} }
/** /**
@ -202,22 +250,25 @@ void DynamicObject::Touch(const String& name)
*/ */
Value DynamicObject::Get(const String& name) const Value DynamicObject::Get(const String& name) const
{ {
assert(!OwnsLock());
ObjectLock olock(this);
boost::mutex::scoped_lock lock(m_AttributeMutex);
return InternalGetAttribute(name); return InternalGetAttribute(name);
} }
/** /**
* @threadsafety Always. * @threadsafety Caller must hold m_AttributeMutex.
*/ */
void DynamicObject::InternalSetAttribute(const String& name, const Value& data, void DynamicObject::InternalSetAttribute(const String& name, const Value& data,
double tx, bool allowEditConfig) double tx, bool allowEditConfig)
{ {
ObjectLock olock(this); assert(OwnsLock());
DynamicObject::AttributeIterator it; DynamicObject::AttributeIterator it;
it = m_Attributes.find(name); it = m_Attributes.find(name);
Value oldValue;
if (it == m_Attributes.end()) { if (it == m_Attributes.end()) {
AttributeHolder attr(Attribute_Transient); AttributeHolder attr(Attribute_Transient);
attr.SetValue(tx, data); attr.SetValue(tx, data);
@ -227,7 +278,6 @@ void DynamicObject::InternalSetAttribute(const String& name, const Value& data,
if (!allowEditConfig && (it->second.GetType() & Attribute_Config)) if (!allowEditConfig && (it->second.GetType() & Attribute_Config))
BOOST_THROW_EXCEPTION(runtime_error("Config properties are immutable: '" + name + "'.")); BOOST_THROW_EXCEPTION(runtime_error("Config properties are immutable: '" + name + "'."));
oldValue = it->second.GetValue();
it->second.SetValue(tx, data); it->second.SetValue(tx, data);
if (it->second.GetType() & Attribute_Config) if (it->second.GetType() & Attribute_Config)
@ -240,26 +290,21 @@ void DynamicObject::InternalSetAttribute(const String& name, const Value& data,
* object to the list of modified objects later on if we can't * object to the list of modified objects later on if we can't
* do it here. */ * do it here. */
DynamicObject::Ptr self = GetSelf();
{ {
boost::mutex::scoped_lock lock(m_TransactionMutex); boost::mutex::scoped_lock lock(m_TransactionMutex);
m_ModifiedObjects.insert(self); m_ModifiedObjects.insert(GetSelf());
} }
} }
/* Use insert() rather than [] so we don't overwrite m_ModifiedAttributes.insert(name);
* an existing oldValue if the attribute was previously
* changed in the same transaction */
m_ModifiedAttributes.insert(make_pair(name, oldValue));
} }
/** /**
* @threadsafety Always. * @threadsafety Caller must hold m_AttributeMutex.
*/ */
Value DynamicObject::InternalGetAttribute(const String& name) const Value DynamicObject::InternalGetAttribute(const String& name) const
{ {
ObjectLock olock(this); assert(OwnsLock());
DynamicObject::AttributeConstIterator it; DynamicObject::AttributeConstIterator it;
it = m_Attributes.find(name); it = m_Attributes.find(name);
@ -270,36 +315,11 @@ Value DynamicObject::InternalGetAttribute(const String& name) const
return it->second.GetValue(); return it->second.GetValue();
} }
/**
* @threadsafety Always.
*/
bool DynamicObject::HasAttribute(const String& name) const
{
ObjectLock olock(this);
return (m_Attributes.find(name) != m_Attributes.end());
}
void DynamicObject::ClearAttributesByType(AttributeType type)
{
assert(OwnsLock());
DynamicObject::AttributeIterator at;
for (at = m_Attributes.begin(); at != m_Attributes.end(); at++) {
if (at->second.GetType() != type)
continue;
at->second.SetValue(0, Empty);
}
}
/** /**
* @threadsafety Always. * @threadsafety Always.
*/ */
DynamicType::Ptr DynamicObject::GetType(void) const DynamicType::Ptr DynamicObject::GetType(void) const
{ {
ObjectLock olock(this);
return DynamicType::GetByName(m_Type); return DynamicType::GetByName(m_Type);
} }
@ -308,8 +328,6 @@ DynamicType::Ptr DynamicObject::GetType(void) const
*/ */
String DynamicObject::GetName(void) const String DynamicObject::GetName(void) const
{ {
ObjectLock olock(this);
return m_Name; return m_Name;
} }
@ -318,8 +336,6 @@ String DynamicObject::GetName(void) const
*/ */
bool DynamicObject::IsLocal(void) const bool DynamicObject::IsLocal(void) const
{ {
ObjectLock olock(this);
return m_Local; return m_Local;
} }
@ -328,8 +344,6 @@ bool DynamicObject::IsLocal(void) const
*/ */
bool DynamicObject::IsAbstract(void) const bool DynamicObject::IsAbstract(void) const
{ {
ObjectLock olock(this);
return m_Abstract; return m_Abstract;
} }
@ -338,8 +352,6 @@ bool DynamicObject::IsAbstract(void) const
*/ */
bool DynamicObject::IsRegistered(void) const bool DynamicObject::IsRegistered(void) const
{ {
ObjectLock olock(this);
return m_Registered; return m_Registered;
} }
@ -348,8 +360,6 @@ bool DynamicObject::IsRegistered(void) const
*/ */
void DynamicObject::SetSource(const String& value) void DynamicObject::SetSource(const String& value)
{ {
ObjectLock olock(this);
m_Source = value; m_Source = value;
Touch("__source"); Touch("__source");
} }
@ -359,8 +369,6 @@ void DynamicObject::SetSource(const String& value)
*/ */
String DynamicObject::GetSource(void) const String DynamicObject::GetSource(void) const
{ {
ObjectLock olock(this);
return m_Source; return m_Source;
} }
@ -368,45 +376,30 @@ void DynamicObject::Register(void)
{ {
assert(!OwnsLock()); assert(!OwnsLock());
DynamicObject::Ptr self = GetSelf();
/* Add this new object to the list of modified objects. /* Add this new object to the list of modified objects.
* We're doing this here because we can't construct * We're doing this here because we can't construct
* a while WeakPtr from within the object's constructor. */ * a while WeakPtr from within the object's constructor. */
{ {
boost::mutex::scoped_lock lock(m_TransactionMutex); boost::mutex::scoped_lock lock(m_TransactionMutex);
m_ModifiedObjects.insert(self); m_ModifiedObjects.insert(GetSelf());
} }
{ DynamicType::Ptr dtype = GetType();
DynamicType::Ptr dtype = GetType(); dtype->RegisterObject(GetSelf());
ObjectLock olock(dtype);
DynamicObject::Ptr dobj = dtype->GetObject(GetName());
assert(!dobj || dobj == self);
if (!dobj)
dtype->RegisterObject(self);
}
} }
void DynamicObject::OnRegistrationCompleted(void) void DynamicObject::OnRegistrationCompleted(void)
{ {
assert(!OwnsLock()); assert(!OwnsLock());
DynamicObject::Ptr object;
{ {
ObjectLock olock(this); ObjectLock olock(this);
m_Registered = true; m_Registered = true;
Start();
object = GetSelf();
} }
OnRegistered(object); Start();
OnRegistered(GetSelf());
} }
void DynamicObject::OnUnregistrationCompleted(void) void DynamicObject::OnUnregistrationCompleted(void)
@ -423,7 +416,7 @@ void DynamicObject::OnUnregistrationCompleted(void)
void DynamicObject::Start(void) void DynamicObject::Start(void)
{ {
assert(OwnsLock()); assert(!OwnsLock());
/* Nothing to do here. */ /* Nothing to do here. */
} }
@ -432,17 +425,12 @@ void DynamicObject::Unregister(void)
{ {
assert(!OwnsLock()); assert(!OwnsLock());
DynamicObject::Ptr self = GetSelf();
DynamicType::Ptr dtype = GetType(); DynamicType::Ptr dtype = GetType();
if (!dtype) if (!dtype)
return; return;
{ dtype->UnregisterObject(GetSelf());
ObjectLock olock(dtype);
dtype->UnregisterObject(self);
}
} }
ScriptTask::Ptr DynamicObject::MakeMethodTask(const String& method, ScriptTask::Ptr DynamicObject::MakeMethodTask(const String& method,
@ -450,10 +438,7 @@ ScriptTask::Ptr DynamicObject::MakeMethodTask(const String& method,
{ {
Dictionary::Ptr methods; Dictionary::Ptr methods;
{ methods = m_Methods;
ObjectLock olock(this);
methods = m_Methods;
}
String funcName = methods->Get(method); String funcName = methods->Get(method);
@ -488,8 +473,6 @@ void DynamicObject::DumpObjects(const String& filename)
BOOST_FOREACH(const DynamicType::Ptr& type, DynamicType::GetTypes()) { BOOST_FOREACH(const DynamicType::Ptr& type, DynamicType::GetTypes()) {
BOOST_FOREACH(const DynamicObject::Ptr& object, type->GetObjects()) { BOOST_FOREACH(const DynamicObject::Ptr& object, type->GetObjects()) {
ObjectLock olock(object);
if (object->IsLocal()) if (object->IsLocal())
continue; continue;
@ -566,7 +549,7 @@ void DynamicObject::RestoreObjects(const String& filename)
DynamicObject::Ptr object = dt->GetObject(name); DynamicObject::Ptr object = dt->GetObject(name);
if (hasConfig && !object) { if (hasConfig && !object) {
object = DynamicType::CreateObject(dt, update); object = dt->DynamicType::CreateObject(update);
object->Register(); object->Register();
} else if (object) { } else if (object) {
object->ApplyUpdate(update, Attribute_All); object->ApplyUpdate(update, Attribute_All);
@ -633,22 +616,22 @@ void DynamicObject::NewTx(void)
if (!object || !object->IsRegistered()) if (!object || !object->IsRegistered())
continue; continue;
map<String, Value, string_iless> attrs; set<String, string_iless> attrs;
{ {
ObjectLock olock(object); ObjectLock olock(object);
attrs.swap(object->m_ModifiedAttributes); attrs.swap(object->m_ModifiedAttributes);
} }
map<String, Value, string_iless>::iterator it; BOOST_FOREACH(const String& attr, attrs) {
for (it = attrs.begin(); it != attrs.end(); it++) object->OnAttributeChanged(attr);
object->OnAttributeChanged(it->first, it->second); }
} }
OnTransactionClosing(tx, objects); OnTransactionClosing(tx, objects);
} }
void DynamicObject::OnAttributeChanged(const String&, const Value&) void DynamicObject::OnAttributeChanged(const String&)
{ {
assert(!OwnsLock()); assert(!OwnsLock());
} }

View File

@ -23,170 +23,6 @@
namespace icinga namespace icinga
{ {
/**
* The type of an attribute for a DynamicObject.
*
* @ingroup base
*/
enum AttributeType
{
Attribute_Transient = 1,
/* Unlike transient attributes local attributes are persisted
* in the program state file. */
Attribute_Local = 2,
/* Replicated attributes are sent to other daemons for which
* replication is enabled. */
Attribute_Replicated = 4,
/* Attributes read from the config file are implicitly marked
* as config attributes. */
Attribute_Config = 8,
/* Combination of all attribute types */
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);
return *this;
}
T Get(void) const
{
if (IsEmpty())
return T();
return InternalGet();
}
operator T(void) const
{
return Get();
}
};
/**
* An attribute for a DynamicObject.
*
* @ingroup base
*/
struct AttributeHolder
{
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; class DynamicType;
/** /**
@ -219,8 +55,6 @@ public:
void Touch(const String& name); void Touch(const String& name);
Value Get(const String& name) const; Value Get(const String& name) const;
bool HasAttribute(const String& name) const;
void BindAttribute(const String& name, Value *boundValue); void BindAttribute(const String& name, Value *boundValue);
void ClearAttributesByType(AttributeType type); void ClearAttributesByType(AttributeType type);
@ -264,15 +98,16 @@ protected:
virtual void OnRegistrationCompleted(void); virtual void OnRegistrationCompleted(void);
virtual void OnUnregistrationCompleted(void); virtual void OnUnregistrationCompleted(void);
virtual void OnAttributeChanged(const String& name, const Value& oldValue); virtual void OnAttributeChanged(const String& name);
private: private:
void InternalSetAttribute(const String& name, const Value& data, double tx, bool allowEditConfig = false); void InternalSetAttribute(const String& name, const Value& data, double tx, bool allowEditConfig = false);
Value InternalGetAttribute(const String& name) const; Value InternalGetAttribute(const String& name) const;
void SendLocalUpdateEvents(void); void InternalRegisterAttribute(const String& name, AttributeType type, AttributeBase *boundAttribute = NULL);
mutable boost::mutex m_AttributeMutex;
AttributeMap m_Attributes; AttributeMap m_Attributes;
map<String, Value, string_iless> m_ModifiedAttributes; set<String, string_iless> m_ModifiedAttributes;
double m_ConfigTx; double m_ConfigTx;
Attribute<String> m_Name; Attribute<String> m_Name;

View File

@ -76,8 +76,6 @@ set<DynamicObject::Ptr> DynamicType::GetObjects(void) const
String DynamicType::GetName(void) const String DynamicType::GetName(void) const
{ {
ObjectLock olock(this);
return m_Name; return m_Name;
} }
@ -85,7 +83,8 @@ void DynamicType::RegisterObject(const DynamicObject::Ptr& object)
{ {
String name = object->GetName(); String name = object->GetName();
assert(OwnsLock()); ObjectLock olock(this);
ObjectMap::iterator it = m_ObjectMap.find(name); ObjectMap::iterator it = m_ObjectMap.find(name);
if (it != m_ObjectMap.end()) { if (it != m_ObjectMap.end()) {
@ -103,7 +102,8 @@ void DynamicType::RegisterObject(const DynamicObject::Ptr& object)
void DynamicType::UnregisterObject(const DynamicObject::Ptr& object) void DynamicType::UnregisterObject(const DynamicObject::Ptr& object)
{ {
assert(OwnsLock()); ObjectLock olock(this);
m_ObjectMap.erase(object->GetName()); m_ObjectMap.erase(object->GetName());
m_ObjectSet.erase(object); m_ObjectSet.erase(object);
@ -142,23 +142,21 @@ void DynamicType::RegisterType(const DynamicType::Ptr& type)
InternalGetTypeSet().insert(type); InternalGetTypeSet().insert(type);
} }
DynamicObject::Ptr DynamicType::CreateObject(const DynamicType::Ptr& self, const Dictionary::Ptr& serializedUpdate) DynamicObject::Ptr DynamicType::CreateObject(const Dictionary::Ptr& serializedUpdate)
{ {
assert(!OwnsLock());
ObjectFactory factory; ObjectFactory factory;
{ {
ObjectLock olock(self); ObjectLock olock(this);
factory = self->m_ObjectFactory; factory = m_ObjectFactory;
} }
DynamicObject::Ptr object = factory(serializedUpdate); DynamicObject::Ptr object = factory(serializedUpdate);
{ /* apply the object's non-config attributes */
ObjectLock olock(object); object->ApplyUpdate(serializedUpdate, Attribute_All & ~Attribute_Config);
/* apply the object's non-config attributes */
object->ApplyUpdate(serializedUpdate, Attribute_All & ~Attribute_Config);
}
return object; return object;
} }

View File

@ -39,7 +39,7 @@ public:
static void RegisterType(const DynamicType::Ptr& type); static void RegisterType(const DynamicType::Ptr& type);
static DynamicObject::Ptr CreateObject(const DynamicType::Ptr& self, const Dictionary::Ptr& serializedUpdate); DynamicObject::Ptr CreateObject(const Dictionary::Ptr& serializedUpdate);
DynamicObject::Ptr GetObject(const String& name) const; DynamicObject::Ptr GetObject(const String& name) const;
void RegisterObject(const DynamicObject::Ptr& object); void RegisterObject(const DynamicObject::Ptr& object);

View File

@ -214,6 +214,7 @@ namespace signals2 = boost::signals2;
#include "process.h" #include "process.h"
#include "scriptfunction.h" #include "scriptfunction.h"
#include "scripttask.h" #include "scripttask.h"
#include "attribute.h"
#include "dynamicobject.h" #include "dynamicobject.h"
#include "dynamictype.h" #include "dynamictype.h"
#include "script.h" #include "script.h"

View File

@ -29,7 +29,9 @@ boost::mutex Object::m_DebugMutex;
* Default constructor for the Object class. * Default constructor for the Object class.
*/ */
Object::Object(void) Object::Object(void)
: m_LockCount(0) #ifdef _DEBUG
: m_Locked(false)
#endif /* _DEBUG */
{ } { }
/** /**
@ -46,15 +48,12 @@ Object::~Object(void)
*/ */
Object::SharedPtrHolder Object::GetSelf(void) Object::SharedPtrHolder Object::GetSelf(void)
{ {
ObjectLock olock(this);
return Object::SharedPtrHolder(shared_from_this()); return Object::SharedPtrHolder(shared_from_this());
} }
#ifdef _DEBUG #ifdef _DEBUG
/** /**
* Checks if the calling thread owns the lock on this object or is currently * Checks if the calling thread owns the lock on this object.
* in the constructor or destructor and therefore implicitly owns the lock.
* *
* @returns True if the calling thread owns the lock, false otherwise. * @returns True if the calling thread owns the lock, false otherwise.
*/ */
@ -62,18 +61,6 @@ bool Object::OwnsLock(void) const
{ {
boost::mutex::scoped_lock lock(m_DebugMutex); boost::mutex::scoped_lock lock(m_DebugMutex);
if (m_LockCount == 0 || m_LockOwner != boost::this_thread::get_id()) { return (m_Locked && m_LockOwner == boost::this_thread::get_id());
try {
shared_from_this();
} catch (const boost::bad_weak_ptr& ex) {
/* There's no shared_ptr to this object. Either someone created the object
* directly (e.g. on the stack) or we're in the constructor or destructor. Not holding the lock is ok here. */
return true;
}
return false;
}
return true;
} }
#endif /* _DEBUG */ #endif /* _DEBUG */

View File

@ -91,8 +91,9 @@ public:
holder instance */ holder instance */
}; };
void VerifyLocked(void) const; #ifdef _DEBUG
void WarnIfLocked(void) const; bool OwnsLock(void) const;
#endif /* _DEBUG */
protected: protected:
Object(void); Object(void);
@ -100,22 +101,22 @@ protected:
SharedPtrHolder GetSelf(void); SharedPtrHolder GetSelf(void);
#ifdef _DEBUG
bool OwnsLock(void) const;
#endif /* _DEBUG */
private: private:
Object(const Object& other); Object(const Object& other);
Object& operator=(const Object& rhs); Object& operator=(const Object& rhs);
mutable recursive_mutex m_Mutex; #ifndef _DEBUG
mutable unsigned int m_LockCount; typedef boost::mutex MutexType;
mutable boost::thread::id m_LockOwner; #else /* _DEBUG */
typedef boost::recursive_mutex MutexType;
#ifdef _DEBUG
static boost::mutex m_DebugMutex; static boost::mutex m_DebugMutex;
mutable bool m_Locked;
mutable boost::thread::id m_LockOwner;
#endif /* _DEBUG */ #endif /* _DEBUG */
mutable MutexType m_Mutex;
friend class ObjectLock; friend class ObjectLock;
}; };

View File

@ -21,14 +21,6 @@
using namespace icinga; using namespace icinga;
#ifdef _DEBUG
# ifdef _MSC_VER
static __declspec(thread) int g_LockCount;
# else /* _MSC_VER */
static __thread int g_LockCount;
# endif /* _MSC_VER */
#endif /* _DEBUG */
ObjectLock::ObjectLock(void) ObjectLock::ObjectLock(void)
: m_Object(NULL), m_Lock() : m_Object(NULL), m_Lock()
{ } { }
@ -55,19 +47,16 @@ ObjectLock::ObjectLock(const Object *object)
void ObjectLock::Lock(void) void ObjectLock::Lock(void)
{ {
assert(!m_Lock.owns_lock() && m_Object != NULL); assert(!m_Lock.owns_lock() && m_Object != NULL);
assert(!m_Object->OwnsLock());
m_Lock = recursive_mutex::scoped_lock(m_Object->m_Mutex); m_Lock = Object::MutexType::scoped_lock(m_Object->m_Mutex);
#ifdef _DEBUG #ifdef _DEBUG
{ {
boost::mutex::scoped_lock lock(Object::m_DebugMutex); boost::mutex::scoped_lock lock(Object::m_DebugMutex);
m_Object->m_LockCount++; m_Object->m_Locked = true;
m_Object->m_LockOwner = boost::this_thread::get_id(); m_Object->m_LockOwner = boost::this_thread::get_id();
m_TS = Utility::GetTime();
if (m_Object->m_LockCount == 1) {
g_LockCount++;
m_TS = Utility::GetTime();
}
} }
#endif /* _DEBUG */ #endif /* _DEBUG */
} }
@ -79,21 +68,17 @@ void ObjectLock::Unlock(void)
boost::mutex::scoped_lock lock(Object::m_DebugMutex); boost::mutex::scoped_lock lock(Object::m_DebugMutex);
if (m_Lock.owns_lock()) { if (m_Lock.owns_lock()) {
if (m_Object->m_LockCount == 1) { double dt = Utility::GetTime() - m_TS;
g_LockCount--;
double dt = Utility::GetTime() - m_TS; if (dt > 0.05) {
std::cerr << "Held object lock for " << dt << " seconds at:";
if (dt > 0.05) { Utility::PrintStacktrace(std::cerr);
std::cerr << "Held object lock for " << dt << " seconds at:";
Utility::PrintStacktrace(std::cerr);
}
} }
m_Object->m_LockCount--; m_Object->m_Locked = false;
} }
} }
#endif /* _DEBUG */ #endif /* _DEBUG */
m_Lock = recursive_mutex::scoped_lock(); m_Lock = Object::MutexType::scoped_lock();
} }

View File

@ -38,7 +38,8 @@ public:
private: private:
const Object *m_Object; const Object *m_Object;
recursive_mutex::scoped_lock m_Lock; Object::MutexType::scoped_lock m_Lock;
#ifdef _DEBUG #ifdef _DEBUG
double m_TS; double m_TS;
#endif /* _DEBUG */ #endif /* _DEBUG */

View File

@ -68,7 +68,7 @@ String Script::GetCode(void) const
/** /**
* @threadsafety Always. * @threadsafety Always.
*/ */
void Script::OnAttributeUpdate(const String& name, const Value& oldValue) void Script::OnAttributeUpdate(const String& name)
{ {
assert(!OwnsLock()); assert(!OwnsLock());

View File

@ -44,7 +44,7 @@ public:
String GetCode(void) const; String GetCode(void) const;
protected: protected:
virtual void OnAttributeUpdate(const String& name, const Value& oldValue); virtual void OnAttributeUpdate(const String& name);
private: private:
Attribute<String> m_Language; Attribute<String> m_Language;

View File

@ -48,8 +48,6 @@ StdioStream::~StdioStream(void)
*/ */
void StdioStream::Start(void) void StdioStream::Start(void)
{ {
ObjectLock olock(this);
SetConnected(true); SetConnected(true);
Stream::Start(); Stream::Start();
@ -120,8 +118,6 @@ void StdioStream::Write(const void *buffer, size_t size)
*/ */
void StdioStream::Close(void) void StdioStream::Close(void)
{ {
ObjectLock olock(this);
if (m_OwnsStream) if (m_OwnsStream)
delete m_InnerStream; delete m_InnerStream;

View File

@ -103,10 +103,12 @@ void Stream::Start(void)
*/ */
void Stream::Close(void) void Stream::Close(void)
{ {
ObjectLock olock(this); {
ObjectLock olock(this);
assert(m_Running); assert(m_Running);
m_Running = false; m_Running = false;
}
SetConnected(false); SetConnected(false);
} }

View File

@ -86,12 +86,16 @@ void Timer::Uninitialize(void)
* *
* @threadsafety Always. * @threadsafety Always.
*/ */
void Timer::Call(const Timer::Ptr& self) void Timer::Call(void)
{ {
self->OnTimerExpired(self); assert(!OwnsLock());
Timer::Ptr self = GetSelf();
OnTimerExpired(self);
/* Re-enable the timer so it can be called again. */ /* Re-enable the timer so it can be called again. */
self->Start(); Start();
} }
/** /**

View File

@ -86,7 +86,7 @@ private:
static bool m_StopThread; static bool m_StopThread;
static TimerSet m_Timers; static TimerSet m_Timers;
static void Call(const Timer::Ptr& self); void Call();
static void TimerThreadProc(void); static void TimerThreadProc(void);

View File

@ -114,7 +114,6 @@ void ConfigCompilerContext::Validate(void)
ConfigType::Ptr ctype; ConfigType::Ptr ctype;
{ {
ObjectLock olock(item);
ctype = GetType(item->GetType()); ctype = GetType(item->GetType());
if (!ctype) { if (!ctype) {
@ -124,7 +123,6 @@ void ConfigCompilerContext::Validate(void)
} }
} }
ObjectLock olock(ctype);
ctype->ValidateItem(item); ctype->ValidateItem(item);
} }

View File

@ -50,8 +50,6 @@ ConfigItem::ConfigItem(const String& type, const String& name,
*/ */
String ConfigItem::GetType(void) const String ConfigItem::GetType(void) const
{ {
ObjectLock olock(this);
return m_Type; return m_Type;
} }
@ -62,8 +60,6 @@ String ConfigItem::GetType(void) const
*/ */
String ConfigItem::GetName(void) const String ConfigItem::GetName(void) const
{ {
ObjectLock olock(this);
return m_Name; return m_Name;
} }
@ -74,8 +70,6 @@ String ConfigItem::GetName(void) const
*/ */
String ConfigItem::GetUnit(void) const String ConfigItem::GetUnit(void) const
{ {
ObjectLock olock(this);
return m_Unit; return m_Unit;
} }
@ -86,8 +80,6 @@ String ConfigItem::GetUnit(void) const
*/ */
DebugInfo ConfigItem::GetDebugInfo(void) const DebugInfo ConfigItem::GetDebugInfo(void) const
{ {
ObjectLock olock(this);
return m_DebugInfo; return m_DebugInfo;
} }
@ -98,8 +90,6 @@ DebugInfo ConfigItem::GetDebugInfo(void) const
*/ */
ExpressionList::Ptr ConfigItem::GetExpressionList(void) const ExpressionList::Ptr ConfigItem::GetExpressionList(void) const
{ {
ObjectLock olock(this);
return m_ExpressionList; return m_ExpressionList;
} }
@ -110,18 +100,9 @@ ExpressionList::Ptr ConfigItem::GetExpressionList(void) const
*/ */
vector<String> ConfigItem::GetParents(void) const vector<String> ConfigItem::GetParents(void) const
{ {
ObjectLock olock(this);
return m_Parents; return m_Parents;
} }
set<ConfigItem::WeakPtr> ConfigItem::GetChildren(void) const
{
ObjectLock olock(this);
return m_ChildObjects;
}
Dictionary::Ptr ConfigItem::Link(void) const Dictionary::Ptr ConfigItem::Link(void) const
{ {
Dictionary::Ptr attrs = boost::make_shared<Dictionary>(); Dictionary::Ptr attrs = boost::make_shared<Dictionary>();
@ -146,12 +127,12 @@ void ConfigItem::InternalLink(const Dictionary::Ptr& dictionary) const
ConfigCompilerContext *context = ConfigCompilerContext::GetContext(); ConfigCompilerContext *context = ConfigCompilerContext::GetContext();
if (context) if (context)
parent = context->GetItem(GetType(), name); parent = context->GetItem(m_Type, name);
/* ignore already active objects while we're in the compiler /* ignore already active objects while we're in the compiler
* context and linking to existing items is disabled. */ * context and linking to existing items is disabled. */
if (!parent && (!context || (context->GetFlags() & CompilerLinkExisting))) if (!parent && (!context || (context->GetFlags() & CompilerLinkExisting)))
parent = ConfigItem::GetObject(GetType(), name); parent = ConfigItem::GetObject(m_Type, name);
if (!parent) { if (!parent) {
stringstream message; stringstream message;
@ -160,7 +141,6 @@ void ConfigItem::InternalLink(const Dictionary::Ptr& dictionary) const
BOOST_THROW_EXCEPTION(domain_error(message.str())); BOOST_THROW_EXCEPTION(domain_error(message.str()));
} }
ObjectLock olock(parent);
parent->InternalLink(dictionary); parent->InternalLink(dictionary);
} }
@ -209,7 +189,7 @@ DynamicObject::Ptr ConfigItem::Commit(void)
oldItem->UnregisterFromParents(); oldItem->UnregisterFromParents();
/* Steal the old item's children. */ /* Steal the old item's children. */
children = oldItem->GetChildren(); children = oldItem->m_ChildObjects;
} }
{ {
@ -226,15 +206,15 @@ DynamicObject::Ptr ConfigItem::Commit(void)
m_Items[ikey] = self; m_Items[ikey] = self;
} }
DynamicObject::Ptr dobj = GetDynamicObject(); DynamicObject::Ptr dobj = m_DynamicObject.lock();
if (!dobj) if (!dobj)
dobj = dtype->GetObject(GetName()); dobj = dtype->GetObject(m_Name);
/* Register this item with its parents. */ /* Register this item with its parents. */
BOOST_FOREACH(const String& parentName, GetParents()) { BOOST_FOREACH(const String& parentName, m_Parents) {
ConfigItem::Ptr parent = GetObject(GetType(), parentName); ConfigItem::Ptr parent = GetObject(m_Type, parentName);
parent->RegisterChild(self); parent->m_ChildObjects.insert(self);
} }
/* Create a fake update in the format that /* Create a fake update in the format that
@ -272,7 +252,7 @@ DynamicObject::Ptr ConfigItem::Commit(void)
bool was_null = false; bool was_null = false;
if (!dobj) { if (!dobj) {
dobj = DynamicType::CreateObject(dtype, update); dobj = dtype->CreateObject(update);
was_null = true; was_null = true;
} }
@ -300,7 +280,7 @@ DynamicObject::Ptr ConfigItem::Commit(void)
child->OnParentCommitted(); child->OnParentCommitted();
} }
OnCommitted(GetSelf()); OnCommitted(self);
return dobj; return dobj;
} }
@ -312,7 +292,7 @@ void ConfigItem::Unregister(void)
{ {
assert(!OwnsLock()); assert(!OwnsLock());
DynamicObject::Ptr dobj = GetDynamicObject(); DynamicObject::Ptr dobj = m_DynamicObject.lock();
if (dobj) if (dobj)
dobj->Unregister(); dobj->Unregister();
@ -321,40 +301,26 @@ void ConfigItem::Unregister(void)
ObjectLock olock(this); ObjectLock olock(this);
ConfigItem::ItemMap::iterator it; ConfigItem::ItemMap::iterator it;
it = m_Items.find(make_pair(GetType(), GetName())); it = m_Items.find(make_pair(m_Type, m_Name));
if (it != m_Items.end()) if (it != m_Items.end())
m_Items.erase(it); m_Items.erase(it);
}
UnregisterFromParents(); UnregisterFromParents();
}
OnRemoved(GetSelf()); OnRemoved(GetSelf());
} }
void ConfigItem::RegisterChild(const ConfigItem::Ptr& child)
{
ObjectLock olock(this);
m_ChildObjects.insert(child);
}
void ConfigItem::UnregisterChild(const ConfigItem::Ptr& child)
{
ObjectLock olock(this);
m_ChildObjects.erase(child);
}
void ConfigItem::UnregisterFromParents(void) void ConfigItem::UnregisterFromParents(void)
{ {
ObjectLock olock(this); assert(OwnsLock());
BOOST_FOREACH(const String& parentName, m_Parents) { BOOST_FOREACH(const String& parentName, m_Parents) {
ConfigItem::Ptr parent = GetObject(GetType(), parentName); ConfigItem::Ptr parent = GetObject(GetType(), parentName);
if (parent) if (parent)
parent->UnregisterChild(GetSelf()); parent->m_ChildObjects.erase(GetSelf());
} }
} }
@ -365,15 +331,10 @@ void ConfigItem::OnParentCommitted(void)
{ {
assert(!OwnsLock()); assert(!OwnsLock());
ConfigItem::Ptr self; ConfigItem::Ptr self = GetSelf();
{ if (GetObject(m_Type, m_Name) != self)
ObjectLock olock(this); return;
self = GetSelf();
if (GetObject(self->GetType(), self->GetName()) != self)
return;
}
Commit(); Commit();
} }
@ -458,7 +419,7 @@ void ConfigItem::UnloadUnit(const String& unit)
BOOST_FOREACH(tie(tuples::ignore, item), m_Items) { BOOST_FOREACH(tie(tuples::ignore, item), m_Items) {
ObjectLock olock(item); ObjectLock olock(item);
if (item->GetUnit() != unit) if (item->m_Unit != unit)
continue; continue;
obsoleteItems.push_back(item); obsoleteItems.push_back(item);

View File

@ -43,7 +43,6 @@ public:
String GetUnit(void) const; String GetUnit(void) const;
vector<String> GetParents(void) const; vector<String> GetParents(void) const;
set<ConfigItem::WeakPtr> GetChildren(void) const;
ExpressionList::Ptr GetExpressionList(void) const; ExpressionList::Ptr GetExpressionList(void) const;
@ -69,8 +68,6 @@ public:
private: private:
void InternalLink(const Dictionary::Ptr& dictionary) const; void InternalLink(const Dictionary::Ptr& dictionary) const;
void RegisterChild(const ConfigItem::Ptr& child);
void UnregisterChild(const ConfigItem::Ptr& child);
void UnregisterFromParents(void); void UnregisterFromParents(void);
void OnParentCommitted(void); void OnParentCommitted(void);

View File

@ -52,24 +52,14 @@ DebugInfo ConfigType::GetDebugInfo(void) const
void ConfigType::ValidateItem(const ConfigItem::Ptr& item) const void ConfigType::ValidateItem(const ConfigItem::Ptr& item) const
{ {
String type, name; Dictionary::Ptr attrs = item->Link();
Dictionary::Ptr attrs;
{
ObjectLock olock(item);
attrs = item->Link();
type = item->GetType();
name = item->GetName();
}
ObjectLock olock(attrs);
/* Don't validate abstract items. */ /* Don't validate abstract items. */
if (attrs->Get("__abstract")) if (attrs->Get("__abstract"))
return; return;
vector<String> locations; vector<String> locations;
locations.push_back("Object '" + name + "' (Type: '" + type + "')"); locations.push_back("Object '" + item->GetName() + "' (Type: '" + item->GetType() + "')");
ConfigType::Ptr parent; ConfigType::Ptr parent;
if (m_Parent.IsEmpty()) { if (m_Parent.IsEmpty()) {

View File

@ -54,7 +54,6 @@ void Expression::Execute(const Dictionary::Ptr& dictionary) const
case OperatorSet: case OperatorSet:
if (valueExprl) { if (valueExprl) {
ObjectLock olock(valueExprl);
dict = boost::make_shared<Dictionary>(); dict = boost::make_shared<Dictionary>();
valueExprl->Execute(dict); valueExprl->Execute(dict);
newValue = dict; newValue = dict;
@ -63,10 +62,7 @@ void Expression::Execute(const Dictionary::Ptr& dictionary) const
break; break;
case OperatorPlus: case OperatorPlus:
{ oldValue = dictionary->Get(m_Key);
ObjectLock olock(dictionary);
oldValue = dictionary->Get(m_Key);
}
if (oldValue.IsObjectType<Dictionary>()) if (oldValue.IsObjectType<Dictionary>())
dict = oldValue; dict = oldValue;
@ -87,12 +83,9 @@ void Expression::Execute(const Dictionary::Ptr& dictionary) const
newValue = dict; newValue = dict;
if (valueExprl) { if (valueExprl) {
ObjectLock olock(valueExprl);
valueExprl->Execute(dict); valueExprl->Execute(dict);
} else if (valueDict) { } else if (valueDict) {
ObjectLock olock(valueDict); ObjectLock olock(valueDict);
ObjectLock dlock(dict);
String key; String key;
Value value; Value value;
@ -112,7 +105,6 @@ void Expression::Execute(const Dictionary::Ptr& dictionary) const
BOOST_THROW_EXCEPTION(runtime_error("Not yet implemented.")); BOOST_THROW_EXCEPTION(runtime_error("Not yet implemented."));
} }
ObjectLock olock(dictionary);
if (m_Key.IsEmpty()) if (m_Key.IsEmpty())
dictionary->Add(newValue); dictionary->Add(newValue);
else else

View File

@ -65,8 +65,6 @@ void Host::OnRegistrationCompleted(void)
String Host::GetDisplayName(void) const String Host::GetDisplayName(void) const
{ {
ObjectLock olock(this);
if (!m_DisplayName.IsEmpty()) if (!m_DisplayName.IsEmpty())
return m_DisplayName; return m_DisplayName;
else else
@ -85,36 +83,26 @@ Host::Ptr Host::GetByName(const String& name)
Dictionary::Ptr Host::GetGroups(void) const Dictionary::Ptr Host::GetGroups(void) const
{ {
ObjectLock olock(this);
return m_HostGroups;; return m_HostGroups;;
} }
Dictionary::Ptr Host::GetMacros(void) const Dictionary::Ptr Host::GetMacros(void) const
{ {
ObjectLock olock(this);
return m_Macros; return m_Macros;
} }
Dictionary::Ptr Host::GetHostDependencies(void) const Dictionary::Ptr Host::GetHostDependencies(void) const
{ {
ObjectLock olock(this);
return m_HostDependencies;; return m_HostDependencies;;
} }
Dictionary::Ptr Host::GetServiceDependencies(void) const Dictionary::Ptr Host::GetServiceDependencies(void) const
{ {
ObjectLock olock(this);
return m_ServiceDependencies; return m_ServiceDependencies;
} }
String Host::GetHostCheck(void) const String Host::GetHostCheck(void) const
{ {
ObjectLock olock(this);
return m_HostCheck; return m_HostCheck;
} }
@ -154,6 +142,10 @@ bool Host::IsReachable(void) const
ObjectLock olock(hc); ObjectLock olock(hc);
/* ignore soft states */
if (hc->GetStateType() == StateTypeSoft)
continue;
/* ignore hosts that are up */ /* ignore hosts that are up */
if (hc->GetState() == StateOK) if (hc->GetState() == StateOK)
continue; continue;
@ -167,8 +159,6 @@ bool Host::IsReachable(void) const
template<bool copyServiceAttrs, typename TDict> template<bool copyServiceAttrs, typename TDict>
static void CopyServiceAttributes(TDict serviceDesc, const ConfigItemBuilder::Ptr& builder) static void CopyServiceAttributes(TDict serviceDesc, const ConfigItemBuilder::Ptr& builder)
{ {
ObjectLock olock(serviceDesc);
/* TODO: we only need to copy macros if this is an inline definition, /* TODO: we only need to copy macros if this is an inline definition,
* i.e. "typeid(serviceDesc)" != Service, however for now we just * i.e. "typeid(serviceDesc)" != Service, however for now we just
* copy them anyway. */ * copy them anyway. */
@ -253,12 +243,7 @@ void Host::UpdateSlaveServices(void)
} else if (svcdesc.IsObjectType<Dictionary>()) { } else if (svcdesc.IsObjectType<Dictionary>()) {
Dictionary::Ptr service = svcdesc; Dictionary::Ptr service = svcdesc;
Dictionary::Ptr templates; Dictionary::Ptr templates = service->Get("templates");
{
ObjectLock olock(service);
templates = service->Get("templates");
}
if (templates) { if (templates) {
ObjectLock olock(templates); ObjectLock olock(templates);
@ -298,11 +283,10 @@ void Host::UpdateSlaveServices(void)
newServices->Seal(); newServices->Seal();
ObjectLock olock(this);
Set("slave_services", newServices); Set("slave_services", newServices);
} }
void Host::OnAttributeChanged(const String& name, const Value&) void Host::OnAttributeChanged(const String& name)
{ {
assert(!OwnsLock()); assert(!OwnsLock());
@ -311,15 +295,8 @@ void Host::OnAttributeChanged(const String& name, const Value&)
else if (name == "services") { else if (name == "services") {
UpdateSlaveServices(); UpdateSlaveServices();
} else if (name == "notifications") { } else if (name == "notifications") {
set<Service::Ptr> services; BOOST_FOREACH(const Service::Ptr& service, GetServices()) {
service->UpdateSlaveNotifications();
{
ObjectLock olock(this);
services = GetServices();
}
BOOST_FOREACH(const Service::Ptr& service, services) {
Service::UpdateSlaveNotifications(service);
} }
} }
} }
@ -371,28 +348,14 @@ void Host::RefreshServicesCache(void)
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) { BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) {
const Service::Ptr& service = static_pointer_cast<Service>(object); const Service::Ptr& service = static_pointer_cast<Service>(object);
Host::Ptr host; Host::Ptr host = service->GetHost();
String short_name;
{
ObjectLock olock(service);
host = service->GetHost();
short_name = service->GetShortName();
}
if (!host) if (!host)
continue; continue;
String host_name;
{
ObjectLock olock(host);
host_name = host->GetName();
}
// TODO: assert for duplicate short_names // TODO: assert for duplicate short_names
newServicesCache[host_name][short_name] = service; newServicesCache[host->GetName()][service->GetShortName()] = service;
} }
boost::mutex::scoped_lock lock(m_ServiceMutex); boost::mutex::scoped_lock lock(m_ServiceMutex);
@ -538,15 +501,10 @@ Dictionary::Ptr Host::CalculateDynamicMacros(void) const
assert(!OwnsLock()); assert(!OwnsLock());
Dictionary::Ptr macros = boost::make_shared<Dictionary>(); Dictionary::Ptr macros = boost::make_shared<Dictionary>();
ObjectLock mlock(macros);
{ macros->Set("HOSTNAME", GetName());
ObjectLock olock(this); macros->Set("HOSTDISPLAYNAME", GetDisplayName());
macros->Set("HOSTALIAS", GetName());
macros->Set("HOSTNAME", GetName());
macros->Set("HOSTDISPLAYNAME", GetDisplayName());
macros->Set("HOSTALIAS", GetName());
}
Dictionary::Ptr cr; Dictionary::Ptr cr;
@ -588,8 +546,6 @@ Dictionary::Ptr Host::CalculateDynamicMacros(void) const
macros->Set("HOSTLATENCY", Service::CalculateLatency(cr)); macros->Set("HOSTLATENCY", Service::CalculateLatency(cr));
macros->Set("HOSTEXECUTIONTIME", Service::CalculateExecutionTime(cr)); macros->Set("HOSTEXECUTIONTIME", Service::CalculateExecutionTime(cr));
ObjectLock olock(cr);
macros->Set("HOSTOUTPUT", cr->Get("output")); macros->Set("HOSTOUTPUT", cr->Get("output"));
macros->Set("HOSTPERFDATA", cr->Get("performance_data_raw")); macros->Set("HOSTPERFDATA", cr->Get("performance_data_raw"));
} }

View File

@ -67,7 +67,7 @@ public:
protected: protected:
virtual void OnRegistrationCompleted(void); virtual void OnRegistrationCompleted(void);
virtual void OnAttributeChanged(const String& name, const Value& oldValue); virtual void OnAttributeChanged(const String& name);
private: private:
Attribute<String> m_DisplayName; Attribute<String> m_DisplayName;

View File

@ -55,8 +55,6 @@ void HostGroup::OnRegistrationCompleted(void)
*/ */
String HostGroup::GetDisplayName(void) const String HostGroup::GetDisplayName(void) const
{ {
ObjectLock olock(this);
if (!m_DisplayName.IsEmpty()) if (!m_DisplayName.IsEmpty())
return m_DisplayName; return m_DisplayName;
else else
@ -68,8 +66,6 @@ String HostGroup::GetDisplayName(void) const
*/ */
String HostGroup::GetNotesUrl(void) const String HostGroup::GetNotesUrl(void) const
{ {
ObjectLock olock(this);
return m_NotesUrl; return m_NotesUrl;
} }
@ -78,8 +74,6 @@ String HostGroup::GetNotesUrl(void) const
*/ */
String HostGroup::GetActionUrl(void) const String HostGroup::GetActionUrl(void) const
{ {
ObjectLock olock(this);
return m_ActionUrl; return m_ActionUrl;
} }
@ -150,7 +144,6 @@ void HostGroup::RefreshMembersCache(void)
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Host")) { BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Host")) {
const Host::Ptr& host = static_pointer_cast<Host>(object); const Host::Ptr& host = static_pointer_cast<Host>(object);
ObjectLock olock(host);
Dictionary::Ptr dict; Dictionary::Ptr dict;
dict = host->GetGroups(); dict = host->GetGroups();

View File

@ -215,7 +215,6 @@ shared_ptr<SSL_CTX> IcingaApplication::GetSSLContext(void) const
Dictionary::Ptr IcingaApplication::CalculateDynamicMacros(void) Dictionary::Ptr IcingaApplication::CalculateDynamicMacros(void)
{ {
Dictionary::Ptr macros = boost::make_shared<Dictionary>(); Dictionary::Ptr macros = boost::make_shared<Dictionary>();
ObjectLock mlock(macros);
double now = Utility::GetTime(); double now = Utility::GetTime();

View File

@ -56,8 +56,6 @@ Value MacroProcessor::ResolveMacros(const Value& cmd, const Dictionary::Ptr& mac
*/ */
String MacroProcessor::InternalResolveMacros(const String& str, const Dictionary::Ptr& macros) String MacroProcessor::InternalResolveMacros(const String& str, const Dictionary::Ptr& macros)
{ {
ObjectLock olock(macros);
size_t offset, pos_first, pos_second; size_t offset, pos_first, pos_second;
offset = 0; offset = 0;

View File

@ -54,8 +54,6 @@ Notification::Ptr Notification::GetByName(const String& name)
*/ */
Service::Ptr Notification::GetService(void) const Service::Ptr Notification::GetService(void) const
{ {
ObjectLock olock(this);
Host::Ptr host = Host::GetByName(m_HostName); Host::Ptr host = Host::GetByName(m_HostName);
if (!host) if (!host)
@ -72,8 +70,6 @@ Service::Ptr Notification::GetService(void) const
*/ */
Value Notification::GetNotificationCommand(void) const Value Notification::GetNotificationCommand(void) const
{ {
ObjectLock olock(this);
return m_NotificationCommand; return m_NotificationCommand;
} }
@ -82,8 +78,6 @@ Value Notification::GetNotificationCommand(void) const
*/ */
Dictionary::Ptr Notification::GetMacros(void) const Dictionary::Ptr Notification::GetMacros(void) const
{ {
ObjectLock olock(this);
return m_Macros; return m_Macros;
} }
@ -94,12 +88,7 @@ set<User::Ptr> Notification::GetUsers(void) const
{ {
set<User::Ptr> result; set<User::Ptr> result;
Dictionary::Ptr users; Dictionary::Ptr users = m_Users;
{
ObjectLock olock(this);
users = m_Users;
}
if (users) { if (users) {
ObjectLock olock(users); ObjectLock olock(users);
@ -125,12 +114,7 @@ set<UserGroup::Ptr> Notification::GetGroups(void) const
{ {
set<UserGroup::Ptr> result; set<UserGroup::Ptr> result;
Dictionary::Ptr groups; Dictionary::Ptr groups = m_Groups;
{
ObjectLock olock(this);
groups = m_Groups;
}
if (groups) { if (groups) {
ObjectLock olock(groups); ObjectLock olock(groups);
@ -221,14 +205,7 @@ void Notification::BeginExecuteNotification(NotificationType type)
} }
BOOST_FOREACH(const User::Ptr& user, allUsers) { BOOST_FOREACH(const User::Ptr& user, allUsers) {
String user_name; Logger::Write(LogDebug, "icinga", "Sending notification for user " + user->GetName());
{
ObjectLock olock(user);
user_name = user->GetName();
}
Logger::Write(LogDebug, "icinga", "Sending notification for user " + user_name);
BeginExecuteNotificationHelper(macros, type, user); BeginExecuteNotificationHelper(macros, type, user);
} }
@ -289,7 +266,11 @@ void Notification::NotificationCompletedHandler(const ScriptTask::Ptr& task)
{ {
assert(!OwnsLock()); assert(!OwnsLock());
m_Tasks.erase(task); {
ObjectLock olock(this);
m_Tasks.erase(task);
}
try { try {
task->GetResult(); task->GetResult();
@ -308,7 +289,7 @@ void Notification::NotificationCompletedHandler(const ScriptTask::Ptr& task)
/** /**
* @threadsafety Always. * @threadsafety Always.
*/ */
void Notification::OnAttributeChanged(const String& name, const Value& oldValue) void Notification::OnAttributeChanged(const String& name)
{ {
assert(!OwnsLock()); assert(!OwnsLock());

View File

@ -68,7 +68,7 @@ public:
static String NotificationTypeToString(NotificationType type); static String NotificationTypeToString(NotificationType type);
protected: protected:
void OnAttributeChanged(const String& name, const Value& oldValue); void OnAttributeChanged(const String& name);
private: private:
Attribute<Value> m_NotificationCommand; Attribute<Value> m_NotificationCommand;

View File

@ -38,12 +38,11 @@ PerfdataWriter::~PerfdataWriter(void)
/** /**
* @threadsafety Always. * @threadsafety Always.
*/ */
void PerfdataWriter::OnAttributeChanged(const String& name, const Value& oldValue) void PerfdataWriter::OnAttributeChanged(const String& name)
{ {
assert(!OwnsLock()); assert(!OwnsLock());
if (name == "rotation_interval") { if (name == "rotation_interval") {
ObjectLock olock(this);
m_RotationTimer->SetInterval(GetRotationInterval()); m_RotationTimer->SetInterval(GetRotationInterval());
} }
} }
@ -53,16 +52,9 @@ void PerfdataWriter::OnAttributeChanged(const String& name, const Value& oldValu
*/ */
void PerfdataWriter::Start(void) void PerfdataWriter::Start(void)
{ {
ObjectLock olock(this);
m_Endpoint = Endpoint::MakeEndpoint("perfdata_" + GetName(), false); m_Endpoint = Endpoint::MakeEndpoint("perfdata_" + GetName(), false);
m_Endpoint->RegisterTopicHandler("checker::CheckResult",
{ boost::bind(&PerfdataWriter::CheckResultRequestHandler, this, _3));
ObjectLock olock(m_Endpoint);
m_Endpoint->RegisterTopicHandler("checker::CheckResult",
boost::bind(&PerfdataWriter::CheckResultRequestHandler, this, _3));
}
m_RotationTimer = boost::make_shared<Timer>(); m_RotationTimer = boost::make_shared<Timer>();
m_RotationTimer->OnTimerExpired.connect(boost::bind(&PerfdataWriter::RotationTimerHandler, this)); m_RotationTimer->OnTimerExpired.connect(boost::bind(&PerfdataWriter::RotationTimerHandler, this));
@ -87,8 +79,6 @@ PerfdataWriter::Ptr PerfdataWriter::GetByName(const String& name)
*/ */
String PerfdataWriter::GetPathPrefix(void) const String PerfdataWriter::GetPathPrefix(void) const
{ {
ObjectLock olock(this);
if (!m_PathPrefix.IsEmpty()) if (!m_PathPrefix.IsEmpty())
return m_PathPrefix; return m_PathPrefix;
else else
@ -100,8 +90,6 @@ String PerfdataWriter::GetPathPrefix(void) const
*/ */
String PerfdataWriter::GetFormatTemplate(void) const String PerfdataWriter::GetFormatTemplate(void) const
{ {
ObjectLock olock(this);
if (!m_FormatTemplate.IsEmpty()) { if (!m_FormatTemplate.IsEmpty()) {
return m_FormatTemplate; return m_FormatTemplate;
} else { } else {
@ -123,8 +111,6 @@ String PerfdataWriter::GetFormatTemplate(void) const
*/ */
double PerfdataWriter::GetRotationInterval(void) const double PerfdataWriter::GetRotationInterval(void) const
{ {
ObjectLock olock(this);
if (!m_RotationInterval.IsEmpty()) if (!m_RotationInterval.IsEmpty())
return m_RotationInterval; return m_RotationInterval;
else else

View File

@ -44,7 +44,7 @@ public:
double GetRotationInterval(void) const; double GetRotationInterval(void) const;
protected: protected:
virtual void OnAttributeChanged(const String& name, const Value& oldValue); virtual void OnAttributeChanged(const String& name);
virtual void Start(void); virtual void Start(void);
private: private:

View File

@ -25,16 +25,14 @@ const int Service::DefaultMaxCheckAttempts = 3;
const int Service::DefaultCheckInterval = 5 * 60; const int Service::DefaultCheckInterval = 5 * 60;
const int Service::CheckIntervalDivisor = 5; const int Service::CheckIntervalDivisor = 5;
signals2::signal<void (const Service::Ptr&, const String&)> Service::OnCheckerChanged; signals2::signal<void (const Service::Ptr&)> Service::OnCheckerChanged;
signals2::signal<void (const Service::Ptr&, const Value&)> Service::OnNextCheckChanged; signals2::signal<void (const Service::Ptr&)> Service::OnNextCheckChanged;
/** /**
* @threadsafety Always. * @threadsafety Always.
*/ */
Value Service::GetCheckCommand(void) const Value Service::GetCheckCommand(void) const
{ {
ObjectLock olock(this);
return m_CheckCommand; return m_CheckCommand;
} }
@ -43,8 +41,6 @@ Value Service::GetCheckCommand(void) const
*/ */
long Service::GetMaxCheckAttempts(void) const long Service::GetMaxCheckAttempts(void) const
{ {
ObjectLock olock(this);
if (m_MaxCheckAttempts.IsEmpty()) if (m_MaxCheckAttempts.IsEmpty())
return DefaultMaxCheckAttempts; return DefaultMaxCheckAttempts;
@ -56,8 +52,6 @@ long Service::GetMaxCheckAttempts(void) const
*/ */
double Service::GetCheckInterval(void) const double Service::GetCheckInterval(void) const
{ {
ObjectLock olock(this);
if (m_CheckInterval.IsEmpty()) if (m_CheckInterval.IsEmpty())
return DefaultCheckInterval; return DefaultCheckInterval;
@ -69,8 +63,6 @@ double Service::GetCheckInterval(void) const
*/ */
double Service::GetRetryInterval(void) const double Service::GetRetryInterval(void) const
{ {
ObjectLock olock(this);
if (m_RetryInterval.IsEmpty()) if (m_RetryInterval.IsEmpty())
return GetCheckInterval() / CheckIntervalDivisor; return GetCheckInterval() / CheckIntervalDivisor;
@ -82,8 +74,6 @@ double Service::GetRetryInterval(void) const
*/ */
Dictionary::Ptr Service::GetCheckers(void) const Dictionary::Ptr Service::GetCheckers(void) const
{ {
ObjectLock olock(this);
return m_Checkers; return m_Checkers;
} }
@ -92,8 +82,6 @@ Dictionary::Ptr Service::GetCheckers(void) const
*/ */
void Service::SetSchedulingOffset(long offset) void Service::SetSchedulingOffset(long offset)
{ {
ObjectLock olock(this);
m_SchedulingOffset = offset; m_SchedulingOffset = offset;
} }
@ -102,8 +90,6 @@ void Service::SetSchedulingOffset(long offset)
*/ */
long Service::GetSchedulingOffset(void) long Service::GetSchedulingOffset(void)
{ {
ObjectLock olock(this);
return m_SchedulingOffset; return m_SchedulingOffset;
} }
@ -112,8 +98,6 @@ long Service::GetSchedulingOffset(void)
*/ */
void Service::SetNextCheck(double nextCheck) void Service::SetNextCheck(double nextCheck)
{ {
ObjectLock olock(this);
m_NextCheck = nextCheck; m_NextCheck = nextCheck;
Touch("next_check"); Touch("next_check");
} }
@ -123,15 +107,6 @@ void Service::SetNextCheck(double nextCheck)
*/ */
double Service::GetNextCheck(void) double Service::GetNextCheck(void)
{ {
ObjectLock olock(this);
if (m_NextCheck.IsEmpty()) {
UpdateNextCheck();
if (m_NextCheck.IsEmpty())
BOOST_THROW_EXCEPTION(runtime_error("Failed to schedule next check."));
}
return m_NextCheck; return m_NextCheck;
} }
@ -163,8 +138,6 @@ void Service::UpdateNextCheck(void)
*/ */
void Service::SetCurrentChecker(const String& checker) void Service::SetCurrentChecker(const String& checker)
{ {
ObjectLock olock(this);
m_CurrentChecker = checker; m_CurrentChecker = checker;
Touch("current_checker"); Touch("current_checker");
} }
@ -174,8 +147,6 @@ void Service::SetCurrentChecker(const String& checker)
*/ */
String Service::GetCurrentChecker(void) const String Service::GetCurrentChecker(void) const
{ {
ObjectLock olock(this);
return m_CurrentChecker; return m_CurrentChecker;
} }
@ -184,8 +155,6 @@ String Service::GetCurrentChecker(void) const
*/ */
void Service::SetCurrentCheckAttempt(long attempt) void Service::SetCurrentCheckAttempt(long attempt)
{ {
ObjectLock olock(this);
m_CheckAttempt = attempt; m_CheckAttempt = attempt;
Touch("check_attempt"); Touch("check_attempt");
} }
@ -195,8 +164,6 @@ void Service::SetCurrentCheckAttempt(long attempt)
*/ */
long Service::GetCurrentCheckAttempt(void) const long Service::GetCurrentCheckAttempt(void) const
{ {
ObjectLock olock(this);
if (m_CheckAttempt.IsEmpty()) if (m_CheckAttempt.IsEmpty())
return 1; return 1;
@ -208,8 +175,6 @@ long Service::GetCurrentCheckAttempt(void) const
*/ */
void Service::SetState(ServiceState state) void Service::SetState(ServiceState state)
{ {
ObjectLock olock(this);
m_State = static_cast<long>(state); m_State = static_cast<long>(state);
Touch("state"); Touch("state");
} }
@ -219,8 +184,6 @@ void Service::SetState(ServiceState state)
*/ */
ServiceState Service::GetState(void) const ServiceState Service::GetState(void) const
{ {
ObjectLock olock(this);
if (m_State.IsEmpty()) if (m_State.IsEmpty())
return StateUnknown; return StateUnknown;
@ -233,8 +196,6 @@ ServiceState Service::GetState(void) const
*/ */
void Service::SetStateType(ServiceStateType type) void Service::SetStateType(ServiceStateType type)
{ {
ObjectLock olock(this);
m_StateType = static_cast<long>(type); m_StateType = static_cast<long>(type);
Touch("state_type"); Touch("state_type");
} }
@ -244,8 +205,6 @@ void Service::SetStateType(ServiceStateType type)
*/ */
ServiceStateType Service::GetStateType(void) const ServiceStateType Service::GetStateType(void) const
{ {
ObjectLock olock(this);
if (m_StateType.IsEmpty()) if (m_StateType.IsEmpty())
return StateTypeSoft; return StateTypeSoft;
@ -258,8 +217,6 @@ ServiceStateType Service::GetStateType(void) const
*/ */
void Service::SetLastCheckResult(const Dictionary::Ptr& result) void Service::SetLastCheckResult(const Dictionary::Ptr& result)
{ {
ObjectLock olock(this);
m_LastResult = result; m_LastResult = result;
Touch("last_result"); Touch("last_result");
} }
@ -269,8 +226,6 @@ void Service::SetLastCheckResult(const Dictionary::Ptr& result)
*/ */
Dictionary::Ptr Service::GetLastCheckResult(void) const Dictionary::Ptr Service::GetLastCheckResult(void) const
{ {
ObjectLock olock(this);
return m_LastResult; return m_LastResult;
} }
@ -279,8 +234,6 @@ Dictionary::Ptr Service::GetLastCheckResult(void) const
*/ */
void Service::SetLastStateChange(double ts) void Service::SetLastStateChange(double ts)
{ {
ObjectLock olock(this);
m_LastStateChange = ts; m_LastStateChange = ts;
Touch("last_state_change"); Touch("last_state_change");
} }
@ -290,8 +243,6 @@ void Service::SetLastStateChange(double ts)
*/ */
double Service::GetLastStateChange(void) const double Service::GetLastStateChange(void) const
{ {
ObjectLock olock(this);
if (m_LastStateChange.IsEmpty()) if (m_LastStateChange.IsEmpty())
return IcingaApplication::GetInstance()->GetStartTime(); return IcingaApplication::GetInstance()->GetStartTime();
@ -303,8 +254,6 @@ double Service::GetLastStateChange(void) const
*/ */
void Service::SetLastHardStateChange(double ts) void Service::SetLastHardStateChange(double ts)
{ {
ObjectLock olock(this);
m_LastHardStateChange = ts; m_LastHardStateChange = ts;
Touch("last_hard_state_change"); Touch("last_hard_state_change");
} }
@ -314,8 +263,6 @@ void Service::SetLastHardStateChange(double ts)
*/ */
double Service::GetLastHardStateChange(void) const double Service::GetLastHardStateChange(void) const
{ {
ObjectLock olock(this);
if (m_LastHardStateChange.IsEmpty()) if (m_LastHardStateChange.IsEmpty())
return IcingaApplication::GetInstance()->GetStartTime(); return IcingaApplication::GetInstance()->GetStartTime();
@ -327,8 +274,6 @@ double Service::GetLastHardStateChange(void) const
*/ */
bool Service::GetEnableActiveChecks(void) const bool Service::GetEnableActiveChecks(void) const
{ {
ObjectLock olock(this);
if (m_EnableActiveChecks.IsEmpty()) if (m_EnableActiveChecks.IsEmpty())
return true; return true;
else else
@ -340,8 +285,6 @@ bool Service::GetEnableActiveChecks(void) const
*/ */
void Service::SetEnableActiveChecks(bool enabled) void Service::SetEnableActiveChecks(bool enabled)
{ {
ObjectLock olock(this);
m_EnableActiveChecks = enabled ? 1 : 0; m_EnableActiveChecks = enabled ? 1 : 0;
Touch("enable_active_checks"); Touch("enable_active_checks");
} }
@ -351,8 +294,6 @@ void Service::SetEnableActiveChecks(bool enabled)
*/ */
bool Service::GetEnablePassiveChecks(void) const bool Service::GetEnablePassiveChecks(void) const
{ {
ObjectLock olock(this);
if (m_EnablePassiveChecks.IsEmpty()) if (m_EnablePassiveChecks.IsEmpty())
return true; return true;
else else
@ -364,8 +305,6 @@ bool Service::GetEnablePassiveChecks(void) const
*/ */
void Service::SetEnablePassiveChecks(bool enabled) void Service::SetEnablePassiveChecks(bool enabled)
{ {
ObjectLock olock(this);
m_EnablePassiveChecks = enabled ? 1 : 0; m_EnablePassiveChecks = enabled ? 1 : 0;
Touch("enable_passive_checks"); Touch("enable_passive_checks");
} }
@ -375,8 +314,6 @@ void Service::SetEnablePassiveChecks(bool enabled)
*/ */
bool Service::GetForceNextCheck(void) const bool Service::GetForceNextCheck(void) const
{ {
ObjectLock olock(this);
if (m_ForceNextCheck.IsEmpty()) if (m_ForceNextCheck.IsEmpty())
return false; return false;
@ -388,8 +325,6 @@ bool Service::GetForceNextCheck(void) const
*/ */
void Service::SetForceNextCheck(bool forced) void Service::SetForceNextCheck(bool forced)
{ {
ObjectLock olock(this);
m_ForceNextCheck = forced ? 1 : 0; m_ForceNextCheck = forced ? 1 : 0;
Touch("force_next_check"); Touch("force_next_check");
} }
@ -455,6 +390,7 @@ void Service::ProcessCheckResult(const Dictionary::Ptr& cr)
/* reschedule service dependencies */ /* reschedule service dependencies */
BOOST_FOREACH(const Service::Ptr& parent, GetParentServices()) { BOOST_FOREACH(const Service::Ptr& parent, GetParentServices()) {
ObjectLock olock(parent);
parent->SetNextCheck(Utility::GetTime()); parent->SetNextCheck(Utility::GetTime());
} }
@ -462,7 +398,7 @@ void Service::ProcessCheckResult(const Dictionary::Ptr& cr)
BOOST_FOREACH(const Host::Ptr& parent, GetParentHosts()) { BOOST_FOREACH(const Host::Ptr& parent, GetParentHosts()) {
Service::Ptr service = parent->GetHostCheckService(); Service::Ptr service = parent->GetHostCheckService();
if (service) { if (service && service->GetName() != GetName()) {
ObjectLock olock(service); ObjectLock olock(service);
service->SetNextCheck(Utility::GetTime()); service->SetNextCheck(Utility::GetTime());
} }
@ -582,13 +518,14 @@ bool Service::IsAllowedChecker(const String& checker) const
/** /**
* @threadsafety Always. * @threadsafety Always.
*/ */
void Service::BeginExecuteCheck(const Service::Ptr& self, const function<void (void)>& callback) void Service::BeginExecuteCheck(const function<void (void)>& callback)
{ {
ObjectLock slock(self); assert(!OwnsLock());
ObjectLock olock(this);
/* don't run another check if there is one pending */ /* don't run another check if there is one pending */
if (self->m_CurrentTask) { if (m_CurrentTask) {
slock.Unlock(); olock.Unlock();
/* we need to call the callback anyway */ /* we need to call the callback anyway */
callback(); callback();
@ -598,18 +535,19 @@ void Service::BeginExecuteCheck(const Service::Ptr& self, const function<void (v
/* keep track of scheduling info in case the check type doesn't provide its own information */ /* keep track of scheduling info in case the check type doesn't provide its own information */
Dictionary::Ptr checkInfo = boost::make_shared<Dictionary>(); Dictionary::Ptr checkInfo = boost::make_shared<Dictionary>();
checkInfo->Set("schedule_start", self->GetNextCheck()); checkInfo->Set("schedule_start", GetNextCheck());
checkInfo->Set("execution_start", Utility::GetTime()); checkInfo->Set("execution_start", Utility::GetTime());
vector<Dictionary::Ptr> macroDicts; vector<Dictionary::Ptr> macroDicts;
macroDicts.push_back(self->GetMacros()); macroDicts.push_back(GetMacros());
macroDicts.push_back(self->CalculateDynamicMacros());
Value raw_command = self->GetCheckCommand(); Value raw_command = GetCheckCommand();
Host::Ptr host = self->GetHost(); Host::Ptr host = GetHost();
slock.Unlock(); olock.Unlock();
macroDicts.push_back(CalculateDynamicMacros());
macroDicts.push_back(host->GetMacros()); macroDicts.push_back(host->GetMacros());
macroDicts.push_back(host->CalculateDynamicMacros()); macroDicts.push_back(host->CalculateDynamicMacros());
@ -623,15 +561,16 @@ void Service::BeginExecuteCheck(const Service::Ptr& self, const function<void (v
checkInfo->Set("macros", macros); checkInfo->Set("macros", macros);
Service::Ptr self = GetSelf();
vector<Value> arguments; vector<Value> arguments;
arguments.push_back(self); arguments.push_back(self);
arguments.push_back(macros); arguments.push_back(macros);
ScriptTask::Ptr task; ScriptTask::Ptr task = MakeMethodTask("check", arguments);
{ {
ObjectLock olock(self); ObjectLock slock(this);
task = self->MakeMethodTask("check", arguments);
self->m_CurrentTask = task; self->m_CurrentTask = task;
} }
@ -691,8 +630,6 @@ void Service::CheckCompletedHandler(const Dictionary::Ptr& checkInfo,
if (!result->Contains("current_checker")) { if (!result->Contains("current_checker")) {
EndpointManager::Ptr em = EndpointManager::GetInstance(); EndpointManager::Ptr em = EndpointManager::GetInstance();
ObjectLock olock(em);
result->Set("current_checker", em->GetIdentity()); result->Set("current_checker", em->GetIdentity());
} }
@ -768,5 +705,4 @@ double Service::CalculateLatency(const Dictionary::Ptr& cr)
} }
return (schedule_end - schedule_start) - CalculateExecutionTime(cr); return (schedule_end - schedule_start) - CalculateExecutionTime(cr);
} }

View File

@ -43,8 +43,6 @@ int Service::GetNextCommentID(void)
*/ */
Dictionary::Ptr Service::GetComments(void) const Dictionary::Ptr Service::GetComments(void) const
{ {
ObjectLock olock(this);
return m_Comments; return m_Comments;
} }
@ -70,17 +68,22 @@ String Service::AddComment(CommentType entryType, const String& author,
comment->Set("legacy_id", legacy_id); comment->Set("legacy_id", legacy_id);
ObjectLock olock(this); Dictionary::Ptr comments;
Dictionary::Ptr comments = GetComments(); {
ObjectLock olock(this);
if (!comments) comments = GetComments();
comments = boost::make_shared<Dictionary>();
if (!comments)
comments = boost::make_shared<Dictionary>();
m_Comments = comments;
}
String id = Utility::NewUUID(); String id = Utility::NewUUID();
comments->Set(id, comment); comments->Set(id, comment);
m_Comments = comments;
Touch("comments"); Touch("comments");
return id; return id;
@ -91,8 +94,6 @@ String Service::AddComment(CommentType entryType, const String& author,
*/ */
void Service::RemoveAllComments(void) void Service::RemoveAllComments(void)
{ {
ObjectLock olock(this);
m_Comments = Empty; m_Comments = Empty;
Touch("comments"); Touch("comments");
} }
@ -107,8 +108,6 @@ void Service::RemoveComment(const String& id)
if (!owner) if (!owner)
return; return;
ObjectLock olock(owner);
Dictionary::Ptr comments = owner->GetComments(); Dictionary::Ptr comments = owner->GetComments();
if (comments) { if (comments) {
@ -203,12 +202,7 @@ void Service::RefreshCommentsCache(void)
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) { BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) {
Service::Ptr service = dynamic_pointer_cast<Service>(object); Service::Ptr service = dynamic_pointer_cast<Service>(object);
Dictionary::Ptr comments; Dictionary::Ptr comments = service->GetComments();
{
ObjectLock olock(service);
comments = service->GetComments();
}
if (!comments) if (!comments)
continue; continue;
@ -218,8 +212,6 @@ void Service::RefreshCommentsCache(void)
String id; String id;
Dictionary::Ptr comment; Dictionary::Ptr comment;
BOOST_FOREACH(tie(id, comment), comments) { BOOST_FOREACH(tie(id, comment), comments) {
ObjectLock clock(comment);
int legacy_id = comment->Get("legacy_id"); int legacy_id = comment->Get("legacy_id");
if (legacy_id >= m_NextCommentID) if (legacy_id >= m_NextCommentID)
@ -257,8 +249,6 @@ void Service::RefreshCommentsCache(void)
*/ */
void Service::RemoveExpiredComments(void) void Service::RemoveExpiredComments(void)
{ {
ObjectLock olock(this);
Dictionary::Ptr comments = GetComments(); Dictionary::Ptr comments = GetComments();
if (!comments) if (!comments)
@ -266,17 +256,19 @@ void Service::RemoveExpiredComments(void)
vector<String> expiredComments; vector<String> expiredComments;
ObjectLock dlock(comments); {
ObjectLock olock(comments);
String id; String id;
Dictionary::Ptr comment; Dictionary::Ptr comment;
BOOST_FOREACH(tie(id, comment), comments) { BOOST_FOREACH(tie(id, comment), comments) {
if (IsCommentExpired(comment)) if (IsCommentExpired(comment))
expiredComments.push_back(id); expiredComments.push_back(id);
}
} }
if (expiredComments.size() > 0) { if (expiredComments.size() > 0) {
BOOST_FOREACH(id, expiredComments) { BOOST_FOREACH(const String& id, expiredComments) {
comments->Remove(id); comments->Remove(id);
} }

View File

@ -83,15 +83,22 @@ String Service::AddDowntime(const String& author, const String& comment,
otherOwner->Touch("downtimes"); otherOwner->Touch("downtimes");
} }
Dictionary::Ptr downtimes = m_Downtimes; Dictionary::Ptr downtimes;
if (!downtimes) {
downtimes = boost::make_shared<Dictionary>(); ObjectLock olock(this);
downtimes = m_Downtimes;
if (!downtimes)
downtimes = boost::make_shared<Dictionary>();
m_Downtimes = downtimes;
}
String id = Utility::NewUUID(); String id = Utility::NewUUID();
downtimes->Set(id, downtime); downtimes->Set(id, downtime);
m_Downtimes = downtimes;
Touch("downtimes"); Touch("downtimes");
return id; return id;
@ -107,8 +114,6 @@ void Service::RemoveDowntime(const String& id)
if (!owner) if (!owner)
return; return;
ObjectLock olock(owner);
Dictionary::Ptr downtimes = owner->GetDowntimes(); Dictionary::Ptr downtimes = owner->GetDowntimes();
if (!downtimes) if (!downtimes)
@ -149,8 +154,6 @@ void Service::TriggerDowntime(const String& id)
double now = Utility::GetTime(); double now = Utility::GetTime();
ObjectLock olock(downtime);
if (now < downtime->Get("start_time") || if (now < downtime->Get("start_time") ||
now > downtime->Get("end_time")) now > downtime->Get("end_time"))
return; return;
@ -159,7 +162,7 @@ void Service::TriggerDowntime(const String& id)
downtime->Set("trigger_time", now); downtime->Set("trigger_time", now);
Dictionary::Ptr triggers = downtime->Get("triggers"); Dictionary::Ptr triggers = downtime->Get("triggers");
ObjectLock tlock(triggers); ObjectLock olock(triggers);
String tid; String tid;
BOOST_FOREACH(tie(tid, tuples::ignore), triggers) { BOOST_FOREACH(tie(tid, tuples::ignore), triggers) {
TriggerDowntime(tid); TriggerDowntime(tid);
@ -217,8 +220,6 @@ bool Service::IsDowntimeActive(const Dictionary::Ptr& downtime)
{ {
double now = Utility::GetTime(); double now = Utility::GetTime();
ObjectLock olock(downtime);
if (now < downtime->Get("start_time") || if (now < downtime->Get("start_time") ||
now > downtime->Get("end_time")) now > downtime->Get("end_time"))
return false; return false;
@ -275,12 +276,7 @@ void Service::RefreshDowntimesCache(void)
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) { BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) {
Service::Ptr service = dynamic_pointer_cast<Service>(object); Service::Ptr service = dynamic_pointer_cast<Service>(object);
Dictionary::Ptr downtimes; Dictionary::Ptr downtimes = service->GetDowntimes();
{
ObjectLock olock(service);
downtimes = service->GetDowntimes();
}
if (!downtimes) if (!downtimes)
continue; continue;
@ -290,7 +286,6 @@ void Service::RefreshDowntimesCache(void)
String id; String id;
Dictionary::Ptr downtime; Dictionary::Ptr downtime;
BOOST_FOREACH(tie(id, downtime), downtimes) { BOOST_FOREACH(tie(id, downtime), downtimes) {
ObjectLock dlock(downtime);
int legacy_id = downtime->Get("legacy_id"); int legacy_id = downtime->Get("legacy_id");
if (legacy_id >= m_NextDowntimeID) if (legacy_id >= m_NextDowntimeID)
@ -327,8 +322,6 @@ void Service::RefreshDowntimesCache(void)
*/ */
void Service::RemoveExpiredDowntimes(void) void Service::RemoveExpiredDowntimes(void)
{ {
ObjectLock olock(this);
Dictionary::Ptr downtimes = GetDowntimes(); Dictionary::Ptr downtimes = GetDowntimes();
if (!downtimes) if (!downtimes)
@ -336,17 +329,19 @@ void Service::RemoveExpiredDowntimes(void)
vector<String> expiredDowntimes; vector<String> expiredDowntimes;
ObjectLock dlock(downtimes); {
ObjectLock olock(downtimes);
String id; String id;
Dictionary::Ptr downtime; Dictionary::Ptr downtime;
BOOST_FOREACH(tie(id, downtime), downtimes) { BOOST_FOREACH(tie(id, downtime), downtimes) {
if (IsDowntimeExpired(downtime)) if (IsDowntimeExpired(downtime))
expiredDowntimes.push_back(id); expiredDowntimes.push_back(id);
}
} }
if (expiredDowntimes.size() > 0) { if (expiredDowntimes.size() > 0) {
BOOST_FOREACH(id, expiredDowntimes) { BOOST_FOREACH(const String& id, expiredDowntimes) {
downtimes->Remove(id); downtimes->Remove(id);
} }

View File

@ -149,8 +149,6 @@ set<Notification::Ptr> Service::GetNotifications(void) const
template<typename TDict> template<typename TDict>
static void CopyNotificationAttributes(TDict notificationDesc, const ConfigItemBuilder::Ptr& builder) static void CopyNotificationAttributes(TDict notificationDesc, const ConfigItemBuilder::Ptr& builder)
{ {
ObjectLock olock(notificationDesc);
/* TODO: we only need to copy macros if this is an inline definition, /* TODO: we only need to copy macros if this is an inline definition,
* i.e. "typeid(notificationDesc)" != Notification, however for now we just * i.e. "typeid(notificationDesc)" != Notification, however for now we just
* copy them anyway. */ * copy them anyway. */
@ -171,52 +169,35 @@ static void CopyNotificationAttributes(TDict notificationDesc, const ConfigItemB
builder->AddExpression("notification_interval", OperatorSet, notificationInterval);*/ builder->AddExpression("notification_interval", OperatorSet, notificationInterval);*/
} }
void Service::UpdateSlaveNotifications(const Service::Ptr& self) void Service::UpdateSlaveNotifications(void)
{ {
Dictionary::Ptr oldNotifications; Dictionary::Ptr oldNotifications;
Host::Ptr host;
vector<Dictionary::Ptr> notificationDescsList; vector<Dictionary::Ptr> notificationDescsList;
String service_name, short_name;
ConfigItem::Ptr item; ConfigItem::Ptr item;
{ item = ConfigItem::GetObject("Service", GetName());
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. */
/* Don't create slave notifications unless we own this object if (!item || IsAbstract())
* and it's not a template. */ return;
if (!item || self->IsAbstract())
return;
service_name = self->GetName();
short_name = self->GetShortName();
oldNotifications = self->m_SlaveNotifications;
host = self->GetHost();
notificationDescsList.push_back(self->Get("notifications"));
}
DebugInfo debug_info;
{ {
ObjectLock ilock(item); ObjectLock olock(this);
debug_info = item->GetDebugInfo(); oldNotifications = m_SlaveNotifications;
} }
notificationDescsList.push_back(Get("notifications"));
Dictionary::Ptr newNotifications; Dictionary::Ptr newNotifications;
newNotifications = boost::make_shared<Dictionary>(); newNotifications = boost::make_shared<Dictionary>();
ObjectLock nlock(newNotifications); Host::Ptr host = GetHost();
String host_name; if (!host)
return;
{ notificationDescsList.push_back(host->Get("notifications"));
ObjectLock olock(host);
notificationDescsList.push_back(host->Get("notifications"));
host_name = host->GetName();
}
BOOST_FOREACH(const Dictionary::Ptr& notificationDescs, notificationDescsList) { BOOST_FOREACH(const Dictionary::Ptr& notificationDescs, notificationDescsList) {
if (!notificationDescs) if (!notificationDescs)
@ -231,22 +212,21 @@ void Service::UpdateSlaveNotifications(const Service::Ptr& self)
nfcname = nfcdesc; nfcname = nfcdesc;
stringstream namebuf; stringstream namebuf;
namebuf << service_name << "-" << nfcname; namebuf << GetName() << "-" << nfcname;
String name = namebuf.str(); String name = namebuf.str();
ConfigItemBuilder::Ptr builder = boost::make_shared<ConfigItemBuilder>(debug_info); ConfigItemBuilder::Ptr builder = boost::make_shared<ConfigItemBuilder>(item->GetDebugInfo());
builder->SetType("Notification"); builder->SetType("Notification");
builder->SetName(name); builder->SetName(name);
builder->AddExpression("host_name", OperatorSet, host_name); builder->AddExpression("host_name", OperatorSet, host->GetName());
builder->AddExpression("service", OperatorSet, short_name); builder->AddExpression("service", OperatorSet, GetShortName());
CopyNotificationAttributes(self, builder); CopyNotificationAttributes(this, builder);
if (nfcdesc.IsScalar()) { if (nfcdesc.IsScalar()) {
builder->AddParent(nfcdesc); builder->AddParent(nfcdesc);
} else if (nfcdesc.IsObjectType<Dictionary>()) { } else if (nfcdesc.IsObjectType<Dictionary>()) {
Dictionary::Ptr notification = nfcdesc; Dictionary::Ptr notification = nfcdesc;
ObjectLock nlock(notification);
Dictionary::Ptr templates = notification->Get("templates"); Dictionary::Ptr templates = notification->Get("templates");
@ -287,8 +267,8 @@ void Service::UpdateSlaveNotifications(const Service::Ptr& self)
} }
{ {
ObjectLock olock(self); ObjectLock olock(this);
self->m_SlaveNotifications = newNotifications; m_SlaveNotifications = newNotifications;
} }
} }
@ -297,8 +277,6 @@ void Service::UpdateSlaveNotifications(const Service::Ptr& self)
*/ */
double Service::GetLastNotification(void) const double Service::GetLastNotification(void) const
{ {
ObjectLock olock(this);
if (m_LastNotification.IsEmpty()) if (m_LastNotification.IsEmpty())
return 0; return 0;
else else
@ -310,8 +288,6 @@ double Service::GetLastNotification(void) const
*/ */
void Service::SetLastNotification(double time) void Service::SetLastNotification(double time)
{ {
ObjectLock olock(this);
m_LastNotification = time; m_LastNotification = time;
Touch("last_notification"); Touch("last_notification");
} }
@ -321,8 +297,6 @@ void Service::SetLastNotification(double time)
*/ */
bool Service::GetEnableNotifications(void) const bool Service::GetEnableNotifications(void) const
{ {
ObjectLock olock(this);
if (m_EnableNotifications.IsEmpty()) if (m_EnableNotifications.IsEmpty())
return true; return true;
else else
@ -334,8 +308,6 @@ bool Service::GetEnableNotifications(void) const
*/ */
void Service::SetEnableNotifications(bool enabled) void Service::SetEnableNotifications(bool enabled)
{ {
ObjectLock olock(this);
m_EnableNotifications = enabled; m_EnableNotifications = enabled;
Touch("enable_notifications"); Touch("enable_notifications");
} }
@ -345,8 +317,6 @@ void Service::SetEnableNotifications(bool enabled)
*/ */
double Service::GetNotificationInterval(void) const double Service::GetNotificationInterval(void) const
{ {
ObjectLock olock(this);
if (m_NotificationInterval.IsEmpty()) if (m_NotificationInterval.IsEmpty())
return 300; return 300;
else else

View File

@ -93,8 +93,6 @@ void Service::OnRegistrationCompleted(void)
*/ */
String Service::GetDisplayName(void) const String Service::GetDisplayName(void) const
{ {
ObjectLock olock(this);
if (m_DisplayName.IsEmpty()) if (m_DisplayName.IsEmpty())
return GetShortName(); return GetShortName();
else else
@ -136,8 +134,6 @@ Service::Ptr Service::GetByNamePair(const String& hostName, const String& servic
*/ */
Host::Ptr Service::GetHost(void) const Host::Ptr Service::GetHost(void) const
{ {
ObjectLock olock(this);
return Host::GetByName(m_HostName); return Host::GetByName(m_HostName);
} }
@ -146,8 +142,6 @@ Host::Ptr Service::GetHost(void) const
*/ */
Dictionary::Ptr Service::GetMacros(void) const Dictionary::Ptr Service::GetMacros(void) const
{ {
ObjectLock olock(this);
return m_Macros; return m_Macros;
} }
@ -156,8 +150,6 @@ Dictionary::Ptr Service::GetMacros(void) const
*/ */
Dictionary::Ptr Service::GetHostDependencies(void) const Dictionary::Ptr Service::GetHostDependencies(void) const
{ {
ObjectLock olock(this);
return m_HostDependencies; return m_HostDependencies;
} }
@ -166,8 +158,6 @@ Dictionary::Ptr Service::GetHostDependencies(void) const
*/ */
Dictionary::Ptr Service::GetServiceDependencies(void) const Dictionary::Ptr Service::GetServiceDependencies(void) const
{ {
ObjectLock olock(this);
return m_ServiceDependencies; return m_ServiceDependencies;
} }
@ -176,8 +166,6 @@ Dictionary::Ptr Service::GetServiceDependencies(void) const
*/ */
Dictionary::Ptr Service::GetGroups(void) const Dictionary::Ptr Service::GetGroups(void) const
{ {
ObjectLock olock(this);
return m_ServiceGroups; return m_ServiceGroups;
} }
@ -186,8 +174,6 @@ Dictionary::Ptr Service::GetGroups(void) const
*/ */
String Service::GetHostName(void) const String Service::GetHostName(void) const
{ {
ObjectLock olock(this);
return m_HostName; return m_HostName;
} }
@ -196,8 +182,6 @@ String Service::GetHostName(void) const
*/ */
String Service::GetShortName(void) const String Service::GetShortName(void) const
{ {
ObjectLock olock(this);
if (m_ShortName.IsEmpty()) if (m_ShortName.IsEmpty())
return GetName(); return GetName();
else else
@ -266,8 +250,6 @@ bool Service::IsReachable(void) const
*/ */
AcknowledgementType Service::GetAcknowledgement(void) AcknowledgementType Service::GetAcknowledgement(void)
{ {
ObjectLock olock(this);
if (m_Acknowledgement.IsEmpty()) if (m_Acknowledgement.IsEmpty())
return AcknowledgementNone; return AcknowledgementNone;
@ -292,8 +274,6 @@ AcknowledgementType Service::GetAcknowledgement(void)
*/ */
void Service::SetAcknowledgement(AcknowledgementType acknowledgement) void Service::SetAcknowledgement(AcknowledgementType acknowledgement)
{ {
ObjectLock olock(this);
m_Acknowledgement = acknowledgement; m_Acknowledgement = acknowledgement;
Touch("acknowledgement"); Touch("acknowledgement");
} }
@ -311,8 +291,6 @@ bool Service::IsAcknowledged(void)
*/ */
double Service::GetAcknowledgementExpiry(void) const double Service::GetAcknowledgementExpiry(void) const
{ {
ObjectLock olock(this);
if (m_AcknowledgementExpiry.IsEmpty()) if (m_AcknowledgementExpiry.IsEmpty())
return 0; return 0;
@ -324,8 +302,6 @@ double Service::GetAcknowledgementExpiry(void) const
*/ */
void Service::SetAcknowledgementExpiry(double timestamp) void Service::SetAcknowledgementExpiry(double timestamp)
{ {
ObjectLock olock(this);
m_AcknowledgementExpiry = timestamp; m_AcknowledgementExpiry = timestamp;
Touch("acknowledgement_expiry"); Touch("acknowledgement_expiry");
} }
@ -348,6 +324,8 @@ void Service::AcknowledgeProblem(AcknowledgementType type, double expiry)
*/ */
void Service::ClearAcknowledgement(void) void Service::ClearAcknowledgement(void)
{ {
ObjectLock olock(this);
SetAcknowledgement(AcknowledgementNone); SetAcknowledgement(AcknowledgementNone);
SetAcknowledgementExpiry(0); SetAcknowledgementExpiry(0);
} }
@ -355,43 +333,33 @@ void Service::ClearAcknowledgement(void)
/** /**
* @threadsafety Always. * @threadsafety Always.
*/ */
void Service::OnAttributeChanged(const String& name, const Value& oldValue) void Service::OnAttributeChanged(const String& name)
{ {
assert(!OwnsLock()); assert(!OwnsLock());
Service::Ptr self; Service::Ptr self = GetSelf();
String service_name;
bool abstract;
{
ObjectLock olock(this);
self = GetSelf();
service_name = GetName();
abstract = IsAbstract();
}
if (name == "current_checker") if (name == "current_checker")
OnCheckerChanged(self, oldValue); OnCheckerChanged(self);
else if (name == "next_check") else if (name == "next_check")
OnNextCheckChanged(self, oldValue); OnNextCheckChanged(self);
else if (name == "servicegroups") else if (name == "servicegroups")
ServiceGroup::InvalidateMembersCache(); ServiceGroup::InvalidateMembersCache();
else if (name == "host_name" || name == "short_name") { else if (name == "host_name" || name == "short_name") {
Host::InvalidateServicesCache(); Host::InvalidateServicesCache();
UpdateSlaveNotifications(self); UpdateSlaveNotifications();
} else if (name == "downtimes") } else if (name == "downtimes")
Service::InvalidateDowntimesCache(); Service::InvalidateDowntimesCache();
else if (name == "comments") else if (name == "comments")
Service::InvalidateCommentsCache(); Service::InvalidateCommentsCache();
else if (name == "notifications") else if (name == "notifications")
UpdateSlaveNotifications(self); UpdateSlaveNotifications();
else if (name == "check_interval") { else if (name == "check_interval") {
ObjectLock olock(this); ConfigItem::Ptr item = ConfigItem::GetObject("Service", GetName());
ConfigItem::Ptr item = ConfigItem::GetObject("Service", service_name);
/* update the next check timestamp if we're the owner of this service */ /* update the next check timestamp if we're the owner of this service */
if (item && !abstract) if (item && !IsAbstract())
UpdateNextCheck(); UpdateNextCheck();
} }
} }
@ -481,11 +449,11 @@ Dictionary::Ptr Service::CalculateDynamicMacros(void) const
} }
if (cr) { if (cr) {
assert(cr->IsSealed());
macros->Set("SERVICELATENCY", Service::CalculateLatency(cr)); macros->Set("SERVICELATENCY", Service::CalculateLatency(cr));
macros->Set("SERVICEEXECUTIONTIME", Service::CalculateExecutionTime(cr)); macros->Set("SERVICEEXECUTIONTIME", Service::CalculateExecutionTime(cr));
ObjectLock olock(cr);
macros->Set("SERVICEOUTPUT", cr->Get("output")); macros->Set("SERVICEOUTPUT", cr->Get("output"));
macros->Set("SERVICEPERFDATA", cr->Get("performance_data_raw")); macros->Set("SERVICEPERFDATA", cr->Get("performance_data_raw"));
} }

View File

@ -170,7 +170,7 @@ public:
void AcknowledgeProblem(AcknowledgementType type, double expiry = 0); void AcknowledgeProblem(AcknowledgementType type, double expiry = 0);
void ClearAcknowledgement(void); void ClearAcknowledgement(void);
static void BeginExecuteCheck(const Service::Ptr& self, const function<void (void)>& callback); void BeginExecuteCheck(const function<void (void)>& callback);
void ProcessCheckResult(const Dictionary::Ptr& cr); void ProcessCheckResult(const Dictionary::Ptr& cr);
static double CalculateExecutionTime(const Dictionary::Ptr& cr); static double CalculateExecutionTime(const Dictionary::Ptr& cr);
@ -182,8 +182,8 @@ public:
static ServiceStateType StateTypeFromString(const String& state); static ServiceStateType StateTypeFromString(const String& state);
static String StateTypeToString(ServiceStateType state); static String StateTypeToString(ServiceStateType state);
static signals2::signal<void (const Service::Ptr&, const String&)> OnCheckerChanged; static signals2::signal<void (const Service::Ptr&)> OnCheckerChanged;
static signals2::signal<void (const Service::Ptr&, const Value&)> OnNextCheckChanged; static signals2::signal<void (const Service::Ptr&)> OnNextCheckChanged;
/* Downtimes */ /* Downtimes */
static int GetNextDowntimeID(void); static int GetNextDowntimeID(void);
@ -243,14 +243,14 @@ public:
static void InvalidateNotificationsCache(void); static void InvalidateNotificationsCache(void);
static void UpdateSlaveNotifications(const Service::Ptr& self); void UpdateSlaveNotifications(void);
double GetLastNotification(void) const; double GetLastNotification(void) const;
void SetLastNotification(double time); void SetLastNotification(double time);
protected: protected:
virtual void OnRegistrationCompleted(void); virtual void OnRegistrationCompleted(void);
virtual void OnAttributeChanged(const String& name, const Value& oldValue); virtual void OnAttributeChanged(const String& name);
private: private:
Dictionary::Ptr m_SlaveNotifications; Dictionary::Ptr m_SlaveNotifications;

View File

@ -55,8 +55,6 @@ void ServiceGroup::OnRegistrationCompleted(void)
*/ */
String ServiceGroup::GetDisplayName(void) const String ServiceGroup::GetDisplayName(void) const
{ {
ObjectLock olock(this);
if (!m_DisplayName.Get().IsEmpty()) if (!m_DisplayName.Get().IsEmpty())
return m_DisplayName; return m_DisplayName;
else else
@ -68,8 +66,6 @@ String ServiceGroup::GetDisplayName(void) const
*/ */
String ServiceGroup::GetNotesUrl(void) const String ServiceGroup::GetNotesUrl(void) const
{ {
ObjectLock olock(this);
return m_NotesUrl; return m_NotesUrl;
} }
@ -78,8 +74,6 @@ String ServiceGroup::GetNotesUrl(void) const
*/ */
String ServiceGroup::GetActionUrl(void) const String ServiceGroup::GetActionUrl(void) const
{ {
ObjectLock olock(this);
return m_ActionUrl; return m_ActionUrl;
} }
@ -150,7 +144,6 @@ void ServiceGroup::RefreshMembersCache(void)
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) { BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) {
const Service::Ptr& service = static_pointer_cast<Service>(object); const Service::Ptr& service = static_pointer_cast<Service>(object);
ObjectLock olock(service);
Dictionary::Ptr dict; Dictionary::Ptr dict;
dict = service->GetGroups(); dict = service->GetGroups();

View File

@ -39,7 +39,7 @@ User::~User(void)
/** /**
* @threadsafety Always. * @threadsafety Always.
*/ */
void User::OnAttributeChanged(const String& name, const Value& oldValue) void User::OnAttributeChanged(const String& name)
{ {
assert(!OwnsLock()); assert(!OwnsLock());
@ -62,8 +62,6 @@ User::Ptr User::GetByName(const String& name)
*/ */
String User::GetDisplayName(void) const String User::GetDisplayName(void) const
{ {
ObjectLock olock(this);
if (!m_DisplayName.IsEmpty()) if (!m_DisplayName.IsEmpty())
return m_DisplayName; return m_DisplayName;
else else
@ -75,8 +73,6 @@ String User::GetDisplayName(void) const
*/ */
Dictionary::Ptr User::GetGroups(void) const Dictionary::Ptr User::GetGroups(void) const
{ {
ObjectLock olock(this);
return m_Groups; return m_Groups;
} }
@ -85,8 +81,6 @@ Dictionary::Ptr User::GetGroups(void) const
*/ */
Dictionary::Ptr User::GetMacros(void) const Dictionary::Ptr User::GetMacros(void) const
{ {
ObjectLock olock(this);
return m_Macros; return m_Macros;
} }

View File

@ -46,7 +46,7 @@ public:
Dictionary::Ptr CalculateDynamicMacros(void) const; Dictionary::Ptr CalculateDynamicMacros(void) const;
protected: protected:
void OnAttributeChanged(const String& name, const Value& oldValue); virtual void OnAttributeChanged(const String& name);
private: private:
Attribute<String> m_DisplayName; Attribute<String> m_DisplayName;

View File

@ -53,8 +53,6 @@ void UserGroup::OnRegistrationCompleted(void)
*/ */
String UserGroup::GetDisplayName(void) const String UserGroup::GetDisplayName(void) const
{ {
ObjectLock olock(this);
if (!m_DisplayName.IsEmpty()) if (!m_DisplayName.IsEmpty())
return m_DisplayName; return m_DisplayName;
else else
@ -128,7 +126,6 @@ void UserGroup::RefreshMembersCache(void)
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("User")) { BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("User")) {
const User::Ptr& user = static_pointer_cast<User>(object); const User::Ptr& user = static_pointer_cast<User>(object);
ObjectLock olock(user);
Dictionary::Ptr dict; Dictionary::Ptr dict;
dict = user->GetGroups(); dict = user->GetGroups();

View File

@ -25,8 +25,6 @@ REGISTER_TYPE(Endpoint);
signals2::signal<void (const Endpoint::Ptr&)> Endpoint::OnConnected; signals2::signal<void (const Endpoint::Ptr&)> Endpoint::OnConnected;
signals2::signal<void (const Endpoint::Ptr&)> Endpoint::OnDisconnected; signals2::signal<void (const Endpoint::Ptr&)> Endpoint::OnDisconnected;
signals2::signal<void (const Endpoint::Ptr&, const String& topic)> Endpoint::OnSubscriptionRegistered;
signals2::signal<void (const Endpoint::Ptr&, const String& topic)> Endpoint::OnSubscriptionUnregistered;
/** /**
* Constructor for the Endpoint class. * Constructor for the Endpoint class.
@ -43,6 +41,9 @@ Endpoint::Endpoint(const Dictionary::Ptr& serializedUpdate)
RegisterAttribute("subscriptions", Attribute_Replicated, &m_Subscriptions); RegisterAttribute("subscriptions", Attribute_Replicated, &m_Subscriptions);
} }
Endpoint::~Endpoint(void)
{ }
/** /**
* Retrieves an endpoint by name. * Retrieves an endpoint by name.
* *
@ -84,8 +85,6 @@ Endpoint::Ptr Endpoint::MakeEndpoint(const String& name, bool replicated, bool l
*/ */
bool Endpoint::IsLocalEndpoint(void) const bool Endpoint::IsLocalEndpoint(void) const
{ {
ObjectLock olock(this);
return m_Local; return m_Local;
} }
@ -141,6 +140,8 @@ void Endpoint::RegisterSubscription(const String& topic)
if (!subscriptions->Contains(topic)) { if (!subscriptions->Contains(topic)) {
Dictionary::Ptr newSubscriptions = subscriptions->ShallowClone(); Dictionary::Ptr newSubscriptions = subscriptions->ShallowClone();
newSubscriptions->Set(topic, topic); newSubscriptions->Set(topic, topic);
ObjectLock olock(this);
SetSubscriptions(newSubscriptions); SetSubscriptions(newSubscriptions);
} }
} }
@ -182,8 +183,6 @@ bool Endpoint::HasSubscription(const String& topic) const
*/ */
void Endpoint::ClearSubscriptions(void) void Endpoint::ClearSubscriptions(void)
{ {
ObjectLock olock(this);
m_Subscriptions = Empty; m_Subscriptions = Empty;
Touch("subscriptions"); Touch("subscriptions");
} }
@ -195,8 +194,6 @@ Dictionary::Ptr Endpoint::GetSubscriptions(void) const
void Endpoint::SetSubscriptions(const Dictionary::Ptr& subscriptions) void Endpoint::SetSubscriptions(const Dictionary::Ptr& subscriptions)
{ {
ObjectLock olock(this);
subscriptions->Seal(); subscriptions->Seal();
m_Subscriptions = subscriptions; m_Subscriptions = subscriptions;
Touch("subscriptions"); Touch("subscriptions");
@ -220,6 +217,8 @@ void Endpoint::RegisterTopicHandler(const String& topic, const function<Endpoint
sig->connect(callback); sig->connect(callback);
olock.Unlock();
RegisterSubscription(topic); RegisterSubscription(topic);
} }
@ -232,44 +231,6 @@ void Endpoint::UnregisterTopicHandler(const String& topic, const function<Endpoi
BOOST_THROW_EXCEPTION(NotImplementedException()); BOOST_THROW_EXCEPTION(NotImplementedException());
} }
void Endpoint::OnAttributeChanged(const String& name, const Value& oldValue)
{
assert(!OwnsLock());
if (name == "subscriptions") {
Dictionary::Ptr oldSubscriptions, newSubscriptions;
if (oldValue.IsObjectType<Dictionary>())
oldSubscriptions = oldValue;
newSubscriptions = GetSubscriptions();
if (oldSubscriptions) {
ObjectLock olock(oldSubscriptions);
String subscription;
BOOST_FOREACH(tie(tuples::ignore, subscription), oldSubscriptions) {
if (!newSubscriptions || !newSubscriptions->Contains(subscription)) {
Logger::Write(LogInformation, "remoting", "Removed subscription for '" + GetName() + "': " + subscription);
OnSubscriptionUnregistered(GetSelf(), subscription);
}
}
}
if (newSubscriptions) {
ObjectLock olock(newSubscriptions);
String subscription;
BOOST_FOREACH(tie(tuples::ignore, subscription), newSubscriptions) {
if (!oldSubscriptions || !oldSubscriptions->Contains(subscription)) {
Logger::Write(LogDebug, "remoting", "New subscription for '" + GetName() + "': " + subscription);
OnSubscriptionRegistered(GetSelf(), subscription);
}
}
}
}
}
void Endpoint::ProcessRequest(const Endpoint::Ptr& sender, const RequestMessage& request) void Endpoint::ProcessRequest(const Endpoint::Ptr& sender, const RequestMessage& request)
{ {
if (!IsConnected()) { if (!IsConnected()) {

View File

@ -39,6 +39,7 @@ public:
typedef void (Callback)(const Endpoint::Ptr&, const Endpoint::Ptr&, const RequestMessage&); typedef void (Callback)(const Endpoint::Ptr&, const Endpoint::Ptr&, const RequestMessage&);
Endpoint(const Dictionary::Ptr& serializedUpdate); Endpoint(const Dictionary::Ptr& serializedUpdate);
~Endpoint(void);
static Endpoint::Ptr GetByName(const String& name); static Endpoint::Ptr GetByName(const String& name);
@ -63,8 +64,6 @@ public:
void RegisterTopicHandler(const String& topic, const function<Callback>& callback); void RegisterTopicHandler(const String& topic, const function<Callback>& callback);
void UnregisterTopicHandler(const String& topic, const function<Callback>& callback); void UnregisterTopicHandler(const String& topic, const function<Callback>& callback);
virtual void OnAttributeChanged(const String& name, const Value& oldValue);
String GetNode(void) const; String GetNode(void) const;
String GetService(void) const; String GetService(void) const;
@ -73,9 +72,6 @@ public:
static signals2::signal<void (const Endpoint::Ptr&)> OnConnected; static signals2::signal<void (const Endpoint::Ptr&)> OnConnected;
static signals2::signal<void (const Endpoint::Ptr&)> OnDisconnected; static signals2::signal<void (const Endpoint::Ptr&)> OnDisconnected;
static signals2::signal<void (const Endpoint::Ptr&, const String& topic)> OnSubscriptionRegistered;
static signals2::signal<void (const Endpoint::Ptr&, const String& topic)> OnSubscriptionUnregistered;
private: private:
Attribute<bool> m_Local; Attribute<bool> m_Local;
Attribute<Dictionary::Ptr> m_Subscriptions; Attribute<Dictionary::Ptr> m_Subscriptions;