1 //===-- MICmnLog.cpp --------------------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // In-house headers:
11 #include "MICmnLog.h"
12 #include "MICmnLogMediumFile.h"
13 #include "MICmnResources.h"
14 #include "MIDriverMgr.h"
15 #include "MIUtilDateTimeStd.h"
16
17 //++
18 //------------------------------------------------------------------------------------
19 // Details: CMICmnLog constructor.
20 // Type: Method.
21 // Args: None.
22 // Return: None.
23 // Throws: None.
24 //--
CMICmnLog()25 CMICmnLog::CMICmnLog() : m_bEnabled(false), m_bInitializingATM(false) {
26 // Do not use this constructor, use Initialize()
27 }
28
29 //++
30 //------------------------------------------------------------------------------------
31 // Details: CMICmnLog destructor.
32 // Type: Method.
33 // Args: None.
34 // Return: None.
35 // Throws: None.
36 //--
~CMICmnLog()37 CMICmnLog::~CMICmnLog() { Shutdown(); }
38
39 //++
40 //------------------------------------------------------------------------------------
41 // Details: Initialize resources for *this Logger.
42 // Type: Method.
43 // Args: None.
44 // Return: MIstatus::success - Functional succeeded.
45 // MIstatus::failure - Functional failed.
46 // Throws: None.
47 //--
Initialize()48 bool CMICmnLog::Initialize() {
49 m_clientUsageRefCnt++;
50
51 if (m_bInitialized)
52 return MIstatus::success;
53
54 ClrErrorDescription();
55
56 // Mediums set inside because explicitly initing in MIDriverMain.cpp causes
57 // compile errors with CAtlFile
58 CMICmnLogMediumFile &rFileLog(CMICmnLogMediumFile::Instance());
59 bool bOk = RegisterMedium(rFileLog);
60 if (bOk) {
61 // Set the Log trace file's header
62 const CMIUtilString &rCR(rFileLog.GetLineReturn());
63 CMIUtilDateTimeStd date;
64 CMIUtilString msg;
65 msg = CMIUtilString::Format(
66 "%s\n", CMIDriverMgr::Instance().GetAppVersion().c_str());
67 CMIUtilString logHdr(msg);
68 msg = CMIUtilString::Format(MIRSRC(IDS_LOG_MSG_CREATION_DATE),
69 date.GetDate().c_str(), date.GetTime().c_str(),
70 rCR.c_str());
71 logHdr += msg;
72 msg =
73 CMIUtilString::Format(MIRSRC(IDS_LOG_MSG_FILE_LOGGER_PATH),
74 rFileLog.GetFileNamePath().c_str(), rCR.c_str());
75 logHdr += msg;
76
77 bOk = rFileLog.SetHeaderTxt(logHdr);
78
79 // Note log file medium's status is not available until we write at least
80 // once to the file (so just write the title 1st line)
81 m_bInitializingATM = true;
82 CMICmnLog::WriteLog(".");
83 if (!rFileLog.IsOk()) {
84 const CMIUtilString msg(
85 CMIUtilString::Format(MIRSRC(IDS_LOG_ERR_FILE_LOGGER_DISABLED),
86 rFileLog.GetErrorDescription().c_str()));
87 CMICmnLog::WriteLog(msg);
88 }
89 m_bInitializingATM = false;
90 }
91
92 m_bInitialized = bOk;
93
94 return bOk;
95 }
96
97 //++
98 //------------------------------------------------------------------------------------
99 // Details: Release resources for *this Logger.
100 // Type: Method.
101 // Args: None.
102 // Return: MIstatus::success - Functional succeeded.
103 // MIstatus::failure - Functional failed.
104 // Throws: None.
105 //--
Shutdown()106 bool CMICmnLog::Shutdown() {
107 if (--m_clientUsageRefCnt > 0)
108 return MIstatus::success;
109
110 if (!m_bInitialized)
111 return MIstatus::success;
112
113 ClrErrorDescription();
114
115 const bool bOk = UnregisterMediumAll();
116
117 m_bInitialized = bOk;
118
119 return bOk;
120 }
121
122 //++
123 //------------------------------------------------------------------------------------
124 // Details: Enabled or disable *this Logger from writing any data to registered
125 // clients.
126 // Type: Method.
127 // Args: vbYes - (R) True = Logger enabled, false = disabled.
128 // Return: MIstatus::success - Functional succeeded.
129 // MIstatus::failure - Functional failed.
130 // Throws: None.
131 //--
SetEnabled(const bool vbYes)132 bool CMICmnLog::SetEnabled(const bool vbYes) {
133 m_bEnabled = vbYes;
134
135 return MIstatus::success;
136 }
137
138 //++
139 //------------------------------------------------------------------------------------
140 // Details: Retrieve state whether *this Logger is enabled writing data to
141 // registered clients.
142 // Type: Method.
143 // Args: None.
144 // Return: True = Logger enable.
145 // False = disabled.
146 // Throws: None.
147 //--
GetEnabled() const148 bool CMICmnLog::GetEnabled() const { return m_bEnabled; }
149
150 //++
151 //------------------------------------------------------------------------------------
152 // Details: Unregister all the Mediums registered with *this Logger.
153 // Type: Method.
154 // Args: None.
155 // Return: MIstatus::success - Functional succeeded.
156 // MIstatus::failure - Functional failed.
157 // Throws: None.
158 //--
UnregisterMediumAll()159 bool CMICmnLog::UnregisterMediumAll() {
160 MapMediumToName_t::const_iterator it = m_mapMediumToName.begin();
161 for (; it != m_mapMediumToName.end(); it++) {
162 IMedium *pMedium = (*it).first;
163 pMedium->Shutdown();
164 }
165
166 m_mapMediumToName.clear();
167
168 return MIstatus::success;
169 }
170
171 //++
172 //------------------------------------------------------------------------------------
173 // Details: Register a Medium with *this Logger.
174 // Type: Method.
175 // Args: vrMedium - (R) The medium to register.
176 // Return: MIstatus::success - Functional succeeded.
177 // MIstatus::failure - Functional failed.
178 // Throws: None.
179 //--
RegisterMedium(const IMedium & vrMedium)180 bool CMICmnLog::RegisterMedium(const IMedium &vrMedium) {
181 if (HaveMediumAlready(vrMedium))
182 return MIstatus::success;
183
184 IMedium *pMedium = const_cast<IMedium *>(&vrMedium);
185 if (!pMedium->Initialize()) {
186 const CMIUtilString &rStrMedName(pMedium->GetName());
187 const CMIUtilString &rStrMedErr(pMedium->GetError());
188 SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LOG_MEDIUM_ERR_INIT),
189 rStrMedName.c_str(),
190 rStrMedErr.c_str()));
191 return MIstatus::failure;
192 }
193
194 MapPairMediumToName_t pr(pMedium, pMedium->GetName());
195 m_mapMediumToName.insert(pr);
196
197 return MIstatus::success;
198 }
199
200 //++
201 //------------------------------------------------------------------------------------
202 // Details: Query the Logger to see if a medium is already registered.
203 // Type: Method.
204 // Args: vrMedium - (R) The medium to query.
205 // Return: True - registered.
206 // False - not registered.
207 // Throws: None.
208 //--
HaveMediumAlready(const IMedium & vrMedium) const209 bool CMICmnLog::HaveMediumAlready(const IMedium &vrMedium) const {
210 IMedium *pMedium = const_cast<IMedium *>(&vrMedium);
211 const MapMediumToName_t::const_iterator it = m_mapMediumToName.find(pMedium);
212 return it != m_mapMediumToName.end();
213 }
214
215 //++
216 //------------------------------------------------------------------------------------
217 // Details: Unregister a medium from the Logger.
218 // Type: Method.
219 // Args: vrMedium - (R) The medium to unregister.
220 // Return: MIstatus::success - Functional succeeded.
221 // MIstatus::failure - Functional failed.
222 // Throws: None.
223 //--
UnregisterMedium(const IMedium & vrMedium)224 bool CMICmnLog::UnregisterMedium(const IMedium &vrMedium) {
225 IMedium *pMedium = const_cast<IMedium *>(&vrMedium);
226 m_mapMediumToName.erase(pMedium);
227
228 return MIstatus::success;
229 }
230
231 //++
232 //------------------------------------------------------------------------------------
233 // Details: The callee client uses this function to write to the Logger. The
234 // data to be
235 // written is given out to all the mediums registered. The verbosity
236 // type parameter
237 // indicates to the medium(s) the type of data or message given to it.
238 // The medium has
239 // modes of verbosity and depending on the verbosity set determines
240 // which writes
241 // go in to the logger.
242 // The logger must be initialized successfully before a write to any
243 // registered
244 // can be carried out.
245 // Type: Method.
246 // Args: vData - (R) The data to write to the logger.
247 // veType - (R) Verbosity type.
248 // Return: MIstatus::success - Functional succeeded.
249 // MIstatus::failure - Functional failed.
250 // Throws: None.
251 //--
Write(const CMIUtilString & vData,const ELogVerbosity veType)252 bool CMICmnLog::Write(const CMIUtilString &vData, const ELogVerbosity veType) {
253 if (!m_bInitialized && !m_bInitializingATM)
254 return MIstatus::success;
255 if (m_bRecursiveDive)
256 return MIstatus::success;
257 if (!m_bEnabled)
258 return MIstatus::success;
259
260 m_bRecursiveDive = true;
261
262 MIuint cnt = 0;
263 MIuint cntErr = 0;
264 {
265 MapMediumToName_t::const_iterator it = m_mapMediumToName.begin();
266 while (it != m_mapMediumToName.end()) {
267 IMedium *pMedium = (*it).first;
268 const CMIUtilString &rNameMedium = (*it).second;
269 MIunused(rNameMedium);
270 if (pMedium->Write(vData, veType))
271 cnt++;
272 else
273 cntErr++;
274
275 // Next
276 ++it;
277 }
278 }
279
280 bool bOk = MIstatus::success;
281 const MIuint mediumCnt = m_mapMediumToName.size();
282 if ((cnt == 0) && (mediumCnt > 0)) {
283 SetErrorDescription(MIRSRC(IDS_LOG_MEDIUM_ERR_WRITE_ANY));
284 bOk = MIstatus::failure;
285 }
286 if (bOk && (cntErr != 0)) {
287 SetErrorDescription(MIRSRC(IDS_LOG_MEDIUM_ERR_WRITE_MEDIUMFAIL));
288 bOk = MIstatus::failure;
289 }
290
291 m_bRecursiveDive = false;
292
293 return bOk;
294 }
295
296 //++
297 //------------------------------------------------------------------------------------
298 // Details: Short cut function call to write only to the Log file.
299 // The logger must be initialized successfully before a write to any
300 // registered
301 // can be carried out.
302 // Type: Static.
303 // Args: vData - (R) The data to write to the logger.
304 // Return: MIstatus::success - Functional succeeded.
305 // MIstatus::failure - Functional failed.
306 // Throws: None.
307 //--
WriteLog(const CMIUtilString & vData)308 bool CMICmnLog::WriteLog(const CMIUtilString &vData) {
309 return CMICmnLog::Instance().Write(vData, CMICmnLog::eLogVerbosity_Log);
310 }
311
312 //++
313 //------------------------------------------------------------------------------------
314 // Details: Retrieve a string detailing the last error.
315 // Type: Method.
316 // Args: None,
317 // Return: CMIUtilString.
318 // Throws: None.
319 //--
GetErrorDescription() const320 const CMIUtilString &CMICmnLog::GetErrorDescription() const {
321 return m_strMILastErrorDescription;
322 }
323
324 //++
325 //------------------------------------------------------------------------------------
326 // Details: Set the internal description of the last error.
327 // Type: Method.
328 // Args: (R) String containing a description of the last error.
329 // Return: None.
330 // Throws: None.
331 //--
SetErrorDescription(const CMIUtilString & vrTxt) const332 void CMICmnLog::SetErrorDescription(const CMIUtilString &vrTxt) const {
333 m_strMILastErrorDescription = vrTxt;
334 }
335
336 //++
337 //------------------------------------------------------------------------------------
338 // Details: Clear the last error.
339 // Type: None.
340 // Args: None.
341 // Return: None.
342 // Throws: None.
343 //--
ClrErrorDescription() const344 void CMICmnLog::ClrErrorDescription() const {
345 m_strMILastErrorDescription = CMIUtilString("");
346 }
347