Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 

647 рядки
18 KiB

  1. /*******************************************************************************
  2. * *
  3. * Société de Transports de Montréal. *
  4. * 2012 - 2013 *
  5. * *
  6. * Projet Zones Tests *
  7. * *
  8. * *
  9. * *
  10. *******************************************************************************/
  11. /*
  12. Description:
  13. Cette classe est responsable de la création d'une liste d'objets CLogElement
  14. à partir des données de passage des trains contenues dans les fichiers log.
  15. Cette classe est principalement utilisée par l'interface graphique pour la
  16. visualisation des passages.
  17. */
  18. /* ************************************************************************** */
  19. /* Revision:
  20. ### 20121024 JFM
  21. ### YYYYMMDD Description du besoin ou du bug
  22. Description du changement.
  23. */
  24. /* ************************************************************************** */
  25. #include "LogMgr.h"
  26. #include "TrainLogFileMgr.h"
  27. //#include "OutilZT.h"
  28. //#include "ZTLog.h"
  29. #include <QCoreApplication>
  30. #include <QMessageBox>
  31. #include <QBuffer>
  32. #include <QThread>
  33. CLogMgr::CLogMgr()
  34. {
  35. mProgramHandle = 0;
  36. mDirParserThread = new QThread();
  37. mDirParserWorkerThread = new CDirParserThread();
  38. mDirParserWorkerThread->moveToThread(mDirParserThread);
  39. connect(mDirParserThread,SIGNAL(started()),mDirParserWorkerThread,SLOT(ParseDirectories()));
  40. connect(mDirParserThread,SIGNAL(finished()),this,SLOT(ThreadQuit()));
  41. connect(mDirParserThread,SIGNAL(terminated()),this,SLOT(ThreadTerminated()));
  42. // connect(mDirParserWorkerThread,SIGNAL(NewLogParsed(QString,bool)),this,SLOT(NewLogParsed(QString,bool)));
  43. connect(mDirParserWorkerThread,SIGNAL(NewLogParsed(CLogElement*)),this,SLOT(NewLogParsed(CLogElement*)));
  44. connect(mDirParserWorkerThread,SIGNAL(ParsingFinished(int)),this,SLOT(DirParsingFinished(int)));
  45. connect(mDirParserWorkerThread,SIGNAL(EmptyDirParsed()),this,SLOT(EmptyDirParsed()));
  46. mDatabaseParsingTimer = new QTimer();
  47. mDatabaseParsingTimer->setInterval(60000);
  48. connect(mDatabaseParsingTimer,SIGNAL(timeout()),this,SLOT(ParsingTimerExpired()));
  49. }
  50. CLogMgr::~CLogMgr()
  51. {
  52. DestroyLogList();
  53. delete mDirParserThread;
  54. delete mDirParserWorkerThread;
  55. delete mDatabaseParsingTimer;
  56. }
  57. unsigned int CLogMgr::DestroyLogList()
  58. {
  59. for(int i = 0; i < mPassagesList.size(); i++)
  60. {
  61. delete mPassagesList.at(i);
  62. }
  63. mPassagesList.clear();
  64. return RET_OK;
  65. }
  66. unsigned int CLogMgr::ProtectLogElementFile(bool IsProtected, CLogElement *Element)
  67. {
  68. if(Element->mZTLogType == ZT1_LOG_TYPE)
  69. {
  70. CZT1LogElement *ZT1Element = (CZT1LogElement*)Element;
  71. if(CTrainLogFileMgr::instance()->SetTrainLogProtected(IsProtected,ZT1Element->mLogFileName) == RET_OK)
  72. {
  73. ZT1Element->mFileProtected = IsProtected;
  74. SaveDatabaseFile();
  75. return RET_OK;
  76. }
  77. }
  78. else if(Element->mZTLogType == ZT2_LOG_TYPE)
  79. {
  80. CZT2LogElement *ZT2Element = (CZT2LogElement*)Element;
  81. if(CTrainLogFileMgr::instance()->SetTrainLogProtected(IsProtected,ZT2Element->mLogFileName) == RET_OK)
  82. {
  83. ZT2Element->mFileProtected = IsProtected;
  84. SaveDatabaseFile();
  85. return RET_OK;
  86. }
  87. }
  88. return RET_ERROR;
  89. }
  90. unsigned int CLogMgr::ParseLogs(bool RebuildDatabase, bool KeepData)
  91. {
  92. DestroyLogList();
  93. qDebug("Parsing Logs now...");
  94. mSaveDBFile = false;
  95. mParsingFinished = false;
  96. // mProgramHandle->DatabaseFetchingBegin(this);
  97. mDatabaseFileCounter = 0;
  98. if(RebuildDatabase == true)
  99. {
  100. qDebug("Rebuilding database now...");
  101. //mDirParserWorkerThread->SetParsingInfo(QDir(mLogDataDir),"*.bin",KeepData);
  102. qDebug("Starting parser thread now...");
  103. mDirParserThread->start();
  104. mSaveDBFile = true;
  105. }
  106. else
  107. {
  108. //Load database file.
  109. QDir BaseDir(mLogDataDir);
  110. QString DatabaseFilePath = BaseDir.filePath("Trains.zdb");
  111. // DatabaseFilePath += "Trains.zdb";
  112. QFile* DatabaseFile = new QFile(BaseDir.filePath("Trains.zdb")/*DatabaseFilePath*/);
  113. if(DatabaseFile)
  114. {
  115. if(DatabaseFile->open(QIODevice::ReadOnly | QIODevice::Unbuffered) == false)
  116. {
  117. //rebuild database...
  118. qDebug("Failed to open Trains.zdb, rebuilding database now...");
  119. //mDirParserWorkerThread->SetParsingInfo(QDir(mLogDataDir),"*.bin",KeepData);
  120. qDebug("Starting parser thread now...");
  121. mDirParserThread->start();
  122. mSaveDBFile = true;
  123. delete DatabaseFile;
  124. return RET_OK;
  125. }
  126. }
  127. else
  128. {
  129. DirParsingFinished(0);
  130. return RET_ERROR;
  131. }
  132. QByteArray DBData = DatabaseFile->readAll();
  133. QDataStream *DBStrm = new QDataStream(DBData);
  134. qint32 NBRecords;
  135. *DBStrm >> NBRecords;
  136. for(qint32 i = 0; i < NBRecords; i++)
  137. {
  138. unsigned int LogType;
  139. *DBStrm >> LogType;
  140. if(LogType == ZT1_LOG_TYPE)
  141. {
  142. CZT1LogElement *NewElement = new CZT1LogElement;
  143. *DBStrm >> NewElement->mPassageDateTime
  144. >> NewElement->mTrainType
  145. >> NewElement->mNbElements
  146. >> NewElement->mThreadDataStartTime
  147. >> NewElement->mThreadDataEndTime
  148. >> NewElement->mLogFileName
  149. >> NewElement->mMeanSpeed
  150. >> NewElement->mFlags
  151. >> NewElement->mStationName
  152. >> NewElement->mFileProtected;
  153. int NBDetect;
  154. *DBStrm >> NBDetect;
  155. for(int i = 0; i < NBDetect; i++)
  156. {
  157. CZTDetectionData *NewDetection = new CZTDetectionData;
  158. *DBStrm >> NewDetection->mDetectionID
  159. >> NewDetection->mRank
  160. >> NewDetection->mTimeStamp;
  161. NewElement->mZTDetections.append(NewDetection);
  162. }
  163. NewLogParsed(NewElement);
  164. }
  165. else if(LogType == ZT2_LOG_TYPE)
  166. {
  167. CZT2LogElement *NewElement = new CZT2LogElement;
  168. *DBStrm >> NewElement->mPassageDateTime
  169. >> NewElement->mLogFileName
  170. >> NewElement->mNbElements
  171. >> NewElement-> mStationName
  172. >> NewElement->mFlags
  173. >> NewElement->mFileProtected;
  174. int NBDetect;
  175. *DBStrm >> NBDetect;
  176. for(int i = 0; i < NBDetect; i++)
  177. {
  178. CZTDetectionData *NewDetection = new CZTDetectionData;
  179. *DBStrm >> NewDetection->mDetectionID
  180. >> NewDetection->mRank
  181. >> NewDetection->mTimeStamp;
  182. NewElement->mZTDetections.append(NewDetection);
  183. }
  184. NewLogParsed(NewElement);
  185. }
  186. else
  187. {
  188. qDebug("Invalid logtype in DB file...");
  189. }
  190. }
  191. DatabaseFile->close();
  192. delete DatabaseFile;
  193. delete DBStrm;
  194. DirParsingFinished(1);
  195. }
  196. return RET_OK;
  197. }
  198. unsigned int CLogMgr::SaveDatabaseFile()
  199. {
  200. QDir BaseDir(mLogDataDir);
  201. QString DatabaseFilePath = BaseDir.filePath("Trains.zdb");
  202. // DatabaseFilePath += "Trains.zdb";
  203. QFile* DatabaseFile = new QFile(BaseDir.filePath("Trains.zdb")/*DatabaseFilePath*/);
  204. if(DatabaseFile)
  205. {
  206. if(DatabaseFile->open(QIODevice::WriteOnly | QIODevice::Unbuffered) == false)
  207. {
  208. QMessageBox::information(0,"Erreur","Impossible de créer le fichier DB");
  209. delete DatabaseFile;
  210. return RET_ERROR;
  211. }
  212. }
  213. else
  214. {
  215. QMessageBox::information(0,"Erreur","Impossible de créer le fichier DB");
  216. return RET_ERROR;
  217. }
  218. QByteArray byteArray;
  219. QBuffer FileBuffer(&byteArray);
  220. FileBuffer.open(QIODevice::WriteOnly);
  221. QDataStream *DBStrm = new QDataStream(&FileBuffer);
  222. qint32 NBRecords = mPassagesList.size();
  223. *DBStrm << NBRecords;
  224. for(qint32 i = 0; i < NBRecords; i++)
  225. {
  226. unsigned int LogType = mPassagesList.at(i)->mZTLogType;
  227. *DBStrm << LogType;
  228. if(LogType == ZT1_LOG_TYPE)
  229. {
  230. CZT1LogElement *NewElement = (CZT1LogElement*)mPassagesList.at(i);
  231. QDateTime test = NewElement->mPassageDateTime;
  232. // *DBStrm << NewElement->mPassageDateTime
  233. *DBStrm << test
  234. << NewElement->mTrainType
  235. << NewElement->mNbElements
  236. << NewElement->mThreadDataStartTime
  237. << NewElement->mThreadDataEndTime
  238. << NewElement->mLogFileName
  239. << NewElement->mMeanSpeed
  240. << NewElement->mFlags
  241. << NewElement->mStationName
  242. << NewElement->mFileProtected;
  243. int NBDetect = NewElement->mZTDetections.size();
  244. *DBStrm << NBDetect;
  245. for(int i = 0; i < NBDetect; i++)
  246. {
  247. *DBStrm << NewElement->mZTDetections.at(i)->mDetectionID
  248. << NewElement->mZTDetections.at(i)->mRank
  249. << NewElement->mZTDetections.at(i)->mTimeStamp;
  250. }
  251. }
  252. else if(LogType == ZT2_LOG_TYPE)
  253. {
  254. CZT2LogElement *NewElement = (CZT2LogElement*)mPassagesList.at(i);
  255. *DBStrm << NewElement->mPassageDateTime
  256. << NewElement->mLogFileName
  257. << NewElement->mNbElements
  258. << NewElement->mStationName
  259. << NewElement->mFlags
  260. << NewElement->mFileProtected;
  261. int NBDetect = NewElement->mZTDetections.size();
  262. *DBStrm << NBDetect;
  263. for(int i = 0; i < NBDetect; i++)
  264. {
  265. *DBStrm << NewElement->mZTDetections.at(i)->mDetectionID
  266. << NewElement->mZTDetections.at(i)->mRank
  267. << NewElement->mZTDetections.at(i)->mTimeStamp;
  268. }
  269. }
  270. else
  271. {
  272. qDebug("Invalid log type in array!!!");
  273. }
  274. }
  275. FileBuffer.seek(0);
  276. DatabaseFile->write(FileBuffer.buffer());
  277. DatabaseFile->flush();
  278. FileBuffer.close();
  279. DatabaseFile->close();
  280. delete DatabaseFile;
  281. delete DBStrm;
  282. mSaveDBFile = false;
  283. return RET_OK;
  284. }
  285. unsigned int CLogMgr::RebuildDatabaseFile()
  286. {
  287. ParseLogs(true,false);
  288. mSaveDBFile = true;
  289. return RET_OK;
  290. }
  291. int CLogMgr::ParseDir(QDir dir, bool KeepData)
  292. {
  293. QStringList LogFilters;
  294. QFileInfoList list;
  295. // QString LogDataDir = mProgramHandle->GetLogDataPath();
  296. LogFilters << "*.bin";
  297. //Load files in base directory
  298. QDir LogDir(dir);
  299. LogDir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
  300. LogDir.setNameFilters(LogFilters);
  301. LogDir.setSorting(QDir::Name);
  302. list = LogDir.entryInfoList();
  303. if(list.size() != 0)
  304. {
  305. //Extract data for each passage
  306. for(int i = 0; i < list.size(); i++)
  307. {
  308. ParseNewLog(list.at(i).filePath(),KeepData);
  309. }
  310. }
  311. //Check for subdirectories
  312. QDir SubDirectories(dir);
  313. SubDirectories.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
  314. QFileInfoList SubDirList = SubDirectories.entryInfoList();
  315. for(int i = 0; i < SubDirList.size(); i++)
  316. {
  317. ParseDir(QDir(SubDirList.at(i).absoluteFilePath()), KeepData);
  318. }
  319. return 1;
  320. }
  321. CLogElement* CLogMgr::LoadLogData(CLogElement *Element)
  322. {
  323. if(Element->mZTLogType == ZT1_LOG_TYPE)
  324. {
  325. CZT1LogElement *TargetElement = (CZT1LogElement*)Element;
  326. QString FilePath = TargetElement->mLogFileName;
  327. unsigned int ret;
  328. //Make shure that the lists are empty in the target element
  329. for(int i = 0; i < TargetElement->mZTLogData.size(); i++)
  330. {
  331. delete TargetElement->mZTLogData.at(i);
  332. }
  333. for(int i = 0; i < TargetElement->mZTDetections.size(); i++)
  334. {
  335. delete TargetElement->mZTDetections.at(i);
  336. }
  337. TargetElement->mZTLogData.clear();
  338. TargetElement->mZTDetections.clear();
  339. //Passing the TargetElement to the OpenTrainLog function will fill it with data
  340. CTrainLogFileMgr::instance()->OpenTrainLog(FilePath,ret,TargetElement,true);
  341. return (CLogElement*)TargetElement;
  342. }
  343. else if(Element->mZTLogType == ZT2_LOG_TYPE)
  344. {
  345. CZT2LogElement *TargetElement = (CZT2LogElement*)Element;
  346. QString FilePath = TargetElement->mLogFileName;
  347. unsigned int ret;
  348. //Make shure that the lists are empty in the target element
  349. for(int i = 0; i < TargetElement->mZTLogData.size(); i++)
  350. {
  351. delete TargetElement->mZTLogData.at(i);
  352. }
  353. for(int i = 0; i < TargetElement->mZTDetections.size(); i++)
  354. {
  355. delete TargetElement->mZTDetections.at(i);
  356. }
  357. TargetElement->mZTLogData.clear();
  358. TargetElement->mZTDetections.clear();
  359. //Passing the TargetElement to the OpenTrainLog function will fill it with data
  360. CTrainLogFileMgr::instance()->OpenTrainLog(FilePath,ret,TargetElement,true);
  361. return (CLogElement*)TargetElement;
  362. }
  363. return 0;
  364. }
  365. unsigned int CLogMgr::FreeLogData(CLogElement *Element)
  366. {
  367. if(Element->mZTLogType == ZT1_LOG_TYPE)
  368. {
  369. CZT1LogElement *temp = (CZT1LogElement*)Element;
  370. for(int i = 0; i < temp->mZTLogData.size(); i++)
  371. delete temp->mZTLogData.at(i);
  372. temp->mZTLogData.clear();
  373. }
  374. if(Element->mZTLogType == ZT2_LOG_TYPE)
  375. {
  376. CZT2LogElement *temp = (CZT2LogElement*)Element;
  377. for(int i = 0; i < temp->mZTLogData.size(); i++)
  378. delete temp->mZTLogData.at(i);
  379. temp->mZTLogData.clear();
  380. }
  381. return RET_OK;
  382. }
  383. unsigned int CLogMgr::DeleteLog(int LogIndex)
  384. {
  385. if(LogIndex >= mPassagesList.size())
  386. return RET_ERROR;
  387. QString Filename;
  388. CLogElement *Element = mPassagesList.takeAt(LogIndex);
  389. FreeLogData(Element); //make shure no data will be leaked
  390. {
  391. if(Element->mZTLogType == ZT1_LOG_TYPE)
  392. {
  393. CZT1LogElement *temp = (CZT1LogElement*)Element;
  394. Filename = temp->mLogFileName;
  395. }
  396. if(Element->mZTLogType == ZT2_LOG_TYPE)
  397. {
  398. CZT2LogElement *temp = (CZT2LogElement*)Element;
  399. Filename = temp->mLogFileName;
  400. }
  401. }
  402. QDir DirObject;
  403. DirObject.remove(Filename);
  404. delete Element;
  405. SaveDatabaseFile();
  406. return RET_OK;
  407. }
  408. bool CLogMgr::ParseNextLog()
  409. {
  410. if((int)mLogsFileIndex >= mLogsFilelist.size())
  411. return false;
  412. //Extract data
  413. if(ParseNewLog(mLogsFilelist.at(mLogsFileIndex).filePath()) == RET_ERROR)
  414. return false;
  415. mLogsFileIndex++;
  416. return true;
  417. }
  418. void CLogMgr::NewLogParsed(QString Filename,bool KeepData)
  419. {
  420. ParseNewLog(Filename,KeepData);
  421. mDatabaseParsingTimer->start();
  422. }
  423. void CLogMgr::NewLogParsed(CLogElement * NewLog)
  424. {
  425. mPassagesList.append(NewLog);
  426. mDatabaseParsingTimer->start();
  427. // mProgramHandle->DatabaseFetchingTick(this,mDatabaseFileCounter++);
  428. }
  429. void CLogMgr::DirParsingFinished(int Res)
  430. {
  431. mDatabaseParsingTimer->stop();
  432. mParsingFinished = true;
  433. mDirParserThread->quit();
  434. // mProgramHandle->LogsDatabaseLoaded(this,Res);
  435. if(mSaveDBFile == true)
  436. {
  437. SaveDatabaseFile();
  438. }
  439. }
  440. void CLogMgr::ParsingTimerExpired()
  441. {
  442. qDebug("Parsing timer timeout");
  443. mDirParserWorkerThread->KillThread();
  444. mDirParserThread->terminate();
  445. DirParsingFinished(2);
  446. }
  447. void CLogMgr::EmptyDirParsed()
  448. {
  449. //The thread is not stuck. Kick the timer...
  450. mDatabaseParsingTimer->start();
  451. }
  452. void CLogMgr::ThreadQuit()
  453. {
  454. qDebug("Thread quit slot");
  455. }
  456. void CLogMgr::ThreadTerminated()
  457. {
  458. qDebug("Thread terminated slot");
  459. }
  460. unsigned int CLogMgr::ParseNewLog(QString FileName, bool KeepData)
  461. {
  462. Q_UNUSED(KeepData)
  463. unsigned int ret;
  464. CLogElement *NewLog = CTrainLogFileMgr::instance()->OpenTrainLog(FileName,ret);
  465. if(ret == RET_ERROR)
  466. {
  467. return RET_ERROR;
  468. }
  469. //the date and time of the log entry is assigned the date and time of the first record...
  470. if(NewLog->mZTLogType == ZT1_LOG_TYPE)
  471. {
  472. mPassagesList.append(NewLog);
  473. }
  474. else if(NewLog->mZTLogType == ZT2_LOG_TYPE)
  475. {
  476. mPassagesList.append(NewLog);
  477. }
  478. return RET_OK;
  479. }
  480. unsigned int CLogMgr::ParseImportedLogs(QStringList *NewLogFiles)
  481. {
  482. if(NewLogFiles == 0)
  483. {
  484. return RET_ERROR;
  485. }
  486. for(int i = 0; i < NewLogFiles->size(); i++)
  487. {
  488. ParseNewLog(NewLogFiles->at(i));
  489. }
  490. SaveDatabaseFile();
  491. // mProgramHandle->LogsDatabaseLoaded(this,1);
  492. return RET_OK;
  493. }
  494. unsigned int CLogMgr::GetLogsCount()
  495. {
  496. return mPassagesList.size();
  497. }
  498. QList<CLogElement*> * CLogMgr::GetLogsList()
  499. {
  500. return &mPassagesList;
  501. }
  502. CLogElement::~CLogElement()
  503. {
  504. }
  505. CZT1LogElement::~CZT1LogElement()
  506. {
  507. qDeleteAll(mZTLogData);
  508. mZTLogData.clear();
  509. qDeleteAll(mZTDetections);
  510. mZTDetections.clear();
  511. }
  512. CZT2LogElement::~CZT2LogElement()
  513. {
  514. for(int i = 0; i < mZTLogData.size(); i++)
  515. delete mZTLogData.at(i);
  516. mZTLogData.clear();
  517. for(int i = 0; i < mZTDetections.size(); i++)
  518. delete mZTDetections.at(i);
  519. mZTDetections.clear();
  520. }