kde-playground/akonadi/shared/akdebug.cpp
2015-09-23 09:37:02 +00:00

177 lines
4.5 KiB
C++

/*
Copyright (c) 2008 Volker Krause <vkrause@kde.org>
Inspired by kdelibs/kdecore/io/kdebug.h
Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
2002 Holger Freyther (freyther@kde.org)
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library 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 Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "akdebug.h"
#include "akcrash.h"
#include "akstandarddirs.h"
#include <libs/xdgbasedirs_p.h>
using Akonadi::XdgBaseDirs;
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QMutex>
#include <cassert>
class FileDebugStream : public QIODevice
{
public:
FileDebugStream()
: mType( QtCriticalMsg )
{
open( WriteOnly );
}
bool isSequential() const { return true; }
qint64 readData( char *, qint64 ) { return 0; }
qint64 readLineData( char *, qint64 ) { return 0; }
qint64 writeData( const char *data, qint64 len )
{
QByteArray buf = QByteArray::fromRawData( data, len );
if ( !mFileName.isEmpty() ) {
QFile outputFile( mFileName );
outputFile.open( QIODevice::WriteOnly | QIODevice::Append | QIODevice::Unbuffered );
outputFile.write( data, len );
outputFile.putChar( '\n' );
outputFile.close();
}
qt_message_output( mType,
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
QMessageLogContext(),
QString::fromLatin1( buf.trimmed() ) );
#else
buf.trimmed().constData() );
#endif
return len;
}
void setFileName( const QString &fileName )
{
mFileName = fileName;
}
void setType( QtMsgType type )
{
mType = type;
}
private:
QString mFileName;
QtMsgType mType;
};
class DebugPrivate
{
public:
DebugPrivate()
: fileStream( new FileDebugStream() )
{
}
~DebugPrivate()
{
delete fileStream;
}
QString errorLogFileName() const
{
return AkStandardDirs::saveDir( "data" )
+ QDir::separator()
+ name
+ QString::fromLatin1( ".error" );
}
QDebug stream( QtMsgType type )
{
QMutexLocker locker( &mutex );
#ifndef QT_NO_DEBUG_OUTPUT
if ( type == QtDebugMsg ) {
return qDebug();
}
#endif
fileStream->setType( type );
return QDebug( fileStream );
}
void setName( const QString &appName )
{
// Keep only the executable name, e.g. akonadi_control
name = appName.mid( appName.lastIndexOf( QLatin1Char( '/' ) ) + 1 );
fileStream->setFileName( errorLogFileName() );
}
QMutex mutex;
FileDebugStream *fileStream;
QString name;
};
Q_GLOBAL_STATIC( DebugPrivate, sInstance )
QDebug akFatal()
{
return sInstance()->stream( QtFatalMsg );
}
QDebug akError()
{
return sInstance()->stream( QtCriticalMsg );
}
#ifndef QT_NO_DEBUG_OUTPUT
QDebug akDebug()
{
return sInstance()->stream( QtDebugMsg );
}
#endif
void akInit( const QString &appName )
{
AkonadiCrash::init();
sInstance()->setName( appName );
QFileInfo infoOld( sInstance()->errorLogFileName() + QString::fromLatin1( ".old" ) );
if ( infoOld.exists() ) {
QFile fileOld( infoOld.absoluteFilePath() );
const bool success = fileOld.remove();
if ( !success ) {
qFatal( "Cannot remove old log file - running on a readonly filesystem maybe?" );
}
}
QFileInfo info( sInstance()->errorLogFileName() );
if ( info.exists() ) {
QFile file( info.absoluteFilePath() );
const bool success = file.rename( sInstance()->errorLogFileName() + QString::fromLatin1( ".old" ) );
if ( !success ) {
qFatal( "Cannot rename log file - running on a readonly filesystem maybe?" );
}
}
}
QString getEnv( const char *name, const QString &defaultValue )
{
const QString v = QString::fromLocal8Bit( qgetenv( name ) );
return !v.isEmpty() ? v : defaultValue;
}