Mercurial > servermonitor
diff ServerMonitor/Objects/ServerMonitor.cs @ 4:3142e52cbe69
Lots more progress
author | Brad Greco <brad@bgreco.net> |
---|---|
date | Sun, 10 Feb 2019 20:51:26 -0500 |
parents | 3e1a2131f897 |
children | b6fe203af9d5 |
line wrap: on
line diff
--- a/ServerMonitor/Objects/ServerMonitor.cs Fri Jan 11 22:34:18 2019 -0500 +++ b/ServerMonitor/Objects/ServerMonitor.cs Sun Feb 10 20:51:26 2019 -0500 @@ -1,11 +1,14 @@ -using System; +using ServerMonitorApp.Properties; +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; +using System.Net.NetworkInformation; using System.Text; using System.Threading; using System.Threading.Tasks; +using System.Windows.Forms; using System.Xml.Serialization; namespace ServerMonitorApp @@ -15,20 +18,24 @@ private readonly string configFileDir; private readonly Logger logger; private readonly Dictionary<int, CancellationTokenSource> tokens = new Dictionary<int, CancellationTokenSource>(); - private bool running; + private readonly List<int> pausedChecks = new List<int>(); + private bool running, networkAvailable; private Dictionary<Task<CheckResult>, int> tasks; + private ServerSummaryForm mainForm; + //private List<Task<CheckResult>> tasks; public event EventHandler<CheckStatusChangedEventArgs> CheckStatusChanged; public List<Server> Servers { get; private set; } = new List<Server>(); - public IEnumerable<Check> Checks { get { return Servers.SelectMany(s => s.Checks); } } + public IEnumerable<Check> Checks => Servers.SelectMany(s => s.Checks); public string ConfigFile { get; private set; } - public ServerMonitor() + public ServerMonitor(ServerSummaryForm mainForm) { + this.mainForm = mainForm; configFileDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ServerMonitor"); ConfigFile = Path.Combine(configFileDir, "servers.xml"); logger = new Logger(Path.Combine(configFileDir, "monitor.log")); @@ -37,6 +44,13 @@ public void AddServer(Server server) { Servers.Add(server); + SaveServers(); + } + + public void DeleteServer(Server server) + { + Servers.Remove(server); + SaveServers(); } public void LoadServers() @@ -56,8 +70,11 @@ foreach (Check check in server.Checks) { check.Server = server; + if (check.Status == CheckStatus.Running) + check.Status = check.LastRunStatus; } server.CheckModified += Server_CheckModified; + server.EnabledChanged += Server_EnabledChanged; } } // If the file doesn't exist, no special handling is needed. It will be created later. @@ -72,6 +89,7 @@ { reader?.Close(); } + NetworkChange.NetworkAddressChanged += NetworkChange_NetworkAddressChanged; Run(); } @@ -109,6 +127,15 @@ if (running) return; running = true; + networkAvailable = Helpers.IsNetworkAvailable(); + if (networkAvailable) + { + foreach (int id in pausedChecks) + { + await ExecuteCheckAsync(Checks.FirstOrDefault(c => c.Id == id)); + } + pausedChecks.Clear(); + } //TODO subscribe to power events. Find any check's NextExecutionTime is in the past. Cancel waiting task and run immediately (or after short delay). //tasks = Checks.Select(c => ScheduleExecuteCheckAsync(c)).ToList(); tasks = Checks.ToDictionary(c => ScheduleExecuteCheckAsync(c), c => c.Id); @@ -137,8 +164,17 @@ OnCheckStatusChanged(check); CheckResult result = await check.ExecuteAsync(token); OnCheckStatusChanged(check, result); + HandleResultAsync(result); + return result; + } + + private void HandleResultAsync(CheckResult result) + { logger.Log(result); - return result; + if (result.FailAction == FailAction.FlashTaskbar) + mainForm.AlertServerForm(result.Check); + if (result.FailAction.In(FailAction.FlashTaskbar, FailAction.NotificationBalloon)) + mainForm.ShowBalloon(result); } public IList<CheckResult> GetLog(Server server) @@ -166,9 +202,7 @@ else { // Check was modified or deleted, so remove any waiting tasks - tasks.Remove(task); - if (tokens.TryGetValue(check.Id, out CancellationTokenSource cts)) - cts.Cancel(); + CancelCheck(check); if (check.Server != null) { // If the check was not deleted, schedule the new check. @@ -183,9 +217,34 @@ Run(); } + private void Server_EnabledChanged(object sender, EventArgs e) + { + Server server = (Server)sender; + if (server.Enabled) + { + Run(); + } + else + { + foreach (Check check in server.Checks) + { + CancelCheck(check); + } + } + } + + private void CancelCheck(Check check) + { + Task<CheckResult> task = tasks.FirstOrDefault(kvp => kvp.Value == check.Id).Key; + tasks.Remove(task); + pausedChecks.RemoveAll(id => id == check.Id); + if (tokens.TryGetValue(check.Id, out CancellationTokenSource cts)) + cts.Cancel(); + } + private async Task<CheckResult> ScheduleExecuteCheckAsync(Check check) { - if (!check.Enabled) + if (!check.Enabled || !check.Server.Enabled) return await Task.FromResult(new CheckResult(check, CheckStatus.Disabled, null)); CancellationTokenSource cts = new CancellationTokenSource(); @@ -193,7 +252,21 @@ check.NextRunTime = check.Schedule.GetNextTime(check.LastScheduledRunTime); await Task.Delay(check.NextRunTime - DateTime.Now, cts.Token); check.LastScheduledRunTime = check.NextRunTime; - return await ExecuteCheckAsync(check, cts.Token); + if (networkAvailable) + return await ExecuteCheckAsync(check, cts.Token); + else + { + if (!pausedChecks.Contains(check.Id)) + pausedChecks.Add(check.Id); + return await Task.FromResult(new CheckResult(check, CheckStatus.Disabled, null)); + } + } + + private void NetworkChange_NetworkAddressChanged(object sender, EventArgs e) + { + networkAvailable = Helpers.IsNetworkAvailable(); + if (networkAvailable) + mainForm.Invoke((MethodInvoker)(() => Run())); } private void GenerateIds() @@ -208,15 +281,16 @@ } } - //TODO if a check is deleted, there might be old results in the log file that share an ID with a new one if (Checks.Any()) { - int id = Checks.Max(c => c.Id); + int id = Math.Max(Settings.Default.MaxCheckId, Checks.Max(c => c.Id)); foreach (Check check in Checks) { if (check.Id == 0) check.Id = ++id; } + Settings.Default.MaxCheckId = id; + Settings.Default.Save(); } } @@ -237,6 +311,7 @@ Check = check; CheckResult = result; } + } - } + public enum FailAction { FlashTaskbar = 0, NotificationBalloon = 1, None = 10 } }