You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ktorrent/libktorrent/util/log.cpp

250 lines
5.6 KiB

/***************************************************************************
* Copyright (C) 2005 by Joris Guisson *
* joris.guisson@gmail.com *
* *
* This program 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 2 of the License, or *
* (at your option) any later version. *
* *
* This program 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. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include <kurl.h>
#include <kprocess.h>
#include <klocale.h>
#include <tqdatetime.h>
#include <tqtextstream.h>
#include <tqfile.h>
#include <tqptrlist.h>
#include <iostream>
#include <stdlib.h>
#include <torrent/globals.h>
#include <interfaces/logmonitorinterface.h>
#include <tqmutex.h>
#include <util/fileops.h>
#include <stdlib.h>
#include "log.h"
#include "error.h"
#include "autorotatelogjob.h"
using namespace kt;
namespace bt
{
const Uint32 MAX_LOG_FILE_SIZE = 10 * 1024 * 1024; // 10 MB
class Log::Private
{
public:
Log* parent;
TQTextStream* out;
TQFile fptr;
bool to_cout;
TQPtrList<LogMonitorInterface> monitors;
TQString tmp;
TQMutex mutex;
unsigned int m_filter;
AutoRotateLogJob* rotate_job;
public:
Private(Log* parent) : parent(parent),out(0),to_cout(false),rotate_job(0)
{
out = new TQTextStream();
}
~Private()
{
delete out;
}
void setFilter(unsigned int filter)
{
m_filter = filter;
}
void rotateLogs(const TQString & file)
{
if (bt::Exists(file + "-10.gz"))
bt::Delete(file + "-10.gz",true);
// move all log files one up
for (Uint32 i = 10;i > 1;i--)
{
TQString prev = TQString("%1-%2.gz").tqarg(file).tqarg(i - 1);
TQString curr = TQString("%1-%2.gz").tqarg(file).tqarg(i);
if (bt::Exists(prev))
bt::Move(prev,curr,true);
}
// move current log to 1 and zip it
bt::Move(file,file + "-1",true);
system(TQString("gzip " + KProcess::quote(file + "-1")).local8Bit());
}
void setOutputFile(const TQString & file)
{
if (fptr.isOpen())
fptr.close();
if (bt::Exists(file))
rotateLogs(file);
fptr.setName(file);
if (!fptr.open(IO_WriteOnly))
throw Error(i18n("Cannot open log file %1 : %2").tqarg(file).tqarg(fptr.errorString()));
out->setDevice(TQT_TQIODEVICE(&fptr));
}
void write(const TQString & line)
{
tmp += line;
}
void finishLine()
{
// only add stuff when we are not rotating the logs
// this could result in the loss of some messages
if (!rotate_job)
{
*out << TQDateTime::currentDateTime().toString() << ": " << tmp << ::endl;
fptr.flush();
if (to_cout)
std::cout << TQString(tmp.local8Bit()) << std::endl;
if (monitors.count() > 0)
{
TQPtrList<LogMonitorInterface>::iterator i = monitors.begin();
while (i != monitors.end())
{
kt::LogMonitorInterface* lmi = *i;
lmi->message(tmp,m_filter);
i++;
}
}
}
tmp = "";
}
void endline()
{
finishLine();
if (fptr.size() > MAX_LOG_FILE_SIZE && !rotate_job)
{
tmp = "Log larger then 10 MB, rotating";
finishLine();
TQString file = fptr.name();
fptr.close(); // close the log file
out->setDevice(0);
// start the rotate job
rotate_job = new AutoRotateLogJob(file,parent);
}
}
void logRotateDone()
{
fptr.open(IO_WriteOnly);
out->setDevice(TQT_TQIODEVICE(&fptr));
rotate_job = 0;
}
};
Log::Log()
{
priv = new Private(this);
}
Log::~Log()
{
delete priv;
}
void Log::setOutputFile(const TQString & file)
{
priv->setOutputFile(file);
}
void Log::addMonitor(kt::LogMonitorInterface* m)
{
priv->monitors.append(m);
}
void Log::removeMonitor(kt::LogMonitorInterface* m)
{
priv->monitors.remove(m);
}
void Log::setOutputToConsole(bool on)
{
priv->to_cout = on;
}
Log & endl(Log & lg)
{
lg.priv->endline();
lg.priv->mutex.unlock(); // unlock after end of line
return lg;
}
Log & Log::operator << (const KURL & url)
{
priv->write(url.prettyURL());
return *this;
}
Log & Log::operator << (const TQString & s)
{
priv->write(s);
return *this;
}
Log & Log::operator << (const char* s)
{
priv->write(s);
return *this;
}
Log & Log::operator << (Uint64 v)
{
return operator << (TQString::number(v));
}
Log & Log::operator << (Int64 v)
{
return operator << (TQString::number(v));
}
void Log::setFilter(unsigned int filter)
{
priv->setFilter(filter);
}
void Log::lock()
{
priv->mutex.lock();
}
void Log::logRotateDone()
{
priv->logRotateDone();
}
Log & Out(unsigned int arg)
{
Log & lg = Globals::instance().getLog(arg);
lg.lock();
return lg;
}
}