You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Zero/ZeroLevel/Services/Logging/LogRouterr.cs

150 lines
4.3 KiB

using System;
using System.Collections.Generic;
using System.Threading;
namespace ZeroLevel.Services.Logging
{
internal sealed class LogRouter :
ILogger,
ILogComposer
{
#region Fields
private long _backlog = -1;
private volatile bool _stopped;
private readonly object LogsCacheeLocker = new object();
private readonly Dictionary<int, List<ILogger>> LogWriters = new Dictionary<int, List<ILogger>>();
private volatile ILogMessageBuffer _messageQueue;
#endregion Fields
#region Ctor
public LogRouter()
{
_messageQueue = new NoLimitedLogMessageBuffer();
AppDomain.CurrentDomain.ProcessExit += (sender, e) => { Dispose(); };
_stopped = false;
var thread = new Thread(ProcessMessageQueueMethod) { IsBackground = true };
thread.Start();
}
#endregion Ctor
#region Routing
public void SetupBacklog(long backlog)
{
if (backlog != _backlog)
{
var currentQueue = _messageQueue;
if (backlog > 0) // Fix
{
_messageQueue = new FixSizeLogMessageBuffer(backlog);
}
else // Unlimited
{
_messageQueue = new NoLimitedLogMessageBuffer();
}
while (currentQueue.Count > 0)
{
var t = currentQueue.Take();
_messageQueue.Push(t.Item1, t.Item2);
}
currentQueue.Dispose();
currentQueue = null;
GC.Collect();
GC.WaitForFullGCComplete();
}
}
private void ProcessMessageQueueMethod(object state)
{
while (false == _stopped || _messageQueue.Count > 0)
{
var message = _messageQueue.Take();
if (message != null)
{
lock (LogsCacheeLocker)
{
foreach (var lv in LogWriters.Keys)
{
if ((lv & ((int)message.Item1)) != 0)
{
foreach (var logger in LogWriters[lv])
{
logger.Write(message.Item1, message.Item2);
}
}
}
}
message = null;
}
}
}
public void AddLogger(ILogger logger, LogLevel level = LogLevel.All)
{
if (false == _stopped)
{
lock (LogsCacheeLocker)
{
var lv = (int)level;
if (false == LogWriters.ContainsKey(lv))
{
LogWriters.Add(lv, new List<ILogger>());
}
LogWriters[lv].Add(logger);
}
}
}
#endregion Routing
#region ILogger
public void Write(LogLevel level, string message)
{
if (false == _stopped)
{
_messageQueue.Push(level, message);
}
}
#endregion ILogger
#region IDisposable
public void Dispose()
{
if (false == _stopped)
{
_stopped = true;
while (_messageQueue.Count > 0)
{
Thread.Sleep(100);
}
_messageQueue.Dispose();
lock (LogsCacheeLocker)
{
foreach (var logCollection in LogWriters.Values)
{
foreach (var logger in logCollection)
{
try
{
logger.Dispose();
}
catch { }
}
}
LogWriters.Clear();
}
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
#endregion IDisposable
}
}

Powered by TurnKey Linux.