using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; namespace Wayne.Lib.Log { /// /// The abstract base class for a LogWriter. /// internal abstract class LogWriter : IDisposable { #region Fields private string logName; private object dataLock = new object(); private Dictionary debugLogLevelDict = new Dictionary(); private bool disposed; #endregion #region Construction /// /// Protected constructor. /// /// protected LogWriter(string logName) { this.logName = logName; } /// /// Finalizer. /// ~LogWriter() { Dispose(false, "Shutting down."); } #endregion #region IDisposable Members /// /// Disposes the instance of LogWriter. /// [SuppressMessage("Microsoft.Usage", "CA1816:CallGCSuppressFinalizeCorrectly")] public void Dispose() { Dispose("Shutting down."); } /// /// Disposes the instance of LogWriter. /// [SuppressMessage("Microsoft.Usage", "CA1816:CallGCSuppressFinalizeCorrectly")] public void Dispose(string reason) { Dispose(true, reason); GC.SuppressFinalize(this); disposed = true; } /// /// Internal dispose method that is called either by the public Dispose method or the finalizer. /// /// /// protected abstract void Dispose(bool disposing, string reason); #endregion #region Properties /// /// Log name that identifies this log writer. /// [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] public string LogName { get { return logName; } } ///// ///// The number of character each lines is indented with as default. ///// //public abstract int IndentLength { get;} #endregion #region Virtual Methods public abstract void PerformWrite(LogEntry logEntry); #endregion #region Internal Methods /// /// Writes the LogEntry to the log. /// /// internal void Write(LogEntry logEntry) { if (disposed) return; bool doPerformWrite; DebugLogEntry debugLogEntry = logEntry as DebugLogEntry; EventLogEntry eventLogEntry = logEntry as EventLogEntry; if (debugLogEntry != null) { if (debugLogEntry.LogLevel == DebugLogLevel.Excluded) return; DebugLogLevel level = GetDebugLogLevel(debugLogEntry.EntityCategory); doPerformWrite = (level >= debugLogEntry.LogLevel); } else if (eventLogEntry != null) { if (eventLogEntry.LogLevel == DebugLogLevel.Excluded) return; DebugLogLevel level = GetDebugLogLevel(eventLogEntry.EntityCategory); doPerformWrite = (level >= eventLogEntry.LogLevel); } else doPerformWrite = true; if (doPerformWrite) { // Call the abstract method that is overriden by the descendant classes. PerformWrite(logEntry); } } /// /// Cache the filter data for the given EntityCategory. /// /// /// internal void CacheFilterData(EntityCategory entityCategory, DebugLogLevel logLevel) { // Cache the log level. lock (dataLock) { DebugLogLevel currentDebugLogLevel; if (debugLogLevelDict.TryGetValue(entityCategory, out currentDebugLogLevel)) debugLogLevelDict[entityCategory] = DebugLogger.MaxDebugLogLevel(currentDebugLogLevel, logLevel); else debugLogLevelDict.Add(entityCategory, logLevel); } } internal virtual void PerformListCleaning(DateTime oldestAllowedTouch) { #region Clean the logwriterPreparedDict. lock (dataLock) { List entityCategoriesToRemove = new List(); foreach (EntityCategory entityCategory in debugLogLevelDict.Keys) { if (entityCategory.LastTouched < oldestAllowedTouch) entityCategoriesToRemove.Add(entityCategory); } //Remove from the list. foreach (EntityCategory entityCategoryToRemove in entityCategoriesToRemove) { debugLogLevelDict.Remove(entityCategoryToRemove); } } #endregion } internal void RemoveEntity(IIdentifiableEntity entity) { lock (dataLock) { List entityCategoriesToRemove = new List(); foreach (EntityCategory entityCategory in debugLogLevelDict.Keys) { if (IdentifiableEntity.Equals(entityCategory.Entity, entity)) entityCategoriesToRemove.Add(entityCategory); } //Remove from the list. foreach (EntityCategory entityCategoryToRemove in entityCategoriesToRemove) { debugLogLevelDict.Remove(entityCategoryToRemove); } } } #endregion #region Protected Methods /// /// Get the debug level for the given EntityCategory. /// /// /// public DebugLogLevel GetDebugLogLevel(EntityCategory entityCategory) { if (disposed) return DebugLogLevel.Excluded; else if (entityCategory != null) { lock (dataLock) { DebugLogLevel debugLevel; if (debugLogLevelDict.TryGetValue(entityCategory, out debugLevel)) return debugLevel; } } return DebugLogLevel.Normal; } #endregion } }