summaryrefslogtreecommitdiffstats
path: root/ksystemlog/src/defaultReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ksystemlog/src/defaultReader.cpp')
-rw-r--r--ksystemlog/src/defaultReader.cpp498
1 files changed, 498 insertions, 0 deletions
diff --git a/ksystemlog/src/defaultReader.cpp b/ksystemlog/src/defaultReader.cpp
new file mode 100644
index 0000000..e70f5e5
--- /dev/null
+++ b/ksystemlog/src/defaultReader.cpp
@@ -0,0 +1,498 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Nicolas Ternisien *
+ * nicolas.ternisien@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 <klocale.h>
+#include <kmessagebox.h>
+
+#include "logListItem.h"
+#include "ksystemlogConfig.h"
+#include "logLine.h"
+#include "view.h"
+#include "parsingHelper.h"
+
+#include "defaultReader.h"
+
+
+DefaultReader::DefaultReader(QObject *parent, const char *name) :
+ Reader(parent, name),
+ buffers(NULL)
+ {
+
+
+}
+
+
+DefaultReader::~DefaultReader() {
+ delete buffers;
+}
+
+void DefaultReader::readLog() {
+ //Each file in the Log file list are watched with the following method
+ watchLogFiles();
+
+ if (buffers!=NULL)
+ delete buffers;
+
+ if (logManager->getGroupBy()==NO_GROUP_BY)
+ buffers=new LogLineList();
+ else {
+ buffers=new LogLineTree(logManager->getColumns(), logManager->getGroupBy(), logManager->getGroupByColumn());
+ }
+
+
+ LogFiles& files=logManager->getLogFiles();
+
+ //Inform connected QObject that the reading has begun
+ emit readingBegin();
+
+ //Read each file of the list, and place their lines in the buffer
+ int i=files.count()-1;
+ LogFile* logFile;
+ while(i>=0) {
+ logFile=files[i];
+ kdDebug() << "Reading file " << logFile->url.path() << endl;
+ this->readFile(logFile);
+
+ i--;
+ }
+
+ //Synchronize the buffer once we have fill it
+ logManager->synchronize(buffers);
+
+ //Says to the buffer that we have read all files, and that
+ //the next adding will come from logChanged method
+ if (!buffers->isEmpty())
+ buffers->setFirstReadPerformed(true);
+
+ //Inform connected QObject that the reading is now finished
+ emit readingEnd();
+
+ //Emit a signal which informs connected slots that there are new lines
+ emit logUpdated(logManager->getView()->getLogList()->childCount());
+}
+
+void DefaultReader::readFile(LogFile* logFile) {
+ QString message=i18n("Opening file '%1'...").arg(logFile->url.path());
+ emit statusbarChanged(message);
+
+ //Inform connected QObject that we are now reading the "index" file
+ emit readingFile(logManager->getLogFiles().count() - logManager->getLogFiles().findIndex(logFile));
+
+
+ //We initialize these values from configuration to be used by the insert methods
+ tmpDeleteDuplicate=KSystemLogConfig::deleteDuplicatedLines();
+ tmpDeleteProcessId=KSystemLogConfig::deleteProcessIdentifier();
+ tmpMaxLines=KSystemLogConfig::maxLines();
+ tmpMaxCharacters=KSystemLogConfig::maxReadCharacters();
+
+ //Open the file
+ QFile* file=this->openFile(logFile->url.path());
+
+ //If an error occurs, end this method
+ if (file==NULL) {
+ return;
+ }
+
+ QString buffer;
+ QString filePath=logFile->url.path();
+
+
+ //Insert the content of the file in a string list
+ QStringList* rawBuffer=getRawBuffer(file);
+
+ //If there is no line
+ if (rawBuffer->size()==0) {
+ QString message=i18n("No log line in '%1'.").arg(logFile->url.path());
+ emit statusbarChanged(message);
+
+ delete rawBuffer;
+ return;
+ }
+
+ kdDebug() << "Testing each line..." << endl;
+
+ QStringList::iterator it;
+ it=rawBuffer->end();
+ it--;
+
+ //Calculate how many lines we will read
+ int size=rawBuffer->size();
+ int stop;
+ if (size>tmpMaxLines)
+ stop=size-tmpMaxLines;
+ else
+ stop=0;
+
+
+ //Test each line of the raw buffer
+ int i=size-1;
+
+ int progress=0;
+
+ int progressTotal=size-1 - stop;
+ int each=progressTotal / 100;
+ if (each==0)
+ each=progressTotal;
+
+
+ while(i>=stop) {
+ buffer=*it;
+
+ if (insertOrReplaceLine(buffer, logFile)==false)
+ break;
+
+ it--;
+ i--;
+
+ if (i>=0 && i%each==0) {
+ emit openingProgressed(progress++);
+ }
+ }
+
+ delete rawBuffer;
+
+ logFile->lastFileSize=file->size();
+
+ // Close the file
+ this->closeFile(file);
+
+ message=i18n("Log file '%1' loaded successfully.").arg(logFile->url.path());
+ emit statusbarChanged(message);
+
+}
+
+
+
+void DefaultReader::logChanged(LogFile* logFile) {
+ kdDebug() << "SortedReader : File has been modified !" << endl;
+
+ //We initialize these values from configuration to be used by the insert methods
+ tmpDeleteDuplicate=KSystemLogConfig::deleteDuplicatedLines();
+ tmpDeleteProcessId=KSystemLogConfig::deleteProcessIdentifier();
+ tmpMaxLines=KSystemLogConfig::maxLines();
+ tmpMaxCharacters=KSystemLogConfig::maxReadCharacters();
+
+ QString buffer;
+
+ QString filePath=logFile->url.path();
+ QFile* file=this->openFile(filePath);
+
+ if (file==NULL)
+ return;
+
+
+ //If there are new lines in the file, insert only them
+ if (logFile->lastFileSize <= (int) file->size()) {
+ //Place the cursor to the last line opened
+ file->at(logFile->lastFileSize);
+
+ kdDebug() << "Retrieving a part of the file..." << endl;
+
+ //Get the maximum number of line read from LogManager
+ int maxLines=KSystemLogConfig::maxLines();
+
+ QString buffer;
+ QStringList* rawBuffer=getRawBuffer(file);
+
+ //If there is no line
+ if (rawBuffer->size()==0) {
+ delete rawBuffer;
+ return;
+ }
+
+ kdDebug() << "Testing each line..." << endl;
+
+ QStringList::iterator it;
+ it=rawBuffer->end();
+ it--;
+
+ //Calculate how many lines we will read
+ int size=rawBuffer->size();
+ int stop=0;
+ if (size>maxLines)
+ stop=size-maxLines;
+
+ //Test each line of the raw buffer
+ int i=size-1;
+ while(i>=stop) {
+ buffer=*it;
+
+ if (insertOrReplaceLine(buffer, logFile)==false)
+ break;
+
+ it--;
+ i--;
+ }
+
+ kdDebug() << "Total read lines : " << (size-1-i) << endl;
+
+ delete rawBuffer;
+
+
+ }
+ //Else reread all lines, clear log list
+ else {
+ buffers->clear();
+
+ file->close();
+
+ this->readFile(logFile);
+ }
+
+ int newLineCount=buffers->getNewLineCount();
+
+ logManager->synchronize(buffers);
+
+ //Get the size file for the next calculation
+ logFile->lastFileSize=file->size();
+
+ // Close the file
+ this->closeFile(file);
+
+ QString message;
+ message=i18n("Log file '%1' has changed.").arg(logFile->url.path());
+ emit statusbarChanged(message);
+
+ //Emit a signal which informs connected slots that there are new lines
+ emit logUpdated(newLineCount);
+}
+
+
+
+
+bool DefaultReader::insertLine(QString& buffer, LogFile* originalFile) {
+ LogLine* line=this->parseMessage(buffer, originalFile);
+
+ //Do not insert the line if it NULL
+ //TODO Maybe return true (because we don't want to stop the reading for one dirty line)
+ if (line==NULL)
+ return(false);
+
+
+ //If the Delete Duplicated Line is checked, we first test that the line is really new
+ if (tmpDeleteDuplicate==true) {
+ if (buffers->lineAlreadyExists(line)==true)
+ return(true);
+ }
+
+ //If the line is newer, it can be inserted
+ if (buffers->isNewer(line)==true) {
+
+ if (buffers->getItemCount()<tmpMaxLines) {
+ buffers->insert(line);
+ }
+ else {
+ return(false);
+ }
+ }
+ //If the line is older, then inserts it only if there is still space in the buffer
+ else if (buffers->getItemCount()<tmpMaxLines) {
+ buffers->insert(line);
+ }
+
+ return(true);
+}
+
+
+bool DefaultReader::insertOrReplaceLine(QString& buffer, LogFile* originalFile) {
+ LogLine* line=this->parseMessage(buffer, originalFile);
+
+ //Do not insert the line if it NULL
+ //TODO Maybe return true (because we don't want to stop the reading for one dirty line)
+ if (line==NULL)
+ return(false);
+
+ //If the Delete Duplicated Line is checked, we first test that the line is really new
+ if (tmpDeleteDuplicate==true) {
+ if (buffers->lineAlreadyExists(line)==true) {
+ return(true);
+ }
+ }
+
+
+ //If the line is newer, it can be inserted
+ if (buffers->isNewer(line)==true) {
+
+ if (buffers->getItemCount()<tmpMaxLines) {
+ buffers->insert(line);
+ return(true);
+ }
+ else {
+ buffers->removeOldestLine();
+ buffers->insert(line);
+ return(true);
+ }
+ }
+ //If the line is older, then inserts it only if there is still space in the buffer
+ else if (buffers->getItemCount()<tmpMaxLines) {
+ buffers->insert(line);
+ return(true);
+ }
+
+ return(false);
+}
+
+/**
+ * TODO Improve speed of this method (with KRegExp class for example)
+ */
+LogLine* DefaultReader::parseMessage(QString& logLine, LogFile* originalFile) {
+ //kdDebug() << "Please don't use parseMessage() from SortedReader class" << endl;
+
+ int year=QDate::currentDate().year();
+
+ //Month number
+ QString month;
+ month=logLine.left(3);
+
+ logLine=logLine.remove(0, 4);
+ int monthNum=ParsingHelper::parseMonthNumber(month);
+
+ //Day number
+ QString day;
+
+ day=logLine.left(2);
+ int dayNum=day.toInt();
+
+ logLine=logLine.remove(0, 3);
+
+ QDate date(year, monthNum, dayNum);
+ if (!date.isValid()) {
+ kdDebug() << "Malformed date" << endl;
+ date=QDate::currentDate();
+ }
+
+ //Time
+ QString stringTime;
+ stringTime=logLine.left(8);
+ int h=stringTime.left(2).toInt();
+ stringTime.remove(0, 3);
+ int m=stringTime.left(2).toInt();
+ stringTime.remove(0, 3);
+ int s=stringTime.left(2).toInt();
+ stringTime.remove(0, 3);
+
+ QTime time(h, m, s);
+ if (!time.isValid()) {
+ kdDebug() << "Malformed time" << endl;
+ time=QTime::currentTime();
+ }
+
+ //QStringList
+ logLine=logLine.remove(0, 9);
+
+ int nextSpace;
+ nextSpace=logLine.find(' ');
+
+ //Host name
+ QString hostname;
+
+ hostname=logLine.left(nextSpace);
+
+ logLine=logLine.remove(0, nextSpace+1);
+
+
+ QString process;
+ QString message;
+
+ //Process name
+ nextSpace=logLine.find(':');
+ if (nextSpace!=-1) {
+ process=logLine.left(nextSpace);
+
+ //If the delete process identifier option is enabled
+ if (tmpDeleteProcessId==true) {
+ int squareBracket=process.find('[');
+
+ //If we find a bracket, we remove the useless part
+ if (squareBracket!=-1) {
+ process=process.left(squareBracket);
+ }
+
+ }
+ logLine=logLine.remove(0, nextSpace+1);
+
+ message=logLine.remove(0, 1);
+ }
+ //If we can't find any ':' character, it means that this line is a
+ //internal message of syslogd
+ else {
+ process=i18n("none");
+
+ message=logLine;
+ }
+
+
+
+
+
+ QStringList list;
+ list.append(hostname);
+ list.append(process);
+ list.append(message);
+
+ /*
+ *TODO Try to avoid that 2 columns with the same timestamps (but not the
+ *same appearance order are not sorted correctly
+ */
+ /*
+ LogLine* lastLine=buffers->lastLineInserted();
+ if (lastLine!=NULL) {
+ if (lastLine->getTime().date()==date && lastLine->getTime().time()==time)
+ time=time.addMSecs(1);
+ }
+ */
+
+ QString filePath=originalFile->url.path();
+ LogLine* logLineObject=new LogLine(date, time, list, filePath, originalFile->level, Globals::noMode->id);
+
+ return(logLineObject);
+}
+
+
+QStringList* DefaultReader::getRawBuffer(QFile* file) {
+ kdDebug() << "Retrieving the raw buffer..." << endl;
+
+ QString buffer;
+ QString tmpBuffer;
+ QStringList* rawBuffer=new QStringList();
+
+ int res;
+
+ //Insert the content of the file in a string list
+ while(!file->atEnd()) {
+
+ //Read the first MaxCharactersRead characters
+ res=file->readLine(buffer, tmpMaxCharacters);
+
+ //Ignore the rest of the line
+ while(res==tmpMaxCharacters)
+ file->readLine(tmpBuffer, tmpMaxCharacters);
+
+ //Push the new buffer to the list
+ rawBuffer->push_back(buffer);
+ }
+
+ kdDebug() << "Raw buffer retrieved." << endl;
+
+ return(rawBuffer);
+}
+
+#include "defaultReader.moc"