ZTStats/Sources/LogMgr.cpp
2024-08-09 12:11:50 -04:00

647 lines
18 KiB
C++

/*******************************************************************************
* *
* Société de Transports de Montréal. *
* 2012 - 2013 *
* *
* Projet Zones Tests *
* *
* *
* *
*******************************************************************************/
/*
Description:
Cette classe est responsable de la création d'une liste d'objets CLogElement
à partir des données de passage des trains contenues dans les fichiers log.
Cette classe est principalement utilisée par l'interface graphique pour la
visualisation des passages.
*/
/* ************************************************************************** */
/* Revision:
### 20121024 JFM
### YYYYMMDD Description du besoin ou du bug
Description du changement.
*/
/* ************************************************************************** */
#include "LogMgr.h"
#include "TrainLogFileMgr.h"
//#include "OutilZT.h"
//#include "ZTLog.h"
#include <QCoreApplication>
#include <QMessageBox>
#include <QBuffer>
#include <QThread>
CLogMgr::CLogMgr()
{
mProgramHandle = 0;
mDirParserThread = new QThread();
mDirParserWorkerThread = new CDirParserThread();
mDirParserWorkerThread->moveToThread(mDirParserThread);
connect(mDirParserThread,SIGNAL(started()),mDirParserWorkerThread,SLOT(ParseDirectories()));
connect(mDirParserThread,SIGNAL(finished()),this,SLOT(ThreadQuit()));
connect(mDirParserThread,SIGNAL(terminated()),this,SLOT(ThreadTerminated()));
// connect(mDirParserWorkerThread,SIGNAL(NewLogParsed(QString,bool)),this,SLOT(NewLogParsed(QString,bool)));
connect(mDirParserWorkerThread,SIGNAL(NewLogParsed(CLogElement*)),this,SLOT(NewLogParsed(CLogElement*)));
connect(mDirParserWorkerThread,SIGNAL(ParsingFinished(int)),this,SLOT(DirParsingFinished(int)));
connect(mDirParserWorkerThread,SIGNAL(EmptyDirParsed()),this,SLOT(EmptyDirParsed()));
mDatabaseParsingTimer = new QTimer();
mDatabaseParsingTimer->setInterval(60000);
connect(mDatabaseParsingTimer,SIGNAL(timeout()),this,SLOT(ParsingTimerExpired()));
}
CLogMgr::~CLogMgr()
{
DestroyLogList();
delete mDirParserThread;
delete mDirParserWorkerThread;
delete mDatabaseParsingTimer;
}
unsigned int CLogMgr::DestroyLogList()
{
for(int i = 0; i < mPassagesList.size(); i++)
{
delete mPassagesList.at(i);
}
mPassagesList.clear();
return RET_OK;
}
unsigned int CLogMgr::ProtectLogElementFile(bool IsProtected, CLogElement *Element)
{
if(Element->mZTLogType == ZT1_LOG_TYPE)
{
CZT1LogElement *ZT1Element = (CZT1LogElement*)Element;
if(CTrainLogFileMgr::instance()->SetTrainLogProtected(IsProtected,ZT1Element->mLogFileName) == RET_OK)
{
ZT1Element->mFileProtected = IsProtected;
SaveDatabaseFile();
return RET_OK;
}
}
else if(Element->mZTLogType == ZT2_LOG_TYPE)
{
CZT2LogElement *ZT2Element = (CZT2LogElement*)Element;
if(CTrainLogFileMgr::instance()->SetTrainLogProtected(IsProtected,ZT2Element->mLogFileName) == RET_OK)
{
ZT2Element->mFileProtected = IsProtected;
SaveDatabaseFile();
return RET_OK;
}
}
return RET_ERROR;
}
unsigned int CLogMgr::ParseLogs(bool RebuildDatabase, bool KeepData)
{
DestroyLogList();
qDebug("Parsing Logs now...");
mSaveDBFile = false;
mParsingFinished = false;
// mProgramHandle->DatabaseFetchingBegin(this);
mDatabaseFileCounter = 0;
if(RebuildDatabase == true)
{
qDebug("Rebuilding database now...");
//mDirParserWorkerThread->SetParsingInfo(QDir(mLogDataDir),"*.bin",KeepData);
qDebug("Starting parser thread now...");
mDirParserThread->start();
mSaveDBFile = true;
}
else
{
//Load database file.
QDir BaseDir(mLogDataDir);
QString DatabaseFilePath = BaseDir.filePath("Trains.zdb");
// DatabaseFilePath += "Trains.zdb";
QFile* DatabaseFile = new QFile(BaseDir.filePath("Trains.zdb")/*DatabaseFilePath*/);
if(DatabaseFile)
{
if(DatabaseFile->open(QIODevice::ReadOnly | QIODevice::Unbuffered) == false)
{
//rebuild database...
qDebug("Failed to open Trains.zdb, rebuilding database now...");
//mDirParserWorkerThread->SetParsingInfo(QDir(mLogDataDir),"*.bin",KeepData);
qDebug("Starting parser thread now...");
mDirParserThread->start();
mSaveDBFile = true;
delete DatabaseFile;
return RET_OK;
}
}
else
{
DirParsingFinished(0);
return RET_ERROR;
}
QByteArray DBData = DatabaseFile->readAll();
QDataStream *DBStrm = new QDataStream(DBData);
qint32 NBRecords;
*DBStrm >> NBRecords;
for(qint32 i = 0; i < NBRecords; i++)
{
unsigned int LogType;
*DBStrm >> LogType;
if(LogType == ZT1_LOG_TYPE)
{
CZT1LogElement *NewElement = new CZT1LogElement;
*DBStrm >> NewElement->mPassageDateTime
>> NewElement->mTrainType
>> NewElement->mNbElements
>> NewElement->mThreadDataStartTime
>> NewElement->mThreadDataEndTime
>> NewElement->mLogFileName
>> NewElement->mMeanSpeed
>> NewElement->mFlags
>> NewElement->mStationName
>> NewElement->mFileProtected;
int NBDetect;
*DBStrm >> NBDetect;
for(int i = 0; i < NBDetect; i++)
{
CZTDetectionData *NewDetection = new CZTDetectionData;
*DBStrm >> NewDetection->mDetectionID
>> NewDetection->mRank
>> NewDetection->mTimeStamp;
NewElement->mZTDetections.append(NewDetection);
}
NewLogParsed(NewElement);
}
else if(LogType == ZT2_LOG_TYPE)
{
CZT2LogElement *NewElement = new CZT2LogElement;
*DBStrm >> NewElement->mPassageDateTime
>> NewElement->mLogFileName
>> NewElement->mNbElements
>> NewElement-> mStationName
>> NewElement->mFlags
>> NewElement->mFileProtected;
int NBDetect;
*DBStrm >> NBDetect;
for(int i = 0; i < NBDetect; i++)
{
CZTDetectionData *NewDetection = new CZTDetectionData;
*DBStrm >> NewDetection->mDetectionID
>> NewDetection->mRank
>> NewDetection->mTimeStamp;
NewElement->mZTDetections.append(NewDetection);
}
NewLogParsed(NewElement);
}
else
{
qDebug("Invalid logtype in DB file...");
}
}
DatabaseFile->close();
delete DatabaseFile;
delete DBStrm;
DirParsingFinished(1);
}
return RET_OK;
}
unsigned int CLogMgr::SaveDatabaseFile()
{
QDir BaseDir(mLogDataDir);
QString DatabaseFilePath = BaseDir.filePath("Trains.zdb");
// DatabaseFilePath += "Trains.zdb";
QFile* DatabaseFile = new QFile(BaseDir.filePath("Trains.zdb")/*DatabaseFilePath*/);
if(DatabaseFile)
{
if(DatabaseFile->open(QIODevice::WriteOnly | QIODevice::Unbuffered) == false)
{
QMessageBox::information(0,"Erreur","Impossible de créer le fichier DB");
delete DatabaseFile;
return RET_ERROR;
}
}
else
{
QMessageBox::information(0,"Erreur","Impossible de créer le fichier DB");
return RET_ERROR;
}
QByteArray byteArray;
QBuffer FileBuffer(&byteArray);
FileBuffer.open(QIODevice::WriteOnly);
QDataStream *DBStrm = new QDataStream(&FileBuffer);
qint32 NBRecords = mPassagesList.size();
*DBStrm << NBRecords;
for(qint32 i = 0; i < NBRecords; i++)
{
unsigned int LogType = mPassagesList.at(i)->mZTLogType;
*DBStrm << LogType;
if(LogType == ZT1_LOG_TYPE)
{
CZT1LogElement *NewElement = (CZT1LogElement*)mPassagesList.at(i);
QDateTime test = NewElement->mPassageDateTime;
// *DBStrm << NewElement->mPassageDateTime
*DBStrm << test
<< NewElement->mTrainType
<< NewElement->mNbElements
<< NewElement->mThreadDataStartTime
<< NewElement->mThreadDataEndTime
<< NewElement->mLogFileName
<< NewElement->mMeanSpeed
<< NewElement->mFlags
<< NewElement->mStationName
<< NewElement->mFileProtected;
int NBDetect = NewElement->mZTDetections.size();
*DBStrm << NBDetect;
for(int i = 0; i < NBDetect; i++)
{
*DBStrm << NewElement->mZTDetections.at(i)->mDetectionID
<< NewElement->mZTDetections.at(i)->mRank
<< NewElement->mZTDetections.at(i)->mTimeStamp;
}
}
else if(LogType == ZT2_LOG_TYPE)
{
CZT2LogElement *NewElement = (CZT2LogElement*)mPassagesList.at(i);
*DBStrm << NewElement->mPassageDateTime
<< NewElement->mLogFileName
<< NewElement->mNbElements
<< NewElement->mStationName
<< NewElement->mFlags
<< NewElement->mFileProtected;
int NBDetect = NewElement->mZTDetections.size();
*DBStrm << NBDetect;
for(int i = 0; i < NBDetect; i++)
{
*DBStrm << NewElement->mZTDetections.at(i)->mDetectionID
<< NewElement->mZTDetections.at(i)->mRank
<< NewElement->mZTDetections.at(i)->mTimeStamp;
}
}
else
{
qDebug("Invalid log type in array!!!");
}
}
FileBuffer.seek(0);
DatabaseFile->write(FileBuffer.buffer());
DatabaseFile->flush();
FileBuffer.close();
DatabaseFile->close();
delete DatabaseFile;
delete DBStrm;
mSaveDBFile = false;
return RET_OK;
}
unsigned int CLogMgr::RebuildDatabaseFile()
{
ParseLogs(true,false);
mSaveDBFile = true;
return RET_OK;
}
int CLogMgr::ParseDir(QDir dir, bool KeepData)
{
QStringList LogFilters;
QFileInfoList list;
// QString LogDataDir = mProgramHandle->GetLogDataPath();
LogFilters << "*.bin";
//Load files in base directory
QDir LogDir(dir);
LogDir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
LogDir.setNameFilters(LogFilters);
LogDir.setSorting(QDir::Name);
list = LogDir.entryInfoList();
if(list.size() != 0)
{
//Extract data for each passage
for(int i = 0; i < list.size(); i++)
{
ParseNewLog(list.at(i).filePath(),KeepData);
}
}
//Check for subdirectories
QDir SubDirectories(dir);
SubDirectories.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
QFileInfoList SubDirList = SubDirectories.entryInfoList();
for(int i = 0; i < SubDirList.size(); i++)
{
ParseDir(QDir(SubDirList.at(i).absoluteFilePath()), KeepData);
}
return 1;
}
CLogElement* CLogMgr::LoadLogData(CLogElement *Element)
{
if(Element->mZTLogType == ZT1_LOG_TYPE)
{
CZT1LogElement *TargetElement = (CZT1LogElement*)Element;
QString FilePath = TargetElement->mLogFileName;
unsigned int ret;
//Make shure that the lists are empty in the target element
for(int i = 0; i < TargetElement->mZTLogData.size(); i++)
{
delete TargetElement->mZTLogData.at(i);
}
for(int i = 0; i < TargetElement->mZTDetections.size(); i++)
{
delete TargetElement->mZTDetections.at(i);
}
TargetElement->mZTLogData.clear();
TargetElement->mZTDetections.clear();
//Passing the TargetElement to the OpenTrainLog function will fill it with data
CTrainLogFileMgr::instance()->OpenTrainLog(FilePath,ret,TargetElement,true);
return (CLogElement*)TargetElement;
}
else if(Element->mZTLogType == ZT2_LOG_TYPE)
{
CZT2LogElement *TargetElement = (CZT2LogElement*)Element;
QString FilePath = TargetElement->mLogFileName;
unsigned int ret;
//Make shure that the lists are empty in the target element
for(int i = 0; i < TargetElement->mZTLogData.size(); i++)
{
delete TargetElement->mZTLogData.at(i);
}
for(int i = 0; i < TargetElement->mZTDetections.size(); i++)
{
delete TargetElement->mZTDetections.at(i);
}
TargetElement->mZTLogData.clear();
TargetElement->mZTDetections.clear();
//Passing the TargetElement to the OpenTrainLog function will fill it with data
CTrainLogFileMgr::instance()->OpenTrainLog(FilePath,ret,TargetElement,true);
return (CLogElement*)TargetElement;
}
return 0;
}
unsigned int CLogMgr::FreeLogData(CLogElement *Element)
{
if(Element->mZTLogType == ZT1_LOG_TYPE)
{
CZT1LogElement *temp = (CZT1LogElement*)Element;
for(int i = 0; i < temp->mZTLogData.size(); i++)
delete temp->mZTLogData.at(i);
temp->mZTLogData.clear();
}
if(Element->mZTLogType == ZT2_LOG_TYPE)
{
CZT2LogElement *temp = (CZT2LogElement*)Element;
for(int i = 0; i < temp->mZTLogData.size(); i++)
delete temp->mZTLogData.at(i);
temp->mZTLogData.clear();
}
return RET_OK;
}
unsigned int CLogMgr::DeleteLog(int LogIndex)
{
if(LogIndex >= mPassagesList.size())
return RET_ERROR;
QString Filename;
CLogElement *Element = mPassagesList.takeAt(LogIndex);
FreeLogData(Element); //make shure no data will be leaked
{
if(Element->mZTLogType == ZT1_LOG_TYPE)
{
CZT1LogElement *temp = (CZT1LogElement*)Element;
Filename = temp->mLogFileName;
}
if(Element->mZTLogType == ZT2_LOG_TYPE)
{
CZT2LogElement *temp = (CZT2LogElement*)Element;
Filename = temp->mLogFileName;
}
}
QDir DirObject;
DirObject.remove(Filename);
delete Element;
SaveDatabaseFile();
return RET_OK;
}
bool CLogMgr::ParseNextLog()
{
if((int)mLogsFileIndex >= mLogsFilelist.size())
return false;
//Extract data
if(ParseNewLog(mLogsFilelist.at(mLogsFileIndex).filePath()) == RET_ERROR)
return false;
mLogsFileIndex++;
return true;
}
void CLogMgr::NewLogParsed(QString Filename,bool KeepData)
{
ParseNewLog(Filename,KeepData);
mDatabaseParsingTimer->start();
}
void CLogMgr::NewLogParsed(CLogElement * NewLog)
{
mPassagesList.append(NewLog);
mDatabaseParsingTimer->start();
// mProgramHandle->DatabaseFetchingTick(this,mDatabaseFileCounter++);
}
void CLogMgr::DirParsingFinished(int Res)
{
mDatabaseParsingTimer->stop();
mParsingFinished = true;
mDirParserThread->quit();
// mProgramHandle->LogsDatabaseLoaded(this,Res);
if(mSaveDBFile == true)
{
SaveDatabaseFile();
}
}
void CLogMgr::ParsingTimerExpired()
{
qDebug("Parsing timer timeout");
mDirParserWorkerThread->KillThread();
mDirParserThread->terminate();
DirParsingFinished(2);
}
void CLogMgr::EmptyDirParsed()
{
//The thread is not stuck. Kick the timer...
mDatabaseParsingTimer->start();
}
void CLogMgr::ThreadQuit()
{
qDebug("Thread quit slot");
}
void CLogMgr::ThreadTerminated()
{
qDebug("Thread terminated slot");
}
unsigned int CLogMgr::ParseNewLog(QString FileName, bool KeepData)
{
Q_UNUSED(KeepData)
unsigned int ret;
CLogElement *NewLog = CTrainLogFileMgr::instance()->OpenTrainLog(FileName,ret);
if(ret == RET_ERROR)
{
return RET_ERROR;
}
//the date and time of the log entry is assigned the date and time of the first record...
if(NewLog->mZTLogType == ZT1_LOG_TYPE)
{
mPassagesList.append(NewLog);
}
else if(NewLog->mZTLogType == ZT2_LOG_TYPE)
{
mPassagesList.append(NewLog);
}
return RET_OK;
}
unsigned int CLogMgr::ParseImportedLogs(QStringList *NewLogFiles)
{
if(NewLogFiles == 0)
{
return RET_ERROR;
}
for(int i = 0; i < NewLogFiles->size(); i++)
{
ParseNewLog(NewLogFiles->at(i));
}
SaveDatabaseFile();
// mProgramHandle->LogsDatabaseLoaded(this,1);
return RET_OK;
}
unsigned int CLogMgr::GetLogsCount()
{
return mPassagesList.size();
}
QList<CLogElement*> * CLogMgr::GetLogsList()
{
return &mPassagesList;
}
CLogElement::~CLogElement()
{
}
CZT1LogElement::~CZT1LogElement()
{
qDeleteAll(mZTLogData);
mZTLogData.clear();
qDeleteAll(mZTDetections);
mZTDetections.clear();
}
CZT2LogElement::~CZT2LogElement()
{
for(int i = 0; i < mZTLogData.size(); i++)
delete mZTLogData.at(i);
mZTLogData.clear();
for(int i = 0; i < mZTDetections.size(); i++)
delete mZTDetections.at(i);
mZTDetections.clear();
}