mirror of https://github.com/Icinga/icinga2.git
Implement complex 1.x timeperiod definitions.
This commit is contained in:
parent
2e600a7810
commit
8a1d24042d
|
@ -122,6 +122,11 @@ size_t String::GetLength(void) const
|
||||||
return m_Data.size();
|
return m_Data.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t String::Find(const String& str, size_t pos) const
|
||||||
|
{
|
||||||
|
return m_Data.find(str, pos);
|
||||||
|
}
|
||||||
|
|
||||||
size_t String::FindFirstOf(const char *s, size_t pos) const
|
size_t String::FindFirstOf(const char *s, size_t pos) const
|
||||||
{
|
{
|
||||||
return m_Data.find_first_of(s, pos);
|
return m_Data.find_first_of(s, pos);
|
||||||
|
|
|
@ -75,6 +75,7 @@ public:
|
||||||
void Clear(void);
|
void Clear(void);
|
||||||
size_t GetLength(void) const;
|
size_t GetLength(void) const;
|
||||||
|
|
||||||
|
size_t Find(const String& str, size_t pos = 0) const;
|
||||||
size_t FindFirstOf(const char *s, size_t pos = 0) const;
|
size_t FindFirstOf(const char *s, size_t pos = 0) const;
|
||||||
size_t FindFirstOf(char ch, size_t pos = 0) const;
|
size_t FindFirstOf(char ch, size_t pos = 0) const;
|
||||||
String SubStr(size_t first, size_t len = NPos) const;
|
String SubStr(size_t first, size_t len = NPos) const;
|
||||||
|
|
|
@ -33,32 +33,272 @@ using namespace icinga;
|
||||||
|
|
||||||
REGISTER_SCRIPTFUNCTION(LegacyTimePeriod, &LegacyTimePeriod::ScriptFunc);
|
REGISTER_SCRIPTFUNCTION(LegacyTimePeriod, &LegacyTimePeriod::ScriptFunc);
|
||||||
|
|
||||||
bool LegacyTimePeriod::IsInDayDefinition(const String& daydef, tm *reference)
|
bool LegacyTimePeriod::IsInTimeRange(tm *begin, tm *end, int stride, tm *reference)
|
||||||
{
|
{
|
||||||
if (daydef == "sunday" || daydef == "monday" || daydef == "tuesday" ||
|
time_t tsbegin, tsend, tsref;
|
||||||
daydef == "wednesday" || daydef == "thursday" || daydef == "friday" ||
|
tsbegin = mktime(begin);
|
||||||
daydef == "saturday") {
|
tsend = mktime(end);
|
||||||
int wday;
|
tsref = mktime(reference);
|
||||||
|
|
||||||
if (daydef == "sunday")
|
if (tsref < tsbegin || tsref > tsend)
|
||||||
wday = 0;
|
return false;
|
||||||
else if (daydef == "monday")
|
|
||||||
wday = 1;
|
|
||||||
else if (daydef == "tuesday")
|
|
||||||
wday = 2;
|
|
||||||
else if (daydef == "wednesday")
|
|
||||||
wday = 3;
|
|
||||||
else if (daydef == "thursday")
|
|
||||||
wday = 4;
|
|
||||||
else if (daydef == "friday")
|
|
||||||
wday = 5;
|
|
||||||
else if (daydef == "saturday")
|
|
||||||
wday = 6;
|
|
||||||
|
|
||||||
return reference->tm_wday == wday;
|
int daynumber = (tsref - tsbegin) / (24 * 60 * 60);
|
||||||
|
|
||||||
|
if (daynumber % stride == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LegacyTimePeriod::FindNthWeekday(int wday, int n, tm *reference)
|
||||||
|
{
|
||||||
|
int seen = 0;
|
||||||
|
|
||||||
|
ASSERT(n > 0);
|
||||||
|
|
||||||
|
reference->tm_mday = 1;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
mktime(reference);
|
||||||
|
|
||||||
|
if (reference->tm_wday == wday) {
|
||||||
|
seen++;
|
||||||
|
|
||||||
|
if (seen == n)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reference->tm_mday++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int LegacyTimePeriod::WeekdayFromString(const String& daydef)
|
||||||
|
{
|
||||||
|
if (daydef == "sunday")
|
||||||
|
return 0;
|
||||||
|
else if (daydef == "monday")
|
||||||
|
return 1;
|
||||||
|
else if (daydef == "tuesday")
|
||||||
|
return 2;
|
||||||
|
else if (daydef == "wednesday")
|
||||||
|
return 3;
|
||||||
|
else if (daydef == "thursday")
|
||||||
|
return 4;
|
||||||
|
else if (daydef == "friday")
|
||||||
|
return 5;
|
||||||
|
else if (daydef == "saturday")
|
||||||
|
return 6;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LegacyTimePeriod::MonthFromString(const String& monthdef)
|
||||||
|
{
|
||||||
|
if (monthdef == "january")
|
||||||
|
return 0;
|
||||||
|
else if (monthdef == "february")
|
||||||
|
return 1;
|
||||||
|
else if (monthdef == "march")
|
||||||
|
return 2;
|
||||||
|
else if (monthdef == "april")
|
||||||
|
return 3;
|
||||||
|
else if (monthdef == "may")
|
||||||
|
return 4;
|
||||||
|
else if (monthdef == "june")
|
||||||
|
return 5;
|
||||||
|
else if (monthdef == "july")
|
||||||
|
return 6;
|
||||||
|
else if (monthdef == "august")
|
||||||
|
return 7;
|
||||||
|
else if (monthdef == "september")
|
||||||
|
return 8;
|
||||||
|
else if (monthdef == "october")
|
||||||
|
return 9;
|
||||||
|
else if (monthdef == "november")
|
||||||
|
return 10;
|
||||||
|
else if (monthdef == "december")
|
||||||
|
return 11;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LegacyTimePeriod::ParseTimeSpec(const String& timespec, tm *begin, tm *end, tm *reference)
|
||||||
|
{
|
||||||
|
/* YYYY-MM-DD */
|
||||||
|
if (timespec.GetLength() == 10 && timespec[4] == '-' && timespec[7] == '-') {
|
||||||
|
int year = Convert::ToLong(timespec.SubStr(0, 4));
|
||||||
|
int month = Convert::ToLong(timespec.SubStr(5, 2));
|
||||||
|
int day = Convert::ToLong(timespec.SubStr(7, 2));
|
||||||
|
|
||||||
|
if (begin) {
|
||||||
|
begin->tm_year = year - 1900;
|
||||||
|
begin->tm_mon = month;
|
||||||
|
begin->tm_mday = day;
|
||||||
|
begin->tm_hour = 0;
|
||||||
|
begin->tm_min = 0;
|
||||||
|
begin->tm_sec = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end) {
|
||||||
|
end->tm_year = year - 1900;
|
||||||
|
end->tm_mon = month;
|
||||||
|
end->tm_mday = day;
|
||||||
|
end->tm_hour = 24;
|
||||||
|
end->tm_min = 0;
|
||||||
|
end->tm_sec = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid day definition: " + daydef));
|
std::vector<String> tokens;
|
||||||
|
boost::algorithm::split(tokens, timespec, boost::is_any_of(" "));
|
||||||
|
|
||||||
|
if (tokens.size() > 1 && tokens[0] == "day") {
|
||||||
|
int mday = Convert::ToLong(tokens[1]);
|
||||||
|
|
||||||
|
if (begin) {
|
||||||
|
*begin = *reference;
|
||||||
|
begin->tm_mday = mday;
|
||||||
|
begin->tm_hour = 0;
|
||||||
|
begin->tm_min = 0;
|
||||||
|
begin->tm_sec = 0;
|
||||||
|
|
||||||
|
/* Negative days are relative to the next month. */
|
||||||
|
if (mday < 0) {
|
||||||
|
end->tm_mday--;
|
||||||
|
begin->tm_mon++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end) {
|
||||||
|
*end = *reference;
|
||||||
|
end->tm_mday = mday;
|
||||||
|
end->tm_hour = 24;
|
||||||
|
end->tm_min = 0;
|
||||||
|
end->tm_sec = 0;
|
||||||
|
|
||||||
|
/* Negative days are relative to the next month. */
|
||||||
|
if (mday < 0) {
|
||||||
|
end->tm_mday--;
|
||||||
|
end->tm_mon++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wday;
|
||||||
|
|
||||||
|
if (tokens.size() > 1 && (wday = WeekdayFromString(tokens[0])) != -1) {
|
||||||
|
tm myref = *reference;
|
||||||
|
|
||||||
|
if (tokens.size() > 2) {
|
||||||
|
int mon = MonthFromString(tokens[2]);
|
||||||
|
|
||||||
|
if (mon == -1)
|
||||||
|
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid month in time specification: " + timespec));
|
||||||
|
|
||||||
|
myref.tm_mon = mon;
|
||||||
|
}
|
||||||
|
|
||||||
|
int n = Convert::ToLong(tokens[1]);
|
||||||
|
|
||||||
|
if (begin) {
|
||||||
|
*begin = myref;
|
||||||
|
FindNthWeekday(wday, n, begin);
|
||||||
|
begin->tm_hour = 0;
|
||||||
|
begin->tm_min = 0;
|
||||||
|
begin->tm_sec = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end) {
|
||||||
|
*end = myref;
|
||||||
|
FindNthWeekday(wday, n, end);
|
||||||
|
end->tm_hour = 0;
|
||||||
|
end->tm_min = 0;
|
||||||
|
end->tm_sec = 0;
|
||||||
|
end->tm_mday++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid time specification: " + timespec));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LegacyTimePeriod::ParseTimeRange(const String& timerange, tm *begin, tm *end, int *stride, tm *reference)
|
||||||
|
{
|
||||||
|
String def = timerange;
|
||||||
|
|
||||||
|
/* Figure out the stride. */
|
||||||
|
size_t pos = def.FindFirstOf('/');
|
||||||
|
|
||||||
|
if (pos != String::NPos) {
|
||||||
|
String strStride = def.SubStr(pos + 1);
|
||||||
|
strStride.Trim();
|
||||||
|
*stride = Convert::ToLong(strStride);
|
||||||
|
|
||||||
|
/* Remove the stride parameter from the definition. */
|
||||||
|
def = def.SubStr(0, pos);
|
||||||
|
} else {
|
||||||
|
*stride = 1; /* User didn't specify anything, assume default. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Figure out whether the user has specified two dates. */
|
||||||
|
pos = def.Find("- ");
|
||||||
|
|
||||||
|
std::cout << "XXX: " << def << std::endl;
|
||||||
|
|
||||||
|
if (pos != String::NPos) {
|
||||||
|
String first = def.SubStr(0, pos);
|
||||||
|
first.Trim();
|
||||||
|
|
||||||
|
String second = def.SubStr(pos + 1);
|
||||||
|
second.Trim();
|
||||||
|
|
||||||
|
ParseTimeSpec(first, begin, NULL, reference);
|
||||||
|
|
||||||
|
/* If the second definition starts with a number we need
|
||||||
|
* to add the first word from the first definition, e.g.:
|
||||||
|
* day 1 - 15 --> "day 15" */
|
||||||
|
bool is_number = true;
|
||||||
|
size_t xpos = second.FindFirstOf(' ');
|
||||||
|
String fword = second.SubStr(0, xpos);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Convert::ToLong(fword);
|
||||||
|
} catch (...) {
|
||||||
|
is_number = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_number) {
|
||||||
|
xpos = first.FindFirstOf(' ');
|
||||||
|
ASSERT(xpos != String::NPos);
|
||||||
|
second = first.SubStr(0, xpos + 1) + second;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParseTimeSpec(second, NULL, end, reference);
|
||||||
|
} else {
|
||||||
|
ParseTimeSpec(def, begin, end, reference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LegacyTimePeriod::IsInDayDefinition(const String& daydef, tm *reference)
|
||||||
|
{
|
||||||
|
/* Week specifications are special in that they don't have a reference frame. */
|
||||||
|
int wday = WeekdayFromString(daydef);
|
||||||
|
|
||||||
|
if (wday != -1)
|
||||||
|
return reference->tm_wday == wday;
|
||||||
|
|
||||||
|
tm begin, end;
|
||||||
|
int stride;
|
||||||
|
|
||||||
|
ParseTimeRange(daydef, &begin, &end, &stride, reference);
|
||||||
|
|
||||||
|
return IsInTimeRange(&begin, &end, stride, reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
Dictionary::Ptr LegacyTimePeriod::ProcessTimeRange(const String& timerange, tm *reference)
|
Dictionary::Ptr LegacyTimePeriod::ProcessTimeRange(const String& timerange, tm *reference)
|
||||||
|
|
|
@ -37,6 +37,12 @@ class I2_ICINGA_API LegacyTimePeriod
|
||||||
public:
|
public:
|
||||||
static Array::Ptr ScriptFunc(const TimePeriod::Ptr& tp, double start, double end);
|
static Array::Ptr ScriptFunc(const TimePeriod::Ptr& tp, double start, double end);
|
||||||
|
|
||||||
|
static bool IsInTimeRange(tm *begin, tm *end, int stride, tm *reference);
|
||||||
|
static void FindNthWeekday(int wday, int n, tm *reference);
|
||||||
|
static int WeekdayFromString(const String& daydef);
|
||||||
|
static int MonthFromString(const String& monthdef);
|
||||||
|
static void ParseTimeSpec(const String& timespec, tm *begin, tm *end, tm *reference);
|
||||||
|
static void ParseTimeRange(const String& timerange, tm *begin, tm *end, int *stride, tm *reference);
|
||||||
static bool IsInDayDefinition(const String& daydef, tm *reference);
|
static bool IsInDayDefinition(const String& daydef, tm *reference);
|
||||||
static Dictionary::Ptr ProcessTimeRange(const String& timerange, tm *reference);
|
static Dictionary::Ptr ProcessTimeRange(const String& timerange, tm *reference);
|
||||||
static void ProcessTimeRanges(const String& timeranges, tm *reference, const Array::Ptr& result);
|
static void ProcessTimeRanges(const String& timeranges, tm *reference, const Array::Ptr& result);
|
||||||
|
|
Loading…
Reference in New Issue