Implement support for namespaces

This commit is contained in:
Gunnar Beutner 2018-08-07 13:55:41 +02:00
parent 9d513d8f05
commit 1a8692d972
43 changed files with 789 additions and 143 deletions

View File

@ -203,6 +203,38 @@ to dereference a reference:
*p = "Hi!"
log(value) // Prints "Hi!" because the variable was changed
### Namespaces <a id="namespaces"></a>
Namespaces can be used to organize variables and functions. They are used to avoid name conflicts. The `namespace`
keyword is used to create a new namespace:
namespace Utils {
function calculate() {
return 2 + 2
}
}
The namespace is made available as a global variable which has the namespace's name (e.g. `Utils`):
Utils.calculate()
The `using` keyword can be used to make all attributes in a namespace available to a script without having to
explicitly specify the namespace's name for each access:
using Utils
calculate()
The `using` keyword only has an effect for the current file and only for code that follows the keyword:
calculate() // This will not work.
using Utils
The following namespaces are automatically imported as if by using the `using` keyword:
* System
* Types
* Icinga
### Function Calls <a id="function-calls"></a>
Functions can be called using the `()` operator:

View File

@ -21,6 +21,7 @@
#include "config/configcompilercontext.hpp"
#include "config/configcompiler.hpp"
#include "config/configitembuilder.hpp"
#include "config/expression.hpp"
#include "base/application.hpp"
#include "base/logger.hpp"
#include "base/timer.hpp"
@ -440,7 +441,24 @@ static int Main()
key = define;
value = "1";
}
ScriptGlobal::Set(key, value);
std::vector<String> keyTokens = key.Split(".");
std::unique_ptr<Expression> expr;
std::unique_ptr<VariableExpression> varExpr{new VariableExpression(keyTokens[0], {}, DebugInfo())};
expr = std::move(varExpr);
for (size_t i = 1; i < keyTokens.size(); i++) {
std::unique_ptr<IndexerExpression> indexerExpr{new IndexerExpression(std::move(expr), MakeLiteral(keyTokens[i]))};
indexerExpr->SetOverrideFrozen();
expr = std::move(indexerExpr);
}
std::unique_ptr<SetExpression> setExpr{new SetExpression(std::move(expr), OpSetLiteral, MakeLiteral(value))};
setExpr->SetOverrideFrozen();
ScriptFrame frame(true);
setExpr->Evaluate(frame);
}
}

View File

