2 // This file is part of the aMule Project.
4 // Copyright (c) 2005-2008 aMule Team ( admin@amule.org / http://www.amule.org )
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
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.
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
27 #include "Preferences.h"
29 #include <wx/tokenzr.h>
30 #include <wx/wfstream.h>
31 #include <wx/sstream.h>
32 #include <wx/filename.h>
35 DEFINE_LOCAL_EVENT_TYPE(MULE_EVT_LOGLINE
)
38 CDebugCategory::CDebugCategory( DebugType type
, const wxString
& name
)
46 bool CDebugCategory::IsEnabled() const
52 void CDebugCategory::SetEnabled( bool enabled
)
58 const wxString
& CDebugCategory::GetName() const
64 DebugType
CDebugCategory::GetType() const
69 CDebugCategory g_debugcats
[] = {
70 CDebugCategory( logGeneral
, wxT("General") ),
71 CDebugCategory( logHasher
, wxT("Hasher") ),
72 CDebugCategory( logClient
, wxT("ED2k Client") ),
73 CDebugCategory( logLocalClient
, wxT("Local Client Protocol") ),
74 CDebugCategory( logRemoteClient
, wxT("Remote Client Protocol") ),
75 CDebugCategory( logPacketErrors
, wxT("Packet Parsing Errors") ),
76 CDebugCategory( logCFile
, wxT("CFile") ),
77 CDebugCategory( logFileIO
, wxT("FileIO") ),
78 CDebugCategory( logZLib
, wxT("ZLib") ),
79 CDebugCategory( logAICHThread
, wxT("AICH-Hasher") ),
80 CDebugCategory( logAICHTransfer
, wxT("AICH-Transfer") ),
81 CDebugCategory( logAICHRecovery
, wxT("AICH-Recovery") ),
82 CDebugCategory( logListenSocket
, wxT("ListenSocket") ),
83 CDebugCategory( logCredits
, wxT("Credits") ),
84 CDebugCategory( logClientUDP
, wxT("ClientUDPSocket") ),
85 CDebugCategory( logDownloadQueue
, wxT("DownloadQueue") ),
86 CDebugCategory( logIPFilter
, wxT("IPFilter") ),
87 CDebugCategory( logKnownFiles
, wxT("KnownFileList") ),
88 CDebugCategory( logPartFile
, wxT("PartFiles") ),
89 CDebugCategory( logSHAHashSet
, wxT("SHAHashSet") ),
90 CDebugCategory( logServer
, wxT("Servers") ),
91 CDebugCategory( logProxy
, wxT("Proxy") ),
92 CDebugCategory( logSearch
, wxT("Searching") ),
93 CDebugCategory( logServerUDP
, wxT("ServerUDP") ),
94 CDebugCategory( logClientKadUDP
, wxT("Client Kademlia UDP") ),
95 CDebugCategory( logKadSearch
, wxT("Kademlia Search") ),
96 CDebugCategory( logKadRouting
, wxT("Kademlia Routing") ),
97 CDebugCategory( logKadIndex
, wxT("Kademlia Indexing") ),
98 CDebugCategory( logKadMain
, wxT("Kademlia Main Thread") ),
99 CDebugCategory( logKadPrefs
, wxT("Kademlia Preferences") ),
100 CDebugCategory( logPfConvert
, wxT("PartFileConvert") ),
101 CDebugCategory( logMuleUDP
, wxT("MuleUDPSocket" ) ),
102 CDebugCategory( logThreads
, wxT("ThreadScheduler" ) ),
103 CDebugCategory( logUPnP
, wxT("Universal Plug and Play" ) ),
104 CDebugCategory( logKadUdpFwTester
, wxT("Kademlia UDP Firewall Tester") ),
105 CDebugCategory( logKadPacketTracking
, wxT("Kademlia Packet Tracking") ),
106 CDebugCategory( logKadEntryTracking
, wxT("Kademlia Entry Tracking") )
110 const int categoryCount
= sizeof( g_debugcats
) / sizeof( g_debugcats
[0] );
114 bool CLogger::IsEnabled( DebugType type
)
117 int index
= (int)type
;
119 if ( index
>= 0 && index
< categoryCount
) {
120 const CDebugCategory
& cat
= g_debugcats
[ index
];
121 wxASSERT( type
== cat
.GetType() );
123 return ( cat
.IsEnabled() && thePrefs::GetVerbose() );
132 void CLogger::SetEnabled( DebugType type
, bool enabled
)
134 int index
= (int)type
;
136 if ( index
>= 0 && index
< categoryCount
) {
137 CDebugCategory
& cat
= g_debugcats
[ index
];
138 wxASSERT( type
== cat
.GetType() );
140 cat
.SetEnabled( enabled
);
147 bool CLogger::IsEnabledStdoutLog()
153 void CLogger::SetEnabledStdoutLog(bool enabled
)
155 m_StdoutLog
= enabled
;
159 void CLogger::AddLogLine(
160 const wxString
&file
,
168 // handle Debug messages
169 if (type
!= logStandard
) {
170 if (!critical
&& !IsEnabled(type
)) {
173 int index
= (int)type
;
175 if ( index
>= 0 && index
< categoryCount
) {
176 const CDebugCategory
& cat
= g_debugcats
[ index
];
177 wxASSERT(type
== cat
.GetType());
179 msg
= cat
.GetName() + wxT(": ") + msg
;
186 msg
= file
.AfterLast(wxFileName::GetPathSeparator()).AfterLast(wxT('/')) << wxT("(") << line
<< wxT("): ") + msg
;
189 CLoggingEvent
Event(critical
, toStdout
, msg
);
191 // Try to handle events immediatly when possible (to save to file).
192 if (wxThread::IsMain()) {
193 // main thread and log file available: process directly
196 // otherwise put to background
197 AddPendingEvent(Event
);
202 void CLogger::AddLogLine(
203 const wxString
&file
,
207 const std::ostringstream
&msg
)
209 int index
= (int)type
;
211 if ( index
>= 0 && index
< categoryCount
) {
212 const CDebugCategory
& cat
= g_debugcats
[ index
];
213 wxASSERT(type
== cat
.GetType());
215 AddLogLine(file
, line
, critical
, logStandard
, cat
.GetName() + wxT(": ") + char2unicode(msg
.str().c_str()));
220 const CDebugCategory
& CLogger::GetDebugCategory( int index
)
222 wxASSERT( index
>= 0 && index
< categoryCount
);
224 return g_debugcats
[ index
];
228 unsigned int CLogger::GetDebugCategoryCount()
230 return categoryCount
;
234 bool CLogger::OpenLogfile(const wxString
& name
)
236 applog
= new wxFFileOutputStream(name
);
237 bool ret
= applog
->Ok();
240 m_LogfileName
= name
;
248 void CLogger::CloseLogfile()
252 m_LogfileName
= wxT("");
256 void CLogger::OnLoggingEvent(class CLoggingEvent
& evt
)
258 // Remove newspace at end
259 wxString bufferline
= evt
.Message().Strip(wxString::trailing
);
261 // Create the timestamp
262 wxString stamp
= wxDateTime::Now().FormatISODate() + wxT(" ") + wxDateTime::Now().FormatISOTime()
264 + wxT(" (remote-GUI): ");
269 // critical lines get a ! prepended, others a blank
270 wxString prefix
= evt
.IsCritical() ? wxT("!") : wxT(" ");
272 if ( bufferline
.IsEmpty() ) {
273 // If it's empty we just write a blank line with no timestamp.
274 DoLine(wxT(" \n"), evt
.ToStdout());
276 // Split multi-line messages into individual lines
277 wxStringTokenizer
tokens( bufferline
, wxT("\n") );
278 while ( tokens
.HasMoreTokens() ) {
279 wxString fullline
= prefix
+ stamp
+ tokens
.GetNextToken() + wxT("\n");
280 DoLine(fullline
, evt
.ToStdout());
286 void CLogger::DoLine(const wxString
& line
, bool toStdout
)
295 if (m_StdoutLog
|| toStdout
) {
296 printf("%s", (const char*)unicode2char(line
));
299 // write to Listcontrol
300 theApp
->AddGuiLogLine(line
);
305 void CLogger::FlushApplog()
307 if (applog
) { // Wait with output until logfile is actually opened
308 wxStringInputStream
stream(m_ApplogBuf
);
311 m_ApplogBuf
= wxEmptyString
;
317 BEGIN_EVENT_TABLE(CLogger
, wxEvtHandler
)
318 EVT_MULE_LOGGING(CLogger::OnLoggingEvent
)
322 CLoggerTarget::CLoggerTarget()
327 void CLoggerTarget::DoLogString(const wxChar
* msg
, time_t)
329 // prevent infinite recursion
330 static bool recursion
= false;
336 wxCHECK_RET(msg
, wxT("Log message is NULL in DoLogString!"));
340 // This is much simpler than manually handling all wx log-types.
341 bool critical
= str
.StartsWith(_("ERROR: ")) || str
.StartsWith(_("WARNING: "));
343 AddLogLineM(critical
, str
);
349 CLoggerAccess::CLoggerAccess()
352 m_buffer
= new wxCharBuffer(m_bufferlen
);
353 m_logfile
= new wxFFileInputStream(theLogger
.GetLogfileName());
359 CLoggerAccess::~CLoggerAccess()
367 // read a line of text from the logfile if available
368 // (can't believe there's no library function for this >:( )
370 bool CLoggerAccess::HasString()
373 int c
= m_logfile
->GetC();
377 // check for buffer overrun
378 if (m_pos
== m_bufferlen
) {
380 m_buffer
->extend(m_bufferlen
);
382 m_buffer
->data()[m_pos
++] = c
;
391 bool CLoggerAccess::GetString(wxString
& s
)
396 s
= wxString(m_buffer
->data(), wxConvUTF8
, m_pos
);
402 // File_checked_for_headers