2014-05-30 08:53:19 +00:00
/*
This file is part of Telegram Desktop ,
2014-12-01 10:47:38 +00:00
the official desktop version of Telegram messaging app , see https : //telegram.org
2014-05-30 08:53:19 +00:00
Telegram Desktop is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
It is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
Full license : https : //github.com/telegramdesktop/tdesktop/blob/master/LICENSE
2014-12-01 10:47:38 +00:00
Copyright ( c ) 2014 John Preston , https : //desktop.telegram.org
2014-05-30 08:53:19 +00:00
*/
# include "stdafx.h"
2014-07-08 10:24:21 +00:00
# include <iostream>
2014-05-30 08:53:19 +00:00
# include "pspecific.h"
namespace {
QFile debugLog , tcpLog , mtpLog , mainLog ;
QTextStream * debugLogStream = 0 , * tcpLogStream = 0 , * mtpLogStream = 0 , * mainLogStream = 0 ;
2014-09-30 14:11:09 +00:00
int32 part = - 1 ;
2014-05-30 08:53:19 +00:00
QChar zero ( ' 0 ' ) ;
QMutex debugLogMutex , mainLogMutex ;
class _StreamCreator {
public :
~ _StreamCreator ( ) {
logsClose ( ) ;
}
} ;
QString debugLogEntryStart ( ) {
static uint32 logEntry = 0 ;
QDateTime tm ( QDateTime : : currentDateTime ( ) ) ;
QThread * thread = QThread : : currentThread ( ) ;
MTPThread * mtpThread = dynamic_cast < MTPThread * > ( thread ) ;
uint32 threadId = mtpThread ? mtpThread - > getThreadId ( ) : 0 ;
return QString ( " [%1 %2-%3] " ) . arg ( tm . toString ( " hh:mm:ss.zzz " ) ) . arg ( QString ( " %1 " ) . arg ( threadId , 2 , 10 , zero ) ) . arg ( + + logEntry , 7 , 10 , zero ) ;
}
}
void debugLogWrite ( const char * file , int32 line , const QString & v ) {
if ( ! cDebug ( ) | | ! debugLogStream ) return ;
const char * last = strstr ( file , " / " ) , * found = 0 ;
while ( last ) {
found = last ;
last = strstr ( last + 1 , " / " ) ;
}
last = strstr ( file , " \\ " ) ;
while ( last ) {
found = last ;
last = strstr ( last + 1 , " \\ " ) ;
}
if ( found ) {
file = found + 1 ;
}
{
QMutexLocker lock ( & debugLogMutex ) ;
2014-09-30 14:11:09 +00:00
logsInitDebug ( ) ; // maybe need to reopen new file
2014-05-30 08:53:19 +00:00
QString msg ( QString ( " %1 %2 (%3 : %4) \ n " ).arg(debugLogEntryStart()).arg(v).arg(file).arg(line)) ;
( * debugLogStream ) < < msg ;
debugLogStream - > flush ( ) ;
# ifdef Q_OS_WIN
2014-11-23 11:20:40 +00:00
// OutputDebugString(reinterpret_cast<const wchar_t *>(msg.utf16()));
2014-06-25 07:25:55 +00:00
# elif defined Q_OS_MAC
objc_outputDebugString ( msg ) ;
2014-07-08 10:24:21 +00:00
# elif defined Q_OS_LINUX && defined _DEBUG
2015-01-15 14:22:15 +00:00
// std::cout << msg.toUtf8().constData();
2014-05-30 08:53:19 +00:00
# endif
}
}
void tcpLogWrite ( const QString & v ) {
if ( ! cDebug ( ) | | ! tcpLogStream ) return ;
{
QMutexLocker lock ( & debugLogMutex ) ;
2014-09-30 14:11:09 +00:00
logsInitDebug ( ) ; // maybe need to reopen new file
2014-05-30 08:53:19 +00:00
( * tcpLogStream ) < < QString ( " %1 %2 \n " ) . arg ( debugLogEntryStart ( ) ) . arg ( v ) ;
tcpLogStream - > flush ( ) ;
}
}
void mtpLogWrite ( int32 dc , const QString & v ) {
if ( ! cDebug ( ) | | ! mtpLogStream ) return ;
{
QMutexLocker lock ( & debugLogMutex ) ;
2014-09-30 14:11:09 +00:00
logsInitDebug ( ) ; // maybe need to reopen new file
2014-05-30 08:53:19 +00:00
( * mtpLogStream ) < < QString ( " %1 (dc:%2) %3 \n " ) . arg ( debugLogEntryStart ( ) ) . arg ( dc ) . arg ( v ) ;
mtpLogStream - > flush ( ) ;
}
}
void logWrite ( const QString & v ) {
if ( ! mainLog . isOpen ( ) ) return ;
time_t t = time ( NULL ) ;
struct tm tm ;
mylocaltime ( & tm , & t ) ;
{
QMutexLocker lock ( & mainLogMutex ) ;
QString msg ( QString ( " [%1.%2.%3 %4:%5:%6] %7 \n " ) . arg ( tm . tm_year + 1900 ) . arg ( tm . tm_mon + 1 , 2 , 10 , zero ) . arg ( tm . tm_mday , 2 , 10 , zero ) . arg ( tm . tm_hour , 2 , 10 , zero ) . arg ( tm . tm_min , 2 , 10 , zero ) . arg ( tm . tm_sec , 2 , 10 , zero ) . arg ( v ) ) ;
( * mainLogStream ) < < msg ;
mainLogStream - > flush ( ) ;
}
if ( cDebug ( ) ) debugLogWrite ( " logs " , 0 , v ) ;
}
2014-09-30 14:11:09 +00:00
void moveOldDataFiles ( const QString & wasDir ) {
QFile data ( wasDir + " data " ) , dataConfig ( wasDir + " data_config " ) , tdataConfig ( wasDir + " tdata/config " ) ;
if ( data . exists ( ) & & dataConfig . exists ( ) & & ! QFileInfo ( cWorkingDir ( ) + " data " ) . exists ( ) & & ! QFileInfo ( cWorkingDir ( ) + " data_config " ) . exists ( ) ) { // move to home dir
LOG ( ( " Copying data to home dir '%1' from '%2' " ) . arg ( cWorkingDir ( ) ) . arg ( wasDir ) ) ;
if ( data . copy ( cWorkingDir ( ) + " data " ) ) {
LOG ( ( " Copied 'data' to home dir " ) ) ;
if ( dataConfig . copy ( cWorkingDir ( ) + " data_config " ) ) {
LOG ( ( " Copied 'data_config' to home dir " ) ) ;
bool tdataGood = true ;
if ( tdataConfig . exists ( ) ) {
tdataGood = false ;
QDir ( ) . mkpath ( cWorkingDir ( ) + " tdata " ) ;
if ( tdataConfig . copy ( cWorkingDir ( ) + " tdata/config " ) ) {
LOG ( ( " Copied 'tdata/config' to home dir " ) ) ;
tdataGood = true ;
} else {
LOG ( ( " Copied 'data' and 'data_config', but could not copy 'tdata/config'! " ) ) ;
}
}
if ( tdataGood ) {
if ( data . remove ( ) ) {
LOG ( ( " Removed 'data' " ) ) ;
} else {
LOG ( ( " Could not remove 'data' " ) ) ;
}
if ( dataConfig . remove ( ) ) {
LOG ( ( " Removed 'data_config' " ) ) ;
} else {
LOG ( ( " Could not remove 'data_config' " ) ) ;
}
if ( ! tdataConfig . exists ( ) | | tdataConfig . remove ( ) ) {
LOG ( ( " Removed 'tdata/config' " ) ) ;
LOG ( ( " Could not remove 'tdata/config' " ) ) ;
} else {
}
QDir ( ) . rmdir ( wasDir + " tdata " ) ;
}
} else {
LOG ( ( " Copied 'data', but could not copy 'data_config'!! " ) ) ;
}
} else {
LOG ( ( " Could not copy 'data'! " ) ) ;
}
}
}
2014-05-30 08:53:19 +00:00
void logsInit ( ) {
static _StreamCreator streamCreator ;
if ( mainLogStream ) return ;
2014-07-24 16:00:35 +00:00
QString wasDir = cWorkingDir ( ) ;
2014-07-26 09:57:07 +00:00
# if (defined Q_OS_MAC || defined Q_OS_LINUX)
# ifdef _DEBUG
cForceWorkingDir ( cExeDir ( ) ) ;
# else
2014-07-24 16:00:35 +00:00
cForceWorkingDir ( psAppDataPath ( ) ) ;
2014-07-26 09:57:07 +00:00
# endif
# if (defined Q_OS_LINUX && !defined _DEBUG) // fix first version
2014-09-30 14:11:09 +00:00
moveOldDataFiles ( wasDir ) ;
2014-07-24 16:00:35 +00:00
# endif
2014-06-14 19:32:11 +00:00
# endif
2014-05-30 08:53:19 +00:00
2014-07-24 16:00:35 +00:00
QString rightDir = cWorkingDir ( ) ;
cForceWorkingDir ( rightDir ) ;
2014-05-30 08:53:19 +00:00
mainLog . setFileName ( cWorkingDir ( ) + " log.txt " ) ;
mainLog . open ( QIODevice : : WriteOnly | QIODevice : : Text ) ;
if ( ! mainLog . isOpen ( ) ) {
cForceWorkingDir ( cExeDir ( ) ) ;
mainLog . setFileName ( cWorkingDir ( ) + " log.txt " ) ;
mainLog . open ( QIODevice : : WriteOnly | QIODevice : : Text ) ;
if ( ! mainLog . isOpen ( ) ) {
cForceWorkingDir ( psAppDataPath ( ) ) ;
mainLog . setFileName ( cWorkingDir ( ) + " log.txt " ) ;
mainLog . open ( QIODevice : : WriteOnly | QIODevice : : Text ) ;
}
}
if ( mainLog . isOpen ( ) ) {
mainLogStream = new QTextStream ( ) ;
mainLogStream - > setDevice ( & mainLog ) ;
mainLogStream - > setCodec ( " UTF-8 " ) ;
} else {
2014-07-24 16:00:35 +00:00
cForceWorkingDir ( rightDir ) ;
2014-05-30 08:53:19 +00:00
}
cForceWorkingDir ( QDir ( cWorkingDir ( ) ) . absolutePath ( ) + ' / ' ) ;
2014-12-03 13:10:32 +00:00
2015-01-23 15:24:36 +00:00
if ( QFile ( cWorkingDir ( ) + qsl ( " tdata/withtestmode " ) ) . exists ( ) ) {
cSetTestMode ( true ) ;
LOG ( ( " Switched to test mode! " ) ) ;
}
2014-09-30 14:11:09 +00:00
# ifdef Q_OS_WIN
if ( cWorkingDir ( ) = = psAppDataPath ( ) ) { // fix old "Telegram Win (Unofficial)" version
moveOldDataFiles ( psAppDataPathOld ( ) ) ;
}
# endif
if ( cDebug ( ) ) {
logsInitDebug ( ) ;
} else if ( QFile ( cWorkingDir ( ) + qsl ( " tdata/withdebug " ) ) . exists ( ) ) {
logsInitDebug ( ) ;
cSetDebug ( true ) ;
}
2014-05-30 08:53:19 +00:00
}
void logsInitDebug ( ) {
time_t t = time ( NULL ) ;
struct tm tm ;
2014-09-30 14:11:09 +00:00
mylocaltime ( & tm , & t ) ;
2014-05-30 08:53:19 +00:00
2014-09-30 14:11:09 +00:00
static const int switchEach = 15 ; // minutes
int32 newPart = ( tm . tm_min + tm . tm_hour * 60 ) / switchEach ;
if ( newPart = = part ) return ;
2014-05-30 08:53:19 +00:00
2014-09-30 14:11:09 +00:00
part = newPart ;
int32 dayIndex = ( tm . tm_year + 1900 ) * 10000 + ( tm . tm_mon + 1 ) * 100 + tm . tm_mday ;
QString logPostfix = QString ( " _%4_%5 " ) . arg ( ( part * switchEach ) / 60 , 2 , 10 , zero ) . arg ( ( part * switchEach ) % 60 , 2 , 10 , zero ) ;
if ( debugLogStream ) {
delete debugLogStream ;
debugLogStream = 0 ;
debugLog . close ( ) ;
}
debugLog . setFileName ( cWorkingDir ( ) + qsl ( " DebugLogs/log " ) + logPostfix + qsl ( " .txt " ) ) ;
QIODevice : : OpenMode debugLogMode = QIODevice : : WriteOnly | QIODevice : : Text ;
if ( debugLog . exists ( ) ) {
if ( debugLog . open ( QIODevice : : ReadOnly | QIODevice : : Text ) ) {
if ( QString : : fromUtf8 ( debugLog . readLine ( ) ) . toInt ( ) = = dayIndex ) {
debugLogMode | = QIODevice : : Append ;
}
debugLog . close ( ) ;
}
}
if ( ! debugLog . open ( debugLogMode ) ) {
2014-05-30 08:53:19 +00:00
QDir dir ( QDir : : current ( ) ) ;
2014-09-30 14:11:09 +00:00
dir . mkdir ( cWorkingDir ( ) + qsl ( " DebugLogs " ) ) ;
debugLog . open ( debugLogMode ) ;
2014-05-30 08:53:19 +00:00
}
if ( debugLog . isOpen ( ) ) {
debugLogStream = new QTextStream ( ) ;
debugLogStream - > setDevice ( & debugLog ) ;
debugLogStream - > setCodec ( " UTF-8 " ) ;
2014-09-30 14:11:09 +00:00
( * debugLogStream ) < < ( ( debugLogMode & QIODevice : : Append ) ? qsl ( " ---------------------------------------------------------------- \n NEW LOGGING INSTANCE STARTED!!! \n ---------------------------------------------------------------- \n " ) : qsl ( " %1 \n " ) . arg ( dayIndex ) ) ;
debugLogStream - > flush ( ) ;
2014-05-30 08:53:19 +00:00
}
2014-09-30 14:11:09 +00:00
if ( tcpLogStream ) {
delete tcpLogStream ;
tcpLogStream = 0 ;
tcpLog . close ( ) ;
}
tcpLog . setFileName ( cWorkingDir ( ) + qsl ( " DebugLogs/tcp " ) + logPostfix + qsl ( " .txt " ) ) ;
QIODevice : : OpenMode tcpLogMode = QIODevice : : WriteOnly | QIODevice : : Text ;
if ( tcpLog . exists ( ) ) {
if ( tcpLog . open ( QIODevice : : ReadOnly | QIODevice : : Text ) ) {
if ( QString : : fromUtf8 ( tcpLog . readLine ( ) ) . toInt ( ) = = dayIndex ) {
tcpLogMode | = QIODevice : : Append ;
}
tcpLog . close ( ) ;
}
}
if ( tcpLog . open ( tcpLogMode ) ) {
2014-05-30 08:53:19 +00:00
tcpLogStream = new QTextStream ( ) ;
tcpLogStream - > setDevice ( & tcpLog ) ;
tcpLogStream - > setCodec ( " UTF-8 " ) ;
2014-09-30 14:11:09 +00:00
( * tcpLogStream ) < < ( ( tcpLogMode & QIODevice : : Append ) ? qsl ( " ---------------------------------------------------------------- \n NEW LOGGING INSTANCE STARTED!!! \n ---------------------------------------------------------------- \n " ) : qsl ( " %1 \n " ) . arg ( dayIndex ) ) ;
tcpLogStream - > flush ( ) ;
}
if ( mtpLogStream ) {
delete mtpLogStream ;
mtpLogStream = 0 ;
mtpLog . close ( ) ;
2014-05-30 08:53:19 +00:00
}
2014-09-30 14:11:09 +00:00
mtpLog . setFileName ( cWorkingDir ( ) + qsl ( " DebugLogs/mtp " ) + logPostfix + qsl ( " .txt " ) ) ;
QIODevice : : OpenMode mtpLogMode = QIODevice : : WriteOnly | QIODevice : : Text ;
if ( mtpLog . exists ( ) ) {
if ( mtpLog . open ( QIODevice : : ReadOnly | QIODevice : : Text ) ) {
if ( QString : : fromUtf8 ( mtpLog . readLine ( ) ) . toInt ( ) = = dayIndex ) {
mtpLogMode | = QIODevice : : Append ;
}
mtpLog . close ( ) ;
}
}
if ( mtpLog . open ( mtpLogMode ) ) {
2014-05-30 08:53:19 +00:00
mtpLogStream = new QTextStream ( ) ;
mtpLogStream - > setDevice ( & mtpLog ) ;
mtpLogStream - > setCodec ( " UTF-8 " ) ;
2014-09-30 14:11:09 +00:00
( * mtpLogStream ) < < ( ( mtpLogMode & QIODevice : : Append ) ? qsl ( " ---------------------------------------------------------------- \n NEW LOGGING INSTANCE STARTED!!! \n ---------------------------------------------------------------- \n " ) : qsl ( " %1 \n " ) . arg ( dayIndex ) ) ;
mtpLogStream - > flush ( ) ;
2014-05-30 08:53:19 +00:00
}
}
void logsClose ( ) {
if ( cDebug ( ) ) {
if ( debugLogStream ) {
delete debugLogStream ;
debugLogStream = 0 ;
debugLog . close ( ) ;
}
if ( tcpLogStream ) {
delete tcpLogStream ;
tcpLogStream = 0 ;
tcpLog . close ( ) ;
}
if ( mtpLogStream ) {
delete mtpLogStream ;
mtpLogStream = 0 ;
mtpLog . close ( ) ;
}
}
if ( mainLogStream ) {
delete mainLogStream ;
mainLogStream = 0 ;
mainLog . close ( ) ;
}
}
QString logVectorLong ( const QVector < MTPlong > & ids ) {
if ( ! ids . size ( ) ) return " [void list] " ;
QString idsStr = QString ( " [%1 " ) . arg ( ids . cbegin ( ) - > v ) ;
for ( QVector < MTPlong > : : const_iterator i = ids . cbegin ( ) + 1 , e = ids . cend ( ) ; i ! = e ; + + i ) {
idsStr + = QString ( " , %2 " ) . arg ( i - > v ) ;
}
return idsStr + " ] " ;
}
2014-11-05 17:43:32 +00:00
QString logVectorLong ( const QVector < uint64 > & ids ) {
if ( ! ids . size ( ) ) return " [void list] " ;
QString idsStr = QString ( " [%1 " ) . arg ( * ids . cbegin ( ) ) ;
for ( QVector < uint64 > : : const_iterator i = ids . cbegin ( ) + 1 , e = ids . cend ( ) ; i ! = e ; + + i ) {
idsStr + = QString ( " , %2 " ) . arg ( * i ) ;
}
return idsStr + " ] " ;
}