00001 #ifndef LOG_H
00002 #define LOG_H
00003 #include <stdio.h>
00004 #include <stdlib.h>
00005 #include <vector>
00006 #include <string>
00007 #include <string.h>
00008 #include <map>
00009 #include "engine/mutex.h"
00010 #include "engine/thread_obj.h"
00011 #include "net/client_no_log.h"
00012
00013 enum LogLevel
00014 {
00015 LogPanic,
00016 LogDebug,
00017 LogNone,
00018 LogError,
00019 LogWarning,
00020 LogInfo,
00021 LogLast,
00022 };
00023
00024 class LineLogger : private Mutex
00025 {
00026 protected:
00027 virtual void WriteToLog(const char* msg) = 0;
00028 public:
00029 LineLogger() {}
00030 virtual ~LineLogger() {}
00031
00032 void Write(enum LogLevel log_level, const char* debug_info, const char* msg);
00033 };
00034
00035 class StdoutLogger : public LineLogger
00036 {
00037 protected:
00038 void WriteToLog(const char* msg);
00039 };
00040
00041 class StderrLogger : public LineLogger
00042 {
00043 protected:
00044 void WriteToLog(const char* msg);
00045 };
00046
00047 class FileLogger : public LineLogger
00048 {
00049 FILE* f;
00050 protected:
00051 void WriteToLog(const char* msg);
00052 public:
00053 ~FileLogger();
00054 FileLogger(std::string filename);
00055 };
00056
00057 class NetLogger : public LineLogger, private ClientNoLog
00058 {
00059 std::string buf;
00060 bool host_is_valid;
00061
00062 protected:
00063 void WriteToLog(const char* msg);
00064 public:
00065 ~NetLogger();
00066 NetLogger(std::string hostport);
00067 };
00068
00069 class Log : private Mutex
00070 {
00071 std::vector<LineLogger*> loggers;
00072 std::map<std::string, LineLogger*> inited_loggers;
00073 bool inited;
00074 void LoadLogObj(std::string logger_name, enum LogLevel logger_no);
00075 void Init();
00076 public:
00077 Log();
00078 ~Log();
00079
00080 void Reload();
00081 LineLogger* GetLogger(enum LogLevel log_lvl);
00082 };
00083
00084 #define LOG_FILENAME_LENGTH 16
00085 #define LOG_LINE_LENGTH 5
00086 #define LOG_THREAD_LENGTH 16
00087 #define LOG_DEBUG_LENGTH (LOG_FILENAME_LENGTH + LOG_LINE_LENGTH + LOG_THREAD_LENGTH + 2)
00088 #define LOG_MSG_LENGTH 1024
00089
00090 #define __MYFILE__ ((strrchr(__FILE__, '/') ? : __FILE__- 1) + 1)
00091
00092 #define log(__libldsw_dbg_lev,__libldsw_arg...) \
00093 do \
00094 { \
00095 if(__libldsw_dbg_lev == LogNone) break; \
00096 LineLogger* __libldsw_logger = __libldsw_thread_log.GetLogger(__libldsw_dbg_lev); \
00097 if(!__libldsw_logger) { \
00098 fprintf(stderr, ##__libldsw_arg); \
00099 fprintf(stderr, "\n"); \
00100 } \
00101 \
00102 if(__libldsw_dbg_lev == LogPanic && !__libldsw_logger) \
00103 exit(EXIT_FAILURE); \
00104 \
00105 if(!__libldsw_logger) break; \
00106 \
00107 ThreadObj* __libldsw_th = GetCurrentThread(); \
00108 char __libldsw_debug_line[LOG_DEBUG_LENGTH + 1]; \
00109 memset(__libldsw_debug_line, ' ', LOG_DEBUG_LENGTH + 1); \
00110 __libldsw_debug_line[LOG_DEBUG_LENGTH] = '\0'; \
00111 \
00112 memcpy(__libldsw_debug_line, __MYFILE__, strlen(__MYFILE__) > LOG_FILENAME_LENGTH ? LOG_FILENAME_LENGTH : strlen(__MYFILE__)); \
00113 \
00114 char __libldsw_line[LOG_LINE_LENGTH + 1]; \
00115 snprintf(__libldsw_line, LOG_LINE_LENGTH, "%i", __LINE__); \
00116 memcpy(__libldsw_debug_line + LOG_FILENAME_LENGTH + 1, __libldsw_line, strlen(__libldsw_line)); \
00117 \
00118 if(__libldsw_th) \
00119 memcpy(__libldsw_debug_line + LOG_FILENAME_LENGTH + LOG_LINE_LENGTH + 1, __libldsw_th->name.c_str(), __libldsw_th->name.size() > LOG_THREAD_LENGTH ? LOG_THREAD_LENGTH : __libldsw_th->name.size()); \
00120 else \
00121 memcpy(__libldsw_debug_line + LOG_FILENAME_LENGTH + LOG_LINE_LENGTH + 1, "main", 4); \
00122 \
00123 char __libldsw_msg[LOG_MSG_LENGTH + 1]; \
00124 memset(__libldsw_msg, 0, LOG_MSG_LENGTH + 1); \
00125 snprintf(__libldsw_msg, LOG_MSG_LENGTH, ##__libldsw_arg); \
00126 \
00127 __libldsw_logger->Write(__libldsw_dbg_lev, __libldsw_debug_line, __libldsw_msg); \
00128 if(__libldsw_dbg_lev == LogPanic) exit(EXIT_FAILURE); \
00129 \
00130 } while(0)
00131
00132 extern Log __libldsw_thread_log;
00133 #endif