/* * CXorayaLogPlugin.cpp * * Created on: 25.10.2011 * Author: Eisenhauer */ #include #include #include #include #include #include #include #include "interface_manager.h" #include "CXorayaLogPlugin.h" #include "global.h" #include "plugin_api.h" #include "IPluginExecutor.h" #define nSTR_LOGFILE_PATH "../data/current.log" CXorayaLogPlugin::CXorayaLogPlugin() :m_u32PluginId(0) ,m_boStopIOThread(false) ,m_iFd(0) ,m_u32LogMsgBufferCounter(0) ,m_xLogMsgBuffer(nLOG_MSG_BUFFER_SIZE) ,m_fctThreadProc(boost::bind(&CXorayaLogPlugin::vIoThreadProc,boost::ref(*this))) ,m_xIoThread(m_fctThreadProc) { int res = 0; int schedulerPolicy = SCHED_RR; sched_param sp; sp.sched_priority = tenPrio::nenLOW; if( (res = pthread_setschedparam(m_xIoThread.native_handle(), schedulerPolicy, &sp)) != 0 ) { ERROR_PRINT("pthread_setschedparam failed: %d errno: %d",res,errno); } if( (res = pthread_getschedparam(m_xIoThread.native_handle(),&schedulerPolicy,&sp)) != 0 ) { ERROR_PRINT("pthread_getschedparam failed: %d errno: %d",res,errno); } else { DEBUG_PRINT("disc IO thread prio: %d scheduler: %s" ,sp.sched_priority ,(schedulerPolicy==SCHED_OTHER)?"SCHED_OTHER": (schedulerPolicy==SCHED_FIFO)?"SCHED_FIFO": (schedulerPolicy==SCHED_RR)?"SCHED_RR":"other"); } enRotateLogfile(); } CXorayaLogPlugin::~CXorayaLogPlugin() { DEBUG_PRINT("entry"); DEBUG_PRINT("exit"); } void CXorayaLogPlugin::vRun() { x2e::status_t enRes; x2e::Log::queueFillLevel stRxFillLvl; x2e::Log::messageDescription stMsgDesc; x2e::Log::framePayload stFrmPl; // DEBUG_PRINT("entry"); enRes = m_pxIfMan->enGetQueueFillLevel(stRxFillLvl); if( x2e::OK != enRes ) { DEBUG_PRINT("abnormal exit"); return; } do { enRes = m_pxIfMan->enPeekMessage(stRxFillLvl,&stMsgDesc,&stFrmPl); if( enRes == x2e::OK ) { tstLogMessage stLogMessage; stLogMessage.u32TsLow = stMsgDesc.timestamp.getLow(); stLogMessage.u32TsHigh = stMsgDesc.timestamp.getHigh(); if( stFrmPl.frame.CAN.m_Identifier.isExtendedIdentifier() ) { stLogMessage.u32MsgId = stFrmPl.frame.CAN.m_Identifier.getExtendedIdentifier(); } else { stLogMessage.u32MsgId = stFrmPl.frame.CAN.m_Identifier.getStandardIdentifier(); } stLogMessage.i32Interface = stMsgDesc.trailer.getInterfaceID(); stLogMessage.u8Dir = static_cast(::nenRx); memcpy( (void*) stLogMessage.au8Data, (const void*) stFrmPl.frame.CAN.m_Payload.uint8, 8 ); vLogMessage(stLogMessage); } } while( enRes == x2e::OK ); // DEBUG_PRINT("normal exit"); } void CXorayaLogPlugin::vLogMessage(const tstLogMessage& stLogMessage) { m_xLogMsgBuffer.push_front(stLogMessage); } int32_t CXorayaLogPlugin::i32GetCanInterfaceHandle( void ) { return 0; } void CXorayaLogPlugin::vStopIOThread( void ) { DEBUG_PRINT("entry"); { boost::lock_guard xStopLock(m_xStopIOFlagMutex); m_boStopIOThread = true; } tstLogMessage stLogMessage; stLogMessage.u32MsgId = ~0x0; m_xLogMsgBuffer.push_front(stLogMessage); DEBUG_PRINT("exit"); } void CXorayaLogPlugin::vIoThreadProc() { bool boStop = false; while( !boStop ) { // DEBUG_PRINT("running"); tstLogMessage stLogMessage; m_xLogMsgBuffer.pop_back(&stLogMessage); // DEBUG_PRINT("Popped %s msg with id %#x from bounded buffer",(stLogMessage.u8Dir==0)?"RX":"TX",stLogMessage.u32MsgId); if( stLogMessage.u8Dir == 0 ) { stLogMessage.i32Interface = m_pxIfMan->i32GetInterfaceByLogIfId(stLogMessage.i32Interface); } // DEBUG_PRINT("Logging message with ID 0x%X",pstLogMessage->u32Id); if( (stLogMessage.u32MsgId != ~0x0U) && (stLogMessage.i32Interface != -1) ) { boost::lock_guard lock(m_xLogBufferMutex); if( (sizeof(tstLogMessage)*(m_u32LogMsgBufferCounter+1)) > nINT_BUFF_SIZE ) { // write log file if( m_iFd > 0 ) { write( m_iFd, reinterpret_cast(m_acLogBuffer), sizeof(tstLogMessage)*m_u32LogMsgBufferCounter ); } m_u32LogMsgBufferCounter = 0; } m_pxExec->vUploadLogMessage(stLogMessage); memcpy( (void*) (m_acLogBuffer+(sizeof(tstLogMessage)*m_u32LogMsgBufferCounter)),(void*)&stLogMessage,sizeof(stLogMessage)); m_u32LogMsgBufferCounter++; } // DEBUG_PRINT("sleeping"); { boost::lock_guard lock(m_xStopIOFlagMutex); boStop = m_boStopIOThread; } } if( m_iFd > 0 ) { close(m_iFd); } DEBUG_PRINT("exit"); } void CXorayaLogPlugin::vStop() { DEBUG_PRINT("entry"); vStopIOThread(); m_xIoThread.join(); DEBUG_PRINT("exit"); } tenRetCodes CXorayaLogPlugin::enGetLog(const char* pcReqFilename, char* pcRespFilename) { tenRetCodes enRetCode = nenOK; if( strcmp( pcReqFilename, nSTR_LOGFILE_PATH ) == 0) { enRetCode = enRotateLogfile(); strcpy(pcRespFilename,m_acLogfileName); } else { strcpy(pcRespFilename,pcReqFilename); } return enRetCode; } void CXorayaLogPlugin::vInit(void* pvExecutor, void* pvIfMan, int32_t i32Interface,uint32_t u32PluginId) { DEBUG_PRINT("entry"); if(!pvExecutor) { ERROR_PRINT("no main application provided"); return; } if(!pvIfMan) { ERROR_PRINT("no interface manager provided"); return; } m_pxExec = reinterpret_cast(pvExecutor); m_pxIfMan = reinterpret_cast(pvIfMan); m_u32PluginId = u32PluginId; DEBUG_PRINT("exit"); } void CXorayaLogPlugin::vInitLogfile() { time_t xEpochSeconds; xEpochSeconds = time(NULL); size_t xBytesWritten = 0; int iFlags = O_WRONLY | O_CREAT | O_TRUNC; mode_t xMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; m_iFd = open( nSTR_LOGFILE_PATH, iFlags, xMode ); if( m_iFd < 0 ) { ERROR_PRINT("Error opening file %s. Errno: %d",nSTR_LOGFILE_PATH,errno); return; } DEBUG_PRINT("Opened file %s",nSTR_LOGFILE_PATH); xBytesWritten = write( m_iFd, reinterpret_cast(&xEpochSeconds), sizeof(time_t) ); if( xBytesWritten != sizeof(time_t) ) { ERROR_PRINT("Error writing to file %s",nSTR_LOGFILE_PATH); } else { DEBUG_PRINT("Wrote timestamp to file %s",nSTR_LOGFILE_PATH); } } tenRetCodes CXorayaLogPlugin::enRotateLogfile() { tenRetCodes enRetCode = nenOK; time_t xTime; struct tm *pstTime = NULL; const char* pcLogFilenameFormat = "../data/x%Y%m%d_%H%M%S.log"; xTime = time(NULL); pstTime = localtime(&xTime); if( pstTime == NULL ) { perror("localtime"); enRetCode = nenERR_MOVELOG; return enRetCode; } if( strftime( m_acLogfileName, sizeof(m_acLogfileName), pcLogFilenameFormat, pstTime ) == 0 ) { ERROR_PRINT("Error creating new filename"); enRetCode = nenERR_MOVELOG; return enRetCode; } { boost::lock_guard lock(m_xLogBufferMutex); if( m_iFd > 0 ) { write( m_iFd, reinterpret_cast(m_acLogBuffer), sizeof(tstLogMessage)*m_u32LogMsgBufferCounter ); close(m_iFd); } m_u32LogMsgBufferCounter = 0; if( rename(nSTR_LOGFILE_PATH,m_acLogfileName) ) { ERROR_PRINT("Error renaming current log to %s",m_acLogfileName); enRetCode = nenERR_MOVELOG; return enRetCode; } vInitLogfile(); } return enRetCode; } static CXorayaLogPlugin g_sxLogPlugin; IPlugin* pxCreatePlugin(void* pvExecutor, void* pvIfMan, int32_t i32Interface, uint32_t u32PluginId) { DEBUG_PRINT("entry"); if( !pvIfMan ) { ERROR_PRINT("no interface manager provided"); return NULL; } if( !pvExecutor ) { ERROR_PRINT("no main application provided"); return NULL; } g_sxLogPlugin.vInit(pvExecutor, pvIfMan, i32Interface, u32PluginId); return &g_sxLogPlugin; } void vDestroyPlugin(IPlugin* pxPlugin) { DEBUG_PRINT("destroy log plugin entry"); if( pxPlugin ) { DEBUG_PRINT("destroy log plugin deleting instance"); reinterpret_cast(pxPlugin)->vStop(); } DEBUG_PRINT("destroy log plugin exit"); }