}
}
+Dictionary::Ptr LegacyTimePeriod::FindRunningSegment(const String& daydef, const String& timeranges, tm *reference)
+{
+ tm begin, end, iter;
+ time_t tsend, tsiter, tsref;
+ int stride;
+
+ tsref = mktime(reference);
+
+ ParseTimeRange(daydef, &begin, &end, &stride, reference);
+
+ iter = begin;
+
+ tsend = mktime(&end);
+
+ do {
+ if (IsInTimeRange(&begin, &end, stride, &iter)) {
+ Array::Ptr segments = new Array();
+ ProcessTimeRanges(timeranges, &iter, segments);
+
+ Dictionary::Ptr bestSegment;
+ double bestEnd;
+
+ ObjectLock olock(segments);
+ for (const Dictionary::Ptr& segment : segments) {
+ double begin = segment->Get("begin");
+ double end = segment->Get("end");
+
+ if (begin >= tsref || end < tsref)
+ continue;
+
+ if (!bestSegment || end > bestEnd) {
+ bestSegment = segment;
+ bestEnd = end;
+ }
+ }
+
+ if (bestSegment)
+ return bestSegment;
+ }
+
+ iter.tm_mday++;
+ iter.tm_hour = 0;
+ iter.tm_min = 0;
+ iter.tm_sec = 0;
+ tsiter = mktime(&iter);
+ } while (tsiter < tsend);
+
+ return nullptr;
+}
+
Dictionary::Ptr LegacyTimePeriod::FindNextSegment(const String& daydef, const String& timeranges, tm *reference)
{
tm begin, end, iter, ref;
return host->GetServiceByShortName(GetServiceName());
}
+std::pair<double, double> ScheduledDowntime::FindRunningSegment(double minEnd)
+{
+ time_t refts = Utility::GetTime();
+ tm reference = Utility::LocalTime(refts);
+
+ Log(LogDebug, "ScheduledDowntime")
+ << "Finding running scheduled downtime segment for time " << refts
+ << " (minEnd " << (minEnd > 0 ? Utility::FormatDateTime("%c", minEnd) : "-") << ")";
+
+ Dictionary::Ptr ranges = GetRanges();
+
+ if (!ranges)
+ return std::make_pair(0, 0);
+
+ Array::Ptr segments = new Array();
+
+ Dictionary::Ptr bestSegment;
+ double bestBegin, bestEnd;
+ double now = Utility::GetTime();
+
+ ObjectLock olock(ranges);
+
+ /* Find the longest lasting (and longer than minEnd, if given) segment that's already running */
+ for (const Dictionary::Pair& kv : ranges) {
+ Log(LogDebug, "ScheduledDowntime")
+ << "Evaluating (running?) segment: " << kv.first << ": " << kv.second;
+
+ Dictionary::Ptr segment = LegacyTimePeriod::FindRunningSegment(kv.first, kv.second, &reference);
+
+ if (!segment)
+ continue;
+
+ double begin = segment->Get("begin");
+ double end = segment->Get("end");
+
+ Log(LogDebug, "ScheduledDowntime")
+ << "Considering (running?) segment: " << Utility::FormatDateTime("%c", begin) << " -> " << Utility::FormatDateTime("%c", end);
+
+ if (begin >= now || end < now) {
+ Log(LogDebug, "ScheduledDowntime") << "not running.";
+ continue;
+ }
+ if (minEnd && end <= minEnd) {
+ Log(LogDebug, "ScheduledDowntime") << "ending too early.";
+ continue;
+ }
+
+ if (!bestSegment || end > bestEnd) {
+ Log(LogDebug, "ScheduledDowntime") << "(best match yet)";
+ bestSegment = segment;
+ bestBegin = begin;
+ bestEnd = end;
+ }
+ }
+
+ if (bestSegment)
+ return std::make_pair(bestBegin, bestEnd);
+
+ return std::make_pair(0, 0);
+}
+
std::pair<double, double> ScheduledDowntime::FindNextSegment()
{
time_t refts = Utility::GetTime();
Array::Ptr segments = new Array();
Dictionary::Ptr bestSegment;
- double bestBegin;
+ double bestBegin, bestEnd;
double now = Utility::GetTime();
ObjectLock olock(ranges);
+
+ /* Find the segment starting earliest */
for (const Dictionary::Pair& kv : ranges) {
Log(LogDebug, "ScheduledDowntime")
<< "Evaluating segment: " << kv.first << ": " << kv.second;
if (!segment)
continue;
- Log(LogDebug, "ScheduledDowntime")
- << "Considering segment: " << Utility::FormatDateTime("%c", segment->Get("begin")) << " -> " << Utility::FormatDateTime("%c", segment->Get("end"));
-
double begin = segment->Get("begin");
+ double end = segment->Get("end");
- if (begin < now)
+ Log(LogDebug, "ScheduledDowntime")
+ << "Considering segment: " << Utility::FormatDateTime("%c", begin) << " -> " << Utility::FormatDateTime("%c", end);
+
+ if (begin < now) {
+ Log(LogDebug, "ScheduledDowntime") << "already running.";
continue;
+ }
if (!bestSegment || begin < bestBegin) {
+ Log(LogDebug, "ScheduledDowntime") << "(best match yet)";
bestSegment = segment;
bestBegin = begin;
+ bestEnd = end;
}
}
if (bestSegment)
- return std::make_pair(bestSegment->Get("begin"), bestSegment->Get("end"));
- else
- return std::make_pair(0, 0);
+ return std::make_pair(bestBegin, bestEnd);
+
+ return std::make_pair(0, 0);
}
void ScheduledDowntime::CreateNextDowntime()
{
+ double minEnd = 0;
+
for (const Downtime::Ptr& downtime : GetCheckable()->GetDowntimes()) {
+ double end = downtime->GetEndTime();
+ if (end > minEnd)
+ minEnd = end;
+
if (downtime->GetScheduledBy() != GetName() ||
downtime->GetStartTime() < Utility::GetTime())
continue;
Log(LogDebug, "ScheduledDowntime")
<< "Creating new Downtime for ScheduledDowntime \"" << GetName() << "\"";
- std::pair<double, double> segment = FindNextSegment();
-
- if (segment.first == 0 && segment.second == 0)
- return;
+ std::pair<double, double> segment = FindRunningSegment(minEnd);
+ if (segment.first == 0 && segment.second == 0) {
+ segment = FindNextSegment();
+ if (segment.first == 0 && segment.second == 0)
+ return;
+ }
String downtimeName = Downtime::AddDowntime(GetCheckable(), GetAuthor(), GetComment(),
segment.first, segment.second,