Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TProofLog.cxx
Go to the documentation of this file.
1// @(#)root/proof:$Id$
2// Author: G. Ganis 31/08/06
3
4/*************************************************************************
5 * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TProofLog
13\ingroup proofkernel
14
15Implementation of the PROOF session log handler.
16
17*/
18
19#include "TFile.h"
20#include "TMacro.h"
21#include "TProofLog.h"
22#include "TProofMgr.h"
23#include "TObjString.h"
24#include "TUrl.h"
25
27
28////////////////////////////////////////////////////////////////////////////////
29/// Constructor.
30
31TProofLog::TProofLog(const char *stag, const char *url, TProofMgr *mgr)
32 : TNamed(stag, url)
33{
35 fFILE = 0;
36 fElem = new TList;
37 fElem->SetOwner();
38 fMgr = mgr;
39 // Set a fake starting time
41 // Extract real starting time
42 TString st(stag);
43 Int_t idx = st.Index('-');
44 if (idx != kNPOS) {
45 st.Remove(0, idx+1);
46 idx = st.Index('-');
47 if (idx != kNPOS) {
48 st.Remove(idx);
49 if (st.IsDigit()) {
50 fStartTime.Set(st.Atoi());
51 }
52 }
53 }
54}
55
56////////////////////////////////////////////////////////////////////////////////
57/// Destructor.
58
60{
62}
63
64////////////////////////////////////////////////////////////////////////////////
65/// Add new entry to the list of elements.
66
67TProofLogElem *TProofLog::Add(const char *ord, const char *url)
68{
69 TProofLogElem *ple = new TProofLogElem(ord, url, this);
70 fElem->Add(ple);
71 // Done
72 return ple;
73}
74
75////////////////////////////////////////////////////////////////////////////////
76/// Retrieve the content of the log file associated with worker 'ord'.
77/// If 'ord' is "*" (default), all the workers are retrieved. If 'all'
78/// is true, the whole files are retrieved; else a max of
79/// fgMaxTransferSize (about 1000 lines) per file is read, starting from
80/// the end (i.e. the last ~1000 lines).
81/// The received buffer is added to the file fname, if the latter is defined.
82/// If opt == TProofLog::kGrep only the lines containing 'pattern' are
83/// retrieved (remote grep functionality); to filter out a pattern 'pat' use
84/// pattern = "-v pat".
85/// Return 0 on success, -1 in case of any error.
86
88 const char *fname, const char *pattern)
89{
90 // Validate inputs
91 if (opt == TProofLog::kGrep && (!pattern || strlen(pattern) <= 0)) {
92 Error("Retrieve", "option 'Grep' requires a pattern");
93 return -1;
94 }
95
96 Int_t nel = (ord[0] == '*') ? fElem->GetSize() : 1;
97 // Iterate over the elements
98 TIter nxe(fElem);
99 TProofLogElem *ple = 0;
100 Int_t nd = 0, nb = 0;
101 TString msg;
102 while ((ple = (TProofLogElem *) nxe())) {
103 if (ord[0] == '*' || !strcmp(ord, ple->GetName())) {
104 if (ple->Retrieve(opt, pattern) != 0) {
105 nb++;
106 } else {
107 nd++;
108 }
109 Float_t frac = ((Float_t)nd + (Float_t)nb) * 100. / (Float_t)nel;
110 msg.Form("Retrieving logs: %d ok, %d not ok (%.0f%% processed)\r", nd, nb, frac);
111 Prt(msg.Data(), kFALSE);
112 }
113 }
114 Prt("\n");
115
116 // Save to file, if required
117 if (fname)
118 Save(ord, fname);
119
120 // Done
121 return 0;
122}
123
124////////////////////////////////////////////////////////////////////////////////
125/// Display the content associated with worker 'ord' from line 'from'
126/// to line 'to' inclusive. A negative value
127/// for 'from' indicates lines counted from the end (tail action); 'to'
128/// is ignored in such a case.
129/// If 'ord' is "*" (default), all the workers are displayed.
130
131void TProofLog::Display(const char *ord, Int_t from, Int_t to)
132{
133 TString msg;
134 if (ord[0] == '*') {
135 Int_t nel = (fElem) ? fElem->GetSize() : 0;
136 // Write global header
137 msg.Form("\n// --------- Displaying PROOF Session logs --------\n"
138 "// Server: %s \n// Session: %s \n// # of elements: %d \n"
139 "// ------------------------------------------------\n\n",
140 GetTitle(), GetName(), nel);
141 Prt(msg.Data());
142 }
143 // Iterate over the elements
144 TIter nxe(fElem);
145 TProofLogElem *ple = 0;
146 while ((ple = (TProofLogElem *) nxe())) {
147 if (ord[0] == '*' || !strcmp(ord, ple->GetName()))
148 ple->Display(from, to);
149 }
150 if (ord[0] == '*')
151 // Write global tail
152 Prt("// --------- End of PROOF Session logs ---------\n");
153}
154
155////////////////////////////////////////////////////////////////////////////////
156/// Print head info about the content
157
159{
160 Int_t nel = (fElem) ? fElem->GetSize() : 0;
161 // Write global header
162 fprintf(stderr, "// --------- PROOF Session logs object --------\n");
163 fprintf(stderr, "// Server: %s \n", GetTitle());
164 fprintf(stderr, "// Session: %s \n", GetName());
165 fprintf(stderr, "// # of elements: %d \n", nel);
166 fprintf(stderr, "// --------------------------------------------\n");
167
168 // Iterate over the elements
169 TIter nxe(fElem);
170 TProofLogElem *ple = 0;
171 while ((ple = (TProofLogElem *) nxe()))
172 ple->Print(opt);
173
174 // Write global tail
175 fprintf(stderr, "// --------------------------------------------\n");
176}
177
178////////////////////////////////////////////////////////////////////////////////
179/// Special printing procedure
180
181void TProofLog::Prt(const char *what, Bool_t newline)
182{
183 if (what) {
184 if (LogToBox()) {
185 // Send to log box:
186 EmitVA("Prt(const char*)", 2, what, kFALSE);
187 } else {
188 FILE *where = (fFILE) ? (FILE *)fFILE : stderr;
189 fputs(what, where);
190 if (newline) fputc('\n', where);
191 }
192 }
193}
194
195////////////////////////////////////////////////////////////////////////////////
196/// Save the content associated with worker 'ord' to finel 'fname'.
197/// If 'ord' is "*" (default), the log from all the workers is saved.
198/// If 'opt' is "a" the file is open in append mode; otherwise the file
199/// is truncated.
200
201Int_t TProofLog::Save(const char *ord, const char *fname, Option_t *opt)
202{
203 // Make sure we got a file name
204 if (!fname) {
205 Warning("Save", "filename undefined - do nothing");
206 return -1;
207 }
208
209 // Open file to write header
210 // Check, if the option is to append
211 TString option = opt;
212 option.ToLower();
213 FILE *fout=0;
214 if (option.Contains("a")){
215 fout = fopen(fname, "a");
216 } else {
217 fout = fopen(fname, "w");
218 }
219 if (!fout) {
220 Warning("Save", "file could not be opened - do nothing");
221 return -1;
222 }
223 fFILE = (void *) fout;
224
225 TString msg;
226 if (ord[0] == '*') {
227 Int_t nel = (fElem) ? fElem->GetSize() : 0;
228 // Write global header
229 msg.Form("\n// --------- Displaying PROOF Session logs --------\n"
230 "// Server: %s \n// Session: %s \n// # of elements: %d \n"
231 "// ------------------------------------------------\n\n",
232 GetTitle(), GetName(), nel);
233 Prt(msg.Data());
234 }
235
236 // Iterate over the elements
237 TIter nxe(fElem);
238 TProofLogElem *ple = 0;
239 while ((ple = (TProofLogElem *) nxe())) {
240 if (ord[0] == '*' || !strcmp(ord, ple->GetName()))
241 ple->Display(0);
242 }
243
244 if (ord[0] == '*') {
245 // Write global tail
246 Prt("// --------- End of PROOF Session logs ---------\n");
247 }
248
249 // Close file
250 fclose(fout);
251 fFILE = 0;
252
253 // Done
254 return 0;
255}
256
257////////////////////////////////////////////////////////////////////////////////
258/// Search lines containing 'txt', starting from line 'from'.
259/// Print the lines where this happens.
260
261Int_t TProofLog::Grep(const char *txt, Int_t from)
262{
263 if (!txt || strlen(txt) <= 0) {
264 Warning("Grep", "text to be searched for is undefined - do nothing");
265 return -1;
266 }
267
268 Int_t nel = (fElem) ? fElem->GetSize() : 0;
269 // Write global header
270 TString msg;
271 msg.Form("\n// --------- Search in PROOF Session logs --------\n"
272 "// Server: %s \n// Session: %s \n// # of elements: %d \n"
273 "// Text searched for: \"%s\"", GetTitle(), GetName(), nel, txt);
274 Prt(msg.Data());
275 if (from > 1) {
276 msg.Form("// starting from line %d \n", from);
277 } else {
278 msg = "\n";
279 }
280 Prt(msg.Data());
281 Prt("// ------------------------------------------------\n");
282
283 // Iterate over the elements
284 TIter nxe(fElem);
285 TProofLogElem *ple = 0;
286 while ((ple = (TProofLogElem *) nxe())) {
287 TString res;
288 Int_t nf = ple->Grep(txt, res, from);
289 if (nf > 0) {
290 msg.Form("// Ord: %s - line(s): %s\n", ple->GetName(), res.Data());
291 Prt(msg.Data());
292 }
293 }
294
295 Prt("// ------------------------------------------------\n");
296
297 // Done
298 return 0;
299}
300
301////////////////////////////////////////////////////////////////////////////////
302/// Set max transfer size.
303
305{
307}
308
309//
310// TProofLogElem
311//
312
313Long64_t TProofLogElem::fgMaxTransferSize = 100000; // about 1000 lines
314
315////////////////////////////////////////////////////////////////////////////////
316/// Constructor.
317
318TProofLogElem::TProofLogElem(const char *ord, const char *url,
319 TProofLog *logger)
320 : TNamed(ord, url)
321{
322 fLogger = logger;
323 fMacro = new TMacro;
324 fSize = -1;
325 fFrom = -1;
326 fTo = -1;
327
328 //Note the role here, don't redo at each call of Display()
329 if (strstr(GetTitle(), "worker-")) {
330 fRole = "worker";
331 } else {
332 if (strchr(GetName(), '.')) {
333 fRole = "submaster";
334 } else {
335 fRole = "master";
336 }
337 }
338}
339
340////////////////////////////////////////////////////////////////////////////////
341/// Destructor.
342
344{
346}
347
348////////////////////////////////////////////////////////////////////////////////
349/// Get max transfer size.
350
352{
353 return fgMaxTransferSize;
354}
355
356////////////////////////////////////////////////////////////////////////////////
357/// Set max transfer size.
358
360{
361 fgMaxTransferSize = maxsz;
362}
363
364////////////////////////////////////////////////////////////////////////////////
365/// Retrieve the content of the associated file. The approximate number
366/// of lines to be retrieved is given by 'lines', with the convention that
367/// 0 means 'all', a positive number means the first 'lines' and a negative
368/// number means the last '-lines'. Default is -1000.
369/// If opt == TProofLog::kGrep only the lines containing 'pattern' are
370/// retrieved (remote grep functionality); to filter out a pattern 'pat' use
371/// pattern = "-v pat".
372/// Return 0 on success, -1 in case of any error.
373
375{
376 // Make sure we have a reference manager
377 if (!fLogger->fMgr || !fLogger->fMgr->IsValid()) {
378 Warning("Retrieve", "No reference manager: corruption?");
379 return -1;
380 }
381
382 // Print some info on the file
383 if (gDebug >= 2) {
384 Info("Retrieve", "Retrieving from ordinal %s file %s with pattern %s",
385 GetName(), GetTitle(), (pattern ? pattern : "(no pattern)"));
386 }
387
388 // Determine offsets
389 if (opt == TProofLog::kAll) {
390 // Re-read everything
391 fFrom = 0;
392 fTo = -1;
393 if (gDebug >= 1)
394 Info("Retrieve", "Retrieving the whole file");
395 } else if (opt == TProofLog::kLeading) {
396 // Read leading part
397 fFrom = 0;
399 if (gDebug >= 1)
400 Info("Retrieve", "Retrieving the leading %lld lines of file", fTo);
401 } else if (opt == TProofLog::kGrep) {
402 // Retrieve lines containing 'pattern', which must be defined
403 if (!pattern || strlen(pattern) <= 0) {
404 Error("Retrieve", "option 'Grep' requires a pattern");
405 return -1;
406 }
407 if (gDebug >= 1)
408 Info("Retrieve", "Retrieving only lines filtered with %s", pattern);
409 } else {
410 // Read trailing part
412 fTo = -1;
413 if (gDebug >= 1)
414 Info("Retrieve", "Retrieving the last %lld lines of file", -fFrom);
415 }
416
417 // Reset the macro
419 fMacro = new TMacro;
420
421 // Size to be read
422 Long64_t len = (fTo > fFrom) ? fTo - fFrom : -1;
423
424 // Readout the buffer
425 TObjString *os = 0;
426 if (fLogger->fMgr) {
427 TString fileName = GetTitle();
428 if (fileName.Contains("__igprof.pp__")) {
429 // File is an IgProf log. Override all patterns and preprocess it
430 if (gDebug >= 1)
431 Info("Retrieve", "Retrieving analyzed IgProf performance profile");
432 TString analyzeAndFilter = \
433 "|( T=`mktemp` && cat > \"$T\" ; igprof-analyse -d -g \"$T\" ; rm -f \"$T\" )";
434 if (pattern && (*pattern == '|'))
435 analyzeAndFilter.Append(pattern);
436 os = fLogger->fMgr->ReadBuffer(fileName.Data(), analyzeAndFilter.Data());
437 }
438 else if (opt == TProofLog::kGrep)
439 os = fLogger->fMgr->ReadBuffer(fileName.Data(), pattern);
440 else
441 os = fLogger->fMgr->ReadBuffer(fileName.Data(), fFrom, len);
442 }
443 if (os) {
444 // Loop over lines
445 TString ln;
446 Ssiz_t from = 0;
447 while (os->String().Tokenize(ln, from, "\n"))
448 fMacro->AddLine(ln.Data());
449
450 // Cleanup
451 delete os;
452 }
453
454 // Done
455 return 0;
456}
457
458////////////////////////////////////////////////////////////////////////////////
459/// Display the current content starting from line 'from' to line 'to'
460/// inclusive.
461/// A negative value for 'from' indicates lines counted from the end
462/// (tail action); 'to' is ignored in such a case.
463/// TProofLog::Prt is called to display: the location (screen, file, box)
464/// is defined there.
465/// Return 0 on success, -1 in case of any error.
466
468{
469 Int_t nls = (fMacro->GetListOfLines()) ?
470 fMacro->GetListOfLines()->GetSize() : 0;
471
472 // Starting line
473 Int_t i = 0;
474 Int_t ie = (to > -1 && to < nls) ? to : nls;
475 if (from > 1) {
476 if (from <= nls)
477 i = from - 1;
478 } else if (from < 0) {
479 // Tail action
480 if (-from <= nls)
481 i = nls + from;
482 ie = nls;
483 }
484 // Write header
485 TString msg;
486 Prt("// --------- Start of element log -----------------\n");
487 msg.Form("// Ordinal: %s (role: %s)\n", GetName(), fRole.Data());
488 Prt(msg.Data());
489 // Separate out the submaster path, if any
490 TString path(GetTitle());
491 Int_t ic = path.Index(",");
492 if (ic != kNPOS) {
493 TString subm(path);
494 path.Remove(0, ic+1);
495 subm.Remove(ic);
496 msg.Form("// Submaster: %s \n", subm.Data());
497 Prt(msg.Data());
498 }
499 msg.Form("// Path: %s \n// # of retrieved lines: %d ", path.Data(), nls);
500 Prt(msg.Data());
501 if (i > 0 || ie < nls) {
502 msg.Form("(displaying lines: %d -> %d)\n", i+1, ie);
503 } else {
504 msg = "\n";
505 }
506 Prt(msg.Data());
507 Prt("// ------------------------------------------------\n");
508 // Write lines
509 msg = "";
510 if (fMacro->GetListOfLines()) {
512 TObjString *os = 0;
513 Int_t kk = 0;
514 while ((os = (TObjString *) nxl())) {
515 kk++;
516 if (kk > i) {
517 if (msg.Length() < 100000) {
518 if (msg.Length() > 0) msg += "\n";
519 msg += os->GetName();
520 } else {
521 Prt(msg.Data());
522 msg = "";
523 }
524 }
525 if (kk > ie) break;
526 }
527 }
528 if (msg.Length() > 0) Prt(msg.Data());
529 // Write tail
530 Prt("// --------- End of element log -------------------\n\n");
531}
532
533////////////////////////////////////////////////////////////////////////////////
534/// Print a line with the relevant info.
535
537{
538 Int_t nls = (fMacro->GetListOfLines()) ?
539 fMacro->GetListOfLines()->GetSize() : 0;
540 const char *role = (strstr(GetTitle(), "worker-")) ? "worker" : "master";
541
542 fprintf(stderr, "Ord: %s Host: Role: %s lines: %d\n", GetName(), role, nls);
543}
544
545////////////////////////////////////////////////////////////////////////////////
546/// Special printing procedure.
547
548void TProofLogElem::Prt(const char *what)
549{
550 if (fLogger)
551 fLogger->Prt(what);
552}
553
554////////////////////////////////////////////////////////////////////////////////
555/// Search lines containing 'txt', starting from line 'from'. Return
556/// their blanck-separated list into 'res'.
557/// Return the number of lines found, or -1 in case of error.
558
559Int_t TProofLogElem::Grep(const char *txt, TString &res, Int_t from)
560{
561 Int_t nls = (fMacro->GetListOfLines()) ?
562 fMacro->GetListOfLines()->GetSize() : 0;
563
564 Int_t nf = 0;
565 Int_t i = (from > 0) ? (from - 1) : 0;
566 for( ; i < nls; i++) {
568 if (os) {
569 if (strstr(os->GetName(), txt)) {
570 if (res.Length() > 0)
571 res += " ";
572 res += (i + 1);
573 nf++;
574 }
575 }
576 }
577
578 // Done
579 return nf;
580}
#define SafeDelete(p)
Definition RConfig.hxx:537
const Ssiz_t kNPOS
Definition RtypesCore.h:124
const Bool_t kFALSE
Definition RtypesCore.h:101
long long Long64_t
Definition RtypesCore.h:80
float Float_t
Definition RtypesCore.h:57
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:364
Int_t gDebug
Definition TROOT.cxx:592
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
void Set()
Set Date/Time to current time as reported by the system.
Definition TDatime.cxx:289
A doubly linked list.
Definition TList.h:38
virtual void Add(TObject *obj)
Definition TList.h:81
virtual TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:357
Class supporting a collection of lines with C++ code.
Definition TMacro.h:31
virtual TObjString * AddLine(const char *text)
Add line with text in the list of lines of this macro.
Definition TMacro.cxx:141
TList * GetListOfLines() const
Definition TMacro.h:51
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
virtual const char * GetTitle() const
Returns title of object.
Definition TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
Collectable string class.
Definition TObjString.h:28
const char * GetName() const
Returns name of object.
Definition TObjString.h:38
TString & String()
Definition TObjString.h:48
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:949
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:963
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:937
static Long64_t fgMaxTransferSize
Definition TProofLog.h:89
static Long64_t GetMaxTransferSize()
Get max transfer size.
Long64_t fFrom
Definition TProofLog.h:85
Int_t Grep(const char *txt, TString &res, Int_t from=0)
Search lines containing 'txt', starting from line 'from'.
Long64_t fTo
Definition TProofLog.h:86
void Print(Option_t *opt=0) const
Print a line with the relevant info.
TProofLogElem(const char *ord, const char *url, TProofLog *logger)
Constructor.
Long64_t fSize
Definition TProofLog.h:84
TMacro * fMacro
Definition TProofLog.h:83
Int_t Retrieve(TProofLog::ERetrieveOpt opt=TProofLog::kTrailing, const char *pattern=0)
Retrieve the content of the associated file.
TString fRole
Definition TProofLog.h:87
void Display(Int_t from=0, Int_t to=-1)
Display the current content starting from line 'from' to line 'to' inclusive.
virtual ~TProofLogElem()
Destructor.
static void SetMaxTransferSize(Long64_t maxsz)
Set max transfer size.
TProofLog * fLogger
Definition TProofLog.h:82
void Prt(const char *what)
Special printing procedure.
Implementation of the PROOF session log handler.
Definition TProofLog.h:32
TProofLogElem * Add(const char *ord, const char *url)
Add new entry to the list of elements.
Definition TProofLog.cxx:67
TList * fElem
Definition TProofLog.h:41
void Print(Option_t *opt=0) const
Print head info about the content.
static void SetMaxTransferSize(Long64_t maxsz)
Set max transfer size.
void Prt(const char *what, Bool_t newline=kTRUE)
Special printing procedure.
Int_t Grep(const char *txt, Int_t from=0)
Search lines containing 'txt', starting from line 'from'.
TProofMgr * fMgr
Definition TProofLog.h:39
void Display(const char *ord="*", Int_t from=-10, Int_t to=-1)
Display the content associated with worker 'ord' from line 'from' to line 'to' inclusive.
TProofLog(const char *stag, const char *url, TProofMgr *mgr)
Constructor.
Definition TProofLog.cxx:31
TDatime fStartTime
Definition TProofLog.h:42
Int_t Save(const char *ord="*", const char *fname=0, Option_t *opt="w")
Save the content associated with worker 'ord' to finel 'fname'.
Int_t Retrieve(const char *ord="*", TProofLog::ERetrieveOpt opt=TProofLog::kTrailing, const char *fname=0, const char *pattern=0)
Retrieve the content of the log file associated with worker 'ord'.
Definition TProofLog.cxx:87
friend class TProofLogElem
Definition TProofLog.h:34
virtual ~TProofLog()
Destructor.
Definition TProofLog.cxx:59
Bool_t LogToBox()
Definition TProofLog.h:71
void SetLogToBox(Bool_t lgbox=kFALSE)
Definition TProofLog.h:70
void * fFILE
Definition TProofLog.h:40
The PROOF manager interacts with the PROOF server coordinator to create or destroy a PROOF session,...
Definition TProofMgr.h:43
virtual Bool_t IsValid() const
Definition TProofMgr.h:77
virtual TObjString * ReadBuffer(const char *, Long64_t, Int_t)
Definition TProofMgr.h:97
void EmitVA(const char *signal_name, Int_t, const T &... params)
Emit a signal with a varying number of arguments.
Definition TQObject.h:100
Basic string class.
Definition TString.h:136
Ssiz_t Length() const
Definition TString.h:410
void ToLower()
Change string to lower-case.
Definition TString.cxx:1150
Int_t Atoi() const
Return integer value of string.
Definition TString.cxx:1946
const char * Data() const
Definition TString.h:369
Bool_t IsDigit() const
Returns true if all characters in string are digits (0-9) or white spaces, i.e.
Definition TString.cxx:1788
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition TString.cxx:2222
TString & Remove(Ssiz_t pos)
Definition TString.h:673
TString & Append(const char *cs)
Definition TString.h:564
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2314
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:624
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:639
static const char * what
Definition stlLoader.cc:6