1 martin 1.59 //%LICENSE////////////////////////////////////////////////////////////////
|
2 martin 1.60 //
|
3 martin 1.59 // Licensed to The Open Group (TOG) under one or more contributor license
4 // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
5 // this work for additional information regarding copyright ownership.
6 // Each contributor licenses this file to you under the OpenPegasus Open
7 // Source License; you may not use this file except in compliance with the
8 // License.
|
9 martin 1.60 //
|
10 martin 1.59 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
|
16 martin 1.60 //
|
17 martin 1.59 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
|
19 martin 1.60 //
|
20 martin 1.59 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
21 martin 1.60 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22 martin 1.59 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27 martin 1.60 //
|
28 martin 1.59 //////////////////////////////////////////////////////////////////////////
|
29 mike 1.2 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
|
32 sage 1.4 #include <Pegasus/Common/Config.h>
|
33 thilo.boehm 1.54 #include <Pegasus/Common/Constants.h>
|
34 mike 1.2 #include <Pegasus/Common/Tracer.h>
|
35 r.kieninger 1.49 #include <Pegasus/Common/TraceFileHandler.h>
36 #include <Pegasus/Common/TraceLogHandler.h>
|
37 thilo.boehm 1.52 #include <Pegasus/Common/TraceMemoryHandler.h>
|
38 kumpf 1.3 #include <Pegasus/Common/Thread.h>
39 #include <Pegasus/Common/System.h>
|
40 sushma.fernandes 1.45 #include <Pegasus/Common/HTTPMessage.h>
|
41 thilo.boehm 1.52 #include <Pegasus/Common/StringConversion.h>
|
42 thilo.boehm 1.54 #include <Pegasus/Common/FileSystem.h>
|
43 r.kieninger 1.49
|
44 mike 1.2 PEGASUS_USING_STD;
45
46 PEGASUS_NAMESPACE_BEGIN
47
|
48 kumpf 1.53 /**
49 String constants for naming the various Trace components.
50 These strings will used when turning on tracing for the respective
51 components. The component list must be kept in sync with the
52 TraceComponentId enumeration.
53
|
54 thilo.boehm 1.56 The tracer uses the _traceComponentMask in form of a 64bit field to mask
55 the user configured components.
56 Please ensure that no more than 64 components are specified in the
57 TRACE_COMPONENT_LIST.
58
|
59 kumpf 1.53 The following example shows the usage of trace component names.
60 The setTraceComponents method is used to turn on tracing for the
61 components: Config and Repository. The component names are passed as a
62 comma separated list.
63
64 Tracer::setTraceComponents("Config,Repository");
65 */
|
66 karl 1.67 char const* Tracer::TRACE_COMPONENT_LIST[] =
|
67 kumpf 1.53 {
|
68 thilo.boehm 1.58 "Xml",
|
69 kumpf 1.53 "XmlIO",
70 "Http",
71 "Repository",
72 "Dispatcher",
73 "OsAbstraction",
74 "Config",
|
75 thilo.boehm 1.58 "IndicationHandler",
|
76 kumpf 1.53 "Authentication",
77 "Authorization",
78 "UserManager",
79 "Shutdown",
80 "Server",
81 "IndicationService",
82 "MessageQueueService",
83 "ProviderManager",
84 "ObjectResolution",
85 "WQL",
86 "CQL",
87 "Thread",
88 "CIMExportRequestDispatcher",
89 "SSL",
90 "ControlProvider",
91 "CIMOMHandle",
92 "L10N",
93 "ExportClient",
94 "Listener",
95 "DiscardedData",
96 "ProviderAgent",
97 kumpf 1.53 "IndicationFormatter",
98 "StatisticalData",
99 "CMPIProvider",
100 "IndicationGeneration",
101 "IndicationReceipt",
102 "CMPIProviderInterface",
103 "WsmServer",
|
104 a.rachapudi 1.62 "LogMessages",
|
105 marek 1.65 "WMIMapperConsumer",
106 "InternalProvider"
|
107 kumpf 1.53 };
108
|
109 karl 1.67 // Set the number of defined components
110 const Uint32 Tracer::_NUM_COMPONENTS =
111 sizeof(TRACE_COMPONENT_LIST)/sizeof(TRACE_COMPONENT_LIST[0]);
112
|
113 r.kieninger 1.49
114 // Defines the value values for trace facilities
115 // Keep the TRACE_FACILITY_LIST in sync with the TRACE_FACILITY_INDEX,
116 // so that the index matches the according string in the list.
117 char const* Tracer::TRACE_FACILITY_LIST[] =
118 {
119 "File",
120 "Log",
|
121 thilo.boehm 1.52 "Memory",
|
122 r.kieninger 1.49 0
123 };
|
124 kumpf 1.61
|
125 r.kieninger 1.49
|
126 mike 1.2 // Set the trace levels
127 // These levels will be compared against a trace level mask to determine
|
128 chip 1.20 // if a specific trace level is enabled
|
129 mike 1.2
|
130 marek 1.48 const Uint32 Tracer::LEVEL0 = 0;
|
131 mike 1.2 const Uint32 Tracer::LEVEL1 = (1 << 0);
132 const Uint32 Tracer::LEVEL2 = (1 << 1);
133 const Uint32 Tracer::LEVEL3 = (1 << 2);
134 const Uint32 Tracer::LEVEL4 = (1 << 3);
|
135 marek 1.48 const Uint32 Tracer::LEVEL5 = (1 << 4);
|
136 mike 1.2
137 // Set the Enter and Exit messages
|
138 kumpf 1.13 const char Tracer::_METHOD_ENTER_MSG[] = "Entering method";
139 const char Tracer::_METHOD_EXIT_MSG[] = "Exiting method";
|
140 mike 1.2
141 // Initialize singleton instance of Tracer
142 Tracer* Tracer::_tracerInstance = 0;
|
143 chip 1.20
|
144 mike 1.2 // Set component separator
145 const char Tracer::_COMPONENT_SEPARATOR = ',';
146
147 // Set the line maximum
148 const Uint32 Tracer::_STRLEN_MAX_UNSIGNED_INT = 21;
149
|
150 kumpf 1.3 // Set the max PID and Thread ID Length
|
151 mike 1.39 const Uint32 Tracer::_STRLEN_MAX_PID_TID = 21;
|
152 kumpf 1.3
|
153 r.kieninger 1.30 // Initialize public indicator of trace state
|
154 thilo.boehm 1.56 Boolean Tracer::_traceOn=false;
155 Uint32 Tracer::_traceLevelMask=0;
156 Uint64 Tracer::_traceComponentMask=(Uint64)0;
|
157 r.kieninger 1.30
|
158 mike 1.2 ////////////////////////////////////////////////////////////////////////////////
159 // Tracer constructor
160 // Constructor is private to preclude construction of Tracer objects
161 // Single Instance of Tracer is maintained for each process.
162 ////////////////////////////////////////////////////////////////////////////////
163 Tracer::Tracer()
|
164 thilo.boehm 1.56 : _traceMemoryBufferSize(PEGASUS_TRC_DEFAULT_BUFFER_SIZE_KB),
|
165 r.kieninger 1.49 _traceFacility(TRACE_FACILITY_FILE),
|
166 thilo.boehm 1.54 _runningOOP(false),
|
167 r.kieninger 1.49 _traceHandler(0)
|
168 mike 1.2 {
|
169 thilo.boehm 1.56
170 // The tracer uses a 64bit field to mask the user configured components.
171 // This assert ensures that no more than 64 components are specified in the
172 // TRACE_COMPONENT_LIST.
173 PEGASUS_ASSERT(_NUM_COMPONENTS <= 64);
174
|
175 r.kieninger 1.49 // Instantiate trace handler according to configured facility
|
176 thilo.boehm 1.52 _setTraceHandler(_traceFacility);
|
177 mike 1.2 }
|
178 chip 1.20
|
179 mike 1.2 ////////////////////////////////////////////////////////////////////////////////
180 //Tracer destructor
181 ////////////////////////////////////////////////////////////////////////////////
182 Tracer::~Tracer()
183 {
|
184 thilo.boehm 1.52 delete _traceHandler;
|
185 mike 1.2 delete _tracerInstance;
186 }
187
188
189 ////////////////////////////////////////////////////////////////////////////////
|
190 r.kieninger 1.49 //Factory function for the trace handler instances.
191 ////////////////////////////////////////////////////////////////////////////////
|
192 thilo.boehm 1.52 void Tracer::_setTraceHandler( Uint32 traceFacility )
|
193 r.kieninger 1.49 {
|
194 thilo.boehm 1.52 TraceHandler * oldTrcHandler = _traceHandler;
195
|
196 r.kieninger 1.49 switch(traceFacility)
197 {
198 case TRACE_FACILITY_LOG:
|
199 thilo.boehm 1.52 _traceFacility = TRACE_FACILITY_LOG;
200 _traceHandler = new TraceLogHandler();
201 break;
202
203 case TRACE_FACILITY_MEMORY:
204 _traceFacility = TRACE_FACILITY_MEMORY;
|
205 thilo.boehm 1.54 _traceHandler = new TraceMemoryHandler();
|
206 r.kieninger 1.49 break;
207
208 case TRACE_FACILITY_FILE:
209 default:
|
210 thilo.boehm 1.52 _traceFacility = TRACE_FACILITY_FILE;
211 _traceHandler = new TraceFileHandler();
|
212 r.kieninger 1.49 }
|
213 thilo.boehm 1.54 delete oldTrcHandler;
214 }
215
216 ////////////////////////////////////////////////////////////////////////////////
217 // Validates if a given file path if it is eligible for writing traces.
218 ////////////////////////////////////////////////////////////////////////////////
219 Boolean Tracer::_isValidTraceFile(String fileName)
220 {
221 // Check if the file path is a directory
222 FileSystem::translateSlashes(fileName);
223 if (FileSystem::isDirectory(fileName))
224 {
225 return false;
226 }
227
228 // Check if the file exists and is writable
229 if (FileSystem::exists(fileName))
230 {
231 return FileSystem::canWrite(fileName);
232 }
233
234 thilo.boehm 1.54 // Check if directory is writable
235 Uint32 index = fileName.reverseFind('/');
|
236 r.kieninger 1.49
|
237 thilo.boehm 1.54 if (index != PEG_NOT_FOUND)
238 {
239 String dirName = fileName.subString(0,index);
240
241 if (dirName.size() == 0)
242 {
243 dirName = "/";
244 }
245
246 if (!FileSystem::isDirectory(dirName))
247 {
248 return false;
249 }
250
251 return FileSystem::canWrite(dirName);
252 }
253
254 String currentDir;
255
256 // Check if there is permission to write in the
257 // current working directory
258 thilo.boehm 1.54 FileSystem::getCurrentDirectory(currentDir);
259
260 return FileSystem::canWrite(currentDir);
|
261 r.kieninger 1.49 }
262
263 ////////////////////////////////////////////////////////////////////////////////
|
264 mike 1.2 //Traces the given message - Overloaded for including FileName and Line number
265 ////////////////////////////////////////////////////////////////////////////////
266 void Tracer::_trace(
267 const char* fileName,
268 const Uint32 lineNum,
|
269 kumpf 1.53 const TraceComponentId traceComponent,
|
270 mike 1.2 const char* fmt,
271 va_list argList)
272 {
273 char* message;
|
274 marek 1.42 //
275 // Allocate memory for the message string
276 // Needs to be updated if additional info is added
277 //
278 message = new char[strlen(fileName) +
279 _STRLEN_MAX_UNSIGNED_INT + (_STRLEN_MAX_PID_TID * 2) + 8];
280 sprintf(
281 message,
|
282 kumpf 1.51 "[%u:%s:%s:%u]: ",
|
283 marek 1.42 System::getPID(),
284 Threads::id().buffer,
285 fileName,
286 lineNum);
|
287 mike 1.2
|
288 marek 1.42 _trace(traceComponent, message, fmt, argList);
289 delete [] message;
|
290 mike 1.2 }
291
292 ////////////////////////////////////////////////////////////////////////////////
|
293 kumpf 1.5 //Traces the message in the given CIMException object.
294 ////////////////////////////////////////////////////////////////////////////////
295 void Tracer::_traceCIMException(
|
296 kumpf 1.53 const TraceComponentId traceComponent,
|
297 kumpf 1.40 const CIMException& cimException)
|
298 thilo.boehm 1.56 {
|
299 kumpf 1.43 // get the CIMException trace message string
300 CString traceMsg =
301 TraceableCIMException(cimException).getTraceDescription().getCString();
302 // trace the string
303 _traceCString(traceComponent, "", (const char*) traceMsg);
|
304 mike 1.2 }
305
|
306 marek 1.64 char* Tracer::_formatHexDump(
307 char* targetBuffer,
308 const char * data,
309 Uint32 size)
310 {
311 unsigned char* p = (unsigned char*)data;
312 unsigned char buf[16];
313 size_t n = 0;
314 int len;
315
316 for (size_t i = 0, col = 0; i < size; i++)
317 {
318 unsigned char c = p[i];
319 buf[n++] = c;
320
321 if (col == 0)
322 {
323 len = sprintf(targetBuffer, "%06X ", (unsigned int)i);
324 targetBuffer+=len;
325 }
326
327 marek 1.64 len = sprintf(targetBuffer, "%02X", c);
328 targetBuffer+=len;
329
|
330 ashok.pathak 1.66 if ( ((col+1) & 3) == 0 )
|
331 marek 1.64 {
332 *targetBuffer = ' ';
333 targetBuffer++;
334 }
335 if (col + 1 == sizeof(buf) || i + 1 == size)
336 {
337 for (size_t j = col + 1; j < sizeof(buf); j++)
338 {
339 targetBuffer[0]=' ';
340 targetBuffer[1]=' ';
341 targetBuffer[2]=' ';
342 targetBuffer += 3;
343 }
344 for (size_t j = 0; j < n; j++)
345 {
346 c = buf[j];
347
348 if (c >= ' ' && c <= '~')
349 {
350 *targetBuffer = c;
351 }
352 marek 1.64 else
353 {
354 *targetBuffer = '.';
355 }
356 targetBuffer++;
357 }
358 *targetBuffer = '\n';
359 targetBuffer++;
360 n = 0;
361 }
362 if (col + 1 == sizeof(buf))
363 {
364 col = 0;
365 }
366 else
367 {
368 col++;
369 }
370 }
371 *targetBuffer = '\n';
372 targetBuffer++;
373 marek 1.64 return targetBuffer;
374 }
375
376 SharedArrayPtr<char> Tracer::traceFormatChars(
377 const Buffer& data,
378 bool binary)
379 {
380 static char start[]="\n### Begin of binary data\n";
381 static char end[]="\n### End of binary data\n";
382 static char msg[] ="\n### Parts of data omitted. Only first 768 bytes and "\
383 "last 256 bytes shown. For complete information, use traceLevel 5.\n\n";
384
385 SharedArrayPtr<char> outputBuffer(
386 new char[(10*data.size()+sizeof(start)+sizeof(end)+sizeof(msg))]);
387
388 char* target = outputBuffer.get();
389 size_t size = data.size();
390
391 if (0 == size)
392 {
393 target[0] = 0;
394 marek 1.64 return outputBuffer;
395 }
396 if (binary)
397 {
398 memcpy(target,&(start[0]),sizeof(start)-1);
399 target+=sizeof(start)-1;
400 // If there are more then 1024 bytes of binary data and the trace level
401 // is not at highest level(5), we only trace part of the data and not
402 // everything
403 if ((_traceLevelMask & Tracer::LEVEL5) || (size <= 1024))
404 {
405 target=_formatHexDump(target, data.getData(), size);
406
407 }
408 else
409 {
410 target=_formatHexDump(target, data.getData(), 768);
411
412 memcpy(target, &(msg[0]), sizeof(msg)-1);
413 target+=sizeof(msg)-1;
414
415 marek 1.64 target=_formatHexDump(target, &(data.getData()[size-256]), 256);
416 }
417 memcpy(target,&(end[0]),sizeof(end));
418 }
419 else
420 {
421 memcpy(target, data.getData(), size);
422 target[size] = 0;
423 }
424 return outputBuffer;
425 }
426
|
427 sushma.fernandes 1.45 SharedArrayPtr<char> Tracer::getHTTPRequestMessage(
428 const Buffer& requestMessage)
429 {
430 const Uint32 requestSize = requestMessage.size();
431
|
432 marek 1.64 // Check if requestMessage contains "application/x-openpegasus"
433 // and if true format the the requestBuf as HexDump for tracing
434 //
435 // Binary is only possible on localConnect and doesn't have Basic
436 // authorization for that reason
437 if (strstr(requestMessage.getData(),"application/x-openpegasus"))
438 {
439 return traceFormatChars(requestMessage,true);
440 }
441
|
442 sushma.fernandes 1.45 // Make a copy of the request message.
443 SharedArrayPtr<char>
444 requestBuf(new char [requestSize + 1]);
445 strncpy(requestBuf.get(), requestMessage.getData(), requestSize);
446 requestBuf.get()[requestSize] = 0;
447
448 //
449 // Check if requestBuffer contains a Basic authorization header.
450 // If true, suppress the user/passwd info in the request buffer.
451 //
452 char* sep;
453 const char* line = requestBuf.get();
454
|
455 marek 1.69 while ((sep = HTTPMessage::findSeparator(line)) && (line != sep))
|
456 sushma.fernandes 1.45 {
457 if (HTTPMessage::expectHeaderToken(line, "Authorization") &&
458 HTTPMessage::expectHeaderToken(line, ":") &&
459 HTTPMessage::expectHeaderToken(line, "Basic"))
460 {
461 // Suppress the user/passwd info
462 HTTPMessage::skipHeaderWhitespace(line);
|
463 thilo.boehm 1.56 for ( char* userpass = (char*)line ;
464 userpass < sep;
|
465 marek 1.63 *userpass = 'X', userpass++)
466 {
467 }
|
468 sushma.fernandes 1.45 break;
469 }
470
471 line = sep + ((*sep == '\r') ? 2 : 1);
472 }
473 return requestBuf;
474 }
475
|
476 mike 1.2 ////////////////////////////////////////////////////////////////////////////////
|
477 marek 1.42 //Traces method entry and exit
|
478 mike 1.2 ////////////////////////////////////////////////////////////////////////////////
|
479 marek 1.42 void Tracer::_traceMethod(
|
480 mike 1.2 const char* fileName,
481 const Uint32 lineNum,
|
482 kumpf 1.53 const TraceComponentId traceComponent,
|
483 marek 1.42 const char* methodEntryExit,
484 const char* method)
|
485 mike 1.2 {
486 char* message;
487
|
488 marek 1.42 //
489 // Allocate memory for the message string
490 // Needs to be updated if additional info is added
491 //
492 // assume Method entry/exit string 15 characters long
493 // +1 space character
494 message = new char[ strlen(fileName) +
|
495 thilo.boehm 1.56 _STRLEN_MAX_UNSIGNED_INT + (_STRLEN_MAX_PID_TID * 2) + 8
|
496 marek 1.42 + 16];
497
498 sprintf(
499 message,
|
500 kumpf 1.51 "[%u:%s:%s:%u]: %s ",
|
501 marek 1.42 System::getPID(),
502 Threads::id().buffer,
503 fileName,
504 lineNum,
505 methodEntryExit);
|
506 kumpf 1.61
|
507 marek 1.42 _traceCString(traceComponent, message, method);
|
508 carson.hovey 1.37
|
509 marek 1.42 delete [] message;
|
510 mike 1.2 }
511
512 ////////////////////////////////////////////////////////////////////////////////
|
513 marek 1.42 //Called by all trace interfaces with variable arguments
514 //to log message to trace file
|
515 mike 1.2 ////////////////////////////////////////////////////////////////////////////////
516 void Tracer::_trace(
|
517 kumpf 1.53 const TraceComponentId traceComponent,
|
518 mike 1.2 const char* message,
519 const char* fmt,
520 va_list argList)
521 {
522 char* msgHeader;
|
523 thilo.boehm 1.52 Uint32 msgLen;
524 Uint32 usec,sec;
|
525 mike 1.2
526 // Get the current system time and prepend to message
|
527 thilo.boehm 1.52 System::getCurrentTimeUsec(sec,usec);
|
528 mike 1.2
|
529 kumpf 1.3 //
|
530 chip 1.20 // Allocate messageHeader.
|
531 kumpf 1.3 // Needs to be updated if additional info is added
532 //
|
533 mday 1.19
|
534 mike 1.2 // Construct the message header
|
535 chip 1.20 // The message header is in the following format
|
536 mike 1.2 // timestamp: <component name> [file name:line number]
|
537 thilo.boehm 1.52 //
|
538 kumpf 1.61 // Format string length calculation:
|
539 thilo.boehm 1.52 // 11(sec)+ 2('s-')+11(usec)+4('us: ')+1(' ')+1(\0) = 30
|
540 joyce.j 1.26 if (*message != '\0')
|
541 mike 1.2 {
|
542 kumpf 1.40 msgHeader = new char [strlen(message) +
|
543 thilo.boehm 1.52 strlen(TRACE_COMPONENT_LIST[traceComponent]) + 30];
|
544 kumpf 1.40
|
545 thilo.boehm 1.52 msgLen = sprintf(msgHeader, "%us-%uus: %s %s", sec, usec,
|
546 kumpf 1.40 TRACE_COMPONENT_LIST[traceComponent], message);
|
547 mike 1.2 }
548 else
549 {
|
550 kumpf 1.3 //
|
551 chip 1.20 // Allocate messageHeader.
|
552 kumpf 1.3 // Needs to be updated if additional info is added
553 //
|
554 thilo.boehm 1.56 // Format string length calculation:
|
555 thilo.boehm 1.52 // 11(sec)+2('s-')+11(usec)+4('us: ')+
556 // +2(' [')+1(':')+3(']: ')+1(\0) = 35
|
557 thilo.boehm 1.56 msgHeader = new char[2 * _STRLEN_MAX_PID_TID +
|
558 thilo.boehm 1.52 strlen(TRACE_COMPONENT_LIST[traceComponent]) + 35];
559
560 msgLen = sprintf(msgHeader, "%us-%uus: %s [%u:%s]: ", sec, usec,
|
561 kumpf 1.61 TRACE_COMPONENT_LIST[traceComponent],
|
562 kumpf 1.40 System::getPID(), Threads::id().buffer);
|
563 mike 1.2 }
564
565 // Call trace file handler to write message
|
566 thilo.boehm 1.52 _getInstance()->_traceHandler->handleMessage(msgHeader,msgLen,fmt,argList);
|
567 chip 1.20
568 delete [] msgHeader;
|
569 mike 1.2 }
570
571 ////////////////////////////////////////////////////////////////////////////////
|
572 marek 1.42 //Called by all trace interfaces using a character string without format string
573 //to log message to trace file
574 ////////////////////////////////////////////////////////////////////////////////
575 void Tracer::_traceCString(
|
576 kumpf 1.53 const TraceComponentId traceComponent,
|
577 marek 1.42 const char* message,
578 const char* cstring)
579 {
580 char* completeMessage;
|
581 thilo.boehm 1.52 Uint32 msgLen;
582 Uint32 usec,sec;
|
583 marek 1.42
584 // Get the current system time and prepend to message
|
585 thilo.boehm 1.52 System::getCurrentTimeUsec(sec,usec);
586
|
587 marek 1.42 //
588 // Allocate completeMessage.
589 // Needs to be updated if additional info is added
590 //
591
592 // Construct the message header
593 // The message header is in the following format
594 // timestamp: <component name> [file name:line number]
|
595 thilo.boehm 1.52 //
|
596 thilo.boehm 1.56 // Format string length calculation:
|
597 thilo.boehm 1.52 // 11(sec)+ 2('s-')+11(usec)+4('us: ')+1(' ')+1(\0) = 30
|
598 marek 1.42 if (*message != '\0')
599 {
600 completeMessage = new char [strlen(message) +
601 strlen(TRACE_COMPONENT_LIST[traceComponent]) +
|
602 thilo.boehm 1.52 strlen(cstring) + 30];
|
603 marek 1.42
|
604 thilo.boehm 1.52 msgLen = sprintf(completeMessage, "%us-%uus: %s %s%s", sec, usec,
|
605 marek 1.42 TRACE_COMPONENT_LIST[traceComponent], message, cstring);
606 }
607 else
608 {
609 //
610 // Allocate messageHeader.
611 // Needs to be updated if additional info is added
612 //
|
613 kumpf 1.61 // Format string length calculation:
|
614 thilo.boehm 1.52 // 11(sec)+2('s-')+11(usec)+4('us: ')+
615 // +2(' [')+1(':')+3(']: ')+1(\0) = 35
616 completeMessage = new char[2 * _STRLEN_MAX_PID_TID +
|
617 marek 1.42 strlen(TRACE_COMPONENT_LIST[traceComponent]) +
|
618 thilo.boehm 1.52 strlen(cstring) +35];
|
619 marek 1.42
|
620 thilo.boehm 1.52 msgLen = sprintf(completeMessage, "%us-%uus: %s [%u:%s] %s", sec, usec,
|
621 thilo.boehm 1.56 TRACE_COMPONENT_LIST[traceComponent],
622 System::getPID(), Threads::id().buffer,
|
623 thilo.boehm 1.52 cstring);
|
624 marek 1.42 }
625
626 // Call trace file handler to write message
|
627 thilo.boehm 1.52 _getInstance()->_traceHandler->handleMessage(completeMessage,msgLen);
|
628 marek 1.42
629 delete [] completeMessage;
630 }
631
632
633 ////////////////////////////////////////////////////////////////////////////////
|
634 mike 1.2 //Validate the trace file
635 ////////////////////////////////////////////////////////////////////////////////
|
636 kumpf 1.10 Boolean Tracer::isValidFileName(const char* filePath)
|
637 mike 1.2 {
|
638 thilo.boehm 1.54 Tracer* instance = _getInstance();
639 String testTraceFile(filePath);
640
641 if (instance->_runningOOP)
|
642 kumpf 1.23 {
|
643 thilo.boehm 1.54 testTraceFile.append(".");
644 testTraceFile.append(instance->_oopTraceFileExtension);
|
645 kumpf 1.23 }
|
646 thilo.boehm 1.54
647 return _isValidTraceFile(testTraceFile);
|
648 mike 1.2 }
649
650 ////////////////////////////////////////////////////////////////////////////////
651 //Validate the trace components
652 ////////////////////////////////////////////////////////////////////////////////
|
653 kumpf 1.23 Boolean Tracer::isValidComponents(const String& traceComponents)
|
654 kumpf 1.10 {
655 String invalidComponents;
656 return isValidComponents(traceComponents, invalidComponents);
657 }
658
659 Boolean Tracer::isValidComponents(
|
660 kumpf 1.40 const String& traceComponents,
661 String& invalidComponents)
|
662 mike 1.2 {
663 // Validate the trace components and modify the traceComponents argument
664 // to reflect the invalid components
665
666 Uint32 position=0;
667 Uint32 index=0;
|
668 kumpf 1.44 String componentName;
669 String componentStr;
|
670 mike 1.2 Boolean validComponent=false;
671 Boolean retCode=true;
672
673 componentStr = traceComponents;
674 invalidComponents = String::EMPTY;
675
676 if (componentStr != String::EMPTY)
677 {
678 // Check if ALL is specified
679 if (String::equalNoCase(componentStr,"ALL"))
680 {
|
681 marek 1.48 return true;
|
682 mike 1.2 }
683
684 // Append _COMPONENT_SEPARATOR to the end of the traceComponents
|
685 kumpf 1.16 componentStr.append(_COMPONENT_SEPARATOR);
|
686 mike 1.2
687 while (componentStr != String::EMPTY)
688 {
|
689 david.dillard 1.32 //
|
690 mike 1.2 // Get the Component name from traceComponents.
691 // Components are separated by _COMPONENT_SEPARATOR
|
692 david.dillard 1.32 //
|
693 mike 1.2 position = componentStr.find(_COMPONENT_SEPARATOR);
694 componentName = componentStr.subString(0,(position));
695
696 // Lookup the index for Component name in TRACE_COMPONENT_LIST
697 index = 0;
698 validComponent = false;
699
700 while (index < _NUM_COMPONENTS)
701 {
|
702 chip 1.20 if (String::equalNoCase(
|
703 david.dillard 1.32 componentName, TRACE_COMPONENT_LIST[index]))
|
704 mike 1.2 {
705 // Found component, break from the loop
|
706 david.dillard 1.32 validComponent = true;
|
707 mike 1.2 break;
708 }
709 else
710 {
711 index++;
712 }
713 }
714
715 // Remove the searched componentname from the traceComponents
716 componentStr.remove(0,position+1);
717
|
718 kumpf 1.40 if (!validComponent)
|
719 david.dillard 1.32 {
720 invalidComponents.append(componentName);
721 invalidComponents.append(_COMPONENT_SEPARATOR);
|
722 mike 1.2 }
723 }
724 }
725 else
726 {
|
727 david.dillard 1.32 // trace components is empty, it is a valid value so return true
|
728 marek 1.48 return true;
|
729 mike 1.2 }
|
730 kumpf 1.40
731 if (invalidComponents != String::EMPTY)
|
732 mike 1.2 {
|
733 david.dillard 1.32 retCode = false;
734 //
735 // Remove the extra ',' at the end
736 //
737 invalidComponents.remove(
738 invalidComponents.reverseFind(_COMPONENT_SEPARATOR));
|
739 mike 1.2 }
740 return retCode;
741 }
|
742 chip 1.20
|
743 mike 1.2 ////////////////////////////////////////////////////////////////////////////////
|
744 r.kieninger 1.49 //Validate the trace facility
745 ////////////////////////////////////////////////////////////////////////////////
746 Boolean Tracer::isValidTraceFacility(const String& traceFacility)
747 {
748 Boolean retCode = false;
749
750 if (traceFacility.size() != 0)
751 {
752 Uint32 index = 0;
753 while (TRACE_FACILITY_LIST[index] != 0 )
754 {
|
755 thilo.boehm 1.52 if (String::equalNoCase(traceFacility,TRACE_FACILITY_LIST[index]))
|
756 r.kieninger 1.49 {
757 retCode = true;
758 break;
759 }
760 index++;
761 }
762 }
763
764 return retCode;
765 }
766
767 ////////////////////////////////////////////////////////////////////////////////
|
768 kumpf 1.61 // Notify the trare running out of process and provide the trace file extension
|
769 thilo.boehm 1.54 // for the out of process trace file.
|
770 kumpf 1.23 ////////////////////////////////////////////////////////////////////////////////
|
771 thilo.boehm 1.54 void Tracer::setOOPTraceFileExtension(const String& oopTraceFileExtension)
|
772 kumpf 1.23 {
|
773 thilo.boehm 1.54 Tracer* instance = _getInstance();
774 instance->_oopTraceFileExtension = oopTraceFileExtension;
775 instance->_runningOOP=true;
776 instance->_traceMemoryBufferSize /= PEGASUS_TRC_BUFFER_OOP_SIZE_DEVISOR;
777
|
778 kumpf 1.23 }
779
780 ////////////////////////////////////////////////////////////////////////////////
|
781 mike 1.2 //Returns the Singleton instance of the Tracer
782 ////////////////////////////////////////////////////////////////////////////////
783 Tracer* Tracer::_getInstance()
784 {
785 if (_tracerInstance == 0)
786 {
787 _tracerInstance = new Tracer();
788 }
789 return _tracerInstance;
790 }
791
|
792 chip 1.20 // PEGASUS_REMOVE_TRACE defines the compile time inclusion of the Trace
|
793 karl 1.35 // interfaces. This section defines the trace functions IF the remove
794 // trace flag is NOT set. If it is set, they are defined as empty functions
795 // in the header file.
|
796 mike 1.2
797 #ifndef PEGASUS_REMOVE_TRACE
798
799 ////////////////////////////////////////////////////////////////////////////////
800 //Set the trace file
801 ////////////////////////////////////////////////////////////////////////////////
802 Uint32 Tracer::setTraceFile(const char* traceFile)
803 {
|
804 kumpf 1.25 if (*traceFile == 0)
805 {
806 return 1;
807 }
808
|
809 thilo.boehm 1.54 Tracer* instance = _getInstance();
810 String newTraceFile(traceFile);
811
812 if (instance->_runningOOP)
813 {
814 newTraceFile.append(".");
815 newTraceFile.append(instance->_oopTraceFileExtension);
816 }
817
818 if (_isValidTraceFile(newTraceFile))
|
819 kumpf 1.23 {
|
820 thilo.boehm 1.54 instance->_traceFile = newTraceFile;
821 instance->_traceHandler->configurationUpdated();
|
822 kumpf 1.23 }
823 else
824 {
|
825 thilo.boehm 1.55 return 1;
|
826 kumpf 1.23 }
|
827 thilo.boehm 1.54
828
|
829 thilo.boehm 1.55 return 0;
|
830 thilo.boehm 1.54
|
831 chip 1.20 }
|
832 mike 1.2
833 ////////////////////////////////////////////////////////////////////////////////
834 //Set the trace level
835 ////////////////////////////////////////////////////////////////////////////////
836 Uint32 Tracer::setTraceLevel(const Uint32 traceLevel)
837 {
838 Uint32 retCode = 0;
839
840 switch (traceLevel)
841 {
|
842 marek 1.48 case LEVEL0:
|
843 thilo.boehm 1.56 _traceLevelMask = 0x00;
|
844 marek 1.48 break;
845
|
846 david.dillard 1.32 case LEVEL1:
|
847 thilo.boehm 1.56 _traceLevelMask = 0x01;
|
848 david.dillard 1.32 break;
|
849 chip 1.20
|
850 mike 1.2 case LEVEL2:
|
851 thilo.boehm 1.56 _traceLevelMask = 0x03;
|
852 david.dillard 1.32 break;
|
853 mike 1.2
854 case LEVEL3:
|
855 thilo.boehm 1.56 _traceLevelMask = 0x07;
|
856 david.dillard 1.32 break;
|
857 mike 1.2
858 case LEVEL4:
|
859 thilo.boehm 1.56 _traceLevelMask = 0x0F;
|
860 david.dillard 1.32 break;
|
861 mike 1.2
|
862 marek 1.48 case LEVEL5:
|
863 thilo.boehm 1.56 _traceLevelMask = 0x1F;
|
864 marek 1.48 break;
865
|
866 mike 1.2 default:
|
867 thilo.boehm 1.56 _traceLevelMask = 0x00;
|
868 mike 1.2 retCode = 1;
869 }
|
870 marek 1.48
|
871 thilo.boehm 1.56 // If one of the components was set for tracing and the traceLevel
872 // is not zero, then turn on tracing.
873 _traceOn=((_traceComponentMask!=(Uint64)0)&&(_traceLevelMask!=LEVEL0));
|
874 marek 1.48
|
875 mike 1.2 return retCode;
876 }
877
878 ////////////////////////////////////////////////////////////////////////////////
|
879 chip 1.20 // Set components to be traced.
|
880 mike 1.2 ////////////////////////////////////////////////////////////////////////////////
|
881 kumpf 1.23 void Tracer::setTraceComponents(const String& traceComponents)
|
882 mike 1.2 {
|
883 marek 1.48 // Check if ALL is specified
884 if (String::equalNoCase(traceComponents,"ALL"))
|
885 mike 1.2 {
|
886 thilo.boehm 1.56 // initialize ComponentMask bit array to true
887 _traceComponentMask = (Uint64)-1;
|
888 kumpf 1.61
|
889 marek 1.48 // If tracing isn't turned off by a traceLevel of zero, let's
890 // turn on the flag that activates tracing.
|
891 thilo.boehm 1.56 _traceOn = (_traceLevelMask != LEVEL0);
|
892 marek 1.48
893 return;
894 }
895
|
896 thilo.boehm 1.56 // initialize ComponentMask bit array to false
897 _traceComponentMask = (Uint64)0;
|
898 marek 1.48 _traceOn = false;
|
899 kumpf 1.61
|
900 marek 1.48 if (traceComponents != String::EMPTY)
901 {
902 Uint32 index = 0;
903 Uint32 position = 0;
904 String componentName;
905 String componentStr = traceComponents;
|
906 mike 1.2
|
907 kumpf 1.61
|
908 r.kieninger 1.30 // Append _COMPONENT_SEPARATOR to the end of the traceComponents
|
909 kumpf 1.16 componentStr.append(_COMPONENT_SEPARATOR);
|
910 mike 1.2
911 while (componentStr != String::EMPTY)
912 {
|
913 chip 1.20 // Get the Component name from traceComponents.
|
914 r.kieninger 1.30 // Components are separated by _COMPONENT_SEPARATOR
|
915 mike 1.2 position = componentStr.find(_COMPONENT_SEPARATOR);
|
916 r.kieninger 1.30 componentName = componentStr.subString(0,(position));
|
917 mike 1.2
|
918 r.kieninger 1.30 // Lookup the index for Component name in TRACE_COMPONENT_LIST
|
919 mike 1.2 index = 0;
|
920 r.kieninger 1.30 while (index < _NUM_COMPONENTS)
921 {
922 if (String::equalNoCase(
923 componentName,TRACE_COMPONENT_LIST[index]))
924 {
|
925 thilo.boehm 1.56 _traceComponentMask=_traceComponentMask|((Uint64)1<<index);
|
926 mike 1.2 // Found component, break from the loop
927 break;
|
928 r.kieninger 1.30 }
929 else
930 {
931 index++;
|
932 mike 1.2 }
|
933 chip 1.20 }
|
934 mike 1.2 // Remove the searched componentname from the traceComponents
935 componentStr.remove(0,position+1);
936 }
|
937 marek 1.48 // If one of the components was set for tracing and the traceLevel
938 // is not zero, then turn on tracing.
|
939 thilo.boehm 1.56 _traceOn=((_traceComponentMask!=(Uint64)0)&&(_traceLevelMask!=LEVEL0));
|
940 mike 1.2 }
|
941 marek 1.48
|
942 mike 1.2 return ;
943 }
944
|
945 r.kieninger 1.49 ////////////////////////////////////////////////////////////////////////////////
946 // Set the trace facility to be used
947 ////////////////////////////////////////////////////////////////////////////////
948 Uint32 Tracer::setTraceFacility(const String& traceFacility)
949 {
950 Uint32 retCode = 0;
951 Tracer* instance = _getInstance();
|
952 thilo.boehm 1.54
|
953 r.kieninger 1.49 if (traceFacility.size() != 0)
954 {
955 Uint32 index = 0;
956 while (TRACE_FACILITY_LIST[index] != 0 )
957 {
958 if (String::equalNoCase( traceFacility,TRACE_FACILITY_LIST[index]))
959 {
960 if (index != instance->_traceFacility)
961 {
|
962 thilo.boehm 1.52 instance->_setTraceHandler(index);
|
963 r.kieninger 1.49 }
964 retCode = 1;
965 break;
966 }
967 index++;
968 }
969 }
970
971 return retCode;
972 }
973
|
974 marek 1.50 ////////////////////////////////////////////////////////////////////////////////
975 // Get the trace facility in use
976 ////////////////////////////////////////////////////////////////////////////////
977 Uint32 Tracer::getTraceFacility()
978 {
979 return _getInstance()->_traceFacility;
980 }
|
981 r.kieninger 1.49
|
982 thilo.boehm 1.52 ////////////////////////////////////////////////////////////////////////////////
983 // Set the size of the memory trace buffer
984 ////////////////////////////////////////////////////////////////////////////////
985 Boolean Tracer::setTraceMemoryBufferSize(Uint32 bufferSize)
986 {
987 Tracer* instance = _getInstance();
|
988 thilo.boehm 1.54 if (instance->_runningOOP)
989 {
990 // in OOP we reduce the trace memory buffer by factor
991 // PEGASUS_TRC_BUFFER_OOP_SIZE_DEVISOR
|
992 kumpf 1.61 instance->_traceMemoryBufferSize =
|
993 thilo.boehm 1.54 bufferSize / PEGASUS_TRC_BUFFER_OOP_SIZE_DEVISOR;
|
994 kumpf 1.61 }
|
995 thilo.boehm 1.54 else
996 {
997 instance->_traceMemoryBufferSize = bufferSize;
998 }
999
|
1000 thilo.boehm 1.52 // If we decide to dynamically change the trace buffer size,
1001 // this is where it needs to be implemented.
1002 return true;
1003 }
1004
1005 ////////////////////////////////////////////////////////////////////////////////
1006 // Flushes the trace buffer to traceFilePath. This method will only
1007 // have an effect when traceFacility=Memory.
1008 ////////////////////////////////////////////////////////////////////////////////
1009 void Tracer::flushTrace()
1010 {
1011 _getInstance()->_traceHandler->flushTrace();
1012 return;
1013 }
1014
1015
|
1016 kumpf 1.40 void Tracer::traceEnter(
1017 TracerToken& token,
|
1018 karl 1.35 const char* file,
1019 size_t line,
|
1020 kumpf 1.53 TraceComponentId traceComponent,
|
1021 karl 1.35 const char* method)
1022 {
|
1023 marek 1.42 token.component = traceComponent;
1024 token.method = method;
|
1025 kumpf 1.61
|
1026 marek 1.48 if (isTraceEnabled(traceComponent, LEVEL5))
|
1027 karl 1.35 {
|
1028 marek 1.42 _traceMethod(
|
1029 kumpf 1.61 file, (Uint32)line, traceComponent,
|
1030 a.dunfey 1.41 _METHOD_ENTER_MSG, method);
|
1031 karl 1.35 }
1032 }
1033
1034 void Tracer::traceExit(
1035 TracerToken& token,
1036 const char* file,
1037 size_t line)
1038 {
|
1039 marek 1.48 if (isTraceEnabled(token.component, LEVEL5) && token.method)
|
1040 marek 1.42 _traceMethod(
1041 file, (Uint32)line, token.component,
|
1042 kumpf 1.40 _METHOD_EXIT_MSG, token.method);
|
1043 karl 1.35 }
1044
|
1045 marek 1.46 ////////////////////////////////////////////////////////////////////////////////
1046 //Traces the given string - Overloaded to include the fileName and line number
1047 //of trace origin.
1048 ////////////////////////////////////////////////////////////////////////////////
1049 void Tracer::traceCString(
|
1050 karl 1.35 const char* fileName,
1051 const Uint32 lineNum,
|
1052 kumpf 1.53 const TraceComponentId traceComponent,
|
1053 marek 1.46 const char* cstring)
|
1054 karl 1.35 {
|
1055 marek 1.46 char* message;
|
1056 karl 1.35
|
1057 thilo.boehm 1.52 Uint32 msgLen;
1058 Uint32 usec,sec;
1059
1060 // Get the current system time
1061 System::getCurrentTimeUsec(sec,usec);
|
1062 kumpf 1.61
|
1063 marek 1.46 //
1064 // Allocate memory for the message string
1065 // Needs to be updated if additional info is added
1066 //
|
1067 thilo.boehm 1.52 message = new char [strlen(fileName) +
1068 _STRLEN_MAX_UNSIGNED_INT + (_STRLEN_MAX_PID_TID * 2) + 8 +
|
1069 thilo.boehm 1.56 strlen(TRACE_COMPONENT_LIST[traceComponent]) +
|
1070 thilo.boehm 1.52 strlen(cstring) + 30];
1071
1072 msgLen = sprintf(message, "%us-%uus: %s [%u:%s:%s:%u]: %s",
|
1073 kumpf 1.61 sec,
|
1074 thilo.boehm 1.52 usec,
|
1075 thilo.boehm 1.56 TRACE_COMPONENT_LIST[traceComponent],
|
1076 r.kieninger 1.49 System::getPID(),
1077 Threads::id().buffer,
1078 fileName,
|
1079 thilo.boehm 1.52 lineNum,
1080 cstring);
1081
1082 // Call trace file handler to write message
1083 _getInstance()->_traceHandler->handleMessage(message,msgLen);
|
1084 karl 1.35
|
1085 marek 1.46 delete [] message;
|
1086 karl 1.35 }
1087
|
1088 marek 1.42 void Tracer::traceCIMException(
|
1089 kumpf 1.53 const TraceComponentId traceComponent,
|
1090 marek 1.42 const Uint32 traceLevel,
1091 const CIMException& cimException)
|
1092 karl 1.35 {
|
1093 marek 1.46 if (isTraceEnabled(traceComponent, traceLevel))
|
1094 marek 1.42 {
1095 _traceCIMException(traceComponent, cimException);
1096 }
|
1097 karl 1.35 }
1098
1099 #endif /* !PEGASUS_REMOVE_TRACE */
|
1100 mike 1.2
|
1101 lawrence.luo 1.71 //set the trace file size only when the tracing is on a file
1102 void Tracer::setMaxTraceFileSize(const String &size)
|
1103 amit99shah 1.70 {
|
1104 lawrence.luo 1.71 Tracer *inst = _getInstance();
1105 if ( inst->getTraceFacility() == TRACE_FACILITY_FILE )
1106 {
1107 Uint32 traceFileSizeKBytes = 0;
1108 tracePropertyToUint32(size, traceFileSizeKBytes);
1109
1110 //Safe to typecast here as we know that handler is of type file
1111 TraceFileHandler *hdlr = (TraceFileHandler*) (inst->_traceHandler);
1112
1113 hdlr->setMaxTraceFileSize(traceFileSizeKBytes*1024);
1114
1115 }
|
1116 amit99shah 1.70 }
1117
|
1118 lawrence.luo 1.71 //set the trace file number for rolling only when the tracing is on a file
1119 void Tracer::setMaxTraceFileNumber(const String &maxTraceFileNumber)
|
1120 amit99shah 1.70 {
|
1121 lawrence.luo 1.71 Tracer *inst = _getInstance();
1122
1123 if ( inst->getTraceFacility() == TRACE_FACILITY_FILE )
1124 {
1125 Uint32 numberOfTraceFiles = 0;
1126 tracePropertyToUint32(maxTraceFileNumber, numberOfTraceFiles);
1127
1128 //Safe to typecast here as we know that handler is of type file
1129 TraceFileHandler *hdlr = (TraceFileHandler*) (inst->_traceHandler);
1130
1131 hdlr->setMaxTraceFileNumber(numberOfTraceFiles);
1132 }
1133 }
1134
1135 //
1136 // Converts the quantifiable trace proprties string into a Uint32 value.
1137 // It returns false and the bufferSize is set to 0 if the string was not valid.
1138 //
1139 Boolean Tracer::tracePropertyToUint32(
1140 const String& traceProperty, Uint32& valueInUint32 )
1141 {
1142 lawrence.luo 1.71 Boolean retCode = false;
1143 Uint64 uInt64BufferSize;
1144
1145 valueInUint32 = 0;
1146 CString stringBufferSize = traceProperty.getCString();
1147
1148
1149 retCode = StringConversion::decimalStringToUint64(stringBufferSize,
1150 uInt64BufferSize);
1151
1152 if (retCode )
1153 {
1154 retCode = StringConversion::checkUintBounds(uInt64BufferSize,
1155 CIMTYPE_UINT32);
1156 }
1157
1158 if (retCode )
1159 {
1160 valueInUint32 = (Uint32)uInt64BufferSize;
1161 }
1162
1163 lawrence.luo 1.71 return retCode;
|
1164 amit99shah 1.70 }
1165
1166
|
1167 mike 1.2 PEGASUS_NAMESPACE_END
|