647 lines
18 KiB
C++
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();
|
|
|
|
}
|