/// <summary> /// Removes the given outage from the outage log. /// </summary> /// <param name="outage">The outage to be removed from the outage log.</param> /// <returns>True if the outage was removed; false otherwise.</returns> public bool Remove(Outage outage) { bool removed; bool modified; using (FileStream stream = GetFileLock(File.OpenWrite)) using (StreamReader reader = new StreamReader(stream)) using (StreamWriter writer = new StreamWriter(stream)) { List <Outage> outages = ReadLog(reader); modified = !m_outages.SequenceEqual(outages); outages.AddRange(m_outages); outages = Outage.MergeOverlapping(outages).ToList(); removed = outages.Remove(outage); modified |= !m_outages.SequenceEqual(outages); if (modified) { m_outages.Clear(); m_outages.AddRange(outages); stream.SetLength(0L); WriteLog(writer); } } if (modified) { LogModified?.Invoke(this, EventArgs.Empty); } return(removed); }
/// <summary> /// Determines if this <see cref="Outage"/> equals another object. /// </summary> /// <param name="obj">The object to be compared.</param> /// <returns>True if the objects are equal; false otherwise.</returns> public override bool Equals(object obj) { Outage other = obj as Outage; return(((object)other != null) ? Equals(other) : false); }
// Because the outage log file stores timestamps down to the millisecond, // we must forcibly align incoming outages to the nearest millisecond. private Outage Align(Outage outage) { DateTimeOffset start = outage.Start.AddTicks(-(outage.Start.Ticks % TimeSpan.TicksPerMillisecond)); DateTimeOffset end = outage.End.AddTicks(-(outage.End.Ticks % TimeSpan.TicksPerMillisecond)); if (start == outage.Start && end == outage.End) { return(outage); } return(new Outage(start, end)); }
private void ProcessNextItem() { if (m_disposed || !m_enabled) { return; } try { Outage nextOutage = null; // Get next outage for processing, if any lock (m_outageLog.ReadWriteLock) { if (m_outageLog.Count > 0) { nextOutage = m_outageLog[0]; } } if ((object)nextOutage != null) { try { // See if we can process the outage at this time if (m_canProcessOutageFunction(nextOutage)) { m_processOutageFunction(nextOutage); // Outage processed successfully, attempt to clear it from the log lock (m_outageLog.ReadWriteLock) { m_outageLog.Remove(nextOutage); } } } finally { // Process next item m_operation.RunOnceAsync(); } } } finally { // Make sure not to process items any faster than the processing interval Thread.Sleep(m_processInterval); } }
// Watches for changes to the log and adds additional outages entered by external processes. private void m_logFileWatcher_Changed(object sender, FileSystemEventArgs e) { long lastWriteTime = File.GetLastWriteTimeUtc(m_fileName).Ticks; if (Interlocked.Exchange(ref m_lastReadTime, lastWriteTime) == lastWriteTime) { return; } if (Interlocked.CompareExchange(ref m_suppressFileWatcher, 0, 1) == 1) { return; } ThreadPool.QueueUserWorkItem(state => { try { bool modified; using (FileStream stream = GetFileLock(File.OpenWrite)) using (StreamReader reader = new StreamReader(stream)) using (StreamWriter writer = new StreamWriter(stream)) { List <Outage> outages = ReadLog(reader); modified = !m_outages.SequenceEqual(outages); if (modified) { outages.AddRange(m_outages); m_outages.Clear(); m_outages.AddRange(Outage.MergeOverlapping(outages)); stream.SetLength(0L); WriteLog(writer); } } if (modified) { LogModified?.Invoke(this, EventArgs.Empty); } } catch (Exception ex) { OnProcessException(ex); } }); }
/// <summary> /// Determines if this <see cref="Outage"/> equals another outage. /// </summary> /// <param name="other">The outage to be compared.</param> /// <returns>True if the outages are equal; false otherwise.</returns> public bool Equals(Outage other) { return(Start == other.Start && End == other.End); }