Mercurial > servermonitor
comparison ServerMonitor/Objects/Schedule.cs @ 17:68d7834dc28e
More comments.
author | Brad Greco <brad@bgreco.net> |
---|---|
date | Sat, 25 May 2019 15:14:26 -0400 |
parents | d92176c5398a |
children | 2342e9459444 |
comparison
equal
deleted
inserted
replaced
16:7626b099aefd | 17:68d7834dc28e |
---|---|
1 using System; | 1 using System; |
2 | 2 |
3 namespace ServerMonitorApp | 3 namespace ServerMonitorApp |
4 { | 4 { |
5 /// <summary>Schedule to control when a check is automatically executed.<summary> | |
5 public class Schedule | 6 public class Schedule |
6 { | 7 { |
8 // Required empty constructor for XML serialization. | |
7 public Schedule() { } | 9 public Schedule() { } |
8 | 10 |
11 /// <summary>Schedule constructor</summary> | |
12 /// <param name="units">The time units to use.</param> | |
13 /// <param name="frequency">How frequently to run the check.</param> | |
14 /// <param name="startTime">Time of day the check should begin running.</param> | |
15 /// <param name="endTime">Time of day the check should stop running.</param> | |
16 /// <remarks> | |
17 /// If endTime is before startTime, then the endTime is interpreted as being on the next day. | |
18 /// For example, if startTime = 17:00 and endTime is 8:00, then the check will start running | |
19 /// at 17:00 and stop running at 8:00 the next day. | |
20 /// </remarks> | |
9 public Schedule(FrequencyUnits units, int frequency, TimeSpan startTime, TimeSpan endTime) | 21 public Schedule(FrequencyUnits units, int frequency, TimeSpan startTime, TimeSpan endTime) |
10 { | 22 { |
11 Units = units; | 23 Units = units; |
12 Frequency = frequency; | 24 Frequency = frequency; |
13 StartTime = startTime; | 25 StartTime = startTime; |
14 EndTime = endTime; | 26 EndTime = endTime; |
15 } | 27 } |
16 | 28 |
29 /// <summary>How often the check should be executed.</summary> | |
17 public int Frequency { get; set; } | 30 public int Frequency { get; set; } |
18 | 31 |
32 /// <summary>The time units used to interpret the frequency.</summary> | |
19 public FrequencyUnits Units { get; set; } | 33 public FrequencyUnits Units { get; set; } |
20 | 34 |
35 /// <summary>Time of day the check should begin running.</summary> | |
21 public TimeSpan StartTime { get; set; } | 36 public TimeSpan StartTime { get; set; } |
22 | 37 |
38 /// <summary>Time of day the check should stop running.</summary> | |
23 public TimeSpan EndTime { get; set; } | 39 public TimeSpan EndTime { get; set; } |
24 | 40 |
41 /// <summary>Given the last time a check was scheduled to run, calculates the next time in the future it should run.</summary> | |
42 /// <param name="lastScheduledTime">The last time a check was scheduled to run.</param> | |
25 public DateTime GetNextTime(DateTime lastScheduledTime) | 43 public DateTime GetNextTime(DateTime lastScheduledTime) |
26 { | 44 { |
27 return GetNextTime(lastScheduledTime, DateTime.Now); | 45 return GetNextTime(lastScheduledTime, DateTime.Now); |
28 } | 46 } |
29 | 47 |
48 /// <summary>Given the last time a check was scheduled to run, calculates the next time after the given date it should run.</summary> | |
49 /// <param name="lastScheduledTime">The last time a check was scheduled to run.</param> | |
50 /// <param name="minStartTime">The earliest allowed time to return.</param> | |
51 /// <remarks> | |
52 /// The next execution time of a check cannot necessarily be determined by taking the | |
53 /// last execution time and adding the configured number of time units. The computer might | |
54 /// have been asleep or the program might have not been running, so the next date might | |
55 /// be in the past. | |
56 /// | |
57 /// To best follow the schedule, we take the last execution time and fast-forward time | |
58 /// by adding the configured time interval until we get a resulting time that is in the future. | |
59 /// For example, suppose a check is scheduled to run every 5 minutes starting at 7:00. | |
60 /// The check last ran at 7:40, and the computer was suspended shortly thereafter and resumed | |
61 /// at 8:28. The next execution time is determined by adding 5 minutes to 7:40 until we obtain | |
62 /// a time after 8:28, in this case, 8:30. | |
63 /// </remarks> | |
30 public DateTime GetNextTime(DateTime lastScheduledTime, DateTime minStartTime) | 64 public DateTime GetNextTime(DateTime lastScheduledTime, DateTime minStartTime) |
31 { | 65 { |
66 // Start by setting the next time to the last time the check was run. | |
32 DateTime nextTime = lastScheduledTime; | 67 DateTime nextTime = lastScheduledTime; |
33 if (Units == FrequencyUnits.Day) | 68 if (Units == FrequencyUnits.Day) |
34 { | 69 { |
70 // If the check is scheduled only once a day, simply add days until we find a time in the future. | |
35 while (nextTime < minStartTime) | 71 while (nextTime < minStartTime) |
36 nextTime = nextTime.AddDays(Frequency).Date.Add(StartTime); | 72 nextTime = nextTime.AddDays(Frequency).Date.Add(StartTime); |
37 } | 73 } |
38 else | 74 else |
39 { | 75 { |
40 // If the last run time was more than a day ago, fast-forward to reduce the number of loops | 76 // If the last run time was more than a day ago, fast-forward a day at a time to reduce the number of loops. |
41 if (nextTime < minStartTime.AddHours(-24)) | 77 if (nextTime < minStartTime.AddHours(-24)) |
42 nextTime = minStartTime.Date.Add(StartTime).AddHours(-24); | 78 nextTime = minStartTime.Date.Add(StartTime).AddHours(-24); |
79 // Add the configured time interval to the last run time until we obtain a time in the future. | |
43 while (nextTime < minStartTime) | 80 while (nextTime < minStartTime) |
44 { | 81 { |
45 switch (Units) | 82 switch (Units) |
46 { | 83 { |
47 case FrequencyUnits.Second: nextTime = nextTime.AddSeconds(Frequency); break; | 84 case FrequencyUnits.Second: nextTime = nextTime.AddSeconds(Frequency); break; |
48 case FrequencyUnits.Minute: nextTime = nextTime.AddMinutes(Frequency); break; | 85 case FrequencyUnits.Minute: nextTime = nextTime.AddMinutes(Frequency); break; |
49 case FrequencyUnits.Hour: nextTime = nextTime.AddHours(Frequency); break; | 86 case FrequencyUnits.Hour: nextTime = nextTime.AddHours(Frequency); break; |
50 default: throw new InvalidOperationException("Unexpected frequency units: " + Units); | 87 default: throw new InvalidOperationException("Unexpected frequency units: " + Units); |
51 } | 88 } |
52 } | 89 } |
90 // Now we have the next date and time, but we don't know yet if it is within | |
91 // the active times of day the check is allowed to run between. | |
53 if (StartTime < EndTime) | 92 if (StartTime < EndTime) |
54 { | 93 { |
94 // The allowed start and end times are on the same day. | |
95 // If the next scheduled time is too early (before the allowed start time), | |
96 // wait to run it until the start time happens. | |
55 if (nextTime.TimeOfDay < StartTime) | 97 if (nextTime.TimeOfDay < StartTime) |
56 nextTime = nextTime.Date + StartTime; | 98 nextTime = nextTime.Date + StartTime; |
99 // If the next scheduled time is too late (after the allowed end time), | |
100 // wait to run it until the start time happens on the following day. | |
57 else if (nextTime.TimeOfDay > EndTime) | 101 else if (nextTime.TimeOfDay > EndTime) |
58 nextTime = nextTime.Date.AddDays(1) + StartTime; | 102 nextTime = nextTime.Date.AddDays(1) + StartTime; |
59 } | 103 } |
60 else if (nextTime.TimeOfDay > EndTime && nextTime.TimeOfDay < StartTime) | 104 else if (nextTime.TimeOfDay > EndTime && nextTime.TimeOfDay < StartTime) |
61 { | 105 { |
106 // The allowed start time is on the day after the allowed end time, | |
107 // and the next scheduled time is too early (before the allowed start time). | |
108 // Wait to run the check until the allowed start time happens. | |
62 nextTime = nextTime.Date + StartTime; | 109 nextTime = nextTime.Date + StartTime; |
63 } | 110 } |
64 } | 111 } |
65 return nextTime; | 112 return nextTime; |
66 } | 113 } |
69 { | 116 { |
70 return string.Format("Every {0} {1}", Frequency, Units.ToString().ToLower() + (Frequency == 1 ? "" : "s")); | 117 return string.Format("Every {0} {1}", Frequency, Units.ToString().ToLower() + (Frequency == 1 ? "" : "s")); |
71 } | 118 } |
72 } | 119 } |
73 | 120 |
121 /// <summary>Units of time that a check can be scheduled to run in intervals of.</summary> | |
74 public enum FrequencyUnits { Second, Minute, Hour, Day } | 122 public enum FrequencyUnits { Second, Minute, Hour, Day } |
75 } | 123 } |