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
}
}