Refactor ScriptFunctions.

This commit is contained in:
Gunnar Beutner 2013-03-25 19:47:02 +00:00
parent ba152d6dc4
commit 70e96aa2f0
19 changed files with 266 additions and 91 deletions

View File

@ -335,17 +335,8 @@ void CompatLog::RotationTimerHandler(void)
ScheduleNextRotation();
}
Value CompatLog::ValidateRotationMethod(const std::vector<Value>& arguments)
void CompatLog::ValidateRotationMethod(const String& location, const Dictionary::Ptr& attrs)
{
if (arguments.size() < 1)
BOOST_THROW_EXCEPTION(std::invalid_argument("Missing argument: Location must be specified."));
if (arguments.size() < 2)
BOOST_THROW_EXCEPTION(std::invalid_argument("Missing argument: Attribute dictionary must be specified."));
String location = arguments[0];
Dictionary::Ptr attrs = arguments[1];
Value rotation_method = attrs->Get("rotation_method");
if (!rotation_method.IsEmpty() && rotation_method != "HOURLY" && rotation_method != "DAILY" &&
@ -353,6 +344,4 @@ Value CompatLog::ValidateRotationMethod(const std::vector<Value>& arguments)
ConfigCompilerContext::GetContext()->AddError(false, "Validation failed for " +
location + ": Rotation method '" + rotation_method + "' is invalid.");
}
return Empty;
}

View File

@ -46,7 +46,7 @@ public:
String GetLogDir(void) const;
String GetRotationMethod(void) const;
static Value ValidateRotationMethod(const std::vector<Value>& arguments);
static void ValidateRotationMethod(const String& location, const Dictionary::Ptr& attrs);
protected:
virtual void OnAttributeChanged(const String& name);

View File

@ -51,6 +51,8 @@ libbase_la_SOURCES = \
script.h \
scriptfunction.cpp \
scriptfunction.h \
scriptfunctionwrapper.cpp \
scriptfunctionwrapper.h \
scriptinterpreter.cpp \
scriptinterpreter.h \
scriptlanguage.cpp \

View File

@ -40,6 +40,7 @@
<ClCompile Include="qstring.cpp" />
<ClCompile Include="ringbuffer.cpp" />
<ClCompile Include="scriptfunction.cpp" />
<ClCompile Include="scriptfunctionwrapper.cpp" />
<ClCompile Include="socket.cpp" />
<ClCompile Include="stacktrace.cpp" />
<ClCompile Include="stdiostream.cpp" />
@ -75,6 +76,7 @@
<ClInclude Include="netstring.h" />
<ClInclude Include="qstring.h" />
<ClInclude Include="scriptfunction.h" />
<ClInclude Include="scriptfunctionwrapper.h" />
<ClInclude Include="logger.h" />
<ClInclude Include="exception.h" />
<ClInclude Include="i2-base.h" />

View File