@ -17,8 +17,8 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
if (!globals.irc) {
globals.irc = globals.log
if (!globals.contains("irc")) {
globals.irc = log
}
hm = {

View File

@ -54,6 +54,7 @@ set(base_SOURCES
math-script.cpp
netstring.cpp netstring.hpp
networkstream.cpp networkstream.hpp
namespace.cpp namespace.hpp namespace-script.cpp
number.cpp number.hpp number-script.cpp
object.cpp object.hpp object-script.cpp
objectlock.cpp objectlock.hpp

View File

@ -75,13 +75,29 @@ private:
#define REGISTER_FUNCTION(ns, name, callback, args) \
INITIALIZE_ONCE_WITH_PRIORITY([]() { \
Function::Ptr sf = new icinga::Function(#ns "#" #name, callback, String(args).Split(":"), false); \
ScriptGlobal::Set(#ns "." #name, sf); \
Namespace::Ptr nsp = ScriptGlobal::Get(#ns); \
nsp->SetAttribute(#name, std::make_shared<ConstEmbeddedNamespaceValue>(sf)); \
}, 10)
#define REGISTER_SAFE_FUNCTION(ns, name, callback, args) \
INITIALIZE_ONCE_WITH_PRIORITY([]() { \
Function::Ptr sf = new icinga::Function(#ns "#" #name, callback, String(args).Split(":"), true); \
ScriptGlobal::Set(#ns "." #name, sf); \
Namespace::Ptr nsp = ScriptGlobal::Get(#ns); \
nsp->SetAttribute(#name, std::make_shared<ConstEmbeddedNamespaceValue>(sf)); \
}, 10)
#define REGISTER_FUNCTION_NONCONST(ns, name, callback, args) \
INITIALIZE_ONCE_WITH_PRIORITY([]() { \
Function::Ptr sf = new icinga::Function(#ns "#" #name, callback, String(args).Split(":"), false); \
Namespace::Ptr nsp = ScriptGlobal::Get(#ns); \
nsp->SetAttribute(#name, std::make_shared<EmbeddedNamespaceValue>(sf)); \
}, 10)
#define REGISTER_SAFE_FUNCTION_NONCONST(ns, name, callback, args) \
INITIALIZE_ONCE_WITH_PRIORITY([]() { \
Function::Ptr sf = new icinga::Function(#ns "#" #name, callback, String(args).Split(":"), true); \
Namespace::Ptr nsp = ScriptGlobal::Get(#ns); \
nsp->SetAttribute(#name, std::make_shared<EmbeddedNamespaceValue>(sf)); \
}, 10)
}

View File

@ -32,11 +32,15 @@ static String JsonEncodeShim(const Value& value)
}
INITIALIZE_ONCE([]() {
Dictionary::Ptr jsonObj = new Dictionary({
/* Methods */
{ "encode", new Function("Json#encode", JsonEncodeShim, { "value" }, true) },
{ "decode", new Function("Json#decode", JsonDecode, { "value" }, true) }
});
auto jsonNSBehavior = new ConstNamespaceBehavior();
Namespace::Ptr jsonNS = new Namespace(jsonNSBehavior);
ScriptGlobal::Set("Json", jsonObj);
/* Methods */
jsonNS->Set("encode", new Function("Json#encode", JsonEncodeShim, { "value" }, true));
jsonNS->Set("decode", new Function("Json#decode", JsonDecode, { "value" }, true));
jsonNSBehavior->Freeze();
Namespace::Ptr systemNS = ScriptGlobal::Get("System");
systemNS->SetAttribute("Json", std::make_shared<ConstEmbeddedNamespaceValue>(jsonNS));
});

View File

@ -19,6 +19,7 @@
#include "base/json.hpp"
#include "base/debug.hpp"
#include "base/namespace.hpp"
#include "base/dictionary.hpp"
#include "base/array.hpp"
#include "base/objectlock.hpp"
@ -39,6 +40,19 @@ typedef unsigned int yajl_size;
typedef size_t yajl_size;
#endif /* YAJL_MAJOR */
static void EncodeNamespace(yajl_gen handle, const Namespace::Ptr& ns)
{
yajl_gen_map_open(handle);
ObjectLock olock(ns);
for (const Namespace::Pair& kv : ns) {
yajl_gen_string(handle, reinterpret_cast<const unsigned char *>(kv.first.CStr()), kv.first.GetLength());
Encode(handle, kv.second->Get());
}
yajl_gen_map_close(handle);
}
static void EncodeDictionary(yajl_gen handle, const Dictionary::Ptr& dict)
{
yajl_gen_map_open(handle);
@ -83,6 +97,13 @@ static void Encode(yajl_gen handle, const Value& value)
case ValueObject:
{
const Object::Ptr& obj = value.Get<Object::Ptr>();
Namespace::Ptr ns = dynamic_pointer_cast<Namespace>(obj);
if (ns) {
EncodeNamespace(handle, ns);
break;
}
Dictionary::Ptr dict = dynamic_pointer_cast<Dictionary>(obj);
if (dict) {

View File

@ -22,6 +22,7 @@
#include "base/functionwrapper.hpp"
#include "base/scriptframe.hpp"
#include "base/initialize.hpp"
#include "base/namespace.hpp"
#include <boost/math/special_functions/round.hpp>
#include <cmath>
@ -158,40 +159,44 @@ static double MathSign(double x)
}
INITIALIZE_ONCE([]() {
Dictionary::Ptr mathObj = new Dictionary({
/* Constants */
{ "E", 2.71828182845904523536 },
{ "LN2", 0.693147180559945309417 },
{ "LN10", 2.30258509299404568402 },
{ "LOG2E", 1.44269504088896340736 },
{ "LOG10E", 0.434294481903251827651 },
{ "PI", 3.14159265358979323846 },
{ "SQRT1_2", 0.707106781186547524401 },
{ "SQRT2", 1.41421356237309504880 },
auto mathNSBehavior = new ConstNamespaceBehavior();
Namespace::Ptr mathNS = new Namespace(mathNSBehavior);
/* Methods */
{ "abs", new Function("Math#abs", MathAbs, { "x" }, true) },
{ "acos", new Function("Math#acos", MathAcos, { "x" }, true) },
{ "asin", new Function("Math#asin", MathAsin, { "x" }, true) },
{ "atan", new Function("Math#atan", MathAtan, { "x" }, true) },
{ "atan2", new Function("Math#atan2", MathAtan2, { "x", "y" }, true) },
{ "ceil", new Function("Math#ceil", MathCeil, { "x" }, true) },
{ "cos", new Function("Math#cos", MathCos, { "x" }, true) },
{ "exp", new Function("Math#exp", MathExp, { "x" }, true) },
{ "floor", new Function("Math#floor", MathFloor, { "x" }, true) },
{ "log", new Function("Math#log", MathLog, { "x" }, true) },
{ "max", new Function("Math#max", MathMax, {}, true) },
{ "min", new Function("Math#min", MathMin, {}, true) },
{ "pow", new Function("Math#pow", MathPow, { "x", "y" }, true) },
{ "random", new Function("Math#random", MathRandom, {}, true) },
{ "round", new Function("Math#round", MathRound, { "x" }, true) },
{ "sin", new Function("Math#sin", MathSin, { "x" }, true) },
{ "sqrt", new Function("Math#sqrt", MathSqrt, { "x" }, true) },
{ "tan", new Function("Math#tan", MathTan, { "x" }, true) },
{ "isnan", new Function("Math#isnan", MathIsnan, { "x" }, true) },
{ "isinf", new Function("Math#isinf", MathIsinf, { "x" }, true) },
{ "sign", new Function("Math#sign", MathSign, { "x" }, true) }
});
/* Constants */
mathNS->Set("E", 2.71828182845904523536);
mathNS->Set("LN2", 0.693147180559945309417);
mathNS->Set("LN10", 2.30258509299404568402);
mathNS->Set("LOG2E", 1.44269504088896340736);
mathNS->Set("LOG10E", 0.434294481903251827651);
mathNS->Set("PI", 3.14159265358979323846);
mathNS->Set("SQRT1_2", 0.707106781186547524401);
mathNS->Set("SQRT2", 1.41421356237309504880);
ScriptGlobal::Set("Math", mathObj);
/* Methods */
mathNS->Set("abs", new Function("Math#abs", MathAbs, { "x" }, true));
mathNS->Set("acos", new Function("Math#acos", MathAcos, { "x" }, true));
mathNS->Set("asin", new Function("Math#asin", MathAsin, { "x" }, true));
mathNS->Set("atan", new Function("Math#atan", MathAtan, { "x" }, true));
mathNS->Set("atan2", new Function("Math#atan2", MathAtan2, { "x", "y" }, true));
mathNS->Set("ceil", new Function("Math#ceil", MathCeil, { "x" }, true));
mathNS->Set("cos", new Function("Math#cos", MathCos, { "x" }, true));
mathNS->Set("exp", new Function("Math#exp", MathExp, { "x" }, true));
mathNS->Set("floor", new Function("Math#floor", MathFloor, { "x" }, true));
mathNS->Set("log", new Function("Math#log", MathLog, { "x" }, true));
mathNS->Set("max", new Function("Math#max", MathMax, {}, true));
mathNS->Set("min", new Function("Math#min", MathMin, {}, true));
mathNS->Set("pow", new Function("Math#pow", MathPow, { "x", "y" }, true));
mathNS->Set("random", new Function("Math#random", MathRandom, {}, true));
mathNS->Set("round", new Function("Math#round", MathRound, { "x" }, true));
mathNS->Set("sin", new Function("Math#sin", MathSin, { "x" }, true));
mathNS->Set("sqrt", new Function("Math#sqrt", MathSqrt, { "x" }, true));
mathNS->Set("tan", new Function("Math#tan", MathTan, { "x" }, true));
mathNS->Set("isnan", new Function("Math#isnan", MathIsnan, { "x" }, true));
mathNS->Set("isinf", new Function("Math#isinf", MathIsinf, { "x" }, true));
mathNS->Set("sign", new Function("Math#sign", MathSign, { "x" }, true));
mathNSBehavior->Freeze();
Namespace::Ptr systemNS = ScriptGlobal::Get("System");
systemNS->SetAttribute("Math", std::make_shared<ConstEmbeddedNamespaceValue>(mathNS));
});

View File

@ -0,0 +1,101 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2018 Icinga Development Team (https://www.icinga.com/) *
* *
* 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 "base/namespace.hpp"
#include "base/function.hpp"
#include "base/functionwrapper.hpp"
#include "base/scriptframe.hpp"
#include "base/array.hpp"
using namespace icinga;
static void NamespaceSet(const String& key, const Value& value)
{
ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
Namespace::Ptr self = static_cast<Namespace::Ptr>(vframe->Self);
REQUIRE_NOT_NULL(self);
self->Set(key, value);
}
static Value NamespaceGet(const String& key)
{
ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
Namespace::Ptr self = static_cast<Namespace::Ptr>(vframe->Self);
REQUIRE_NOT_NULL(self);
return self->Get(key);
}
static void NamespaceRemove(const String& key)
{
ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
Namespace::Ptr self = static_cast<Namespace::Ptr>(vframe->Self);
REQUIRE_NOT_NULL(self);
self->Remove(key);
}
static bool NamespaceContains(const String& key)
{
ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
Namespace::Ptr self = static_cast<Namespace::Ptr>(vframe->Self);
REQUIRE_NOT_NULL(self);
return self->Contains(key);
}
static Array::Ptr NamespaceKeys()
{
ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
Namespace::Ptr self = static_cast<Namespace::Ptr>(vframe->Self);
REQUIRE_NOT_NULL(self);
ArrayData keys;
ObjectLock olock(self);
for (const Namespace::Pair& kv : self) {
keys.push_back(kv.first);
}
return new Array(std::move(keys));
}
static Array::Ptr NamespaceValues()
{
ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
Namespace::Ptr self = static_cast<Namespace::Ptr>(vframe->Self);
REQUIRE_NOT_NULL(self);
ArrayData values;
ObjectLock olock(self);
for (const Namespace::Pair& kv : self) {
values.push_back(kv.second->Get());
}
return new Array(std::move(values));
}
Object::Ptr Namespace::GetPrototype()
{
static Dictionary::Ptr prototype = new Dictionary({
{ "set", new Function("Namespace#set", NamespaceSet, { "key", "value" }) },
{ "get", new Function("Namespace#get", NamespaceGet, { "key" }) },
{ "remove", new Function("Namespace#remove", NamespaceRemove, { "key" }) },
{ "contains", new Function("Namespace#contains", NamespaceContains, { "key" }, true) },
{ "keys", new Function("Namespace#keys", NamespaceKeys, {}, true) },
{ "values", new Function("Namespace#values", NamespaceValues, {}, true) },
});
return prototype;
}

223
lib/base/namespace.cpp Normal file
View File

@ -0,0 +1,223 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2018 Icinga Development Team (https://www.icinga.com/) *
* *
* 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 "base/namespace.hpp"
#include "base/objectlock.hpp"
#include "base/debug.hpp"
#include "base/primitivetype.hpp"
#include "base/debuginfo.hpp"
#include "base/exception.hpp"
#include <sstream>
using namespace icinga;
template class std::map<icinga::String, std::shared_ptr<icinga::NamespaceValue> >;
REGISTER_PRIMITIVE_TYPE(Namespace, Object, Namespace::GetPrototype());
Namespace::Namespace(NamespaceBehavior *behavior)
: m_Behavior(std::unique_ptr<NamespaceBehavior>(behavior))
{ }
Value Namespace::Get(const String& field) const
{
Value value;
if (!GetOwnField(field, &value))
BOOST_THROW_EXCEPTION(ScriptError("Namespace does not contain field '" + field + "'"));
return value;
}
bool Namespace::Get(const String& field, Value *value) const
{
auto nsVal = GetAttribute(field);
if (!nsVal)
return false;
*value = nsVal->Get(DebugInfo());
return true;
}
void Namespace::Set(const String& field, const Value& value, bool overrideFrozen)
{
return SetFieldByName(field, value, overrideFrozen, DebugInfo());
}
bool Namespace::Contains(const String& field) const
{
return HasOwnField(field);
}
void Namespace::Remove(const String& field, bool overrideFrozen)
{
m_Behavior->Remove(this, field, overrideFrozen);
}
void Namespace::RemoveAttribute(const String& field)
{
ObjectLock olock(this);
Namespace::Iterator it;
it = m_Data.find(field);
if (it == m_Data.end())
return;
m_Data.erase(it);
}
std::shared_ptr<NamespaceValue> 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 std::shared_ptr<NamespaceValue>& nsVal)
{
ObjectLock olock(this);
m_Data[key] = nsVal;
}
Value Namespace::GetFieldByName(const String& field, bool, const DebugInfo& debugInfo) const
{
auto nsVal = GetAttribute(field);
if (nsVal)
return nsVal->Get(debugInfo);
else
return GetPrototypeField(const_cast<Namespace *>(this), field, true, debugInfo);
}
void Namespace::SetFieldByName(const String& field, const Value& value, bool overrideFrozen, const DebugInfo& debugInfo)
{
auto nsVal = GetAttribute(field);
if (!nsVal)
m_Behavior->Register(this, field, value, overrideFrozen, debugInfo);
else
nsVal->Set(value, overrideFrozen, debugInfo);
}
bool Namespace::HasOwnField(const String& field) const
{
return GetAttribute(field) != nullptr;
}
bool Namespace::GetOwnField(const String& field, Value *result) const
{
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);
}
void NamespaceBehavior::Register(const Namespace::Ptr& ns, const String& field, const Value& value, bool overrideFrozen, const DebugInfo& debugInfo) const
{
ns->SetAttribute(field, std::make_shared<EmbeddedNamespaceValue>(value));
}
void NamespaceBehavior::Remove(const Namespace::Ptr& ns, const String& field, bool overrideFrozen)
{
if (!overrideFrozen) {
auto attr = ns->GetAttribute(field);
if (dynamic_pointer_cast<ConstEmbeddedNamespaceValue>(attr))
BOOST_THROW_EXCEPTION(ScriptError("Constants must not be removed."));
}
ns->RemoveAttribute(field);
}
void ConstNamespaceBehavior::Register(const Namespace::Ptr& ns, const String& field, const Value& value, bool overrideFrozen, const DebugInfo& debugInfo) const
{
if (m_Frozen && !overrideFrozen)
BOOST_THROW_EXCEPTION(ScriptError("Namespace is read-only and must not be modified.", debugInfo));
ns->SetAttribute(field, std::make_shared<ConstEmbeddedNamespaceValue>(value));
}
void ConstNamespaceBehavior::Remove(const Namespace::Ptr& ns, const String& field, bool overrideFrozen)
{
if (m_Frozen && !overrideFrozen)
BOOST_THROW_EXCEPTION(ScriptError("Namespace is read-only and must not be modified."));
NamespaceBehavior::Remove(ns, field, overrideFrozen);
}
void ConstNamespaceBehavior::Freeze()
{
m_Frozen = true;
}
Namespace::Iterator Namespace::Begin()
{
ASSERT(OwnsLock());
return m_Data.begin();
}
Namespace::Iterator Namespace::End()
{
ASSERT(OwnsLock());
return m_Data.end();
}
Namespace::Iterator icinga::begin(const Namespace::Ptr& x)
{
return x->Begin();
}
Namespace::Iterator icinga::end(const Namespace::Ptr& x)
{
return x->End();
}

123
lib/base/namespace.hpp Normal file
View File

@ -0,0 +1,123 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2018 Icinga Development Team (https://www.icinga.com/) *
* *
* 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 NAMESPACE_H
#define NAMESPACE_H
#include "base/i2-base.hpp"
#include "base/object.hpp"
#include "base/value.hpp"
#include "base/debuginfo.hpp"
#include <map>
#include <vector>
namespace icinga
{
struct NamespaceValue
{
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;
};
class Namespace;
struct NamespaceBehavior
{
virtual void Register(const boost::intrusive_ptr<Namespace>& ns, const String& field, const Value& value, bool overrideFrozen, const DebugInfo& debugInfo) const;
virtual void Remove(const boost::intrusive_ptr<Namespace>& ns, const String& field, bool overrideFrozen);
};
struct ConstNamespaceBehavior : public NamespaceBehavior
{
void Register(const boost::intrusive_ptr<Namespace>& ns, const String& field, const Value& value, bool overrideFrozen, const DebugInfo& debugInfo) const override;
void Remove(const boost::intrusive_ptr<Namespace>& ns, const String& field, bool overrideFrozen) override;
void Freeze();
private:
bool m_Frozen;
};
/**
* A namespace.
*
* @ingroup base
*/
class Namespace final : public Object
{
public:
DECLARE_OBJECT(Namespace);
typedef std::map<String, std::shared_ptr<NamespaceValue> >::iterator Iterator;
typedef std::map<String, std::shared_ptr<NamespaceValue> >::value_type Pair;
Namespace(NamespaceBehavior *behavior = new NamespaceBehavior);
Value Get(const String& field) const;
bool Get(const String& field, Value *value) const;
void Set(const String& field, const Value& value, bool overrideFrozen = false);
bool Contains(const String& field) const;
void Remove(const String& field, bool overrideFrozen = false);
std::shared_ptr<NamespaceValue> GetAttribute(const String& field) const;
void SetAttribute(const String& field, const std::shared_ptr<NamespaceValue>& nsVal);
void RemoveAttribute(const String& field);
Iterator Begin();
Iterator End();
Value GetFieldByName(const String& field, bool sandboxed, const DebugInfo& debugInfo) const override;
void SetFieldByName(const String& field, const Value& value, bool overrideFrozen, const DebugInfo& debugInfo) override;
bool HasOwnField(const String& field) const override;
bool GetOwnField(const String& field, Value *result) const override;
static Object::Ptr GetPrototype();
private:
std::map<String, std::shared_ptr<NamespaceValue> > m_Data;
std::unique_ptr<NamespaceBehavior> m_Behavior;
};
Namespace::Iterator begin(const Namespace::Ptr& x);
Namespace::Iterator end(const Namespace::Ptr& x);
}
extern template class std::map<icinga::String, std::shared_ptr<icinga::NamespaceValue> >;
#endif /* NAMESPACE_H */

View File

@ -26,11 +26,12 @@
#include "base/convert.hpp"
#include "base/objectlock.hpp"
#include "base/exception.hpp"
#include "base/namespace.hpp"
#include <fstream>
using namespace icinga;
Dictionary::Ptr ScriptGlobal::m_Globals = new Dictionary();
Namespace::Ptr ScriptGlobal::m_Globals = new Namespace();
Value ScriptGlobal::Get(const String& name, const Value *defaultValue)
{
@ -46,7 +47,7 @@ Value ScriptGlobal::Get(const String& name, const Value *defaultValue)
return result;
}
void ScriptGlobal::Set(const String& name, const Value& value)
void ScriptGlobal::Set(const String& name, const Value& value, bool overrideFrozen)
{
std::vector<String> tokens = name.Split(".");
@ -56,7 +57,7 @@ void ScriptGlobal::Set(const String& name, const Value& value)
{
ObjectLock olock(m_Globals);
Dictionary::Ptr parent = m_Globals;
Namespace::Ptr parent = m_Globals;
for (std::vector<String>::size_type i = 0; i < tokens.size(); i++) {
const String& token = tokens[i];
@ -65,7 +66,7 @@ void ScriptGlobal::Set(const String& name, const Value& value)
Value vparent;
if (!parent->Get(token, &vparent)) {
Dictionary::Ptr dict = new Dictionary();
Namespace::Ptr dict = new Namespace();
parent->Set(token, dict);
parent = dict;
} else {
@ -74,16 +75,21 @@ void ScriptGlobal::Set(const String& name, const Value& value)
}
}
parent->Set(tokens[tokens.size() - 1], value);
parent->SetFieldByName(tokens[tokens.size() - 1], value, overrideFrozen, DebugInfo());
}
}
void ScriptGlobal::SetConst(const String& name, const Value& value)
{
GetGlobals()->SetAttribute(name, std::make_shared<ConstEmbeddedNamespaceValue>(value));
}
bool ScriptGlobal::Exists(const String& name)
{
return m_Globals->Contains(name);
}
Dictionary::Ptr ScriptGlobal::GetGlobals()
Namespace::Ptr ScriptGlobal::GetGlobals()
{
return m_Globals;
}
@ -102,8 +108,8 @@ void ScriptGlobal::WriteToFile(const String& filename)
StdioStream::Ptr sfp = new StdioStream(&fp, false);
ObjectLock olock(m_Globals);
for (const Dictionary::Pair& kv : m_Globals) {
Value value = kv.second;
for (const Namespace::Pair& kv : m_Globals) {
Value value = kv.second->Get();
if (value.IsObject())
value = Convert::ToString(value);

View File

@ -21,7 +21,7 @@
#define SCRIPTGLOBAL_H
#include "base/i2-base.hpp"
#include "base/dictionary.hpp"
#include "base/namespace.hpp"
namespace icinga
{
@ -35,15 +35,16 @@ class ScriptGlobal
{
public:
static Value Get(const String& name, const Value *defaultValue = nullptr);
static void Set(const String& name, const Value& value);
static void Set(const String& name, const Value& value, bool overrideFrozen = false);
static void SetConst(const String& name, const Value& value);
static bool Exists(const String& name);
static void WriteToFile(const String& filename);
static Dictionary::Ptr GetGlobals();
static Namespace::Ptr GetGlobals();
private:
static Dictionary::Ptr m_Globals;
static Namespace::Ptr m_Globals;
};
}

View File

@ -83,11 +83,11 @@ enum MatchType
void ScriptUtils::StaticInitialize()
{
ScriptGlobal::Set("MatchAll", MatchAll);
ScriptGlobal::Set("MatchAny", MatchAny);
ScriptGlobal::Set("MatchAll", MatchAll, true);
ScriptGlobal::Set("MatchAny", MatchAny, true);
ScriptGlobal::Set("GlobFile", GlobFile);
ScriptGlobal::Set("GlobDirectory", GlobDirectory);
ScriptGlobal::Set("GlobFile", GlobFile, true);
ScriptGlobal::Set("GlobDirectory", GlobDirectory, true);
}
String ScriptUtils::CastString(const Value& value)

View File

@ -23,6 +23,7 @@
#include "base/objectlock.hpp"
#include "base/convert.hpp"
#include "base/exception.hpp"
#include "base/namespace.hpp"
#include <boost/algorithm/string/join.hpp>
#include <deque>
@ -119,6 +120,22 @@ static Dictionary::Ptr SerializeDictionary(const Dictionary::Ptr& input, int att
return new Dictionary(std::move(result));
}
static Dictionary::Ptr SerializeNamespace(const Namespace::Ptr& input, int attributeTypes, SerializeStack& stack)
{
DictionaryData result;
ObjectLock olock(input);
for (const Namespace::Pair& kv : input) {
Value val = kv.second->Get();
stack.Push(kv.first, val);
result.emplace_back(kv.first, Serialize(val, attributeTypes));
stack.Pop();
}
return new Dictionary(std::move(result));
}
static Object::Ptr SerializeObject(const Object::Ptr& input, int attributeTypes, SerializeStack& stack)
{
Type::Ptr type = input->GetReflectionType();
@ -243,6 +260,11 @@ static Value SerializeInternal(const Value& value, int attributeTypes, Serialize
if (dict)
return SerializeDictionary(dict, attributeTypes, stack);
Namespace::Ptr ns = dynamic_pointer_cast<Namespace>(input);
if (ns)
return SerializeNamespace(ns, attributeTypes, stack);
return SerializeObject(input, attributeTypes, stack);
}

View File

@ -19,6 +19,7 @@
#include "base/type.hpp"
#include "base/scriptglobal.hpp"
#include "base/namespace.hpp"
#include "base/objectlock.hpp"
using namespace icinga;
@ -39,19 +40,19 @@ String Type::ToString() const
void Type::Register(const Type::Ptr& type)
{
VERIFY(!GetByName(type->GetName()));
ScriptGlobal::Set("Types." + type->GetName(), type);
ScriptGlobal::Set("Types." + type->GetName(), type, true);
}
Type::Ptr Type::GetByName(const String& name)
{
Dictionary::Ptr typesNS = ScriptGlobal::Get("Types", &Empty);
Namespace::Ptr typesNS = ScriptGlobal::Get("Types", &Empty);
if (!typesNS)
return nullptr;
Value ptype = typesNS->Get(name);
Value ptype;
if (!typesNS->Get(name, &ptype))
return nullptr;
if (!ptype.IsObjectType<Type>())
return nullptr;
@ -63,14 +64,16 @@ std::vector<Type::Ptr> Type::GetAllTypes()
{
std::vector<Type::Ptr> types;
Dictionary::Ptr typesNS = ScriptGlobal::Get("Types", &Empty);
Namespace::Ptr typesNS = ScriptGlobal::Get("Types", &Empty);
if (typesNS) {
ObjectLock olock(typesNS);
for (const Dictionary::Pair& kv : typesNS) {
if (kv.second.IsObjectType<Type>())
types.push_back(kv.second);
for (const Namespace::Pair& kv : typesNS) {
Value value = kv.second->Get();
if (value.IsObjectType<Type>())
types.push_back(value);
}
}

View File

@ -648,7 +648,7 @@ lterm: T_LIBRARY rterm
}
| T_CONST T_IDENTIFIER T_SET rterm
{
$$ = new SetExpression(MakeIndexer(ScopeGlobal, *$2), OpSetLiteral, std::unique_ptr<Expression>($4));
$$ = new SetConstExpression(*$2, std::unique_ptr<Expression>($4), @$);
delete $2;
}
| T_VAR rterm

View File

@ -31,6 +31,7 @@ ConfigItemBuilder::ConfigItemBuilder(const DebugInfo& debugInfo)
void ConfigItemBuilder::SetType(const Type::Ptr& type)
{
ASSERT(type);
m_Type = type;
}

View File

@ -29,6 +29,7 @@
#include "base/scriptglobal.hpp"
#include "base/loader.hpp"
#include "base/reference.hpp"
#include "base/namespace.hpp"
#include <boost/exception_ptr.hpp>
#include <boost/exception/errinfo_nested_exception.hpp>
@ -625,6 +626,28 @@ void SetExpression::SetOverrideFrozen()
m_OverrideFrozen = true;
}
ExpressionResult SetConstExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
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);
CHECK_RESULT(operandres);
Value operand = operandres.GetValue();
globals->SetAttribute(m_Name, std::make_shared<ConstEmbeddedNamespaceValue>(operand));
return Empty;
}
ExpressionResult ConditionalExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
ExpressionResult condition = m_Condition->Evaluate(frame, dhint);
@ -701,7 +724,16 @@ bool IndexerExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *
if (m_Operand1->GetReference(frame, init_dict, &vparent, &vindex, &psdhint)) {
if (init_dict) {
Value old_value = VMOps::GetField(vparent, vindex, frame.Sandboxed, m_Operand1->GetDebugInfo());
Value old_value;
bool has_field = true;
if (vparent.IsObject()) {
Object::Ptr oparent = vparent;
has_field = oparent->HasOwnField(vindex);
}
if (has_field)
old_value = VMOps::GetField(vparent, vindex, frame.Sandboxed, m_Operand1->GetDebugInfo());
if (old_value.IsEmpty() && !old_value.IsString())
VMOps::SetField(vparent, vindex, new Dictionary(), m_OverrideFrozen, m_Operand1->GetDebugInfo());

View File

@ -637,6 +637,19 @@ private:
friend void BindToScope(std::unique_ptr<Expression>& expr, ScopeSpecifier scopeSpec);
};
class SetConstExpression final : public UnaryExpression
{
public:
SetConstExpression(const String& name, std::unique_ptr<Expression> operand, const DebugInfo& debugInfo = DebugInfo())
: UnaryExpression(std::move(operand), debugInfo), m_Name(name)
{ }
protected:
String m_Name;
ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const override;
};
class SetExpression final : public BinaryExpression
{
public:

View File

@ -28,6 +28,7 @@
#include "base/debuginfo.hpp"
#include "base/array.hpp"
#include "base/dictionary.hpp"
#include "base/namespace.hpp"
#include "base/function.hpp"
#include "base/scriptglobal.hpp"
#include "base/exception.hpp"
@ -225,6 +226,26 @@ public:
ExpressionResult res = expression->Evaluate(frame);
CHECK_RESULT_LOOP(res);
}
} else if (value.IsObjectType<Namespace>()) {
if (fvvar.IsEmpty())
BOOST_THROW_EXCEPTION(ScriptError("Cannot use array iterator for namespace.", debugInfo));
Namespace::Ptr ns = value;
std::vector<String> keys;
{
ObjectLock olock(ns);
for (const Namespace::Pair& kv : ns) {
keys.push_back(kv.first);
}
}
for (const String& key : keys) {
frame.Locals->Set(fkvar, key);
frame.Locals->Set(fvvar, ns->Get(key));
ExpressionResult res = expression->Evaluate(frame);
CHECK_RESULT_LOOP(res);
}
} else
BOOST_THROW_EXCEPTION(ScriptError("Invalid type in for expression: " + value.GetTypeName(), debugInfo));

View File

@ -18,10 +18,8 @@
******************************************************************************/
System.assert(Internal.run_with_activation_context(function() {
var _Internal = Internal.clone()
template CheckCommand "ido-check-command" use (_Internal) {
execute = _Internal.IdoCheck
template CheckCommand "ido-check-command" use (checkFunc = Internal.IdoCheck) {
execute = checkFunc
}
object CheckCommand "ido" {

View File

@ -32,7 +32,7 @@
using namespace icinga;
REGISTER_FUNCTION(Internal, IdoCheck, &IdoCheckTask::ScriptFunc, "checkable:cr:resolvedMacros:useResolvedMacros");
REGISTER_FUNCTION_NONCONST(Internal, IdoCheck, &IdoCheckTask::ScriptFunc, "checkable:cr:resolvedMacros:useResolvedMacros");
void IdoCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr,
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)

View File

@ -268,13 +268,13 @@ std::pair<Dictionary::Ptr, Array::Ptr> CIB::GetFeatureStats()
Dictionary::Ptr status = new Dictionary();
Array::Ptr perfdata = new Array();
Dictionary::Ptr statsFunctions = ScriptGlobal::Get("StatsFunctions", &Empty);
Namespace::Ptr statsFunctions = ScriptGlobal::Get("StatsFunctions", &Empty);
if (statsFunctions) {
ObjectLock olock(statsFunctions);
for (const Dictionary::Pair& kv : statsFunctions)
static_cast<Function::Ptr>(kv.second)->Invoke({ status, perfdata });
for (const Namespace::Pair& kv : statsFunctions)
static_cast<Function::Ptr>(kv.second->Get())->Invoke({ status, perfdata });
}
return std::make_pair(status, perfdata);

View File

@ -18,10 +18,8 @@
******************************************************************************/
System.assert(Internal.run_with_activation_context(function() {
var _Internal = Internal.clone()
template TimePeriod "legacy-timeperiod" use (_Internal) default {
update = _Internal.LegacyTimePeriod
template TimePeriod "legacy-timeperiod" use (LegacyTimePeriod = Internal.LegacyTimePeriod) default {
update = LegacyTimePeriod
}
}))

View File

@ -28,7 +28,7 @@
using namespace icinga;
REGISTER_FUNCTION(Internal, LegacyTimePeriod, &LegacyTimePeriod::ScriptFunc, "tp:begin:end");
REGISTER_FUNCTION_NONCONST(Internal, LegacyTimePeriod, &LegacyTimePeriod::ScriptFunc, "tp:begin:end");
bool LegacyTimePeriod::IsInTimeRange(tm *begin, tm *end, int stride, tm *reference)
{

View File

@ -33,7 +33,7 @@
using namespace icinga;
REGISTER_FUNCTION(Internal, ClusterCheck, &ClusterCheckTask::ScriptFunc, "checkable:cr:resolvedMacros:useResolvedMacros");
REGISTER_FUNCTION_NONCONST(Internal, ClusterCheck, &ClusterCheckTask::ScriptFunc, "checkable:cr:resolvedMacros:useResolvedMacros");
void ClusterCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr,
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)

View File

@ -29,7 +29,7 @@
using namespace icinga;
REGISTER_FUNCTION(Internal, ClusterZoneCheck, &ClusterZoneCheckTask::ScriptFunc, "checkable:cr:resolvedMacros:useResolvedMacros");
REGISTER_FUNCTION_NONCONST(Internal, ClusterZoneCheck, &ClusterZoneCheckTask::ScriptFunc, "checkable:cr:resolvedMacros:useResolvedMacros");
void ClusterZoneCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr,
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)

View File

@ -31,7 +31,7 @@
using namespace icinga;
REGISTER_FUNCTION(Internal, DummyCheck, &DummyCheckTask::ScriptFunc, "checkable:cr:resolvedMacros:useResolvedMacros");
REGISTER_FUNCTION_NONCONST(Internal, DummyCheck, &DummyCheckTask::ScriptFunc, "checkable:cr:resolvedMacros:useResolvedMacros");
void DummyCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr,
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)

View File

@ -29,7 +29,7 @@
using namespace icinga;
REGISTER_FUNCTION(Internal, ExceptionCheck, &ExceptionCheckTask::ScriptFunc, "checkable:cr:resolvedMacros:useResolvedMacros");
REGISTER_FUNCTION_NONCONST(Internal, ExceptionCheck, &ExceptionCheckTask::ScriptFunc, "checkable:cr:resolvedMacros:useResolvedMacros");
void ExceptionCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr,
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)

View File

@ -34,7 +34,7 @@
using namespace icinga;
REGISTER_FUNCTION(Internal, IcingaCheck, &IcingaCheckTask::ScriptFunc, "checkable:cr:resolvedMacros:useResolvedMacros");
REGISTER_FUNCTION_NONCONST(Internal, IcingaCheck, &IcingaCheckTask::ScriptFunc, "checkable:cr:resolvedMacros:useResolvedMacros");
void IcingaCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr,
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)

View File

@ -18,68 +18,58 @@
******************************************************************************/
System.assert(Internal.run_with_activation_context(function() {
var _Internal = Internal.clone()
template CheckCommand "icinga-check-command" use (_Internal) {
execute = _Internal.IcingaCheck
template CheckCommand "icinga-check-command" use (IcingaCheck = Internal.IcingaCheck) {
execute = IcingaCheck
vars.icinga_min_version = ""
}
template CheckCommand "cluster-check-command" use (_Internal) {
execute = _Internal.ClusterCheck
template CheckCommand "cluster-check-command" use (ClusterCheck = Internal.ClusterCheck) {
execute = ClusterCheck
}
template CheckCommand "cluster-zone-check-command" use (_Internal) {
execute = _Internal.ClusterZoneCheck
template CheckCommand "cluster-zone-check-command" use (ClusterZoneCheck = Internal.ClusterZoneCheck) {
execute = ClusterZoneCheck
}
template CheckCommand "plugin-check-command" use (_Internal) default {
execute = _Internal.PluginCheck
template CheckCommand "plugin-check-command" use (PluginCheck = Internal.PluginCheck) default {
execute = PluginCheck
}
template CheckCommand "clr-check-command" use (_Internal) {
if (_Internal.ClrCheck) {
execute = _Internal.ClrCheck
} else {
execute = _Internal.NullCheck
}
template NotificationCommand "plugin-notification-command" use (PluginNotification = Internal.PluginNotification) default {
execute = PluginNotification
}
template NotificationCommand "plugin-notification-command" use (_Internal) default {
execute = _Internal.PluginNotification
template EventCommand "plugin-event-command" use (PluginEvent = Internal.PluginEvent) default {
execute = PluginEvent
}
template EventCommand "plugin-event-command" use (_Internal) default {
execute = _Internal.PluginEvent
template CheckCommand "dummy-check-command" use (DummyCheck = Internal.DummyCheck) {
execute = DummyCheck
}
template CheckCommand "dummy-check-command" use (_Internal) {
execute = _Internal.DummyCheck
template CheckCommand "random-check-command" use (RandomCheck = Internal.RandomCheck) {
execute = RandomCheck
}
template CheckCommand "random-check-command" use (_Internal) {
execute = _Internal.RandomCheck
template CheckCommand "exception-check-command" use (ExceptionCheck = Internal.ExceptionCheck) {
execute = ExceptionCheck
}
template CheckCommand "exception-check-command" use (_Internal) {
execute = _Internal.ExceptionCheck
template CheckCommand "null-check-command" use (NullCheck = Internal.NullCheck) {
execute = NullCheck
}
template CheckCommand "null-check-command" use (_Internal) {
execute = _Internal.NullCheck
template EventCommand "null-event-command" use (NullEvent = Internal.NullEvent) {
execute = NullEvent
}
template EventCommand "null-event-command" use (_Internal) {
execute = _Internal.NullEvent
template TimePeriod "empty-timeperiod" use (EmptyTimePeriod = Internal.EmptyTimePeriod) {
update = EmptyTimePeriod
}
template TimePeriod "empty-timeperiod" use (_Internal) {
update = _Internal.EmptyTimePeriod
}
template TimePeriod "even-minutes-timeperiod" use (_Internal) {
update = _Internal.EvenMinutesTimePeriod
template TimePeriod "even-minutes-timeperiod" use (EvenMinutesTimePeriod = Internal.EvenMinutesTimePeriod) {
update = EvenMinutesTimePeriod
}
}))

View File

@ -30,7 +30,7 @@
using namespace icinga;
REGISTER_FUNCTION(Internal, NullCheck, &NullCheckTask::ScriptFunc, "checkable:cr:resolvedMacros:useResolvedMacros");
REGISTER_FUNCTION_NONCONST(Internal, NullCheck, &NullCheckTask::ScriptFunc, "checkable:cr:resolvedMacros:useResolvedMacros");
void NullCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr,
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)

View File

@ -23,7 +23,7 @@
using namespace icinga;
REGISTER_FUNCTION(Internal, NullEvent, &NullEventTask::ScriptFunc, "checkable:resolvedMacros:useResolvedMacros");
REGISTER_FUNCTION_NONCONST(Internal, NullEvent, &NullEventTask::ScriptFunc, "checkable:resolvedMacros:useResolvedMacros");
void NullEventTask::ScriptFunc(const Checkable::Ptr& checkable, const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
{

View File

@ -31,7 +31,7 @@
using namespace icinga;
REGISTER_FUNCTION(Internal, PluginCheck, &PluginCheckTask::ScriptFunc, "checkable:cr:resolvedMacros:useResolvedMacros");
REGISTER_FUNCTION_NONCONST(Internal, PluginCheck, &PluginCheckTask::ScriptFunc, "checkable:cr:resolvedMacros:useResolvedMacros");
void PluginCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr,
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)

View File

@ -31,7 +31,7 @@
using namespace icinga;
REGISTER_FUNCTION(Internal, PluginEvent, &PluginEventTask::ScriptFunc, "checkable:resolvedMacros:useResolvedMacros");
REGISTER_FUNCTION_NONCONST(Internal, PluginEvent, &PluginEventTask::ScriptFunc, "checkable:resolvedMacros:useResolvedMacros");
void PluginEventTask::ScriptFunc(const Checkable::Ptr& checkable,
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)

View File

@ -32,7 +32,7 @@
using namespace icinga;
REGISTER_FUNCTION(Internal, PluginNotification, &PluginNotificationTask::ScriptFunc, "notification:user:cr:itype:author:comment:resolvedMacros:useResolvedMacros");
REGISTER_FUNCTION_NONCONST(Internal, PluginNotification, &PluginNotificationTask::ScriptFunc, "notification:user:cr:itype:author:comment:resolvedMacros:useResolvedMacros");
void PluginNotificationTask::ScriptFunc(const Notification::Ptr& notification,
const User::Ptr& user, const CheckResult::Ptr& cr, int itype,

View File

@ -29,7 +29,7 @@
using namespace icinga;
REGISTER_FUNCTION(Internal, RandomCheck, &RandomCheckTask::ScriptFunc, "checkable:cr:resolvedMacros:useResolvedMacros");
REGISTER_FUNCTION_NONCONST(Internal, RandomCheck, &RandomCheckTask::ScriptFunc, "checkable:cr:resolvedMacros:useResolvedMacros");
void RandomCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr,
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)

View File

@ -22,8 +22,8 @@
using namespace icinga;
REGISTER_FUNCTION(Internal, EmptyTimePeriod, &TimePeriodTask::EmptyTimePeriodUpdate, "tp:begin:end");
REGISTER_FUNCTION(Internal, EvenMinutesTimePeriod, &TimePeriodTask::EvenMinutesTimePeriodUpdate, "tp:begin:end");
REGISTER_FUNCTION_NONCONST(Internal, EmptyTimePeriod, &TimePeriodTask::EmptyTimePeriodUpdate, "tp:begin:end");
REGISTER_FUNCTION_NONCONST(Internal, EvenMinutesTimePeriod, &TimePeriodTask::EvenMinutesTimePeriodUpdate, "tp:begin:end");
Array::Ptr TimePeriodTask::EmptyTimePeriodUpdate(const TimePeriod::Ptr& tp, double, double)
{

View File

@ -27,6 +27,7 @@
#include "base/logger.hpp"
#include "base/serializer.hpp"
#include "base/timer.hpp"
#include "base/namespace.hpp"
#include "base/initialize.hpp"
#include <boost/thread/once.hpp>
#include <set>
@ -233,6 +234,15 @@ static void AddSuggestions(std::vector<String>& matches, const String& word, con
}
}
if (value.IsObjectType<Namespace>()) {
Namespace::Ptr ns = value;
ObjectLock olock(ns);
for (const Namespace::Pair& kv : ns) {
AddSuggestion(matches, word, prefix + kv.first);
}
}
if (withFields) {
Type::Ptr type = value.GetReflectionType();
@ -275,7 +285,7 @@ std::vector<String> ConsoleHandler::GetAutocompletionSuggestions(const String& w
{
ObjectLock olock(ScriptGlobal::GetGlobals());
for (const Dictionary::Pair& kv : ScriptGlobal::GetGlobals()) {
for (const Namespace::Pair& kv : ScriptGlobal::GetGlobals()) {
AddSuggestion(matches, word, kv.first);
}
}

View File

@ -37,7 +37,7 @@ static bool GetDebugJsonRpcCached()
debugJsonRpc = false;
Dictionary::Ptr internal = ScriptGlobal::Get("Internal", &Empty);
Namespace::Ptr internal = ScriptGlobal::Get("Internal", &Empty);
if (!internal)
return false;

View File

@ -22,6 +22,7 @@
#include "remote/filterutility.hpp"
#include "base/serializer.hpp"
#include "base/statsfunction.hpp"
#include "base/namespace.hpp"
using namespace icinga;
@ -35,24 +36,29 @@ public:
void FindTargets(const String& type,
const std::function<void (const Value&)>& addTarget) const override
{
Dictionary::Ptr statsFunctions = ScriptGlobal::Get("StatsFunctions", &Empty);
Namespace::Ptr statsFunctions = ScriptGlobal::Get("StatsFunctions", &Empty);
if (statsFunctions) {
ObjectLock olock(statsFunctions);
for (const Dictionary::Pair& kv : statsFunctions)
for (const Namespace::Pair& kv : statsFunctions)
addTarget(GetTargetByName("Status", kv.first));
}
}
Value GetTargetByName(const String& type, const String& name) const override
{
Dictionary::Ptr statsFunctions = ScriptGlobal::Get("StatsFunctions", &Empty);
Namespace::Ptr statsFunctions = ScriptGlobal::Get("StatsFunctions", &Empty);
if (!statsFunctions)
BOOST_THROW_EXCEPTION(std::invalid_argument("No status functions are available."));
Function::Ptr func = statsFunctions->Get(name);
Value vfunc;
if (!statsFunctions->Get(name, &vfunc))
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid status function name."));
Function::Ptr func = vfunc;
if (!func)
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid status function name."));

View File

@ -24,6 +24,7 @@
#include "base/scriptglobal.hpp"
#include "base/logger.hpp"
#include "base/serializer.hpp"
#include "base/namespace.hpp"
#include <set>
using namespace icinga;
@ -48,10 +49,10 @@ public:
const std::function<void (const Value&)>& addTarget) const override
{
{
Dictionary::Ptr globals = ScriptGlobal::GetGlobals();
Namespace::Ptr globals = ScriptGlobal::GetGlobals();
ObjectLock olock(globals);
for (const Dictionary::Pair& kv : globals) {
addTarget(GetTargetForVar(kv.first, kv.second));
for (const Namespace::Pair& kv : globals) {
addTarget(GetTargetForVar(kv.first, kv.second->Get()));
}
}
}