blob: fc4c3141915b5cdc41e1dee0dfd0d975d8e5e716 [file] [log] [blame]
//===-- MICmnLog.cpp --------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// In-house headers:
#include "MICmnLog.h"
#include "MICmnLogMediumFile.h"
#include "MICmnResources.h"
#include "MIDriverMgr.h"
#include "MIUtilDateTimeStd.h"
//++
// Details: CMICmnLog constructor.
// Type: Method.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmnLog::CMICmnLog() : 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() { 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() {
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);
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() {
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() 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() {
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);
return it != m_mapMediumToName.end();
}
//++
// 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() 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() const {
m_strMILastErrorDescription = CMIUtilString("");
}