using Server.Mobiles; using System; using System.IO; using System.Text; using System.Threading; using System.Collections.Generic; namespace Server.Engines.Logging { // A logger class derived from the producder/consumer model. public class LogPCQueue { // Static main logger for general debugging. public static LogPCQueue Logger = new LogPCQueue( "Logs", "debug.txt" ); // A nested class to wrap data sent to the worker thread. private class LogTask { public bool m_Exit; public string m_Format; public object[] m_Args; public LogTask( bool exit, string taskFormat, params object[] args ) { // If we are telling the thread to exit that is all we care about. if ( exit ) { m_Exit = true; return; } else { // These are only written if we are not exited. m_Exit is explicitly checked by // the worker thread. m_Exit = false; m_Format = taskFormat; m_Args = args; } } } EventWaitHandle m_Wh = new AutoResetEvent( false ); Thread m_Worker; object m_Locker = new object( ); Queue< LogTask > m_Tasks = new Queue< LogTask >( ); private FileStream m_Fs; private StreamWriter m_Sw; public void EnqueueTask( LogLevel reqLevel, LogLevel level, string taskFormat, params object[] args ) { EnqueueTask( false, reqLevel, level, taskFormat, args ); } public void EnqueueTask( bool exit, LogLevel reqLevel, LogLevel level, string taskFormat, params object[] args ) { try { if ( exit || reqLevel <= level ) { LogTask task = new LogTask( exit, taskFormat, args ); lock ( m_Locker ) m_Tasks.Enqueue( task ); m_Wh.Set( ); } } catch ( Exception e ) { Console.WriteLine( "Exception in logger task enqueueing: " + e ); } } public void WaitAndExit( ) { // Queue an exit task then wait for the thread to finish and close any current resources. try { EnqueueTask( false, LogLevel.Unspecified, LogLevel.Unspecified, null ); m_Worker.Join( ); m_Wh.Close( ); m_Fs.Close( ); m_Sw.Close( ); } catch ( Exception e ) { Console.WriteLine( "Exception in logger cleanup: " + e ); } } void Work( ) { try { while ( true ) { LogTask task = null; lock ( m_Locker ) if ( m_Tasks.Count > 0 ) { task = m_Tasks.Dequeue( ); if ( task.m_Exit ) return; } if ( task != null ) { task.m_Format = DateTime.Now + task.m_Format; m_Sw.WriteLine( task.m_Format, task.m_Args ); m_Sw.Flush( ); } else m_Wh.WaitOne( ); } } catch ( Exception e ) { Console.WriteLine( "Exception in logger worker thread: " + e ); } } LogPCQueue( string outDirectory, string outFile ) { try { string dateFormat = DateTime.Now.ToLongDateString( ).Replace( " ", "_" ); dateFormat = dateFormat + " " + DateTime.Now.ToLongTimeString( ).Replace(":","_"); m_Fs = new FileStream( Directory.GetCurrentDirectory( ) + "\\" + outDirectory + "\\" + dateFormat + "_" + outFile, FileMode.OpenOrCreate, FileAccess.Write ); m_Sw = new StreamWriter( m_Fs ); m_Worker = new Thread( Work ); m_Worker.Start( ); } catch ( Exception e ) { Console.WriteLine( "Exception trying to create logger instance: " + e ); } } } }