1 | // $Id: EsafMsgDispatcher.cc 2927 2011-06-16 18:02:41Z mabl $ |
---|
2 | // Author M. Pallavicini created Sep, 24 2004 |
---|
3 | |
---|
4 | /***************************************************************************** |
---|
5 | * ESAF: Euso Simulation and Analysis Framework * |
---|
6 | * * |
---|
7 | * Id: EsafMsgDispatcher * |
---|
8 | * Package: Base * |
---|
9 | * Coordinator: Marco.Pallavicini * |
---|
10 | * * |
---|
11 | *****************************************************************************/ |
---|
12 | |
---|
13 | //______________________________________________________________________________ |
---|
14 | // |
---|
15 | // ESAF Message Dispatcher |
---|
16 | // ======================= |
---|
17 | // |
---|
18 | // ESAF Message Dispatcher |
---|
19 | // This is a single to really dispatch the messages according to the |
---|
20 | // configuration. |
---|
21 | // The user can specify the default message level for screen and log file |
---|
22 | // Besides, the user can also change the message level for specific classes |
---|
23 | // that inherit from EsafMsgSource class |
---|
24 | // See EsafMsgSource.cc for further details |
---|
25 | // |
---|
26 | |
---|
27 | #include <iostream> |
---|
28 | #include <stdexcept> |
---|
29 | #include <unistd.h> |
---|
30 | #include "EsafMsgDispatcher.hh" |
---|
31 | #include <TSystem.h> |
---|
32 | |
---|
33 | ClassImp(EsafMsgDispatcher) |
---|
34 | |
---|
35 | EsafMsgDispatcher* EsafMsgDispatcher::fMe = 0; |
---|
36 | |
---|
37 | const char *const EsafMsgDispatcher::kEsc = "\033["; |
---|
38 | const char *const EsafMsgDispatcher::kReset = "\033[0m"; |
---|
39 | const char *const EsafMsgDispatcher::kBlack = "\033[30m"; |
---|
40 | const char *const EsafMsgDispatcher::kRed = "\033[31m"; |
---|
41 | const char *const EsafMsgDispatcher::kGreen = "\033[32m"; |
---|
42 | const char *const EsafMsgDispatcher::kYellow = "\033[33m"; |
---|
43 | const char *const EsafMsgDispatcher::kBlue = "\033[34m"; |
---|
44 | |
---|
45 | const char *const EsafMsgDispatcher::kMagenta = "\033[35m"; |
---|
46 | const char *const EsafMsgDispatcher::kCyan = "\033[36m"; |
---|
47 | const char *const EsafMsgDispatcher::kWhite = "\033[37m"; |
---|
48 | |
---|
49 | const char *const EsafMsgDispatcher::kBckBlack = "\033[40m"; |
---|
50 | const char *const EsafMsgDispatcher::kBckRed = "\033[41m"; |
---|
51 | const char *const EsafMsgDispatcher::kBckGreen = "\033[42m"; |
---|
52 | const char *const EsafMsgDispatcher::kBckYellow = "\033[43m"; |
---|
53 | const char *const EsafMsgDispatcher::kBckBlue = "\033[44m"; |
---|
54 | const char *const EsafMsgDispatcher::kBckMagenta= "\033[45m"; |
---|
55 | const char *const EsafMsgDispatcher::kBckCyan = "\033[46m"; |
---|
56 | const char *const EsafMsgDispatcher::kBckWhite = "\033[47m"; |
---|
57 | |
---|
58 | const char *const EsafMsgDispatcher::kUnderline = "\033[4m"; |
---|
59 | const char *const EsafMsgDispatcher::kBlink = "\033[5m"; |
---|
60 | const char *const EsafMsgDispatcher::kBright = "\033[1m"; |
---|
61 | const char *const EsafMsgDispatcher::kDark = "\033[2m"; |
---|
62 | |
---|
63 | const char * EsafMsgDispatcher::fgColors[] = { EsafMsgDispatcher::kReset, |
---|
64 | EsafMsgDispatcher::kBlue, |
---|
65 | EsafMsgDispatcher::kGreen, |
---|
66 | EsafMsgDispatcher::kYellow, |
---|
67 | EsafMsgDispatcher::kRed, |
---|
68 | EsafMsgDispatcher::kMagenta, |
---|
69 | EsafMsgDispatcher::kBckRed |
---|
70 | }; |
---|
71 | |
---|
72 | //______________________________________________________________________________ |
---|
73 | EsafMsgDispatcher::EsafMsgDispatcher() : EsafConfigurable(), |
---|
74 | fHeaderLenght(40), fIsScreenFlushed(kFALSE), fIsLogFlushed(kFALSE), |
---|
75 | fUseColors(kTRUE), |
---|
76 | fDefaultLogSeverity(EsafMsg::Info), fDefaultScreenSeverity(EsafMsg::Info) { |
---|
77 | // |
---|
78 | // ctor |
---|
79 | // |
---|
80 | } |
---|
81 | |
---|
82 | //______________________________________________________________________________ |
---|
83 | void EsafMsgDispatcher::LoadConfig() { |
---|
84 | // |
---|
85 | // |
---|
86 | // |
---|
87 | |
---|
88 | string screen = Conf()->GetStr("EsafMsgDispatcher.fScreenSeverity"); |
---|
89 | string logfile = Conf()->GetStr("EsafMsgDispatcher.fLogFileSeverity"); |
---|
90 | |
---|
91 | if ( screen == "Debug" ) |
---|
92 | fDefaultScreenSeverity = EsafMsg::Debug; |
---|
93 | else if ( screen == "Info" ) |
---|
94 | fDefaultScreenSeverity = EsafMsg::Info; |
---|
95 | else if ( screen == "Warning" ) |
---|
96 | fDefaultScreenSeverity = EsafMsg::Warning; |
---|
97 | else if ( screen == "Error" ) |
---|
98 | fDefaultScreenSeverity = EsafMsg::Error; |
---|
99 | else if ( screen == "Panic" ) |
---|
100 | fDefaultScreenSeverity = EsafMsg::Panic; |
---|
101 | else if ( screen == "None" ) |
---|
102 | fDefaultScreenSeverity = EsafMsg::None; |
---|
103 | else |
---|
104 | throw runtime_error("Invalid severity type in EsafMsgDispatcher::EsafMsgDispatcher()"); |
---|
105 | |
---|
106 | if ( logfile == "Debug" ) |
---|
107 | fDefaultLogSeverity = EsafMsg::Debug; |
---|
108 | else if ( logfile == "Info" ) |
---|
109 | fDefaultLogSeverity = EsafMsg::Info; |
---|
110 | else if ( logfile == "Warning" ) |
---|
111 | fDefaultLogSeverity = EsafMsg::Warning; |
---|
112 | else if ( screen == "Error" ) |
---|
113 | fDefaultLogSeverity = EsafMsg::Error; |
---|
114 | else if ( logfile == "Panic" ) |
---|
115 | fDefaultLogSeverity = EsafMsg::Panic; |
---|
116 | else if ( logfile == "None" ) |
---|
117 | fDefaultLogSeverity = EsafMsg::None; |
---|
118 | else |
---|
119 | throw runtime_error("Invalid severity type in EsafMsgDispatcher::EsafMsgDispatcher()"); |
---|
120 | |
---|
121 | |
---|
122 | fUseColors = Conf()->GetBool("EsafMsgDispatcher.fUseColors"); |
---|
123 | } |
---|
124 | |
---|
125 | |
---|
126 | //______________________________________________________________________________ |
---|
127 | void EsafMsgDispatcher::OpenLog( const char* name ) { |
---|
128 | // |
---|
129 | // Open a new log file |
---|
130 | // |
---|
131 | if (fLogFile.is_open()) fLogFile.close(); |
---|
132 | |
---|
133 | string ext = ".log"; |
---|
134 | |
---|
135 | if ( name ) |
---|
136 | fLogFileName = name; |
---|
137 | else |
---|
138 | fLogFileName = Conf()->GetStr("EsafMsgDispatcher.fLogFileName"); |
---|
139 | |
---|
140 | if (fLogFileName.rfind(ext) != (fLogFileName.size()-ext.size())) |
---|
141 | fLogFileName += ext; |
---|
142 | |
---|
143 | TString log = fLogFileName.c_str(); |
---|
144 | gSystem->ExpandPathName(log); |
---|
145 | fLogFileName = log.Data(); |
---|
146 | |
---|
147 | |
---|
148 | fLogFile.open( fLogFileName.c_str() ); |
---|
149 | if (!fLogFile.is_open()) |
---|
150 | throw runtime_error("Cannot open message output file "+fLogFileName); |
---|
151 | |
---|
152 | } |
---|
153 | |
---|
154 | //______________________________________________________________________________ |
---|
155 | EsafMsgDispatcher::~EsafMsgDispatcher() { |
---|
156 | fLogFile.close(); |
---|
157 | } |
---|
158 | |
---|
159 | //______________________________________________________________________________ |
---|
160 | EsafMsgDispatcher* EsafMsgDispatcher::Get() { |
---|
161 | |
---|
162 | // singleton |
---|
163 | |
---|
164 | if (!fMe) |
---|
165 | fMe = new EsafMsgDispatcher(); |
---|
166 | return fMe; |
---|
167 | } |
---|
168 | |
---|
169 | //______________________________________________________________________________ |
---|
170 | const char* MsgStringType[] = {"", |
---|
171 | "Debug: ", |
---|
172 | "Info: ", |
---|
173 | "Warning: ", |
---|
174 | "Error: ", |
---|
175 | "Exception:", |
---|
176 | "Panic: " |
---|
177 | }; |
---|
178 | //______________________________________________________________________________ |
---|
179 | void EsafMsgDispatcher::Dispatch( EsafMsg& msg, Bool_t endline, Bool_t ProcCount) { |
---|
180 | |
---|
181 | // dispatch message |
---|
182 | // Message is written on screen and/or log file according to severity |
---|
183 | // and parameter settings |
---|
184 | |
---|
185 | // check if message must be displayed on screen |
---|
186 | // default threshold is used, unless user has changed this specific sender (class name) |
---|
187 | bool doScreen = (msg.GetSeverity() >= fDefaultScreenSeverity); |
---|
188 | |
---|
189 | map<string,EsafMsg::MsgSeverity>::const_iterator it; |
---|
190 | if ( ( it = fUserMap.find( msg.GetSender() ) ) != fUserMap.end() ) { |
---|
191 | doScreen = ( msg.GetSeverity() >= it->second ); |
---|
192 | } |
---|
193 | |
---|
194 | |
---|
195 | // prepare the header |
---|
196 | string header; |
---|
197 | |
---|
198 | header = string(MsgStringType[msg.GetSeverity()])+"["+msg.GetSender()+"]"; |
---|
199 | |
---|
200 | if ( header.size() < (size_t)fHeaderLenght) |
---|
201 | header.resize(fHeaderLenght,' '); |
---|
202 | |
---|
203 | Int_t progress = 0; |
---|
204 | |
---|
205 | if (ProcCount) { |
---|
206 | progress = msg.GetProgress(); // Current status of counting progress |
---|
207 | cout << "\r"; // Move cursor to the line beginning |
---|
208 | fIsScreenFlushed = kFALSE; // Always print info message |
---|
209 | } |
---|
210 | |
---|
211 | if ( doScreen ) { |
---|
212 | if ( !fIsScreenFlushed ) { |
---|
213 | if ( fUseColors && isatty(fileno(stdout))) { |
---|
214 | cout << fgColors[msg.GetSeverity()]; |
---|
215 | cout << header; |
---|
216 | |
---|
217 | cout << EsafMsgDispatcher::kReset; |
---|
218 | } else { |
---|
219 | cout << header; |
---|
220 | } |
---|
221 | } |
---|
222 | |
---|
223 | // Standard output |
---|
224 | |
---|
225 | cout << msg.GetText(); |
---|
226 | |
---|
227 | // Printing status of progress message |
---|
228 | |
---|
229 | if (ProcCount) { |
---|
230 | if (progress != -1) cout << setw(4) << progress << "%"; |
---|
231 | else cout << " ... "; |
---|
232 | if (progress >= 100) endline = kTRUE; // for the end of counting |
---|
233 | } |
---|
234 | |
---|
235 | cout << flush; |
---|
236 | |
---|
237 | if ( endline ) |
---|
238 | cout << endl; |
---|
239 | |
---|
240 | fIsScreenFlushed = !endline; |
---|
241 | } |
---|
242 | |
---|
243 | if ( fLogFile.is_open()) { |
---|
244 | // check if message must be displayed on log file |
---|
245 | // default threshold is used, unless user has changed this specific sender (class name) |
---|
246 | bool doLog = ( msg.GetSeverity() >= fDefaultLogSeverity ); |
---|
247 | if ( ( it = fUserMap.find( msg.GetSender() ) ) != fUserMap.end() ) { |
---|
248 | doLog = ( msg.GetSeverity() >= it->second ); |
---|
249 | } |
---|
250 | |
---|
251 | if ( doLog ) { |
---|
252 | if ( !fIsLogFlushed ) |
---|
253 | fLogFile << header; |
---|
254 | |
---|
255 | // Normally write to file |
---|
256 | |
---|
257 | if (!ProcCount) fLogFile << msg.GetText() << flush; |
---|
258 | |
---|
259 | // In the beginning of counting write all information |
---|
260 | |
---|
261 | else if (ProcCount && !progress) |
---|
262 | fLogFile << msg.GetText() << " " << progress << "%" << flush; |
---|
263 | |
---|
264 | // Writing only counting progress to file |
---|
265 | |
---|
266 | else if (ProcCount && progress > 0) |
---|
267 | fLogFile << ".." << progress << "%" << flush; |
---|
268 | |
---|
269 | if ( endline ) |
---|
270 | fLogFile << endl; |
---|
271 | |
---|
272 | fIsLogFlushed = !endline; |
---|
273 | } |
---|
274 | } |
---|
275 | |
---|
276 | if ( msg.GetSeverity() >= EsafMsg::Exception ) { |
---|
277 | // copy the original msg to the internal one |
---|
278 | msg.Copy(fException); |
---|
279 | // clear the incoming message |
---|
280 | msg.Clear(); |
---|
281 | |
---|
282 | throw fException; |
---|
283 | } |
---|
284 | } |
---|