From 70e96aa2f0fe26d63fb5e2333010150cfef2a286 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Mon, 25 Mar 2013 19:47:02 +0000 Subject: [PATCH] Refactor ScriptFunctions. --- components/compat/compatlog.cpp | 13 +- components/compat/compatlog.h | 2 +- lib/base/Makefile.am | 2 + lib/base/base.vcxproj | 2 + lib/base/scriptfunction.h | 5 +- lib/base/scriptfunctionwrapper.cpp | 39 ++++++ lib/base/scriptfunctionwrapper.h | 192 ++++++++++++++++++++++++++ lib/icinga/api.cpp | 7 +- lib/icinga/api.h | 2 +- lib/icinga/host.cpp | 10 +- lib/icinga/host.h | 2 +- lib/icinga/nullchecktask.cpp | 6 +- lib/icinga/nullchecktask.h | 5 +- lib/icinga/pluginchecktask.cpp | 8 +- lib/icinga/pluginchecktask.h | 3 +- lib/icinga/pluginnotificationtask.cpp | 24 +--- lib/icinga/pluginnotificationtask.h | 5 +- lib/icinga/timeperiod.cpp | 26 +--- lib/icinga/timeperiod.h | 4 +- 19 files changed, 266 insertions(+), 91 deletions(-) create mode 100644 lib/base/scriptfunctionwrapper.cpp create mode 100644 lib/base/scriptfunctionwrapper.h diff --git a/components/compat/compatlog.cpp b/components/compat/compatlog.cpp index 348775f0b..20df8965a 100644 --- a/components/compat/compatlog.cpp +++ b/components/compat/compatlog.cpp @@ -335,17 +335,8 @@ void CompatLog::RotationTimerHandler(void) ScheduleNextRotation(); } -Value CompatLog::ValidateRotationMethod(const std::vector& 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& arguments) ConfigCompilerContext::GetContext()->AddError(false, "Validation failed for " + location + ": Rotation method '" + rotation_method + "' is invalid."); } - - return Empty; } diff --git a/components/compat/compatlog.h b/components/compat/compatlog.h index 31a1a667c..d07a17850 100644 --- a/components/compat/compatlog.h +++ b/components/compat/compatlog.h @@ -46,7 +46,7 @@ public: String GetLogDir(void) const; String GetRotationMethod(void) const; - static Value ValidateRotationMethod(const std::vector& arguments); + static void ValidateRotationMethod(const String& location, const Dictionary::Ptr& attrs); protected: virtual void OnAttributeChanged(const String& name); diff --git a/lib/base/Makefile.am b/lib/base/Makefile.am index f48abbee1..991b177b8 100644 --- a/lib/base/Makefile.am +++ b/lib/base/Makefile.am @@ -51,6 +51,8 @@ libbase_la_SOURCES = \ script.h \ scriptfunction.cpp \ scriptfunction.h \ + scriptfunctionwrapper.cpp \ + scriptfunctionwrapper.h \ scriptinterpreter.cpp \ scriptinterpreter.h \ scriptlanguage.cpp \ diff --git a/lib/base/base.vcxproj b/lib/base/base.vcxproj index 7d5882544..121e3987d 100644 --- a/lib/base/base.vcxproj +++ b/lib/base/base.vcxproj @@ -40,6 +40,7 @@ + @@ -75,6 +76,7 @@ + diff --git a/lib/base/scriptfunction.h b/lib/base/scriptfunction.h index 669fbeee0..3ad5184b6 100644 --- a/lib/base/scriptfunction.h +++ b/lib/base/scriptfunction.h @@ -23,14 +23,13 @@ #include "base/i2-base.h" #include "base/registry.h" #include "base/value.h" +#include "base/scriptfunctionwrapper.h" #include #include 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)) } diff --git a/lib/base/scriptfunctionwrapper.cpp b/lib/base/scriptfunctionwrapper.cpp new file mode 100644 index 000000000..5a81bfa6b --- /dev/null +++ b/lib/base/scriptfunctionwrapper.cpp @@ -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& arguments) +{ + function(); + + return Empty; +} + +boost::function& arguments)> icinga::WrapScriptFunction(void (*function)(void)) +{ + return boost::bind(&ScriptFunctionWrapperVV, function, _1); +} + +boost::function& arguments)> icinga::WrapScriptFunction(Value (*function)(const std::vector&)) +{ + return boost::bind(function, _1); +} diff --git a/lib/base/scriptfunctionwrapper.h b/lib/base/scriptfunctionwrapper.h new file mode 100644 index 000000000..48ff2858a --- /dev/null +++ b/lib/base/scriptfunctionwrapper.h @@ -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 +#include +#include + +namespace icinga +{ + +Value ScriptFunctionWrapperVV(void (*function)(void), const std::vector& arguments); + +boost::function& arguments)> I2_BASE_API WrapScriptFunction(void (*function)(void)); + +template +Value ScriptFunctionWrapperR(TR (*function)(void), const std::vector& arguments) +{ + return function(); +} + +template +boost::function& arguments)> WrapScriptFunction(TR (*function)(void)) +{ + return boost::bind(&ScriptFunctionWrapperR, function, _1); +} + +template +Value ScriptFunctionWrapperV(void (*function)(T0), const std::vector& arguments) +{ + if (arguments.size() < 1) + BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function.")); + + function(static_cast(arguments[0])); + + return Empty; +} + +template +boost::function& arguments)> WrapScriptFunction(void (*function)(T0)) +{ + return boost::bind(&ScriptFunctionWrapperV, function, _1); +} + +template +Value ScriptFunctionWrapperR(TR (*function)(T0), const std::vector& arguments) +{ + if (arguments.size() < 1) + BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function.")); + + return function(static_cast(arguments[0])); +} + +template +boost::function& arguments)> WrapScriptFunction(TR (*function)(T0)) +{ + return boost::bind(&ScriptFunctionWrapperR, function, _1); +} + +template +Value ScriptFunctionWrapperV(void (*function)(T0, T1), const std::vector& arguments) +{ + if (arguments.size() < 2) + BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function.")); + + function(static_cast(arguments[0]), + static_cast(arguments[1])); + + return Empty; +} + +template +boost::function& arguments)> WrapScriptFunction(void (*function)(T0, T1)) +{ + return boost::bind(&ScriptFunctionWrapperV, function, _1); +} + +template +Value ScriptFunctionWrapperR(TR (*function)(T0, T1), const std::vector& arguments) +{ + if (arguments.size() < 2) + BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function.")); + + return function(static_cast(arguments[0]), + static_cast(arguments[1])); +} + +template +boost::function& arguments)> WrapScriptFunction(TR (*function)(T0, T1)) +{ + return boost::bind(&ScriptFunctionWrapperR, function, _1); +} + +template +Value ScriptFunctionWrapperV(void (*function)(T0, T1, T2), const std::vector& arguments) +{ + if (arguments.size() < 3) + BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function.")); + + function(static_cast(arguments[0]), + static_cast(arguments[1]), + static_cast(arguments[2])); + + return Empty; +} + +template +boost::function& arguments)> WrapScriptFunction(void (*function)(T0, T1, T2)) +{ + return boost::bind(&ScriptFunctionWrapperV, function, _1); +} + +template +Value ScriptFunctionWrapperR(TR (*function)(T0, T1, T2), const std::vector& arguments) +{ + if (arguments.size() < 3) + BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function.")); + + return function(static_cast(arguments[0]), + static_cast(arguments[1]), + static_cast(arguments[2])); +} + +template +boost::function& arguments)> WrapScriptFunction(TR (*function)(T0, T1, T2)) +{ + return boost::bind(&ScriptFunctionWrapperR, function, _1); +} + +template +Value ScriptFunctionWrapperV(void (*function)(T0, T1, T2, T3), const std::vector& arguments) +{ + if (arguments.size() < 4) + BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function.")); + + function(static_cast(arguments[0]), + static_cast(arguments[1]), + static_cast(arguments[2]), + static_cast(arguments[3])); + + return Empty; +} + +template +boost::function& arguments)> WrapScriptFunction(void (*function)(T0, T1, T2, T3)) +{ + return boost::bind(&ScriptFunctionWrapperV, function, _1); +} + +template +Value ScriptFunctionWrapperR(TR (*function)(T0, T1, T2, T3), const std::vector& arguments) +{ + if (arguments.size() < 4) + BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function.")); + + return function(static_cast(arguments[0]), + static_cast(arguments[1]), + static_cast(arguments[2]), + static_cast(arguments[3])); +} + +template +boost::function& arguments)> WrapScriptFunction(TR (*function)(T0, T1, T2, T3)) +{ + return boost::bind(&ScriptFunctionWrapperR, function, _1); +} + +boost::function& arguments)> I2_BASE_API WrapScriptFunction(Value (*function)(const std::vector&)); + +} + +#endif /* SCRIPTFUNCTION_H */ diff --git a/lib/icinga/api.cpp b/lib/icinga/api.cpp index 63a3886d5..62dcd1834 100644 --- a/lib/icinga/api.cpp +++ b/lib/icinga/api.cpp @@ -25,13 +25,8 @@ using namespace icinga; REGISTER_SCRIPTFUNCTION(GetAnswerToEverything, &API::GetAnswerToEverything); -Value API::GetAnswerToEverything(const std::vector& 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; diff --git a/lib/icinga/api.h b/lib/icinga/api.h index b91c38c40..777da2240 100644 --- a/lib/icinga/api.h +++ b/lib/icinga/api.h @@ -35,7 +35,7 @@ namespace icinga class I2_ICINGA_API API { public: - static Value GetAnswerToEverything(const std::vector& arguments); + static int GetAnswerToEverything(const String& text); private: API(void); diff --git a/lib/icinga/host.cpp b/lib/icinga/host.cpp index 6f14e3aa0..e694146c7 100644 --- a/lib/icinga/host.cpp +++ b/lib/icinga/host.cpp @@ -352,16 +352,8 @@ void Host::RefreshServicesCache(void) l_ServicesCache.swap(newServicesCache); } -Value Host::ValidateServiceDictionary(const std::vector& 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; diff --git a/lib/icinga/host.h b/lib/icinga/host.h index 4dd8f4075..5ca9931bc 100644 --- a/lib/icinga/host.h +++ b/lib/icinga/host.h @@ -103,7 +103,7 @@ public: std::set > GetServices(void) const; static void InvalidateServicesCache(void); - static Value ValidateServiceDictionary(const std::vector& arguments); + static Value ValidateServiceDictionary(const String& location, const Dictionary::Ptr& attrs); static HostState CalculateState(ServiceState state, bool reachable); diff --git a/lib/icinga/nullchecktask.cpp b/lib/icinga/nullchecktask.cpp index c79c7bedb..e8849194a 100644 --- a/lib/icinga/nullchecktask.cpp +++ b/lib/icinga/nullchecktask.cpp @@ -19,7 +19,6 @@ #include "icinga/nullchecktask.h" #include "icinga/service.h" -#include "base/dictionary.h" #include "base/scriptfunction.h" #include @@ -27,11 +26,8 @@ using namespace icinga; REGISTER_SCRIPTFUNCTION(NullCheck, &NullCheckTask::ScriptFunc); -Value NullCheckTask::ScriptFunc(const std::vector& 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(); cr->Set("state", StateUnknown); diff --git a/lib/icinga/nullchecktask.h b/lib/icinga/nullchecktask.h index 4a8eeb33d..56bb6104b 100644 --- a/lib/icinga/nullchecktask.h +++ b/lib/icinga/nullchecktask.h @@ -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& arguments); + static Dictionary::Ptr ScriptFunc(const Service::Ptr& service); private: NullCheckTask(void); diff --git a/lib/icinga/pluginchecktask.cpp b/lib/icinga/pluginchecktask.cpp index 52e00ef8e..39b71922e 100644 --- a/lib/icinga/pluginchecktask.cpp +++ b/lib/icinga/pluginchecktask.cpp @@ -24,6 +24,7 @@ #include "base/logger_fwd.h" #include "base/scriptfunction.h" #include "base/utility.h" +#include "base/process.h" #include #include #include @@ -33,13 +34,8 @@ using namespace icinga; REGISTER_SCRIPTFUNCTION(PluginCheck, &PluginCheckTask::ScriptFunc); -Value PluginCheckTask::ScriptFunc(const std::vector& 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 resolvers; diff --git a/lib/icinga/pluginchecktask.h b/lib/icinga/pluginchecktask.h index acf1bdd00..8b312a099 100644 --- a/lib/icinga/pluginchecktask.h +++ b/lib/icinga/pluginchecktask.h @@ -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& arguments); + static Value ScriptFunc(const Service::Ptr& service); static ServiceState ExitStatusToState(int exitStatus); static Dictionary::Ptr ParseCheckOutput(const String& output); diff --git a/lib/icinga/pluginnotificationtask.cpp b/lib/icinga/pluginnotificationtask.cpp index 0ea2ec9d1..fedddabd4 100644 --- a/lib/icinga/pluginnotificationtask.cpp +++ b/lib/icinga/pluginnotificationtask.cpp @@ -26,31 +26,17 @@ #include "base/logger_fwd.h" #include "base/utility.h" #include "base/convert.h" +#include "base/process.h" #include #include using namespace icinga; -REGISTER_SCRIPTFUNCTION(PluginNotification, &PluginNotificationTask::ScriptFunc); +REGISTER_SCRIPTFUNCTION(PluginNotification, &PluginNotificationTask::ScriptFunc); -Value PluginNotificationTask::ScriptFunc(const std::vector& 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(static_cast(arguments[3])); + NotificationType type = static_cast(itype); Service::Ptr service = notification->GetService(); @@ -97,6 +83,4 @@ Value PluginNotificationTask::ScriptFunc(const std::vector& arguments) << pr.ExitStatus << ", output: " << pr.Output; Log(LogWarning, "icinga", msgbuf.str()); } - - return Empty; } diff --git a/lib/icinga/pluginnotificationtask.h b/lib/icinga/pluginnotificationtask.h index f7cef49d5..5dcf61c76 100644 --- a/lib/icinga/pluginnotificationtask.h +++ b/lib/icinga/pluginnotificationtask.h @@ -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& arguments); + static void ScriptFunc(const Notification::Ptr& notification, + const User::Ptr& user, const Dictionary::Ptr& cr, int itype); private: PluginNotificationTask(void); diff --git a/lib/icinga/timeperiod.cpp b/lib/icinga/timeperiod.cpp index 28308d40d..5a67322a4 100644 --- a/lib/icinga/timeperiod.cpp +++ b/lib/icinga/timeperiod.cpp @@ -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& 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(); return segments; } -Value TimePeriod::EvenMinutesTimePeriodUpdate(const std::vector& 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(); for (long t = begin / 60 - 1; t * 60 < end; t++) { diff --git a/lib/icinga/timeperiod.h b/lib/icinga/timeperiod.h index 693042047..c9c29094e 100644 --- a/lib/icinga/timeperiod.h +++ b/lib/icinga/timeperiod.h @@ -49,8 +49,8 @@ public: bool IsInside(double ts) const; double FindNextTransition(double begin); - static Value EmptyTimePeriodUpdate(const std::vector& arguments); - static Value EvenMinutesTimePeriodUpdate(const std::vector& 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 m_ValidBegin; -- 2.40.0