@ -23,14 +23,13 @@
#include "base/i2-base.h"
#include "base/registry.h"
#include "base/value.h"
#include "base/scriptfunctionwrapper.h"
#include <vector>
#include <boost/function.hpp>
namespace icinga
{
class ScriptTask;
/**
* A script function that can be used to execute a script task.
*
@ -72,7 +71,7 @@ public:
};
#define REGISTER_SCRIPTFUNCTION(name, callback) \
I2_EXPORT icinga::RegisterFunctionHelper g_RegisterSF_ ## name(#name, callback)
I2_EXPORT icinga::RegisterFunctionHelper g_RegisterSF_ ## name(#name, WrapScriptFunction(callback))
}

View File

@ -0,0 +1,39 @@
/******************************************************************************
* 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 "base/scriptfunctionwrapper.h"
using namespace icinga;
Value icinga::ScriptFunctionWrapperVV(void (*function)(void), const std::vector<Value>& arguments)
{
function();
return Empty;
}
boost::function<Value (const std::vector<Value>& arguments)> icinga::WrapScriptFunction(void (*function)(void))
{
return boost::bind(&ScriptFunctionWrapperVV, function, _1);
}
boost::function<Value (const std::vector<Value>& arguments)> icinga::WrapScriptFunction(Value (*function)(const std::vector<Value>&))
{
return boost::bind(function, _1);
}

View File

@ -0,0 +1,192 @@
/******************************************************************************
* 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 SCRIPTFUNCTIONWRAPPER_H
#define SCRIPTFUNCTIONWRAPPER_H
#include "base/i2-base.h"
#include "base/value.h"
#include <vector>
#include <boost/function.hpp>
#include <boost/bind.hpp>
namespace icinga
{
Value ScriptFunctionWrapperVV(void (*function)(void), const std::vector<Value>& arguments);
boost::function<Value (const std::vector<Value>& arguments)> I2_BASE_API WrapScriptFunction(void (*function)(void));
template<typename TR>
Value ScriptFunctionWrapperR(TR (*function)(void), const std::vector<Value>& arguments)
{
return function();
}
template<typename TR>
boost::function<Value (const std::vector<Value>& arguments)> WrapScriptFunction(TR (*function)(void))
{
return boost::bind(&ScriptFunctionWrapperR<TR>, function, _1);
}
template<typename T0>
Value ScriptFunctionWrapperV(void (*function)(T0), const std::vector<Value>& arguments)
{
if (arguments.size() < 1)
BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function."));
function(static_cast<T0>(arguments[0]));
return Empty;
}
template<typename T0>
boost::function<Value (const std::vector<Value>& arguments)> WrapScriptFunction(void (*function)(T0))
{
return boost::bind(&ScriptFunctionWrapperV<T0>, function, _1);
}
template<typename TR, typename T0>
Value ScriptFunctionWrapperR(TR (*function)(T0), const std::vector<Value>& arguments)
{
if (arguments.size() < 1)
BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function."));
return function(static_cast<T0>(arguments[0]));
}
template<typename TR, typename T0>
boost::function<Value (const std::vector<Value>& arguments)> WrapScriptFunction(TR (*function)(T0))
{
return boost::bind(&ScriptFunctionWrapperR<TR, T0>, function, _1);
}
template<typename T0, typename T1>
Value ScriptFunctionWrapperV(void (*function)(T0, T1), const std::vector<Value>& arguments)
{
if (arguments.size() < 2)
BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function."));
function(static_cast<T0>(arguments[0]),
static_cast<T1>(arguments[1]));
return Empty;
}
template<typename T0, typename T1>
boost::function<Value (const std::vector<Value>& arguments)> WrapScriptFunction(void (*function)(T0, T1))
{
return boost::bind(&ScriptFunctionWrapperV<T0, T1>, function, _1);
}
template<typename TR, typename T0, typename T1>
Value ScriptFunctionWrapperR(TR (*function)(T0, T1), const std::vector<Value>& arguments)
{
if (arguments.size() < 2)
BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function."));
return function(static_cast<T0>(arguments[0]),
static_cast<T1>(arguments[1]));
}
template<typename TR, typename T0, typename T1>
boost::function<Value (const std::vector<Value>& arguments)> WrapScriptFunction(TR (*function)(T0, T1))
{
return boost::bind(&ScriptFunctionWrapperR<TR, T0, T1>, function, _1);
}
template<typename T0, typename T1, typename T2>
Value ScriptFunctionWrapperV(void (*function)(T0, T1, T2), const std::vector<Value>& arguments)
{
if (arguments.size() < 3)
BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function."));
function(static_cast<T0>(arguments[0]),
static_cast<T1>(arguments[1]),
static_cast<T2>(arguments[2]));
return Empty;
}
template<typename T0, typename T1, typename T2>
boost::function<Value (const std::vector<Value>& arguments)> WrapScriptFunction(void (*function)(T0, T1, T2))
{
return boost::bind(&ScriptFunctionWrapperV<T0, T1, T2>, function, _1);
}
template<typename TR, typename T0, typename T1, typename T2>
Value ScriptFunctionWrapperR(TR (*function)(T0, T1, T2), const std::vector<Value>& arguments)
{
if (arguments.size() < 3)
BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function."));
return function(static_cast<T0>(arguments[0]),
static_cast<T1>(arguments[1]),
static_cast<T2>(arguments[2]));
}
template<typename TR, typename T0, typename T1, typename T2>
boost::function<Value (const std::vector<Value>& arguments)> WrapScriptFunction(TR (*function)(T0, T1, T2))
{
return boost::bind(&ScriptFunctionWrapperR<TR, T0, T1, T2>, function, _1);
}
template<typename T0, typename T1, typename T2, typename T3>
Value ScriptFunctionWrapperV(void (*function)(T0, T1, T2, T3), const std::vector<Value>& arguments)
{
if (arguments.size() < 4)
BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function."));
function(static_cast<T0>(arguments[0]),
static_cast<T1>(arguments[1]),
static_cast<T2>(arguments[2]),
static_cast<T3>(arguments[3]));
return Empty;
}
template<typename T0, typename T1, typename T2, typename T3>
boost::function<Value (const std::vector<Value>& arguments)> WrapScriptFunction(void (*function)(T0, T1, T2, T3))
{
return boost::bind(&ScriptFunctionWrapperV<T0, T1, T2, T3>, function, _1);
}
template<typename TR, typename T0, typename T1, typename T2, typename T3>
Value ScriptFunctionWrapperR(TR (*function)(T0, T1, T2, T3), const std::vector<Value>& arguments)
{
if (arguments.size() < 4)
BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function."));
return function(static_cast<T0>(arguments[0]),
static_cast<T1>(arguments[1]),
static_cast<T2>(arguments[2]),
static_cast<T3>(arguments[3]));
}
template<typename TR, typename T0, typename T1, typename T2, typename T3>
boost::function<Value (const std::vector<Value>& arguments)> WrapScriptFunction(TR (*function)(T0, T1, T2, T3))
{
return boost::bind(&ScriptFunctionWrapperR<TR, T0, T1, T2, T3>, function, _1);
}
boost::function<Value (const std::vector<Value>& arguments)> I2_BASE_API WrapScriptFunction(Value (*function)(const std::vector<Value>&));
}
#endif /* SCRIPTFUNCTION_H */

View File

@ -25,13 +25,8 @@ using namespace icinga;
REGISTER_SCRIPTFUNCTION(GetAnswerToEverything, &API::GetAnswerToEverything);
Value API::GetAnswerToEverything(const std::vector<Value>& arguments)
int API::GetAnswerToEverything(const String& text)
{
if (arguments.size() < 1)
BOOST_THROW_EXCEPTION(std::invalid_argument("Text argument required."));
String text = arguments[0];
Log(LogInformation, "icinga", "Hello from the Icinga 2 API: " + text);
return 42;

View File

@ -35,7 +35,7 @@ namespace icinga
class I2_ICINGA_API API
{
public:
static Value GetAnswerToEverything(const std::vector<Value>& arguments);
static int GetAnswerToEverything(const String& text);
private:
API(void);

View File

@ -352,16 +352,8 @@ void Host::RefreshServicesCache(void)
l_ServicesCache.swap(newServicesCache);
}
Value Host::ValidateServiceDictionary(const std::vector<Value>& arguments)
Value Host::ValidateServiceDictionary(const String& location, const Dictionary::Ptr& attrs)
{
if (arguments.size() < 1)
BOOST_THROW_EXCEPTION(std::invalid_argument("Missing argument: Location must be specified."));
if (arguments.size() < 2)
BOOST_THROW_EXCEPTION(std::invalid_argument("Missing argument: Attribute dictionary must be specified."));
String location = arguments[0];
Dictionary::Ptr attrs = arguments[1];
ObjectLock olock(attrs);
String key;

View File

@ -103,7 +103,7 @@ public:
std::set<shared_ptr<Service> > GetServices(void) const;
static void InvalidateServicesCache(void);
static Value ValidateServiceDictionary(const std::vector<icinga::Value>& arguments);
static Value ValidateServiceDictionary(const String& location, const Dictionary::Ptr& attrs);
static HostState CalculateState(ServiceState state, bool reachable);

View File

@ -19,7 +19,6 @@
#include "icinga/nullchecktask.h"
#include "icinga/service.h"
#include "base/dictionary.h"
#include "base/scriptfunction.h"
#include <boost/smart_ptr/make_shared.hpp>
@ -27,11 +26,8 @@ using namespace icinga;
REGISTER_SCRIPTFUNCTION(NullCheck, &NullCheckTask::ScriptFunc);
Value NullCheckTask::ScriptFunc(const std::vector<Value>& arguments)
Dictionary::Ptr NullCheckTask::ScriptFunc(const Service::Ptr&)
{
if (arguments.size() < 1)
BOOST_THROW_EXCEPTION(std::invalid_argument("Missing argument: Service must be specified."));
Dictionary::Ptr cr = boost::make_shared<Dictionary>();
cr->Set("state", StateUnknown);

View File

@ -21,7 +21,8 @@
#define NULLCHECKTASK_H
#include "icinga/i2-icinga.h"
#include "base/value.h"
#include "icinga/service.h"
#include "base/dictionary.h"
namespace icinga
{
@ -34,7 +35,7 @@ namespace icinga
class I2_ICINGA_API NullCheckTask
{
public:
static Value ScriptFunc(const std::vector<Value>& arguments);
static Dictionary::Ptr ScriptFunc(const Service::Ptr& service);
private:
NullCheckTask(void);

View File

@ -24,6 +24,7 @@
#include "base/logger_fwd.h"
#include "base/scriptfunction.h"
#include "base/utility.h"
#include "base/process.h"
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/smart_ptr/make_shared.hpp>
@ -33,13 +34,8 @@ using namespace icinga;
REGISTER_SCRIPTFUNCTION(PluginCheck, &PluginCheckTask::ScriptFunc);
Value PluginCheckTask::ScriptFunc(const std::vector<Value>& arguments)
Value PluginCheckTask::ScriptFunc(const Service::Ptr& service)
{
if (arguments.size() < 1)
BOOST_THROW_EXCEPTION(std::invalid_argument("Missing argument: Service must be specified."));
Service::Ptr service = arguments[0];
Value raw_command = service->GetCheckCommand();
std::vector<MacroResolver::Ptr> resolvers;

View File

@ -22,7 +22,6 @@
#include "icinga/i2-icinga.h"
#include "icinga/service.h"
#include "base/process.h"
namespace icinga
{
@ -35,7 +34,7 @@ namespace icinga
class I2_ICINGA_API PluginCheckTask
{
public:
static Value ScriptFunc(const std::vector<Value>& arguments);
static Value ScriptFunc(const Service::Ptr& service);
static ServiceState ExitStatusToState(int exitStatus);
static Dictionary::Ptr ParseCheckOutput(const String& output);

View File

@ -26,31 +26,17 @@
#include "base/logger_fwd.h"
#include "base/utility.h"
#include "base/convert.h"
#include "base/process.h"
#include <boost/smart_ptr/make_shared.hpp>
#include <boost/foreach.hpp>
using namespace icinga;
REGISTER_SCRIPTFUNCTION(PluginNotification, &PluginNotificationTask::ScriptFunc);
REGISTER_SCRIPTFUNCTION(PluginNotification, &PluginNotificationTask::ScriptFunc);
Value PluginNotificationTask::ScriptFunc(const std::vector<Value>& arguments)
void PluginNotificationTask::ScriptFunc(const Notification::Ptr& notification, const User::Ptr& user, const Dictionary::Ptr& cr, int itype)
{
if (arguments.size() < 1)
BOOST_THROW_EXCEPTION(std::invalid_argument("Missing argument: Notification target must be specified."));
if (arguments.size() < 2)
BOOST_THROW_EXCEPTION(std::invalid_argument("Missing argument: User must be specified."));
if (arguments.size() < 3)
BOOST_THROW_EXCEPTION(std::invalid_argument("Missing argument: CheckResult must be specified."));
if (arguments.size() < 4)
BOOST_THROW_EXCEPTION(std::invalid_argument("Missing argument: Notification type must be specified."));
Notification::Ptr notification = arguments[0];
User::Ptr user = arguments[1];
Dictionary::Ptr cr = arguments[2];
NotificationType type = static_cast<NotificationType>(static_cast<int>(arguments[3]));
NotificationType type = static_cast<NotificationType>(itype);
Service::Ptr service = notification->GetService();
@ -97,6 +83,4 @@ Value PluginNotificationTask::ScriptFunc(const std::vector<Value>& arguments)
<< pr.ExitStatus << ", output: " << pr.Output;
Log(LogWarning, "icinga", msgbuf.str());
}
return Empty;
}

View File

@ -21,7 +21,7 @@
#define PLUGINNOTIFICATIONTASK_H
#include "icinga/i2-icinga.h"
#include "base/process.h"
#include "icinga/notification.h"
namespace icinga
{
@ -34,7 +34,8 @@ namespace icinga
class I2_ICINGA_API PluginNotificationTask
{
public:
static Value ScriptFunc(const std::vector<Value>& arguments);
static void ScriptFunc(const Notification::Ptr& notification,
const User::Ptr& user, const Dictionary::Ptr& cr, int itype);
private:
PluginNotificationTask(void);

View File

@ -217,9 +217,11 @@ void TimePeriod::UpdateRegion(double begin, double end)
ObjectLock olock(this);
RemoveSegment(begin, end);
ObjectLock dlock(segments);
BOOST_FOREACH(const Dictionary::Ptr& segment, segments) {
AddSegment(segment);
if (segments) {
ObjectLock dlock(segments);
BOOST_FOREACH(const Dictionary::Ptr& segment, segments) {
AddSegment(segment);
}
}
}
}
@ -291,28 +293,14 @@ void TimePeriod::UpdateTimerHandler(void)
}
}
Value TimePeriod::EmptyTimePeriodUpdate(const std::vector<Value>& arguments)
Array::Ptr TimePeriod::EmptyTimePeriodUpdate(const TimePeriod::Ptr tp, double begin, double end)
{
if (arguments.size() < 3)
BOOST_THROW_EXCEPTION(std::runtime_error("Expected 3 arguments."));
// TimePeriod::Ptr tp = arguments[0];
// double begin = arguments[1];
// double end = arguments[2];
Array::Ptr segments = boost::make_shared<Array>();
return segments;
}
Value TimePeriod::EvenMinutesTimePeriodUpdate(const std::vector<Value>& arguments)
Array::Ptr TimePeriod::EvenMinutesTimePeriodUpdate(const TimePeriod::Ptr tp, double begin, double end)
{
if (arguments.size() < 3)
BOOST_THROW_EXCEPTION(std::runtime_error("Expected 3 arguments."));
TimePeriod::Ptr tp = arguments[0];
double begin = arguments[1];
double end = arguments[2];
Array::Ptr segments = boost::make_shared<Array>();
for (long t = begin / 60 - 1; t * 60 < end; t++) {

View File

@ -49,8 +49,8 @@ public:
bool IsInside(double ts) const;
double FindNextTransition(double begin);
static Value EmptyTimePeriodUpdate(const std::vector<Value>& arguments);
static Value EvenMinutesTimePeriodUpdate(const std::vector<Value>& arguments);
static Array::Ptr EmptyTimePeriodUpdate(const TimePeriod::Ptr tp, double begin, double end);
static Array::Ptr EvenMinutesTimePeriodUpdate(const TimePeriod::Ptr tp, double begin, double end);
private:
Attribute<double> m_ValidBegin;