Fix a compiler warning
[amule.git] / src / Logger.cpp
blobe764b0d31b3ac53697687f31dddc20d274f6f646
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2005-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 //
6 // Any parts of this program derived from the xMule, lMule or eMule project,
7 // or contributed by third-party developers are copyrighted by their
8 // respective authors.
9 //
10 // This program is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "Logger.h"
26 #include "amule.h"
27 #include "Preferences.h"
28 #include <common/Macros.h>
29 #include <sstream>
30 #include <wx/tokenzr.h>
31 #include <wx/wfstream.h>
32 #include <wx/sstream.h>
33 #include <wx/filename.h>
36 DEFINE_LOCAL_EVENT_TYPE(MULE_EVT_LOGLINE)
39 CDebugCategory g_debugcats[] = {
40 CDebugCategory( logGeneral, wxT("General") ),
41 CDebugCategory( logHasher, wxT("Hasher") ),
42 CDebugCategory( logClient, wxT("ED2k Client") ),
43 CDebugCategory( logLocalClient, wxT("Local Client Protocol") ),
44 CDebugCategory( logRemoteClient, wxT("Remote Client Protocol") ),
45 CDebugCategory( logPacketErrors, wxT("Packet Parsing Errors") ),
46 CDebugCategory( logCFile, wxT("CFile") ),
47 CDebugCategory( logFileIO, wxT("FileIO") ),
48 CDebugCategory( logZLib, wxT("ZLib") ),
49 CDebugCategory( logAICHThread, wxT("AICH-Hasher") ),
50 CDebugCategory( logAICHTransfer, wxT("AICH-Transfer") ),
51 CDebugCategory( logAICHRecovery, wxT("AICH-Recovery") ),
52 CDebugCategory( logListenSocket, wxT("ListenSocket") ),
53 CDebugCategory( logCredits, wxT("Credits") ),
54 CDebugCategory( logClientUDP, wxT("ClientUDPSocket") ),
55 CDebugCategory( logDownloadQueue, wxT("DownloadQueue") ),
56 CDebugCategory( logIPFilter, wxT("IPFilter") ),
57 CDebugCategory( logKnownFiles, wxT("KnownFileList") ),
58 CDebugCategory( logPartFile, wxT("PartFiles") ),
59 CDebugCategory( logSHAHashSet, wxT("SHAHashSet") ),
60 CDebugCategory( logServer, wxT("Servers") ),
61 CDebugCategory( logProxy, wxT("Proxy") ),
62 CDebugCategory( logSearch, wxT("Searching") ),
63 CDebugCategory( logServerUDP, wxT("ServerUDP") ),
64 CDebugCategory( logClientKadUDP, wxT("Client Kademlia UDP") ),
65 CDebugCategory( logKadSearch, wxT("Kademlia Search") ),
66 CDebugCategory( logKadRouting, wxT("Kademlia Routing") ),
67 CDebugCategory( logKadIndex, wxT("Kademlia Indexing") ),
68 CDebugCategory( logKadMain, wxT("Kademlia Main Thread") ),
69 CDebugCategory( logKadPrefs, wxT("Kademlia Preferences") ),
70 CDebugCategory( logPfConvert, wxT("PartFileConvert") ),
71 CDebugCategory( logMuleUDP, wxT("MuleUDPSocket" ) ),
72 CDebugCategory( logThreads, wxT("ThreadScheduler" ) ),
73 CDebugCategory( logUPnP, wxT("Universal Plug and Play" ) ),
74 CDebugCategory( logKadUdpFwTester, wxT("Kademlia UDP Firewall Tester") ),
75 CDebugCategory( logKadPacketTracking, wxT("Kademlia Packet Tracking") ),
76 CDebugCategory( logKadEntryTracking, wxT("Kademlia Entry Tracking") ),
77 CDebugCategory( logEC, wxT("External Connect") ),
78 CDebugCategory( logHTTP, wxT("HTTP") )
82 const int categoryCount = sizeof( g_debugcats ) / sizeof( g_debugcats[0] );
86 #ifdef __DEBUG__
87 bool CLogger::IsEnabled( DebugType type ) const
89 int index = (int)type;
91 if ( index >= 0 && index < categoryCount ) {
92 const CDebugCategory& cat = g_debugcats[ index ];
93 wxASSERT( type == cat.GetType() );
95 return ( cat.IsEnabled() && thePrefs::GetVerbose() );
98 wxFAIL;
99 return false;
101 #endif
104 void CLogger::SetEnabled( DebugType type, bool enabled )
106 int index = (int)type;
108 if ( index >= 0 && index < categoryCount ) {
109 CDebugCategory& cat = g_debugcats[ index ];
110 wxASSERT( type == cat.GetType() );
112 cat.SetEnabled( enabled );
113 } else {
114 wxFAIL;
119 void CLogger::AddLogLine(
120 const wxString& DEBUG_ONLY(file),
121 int DEBUG_ONLY(line),
122 bool critical,
123 DebugType type,
124 const wxString &str,
125 bool toStdout,
126 bool toGUI)
128 wxString msg(str);
129 // handle Debug messages
130 if (type != logStandard) {
131 if (!critical && !IsEnabled(type)) {
132 return;
134 int index = (int)type;
136 if ( index >= 0 && index < categoryCount ) {
137 const CDebugCategory& cat = g_debugcats[ index ];
138 wxASSERT(type == cat.GetType());
140 msg = cat.GetName() + wxT(": ") + msg;
141 } else {
142 wxFAIL;
146 #ifdef __DEBUG__
147 if (line) {
148 msg = file.AfterLast(wxFileName::GetPathSeparator()).AfterLast(wxT('/')) << wxT("(") << line << wxT("): ") + msg;
150 #endif
152 CLoggingEvent Event(critical, toStdout, toGUI, msg);
154 // Try to handle events immediatly when possible (to save to file).
155 if (wxThread::IsMain()) {
156 // main thread and log file available: process directly
157 ProcessEvent(Event);
158 } else {
159 // otherwise put to background
160 AddPendingEvent(Event);
165 void CLogger::AddLogLine(
166 const wxString &file,
167 int line,
168 bool critical,
169 DebugType type,
170 const std::ostringstream &msg)
172 int index = (int)type;
174 if ( index >= 0 && index < categoryCount ) {
175 const CDebugCategory& cat = g_debugcats[ index ];
176 wxASSERT(type == cat.GetType());
178 AddLogLine(file, line, critical, logStandard,
179 cat.GetName() + wxT(": ") + char2unicode(msg.str().c_str()));
184 const CDebugCategory& CLogger::GetDebugCategory( int index )
186 wxASSERT( index >= 0 && index < categoryCount );
188 return g_debugcats[ index ];
192 unsigned int CLogger::GetDebugCategoryCount()
194 return categoryCount;
198 bool CLogger::OpenLogfile(const wxString & name)
200 applog = new wxFFileOutputStream(name);
201 bool ret = applog->Ok();
202 if (ret) {
203 FlushApplog();
204 m_LogfileName = name;
205 } else {
206 CloseLogfile();
208 return ret;
212 void CLogger::CloseLogfile()
214 delete applog;
215 applog = NULL;
216 m_LogfileName.Clear();
220 void CLogger::OnLoggingEvent(class CLoggingEvent& evt)
222 // Remove newspace at end
223 wxString bufferline = evt.Message().Strip(wxString::trailing);
225 // Create the timestamp
226 wxString stamp = wxDateTime::Now().FormatISODate() + wxT(" ") + wxDateTime::Now().FormatISOTime()
227 #ifdef CLIENT_GUI
228 + wxT(" (remote-GUI): ");
229 #else
230 + wxT(": ");
231 #endif
233 // critical lines get a ! prepended, ordinary lines a blank
234 // logfile-only lines get a . to prevent transmission on EC
235 wxString prefix = !evt.ToGUI() ? wxT(".") : (evt.IsCritical() ? wxT("!") : wxT(" "));
237 if ( bufferline.IsEmpty() ) {
238 // If it's empty we just write a blank line with no timestamp.
239 DoLine(wxT(" \n"), evt.ToStdout(), evt.ToGUI());
240 } else {
241 // Split multi-line messages into individual lines
242 wxStringTokenizer tokens( bufferline, wxT("\n") );
243 while ( tokens.HasMoreTokens() ) {
244 wxString fullline = prefix + stamp + tokens.GetNextToken() + wxT("\n");
245 DoLine(fullline, evt.ToStdout(), evt.ToGUI());
251 void CLogger::DoLine(const wxString & line, bool toStdout, bool GUI_ONLY(toGUI))
253 ++m_count;
255 // write to logfile
256 m_ApplogBuf += line;
257 FlushApplog();
259 // write to Stdout
260 if (m_StdoutLog || toStdout) {
261 printf("%s", (const char*)unicode2char(line));
263 #ifndef AMULE_DAEMON
264 // write to Listcontrol
265 if (toGUI) {
266 theApp->AddGuiLogLine(line);
268 #endif
272 void CLogger::FlushApplog()
274 if (applog) { // Wait with output until logfile is actually opened
275 wxStringInputStream stream(m_ApplogBuf);
276 (*applog) << stream;
277 applog->Sync();
278 m_ApplogBuf.Clear();
282 CLogger theLogger;
284 BEGIN_EVENT_TABLE(CLogger, wxEvtHandler)
285 EVT_MULE_LOGGING(CLogger::OnLoggingEvent)
286 END_EVENT_TABLE()
289 CLoggerTarget::CLoggerTarget()
293 #if wxCHECK_VERSION(2, 9, 0)
294 void CLoggerTarget::DoLogText(const wxString &msg)
296 // prevent infinite recursion
297 static bool recursion = false;
298 if (recursion) {
299 return;
301 recursion = true;
303 // This is much simpler than manually handling all wx log-types.
304 bool critical = msg.StartsWith(_("ERROR: ")) || msg.StartsWith(_("WARNING: "));
306 AddLogLineM(critical, msg);
308 recursion = false;
310 #else
311 void CLoggerTarget::DoLogString(const wxChar* msg, time_t)
313 // prevent infinite recursion
314 static bool recursion = false;
315 if (recursion) {
316 return;
318 recursion = true;
320 wxCHECK_RET(msg, wxT("Log message is NULL in DoLogString!"));
322 wxString str(msg);
324 // This is much simpler than manually handling all wx log-types.
325 bool critical = str.StartsWith(_("ERROR: ")) || str.StartsWith(_("WARNING: "));
327 AddLogLineM(critical, str);
329 recursion = false;
331 #endif
333 CLoggerAccess::CLoggerAccess()
335 m_bufferlen = 4096;
336 m_buffer = new wxCharBuffer(m_bufferlen);
337 m_logfile = new wxFFileInputStream(theLogger.GetLogfileName());
338 m_pos = 0;
339 m_ready = false;
343 CLoggerAccess::~CLoggerAccess()
345 delete m_buffer;
346 delete m_logfile;
351 // read a line of text from the logfile if available
352 // (can't believe there's no library function for this >:( )
354 bool CLoggerAccess::HasString()
356 while (!m_ready) {
357 int c = m_logfile->GetC();
358 if (c == wxEOF) {
359 break;
361 // check for buffer overrun
362 if (m_pos == m_bufferlen) {
363 m_bufferlen += 1024;
364 m_buffer->extend(m_bufferlen);
366 m_buffer->data()[m_pos++] = c;
367 if (c == '\n') {
368 if (m_buffer->data()[0] == '.') {
369 // Log-only line, skip
370 m_pos = 0;
371 } else {
372 m_ready = true;
376 return m_ready;
380 bool CLoggerAccess::GetString(wxString & s)
382 if (!HasString()) {
383 return false;
385 s = wxString(m_buffer->data(), wxConvUTF8, m_pos);
386 m_pos = 0;
387 m_ready = false;
388 return true;
391 // Functions for EC logging
392 bool ECLogIsEnabled()
394 return theLogger.IsEnabled(logEC);
397 void DoECLogLine(const wxString &line)
399 // without file/line
400 theLogger.AddLogLine(wxEmptyString, 0, false, logStandard, line, false, false);
403 // File_checked_for_headers