diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Bindings/LuaFunctions.h | 2 | ||||
-rw-r--r-- | src/Bindings/ManualBindings.cpp | 10 | ||||
-rw-r--r-- | src/CMakeLists.txt | 9 | ||||
-rw-r--r-- | src/CompositeChat.cpp | 24 | ||||
-rw-r--r-- | src/CompositeChat.h | 2 | ||||
-rw-r--r-- | src/Globals.h | 2 | ||||
-rw-r--r-- | src/Log.cpp | 169 | ||||
-rw-r--r-- | src/Log.h | 30 | ||||
-rw-r--r-- | src/Logger.cpp | 145 | ||||
-rw-r--r-- | src/Logger.h | 73 | ||||
-rw-r--r-- | src/LoggerListeners.cpp | 322 | ||||
-rw-r--r-- | src/LoggerListeners.h | 31 | ||||
-rw-r--r-- | src/MCLogger.cpp | 267 | ||||
-rw-r--r-- | src/MCLogger.h | 95 | ||||
-rw-r--r-- | src/OSSupport/File.cpp | 7 | ||||
-rw-r--r-- | src/OSSupport/File.h | 7 | ||||
-rw-r--r-- | src/Root.cpp | 26 | ||||
-rw-r--r-- | src/Root.h | 2 | ||||
-rw-r--r-- | src/StringUtils.h | 1 | ||||
-rw-r--r-- | src/main.cpp | 2 |
20 files changed, 624 insertions, 602 deletions
diff --git a/src/Bindings/LuaFunctions.h b/src/Bindings/LuaFunctions.h index 2ea37d7a4..be1d9aaa9 100644 --- a/src/Bindings/LuaFunctions.h +++ b/src/Bindings/LuaFunctions.h @@ -1,6 +1,6 @@ #pragma once -#include "../MCLogger.h" +#include "Logger.h" #include <time.h> // tolua_begin diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp index 6b40cece8..5aa76eee3 100644 --- a/src/Bindings/ManualBindings.cpp +++ b/src/Bindings/ManualBindings.cpp @@ -168,7 +168,7 @@ static AString GetLogMessage(lua_State * tolua_S) static int tolua_LOG(lua_State * tolua_S) { // If the param is a cCompositeChat, read the log level from it: - cMCLogger::eLogLevel LogLevel = cMCLogger::llRegular; + cLogger::eLogLevel LogLevel = cLogger::llRegular; tolua_Error err; if (tolua_isusertype(tolua_S, 1, "cCompositeChat", false, &err)) { @@ -176,7 +176,7 @@ static int tolua_LOG(lua_State * tolua_S) } // Log the message: - cMCLogger::GetInstance()->LogSimple(GetLogMessage(tolua_S).c_str(), LogLevel); + cLogger::GetInstance().LogSimple(GetLogMessage(tolua_S).c_str(), LogLevel); return 0; } @@ -186,7 +186,7 @@ static int tolua_LOG(lua_State * tolua_S) static int tolua_LOGINFO(lua_State * tolua_S) { - cMCLogger::GetInstance()->LogSimple(GetLogMessage(tolua_S).c_str(), cMCLogger::llInfo); + cLogger::GetInstance().LogSimple(GetLogMessage(tolua_S).c_str(), cLogger::llInfo); return 0; } @@ -196,7 +196,7 @@ static int tolua_LOGINFO(lua_State * tolua_S) static int tolua_LOGWARN(lua_State * tolua_S) { - cMCLogger::GetInstance()->LogSimple(GetLogMessage(tolua_S).c_str(), cMCLogger::llWarning); + cLogger::GetInstance().LogSimple(GetLogMessage(tolua_S).c_str(), cLogger::llWarning); return 0; } @@ -206,7 +206,7 @@ static int tolua_LOGWARN(lua_State * tolua_S) static int tolua_LOGERROR(lua_State * tolua_S) { - cMCLogger::GetInstance()->LogSimple(GetLogMessage(tolua_S).c_str(), cMCLogger::llError); + cLogger::GetInstance().LogSimple(GetLogMessage(tolua_S).c_str(), cLogger::llError); return 0; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3994399f2..6b5efbd1f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required (VERSION 2.8.2) project (MCServer) + include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/") include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/jsoncpp/include") include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/polarssl/include") @@ -41,8 +42,8 @@ SET (SRCS LightingThread.cpp LineBlockTracer.cpp LinearInterpolation.cpp - Log.cpp - MCLogger.cpp + LoggerListeners.cpp + Logger.cpp Map.cpp MapManager.cpp MobCensus.cpp @@ -107,8 +108,8 @@ SET (HDRS LineBlockTracer.h LinearInterpolation.h LinearUpscale.h - Log.h - MCLogger.h + Logger.h + LoggerListeners.h Map.h MapManager.h Matrix4.h diff --git a/src/CompositeChat.cpp b/src/CompositeChat.cpp index f1a797897..0d339021e 100644 --- a/src/CompositeChat.cpp +++ b/src/CompositeChat.cpp @@ -353,23 +353,23 @@ AString cCompositeChat::ExtractText(void) const -cMCLogger::eLogLevel cCompositeChat::MessageTypeToLogLevel(eMessageType a_MessageType) +cLogger::eLogLevel cCompositeChat::MessageTypeToLogLevel(eMessageType a_MessageType) { switch (a_MessageType) { - case mtCustom: return cMCLogger::llRegular; - case mtFailure: return cMCLogger::llWarning; - case mtInformation: return cMCLogger::llInfo; - case mtSuccess: return cMCLogger::llRegular; - case mtWarning: return cMCLogger::llWarning; - case mtFatal: return cMCLogger::llError; - case mtDeath: return cMCLogger::llRegular; - case mtPrivateMessage: return cMCLogger::llRegular; - case mtJoin: return cMCLogger::llRegular; - case mtLeave: return cMCLogger::llRegular; + case mtCustom: return cLogger::llRegular; + case mtFailure: return cLogger::llWarning; + case mtInformation: return cLogger::llInfo; + case mtSuccess: return cLogger::llRegular; + case mtWarning: return cLogger::llWarning; + case mtFatal: return cLogger::llError; + case mtDeath: return cLogger::llRegular; + case mtPrivateMessage: return cLogger::llRegular; + case mtJoin: return cLogger::llRegular; + case mtLeave: return cLogger::llRegular; } ASSERT(!"Unhandled MessageType"); - return cMCLogger::llError; + return cLogger::llError; } diff --git a/src/CompositeChat.h b/src/CompositeChat.h index 1ad196f1d..2dc21b98f 100644 --- a/src/CompositeChat.h +++ b/src/CompositeChat.h @@ -196,7 +196,7 @@ public: /** Converts the MessageType to a LogLevel value. Used by the logging bindings when logging a cCompositeChat object. */ - static cMCLogger::eLogLevel MessageTypeToLogLevel(eMessageType a_MessageType); + static cLogger::eLogLevel MessageTypeToLogLevel(eMessageType a_MessageType); protected: /** All the parts that */ diff --git a/src/Globals.h b/src/Globals.h index 60ee456c9..de1024010 100644 --- a/src/Globals.h +++ b/src/Globals.h @@ -249,7 +249,7 @@ template class SizeChecker<UInt16, 2>; #include "OSSupport/Event.h" #include "OSSupport/Thread.h" #include "OSSupport/File.h" - #include "MCLogger.h" + #include "Logger.h" #else // Logging functions void inline LOGERROR(const char* a_Format, ...) FORMATSTRING(1, 2); diff --git a/src/Log.cpp b/src/Log.cpp deleted file mode 100644 index 7686a0fb4..000000000 --- a/src/Log.cpp +++ /dev/null @@ -1,169 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Log.h" - -#include <fstream> -#include <ctime> -#include "OSSupport/IsThread.h" - -#if defined(ANDROID_NDK) - #include <android/log.h> - #include "ToJava.h" -#endif - - - - -cLog* cLog::s_Log = NULL; - -cLog::cLog(const AString & a_FileName) - : m_File(NULL) -{ - s_Log = this; - - // create logs directory - cFile::CreateFolder(FILE_IO_PREFIX + AString("logs")); - - OpenLog((FILE_IO_PREFIX + AString("logs/") + a_FileName).c_str()); -} - - - - - -cLog::~cLog() -{ - CloseLog(); - s_Log = NULL; -} - - - - - -cLog * cLog::GetInstance() -{ - if (s_Log != NULL) - { - return s_Log; - } - - new cLog("log.txt"); - return s_Log; -} - - - - - -void cLog::CloseLog() -{ - if (m_File) - fclose (m_File); - m_File = 0; -} - - - - - -void cLog::OpenLog( const char* a_FileName) -{ - if (m_File) fclose (m_File); - #ifdef _MSC_VER - fopen_s( &m_File, a_FileName, "a+"); - #else - m_File = fopen(a_FileName, "a+"); - #endif -} - - - - - -void cLog::ClearLog() -{ - #ifdef _MSC_VER - if (fopen_s( &m_File, "log.txt", "w") == 0) - fclose (m_File); - #else - m_File = fopen("log.txt", "w"); - if (m_File) - fclose (m_File); - #endif - m_File = NULL; -} - - - - - -void cLog::Log(const char * a_Format, va_list argList) -{ - AString Message; - AppendVPrintf(Message, a_Format, argList); - - time_t rawtime; - time ( &rawtime); - - struct tm* timeinfo; -#ifdef _MSC_VER - struct tm timeinforeal; - timeinfo = &timeinforeal; - localtime_s(timeinfo, &rawtime); -#else - timeinfo = localtime( &rawtime); -#endif - - AString Line; - #ifdef _DEBUG - Printf(Line, "[%04lx|%02d:%02d:%02d] %s", cIsThread::GetCurrentID(), timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, Message.c_str()); - #else - Printf(Line, "[%02d:%02d:%02d] %s", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, Message.c_str()); - #endif - if (m_File) - { - fprintf(m_File, "%s\n", Line.c_str()); - fflush(m_File); - } - - // Print to console: -#if defined(ANDROID_NDK) - // __android_log_vprint(ANDROID_LOG_ERROR, "MCServer", a_Format, argList); - __android_log_print(ANDROID_LOG_ERROR, "MCServer", "%s", Line.c_str()); - // CallJavaFunction_Void_String(g_JavaThread, "AddToLog", Line); -#else - printf("%s", Line.c_str()); -#endif - - #if defined (_WIN32) && defined(_DEBUG) - // In a Windows Debug build, output the log to debug console as well: - OutputDebugStringA((Line + "\n").c_str()); - #endif // _WIN32 -} - - - - - -void cLog::Log(const char * a_Format, ...) -{ - va_list argList; - va_start(argList, a_Format); - Log(a_Format, argList); - va_end(argList); -} - - - - - -void cLog::SimpleLog(const char * a_String) -{ - Log("%s", a_String); -} - - - - diff --git a/src/Log.h b/src/Log.h deleted file mode 100644 index dc88aa92f..000000000 --- a/src/Log.h +++ /dev/null @@ -1,30 +0,0 @@ - -#pragma once - - - - - -class cLog -{ -private: - FILE * m_File; - static cLog * s_Log; - -public: - cLog(const AString & a_FileName); - ~cLog(); - void Log(const char * a_Format, va_list argList) FORMATSTRING(2, 0); - void Log(const char * a_Format, ...) FORMATSTRING(2, 3); - // tolua_begin - void SimpleLog(const char * a_String); - void OpenLog(const char * a_FileName); - void CloseLog(); - void ClearLog(); - static cLog* GetInstance(); -}; - - - - - diff --git a/src/Logger.cpp b/src/Logger.cpp new file mode 100644 index 000000000..cb528e8ab --- /dev/null +++ b/src/Logger.cpp @@ -0,0 +1,145 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "OSSupport/IsThread.h" +#ifdef _WIN32 + #include <time.h> +#endif + + + + + +cLogger & cLogger::GetInstance(void) +{ + static cLogger Instance; + return Instance; +} + + + + + +void cLogger::InitiateMultithreading() +{ + GetInstance(); +} + + + + + +void cLogger::LogSimple(AString a_Message, eLogLevel a_LogLevel) +{ + time_t rawtime; + time(&rawtime); + + struct tm * timeinfo; + #ifdef _MSC_VER + struct tm timeinforeal; + timeinfo = &timeinforeal; + localtime_s(timeinfo, &rawtime); + #else + timeinfo = localtime(&rawtime); + #endif + + AString Line; + #ifdef _DEBUG + Printf(Line, "[%04lx|%02d:%02d:%02d] %s\n", cIsThread::GetCurrentID(), timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, a_Message.c_str()); + #else + Printf(Line, "[%02d:%02d:%02d] %s\n", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, a_Message.c_str()); + #endif + + + cCSLock Lock(m_CriticalSection); + for (size_t i = 0; i < m_LogListeners.size(); i++) + { + m_LogListeners[i]->Log(Line, a_LogLevel); + } +} + + + + + +void cLogger::Log(const char * a_Format, eLogLevel a_LogLevel, va_list a_ArgList) +{ + AString Message; + AppendVPrintf(Message, a_Format, a_ArgList); + LogSimple(Message, a_LogLevel); +} + + + + + +void cLogger::AttachListener(cListener * a_Listener) +{ + cCSLock Lock(m_CriticalSection); + m_LogListeners.push_back(a_Listener); +} + + + + + +void cLogger::DetachListener(cListener * a_Listener) +{ + cCSLock Lock(m_CriticalSection); + m_LogListeners.erase(std::remove(m_LogListeners.begin(), m_LogListeners.end(), a_Listener)); +} + + + + + +//////////////////////////////////////////////////////////////////////////////// +// Global functions + +void LOG(const char * a_Format, ...) +{ + va_list argList; + va_start(argList, a_Format); + cLogger::GetInstance().Log(a_Format, cLogger::llRegular, argList); + va_end(argList); +} + + + + + +void LOGINFO(const char * a_Format, ...) +{ + va_list argList; + va_start(argList, a_Format); + cLogger::GetInstance().Log( a_Format, cLogger::llInfo, argList); + va_end(argList); +} + + + + + +void LOGWARN(const char * a_Format, ...) +{ + va_list argList; + va_start(argList, a_Format); + cLogger::GetInstance().Log( a_Format, cLogger::llWarning, argList); + va_end(argList); +} + + + + + +void LOGERROR(const char * a_Format, ...) +{ + va_list argList; + va_start(argList, a_Format); + cLogger::GetInstance().Log( a_Format, cLogger::llError, argList); + va_end(argList); +} + + + + diff --git a/src/Logger.h b/src/Logger.h new file mode 100644 index 000000000..5e65de8a8 --- /dev/null +++ b/src/Logger.h @@ -0,0 +1,73 @@ + +#pragma once + + +class cLogger +{ +public: + + enum eLogLevel + { + llRegular, + llInfo, + llWarning, + llError, + }; + + + class cListener + { + public: + virtual void Log(AString a_Message, eLogLevel a_LogLevel) = 0; + + virtual ~cListener(){} + }; + + void Log (const char * a_Format, eLogLevel a_LogLevel, va_list a_ArgList) FORMATSTRING(2, 0); + + /** Logs the simple text message at the specified log level. */ + void LogSimple(AString a_Message, eLogLevel a_LogLevel = llRegular); + + void AttachListener(cListener * a_Listener); + void DetachListener(cListener * a_Listener); + + static cLogger & GetInstance(void); + // Must be called before calling GetInstance in a multithreaded context + static void InitiateMultithreading(); +private: + + cCriticalSection m_CriticalSection; + std::vector<cListener *> m_LogListeners; + +}; + + + + + + +extern void LOG(const char* a_Format, ...) FORMATSTRING(1, 2); +extern void LOGINFO(const char* a_Format, ...) FORMATSTRING(1, 2); +extern void LOGWARN(const char* a_Format, ...) FORMATSTRING(1, 2); +extern void LOGERROR(const char* a_Format, ...) FORMATSTRING(1, 2); + + + + + +// In debug builds, translate LOGD to LOG, otherwise leave it out altogether: +#ifdef _DEBUG + #define LOGD LOG +#else + #define LOGD(...) +#endif // _DEBUG + + + + + +#define LOGWARNING LOGWARN + + + + diff --git a/src/LoggerListeners.cpp b/src/LoggerListeners.cpp new file mode 100644 index 000000000..836536cbd --- /dev/null +++ b/src/LoggerListeners.cpp @@ -0,0 +1,322 @@ + +#include "Globals.h" + +#include "LoggerListeners.h" + +#if defined(_WIN32) + #include <io.h> // Needed for _isatty(), not available on Linux + #include <time.h> +#elif defined(__linux) && !defined(ANDROID_NDK) + #include <unistd.h> // Needed for isatty() on Linux +#elif defined(ANDROID_NDK) + #include <android/log.h> +#endif + + +#if defined(_WIN32) || (defined (__linux) && !defined(ANDROID_NDK)) + class cColouredConsoleListener + : public cLogger::cListener + { + protected: + + virtual void SetLogColour(cLogger::eLogLevel a_LogLevel) = 0; + virtual void SetDefaultLogColour() = 0; + + virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override + { + SetLogColour(a_LogLevel); + fputs(a_Message.c_str(), stdout); + SetDefaultLogColour(); + } + }; +#endif + + + + + +#ifdef _WIN32 + class cWindowsConsoleListener + : public cColouredConsoleListener + { + typedef cColouredConsoleListener super; + public: + cWindowsConsoleListener(HANDLE a_Console, WORD a_DefaultConsoleAttrib) : + m_Console(a_Console), + m_DefaultConsoleAttrib(a_DefaultConsoleAttrib) + { + } + + #ifdef _DEBUG + virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override + { + super::Log(a_Message, a_LogLevel); + // In a Windows Debug build, output the log to debug console as well: + OutputDebugStringA(a_Message.c_str()); + } + #endif + + + virtual void SetLogColour(cLogger::eLogLevel a_LogLevel) override + { + // by default, gray on black + WORD Attrib = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED; + switch (a_LogLevel) + { + case cLogger::llRegular: + { + // Gray on black + Attrib = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED; + break; + } + case cLogger::llInfo: + { + // Yellow on black + Attrib = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; + break; + } + case cLogger::llWarning: + { + // Red on black + Attrib = FOREGROUND_RED | FOREGROUND_INTENSITY; + break; + } + case cLogger::llError: + { + // Black on red + Attrib = BACKGROUND_RED | BACKGROUND_INTENSITY; + break; + } + } + SetConsoleTextAttribute(m_Console, Attrib); + } + + + virtual void SetDefaultLogColour() override + { + SetConsoleTextAttribute(m_Console, m_DefaultConsoleAttrib); + } + + private: + + HANDLE m_Console; + WORD m_DefaultConsoleAttrib; + }; + + + +#elif defined (__linux) && !defined(ANDROID_NDK) + + + + class cLinuxConsoleListener + : public cColouredConsoleListener + { + public: + virtual void SetLogColour(cLogger::eLogLevel a_LogLevel) override + { + switch (a_LogLevel) + { + case cLogger::llRegular: + { + // Whatever the console default is + printf("\x1b[0m"); + break; + } + case cLogger::llInfo: + { + // Yellow on black + printf("\x1b[33;1m"); + break; + } + case cLogger::llWarning: + { + // Red on black + printf("\x1b[31;1m"); + break; + } + case cLogger::llError: + { + // Yellow on red + printf("\x1b[1;33;41;1m"); + break; + } + } + } + + + virtual void SetDefaultLogColour() override + { + // Whatever the console default is + printf("\x1b[0m"); + } + }; + + + +#elif defined(ANDROID_NDK) + + + + class cAndroidConsoleListener + : public cLogger::cListener + { + public: + virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override + { + android_LogPriority AndroidLogLevel; + switch (a_LogLevel) + { + case cLogger::llRegular: + { + AndroidLogLevel = ANDROID_LOG_VERBOSE; + break; + } + case cLogger::llInfo: + { + AndroidLogLevel = ANDROID_LOG_INFO; + break; + } + case cLogger::llWarning: + { + AndroidLogLevel = ANDROID_LOG_WARNING; + break; + } + case cLogger::llError: + { + AndroidLogLevel = ANDROID_LOG_ERROR; + break; + } + } + __android_log_print(AndroidLogLevel, "MCServer", "%s", a_Message.c_str()); + } + }; + +#endif + + + + + +class cVanillaCPPConsoleListener + : public cLogger::cListener +{ +public: + virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override + { + AString LogLevelString; + switch (a_LogLevel) + { + case cLogger::llRegular: + { + LogLevelString = "Log"; + break; + } + case cLogger::llInfo: + { + LogLevelString = "Info"; + break; + } + case cLogger::llWarning: + { + LogLevelString = "Warning"; + break; + } + case cLogger::llError: + { + LogLevelString = "Error"; + break; + } + } + printf("%s: %s", LogLevelString.c_str(), a_Message.c_str()); + } +}; + + + + + +cLogger::cListener * MakeConsoleListener(void) +{ + #ifdef _WIN32 + // See whether we are writing to a console the default console attrib: + bool ShouldColorOutput = (_isatty(_fileno(stdin)) != 0); + if (ShouldColorOutput) + { + CONSOLE_SCREEN_BUFFER_INFO sbi; + HANDLE Console = GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleScreenBufferInfo(Console, &sbi); + WORD DefaultConsoleAttrib = sbi.wAttributes; + return new cWindowsConsoleListener(Console, DefaultConsoleAttrib); + } + else + { + return new cVanillaCPPConsoleListener; + } + + #elif defined (__linux) && !defined(ANDROID_NDK) + // TODO: lookup terminal in terminfo + if (isatty(fileno(stdout))) + { + return new cLinuxConsoleListener(); + } + else + { + return new cVanillaCPPConsoleListener(); + } + #else + return new cVanillaCPPConsoleListener(); + #endif +} + + + + + +//////////////////////////////////////////////////////////////////////////////// +// cFileListener: + +cFileListener::cFileListener(void) +{ + cFile::CreateFolder(FILE_IO_PREFIX + AString("logs")); + AString FileName; + FileName = Printf("%s%sLOG_%d.txt", FILE_IO_PREFIX, "logs/", (int)time(NULL)); + m_File.Open(FileName, cFile::fmAppend); +} + + + + + +void cFileListener::Log(AString a_Message, cLogger::eLogLevel a_LogLevel) +{ + const char * LogLevelPrefix = "Unkn "; + switch (a_LogLevel) + { + case cLogger::llRegular: + { + LogLevelPrefix = " "; + break; + } + case cLogger::llInfo: + { + LogLevelPrefix = "info "; + break; + } + case cLogger::llWarning: + { + LogLevelPrefix = "Warn "; + break; + } + case cLogger::llError: + { + LogLevelPrefix = "Err "; + break; + } + } + m_File.Printf("%s%s", LogLevelPrefix, a_Message.c_str()); +} + + + + diff --git a/src/LoggerListeners.h b/src/LoggerListeners.h new file mode 100644 index 000000000..d300184b1 --- /dev/null +++ b/src/LoggerListeners.h @@ -0,0 +1,31 @@ + +#include "Logger.h" + + + + + +class cFileListener + : public cLogger::cListener +{ +public: + + cFileListener(); + cFileListener(AString a_Filename); + + virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override; + +private: + + cFile m_File; +}; + + + + + +cLogger::cListener * MakeConsoleListener(); + + + + diff --git a/src/MCLogger.cpp b/src/MCLogger.cpp deleted file mode 100644 index 044e83937..000000000 --- a/src/MCLogger.cpp +++ /dev/null @@ -1,267 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include <time.h> -#include "Log.h" - - - - - -cMCLogger * cMCLogger::s_MCLogger = NULL; - -#ifdef _WIN32 - #include <io.h> // Needed for _isatty(), not available on Linux - - HANDLE g_Console = GetStdHandle(STD_OUTPUT_HANDLE); - WORD g_DefaultConsoleAttrib = 0x07; -#elif defined (__linux) && !defined(ANDROID_NDK) - #include <unistd.h> // Needed for isatty() on Linux -#endif - - - - - -cMCLogger * cMCLogger::GetInstance(void) -{ - return s_MCLogger; -} - - - - - -cMCLogger::cMCLogger(void): - m_ShouldColorOutput(false) -{ - AString FileName; - Printf(FileName, "LOG_%d.txt", (int)time(NULL)); - InitLog(FileName); -} - - - - - -cMCLogger::cMCLogger(const AString & a_FileName) -{ - InitLog(a_FileName); -} - - - - - -cMCLogger::~cMCLogger() -{ - m_Log->Log("--- Stopped Log ---\n"); - delete m_Log; - m_Log = NULL; - if (this == s_MCLogger) - { - s_MCLogger = NULL; - } -} - - - - - -void cMCLogger::InitLog(const AString & a_FileName) -{ - m_Log = new cLog(a_FileName); - m_Log->Log("--- Started Log ---\n"); - - s_MCLogger = this; - - #ifdef _WIN32 - // See whether we are writing to a console the default console attrib: - m_ShouldColorOutput = (_isatty(_fileno(stdin)) != 0); - if (m_ShouldColorOutput) - { - CONSOLE_SCREEN_BUFFER_INFO sbi; - GetConsoleScreenBufferInfo(g_Console, &sbi); - g_DefaultConsoleAttrib = sbi.wAttributes; - } - #elif defined (__linux) && !defined(ANDROID_NDK) - m_ShouldColorOutput = isatty(fileno(stdout)); - // TODO: Check if the terminal supports colors, somehow? - #endif -} - - - - - -void cMCLogger::LogSimple(const char * a_Text, eLogLevel a_LogLevel) -{ - switch (a_LogLevel) - { - case llRegular: - { - LOG("%s", a_Text); - break; - } - case llInfo: - { - LOGINFO("%s", a_Text); - break; - } - case llWarning: - { - LOGWARN("%s", a_Text); - break; - } - case llError: - { - LOGERROR("%s", a_Text); - break; - } - } -} - - - - - -void cMCLogger::Log(const char * a_Format, va_list a_ArgList) -{ - cCSLock Lock(m_CriticalSection); - SetColor(csRegular); - m_Log->Log(a_Format, a_ArgList); - ResetColor(); - puts(""); -} - - - - - -void cMCLogger::Info(const char * a_Format, va_list a_ArgList) -{ - cCSLock Lock(m_CriticalSection); - SetColor(csInfo); - m_Log->Log(a_Format, a_ArgList); - ResetColor(); - puts(""); -} - - - - - -void cMCLogger::Warn(const char * a_Format, va_list a_ArgList) -{ - cCSLock Lock(m_CriticalSection); - SetColor(csWarning); - m_Log->Log(a_Format, a_ArgList); - ResetColor(); - puts(""); -} - - - - - -void cMCLogger::Error(const char * a_Format, va_list a_ArgList) -{ - cCSLock Lock(m_CriticalSection); - SetColor(csError); - m_Log->Log(a_Format, a_ArgList); - ResetColor(); - puts(""); -} - - - - - -void cMCLogger::SetColor(eColorScheme a_Scheme) -{ - if (!m_ShouldColorOutput) - { - return; - } - #ifdef _WIN32 - WORD Attrib = 0x07; // by default, gray on black - switch (a_Scheme) - { - case csRegular: Attrib = 0x07; break; // Gray on black - case csInfo: Attrib = 0x0e; break; // Yellow on black - case csWarning: Attrib = 0x0c; break; // Read on black - case csError: Attrib = 0xc0; break; // Black on red - default: ASSERT(!"Unhandled color scheme"); - } - SetConsoleTextAttribute(g_Console, Attrib); - #elif defined(__linux) && !defined(ANDROID_NDK) - switch (a_Scheme) - { - case csRegular: printf("\x1b[0m"); break; // Whatever the console default is - case csInfo: printf("\x1b[33;1m"); break; // Yellow on black - case csWarning: printf("\x1b[31;1m"); break; // Red on black - case csError: printf("\x1b[1;33;41;1m"); break; // Yellow on red - default: ASSERT(!"Unhandled color scheme"); - } - #endif -} - - - - - -void cMCLogger::ResetColor(void) -{ - if (!m_ShouldColorOutput) - { - return; - } - #ifdef _WIN32 - SetConsoleTextAttribute(g_Console, g_DefaultConsoleAttrib); - #elif defined(__linux) && !defined(ANDROID_NDK) - printf("\x1b[0m"); - #endif -} - - - - - -//////////////////////////////////////////////////////////////////////////////// -// Global functions - -void LOG(const char* a_Format, ...) -{ - va_list argList; - va_start(argList, a_Format); - cMCLogger::GetInstance()->Log( a_Format, argList); - va_end(argList); -} - -void LOGINFO(const char* a_Format, ...) -{ - va_list argList; - va_start(argList, a_Format); - cMCLogger::GetInstance()->Info( a_Format, argList); - va_end(argList); -} - -void LOGWARN(const char* a_Format, ...) -{ - va_list argList; - va_start(argList, a_Format); - cMCLogger::GetInstance()->Warn( a_Format, argList); - va_end(argList); -} - -void LOGERROR(const char* a_Format, ...) -{ - va_list argList; - va_start(argList, a_Format); - cMCLogger::GetInstance()->Error( a_Format, argList); - va_end(argList); -} - - - - diff --git a/src/MCLogger.h b/src/MCLogger.h deleted file mode 100644 index aa3a52d02..000000000 --- a/src/MCLogger.h +++ /dev/null @@ -1,95 +0,0 @@ - -#pragma once - - - - -class cLog; - - - - - -class cMCLogger -{ -public: - enum eLogLevel - { - llRegular, - llInfo, - llWarning, - llError, - }; - // tolua_end - - /** Creates a logger with the default filename, "logs/LOG_<timestamp>.log" */ - cMCLogger(void); - - /** Creates a logger with the specified filename inside "logs" folder */ - cMCLogger(const AString & a_FileName); - - ~cMCLogger(); - - void Log (const char * a_Format, va_list a_ArgList) FORMATSTRING(2, 0); - void Info (const char * a_Format, va_list a_ArgList) FORMATSTRING(2, 0); - void Warn (const char * a_Format, va_list a_ArgList) FORMATSTRING(2, 0); - void Error(const char * a_Format, va_list a_ArgList) FORMATSTRING(2, 0); - - /** Logs the simple text message at the specified log level. */ - void LogSimple(const char * a_Text, eLogLevel a_LogLevel = llRegular); - - static cMCLogger * GetInstance(); -private: - enum eColorScheme - { - csRegular, - csInfo, - csWarning, - csError, - } ; - - cCriticalSection m_CriticalSection; - cLog * m_Log; - static cMCLogger * s_MCLogger; - bool m_ShouldColorOutput; - - - /// Sets the specified color scheme in the terminal (TODO: if coloring available) - void SetColor(eColorScheme a_Scheme); - - /// Resets the color back to whatever is the default in the terminal - void ResetColor(void); - - /// Common initialization for all constructors, creates a logfile with the specified name and assigns s_MCLogger to this - void InitLog(const AString & a_FileName); -}; - - - - - -extern void LOG(const char* a_Format, ...) FORMATSTRING(1, 2); -extern void LOGINFO(const char* a_Format, ...) FORMATSTRING(1, 2); -extern void LOGWARN(const char* a_Format, ...) FORMATSTRING(1, 2); -extern void LOGERROR(const char* a_Format, ...) FORMATSTRING(1, 2); - - - - - -// In debug builds, translate LOGD to LOG, otherwise leave it out altogether: -#ifdef _DEBUG - #define LOGD LOG -#else - #define LOGD(...) -#endif // _DEBUG - - - - - -#define LOGWARNING LOGWARN - - - - diff --git a/src/OSSupport/File.cpp b/src/OSSupport/File.cpp index ff6fb5898..2194c46ee 100644 --- a/src/OSSupport/File.cpp +++ b/src/OSSupport/File.cpp @@ -70,6 +70,7 @@ bool cFile::Open(const AString & iFileName, eMode iMode) case fmRead: Mode = "rb"; break; case fmWrite: Mode = "wb"; break; case fmReadWrite: Mode = "rb+"; break; + case fmAppend: Mode = "a+"; break; } if (Mode == NULL) { @@ -255,10 +256,10 @@ int cFile::ReadRestOfFile(AString & a_Contents) return -1; } - int DataSize = GetSize() - Tell(); + size_t DataSize = GetSize() - Tell(); // HACK: This depends on the internal knowledge that AString's data() function returns the internal buffer directly - a_Contents.assign((size_t)DataSize, '\0'); + a_Contents.assign(DataSize, '\0'); return Read((void *)a_Contents.data(), DataSize); } @@ -459,7 +460,7 @@ int cFile::Printf(const char * a_Fmt, ...) va_start(args, a_Fmt); AppendVPrintf(buf, a_Fmt, args); va_end(args); - return Write(buf.c_str(), (int)buf.length()); + return Write(buf.c_str(), buf.length()); } diff --git a/src/OSSupport/File.h b/src/OSSupport/File.h index 2a7ecf0ed..dfb38e839 100644 --- a/src/OSSupport/File.h +++ b/src/OSSupport/File.h @@ -60,9 +60,10 @@ public: /** The mode in which to open the file */ enum eMode { - fmRead, // Read-only. If the file doesn't exist, object will not be valid - fmWrite, // Write-only. If the file already exists, it will be overwritten - fmReadWrite // Read/write. If the file already exists, it will be left intact; writing will overwrite the data from the beginning + fmRead, // Read-only. If the file doesn't exist, object will not be valid + fmWrite, // Write-only. If the file already exists, it will be overwritten + fmReadWrite, // Read/write. If the file already exists, it will be left intact; writing will overwrite the data from the beginning + fmAppend // Write-only. If the file already exists cursor will be moved to the end of the file } ; /** Simple constructor - creates an unopened file object, use Open() to open / create a real file */ diff --git a/src/Root.cpp b/src/Root.cpp index c20cf0d21..ee0d9b835 100644 --- a/src/Root.cpp +++ b/src/Root.cpp @@ -18,6 +18,7 @@ #include "CommandOutput.h" #include "DeadlockDetect.h" #include "OSSupport/Timer.h" +#include "LoggerListeners.h" #include "inifile/iniFile.h" @@ -51,7 +52,6 @@ cRoot::cRoot(void) : m_FurnaceRecipe(NULL), m_WebAdmin(NULL), m_PluginManager(NULL), - m_Log(NULL), m_bStop(false), m_bRestart(false) { @@ -105,10 +105,15 @@ void cRoot::Start(void) HMENU hmenu = GetSystemMenu(hwnd, FALSE); EnableMenuItem(hmenu, SC_CLOSE, MF_GRAYED); // Disable close button when starting up; it causes problems with our CTRL-CLOSE handling #endif + + cLogger::cListener * consoleLogListener = MakeConsoleListener(); + cLogger::cListener * fileLogListener = new cFileListener(); + cLogger::GetInstance().AttachListener(consoleLogListener); + cLogger::GetInstance().AttachListener(fileLogListener); + + LOG("--- Started Log ---\n"); cDeadlockDetect dd; - delete m_Log; - m_Log = new cMCLogger(); m_bStop = false; while (!m_bStop) @@ -249,8 +254,13 @@ void cRoot::Start(void) delete m_Server; m_Server = NULL; LOG("Shutdown successful!"); } - - delete m_Log; m_Log = NULL; + + LOG("--- Stopped Log ---"); + + cLogger::GetInstance().DetachListener(consoleLogListener); + delete consoleLogListener; + cLogger::GetInstance().DetachListener(fileLogListener); + delete fileLogListener; } @@ -274,15 +284,15 @@ void cRoot::LoadWorlds(cIniFile & IniFile) m_WorldsByName[ DefaultWorldName ] = m_pDefaultWorld; // Then load the other worlds - unsigned int KeyNum = IniFile.FindKey("Worlds"); - unsigned int NumWorlds = IniFile.GetNumValues(KeyNum); + int KeyNum = IniFile.FindKey("Worlds"); + int NumWorlds = IniFile.GetNumValues(KeyNum); if (NumWorlds <= 0) { return; } bool FoundAdditionalWorlds = false; - for (unsigned int i = 0; i < NumWorlds; i++) + for (int i = 0; i < NumWorlds; i++) { AString ValueName = IniFile.GetValueName(KeyNum, i); if (ValueName.compare("World") != 0) diff --git a/src/Root.h b/src/Root.h index 1cd175ab4..6840efcbe 100644 --- a/src/Root.h +++ b/src/Root.h @@ -196,8 +196,6 @@ private: cMojangAPI m_MojangAPI; cHTTPServer m_HTTPServer; - cMCLogger * m_Log; - bool m_bStop; bool m_bRestart; diff --git a/src/StringUtils.h b/src/StringUtils.h index 142aaf59b..3d4379352 100644 --- a/src/StringUtils.h +++ b/src/StringUtils.h @@ -12,7 +12,6 @@ - typedef std::string AString; typedef std::vector<AString> AStringVector; typedef std::list<AString> AStringList; diff --git a/src/main.cpp b/src/main.cpp index 106233342..86ecd4000 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -273,6 +273,8 @@ int main( int argc, char **argv) } } // for i - argv[] + cLogger::InitiateMultithreading(); + #if !defined(ANDROID_NDK) try #endif |