mirror of
https://github.com/Icinga/icinga2.git
synced 2025-07-26 07:04:37 +02:00
Merge pull request #9627 from Icinga/namespace-shared-mutex
Namespace: use rwlock and disable read locking after freeze
This commit is contained in:
commit
e38a907a7e
@ -280,17 +280,6 @@ static int Main()
|
|||||||
#endif /* RLIMIT_STACK */
|
#endif /* RLIMIT_STACK */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate additional global constants. */
|
|
||||||
ScriptGlobal::Set("System.PlatformKernel", Utility::GetPlatformKernel(), true);
|
|
||||||
ScriptGlobal::Set("System.PlatformKernelVersion", Utility::GetPlatformKernelVersion(), true);
|
|
||||||
ScriptGlobal::Set("System.PlatformName", Utility::GetPlatformName(), true);
|
|
||||||
ScriptGlobal::Set("System.PlatformVersion", Utility::GetPlatformVersion(), true);
|
|
||||||
ScriptGlobal::Set("System.PlatformArchitecture", Utility::GetPlatformArchitecture(), true);
|
|
||||||
|
|
||||||
ScriptGlobal::Set("System.BuildHostName", ICINGA_BUILD_HOST_NAME, true);
|
|
||||||
ScriptGlobal::Set("System.BuildCompilerName", ICINGA_BUILD_COMPILER_NAME, true);
|
|
||||||
ScriptGlobal::Set("System.BuildCompilerVersion", ICINGA_BUILD_COMPILER_VERSION, true);
|
|
||||||
|
|
||||||
if (!autocomplete)
|
if (!autocomplete)
|
||||||
Application::SetResourceLimits();
|
Application::SetResourceLimits();
|
||||||
|
|
||||||
|
@ -60,28 +60,28 @@ private:
|
|||||||
INITIALIZE_ONCE_WITH_PRIORITY([]() { \
|
INITIALIZE_ONCE_WITH_PRIORITY([]() { \
|
||||||
Function::Ptr sf = new icinga::Function(#ns "#" #name, callback, String(args).Split(":"), false); \
|
Function::Ptr sf = new icinga::Function(#ns "#" #name, callback, String(args).Split(":"), false); \
|
||||||
Namespace::Ptr nsp = ScriptGlobal::Get(#ns); \
|
Namespace::Ptr nsp = ScriptGlobal::Get(#ns); \
|
||||||
nsp->SetAttribute(#name, new ConstEmbeddedNamespaceValue(sf)); \
|
nsp->Set(#name, sf, true); \
|
||||||
}, InitializePriority::RegisterFunctions)
|
}, InitializePriority::RegisterFunctions)
|
||||||
|
|
||||||
#define REGISTER_SAFE_FUNCTION(ns, name, callback, args) \
|
#define REGISTER_SAFE_FUNCTION(ns, name, callback, args) \
|
||||||
INITIALIZE_ONCE_WITH_PRIORITY([]() { \
|
INITIALIZE_ONCE_WITH_PRIORITY([]() { \
|
||||||
Function::Ptr sf = new icinga::Function(#ns "#" #name, callback, String(args).Split(":"), true); \
|
Function::Ptr sf = new icinga::Function(#ns "#" #name, callback, String(args).Split(":"), true); \
|
||||||
Namespace::Ptr nsp = ScriptGlobal::Get(#ns); \
|
Namespace::Ptr nsp = ScriptGlobal::Get(#ns); \
|
||||||
nsp->SetAttribute(#name, new ConstEmbeddedNamespaceValue(sf)); \
|
nsp->Set(#name, sf, true); \
|
||||||
}, InitializePriority::RegisterFunctions)
|
}, InitializePriority::RegisterFunctions)
|
||||||
|
|
||||||
#define REGISTER_FUNCTION_NONCONST(ns, name, callback, args) \
|
#define REGISTER_FUNCTION_NONCONST(ns, name, callback, args) \
|
||||||
INITIALIZE_ONCE_WITH_PRIORITY([]() { \
|
INITIALIZE_ONCE_WITH_PRIORITY([]() { \
|
||||||
Function::Ptr sf = new icinga::Function(#ns "#" #name, callback, String(args).Split(":"), false); \
|
Function::Ptr sf = new icinga::Function(#ns "#" #name, callback, String(args).Split(":"), false); \
|
||||||
Namespace::Ptr nsp = ScriptGlobal::Get(#ns); \
|
Namespace::Ptr nsp = ScriptGlobal::Get(#ns); \
|
||||||
nsp->SetAttribute(#name, new EmbeddedNamespaceValue(sf)); \
|
nsp->Set(#name, sf, false); \
|
||||||
}, InitializePriority::RegisterFunctions)
|
}, InitializePriority::RegisterFunctions)
|
||||||
|
|
||||||
#define REGISTER_SAFE_FUNCTION_NONCONST(ns, name, callback, args) \
|
#define REGISTER_SAFE_FUNCTION_NONCONST(ns, name, callback, args) \
|
||||||
INITIALIZE_ONCE_WITH_PRIORITY([]() { \
|
INITIALIZE_ONCE_WITH_PRIORITY([]() { \
|
||||||
Function::Ptr sf = new icinga::Function(#ns "#" #name, callback, String(args).Split(":"), true); \
|
Function::Ptr sf = new icinga::Function(#ns "#" #name, callback, String(args).Split(":"), true); \
|
||||||
Namespace::Ptr nsp = ScriptGlobal::Get(#ns); \
|
Namespace::Ptr nsp = ScriptGlobal::Get(#ns); \
|
||||||
nsp->SetAttribute(#name, new EmbeddedNamespaceValue(sf)); \
|
nsp->SetAttribute(#name, sf, false); \
|
||||||
}, InitializePriority::RegisterFunctions)
|
}, InitializePriority::RegisterFunctions)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ enum class InitializePriority {
|
|||||||
RegisterTypes,
|
RegisterTypes,
|
||||||
EvaluateConfigFragments,
|
EvaluateConfigFragments,
|
||||||
Default,
|
Default,
|
||||||
|
FreezeNamespaces,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define I2_TOKENPASTE(x, y) x ## y
|
#define I2_TOKENPASTE(x, y) x ## y
|
||||||
|
@ -24,5 +24,5 @@ INITIALIZE_ONCE([]() {
|
|||||||
jsonNS->Freeze();
|
jsonNS->Freeze();
|
||||||
|
|
||||||
Namespace::Ptr systemNS = ScriptGlobal::Get("System");
|
Namespace::Ptr systemNS = ScriptGlobal::Get("System");
|
||||||
systemNS->SetAttribute("Json", new ConstEmbeddedNamespaceValue(jsonNS));
|
systemNS->Set("Json", jsonNS, true);
|
||||||
});
|
});
|
||||||
|
@ -95,7 +95,7 @@ void EncodeNamespace(JsonEncoder<prettyPrint>& stateMachine, const Namespace::Pt
|
|||||||
ObjectLock olock(ns);
|
ObjectLock olock(ns);
|
||||||
for (const Namespace::Pair& kv : ns) {
|
for (const Namespace::Pair& kv : ns) {
|
||||||
stateMachine.Key(Utility::ValidateUTF8(kv.first));
|
stateMachine.Key(Utility::ValidateUTF8(kv.first));
|
||||||
Encode(stateMachine, kv.second->Get());
|
Encode(stateMachine, kv.second.Val);
|
||||||
}
|
}
|
||||||
|
|
||||||
stateMachine.EndObject();
|
stateMachine.EndObject();
|
||||||
|
@ -40,11 +40,11 @@ std::mutex Logger::m_UpdateMinLogSeverityMutex;
|
|||||||
Atomic<LogSeverity> Logger::m_MinLogSeverity (LogDebug);
|
Atomic<LogSeverity> Logger::m_MinLogSeverity (LogDebug);
|
||||||
|
|
||||||
INITIALIZE_ONCE([]() {
|
INITIALIZE_ONCE([]() {
|
||||||
ScriptGlobal::Set("System.LogDebug", LogDebug, true);
|
ScriptGlobal::Set("System.LogDebug", LogDebug);
|
||||||
ScriptGlobal::Set("System.LogNotice", LogNotice, true);
|
ScriptGlobal::Set("System.LogNotice", LogNotice);
|
||||||
ScriptGlobal::Set("System.LogInformation", LogInformation, true);
|
ScriptGlobal::Set("System.LogInformation", LogInformation);
|
||||||
ScriptGlobal::Set("System.LogWarning", LogWarning, true);
|
ScriptGlobal::Set("System.LogWarning", LogWarning);
|
||||||
ScriptGlobal::Set("System.LogCritical", LogCritical, true);
|
ScriptGlobal::Set("System.LogCritical", LogCritical);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -180,5 +180,5 @@ INITIALIZE_ONCE([]() {
|
|||||||
mathNS->Freeze();
|
mathNS->Freeze();
|
||||||
|
|
||||||
Namespace::Ptr systemNS = ScriptGlobal::Get("System");
|
Namespace::Ptr systemNS = ScriptGlobal::Get("System");
|
||||||
systemNS->SetAttribute("Math", new ConstEmbeddedNamespaceValue(mathNS));
|
systemNS->Set("Math", mathNS, true);
|
||||||
});
|
});
|
||||||
|
@ -63,7 +63,7 @@ static Array::Ptr NamespaceValues()
|
|||||||
ArrayData values;
|
ArrayData values;
|
||||||
ObjectLock olock(self);
|
ObjectLock olock(self);
|
||||||
for (const Namespace::Pair& kv : self) {
|
for (const Namespace::Pair& kv : self) {
|
||||||
values.push_back(kv.second->Get());
|
values.push_back(kv.second.Val);
|
||||||
}
|
}
|
||||||
return new Array(std::move(values));
|
return new Array(std::move(values));
|
||||||
}
|
}
|
||||||
|
@ -25,32 +25,47 @@ Namespace::Namespace(bool constValues)
|
|||||||
|
|
||||||
Value Namespace::Get(const String& field) const
|
Value Namespace::Get(const String& field) const
|
||||||
{
|
{
|
||||||
ObjectLock olock(this);
|
|
||||||
|
|
||||||
Value value;
|
Value value;
|
||||||
if (!GetOwnField(field, &value))
|
if (!Get(field, &value))
|
||||||
BOOST_THROW_EXCEPTION(ScriptError("Namespace does not contain field '" + field + "'"));
|
BOOST_THROW_EXCEPTION(ScriptError("Namespace does not contain field '" + field + "'"));
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Namespace::Get(const String& field, Value *value) const
|
bool Namespace::Get(const String& field, Value *value) const
|
||||||
{
|
{
|
||||||
ObjectLock olock(this);
|
auto lock(ReadLockUnlessFrozen());
|
||||||
|
|
||||||
auto nsVal = GetAttribute(field);
|
auto nsVal = m_Data.find(field);
|
||||||
|
|
||||||
if (!nsVal)
|
if (nsVal == m_Data.end()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
*value = nsVal->Get(DebugInfo());
|
*value = nsVal->second.Val;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Namespace::Set(const String& field, const Value& value, bool overrideFrozen)
|
void Namespace::Set(const String& field, const Value& value, bool isConst, const DebugInfo& debugInfo)
|
||||||
{
|
{
|
||||||
ObjectLock olock(this);
|
ObjectLock olock(this);
|
||||||
|
|
||||||
return SetFieldByName(field, value, overrideFrozen, DebugInfo());
|
if (m_Frozen) {
|
||||||
|
BOOST_THROW_EXCEPTION(ScriptError("Namespace is read-only and must not be modified.", debugInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_lock<decltype(m_DataMutex)> dlock (m_DataMutex);
|
||||||
|
|
||||||
|
auto nsVal = m_Data.find(field);
|
||||||
|
|
||||||
|
if (nsVal == m_Data.end()) {
|
||||||
|
m_Data[field] = NamespaceValue{value, isConst};
|
||||||
|
} else {
|
||||||
|
if (nsVal->second.Const) {
|
||||||
|
BOOST_THROW_EXCEPTION(ScriptError("Constant must not be modified.", debugInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
nsVal->second.Val = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,39 +75,43 @@ void Namespace::Set(const String& field, const Value& value, bool overrideFrozen
|
|||||||
*/
|
*/
|
||||||
size_t Namespace::GetLength() const
|
size_t Namespace::GetLength() const
|
||||||
{
|
{
|
||||||
ObjectLock olock(this);
|
auto lock(ReadLockUnlessFrozen());
|
||||||
|
|
||||||
return m_Data.size();
|
return m_Data.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Namespace::Contains(const String& field) const
|
bool Namespace::Contains(const String& field) const
|
||||||
{
|
{
|
||||||
ObjectLock olock(this);
|
auto lock (ReadLockUnlessFrozen());
|
||||||
|
|
||||||
return HasOwnField(field);
|
return m_Data.find(field) != m_Data.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Namespace::Remove(const String& field, bool overrideFrozen)
|
void Namespace::Remove(const String& field)
|
||||||
{
|
{
|
||||||
ObjectLock olock(this);
|
ObjectLock olock(this);
|
||||||
|
|
||||||
if (m_Frozen && !overrideFrozen) {
|
if (m_Frozen) {
|
||||||
BOOST_THROW_EXCEPTION(ScriptError("Namespace is read-only and must not be modified."));
|
BOOST_THROW_EXCEPTION(ScriptError("Namespace is read-only and must not be modified."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!overrideFrozen) {
|
std::unique_lock<decltype(m_DataMutex)> dlock (m_DataMutex);
|
||||||
auto attr = GetAttribute(field);
|
|
||||||
|
|
||||||
if (dynamic_pointer_cast<ConstEmbeddedNamespaceValue>(attr)) {
|
auto it = m_Data.find(field);
|
||||||
|
|
||||||
|
if (it == m_Data.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it->second.Const) {
|
||||||
BOOST_THROW_EXCEPTION(ScriptError("Constants must not be removed."));
|
BOOST_THROW_EXCEPTION(ScriptError("Constants must not be removed."));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
RemoveAttribute(field);
|
m_Data.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Freeze the namespace, preventing further updates unless overrideFrozen is set.
|
* Freeze the namespace, preventing further updates.
|
||||||
*
|
*
|
||||||
* This only prevents inserting, replacing or deleting values from the namespace. This operation has no effect on
|
* This only prevents inserting, replacing or deleting values from the namespace. This operation has no effect on
|
||||||
* objects referenced by the values, these remain mutable if they were before.
|
* objects referenced by the values, these remain mutable if they were before.
|
||||||
@ -103,111 +122,45 @@ void Namespace::Freeze() {
|
|||||||
m_Frozen = true;
|
m_Frozen = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Namespace::RemoveAttribute(const String& field)
|
std::shared_lock<std::shared_timed_mutex> Namespace::ReadLockUnlessFrozen() const
|
||||||
{
|
{
|
||||||
ObjectLock olock(this);
|
if (m_Frozen.load(std::memory_order_relaxed)) {
|
||||||
|
return std::shared_lock<std::shared_timed_mutex>();
|
||||||
Namespace::Iterator it;
|
} else {
|
||||||
it = m_Data.find(field);
|
return std::shared_lock<std::shared_timed_mutex>(m_DataMutex);
|
||||||
|
|
||||||
if (it == m_Data.end())
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_Data.erase(it);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NamespaceValue::Ptr Namespace::GetAttribute(const String& key) const
|
|
||||||
{
|
|
||||||
ObjectLock olock(this);
|
|
||||||
|
|
||||||
auto it = m_Data.find(key);
|
|
||||||
|
|
||||||
if (it == m_Data.end())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Namespace::SetAttribute(const String& key, const NamespaceValue::Ptr& nsVal)
|
|
||||||
{
|
|
||||||
ObjectLock olock(this);
|
|
||||||
|
|
||||||
m_Data[key] = nsVal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Value Namespace::GetFieldByName(const String& field, bool, const DebugInfo& debugInfo) const
|
Value Namespace::GetFieldByName(const String& field, bool, const DebugInfo& debugInfo) const
|
||||||
{
|
{
|
||||||
ObjectLock olock(this);
|
auto lock (ReadLockUnlessFrozen());
|
||||||
|
|
||||||
auto nsVal = GetAttribute(field);
|
auto nsVal = m_Data.find(field);
|
||||||
|
|
||||||
if (nsVal)
|
if (nsVal != m_Data.end())
|
||||||
return nsVal->Get(debugInfo);
|
return nsVal->second.Val;
|
||||||
else
|
else
|
||||||
return GetPrototypeField(const_cast<Namespace *>(this), field, false, debugInfo); /* Ignore indexer not found errors similar to the Dictionary class. */
|
return GetPrototypeField(const_cast<Namespace *>(this), field, false, debugInfo); /* Ignore indexer not found errors similar to the Dictionary class. */
|
||||||
}
|
}
|
||||||
|
|
||||||
void Namespace::SetFieldByName(const String& field, const Value& value, bool overrideFrozen, const DebugInfo& debugInfo)
|
void Namespace::SetFieldByName(const String& field, const Value& value, bool overrideFrozen, const DebugInfo& debugInfo)
|
||||||
{
|
{
|
||||||
ObjectLock olock(this);
|
// The override frozen parameter is mandated by the interface but ignored here. If the namespace is frozen, this
|
||||||
|
// disables locking for read operations, so it must not be modified again to ensure the consistency of the internal
|
||||||
|
// data structures.
|
||||||
|
(void) overrideFrozen;
|
||||||
|
|
||||||
auto nsVal = GetAttribute(field);
|
Set(field, value, false, debugInfo);
|
||||||
|
|
||||||
if (!nsVal) {
|
|
||||||
if (m_Frozen && !overrideFrozen) {
|
|
||||||
BOOST_THROW_EXCEPTION(ScriptError("Namespace is read-only and must not be modified.", debugInfo));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_ConstValues) {
|
|
||||||
SetAttribute(field, new ConstEmbeddedNamespaceValue(value));
|
|
||||||
} else {
|
|
||||||
SetAttribute(field, new EmbeddedNamespaceValue(value));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
nsVal->Set(value, overrideFrozen, debugInfo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Namespace::HasOwnField(const String& field) const
|
bool Namespace::HasOwnField(const String& field) const
|
||||||
{
|
{
|
||||||
ObjectLock olock(this);
|
return Contains(field);
|
||||||
|
|
||||||
return GetAttribute(field) != nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Namespace::GetOwnField(const String& field, Value *result) const
|
bool Namespace::GetOwnField(const String& field, Value *result) const
|
||||||
{
|
{
|
||||||
ObjectLock olock(this);
|
return Get(field, result);
|
||||||
|
|
||||||
auto nsVal = GetAttribute(field);
|
|
||||||
|
|
||||||
if (!nsVal)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
*result = nsVal->Get(DebugInfo());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
EmbeddedNamespaceValue::EmbeddedNamespaceValue(const Value& value)
|
|
||||||
: m_Value(value)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
Value EmbeddedNamespaceValue::Get(const DebugInfo& debugInfo) const
|
|
||||||
{
|
|
||||||
return m_Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmbeddedNamespaceValue::Set(const Value& value, bool, const DebugInfo&)
|
|
||||||
{
|
|
||||||
m_Value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConstEmbeddedNamespaceValue::Set(const Value& value, bool overrideFrozen, const DebugInfo& debugInfo)
|
|
||||||
{
|
|
||||||
if (!overrideFrozen)
|
|
||||||
BOOST_THROW_EXCEPTION(ScriptError("Constant must not be modified.", debugInfo));
|
|
||||||
|
|
||||||
EmbeddedNamespaceValue::Set(value, overrideFrozen, debugInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Namespace::Iterator Namespace::Begin()
|
Namespace::Iterator Namespace::Begin()
|
||||||
|
@ -8,42 +8,52 @@
|
|||||||
#include "base/shared-object.hpp"
|
#include "base/shared-object.hpp"
|
||||||
#include "base/value.hpp"
|
#include "base/value.hpp"
|
||||||
#include "base/debuginfo.hpp"
|
#include "base/debuginfo.hpp"
|
||||||
|
#include <atomic>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <shared_mutex>
|
||||||
|
|
||||||
namespace icinga
|
namespace icinga
|
||||||
{
|
{
|
||||||
|
|
||||||
struct NamespaceValue : public SharedObject
|
struct NamespaceValue
|
||||||
{
|
{
|
||||||
DECLARE_PTR_TYPEDEFS(NamespaceValue);
|
Value Val;
|
||||||
|
bool Const;
|
||||||
virtual Value Get(const DebugInfo& debugInfo = DebugInfo()) const = 0;
|
|
||||||
virtual void Set(const Value& value, bool overrideFrozen, const DebugInfo& debugInfo = DebugInfo()) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EmbeddedNamespaceValue : public NamespaceValue
|
|
||||||
{
|
|
||||||
EmbeddedNamespaceValue(const Value& value);
|
|
||||||
|
|
||||||
Value Get(const DebugInfo& debugInfo) const override;
|
|
||||||
void Set(const Value& value, bool overrideFrozen, const DebugInfo& debugInfo) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Value m_Value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ConstEmbeddedNamespaceValue : public EmbeddedNamespaceValue
|
|
||||||
{
|
|
||||||
using EmbeddedNamespaceValue::EmbeddedNamespaceValue;
|
|
||||||
|
|
||||||
void Set(const Value& value, bool overrideFrozen, const DebugInfo& debugInfo) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A namespace.
|
* A namespace.
|
||||||
*
|
*
|
||||||
|
* ## External Locking
|
||||||
|
*
|
||||||
|
* Synchronization is handled internally, so almost all functions are safe for concurrent use without external locking.
|
||||||
|
* The only exception to this are functions returning an iterator. To use these, the caller has to acquire an ObjectLock
|
||||||
|
* on the namespace. The iterators only remain valid for as long as that ObjectLock is held. Note that this also
|
||||||
|
* includes range-based for loops.
|
||||||
|
*
|
||||||
|
* If consistency across multiple operations is required, an ObjectLock must also be acquired to prevent concurrent
|
||||||
|
* modifications.
|
||||||
|
*
|
||||||
|
* ## Internal Locking
|
||||||
|
*
|
||||||
|
* Two mutex objects are involved in locking a namespace: the recursive mutex inherited from the Object class that is
|
||||||
|
* acquired and released using the ObjectLock class and the m_DataMutex shared mutex contained directly in the
|
||||||
|
* Namespace class. The ObjectLock is used to synchronize multiple write operations against each other. The shared mutex
|
||||||
|
* is only used to ensure the consistency of the m_Data data structure.
|
||||||
|
*
|
||||||
|
* Read operations must acquire a shared lock on m_DataMutex. This prevents concurrent writes to that data structure
|
||||||
|
* but still allows concurrent reads.
|
||||||
|
*
|
||||||
|
* Write operations must first obtain an ObjectLock and then a shared lock on m_DataMutex. This order is important for
|
||||||
|
* preventing deadlocks. The ObjectLock prevents concurrent write operations while the shared lock prevents concurrent
|
||||||
|
* read operations.
|
||||||
|
*
|
||||||
|
* External read access to iterators is synchronized by the caller holding an ObjectLock. This ensures no concurrent
|
||||||
|
* write operations as these require the ObjectLock but still allows concurrent reads as m_DataMutex is not locked.
|
||||||
|
*
|
||||||
* @ingroup base
|
* @ingroup base
|
||||||
*/
|
*/
|
||||||
class Namespace final : public Object
|
class Namespace final : public Object
|
||||||
@ -51,23 +61,19 @@ class Namespace final : public Object
|
|||||||
public:
|
public:
|
||||||
DECLARE_OBJECT(Namespace);
|
DECLARE_OBJECT(Namespace);
|
||||||
|
|
||||||
typedef std::map<String, NamespaceValue::Ptr>::iterator Iterator;
|
typedef std::map<String, NamespaceValue>::iterator Iterator;
|
||||||
|
|
||||||
typedef std::map<String, NamespaceValue::Ptr>::value_type Pair;
|
typedef std::map<String, NamespaceValue>::value_type Pair;
|
||||||
|
|
||||||
explicit Namespace(bool constValues = false);
|
explicit Namespace(bool constValues = false);
|
||||||
|
|
||||||
Value Get(const String& field) const;
|
Value Get(const String& field) const;
|
||||||
bool Get(const String& field, Value *value) const;
|
bool Get(const String& field, Value *value) const;
|
||||||
void Set(const String& field, const Value& value, bool overrideFrozen = false);
|
void Set(const String& field, const Value& value, bool isConst = false, const DebugInfo& debugInfo = DebugInfo());
|
||||||
bool Contains(const String& field) const;
|
bool Contains(const String& field) const;
|
||||||
void Remove(const String& field, bool overrideFrozen = false);
|
void Remove(const String& field);
|
||||||
void Freeze();
|
void Freeze();
|
||||||
|
|
||||||
NamespaceValue::Ptr GetAttribute(const String& field) const;
|
|
||||||
void SetAttribute(const String& field, const NamespaceValue::Ptr& nsVal);
|
|
||||||
void RemoveAttribute(const String& field);
|
|
||||||
|
|
||||||
Iterator Begin();
|
Iterator Begin();
|
||||||
Iterator End();
|
Iterator End();
|
||||||
|
|
||||||
@ -81,9 +87,12 @@ public:
|
|||||||
static Object::Ptr GetPrototype();
|
static Object::Ptr GetPrototype();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<String, NamespaceValue::Ptr> m_Data;
|
std::shared_lock<std::shared_timed_mutex> ReadLockUnlessFrozen() const;
|
||||||
|
|
||||||
|
std::map<String, NamespaceValue> m_Data;
|
||||||
|
mutable std::shared_timed_mutex m_DataMutex;
|
||||||
bool m_ConstValues;
|
bool m_ConstValues;
|
||||||
bool m_Frozen;
|
std::atomic<bool> m_Frozen;
|
||||||
};
|
};
|
||||||
|
|
||||||
Namespace::Iterator begin(const Namespace::Ptr& x);
|
Namespace::Iterator begin(const Namespace::Ptr& x);
|
||||||
|
@ -5,12 +5,13 @@
|
|||||||
#include "base/namespace.hpp"
|
#include "base/namespace.hpp"
|
||||||
#include "base/exception.hpp"
|
#include "base/exception.hpp"
|
||||||
#include "base/configuration.hpp"
|
#include "base/configuration.hpp"
|
||||||
|
#include "base/utility.hpp"
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
boost::thread_specific_ptr<std::stack<ScriptFrame *> > ScriptFrame::m_ScriptFrames;
|
boost::thread_specific_ptr<std::stack<ScriptFrame *> > ScriptFrame::m_ScriptFrames;
|
||||||
|
|
||||||
static Namespace::Ptr l_InternalNS;
|
static Namespace::Ptr l_SystemNS, l_TypesNS, l_StatsNS, l_InternalNS;
|
||||||
|
|
||||||
/* Ensure that this gets called with highest priority
|
/* Ensure that this gets called with highest priority
|
||||||
* and wins against other static initializers in lib/icinga, etc.
|
* and wins against other static initializers in lib/icinga, etc.
|
||||||
@ -19,27 +20,35 @@ static Namespace::Ptr l_InternalNS;
|
|||||||
INITIALIZE_ONCE_WITH_PRIORITY([]() {
|
INITIALIZE_ONCE_WITH_PRIORITY([]() {
|
||||||
Namespace::Ptr globalNS = ScriptGlobal::GetGlobals();
|
Namespace::Ptr globalNS = ScriptGlobal::GetGlobals();
|
||||||
|
|
||||||
Namespace::Ptr systemNS = new Namespace(true);
|
l_SystemNS = new Namespace(true);
|
||||||
systemNS->Freeze();
|
l_SystemNS->Set("PlatformKernel", Utility::GetPlatformKernel());
|
||||||
globalNS->SetAttribute("System", new ConstEmbeddedNamespaceValue(systemNS));
|
l_SystemNS->Set("PlatformKernelVersion", Utility::GetPlatformKernelVersion());
|
||||||
|
l_SystemNS->Set("PlatformName", Utility::GetPlatformName());
|
||||||
|
l_SystemNS->Set("PlatformVersion", Utility::GetPlatformVersion());
|
||||||
|
l_SystemNS->Set("PlatformArchitecture", Utility::GetPlatformArchitecture());
|
||||||
|
l_SystemNS->Set("BuildHostName", ICINGA_BUILD_HOST_NAME);
|
||||||
|
l_SystemNS->Set("BuildCompilerName", ICINGA_BUILD_COMPILER_NAME);
|
||||||
|
l_SystemNS->Set("BuildCompilerVersion", ICINGA_BUILD_COMPILER_VERSION);
|
||||||
|
globalNS->Set("System", l_SystemNS, true);
|
||||||
|
|
||||||
systemNS->SetAttribute("Configuration", new EmbeddedNamespaceValue(new Configuration()));
|
l_SystemNS->Set("Configuration", new Configuration());
|
||||||
|
|
||||||
Namespace::Ptr typesNS = new Namespace(true);
|
l_TypesNS = new Namespace(true);
|
||||||
typesNS->Freeze();
|
globalNS->Set("Types", l_TypesNS, true);
|
||||||
globalNS->SetAttribute("Types", new ConstEmbeddedNamespaceValue(typesNS));
|
|
||||||
|
|
||||||
Namespace::Ptr statsNS = new Namespace(true);
|
l_StatsNS = new Namespace(true);
|
||||||
statsNS->Freeze();
|
globalNS->Set("StatsFunctions", l_StatsNS, true);
|
||||||
globalNS->SetAttribute("StatsFunctions", new ConstEmbeddedNamespaceValue(statsNS));
|
|
||||||
|
|
||||||
l_InternalNS = new Namespace(true);
|
l_InternalNS = new Namespace(true);
|
||||||
globalNS->SetAttribute("Internal", new ConstEmbeddedNamespaceValue(l_InternalNS));
|
globalNS->Set("Internal", l_InternalNS, true);
|
||||||
}, InitializePriority::CreateNamespaces);
|
}, InitializePriority::CreateNamespaces);
|
||||||
|
|
||||||
INITIALIZE_ONCE([]() {
|
INITIALIZE_ONCE_WITH_PRIORITY([]() {
|
||||||
|
l_SystemNS->Freeze();
|
||||||
|
l_TypesNS->Freeze();
|
||||||
|
l_StatsNS->Freeze();
|
||||||
l_InternalNS->Freeze();
|
l_InternalNS->Freeze();
|
||||||
});
|
}, InitializePriority::FreezeNamespaces);
|
||||||
|
|
||||||
ScriptFrame::ScriptFrame(bool allocLocals)
|
ScriptFrame::ScriptFrame(bool allocLocals)
|
||||||
: Locals(allocLocals ? new Dictionary() : nullptr), Self(ScriptGlobal::GetGlobals()), Sandboxed(false), Depth(0)
|
: Locals(allocLocals ? new Dictionary() : nullptr), Self(ScriptGlobal::GetGlobals()), Sandboxed(false), Depth(0)
|
||||||
|
@ -65,7 +65,7 @@ void ScriptGlobal::Set(const String& name, const Value& value, bool overrideFroz
|
|||||||
|
|
||||||
void ScriptGlobal::SetConst(const String& name, const Value& value)
|
void ScriptGlobal::SetConst(const String& name, const Value& value)
|
||||||
{
|
{
|
||||||
GetGlobals()->SetAttribute(name, new ConstEmbeddedNamespaceValue(value));
|
GetGlobals()->Set(name, value, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScriptGlobal::Exists(const String& name)
|
bool ScriptGlobal::Exists(const String& name)
|
||||||
@ -93,7 +93,7 @@ void ScriptGlobal::WriteToFile(const String& filename)
|
|||||||
|
|
||||||
ObjectLock olock(m_Globals);
|
ObjectLock olock(m_Globals);
|
||||||
for (const Namespace::Pair& kv : m_Globals) {
|
for (const Namespace::Pair& kv : m_Globals) {
|
||||||
Value value = kv.second->Get();
|
Value value = kv.second.Val;
|
||||||
|
|
||||||
if (value.IsObject())
|
if (value.IsObject())
|
||||||
value = Convert::ToString(value);
|
value = Convert::ToString(value);
|
||||||
|
@ -71,11 +71,11 @@ enum MatchType
|
|||||||
|
|
||||||
void ScriptUtils::StaticInitialize()
|
void ScriptUtils::StaticInitialize()
|
||||||
{
|
{
|
||||||
ScriptGlobal::Set("System.MatchAll", MatchAll, true);
|
ScriptGlobal::Set("System.MatchAll", MatchAll);
|
||||||
ScriptGlobal::Set("System.MatchAny", MatchAny, true);
|
ScriptGlobal::Set("System.MatchAny", MatchAny);
|
||||||
|
|
||||||
ScriptGlobal::Set("System.GlobFile", GlobFile, true);
|
ScriptGlobal::Set("System.GlobFile", GlobFile);
|
||||||
ScriptGlobal::Set("System.GlobDirectory", GlobDirectory, true);
|
ScriptGlobal::Set("System.GlobDirectory", GlobDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
String ScriptUtils::CastString(const Value& value)
|
String ScriptUtils::CastString(const Value& value)
|
||||||
|
@ -131,7 +131,7 @@ static Dictionary::Ptr SerializeNamespace(const Namespace::Ptr& input, int attri
|
|||||||
ObjectLock olock(input);
|
ObjectLock olock(input);
|
||||||
|
|
||||||
for (const Namespace::Pair& kv : input) {
|
for (const Namespace::Pair& kv : input) {
|
||||||
Value val = kv.second->Get();
|
Value val = kv.second.Val;
|
||||||
stack.Push(kv.first, val);
|
stack.Push(kv.first, val);
|
||||||
|
|
||||||
auto serialized (SerializeInternal(val, attributeTypes, stack, dryRun));
|
auto serialized (SerializeInternal(val, attributeTypes, stack, dryRun));
|
||||||
|
@ -19,26 +19,26 @@ std::map<String, int> SyslogHelper::m_FacilityMap;
|
|||||||
|
|
||||||
void SyslogHelper::StaticInitialize()
|
void SyslogHelper::StaticInitialize()
|
||||||
{
|
{
|
||||||
ScriptGlobal::Set("System.FacilityAuth", "LOG_AUTH", true);
|
ScriptGlobal::Set("System.FacilityAuth", "LOG_AUTH");
|
||||||
ScriptGlobal::Set("System.FacilityAuthPriv", "LOG_AUTHPRIV", true);
|
ScriptGlobal::Set("System.FacilityAuthPriv", "LOG_AUTHPRIV");
|
||||||
ScriptGlobal::Set("System.FacilityCron", "LOG_CRON", true);
|
ScriptGlobal::Set("System.FacilityCron", "LOG_CRON");
|
||||||
ScriptGlobal::Set("System.FacilityDaemon", "LOG_DAEMON", true);
|
ScriptGlobal::Set("System.FacilityDaemon", "LOG_DAEMON");
|
||||||
ScriptGlobal::Set("System.FacilityFtp", "LOG_FTP", true);
|
ScriptGlobal::Set("System.FacilityFtp", "LOG_FTP");
|
||||||
ScriptGlobal::Set("System.FacilityKern", "LOG_KERN", true);
|
ScriptGlobal::Set("System.FacilityKern", "LOG_KERN");
|
||||||
ScriptGlobal::Set("System.FacilityLocal0", "LOG_LOCAL0", true);
|
ScriptGlobal::Set("System.FacilityLocal0", "LOG_LOCAL0");
|
||||||
ScriptGlobal::Set("System.FacilityLocal1", "LOG_LOCAL1", true);
|
ScriptGlobal::Set("System.FacilityLocal1", "LOG_LOCAL1");
|
||||||
ScriptGlobal::Set("System.FacilityLocal2", "LOG_LOCAL2", true);
|
ScriptGlobal::Set("System.FacilityLocal2", "LOG_LOCAL2");
|
||||||
ScriptGlobal::Set("System.FacilityLocal3", "LOG_LOCAL3", true);
|
ScriptGlobal::Set("System.FacilityLocal3", "LOG_LOCAL3");
|
||||||
ScriptGlobal::Set("System.FacilityLocal4", "LOG_LOCAL4", true);
|
ScriptGlobal::Set("System.FacilityLocal4", "LOG_LOCAL4");
|
||||||
ScriptGlobal::Set("System.FacilityLocal5", "LOG_LOCAL5", true);
|
ScriptGlobal::Set("System.FacilityLocal5", "LOG_LOCAL5");
|
||||||
ScriptGlobal::Set("System.FacilityLocal6", "LOG_LOCAL6", true);
|
ScriptGlobal::Set("System.FacilityLocal6", "LOG_LOCAL6");
|
||||||
ScriptGlobal::Set("System.FacilityLocal7", "LOG_LOCAL7", true);
|
ScriptGlobal::Set("System.FacilityLocal7", "LOG_LOCAL7");
|
||||||
ScriptGlobal::Set("System.FacilityLpr", "LOG_LPR", true);
|
ScriptGlobal::Set("System.FacilityLpr", "LOG_LPR");
|
||||||
ScriptGlobal::Set("System.FacilityMail", "LOG_MAIL", true);
|
ScriptGlobal::Set("System.FacilityMail", "LOG_MAIL");
|
||||||
ScriptGlobal::Set("System.FacilityNews", "LOG_NEWS", true);
|
ScriptGlobal::Set("System.FacilityNews", "LOG_NEWS");
|
||||||
ScriptGlobal::Set("System.FacilitySyslog", "LOG_SYSLOG", true);
|
ScriptGlobal::Set("System.FacilitySyslog", "LOG_SYSLOG");
|
||||||
ScriptGlobal::Set("System.FacilityUser", "LOG_USER", true);
|
ScriptGlobal::Set("System.FacilityUser", "LOG_USER");
|
||||||
ScriptGlobal::Set("System.FacilityUucp", "LOG_UUCP", true);
|
ScriptGlobal::Set("System.FacilityUucp", "LOG_UUCP");
|
||||||
|
|
||||||
m_FacilityMap["LOG_AUTH"] = LOG_AUTH;
|
m_FacilityMap["LOG_AUTH"] = LOG_AUTH;
|
||||||
m_FacilityMap["LOG_AUTHPRIV"] = LOG_AUTHPRIV;
|
m_FacilityMap["LOG_AUTHPRIV"] = LOG_AUTHPRIV;
|
||||||
|
@ -24,7 +24,7 @@ String Type::ToString() const
|
|||||||
|
|
||||||
void Type::Register(const Type::Ptr& type)
|
void Type::Register(const Type::Ptr& type)
|
||||||
{
|
{
|
||||||
ScriptGlobal::Set("Types." + type->GetName(), type, true);
|
ScriptGlobal::Set("Types." + type->GetName(), type);
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::Ptr Type::GetByName(const String& name)
|
Type::Ptr Type::GetByName(const String& name)
|
||||||
@ -54,7 +54,7 @@ std::vector<Type::Ptr> Type::GetAllTypes()
|
|||||||
ObjectLock olock(typesNS);
|
ObjectLock olock(typesNS);
|
||||||
|
|
||||||
for (const Namespace::Pair& kv : typesNS) {
|
for (const Namespace::Pair& kv : typesNS) {
|
||||||
Value value = kv.second->Get();
|
Value value = kv.second.Val;
|
||||||
|
|
||||||
if (value.IsObjectType<Type>())
|
if (value.IsObjectType<Type>())
|
||||||
types.push_back(value);
|
types.push_back(value);
|
||||||
|
@ -675,20 +675,11 @@ ExpressionResult SetConstExpression::DoEvaluate(ScriptFrame& frame, DebugHint *d
|
|||||||
{
|
{
|
||||||
auto globals = ScriptGlobal::GetGlobals();
|
auto globals = ScriptGlobal::GetGlobals();
|
||||||
|
|
||||||
auto attr = globals->GetAttribute(m_Name);
|
|
||||||
|
|
||||||
if (dynamic_pointer_cast<ConstEmbeddedNamespaceValue>(attr)) {
|
|
||||||
std::ostringstream msgbuf;
|
|
||||||
msgbuf << "Value for constant '" << m_Name << "' was modified. This behaviour is deprecated.\n";
|
|
||||||
ShowCodeLocation(msgbuf, GetDebugInfo(), false);
|
|
||||||
Log(LogWarning, msgbuf.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
ExpressionResult operandres = m_Operand->Evaluate(frame);
|
ExpressionResult operandres = m_Operand->Evaluate(frame);
|
||||||
CHECK_RESULT(operandres);
|
CHECK_RESULT(operandres);
|
||||||
Value operand = operandres.GetValue();
|
Value operand = operandres.GetValue();
|
||||||
|
|
||||||
globals->SetAttribute(m_Name, new ConstEmbeddedNamespaceValue(operand));
|
globals->Set(m_Name, operand, true);
|
||||||
|
|
||||||
return Empty;
|
return Empty;
|
||||||
}
|
}
|
||||||
|
@ -12,22 +12,22 @@ std::map<String, int> DbQuery::m_CategoryFilterMap;
|
|||||||
|
|
||||||
void DbQuery::StaticInitialize()
|
void DbQuery::StaticInitialize()
|
||||||
{
|
{
|
||||||
ScriptGlobal::Set("Icinga.DbCatConfig", DbCatConfig, true);
|
ScriptGlobal::Set("Icinga.DbCatConfig", DbCatConfig);
|
||||||
ScriptGlobal::Set("Icinga.DbCatState", DbCatState, true);
|
ScriptGlobal::Set("Icinga.DbCatState", DbCatState);
|
||||||
ScriptGlobal::Set("Icinga.DbCatAcknowledgement", DbCatAcknowledgement, true);
|
ScriptGlobal::Set("Icinga.DbCatAcknowledgement", DbCatAcknowledgement);
|
||||||
ScriptGlobal::Set("Icinga.DbCatComment", DbCatComment, true);
|
ScriptGlobal::Set("Icinga.DbCatComment", DbCatComment);
|
||||||
ScriptGlobal::Set("Icinga.DbCatDowntime", DbCatDowntime, true);
|
ScriptGlobal::Set("Icinga.DbCatDowntime", DbCatDowntime);
|
||||||
ScriptGlobal::Set("Icinga.DbCatEventHandler", DbCatEventHandler, true);
|
ScriptGlobal::Set("Icinga.DbCatEventHandler", DbCatEventHandler);
|
||||||
ScriptGlobal::Set("Icinga.DbCatExternalCommand", DbCatExternalCommand, true);
|
ScriptGlobal::Set("Icinga.DbCatExternalCommand", DbCatExternalCommand);
|
||||||
ScriptGlobal::Set("Icinga.DbCatFlapping", DbCatFlapping, true);
|
ScriptGlobal::Set("Icinga.DbCatFlapping", DbCatFlapping);
|
||||||
ScriptGlobal::Set("Icinga.DbCatCheck", DbCatCheck, true);
|
ScriptGlobal::Set("Icinga.DbCatCheck", DbCatCheck);
|
||||||
ScriptGlobal::Set("Icinga.DbCatLog", DbCatLog, true);
|
ScriptGlobal::Set("Icinga.DbCatLog", DbCatLog);
|
||||||
ScriptGlobal::Set("Icinga.DbCatNotification", DbCatNotification, true);
|
ScriptGlobal::Set("Icinga.DbCatNotification", DbCatNotification);
|
||||||
ScriptGlobal::Set("Icinga.DbCatProgramStatus", DbCatProgramStatus, true);
|
ScriptGlobal::Set("Icinga.DbCatProgramStatus", DbCatProgramStatus);
|
||||||
ScriptGlobal::Set("Icinga.DbCatRetention", DbCatRetention, true);
|
ScriptGlobal::Set("Icinga.DbCatRetention", DbCatRetention);
|
||||||
ScriptGlobal::Set("Icinga.DbCatStateHistory", DbCatStateHistory, true);
|
ScriptGlobal::Set("Icinga.DbCatStateHistory", DbCatStateHistory);
|
||||||
|
|
||||||
ScriptGlobal::Set("Icinga.DbCatEverything", DbCatEverything, true);
|
ScriptGlobal::Set("Icinga.DbCatEverything", DbCatEverything);
|
||||||
|
|
||||||
m_CategoryFilterMap["DbCatConfig"] = DbCatConfig;
|
m_CategoryFilterMap["DbCatConfig"] = DbCatConfig;
|
||||||
m_CategoryFilterMap["DbCatState"] = DbCatState;
|
m_CategoryFilterMap["DbCatState"] = DbCatState;
|
||||||
|
@ -9,13 +9,13 @@ using namespace icinga;
|
|||||||
REGISTER_TYPE(CheckResult);
|
REGISTER_TYPE(CheckResult);
|
||||||
|
|
||||||
INITIALIZE_ONCE([]() {
|
INITIALIZE_ONCE([]() {
|
||||||
ScriptGlobal::Set("Icinga.ServiceOK", ServiceOK, true);
|
ScriptGlobal::Set("Icinga.ServiceOK", ServiceOK);
|
||||||
ScriptGlobal::Set("Icinga.ServiceWarning", ServiceWarning, true);
|
ScriptGlobal::Set("Icinga.ServiceWarning", ServiceWarning);
|
||||||
ScriptGlobal::Set("Icinga.ServiceCritical", ServiceCritical, true);
|
ScriptGlobal::Set("Icinga.ServiceCritical", ServiceCritical);
|
||||||
ScriptGlobal::Set("Icinga.ServiceUnknown", ServiceUnknown, true);
|
ScriptGlobal::Set("Icinga.ServiceUnknown", ServiceUnknown);
|
||||||
|
|
||||||
ScriptGlobal::Set("Icinga.HostUp", HostUp, true);
|
ScriptGlobal::Set("Icinga.HostUp", HostUp);
|
||||||
ScriptGlobal::Set("Icinga.HostDown", HostDown, true);
|
ScriptGlobal::Set("Icinga.HostDown", HostDown);
|
||||||
})
|
})
|
||||||
|
|
||||||
double CheckResult::CalculateExecutionTime() const
|
double CheckResult::CalculateExecutionTime() const
|
||||||
|
@ -269,7 +269,7 @@ std::pair<Dictionary::Ptr, Array::Ptr> CIB::GetFeatureStats()
|
|||||||
ObjectLock olock(statsFunctions);
|
ObjectLock olock(statsFunctions);
|
||||||
|
|
||||||
for (const Namespace::Pair& kv : statsFunctions)
|
for (const Namespace::Pair& kv : statsFunctions)
|
||||||
static_cast<Function::Ptr>(kv.second->Get())->Invoke({ status, perfdata });
|
static_cast<Function::Ptr>(kv.second.Val)->Invoke({ status, perfdata });
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_pair(status, perfdata);
|
return std::make_pair(status, perfdata);
|
||||||
|
@ -31,9 +31,9 @@ INITIALIZE_ONCE(&Downtime::StaticInitialize);
|
|||||||
|
|
||||||
void Downtime::StaticInitialize()
|
void Downtime::StaticInitialize()
|
||||||
{
|
{
|
||||||
ScriptGlobal::Set("Icinga.DowntimeNoChildren", "DowntimeNoChildren", true);
|
ScriptGlobal::Set("Icinga.DowntimeNoChildren", "DowntimeNoChildren");
|
||||||
ScriptGlobal::Set("Icinga.DowntimeTriggeredChildren", "DowntimeTriggeredChildren", true);
|
ScriptGlobal::Set("Icinga.DowntimeTriggeredChildren", "DowntimeTriggeredChildren");
|
||||||
ScriptGlobal::Set("Icinga.DowntimeNonTriggeredChildren", "DowntimeNonTriggeredChildren", true);
|
ScriptGlobal::Set("Icinga.DowntimeNonTriggeredChildren", "DowntimeNonTriggeredChildren");
|
||||||
}
|
}
|
||||||
|
|
||||||
String DowntimeNameComposer::MakeName(const String& shortName, const Object::Ptr& context) const
|
String DowntimeNameComposer::MakeName(const String& shortName, const Object::Ptr& context) const
|
||||||
|
@ -28,6 +28,8 @@ REGISTER_TYPE(IcingaApplication);
|
|||||||
/* Ensure that the priority is lower than the basic System namespace initialization in scriptframe.cpp. */
|
/* Ensure that the priority is lower than the basic System namespace initialization in scriptframe.cpp. */
|
||||||
INITIALIZE_ONCE_WITH_PRIORITY(&IcingaApplication::StaticInitialize, InitializePriority::InitIcingaApplication);
|
INITIALIZE_ONCE_WITH_PRIORITY(&IcingaApplication::StaticInitialize, InitializePriority::InitIcingaApplication);
|
||||||
|
|
||||||
|
static Namespace::Ptr l_IcingaNS;
|
||||||
|
|
||||||
void IcingaApplication::StaticInitialize()
|
void IcingaApplication::StaticInitialize()
|
||||||
{
|
{
|
||||||
/* Pre-fill global constants, can be overridden with user input later in icinga-app/icinga.cpp. */
|
/* Pre-fill global constants, can be overridden with user input later in icinga-app/icinga.cpp. */
|
||||||
@ -58,11 +60,14 @@ void IcingaApplication::StaticInitialize()
|
|||||||
Namespace::Ptr globalNS = ScriptGlobal::GetGlobals();
|
Namespace::Ptr globalNS = ScriptGlobal::GetGlobals();
|
||||||
VERIFY(globalNS);
|
VERIFY(globalNS);
|
||||||
|
|
||||||
Namespace::Ptr icingaNS = new Namespace(true);
|
l_IcingaNS = new Namespace(true);
|
||||||
icingaNS->Freeze();
|
globalNS->Set("Icinga", l_IcingaNS, true);
|
||||||
globalNS->SetAttribute("Icinga", new ConstEmbeddedNamespaceValue(icingaNS));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INITIALIZE_ONCE_WITH_PRIORITY([]() {
|
||||||
|
l_IcingaNS->Freeze();
|
||||||
|
}, InitializePriority::FreezeNamespaces);
|
||||||
|
|
||||||
REGISTER_STATSFUNCTION(IcingaApplication, &IcingaApplication::StatsFunc);
|
REGISTER_STATSFUNCTION(IcingaApplication, &IcingaApplication::StatsFunc);
|
||||||
|
|
||||||
void IcingaApplication::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata)
|
void IcingaApplication::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata)
|
||||||
|
@ -63,22 +63,22 @@ Dictionary::Ptr NotificationNameComposer::ParseName(const String& name) const
|
|||||||
|
|
||||||
void Notification::StaticInitialize()
|
void Notification::StaticInitialize()
|
||||||
{
|
{
|
||||||
ScriptGlobal::Set("Icinga.OK", "OK", true);
|
ScriptGlobal::Set("Icinga.OK", "OK");
|
||||||
ScriptGlobal::Set("Icinga.Warning", "Warning", true);
|
ScriptGlobal::Set("Icinga.Warning", "Warning");
|
||||||
ScriptGlobal::Set("Icinga.Critical", "Critical", true);
|
ScriptGlobal::Set("Icinga.Critical", "Critical");
|
||||||
ScriptGlobal::Set("Icinga.Unknown", "Unknown", true);
|
ScriptGlobal::Set("Icinga.Unknown", "Unknown");
|
||||||
ScriptGlobal::Set("Icinga.Up", "Up", true);
|
ScriptGlobal::Set("Icinga.Up", "Up");
|
||||||
ScriptGlobal::Set("Icinga.Down", "Down", true);
|
ScriptGlobal::Set("Icinga.Down", "Down");
|
||||||
|
|
||||||
ScriptGlobal::Set("Icinga.DowntimeStart", "DowntimeStart", true);
|
ScriptGlobal::Set("Icinga.DowntimeStart", "DowntimeStart");
|
||||||
ScriptGlobal::Set("Icinga.DowntimeEnd", "DowntimeEnd", true);
|
ScriptGlobal::Set("Icinga.DowntimeEnd", "DowntimeEnd");
|
||||||
ScriptGlobal::Set("Icinga.DowntimeRemoved", "DowntimeRemoved", true);
|
ScriptGlobal::Set("Icinga.DowntimeRemoved", "DowntimeRemoved");
|
||||||
ScriptGlobal::Set("Icinga.Custom", "Custom", true);
|
ScriptGlobal::Set("Icinga.Custom", "Custom");
|
||||||
ScriptGlobal::Set("Icinga.Acknowledgement", "Acknowledgement", true);
|
ScriptGlobal::Set("Icinga.Acknowledgement", "Acknowledgement");
|
||||||
ScriptGlobal::Set("Icinga.Problem", "Problem", true);
|
ScriptGlobal::Set("Icinga.Problem", "Problem");
|
||||||
ScriptGlobal::Set("Icinga.Recovery", "Recovery", true);
|
ScriptGlobal::Set("Icinga.Recovery", "Recovery");
|
||||||
ScriptGlobal::Set("Icinga.FlappingStart", "FlappingStart", true);
|
ScriptGlobal::Set("Icinga.FlappingStart", "FlappingStart");
|
||||||
ScriptGlobal::Set("Icinga.FlappingEnd", "FlappingEnd", true);
|
ScriptGlobal::Set("Icinga.FlappingEnd", "FlappingEnd");
|
||||||
|
|
||||||
m_StateFilterMap["OK"] = StateFilterOK;
|
m_StateFilterMap["OK"] = StateFilterOK;
|
||||||
m_StateFilterMap["Warning"] = StateFilterWarning;
|
m_StateFilterMap["Warning"] = StateFilterWarning;
|
||||||
|
@ -24,7 +24,7 @@ Dictionary::Ptr IcingaDB::GetStats()
|
|||||||
|
|
||||||
for (auto& kv : statsFunctions)
|
for (auto& kv : statsFunctions)
|
||||||
{
|
{
|
||||||
Function::Ptr func = kv.second->Get();
|
Function::Ptr func = kv.second.Val;
|
||||||
|
|
||||||
if (!func)
|
if (!func)
|
||||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid status function name."));
|
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid status function name."));
|
||||||
|
@ -35,7 +35,7 @@ public:
|
|||||||
Namespace::Ptr globals = ScriptGlobal::GetGlobals();
|
Namespace::Ptr globals = ScriptGlobal::GetGlobals();
|
||||||
ObjectLock olock(globals);
|
ObjectLock olock(globals);
|
||||||
for (const Namespace::Pair& kv : globals) {
|
for (const Namespace::Pair& kv : globals) {
|
||||||
addTarget(GetTargetForVar(kv.first, kv.second->Get()));
|
addTarget(GetTargetForVar(kv.first, kv.second.Val));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user