//===-- MICmnLog.cpp --------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// //++ // File: MICmnLog.cpp // // Overview: CMICmnLog implementation. // // Environment: Compilers: Visual C++ 12. // gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 // Libraries: See MIReadmetxt. // // Copyright: None. //-- // In-house headers: #include "MICmnLog.h" #include "MICmnLogMediumFile.h" #include "MIDriverMgr.h" #include "MICmnResources.h" #include "MIUtilDateTimeStd.h" //++ ------------------------------------------------------------------------------------ // Details: CMICmnLog constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmnLog::CMICmnLog( void ) : m_bEnabled( false ) , m_bInitializingATM( false ) { // Do not use this constructor, use Initialize() } //++ ------------------------------------------------------------------------------------ // Details: CMICmnLog destructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmnLog::~CMICmnLog( void ) { Shutdown(); } //++ ------------------------------------------------------------------------------------ // Details: Initialize resources for *this Logger. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLog::Initialize( void ) { m_clientUsageRefCnt++; if( m_bInitialized ) return MIstatus::success; ClrErrorDescription(); // Mediums set inside because explicitly initing in MIDriverMain.cpp causes compile errors with CAtlFile CMICmnLogMediumFile & rFileLog( CMICmnLogMediumFile::Instance() ); bool bOk = RegisterMedium( rFileLog ); bOk = bOk && SetEnabled( true ); if( bOk ) { // Set the Log trace file's header const CMIUtilString & rCR( rFileLog.GetLineReturn() ); CMIUtilDateTimeStd date; CMIUtilString msg; msg = CMIUtilString::Format( "%s\n", CMIDriverMgr::Instance().GetAppVersion().c_str() ); CMIUtilString logHdr( msg ); msg = CMIUtilString::Format( MIRSRC( IDS_LOG_MSG_CREATION_DATE ), date.GetDate().c_str(), date.GetTime().c_str(), rCR.c_str() ); logHdr += msg; msg = CMIUtilString::Format( MIRSRC( IDS_LOG_MSG_FILE_LOGGER_PATH ), rFileLog.GetFileNamePath().c_str(), rCR.c_str() ); logHdr += msg; bOk = rFileLog.SetHeaderTxt( logHdr ); // Note log file medium's status is not available until we write at least once to the file (so just write the title 1st line) m_bInitializingATM = true; CMICmnLog::WriteLog( "." ); if( !rFileLog.IsOk() ) { const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LOG_ERR_FILE_LOGGER_DISABLED ), rFileLog.GetErrorDescription().c_str() ) ); CMICmnLog::WriteLog( msg ); } m_bInitializingATM = false; } m_bInitialized = bOk; return bOk; } //++ ------------------------------------------------------------------------------------ // Details: Release resources for *this Logger. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLog::Shutdown( void ) { if( --m_clientUsageRefCnt > 0 ) return MIstatus::success; if( !m_bInitialized ) return MIstatus::success; ClrErrorDescription(); const bool bOk = UnregisterMediumAll(); m_bInitialized = bOk; return bOk; } //++ ------------------------------------------------------------------------------------ // Details: Enabled or disable *this Logger from writing any data to registered clients. // Type: Method. // Args: vbYes - (R) True = Logger enabled, false = disabled. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLog::SetEnabled( const bool vbYes ) { m_bEnabled = vbYes; return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Retrieve state whether *this Logger is enabled writing data to registered clients. // Type: Method. // Args: None. // Return: True = Logger enable. // False = disabled. // Throws: None. //-- bool CMICmnLog::GetEnabled( void ) const { return m_bEnabled; } //++ ------------------------------------------------------------------------------------ // Details: Unregister all the Mediums registered with *this Logger. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLog::UnregisterMediumAll( void ) { MapMediumToName_t::const_iterator it = m_mapMediumToName.begin(); for( ; it != m_mapMediumToName.end( ); it++ ) { IMedium * pMedium = (*it).first; pMedium->Shutdown(); } m_mapMediumToName.clear(); return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Register a Medium with *this Logger. // Type: Method. // Args: vrMedium - (R) The medium to register. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLog::RegisterMedium( const IMedium & vrMedium ) { if( HaveMediumAlready( vrMedium ) ) return MIstatus::success; IMedium * pMedium = const_cast< IMedium * >( &vrMedium ); if( !pMedium->Initialize() ) { const CMIUtilString & rStrMedName( pMedium->GetName() ); const CMIUtilString & rStrMedErr( pMedium->GetError() ); SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LOG_MEDIUM_ERR_INIT ), rStrMedName.c_str(), rStrMedErr.c_str() ) ); return MIstatus::failure; } MapPairMediumToName_t pr( pMedium, pMedium->GetName() ); m_mapMediumToName.insert( pr ); return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Query the Logger to see if a medium is already registered. // Type: Method. // Args: vrMedium - (R) The medium to query. // Return: True - registered. // False - not registered. // Throws: None. //-- bool CMICmnLog::HaveMediumAlready( const IMedium & vrMedium ) const { IMedium * pMedium = const_cast< IMedium * >( &vrMedium ); const MapMediumToName_t::const_iterator it = m_mapMediumToName.find( pMedium ); if( it != m_mapMediumToName.end() ) return true; return false; } //++ ------------------------------------------------------------------------------------ // Details: Unregister a medium from the Logger. // Type: Method. // Args: vrMedium - (R) The medium to unregister. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLog::UnregisterMedium( const IMedium & vrMedium ) { IMedium * pMedium = const_cast< IMedium * >( &vrMedium ); m_mapMediumToName.erase( pMedium ); return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: The callee client uses this function to write to the Logger. The data to be // written is given out to all the mediums registered. The verbosity type parameter // indicates to the medium(s) the type of data or message given to it. The medium has // modes of verbosity and depending on the verbosity set determines which writes // go in to the logger. // The logger must be initialized successfully before a write to any registered // can be carried out. // Type: Method. // Args: vData - (R) The data to write to the logger. // veType - (R) Verbosity type. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLog::Write( const CMIUtilString & vData, const ELogVerbosity veType ) { if( !m_bInitialized && !m_bInitializingATM ) return MIstatus::success; if( m_bRecursiveDive ) return MIstatus::success; if( !m_bEnabled ) return MIstatus::success; m_bRecursiveDive = true; MIuint cnt = 0; MIuint cntErr = 0; { MapMediumToName_t::const_iterator it = m_mapMediumToName.begin(); while( it != m_mapMediumToName.end() ) { IMedium * pMedium = (*it).first; const CMIUtilString & rNameMedium = (*it).second; MIunused( rNameMedium ); if( pMedium->Write( vData, veType ) ) cnt++; else cntErr++; // Next ++it; } } bool bOk = MIstatus::success; const MIuint mediumCnt = m_mapMediumToName.size(); if( (cnt == 0) && (mediumCnt > 0) ) { SetErrorDescription( MIRSRC( IDS_LOG_MEDIUM_ERR_WRITE_ANY ) ); bOk = MIstatus::failure; } if( bOk && (cntErr != 0) ) { SetErrorDescription( MIRSRC( IDS_LOG_MEDIUM_ERR_WRITE_MEDIUMFAIL ) ); bOk = MIstatus::failure; } m_bRecursiveDive = false; return bOk; } //++ ------------------------------------------------------------------------------------ // Details: Short cut function call to write only to the Log file. // The logger must be initialized successfully before a write to any registered // can be carried out. // Type: Static. // Args: vData - (R) The data to write to the logger. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLog::WriteLog( const CMIUtilString & vData ) { return CMICmnLog::Instance().Write( vData, CMICmnLog::eLogVerbosity_Log ); } //++ ------------------------------------------------------------------------------------ // Details: Retrieve a string detailing the last error. // Type: Method. // Args: None, // Return: CMIUtilString. // Throws: None. //-- const CMIUtilString & CMICmnLog::GetErrorDescription( void ) const { return m_strMILastErrorDescription; } //++ ------------------------------------------------------------------------------------ // Details: Set the internal description of the last error. // Type: Method. // Args: (R) String containing a description of the last error. // Return: None. // Throws: None. //-- void CMICmnLog::SetErrorDescription( const CMIUtilString & vrTxt ) const { m_strMILastErrorDescription = vrTxt; } //++ ------------------------------------------------------------------------------------ // Details: Clear the last error. // Type: None. // Args: None. // Return: None. // Throws: None. //-- void CMICmnLog::ClrErrorDescription( void ) const { m_strMILastErrorDescription = CMIUtilString( "" ); }