Index: sources/storage/Logger.cpp =================================================================== diff -u -r72494685cc15648712935311cb8ff5b208e70cb4 -raccc25a2cefe436401ad04c57713cfa410621317 --- sources/storage/Logger.cpp (.../Logger.cpp) (revision 72494685cc15648712935311cb8ff5b208e70cb4) +++ sources/storage/Logger.cpp (.../Logger.cpp) (revision accc25a2cefe436401ad04c57713cfa410621317) @@ -44,8 +44,16 @@ if ( ! gLongLogName ) { _fileDateFormat = "yyyy_MM_dd"; // date used in the file name } + + startTimer(_interval); } +void Logger::timerEvent(QTimerEvent *) +{ + // log flush timeouot + logTimeout(); +} + /*! * \brief Logger::init * \details Initializes the Class. @@ -138,16 +146,18 @@ connect(&_exportLogsWatcher, SIGNAL(finished ()), this , SLOT(onExportLogs())); + connect(this , SIGNAL(didLog(QString,LogType,bool)), + this , SLOT( onLog(QString,LogType,bool))); - connect(this, SIGNAL(didLog(QString,LogType,bool)), - this, SLOT( onLog(QString,LogType,bool))); + connect(&_MainTimer , SIGNAL( didDateChange ()), + this , SLOT( concurrentRemoveLogs())); - connect(&_MainTimer, SIGNAL( didDateChange ()), - this , SLOT( concurrentRemoveLogs())); - connect(&_removeLogsWatcher, SIGNAL(finished ()), this , SLOT(onRemoveLogs())); + connect(&_flushLogsWatcher , SIGNAL(finished ()), + this , SLOT(onFlushLogs())); + connect(&_DeviceController, SIGNAL( didSDCardStateChange(bool, bool)), this , SLOT( onSDCardStateChange(bool, bool))); connect(&_DeviceController, SIGNAL( didSDCardSpaceChange(bool, qint64, qint64, quint8)), @@ -195,7 +205,7 @@ moveToThread(qApp->thread()); // validated } -void Logger::onLog(const QString &vContent, LogType vLogType, bool vTimestamp) +void Logger::onLog(const QString &vContent, LogType vLogType, bool /*vTimestamp*/) { static bool notified = false; if ( ! _logStorageReady && ! gDisableSDCFailLogStop ) { @@ -205,8 +215,7 @@ } return; } - - log(vContent, vLogType, vTimestamp); + log(vContent, vLogType); } /*! @@ -307,6 +316,30 @@ return ok; } +void Logger::logTimeout() { + if( _cacheCounter ) { + _cacheCounter --; + } + else { + _cacheCounter = _cachetimeout; + _cacheIndex = logSwitch(); // switch the index for caching while the flush is working + concurrentFlushLog(eLogAppED); + concurrentFlushLog(eLogDebug); + } +} + +bool Logger::logOverflow(LogType vLogType) { + switch ( vLogType ) { + case eLogAppED : return _cacheA[_cacheIndex].count() >= _cacheCount; + case eLogDebug : return _cacheD[_cacheIndex].count() >= _cacheCount; + default : return _cacheD[_cacheIndex].count() >= _cacheCount; + } +} + +Logger::CacheIndex Logger::logSwitch() { + return _cacheIndex == eCache1 ? eCache2 : eCache1;; +} + /*! * \brief Logger::log * \details Logs the content vContent in log type of vLogType. @@ -315,33 +348,87 @@ * \note This method is not thread-safe so is private and needs to be called by concurrentLog * Which uses QtConcurrent::run to run in thread and thread-safe. */ -void Logger::log(const QString &vContent, LogType vLogType, bool vTimestamp) +void Logger::log(const QString &vContent, LogType vLogType) { if ( ! checkThread() ) return; QString mContent; + QDateTime datetime = QDateTime::currentDateTime(); + + // Add timestamp + mContent = datetime.time().toString(_timeFormat) + _sepParam; + mContent += vContent; + // some messages like the version having the U08(uchar) parameters which converts to '\0' and causes problems in reading the log file. + mContent.replace('\0', "0"); + + // Add the recieved message + switch ( vLogType ) { + case eLogAppED : _cacheA[_cacheIndex] += mContent; break; + case eLogDebug : _cacheD[_cacheIndex] += mContent; break; + default : _cacheD[_cacheIndex] += QString("Incorrect type of logging %1").arg(vLogType); + _cacheD[_cacheIndex] += mContent; + } + + if ( logOverflow(vLogType) ) { + _cacheIndex = logSwitch(); // switch the index for caching while the flush is working + concurrentFlushLog(vLogType); + } + + // console out the log if enabled. + if (_enableConsoleOut) { + qDebug().noquote() << mContent; + } +} + +/*! + * \brief Logger::flush + * \details Fluses the buffered logs of the content vContent in log type of vLogType. + * \param vContent - Log buffer + * \param vLogType - Log type + * \return number of lines flushed into log file + * \note This method is not thread-safe so is private and needs to be called by concurrentFlush + * Which uses QtConcurrent::run to run in thread and thread-safe. + */ +int Logger::flush(LogType vLogType) +{ + if ( ! checkThread() ) return 0; + + + //NOTE: the _cacheIndex has been (has to be) switched for the log to continue while we are in the temp thread to flush the log + CacheIndex cacheIndex = logSwitch(); + QString mContent; + QDateTime datetime = QDateTime::currentDateTime(); + int count = 0; + // - Add header - QString currentDate = QDate::currentDate().toString(_fileDateFormat); + QString currentDate = datetime.date().toString(_fileDateFormat); if ( _logFileNameDate != currentDate ) { if ( ! _logFileNameDate.isEmpty() ) { switch ( vLogType ) { case eLogAppED : mContent = _headerA; break; case eLogDebug : mContent = _headerD; break; - // case LogType::eLogTrtmt: // this type of log will never happen here. Only put here to make sure it is intentional. - default : mContent = _headerD; break; + default : break; //TODO create another cacheType enum } - mContent += "\r\n"; + mContent += _sepLines; } _logFileNameDate = currentDate; } + // - Add content + switch ( vLogType ) { + case eLogAppED : count = _cacheA[cacheIndex].count(); mContent += _cacheA[cacheIndex].join(_sepLines); _cacheA[cacheIndex].clear(); break; + case eLogDebug : count = _cacheD[cacheIndex].count(); mContent += _cacheD[cacheIndex].join(_sepLines); _cacheD[cacheIndex].clear(); break; + default : break; //TODO create another cacheType enum + } + // - Make log file name if (_logFileNameMode.isEmpty()) { _logFileNameMode = _logFileNameMode_init; - _logFileNameTime = QDateTime::currentDateTime().time().toString(_fileTimeFormat); + _logFileNameTime = datetime.time().toString(_fileTimeFormat); } + // - make the file name QString fileName; if ( ! gLongLogName ) { fileName = _logFileNameDate @@ -357,7 +444,7 @@ // case LogType::eLogTrtmt: // this type of log will never happen here. Only put here to make sure it is intentional. switch (vLogType) { case LogType::eLogAppED: { - // ------------------------------------------------------------------------ TODO: Improve : function declaration + // ------------------------------------------------------------------------ TODO: Improve : declare function fileName += _logFileNameExt[vLogType]; static QString oFileName; if( oFileName != fileName ) { @@ -372,7 +459,7 @@ } break; case LogType::eLogDebug: { - // ------------------------------------------------------------------------ TODO: Improve : function declaration + // ------------------------------------------------------------------------ TODO: Improve : declare function fileName += _logFileNameExt[vLogType]; static QString oFileName; if( oFileName != fileName ) { @@ -392,31 +479,45 @@ LOG_DEBUG(QString("Incorrect type of logging %1").arg(vLogType)); } - // - Add timestamp - if ( vTimestamp ) - mContent = QTime::currentTime().toString(_timeFormat) + _separator; - - // - Add the content - mContent += vContent; - // some messages like the version having the U08(uchar) parameters which converts to '\0' and causes problems in reading the log file. - mContent.replace('\0', "0"); - - // - Make the log path and write to log. + // - Make the log path QString logPathName = _logPathNames[vLogType]; if (logPathName.isEmpty()) logPathName = _logPathNames[eLogDebug]; _logFileName = logPathName + fileName; + // - Write to log bool isWritten = FileHandler::write(_logFileName, mContent + "\r\n", true); - if(!isWritten) emit didLogIOFail(); + if(! isWritten) emit didLogIOFail(); - // console out the log if enabled. - if (_enableConsoleOut) { - qDebug().noquote() << mContent; - } + return count; } /*! + * \brief Logger::concurrentFlushLogs + * \details Flushes the log buffer to the file in a separate thread + * \return always returns true for now. + * \note This method uses QtConcurrent to execute the flush method in a separate temp thread. + */ +bool Logger::concurrentFlushLog(LogType vLogType) +{ + emit didFlushLogs(true); + LOG_DEBUG("Flush Logs Starting"); + QFuture mFuture = QtConcurrent::run(this, &Logger::flush, vLogType); + _flushLogsWatcher.setFuture(mFuture); + return true; +} + +/*! + * \brief Logger::onRemoveLogs + * \details Remove old logs notification slot which logs result of remove. + */ +void Logger::onFlushLogs() +{ + LOG_DEBUG(tr("Flush Logs Ended: %1").arg(_flushLogsWatcher.result())); + emit didFlushLogs(false); +} + +/*! * \brief Logger::exportLogs * \details Exports the log files from log folder (Storage::Log_Base_Path_Name_Location) * into USB drive folder (Storage::USB_Mount_Point)