janwas
c0ed950657
this snowballed into a massive search+destroy of the hodgepodge of mostly equivalent types we had in use (int, uint, unsigned, unsigned int, i32, u32, ulong, uintN). it is more efficient to use 64-bit types in 64-bit mode, so the preferred default is size_t (for anything remotely resembling a size or index). tile coordinates are ssize_t to allow more efficient conversion to/from floating point. flags are int because we almost never need more than 15 distinct bits, bit test/set is not slower and int is fastest to type. finally, some data that is pretty much directly passed to OpenGL is now typed accordingly. after several hours, the code now requires fewer casts and less guesswork. other changes: - unit and player IDs now have an "invalid id" constant in the respective class to avoid casting and -1 - fix some endian/64-bit bugs in the map (un)packing. added a convenience function to write/read a size_t. - ia32: change CPUID interface to allow passing in ecx (required for cache topology detection, which I need at work). remove some unneeded functions from asm, replace with intrinsics where possible. This was SVN commit r5942.
1108 lines
29 KiB
C++
1108 lines
29 KiB
C++
/**
|
|
*-----------------------------------------------------------------------------
|
|
* FILE : NetLog.cpp
|
|
* PROJECT : 0 A.D.
|
|
* DESCRIPTION : Network subsystem logging classes implementation
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
// INCLUDES
|
|
#include "precompiled.h"
|
|
#include "NetLog.h"
|
|
#include "ps/CConsole.h"
|
|
#include "lib/file/path.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <time.h>
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: CNetLogEvent()
|
|
// Desc: Constructor
|
|
//-----------------------------------------------------------------------------
|
|
CNetLogEvent::CNetLogEvent(
|
|
LogLevel level,
|
|
const CStr& message,
|
|
const CStr& loggerName )
|
|
{
|
|
m_Level = level;
|
|
m_Message = message;
|
|
m_LoggerName = loggerName;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: ~CNetLogEvent()
|
|
// Desc: Destructor
|
|
//-----------------------------------------------------------------------------
|
|
CNetLogEvent::~CNetLogEvent( void )
|
|
{
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: CNetLogSink()
|
|
// Desc: Constructor
|
|
//-----------------------------------------------------------------------------
|
|
CNetLogSink::CNetLogSink( void )
|
|
{
|
|
m_Active = false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: ~CNetLogSink()
|
|
// Desc: Destructor
|
|
//-----------------------------------------------------------------------------
|
|
CNetLogSink::~CNetLogSink( void )
|
|
{
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: SetName()
|
|
// Desc: Set the name for the sink
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogSink::SetName( const CStr& name )
|
|
{
|
|
m_Name = name;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: SetLevel()
|
|
// Desc: Set the level for the sink
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogSink::SetLevel( LogLevel level )
|
|
{
|
|
m_Level = level;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: SetHeader()
|
|
// Desc: Set new header text
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogSink::SetHeader( const CStr& header )
|
|
{
|
|
m_Header = header;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: SetFooter()
|
|
// Desc: Set new footer text
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogSink::SetFooter( const CStr& footer )
|
|
{
|
|
m_Footer = footer;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Activate()
|
|
// Desc: Activates the sink
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogSink::Activate( void )
|
|
{
|
|
CScopeLock lock( m_Mutex );
|
|
|
|
if ( !m_Active )
|
|
{
|
|
OnActivate();
|
|
|
|
m_Active = true;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Close()
|
|
// Desc: Closes the sink
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogSink::Close( void )
|
|
{
|
|
CScopeLock lock( m_Mutex );
|
|
|
|
OnClose();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: DoSink()
|
|
// Desc: Perform event logging
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogSink::DoSink( const CNetLogEvent& event )
|
|
{
|
|
CScopeLock lock( m_Mutex );
|
|
|
|
// Not activated? Nothing to log
|
|
if ( !m_Active ) return;
|
|
|
|
if ( TestEvent( event ) )
|
|
{
|
|
Sink( event );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: DoBulkSink()
|
|
// Desc: Perform logging for a list of events
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogSink::DoBulkSink( const CNetLogEvent* pEvents, size_t eventCount )
|
|
{
|
|
unsigned* pIndices = NULL;
|
|
size_t indexCount = 0;
|
|
size_t i;
|
|
|
|
CScopeLock lock( m_Mutex );
|
|
|
|
// Validate parameters
|
|
if ( !pEvents ) return;
|
|
|
|
// Not activated? Nothing to log
|
|
if ( m_Closed ) return;
|
|
|
|
// Allocate new array which will store the events that will be logged
|
|
pIndices = new unsigned[ eventCount ];
|
|
if ( !pIndices )
|
|
{
|
|
throw std::bad_alloc();
|
|
return;
|
|
}
|
|
|
|
// Filter each event and store the index for
|
|
// those passing the filter test
|
|
for ( i = 0; i < eventCount; i++ )
|
|
{
|
|
if ( TestEvent( pEvents[ i ] ) )
|
|
{
|
|
pIndices[ indexCount++ ] = i;
|
|
}
|
|
}
|
|
|
|
// Log each event
|
|
for ( i = 0; i < indexCount; i++ )
|
|
{
|
|
Sink( pEvents[ pIndices[ i ] ] );
|
|
}
|
|
|
|
delete [] pIndices;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: CNetLogSink()
|
|
// Desc: Test if the event can be logged
|
|
//-----------------------------------------------------------------------------
|
|
bool CNetLogSink::TestEvent( const CNetLogEvent& event )
|
|
{
|
|
return ( event.GetLevel() >= m_Level );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: WriteHeader()
|
|
// Desc: Writes a header
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogSink::WriteHeader( void )
|
|
{
|
|
if ( !m_Header.empty() )
|
|
{
|
|
Write( m_Header );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: WriteFooter()
|
|
// Desc: Writes a footer
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogSink::WriteFooter( void )
|
|
{
|
|
if ( !m_Footer.empty() )
|
|
{
|
|
Write( m_Footer );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: OnActivate()
|
|
// Desc: Called on activation
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogSink::OnActivate( void )
|
|
{
|
|
// Does nothing by default
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: OnClose()
|
|
// Desc: Called on sink closure
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogSink::OnClose( void )
|
|
{
|
|
// Does nothing by default
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: CNetLogFileSink()
|
|
// Desc: Constructor
|
|
//-----------------------------------------------------------------------------
|
|
CNetLogFileSink::CNetLogFileSink( void )
|
|
{
|
|
// Get string time
|
|
CStr time;
|
|
CNetLogger::GetStringTime( time );
|
|
|
|
// Make relative path
|
|
Path path("../logs/net_log");
|
|
path /= time+".txt";
|
|
m_FileName = path.external_file_string();
|
|
m_Append = true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: CNetLogFileSink()
|
|
// Desc: Constructor
|
|
//-----------------------------------------------------------------------------
|
|
CNetLogFileSink::CNetLogFileSink( const CStr& filename )
|
|
{
|
|
m_FileName = filename;
|
|
m_Append = true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: CNetLogFileSink()
|
|
// Desc: Constructor
|
|
//-----------------------------------------------------------------------------
|
|
CNetLogFileSink::CNetLogFileSink( const CStr& filename, bool append )
|
|
{
|
|
m_FileName = filename;
|
|
m_Append = append;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: ~CNetLogFileSink()
|
|
// Desc: Destructor
|
|
//-----------------------------------------------------------------------------
|
|
CNetLogFileSink::~CNetLogFileSink( void )
|
|
{
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Activate()
|
|
// Desc: Open the file which will be used for logging
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogFileSink::OnActivate( void )
|
|
{
|
|
OpenFile( m_FileName, m_Append );
|
|
|
|
WriteHeader();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: OnClose()
|
|
// Desc: Closes the file used for logging
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogFileSink::OnClose( void )
|
|
{
|
|
WriteFooter();
|
|
|
|
CloseFile();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Sink()
|
|
// Desc: Log the event to file
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogFileSink::Sink( const CNetLogEvent& event )
|
|
{
|
|
Write( event.GetMessage() );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Write()
|
|
// Desc: Writes a message to log file
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogFileSink::Write( const CStr& message )
|
|
{
|
|
// File not opened?
|
|
if ( !m_File.is_open() )
|
|
{
|
|
OpenFile( m_FileName, m_Append );
|
|
|
|
// If still not opened, ignore message
|
|
if ( !m_File.is_open() ) return;
|
|
}
|
|
|
|
// Write message
|
|
if ( !message.empty() )
|
|
{
|
|
m_File << message;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Write()
|
|
// Desc: Writes a character to the file
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogFileSink::Write( char c )
|
|
{
|
|
// File not opened?
|
|
if ( !m_File.is_open() )
|
|
{
|
|
OpenFile( m_FileName, m_Append );
|
|
|
|
// If still not opened, ignore character
|
|
if ( !m_File.is_open() ) return;
|
|
}
|
|
|
|
// Write character
|
|
m_File << c;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: OpenFile()
|
|
// Desc: Open the file where the logging will output
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogFileSink::OpenFile( const CStr& fileName, bool append )
|
|
{
|
|
// Close any open file
|
|
if ( m_File.is_open() ) m_File.close();
|
|
|
|
// Open the file and log start
|
|
m_File.open( fileName.c_str(), append ? std::ios::app : std::ios::out );
|
|
if ( !m_File.is_open() )
|
|
{
|
|
// throw std::ios_base::failure
|
|
return;
|
|
}
|
|
|
|
m_FileName = fileName;
|
|
m_Append = append;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: CloseFile()
|
|
// Desc: Closes the opened file
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogFileSink::CloseFile( void )
|
|
{
|
|
if ( m_File.is_open() )
|
|
{
|
|
m_File.flush();
|
|
m_File.close();
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: CNetLogConsoleSink()
|
|
// Desc: Constructor
|
|
//-----------------------------------------------------------------------------
|
|
CNetLogConsoleSink::CNetLogConsoleSink( void )
|
|
{
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: ~CNetLogConsoleSink()
|
|
// Desc: Destructor
|
|
//-----------------------------------------------------------------------------
|
|
CNetLogConsoleSink::~CNetLogConsoleSink( void )
|
|
{
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Activate()
|
|
// Desc: Activates the game console
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogConsoleSink::OnActivate( void )
|
|
{
|
|
WriteHeader();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: OnClose()
|
|
// Desc: Toggles off game console
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogConsoleSink::OnClose( void )
|
|
{
|
|
WriteFooter();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Sink()
|
|
// Desc: Log the event to file
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogConsoleSink::Sink( const CNetLogEvent& event )
|
|
{
|
|
Write( event.GetMessage() );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Write()
|
|
// Desc: Writes a message to game console
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogConsoleSink::Write( const CStr& message )
|
|
{
|
|
// Do we have a valid console?
|
|
if ( !g_Console ) return;
|
|
|
|
// Write message
|
|
if ( !message.empty() )
|
|
{
|
|
g_Console->InsertMessage( message.FromUTF8().c_str() );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Write()
|
|
// Desc: Writes a character to the file
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogConsoleSink::Write( char c )
|
|
{
|
|
// Do we have a valid console?
|
|
if ( !g_Console ) return;
|
|
|
|
// Write character
|
|
Write( CStr( c ) );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: CNetLogger()
|
|
// Desc: Constructor
|
|
//-----------------------------------------------------------------------------
|
|
CNetLogger::CNetLogger( const CStr& name )
|
|
{
|
|
m_Name = name;
|
|
m_Level = LOG_LEVEL_ALL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: ~CNetLogger()
|
|
// Desc: Destructor
|
|
//-----------------------------------------------------------------------------
|
|
CNetLogger::~CNetLogger( void )
|
|
{
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: SetLevel()
|
|
// Desc: Set logger level
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogger::SetLevel( LogLevel level )
|
|
{
|
|
m_Level = level;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: IsDebugEnabled()
|
|
// Desc: Check if enabled for DEBUG level
|
|
//-----------------------------------------------------------------------------
|
|
bool CNetLogger::IsDebugEnabled( void ) const
|
|
{
|
|
return ( LOG_LEVEL_DEBUG >= m_Level );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: IsErrorEnabled()
|
|
// Desc: Check if enabled for ERROR level
|
|
//-----------------------------------------------------------------------------
|
|
bool CNetLogger::IsErrorEnabled( void ) const
|
|
{
|
|
return ( LOG_LEVEL_ERROR >= m_Level );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: IsFatalEnabled()
|
|
// Desc: Check if enabled for FATAL level
|
|
//-----------------------------------------------------------------------------
|
|
bool CNetLogger::IsFatalEnabled( void ) const
|
|
{
|
|
return ( LOG_LEVEL_FATAL >= m_Level );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: IsInfoEnabled()
|
|
// Desc: Check if enabled for INFO level
|
|
//-----------------------------------------------------------------------------
|
|
bool CNetLogger::IsInfoEnabled( void ) const
|
|
{
|
|
return ( LOG_LEVEL_INFO >= m_Level );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: IsWarnEnabled()
|
|
// Desc: Check if enabled for WARN level
|
|
//-----------------------------------------------------------------------------
|
|
bool CNetLogger::IsWarnEnabled( void ) const
|
|
{
|
|
return ( LOG_LEVEL_WARN >= m_Level );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Debug()
|
|
// Desc: Log a message with DEBUG level
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogger::Debug( const CStr& message )
|
|
{
|
|
if ( IsDebugEnabled() )
|
|
{
|
|
// Get timestamp as a string
|
|
CStr timer;
|
|
GetStringTimeStamp( timer );
|
|
|
|
CStr eventMessage = "DEBUG";
|
|
eventMessage += " - ";
|
|
eventMessage += timer;
|
|
eventMessage += " ";
|
|
eventMessage += message;
|
|
eventMessage += "\n";
|
|
|
|
CNetLogEvent newEvent( LOG_LEVEL_DEBUG, eventMessage, m_Name );
|
|
|
|
CallSinks( newEvent );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Debug()
|
|
// Desc: Log a formatted message with DEBUG level
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogger::DebugFormat( const char* pFormat, ... )
|
|
{
|
|
if ( IsDebugEnabled() )
|
|
{
|
|
char buffer[ 512 ] = { 0 };
|
|
CStr timer;
|
|
va_list args;
|
|
|
|
// Get timestamp as a string
|
|
GetStringTimeStamp( timer );
|
|
|
|
// Get arguments as a string
|
|
va_start ( args, pFormat );
|
|
vsnprintf ( buffer, 512, pFormat, args );
|
|
va_end ( args );
|
|
|
|
// Format message (e.g. ERROR - Hello World)
|
|
CStr eventMessage = "DEBUG";
|
|
eventMessage += " - ";
|
|
eventMessage += timer;
|
|
eventMessage += " ";
|
|
eventMessage += buffer;
|
|
eventMessage += "\n";
|
|
|
|
CNetLogEvent newEvent( LOG_LEVEL_DEBUG, eventMessage, m_Name );
|
|
|
|
CallSinks( newEvent );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Error()
|
|
// Desc: Log a message with ERROR level
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogger::Error( const CStr& message )
|
|
{
|
|
if ( IsErrorEnabled() )
|
|
{
|
|
// Get timestamp as a string
|
|
CStr timer;
|
|
GetStringTimeStamp( timer );
|
|
|
|
CStr eventMessage = "ERROR";
|
|
eventMessage += " - ";
|
|
eventMessage += timer;
|
|
eventMessage += " ";
|
|
eventMessage += message;
|
|
eventMessage += "\n";
|
|
|
|
CNetLogEvent newEvent( LOG_LEVEL_ERROR, eventMessage, m_Name );
|
|
|
|
CallSinks( newEvent );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Error()
|
|
// Desc: Log a formatted message with ERROR level
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogger::ErrorFormat( const char* pFormat, ... )
|
|
{
|
|
if ( IsErrorEnabled() )
|
|
{
|
|
char buffer[ 512 ] = { 0 };
|
|
CStr timer;
|
|
va_list args;
|
|
|
|
// Get timestamp as a string
|
|
GetStringTimeStamp( timer );
|
|
|
|
// Get arguments as a string
|
|
va_start ( args, pFormat );
|
|
vsnprintf ( buffer, 512, pFormat, args );
|
|
va_end ( args );
|
|
|
|
// Format message (e.g. ERROR - Hello World)
|
|
CStr eventMessage = "ERROR";
|
|
eventMessage += " - ";
|
|
eventMessage += timer;
|
|
eventMessage += " ";
|
|
eventMessage += buffer;
|
|
eventMessage += "\n";
|
|
|
|
CNetLogEvent newEvent( LOG_LEVEL_ERROR, eventMessage, m_Name );
|
|
|
|
CallSinks( newEvent );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Fatal()
|
|
// Desc: Log a message with FATAL level
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogger::Fatal( const CStr& message )
|
|
{
|
|
if ( IsFatalEnabled() )
|
|
{
|
|
// Get timestamp as a string
|
|
CStr timer;
|
|
GetStringTimeStamp( timer );
|
|
|
|
CStr eventMessage = "FATAL";
|
|
eventMessage += " - ";
|
|
eventMessage += timer;
|
|
eventMessage += " ";
|
|
eventMessage += message;
|
|
eventMessage += "\n";
|
|
|
|
CNetLogEvent newEvent( LOG_LEVEL_FATAL, eventMessage, m_Name );
|
|
|
|
CallSinks( newEvent );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Fatal()
|
|
// Desc: Log a formatted message with FATAL error
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogger::FatalFormat( const char* pFormat, ... )
|
|
{
|
|
if ( IsFatalEnabled() )
|
|
{
|
|
char buffer[ 512 ] = { 0 };
|
|
CStr timer;
|
|
va_list args;
|
|
|
|
// Get timestamp as a string
|
|
GetStringTimeStamp( timer );
|
|
|
|
// Get arguments as a string
|
|
va_start ( args, pFormat );
|
|
vsnprintf ( buffer, 512, pFormat, args );
|
|
va_end ( args );
|
|
|
|
// Format message (e.g. ERROR - Hello World)
|
|
CStr eventMessage = "FATAL";
|
|
eventMessage += " - ";
|
|
eventMessage += timer;
|
|
eventMessage += " ";
|
|
eventMessage += buffer;
|
|
eventMessage += "\n";
|
|
|
|
CNetLogEvent newEvent( LOG_LEVEL_FATAL, eventMessage, m_Name );
|
|
|
|
CallSinks( newEvent );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Info()
|
|
// Desc: Log a message with INFO level
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogger::Info( const CStr& message )
|
|
{
|
|
if ( IsInfoEnabled() )
|
|
{
|
|
// Get timestamp as a string
|
|
CStr timer;
|
|
GetStringTimeStamp( timer );
|
|
|
|
CStr eventMessage = "INFO";
|
|
eventMessage += " - ";
|
|
eventMessage += timer;
|
|
eventMessage += " ";
|
|
eventMessage += message;
|
|
eventMessage += "\n";
|
|
|
|
CNetLogEvent newEvent( LOG_LEVEL_INFO, eventMessage, m_Name );
|
|
|
|
CallSinks( newEvent );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Info()
|
|
// Desc: Log a formatted message with INFO level
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogger::InfoFormat( const char* pFormat, ... )
|
|
{
|
|
if ( IsInfoEnabled() )
|
|
{
|
|
char buffer[ 512 ] = { 0 };
|
|
CStr timer;
|
|
va_list args;
|
|
|
|
// Get timestamp as a string
|
|
GetStringTimeStamp( timer );
|
|
|
|
// Get arguments as a string
|
|
va_start ( args, pFormat );
|
|
vsnprintf ( buffer, 512, pFormat, args );
|
|
va_end ( args );
|
|
|
|
// Format message (e.g. ERROR - Hello World)
|
|
CStr eventMessage = "INFO";
|
|
eventMessage += " - ";
|
|
eventMessage += timer;
|
|
eventMessage += " ";
|
|
eventMessage += buffer;
|
|
eventMessage += "\n";
|
|
|
|
CNetLogEvent newEvent( LOG_LEVEL_INFO, eventMessage, m_Name );
|
|
|
|
CallSinks( newEvent );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Warn()
|
|
// Desc: Log a message with WARN level
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogger::Warn( const CStr& message )
|
|
{
|
|
if ( IsWarnEnabled() )
|
|
{
|
|
// Get timestamp as a string
|
|
CStr timer;
|
|
GetStringTimeStamp( timer );
|
|
|
|
CStr eventMessage = "WARN";
|
|
eventMessage += " - ";
|
|
eventMessage += timer;
|
|
eventMessage += " ";
|
|
eventMessage += message;
|
|
eventMessage += "\n";
|
|
|
|
CNetLogEvent newEvent( LOG_LEVEL_WARN, eventMessage, m_Name );
|
|
|
|
CallSinks( newEvent );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Warn()
|
|
// Desc: Log a formatted message with WARN level
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogger::WarnFormat( const char* pFormat, ... )
|
|
{
|
|
if ( IsWarnEnabled() )
|
|
{
|
|
char buffer[ 512 ] = { 0 };
|
|
CStr timer;
|
|
va_list args;
|
|
|
|
// Get timestamp as a string
|
|
GetStringTimeStamp( timer );
|
|
|
|
// Get arguments as a string
|
|
va_start ( args, pFormat );
|
|
vsnprintf ( buffer, 512, pFormat, args );
|
|
va_end ( args );
|
|
|
|
// Format message (e.g. ERROR - Hello World)
|
|
CStr eventMessage = "WARN";
|
|
eventMessage += " - ";
|
|
eventMessage += timer;
|
|
eventMessage += " ";
|
|
eventMessage += buffer;
|
|
eventMessage += "\n";
|
|
|
|
CNetLogEvent newEvent( LOG_LEVEL_WARN, eventMessage, m_Name );
|
|
|
|
CallSinks( newEvent );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: AddSink()
|
|
// Desc: Attaches a new sink
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogger::AddSink( CNetLogSink* pSink )
|
|
{
|
|
size_t i;
|
|
CScopeLock lock( m_Mutex );
|
|
|
|
assert( pSink );
|
|
|
|
// Validate parameter
|
|
if ( !pSink ) return;
|
|
|
|
// Check if already exists
|
|
for ( i = 0; i < GetSinkCount(); i++ )
|
|
{
|
|
CNetLogSink* pCurrSink = GetSink( i );
|
|
if ( pCurrSink == pSink ) break;
|
|
}
|
|
|
|
// Already exists?
|
|
if ( i >= GetSinkCount() )
|
|
{
|
|
// Activate new sink
|
|
pSink->Activate();
|
|
|
|
// Add new sink to list
|
|
m_Sinks.push_back( pSink );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: RemoveSink()
|
|
// Desc: Removes the sink from the list of attached sinks
|
|
//-----------------------------------------------------------------------------
|
|
CNetLogSink* CNetLogger::RemoveSink( CNetLogSink* pSink )
|
|
{
|
|
CScopeLock lock( m_Mutex );
|
|
|
|
// Validate parameter
|
|
if ( !pSink ) return NULL;
|
|
|
|
// Lookup the sink object
|
|
SinkList::iterator it = m_Sinks.begin();
|
|
for ( ; it != m_Sinks.end(); it++ )
|
|
{
|
|
CNetLogSink* pCurrSink = *it;
|
|
if ( pCurrSink == pSink )
|
|
{
|
|
m_Sinks.erase( it );
|
|
|
|
return pCurrSink;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: RemoveSink()
|
|
// Desc: Removes the named sink
|
|
//-----------------------------------------------------------------------------
|
|
CNetLogSink* CNetLogger::RemoveSink( const CStr& name )
|
|
{
|
|
CScopeLock lock( m_Mutex );
|
|
|
|
// Lookup sink by name
|
|
SinkList::iterator it = m_Sinks.begin();
|
|
for ( ; it != m_Sinks.end(); it++ )
|
|
{
|
|
CNetLogSink* pCurrSink = *it;
|
|
if ( !pCurrSink ) continue;
|
|
|
|
if ( pCurrSink->GetName() == name )
|
|
{
|
|
m_Sinks.erase( it );
|
|
|
|
return pCurrSink;
|
|
}
|
|
}
|
|
|
|
// Sink not found
|
|
return NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: RemoveAllSinks()
|
|
// Desc: Remove all attached sinks
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogger::RemoveAllSinks( void )
|
|
{
|
|
CScopeLock lock( m_Mutex );
|
|
|
|
m_Sinks.clear();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: GetSinkCount()
|
|
// Desc: Retrive the number of attached sinks
|
|
//-----------------------------------------------------------------------------
|
|
size_t CNetLogger::GetSinkCount( void )
|
|
{
|
|
return m_Sinks.size();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: GetSink()
|
|
// Desc: Retrieves the sink by index
|
|
//-----------------------------------------------------------------------------
|
|
CNetLogSink* CNetLogger::GetSink( size_t index )
|
|
{
|
|
// Validate parameter
|
|
if ( index > m_Sinks.size() ) return NULL;
|
|
|
|
return m_Sinks[ index ];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: GetSink()
|
|
// Desc: Retrieve the sink by name
|
|
//-----------------------------------------------------------------------------
|
|
CNetLogSink* CNetLogger::GetSink( const CStr& name )
|
|
{
|
|
for ( size_t i = 0; i < GetSinkCount(); i++ )
|
|
{
|
|
CNetLogSink* pCurrSink = GetSink( i );
|
|
if ( !pCurrSink ) continue;
|
|
|
|
if ( pCurrSink->GetName() == name )
|
|
return pCurrSink;
|
|
}
|
|
|
|
// Sink not found
|
|
return NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: CallSinks()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogger::CallSinks( const CNetLogEvent& event )
|
|
{
|
|
for ( size_t i = 0; i < GetSinkCount(); i++ )
|
|
{
|
|
CNetLogSink* pCurrSink = GetSink( i );
|
|
if ( !pCurrSink ) continue;
|
|
|
|
pCurrSink->DoSink( event );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: GetStringLocalTime()
|
|
// Desc: Returns the local date time into the passed in string
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogger::GetStringDateTime( CStr &str )
|
|
{
|
|
char buffer[ 128 ] = { 0 };
|
|
time_t tm;
|
|
struct tm *now;
|
|
|
|
#if OS_WIN
|
|
// Set timezone
|
|
_tzset();
|
|
|
|
// Get time and convert to tm structure
|
|
time( &tm );
|
|
struct tm nowBuf;
|
|
localtime_s( &nowBuf, &tm );
|
|
now = &nowBuf;
|
|
#else
|
|
time ( &tm );
|
|
now = localtime( &tm );
|
|
#endif
|
|
|
|
// Build custom time string
|
|
strftime( buffer, 128, "%Y-%m-%d %H:%M:%S", now );
|
|
|
|
str = buffer;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: GetStringTime()
|
|
// Desc: Returns the local time into the passed string
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogger::GetStringTime( CStr& str )
|
|
{
|
|
char buffer[ 128 ] = { 0 };
|
|
time_t tm;
|
|
struct tm *now;
|
|
|
|
#if OS_WIN
|
|
// Set timezone
|
|
_tzset();
|
|
|
|
// Get time and convert to tm structure
|
|
time( &tm );
|
|
struct tm nowBuf;
|
|
localtime_s( &nowBuf, &tm );
|
|
now = &nowBuf;
|
|
#else
|
|
time ( &tm );
|
|
now = localtime( &tm );
|
|
#endif
|
|
|
|
// Build custom time string
|
|
strftime( buffer, 128, "%H%M%S", now );
|
|
|
|
str = buffer;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: GetStringTimeStamp()
|
|
// Desc: Returns the formatted current time into the passed string
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogger::GetStringTimeStamp( CStr& str )
|
|
{
|
|
char buffer[ 128 ] = { 0 };
|
|
double timestamp = timer_Time();
|
|
sprintf( buffer, "[%3u.%03u]", ( unsigned )timestamp, ( ( unsigned )( timestamp * 1000 ) % 1000 ) );
|
|
str = buffer;
|
|
}
|
|
|
|
// List of loggers under log manager
|
|
LoggerList CNetLogManager::m_Loggers;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Shutdown()
|
|
// Desc: Shuts down the log manager
|
|
//-----------------------------------------------------------------------------
|
|
void CNetLogManager::Shutdown( void )
|
|
{
|
|
// Remove all loggers
|
|
LoggerList::iterator it = m_Loggers.begin();
|
|
for ( ; it != m_Loggers.end(); it++ )
|
|
{
|
|
CNetLogger *pCurrLogger = *it;
|
|
if ( !pCurrLogger ) continue;
|
|
|
|
pCurrLogger->RemoveAllSinks();
|
|
|
|
delete pCurrLogger;
|
|
}
|
|
|
|
m_Loggers.clear();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: GetLogger()
|
|
// Desc: Retrieve or create a named logger
|
|
//-----------------------------------------------------------------------------
|
|
CNetLogger* CNetLogManager::GetLogger( const CStr& name )
|
|
{
|
|
LoggerList::const_iterator it = m_Loggers.begin();
|
|
for ( ; it != m_Loggers.end(); it++ )
|
|
{
|
|
CNetLogger* pCurrLogger = *it;
|
|
if ( !pCurrLogger ) continue;
|
|
|
|
if ( pCurrLogger->GetName() == name )
|
|
return pCurrLogger;
|
|
}
|
|
|
|
// Logger not found, create it
|
|
CNetLogger* pNewLogger = new CNetLogger( name );
|
|
if ( !pNewLogger ) return NULL;
|
|
|
|
// Add new logger to list
|
|
m_Loggers.push_back( pNewLogger );
|
|
|
|
return pNewLogger;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: GetAllLoggers()
|
|
// Desc: Return the list of loggers
|
|
//-----------------------------------------------------------------------------
|
|
const LoggerList& CNetLogManager::GetAllLoggers( void )
|
|
{
|
|
return m_Loggers;
|
|
}
|
|
|
|
|