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();
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
return m_Data.find_first_of(s, pos);
|
||||
|
|
|
@ -75,6 +75,7 @@ public:
|
|||
void Clear(void);
|
||||
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(char ch, size_t pos = 0) const;
|
||||
String SubStr(size_t first, size_t len = NPos) const;
|
||||
|
|
|
@ -33,32 +33,272 @@ using namespace icinga;
|
|||
|
||||
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" ||
|
||||
daydef == "wednesday" || daydef == "thursday" || daydef == "friday" ||
|
||||
daydef == "saturday") {
|
||||
int wday;
|
||||
time_t tsbegin, tsend, tsref;
|
||||
tsbegin = mktime(begin);
|
||||
tsend = mktime(end);
|
||||
tsref = mktime(reference);
|
||||
|
||||
if (daydef == "sunday")
|
||||
wday = 0;
|
||||
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;
|
||||
if (tsref < tsbegin || tsref > tsend)
|
||||
return false;
|
||||
|
||||
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)
|
||||
|
|
|
@ -37,6 +37,12 @@ class I2_ICINGA_API LegacyTimePeriod
|
|||
public:
|
||||
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 Dictionary::Ptr ProcessTimeRange(const String& timerange, tm *reference);
|
||||
static void ProcessTimeRanges(const String& timeranges, tm *reference, const Array::Ptr& result);
|
||||
|
|
Loading…
Reference in New Issue