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 while ((sep = HTTPMessage::findSeparator(
456 line, (Uint32)(requestSize - (line - requestBuf.get())))) &&
457 (line != sep))
458 {
459 if (HTTPMessage::expectHeaderToken(line, "Authorization") &&
460 HTTPMessage::expectHeaderToken(line, ":") &&
461 HTTPMessage::expectHeaderToken(line, "Basic"))
462 {
463 sushma.fernandes 1.45 // Suppress the user/passwd info
464 HTTPMessage::skipHeaderWhitespace(line);
|
465 thilo.boehm 1.56 for ( char* userpass = (char*)line ;
466 userpass < sep;
|
467 marek 1.63 *userpass = 'X', userpass++)
468 {
469 }
|
470 sushma.fernandes 1.45 break;
471 }
472
473 line = sep + ((*sep == '\r') ? 2 : 1);
474 }
475 return requestBuf;
476 }
477
|
478 mike 1.2 ////////////////////////////////////////////////////////////////////////////////
|
479 marek 1.42 //Traces method entry and exit
|
480 mike 1.2 ////////////////////////////////////////////////////////////////////////////////
|
481 marek 1.42 void Tracer::_traceMethod(
|
482 mike 1.2 const char* fileName,
483 const Uint32 lineNum,
|
484 kumpf 1.53 const TraceComponentId traceComponent,
|
485 marek 1.42 const char* methodEntryExit,
486 const char* method)
|
487 mike 1.2 {
488 char* message;
489
|
490 marek 1.42 //
491 // Allocate memory for the message string
492 // Needs to be updated if additional info is added
493 //
494 // assume Method entry/exit string 15 characters long
495 // +1 space character
496 message = new char[ strlen(fileName) +
|
497 thilo.boehm 1.56 _STRLEN_MAX_UNSIGNED_INT + (_STRLEN_MAX_PID_TID * 2) + 8
|
498 marek 1.42 + 16];
499
500 sprintf(
501 message,
|
502 kumpf 1.51 "[%u:%s:%s:%u]: %s ",
|
503 marek 1.42 System::getPID(),
504 Threads::id().buffer,
505 fileName,
506 lineNum,
507 methodEntryExit);
|
508 kumpf 1.61
|
509 marek 1.42 _traceCString(traceComponent, message, method);
|
510 carson.hovey 1.37
|
511 marek 1.42 delete [] message;
|
512 mike 1.2 }
513
514 ////////////////////////////////////////////////////////////////////////////////
|
515 marek 1.42 //Called by all trace interfaces with variable arguments
516 //to log message to trace file
|
517 mike 1.2 ////////////////////////////////////////////////////////////////////////////////
518 void Tracer::_trace(
|
519 kumpf 1.53 const TraceComponentId traceComponent,
|
520 mike 1.2 const char* message,
521 const char* fmt,
522 va_list argList)
523 {
524 char* msgHeader;
|
525 thilo.boehm 1.52 Uint32 msgLen;
526 Uint32 usec,sec;
|
527 mike 1.2
528 // Get the current system time and prepend to message
|
529 thilo.boehm 1.52 System::getCurrentTimeUsec(sec,usec);
|
530 mike 1.2
|
531 kumpf 1.3 //
|
532 chip 1.20 // Allocate messageHeader.
|
533 kumpf 1.3 // Needs to be updated if additional info is added
534 //
|
535 mday 1.19
|
536 mike 1.2 // Construct the message header
|
537 chip 1.20 // The message header is in the following format
|
538 mike 1.2 // timestamp: <component name> [file name:line number]
|
539 thilo.boehm 1.52 //
|
540 kumpf 1.61 // Format string length calculation:
|
541 thilo.boehm 1.52 // 11(sec)+ 2('s-')+11(usec)+4('us: ')+1(' ')+1(\0) = 30
|
542 joyce.j 1.26 if (*message != '\0')
|
543 mike 1.2 {
|
544 kumpf 1.40 msgHeader = new char [strlen(message) +
|
545 thilo.boehm 1.52 strlen(TRACE_COMPONENT_LIST[traceComponent]) + 30];
|
546 kumpf 1.40
|
547 thilo.boehm 1.52 msgLen = sprintf(msgHeader, "%us-%uus: %s %s", sec, usec,
|
548 kumpf 1.40 TRACE_COMPONENT_LIST[traceComponent], message);
|
549 mike 1.2 }
550 else
551 {
|
552 kumpf 1.3 //
|
553 chip 1.20 // Allocate messageHeader.
|
554 kumpf 1.3 // Needs to be updated if additional info is added
555 //
|
556 thilo.boehm 1.56 // Format string length calculation:
|
557 thilo.boehm 1.52 // 11(sec)+2('s-')+11(usec)+4('us: ')+
558 // +2(' [')+1(':')+3(']: ')+1(\0) = 35
|
559 thilo.boehm 1.56 msgHeader = new char[2 * _STRLEN_MAX_PID_TID +
|
560 thilo.boehm 1.52 strlen(TRACE_COMPONENT_LIST[traceComponent]) + 35];
561
562 msgLen = sprintf(msgHeader, "%us-%uus: %s [%u:%s]: ", sec, usec,
|
563 kumpf 1.61 TRACE_COMPONENT_LIST[traceComponent],
|
564 kumpf 1.40 System::getPID(), Threads::id().buffer);
|
565 mike 1.2 }
566
567 // Call trace file handler to write message
|
568 thilo.boehm 1.52 _getInstance()->_traceHandler->handleMessage(msgHeader,msgLen,fmt,argList);
|
569 chip 1.20
570 delete [] msgHeader;
|
571 mike 1.2 }
572
573 ////////////////////////////////////////////////////////////////////////////////
|
574 marek 1.42 //Called by all trace interfaces using a character string without format string
575 //to log message to trace file
576 ////////////////////////////////////////////////////////////////////////////////
577 void Tracer::_traceCString(
|
578 kumpf 1.53 const TraceComponentId traceComponent,
|
579 marek 1.42 const char* message,
580 const char* cstring)
581 {
582 char* completeMessage;
|
583 thilo.boehm 1.52 Uint32 msgLen;
584 Uint32 usec,sec;
|
585 marek 1.42
586 // Get the current system time and prepend to message
|
587 thilo.boehm 1.52 System::getCurrentTimeUsec(sec,usec);
588
|
589 marek 1.42 //
590 // Allocate completeMessage.
591 // Needs to be updated if additional info is added
592 //
593
594 // Construct the message header
595 // The message header is in the following format
596 // timestamp: <component name> [file name:line number]
|
597 thilo.boehm 1.52 //
|
598 thilo.boehm 1.56 // Format string length calculation:
|
599 thilo.boehm 1.52 // 11(sec)+ 2('s-')+11(usec)+4('us: ')+1(' ')+1(\0) = 30
|
600 marek 1.42 if (*message != '\0')
601 {
602 completeMessage = new char [strlen(message) +
603 strlen(TRACE_COMPONENT_LIST[traceComponent]) +
|
604 thilo.boehm 1.52 strlen(cstring) + 30];
|
605 marek 1.42
|
606 thilo.boehm 1.52 msgLen = sprintf(completeMessage, "%us-%uus: %s %s%s", sec, usec,
|
607 marek 1.42 TRACE_COMPONENT_LIST[traceComponent], message, cstring);
608 }
609 else
610 {
611 //
612 // Since the message is blank, form a string using the pid and tid
613 //
614 char* tmpBuffer;
615
616 //
617 // Allocate messageHeader.
618 // Needs to be updated if additional info is added
619 //
|
620 kumpf 1.61 // Format string length calculation:
|
621 thilo.boehm 1.52 // 11(sec)+2('s-')+11(usec)+4('us: ')+
622 // +2(' [')+1(':')+3(']: ')+1(\0) = 35
623 completeMessage = new char[2 * _STRLEN_MAX_PID_TID +
|
624 marek 1.42 strlen(TRACE_COMPONENT_LIST[traceComponent]) +
|
625 thilo.boehm 1.52 strlen(cstring) +35];
|
626 marek 1.42
|
627 thilo.boehm 1.52 msgLen = sprintf(completeMessage, "%us-%uus: %s [%u:%s] %s", sec, usec,
|
628 thilo.boehm 1.56 TRACE_COMPONENT_LIST[traceComponent],
629 System::getPID(), Threads::id().buffer,
|
630 thilo.boehm 1.52 cstring);
|
631 marek 1.42 }
632
633 // Call trace file handler to write message
|
634 thilo.boehm 1.52 _getInstance()->_traceHandler->handleMessage(completeMessage,msgLen);
|
635 marek 1.42
636 delete [] completeMessage;
637 }
638
639
640 ////////////////////////////////////////////////////////////////////////////////
|
641 mike 1.2 //Validate the trace file
642 ////////////////////////////////////////////////////////////////////////////////
|
643 kumpf 1.10 Boolean Tracer::isValidFileName(const char* filePath)
|
644 mike 1.2 {
|
645 thilo.boehm 1.54 Tracer* instance = _getInstance();
646 String testTraceFile(filePath);
647
648 if (instance->_runningOOP)
|
649 kumpf 1.23 {
|
650 thilo.boehm 1.54 testTraceFile.append(".");
651 testTraceFile.append(instance->_oopTraceFileExtension);
|
652 kumpf 1.23 }
|
653 thilo.boehm 1.54
654 return _isValidTraceFile(testTraceFile);
|
655 mike 1.2 }
656
657 ////////////////////////////////////////////////////////////////////////////////
658 //Validate the trace components
659 ////////////////////////////////////////////////////////////////////////////////
|
660 kumpf 1.23 Boolean Tracer::isValidComponents(const String& traceComponents)
|
661 kumpf 1.10 {
662 String invalidComponents;
663 return isValidComponents(traceComponents, invalidComponents);
664 }
665
666 Boolean Tracer::isValidComponents(
|
667 kumpf 1.40 const String& traceComponents,
668 String& invalidComponents)
|
669 mike 1.2 {
670 // Validate the trace components and modify the traceComponents argument
671 // to reflect the invalid components
672
673 Uint32 position=0;
674 Uint32 index=0;
|
675 kumpf 1.44 String componentName;
676 String componentStr;
|
677 mike 1.2 Boolean validComponent=false;
678 Boolean retCode=true;
679
680 componentStr = traceComponents;
681 invalidComponents = String::EMPTY;
682
683 if (componentStr != String::EMPTY)
684 {
685 // Check if ALL is specified
686 if (String::equalNoCase(componentStr,"ALL"))
687 {
|
688 marek 1.48 return true;
|
689 mike 1.2 }
690
691 // Append _COMPONENT_SEPARATOR to the end of the traceComponents
|
692 kumpf 1.16 componentStr.append(_COMPONENT_SEPARATOR);
|
693 mike 1.2
694 while (componentStr != String::EMPTY)
695 {
|
696 david.dillard 1.32 //
|
697 mike 1.2 // Get the Component name from traceComponents.
698 // Components are separated by _COMPONENT_SEPARATOR
|
699 david.dillard 1.32 //
|
700 mike 1.2 position = componentStr.find(_COMPONENT_SEPARATOR);
701 componentName = componentStr.subString(0,(position));
702
703 // Lookup the index for Component name in TRACE_COMPONENT_LIST
704 index = 0;
705 validComponent = false;
706
707 while (index < _NUM_COMPONENTS)
708 {
|
709 chip 1.20 if (String::equalNoCase(
|
710 david.dillard 1.32 componentName, TRACE_COMPONENT_LIST[index]))
|
711 mike 1.2 {
712 // Found component, break from the loop
|
713 david.dillard 1.32 validComponent = true;
|
714 mike 1.2 break;
715 }
716 else
717 {
718 index++;
719 }
720 }
721
722 // Remove the searched componentname from the traceComponents
723 componentStr.remove(0,position+1);
724
|
725 kumpf 1.40 if (!validComponent)
|
726 david.dillard 1.32 {
727 invalidComponents.append(componentName);
728 invalidComponents.append(_COMPONENT_SEPARATOR);
|
729 mike 1.2 }
730 }
731 }
732 else
733 {
|
734 david.dillard 1.32 // trace components is empty, it is a valid value so return true
|
735 marek 1.48 return true;
|
736 mike 1.2 }
|
737 kumpf 1.40
738 if (invalidComponents != String::EMPTY)
|
739 mike 1.2 {
|
740 david.dillard 1.32 retCode = false;
741 //
742 // Remove the extra ',' at the end
743 //
744 invalidComponents.remove(
745 invalidComponents.reverseFind(_COMPONENT_SEPARATOR));
|
746 mike 1.2 }
747 return retCode;
748 }
|
749 chip 1.20
|
750 mike 1.2 ////////////////////////////////////////////////////////////////////////////////
|
751 r.kieninger 1.49 //Validate the trace facility
752 ////////////////////////////////////////////////////////////////////////////////
753 Boolean Tracer::isValidTraceFacility(const String& traceFacility)
754 {
755 Boolean retCode = false;
756
757 if (traceFacility.size() != 0)
758 {
759 Uint32 index = 0;
760 while (TRACE_FACILITY_LIST[index] != 0 )
761 {
|
762 thilo.boehm 1.52 if (String::equalNoCase(traceFacility,TRACE_FACILITY_LIST[index]))
|
763 r.kieninger 1.49 {
764 retCode = true;
765 break;
766 }
767 index++;
768 }
769 }
770
771 return retCode;
772 }
773
774 ////////////////////////////////////////////////////////////////////////////////
|
775 kumpf 1.61 // Notify the trare running out of process and provide the trace file extension
|
776 thilo.boehm 1.54 // for the out of process trace file.
|
777 kumpf 1.23 ////////////////////////////////////////////////////////////////////////////////
|
778 thilo.boehm 1.54 void Tracer::setOOPTraceFileExtension(const String& oopTraceFileExtension)
|
779 kumpf 1.23 {
|
780 thilo.boehm 1.54 Tracer* instance = _getInstance();
781 instance->_oopTraceFileExtension = oopTraceFileExtension;
782 instance->_runningOOP=true;
783 instance->_traceMemoryBufferSize /= PEGASUS_TRC_BUFFER_OOP_SIZE_DEVISOR;
784
|
785 kumpf 1.23 }
786
787 ////////////////////////////////////////////////////////////////////////////////
|
788 mike 1.2 //Returns the Singleton instance of the Tracer
789 ////////////////////////////////////////////////////////////////////////////////
790 Tracer* Tracer::_getInstance()
791 {
792 if (_tracerInstance == 0)
793 {
794 _tracerInstance = new Tracer();
795 }
796 return _tracerInstance;
797 }
798
|
799 chip 1.20 // PEGASUS_REMOVE_TRACE defines the compile time inclusion of the Trace
|
800 karl 1.35 // interfaces. This section defines the trace functions IF the remove
801 // trace flag is NOT set. If it is set, they are defined as empty functions
802 // in the header file.
|
803 mike 1.2
804 #ifndef PEGASUS_REMOVE_TRACE
805
806 ////////////////////////////////////////////////////////////////////////////////
807 //Set the trace file
808 ////////////////////////////////////////////////////////////////////////////////
809 Uint32 Tracer::setTraceFile(const char* traceFile)
810 {
|
811 kumpf 1.25 if (*traceFile == 0)
812 {
813 return 1;
814 }
815
|
816 thilo.boehm 1.54 Tracer* instance = _getInstance();
817 String newTraceFile(traceFile);
818
819 if (instance->_runningOOP)
820 {
821 newTraceFile.append(".");
822 newTraceFile.append(instance->_oopTraceFileExtension);
823 }
824
825 if (_isValidTraceFile(newTraceFile))
|
826 kumpf 1.23 {
|
827 thilo.boehm 1.54 instance->_traceFile = newTraceFile;
828 instance->_traceHandler->configurationUpdated();
|
829 kumpf 1.23 }
830 else
831 {
|
832 thilo.boehm 1.55 return 1;
|
833 kumpf 1.23 }
|
834 thilo.boehm 1.54
835
|
836 thilo.boehm 1.55 return 0;
|
837 thilo.boehm 1.54
|
838 chip 1.20 }
|
839 mike 1.2
840 ////////////////////////////////////////////////////////////////////////////////
841 //Set the trace level
842 ////////////////////////////////////////////////////////////////////////////////
843 Uint32 Tracer::setTraceLevel(const Uint32 traceLevel)
844 {
845 Uint32 retCode = 0;
846
847 switch (traceLevel)
848 {
|
849 marek 1.48 case LEVEL0:
|
850 thilo.boehm 1.56 _traceLevelMask = 0x00;
|
851 marek 1.48 break;
852
|
853 david.dillard 1.32 case LEVEL1:
|
854 thilo.boehm 1.56 _traceLevelMask = 0x01;
|
855 david.dillard 1.32 break;
|
856 chip 1.20
|
857 mike 1.2 case LEVEL2:
|
858 thilo.boehm 1.56 _traceLevelMask = 0x03;
|
859 david.dillard 1.32 break;
|
860 mike 1.2
861 case LEVEL3:
|
862 thilo.boehm 1.56 _traceLevelMask = 0x07;
|
863 david.dillard 1.32 break;
|
864 mike 1.2
865 case LEVEL4:
|
866 thilo.boehm 1.56 _traceLevelMask = 0x0F;
|
867 david.dillard 1.32 break;
|
868 mike 1.2
|
869 marek 1.48 case LEVEL5:
|
870 thilo.boehm 1.56 _traceLevelMask = 0x1F;
|
871 marek 1.48 break;
872
|
873 mike 1.2 default:
|
874 thilo.boehm 1.56 _traceLevelMask = 0x00;
|
875 mike 1.2 retCode = 1;
876 }
|
877 marek 1.48
|
878 thilo.boehm 1.56 // If one of the components was set for tracing and the traceLevel
879 // is not zero, then turn on tracing.
880 _traceOn=((_traceComponentMask!=(Uint64)0)&&(_traceLevelMask!=LEVEL0));
|
881 marek 1.48
|
882 mike 1.2 return retCode;
883 }
884
885 ////////////////////////////////////////////////////////////////////////////////
|
886 chip 1.20 // Set components to be traced.
|
887 mike 1.2 ////////////////////////////////////////////////////////////////////////////////
|
888 kumpf 1.23 void Tracer::setTraceComponents(const String& traceComponents)
|
889 mike 1.2 {
|
890 marek 1.48 // Check if ALL is specified
891 if (String::equalNoCase(traceComponents,"ALL"))
|
892 mike 1.2 {
|
893 thilo.boehm 1.56 // initialize ComponentMask bit array to true
894 _traceComponentMask = (Uint64)-1;
|
895 kumpf 1.61
|
896 marek 1.48 // If tracing isn't turned off by a traceLevel of zero, let's
897 // turn on the flag that activates tracing.
|
898 thilo.boehm 1.56 _traceOn = (_traceLevelMask != LEVEL0);
|
899 marek 1.48
900 return;
901 }
902
|
903 thilo.boehm 1.56 // initialize ComponentMask bit array to false
904 _traceComponentMask = (Uint64)0;
|
905 marek 1.48 _traceOn = false;
|
906 kumpf 1.61
|
907 marek 1.48 if (traceComponents != String::EMPTY)
908 {
909 Uint32 index = 0;
910 Uint32 position = 0;
911 String componentName;
912 String componentStr = traceComponents;
|
913 mike 1.2
|
914 kumpf 1.61
|
915 r.kieninger 1.30 // Append _COMPONENT_SEPARATOR to the end of the traceComponents
|
916 kumpf 1.16 componentStr.append(_COMPONENT_SEPARATOR);
|
917 mike 1.2
918 while (componentStr != String::EMPTY)
919 {
|
920 chip 1.20 // Get the Component name from traceComponents.
|
921 r.kieninger 1.30 // Components are separated by _COMPONENT_SEPARATOR
|
922 mike 1.2 position = componentStr.find(_COMPONENT_SEPARATOR);
|
923 r.kieninger 1.30 componentName = componentStr.subString(0,(position));
|
924 mike 1.2
|
925 r.kieninger 1.30 // Lookup the index for Component name in TRACE_COMPONENT_LIST
|
926 mike 1.2 index = 0;
|
927 r.kieninger 1.30 while (index < _NUM_COMPONENTS)
928 {
929 if (String::equalNoCase(
930 componentName,TRACE_COMPONENT_LIST[index]))
931 {
|
932 thilo.boehm 1.56 _traceComponentMask=_traceComponentMask|((Uint64)1<<index);
|
933 mike 1.2 // Found component, break from the loop
934 break;
|
935 r.kieninger 1.30 }
936 else
937 {
938 index++;
|
939 mike 1.2 }
|
940 chip 1.20 }
|
941 mike 1.2 // Remove the searched componentname from the traceComponents
942 componentStr.remove(0,position+1);
943 }
|
944 marek 1.48 // If one of the components was set for tracing and the traceLevel
945 // is not zero, then turn on tracing.
|
946 thilo.boehm 1.56 _traceOn=((_traceComponentMask!=(Uint64)0)&&(_traceLevelMask!=LEVEL0));
|
947 mike 1.2 }
|
948 marek 1.48
|
949 mike 1.2 return ;
950 }
951
|
952 r.kieninger 1.49 ////////////////////////////////////////////////////////////////////////////////
953 // Set the trace facility to be used
954 ////////////////////////////////////////////////////////////////////////////////
955 Uint32 Tracer::setTraceFacility(const String& traceFacility)
956 {
957 Uint32 retCode = 0;
958 Tracer* instance = _getInstance();
|
959 thilo.boehm 1.54
|
960 r.kieninger 1.49 if (traceFacility.size() != 0)
961 {
962 Uint32 index = 0;
963 while (TRACE_FACILITY_LIST[index] != 0 )
964 {
965 if (String::equalNoCase( traceFacility,TRACE_FACILITY_LIST[index]))
966 {
967 if (index != instance->_traceFacility)
968 {
|
969 thilo.boehm 1.52 instance->_setTraceHandler(index);
|
970 r.kieninger 1.49 }
971 retCode = 1;
972 break;
973 }
974 index++;
975 }
976 }
977
978 return retCode;
979 }
980
|
981 marek 1.50 ////////////////////////////////////////////////////////////////////////////////
982 // Get the trace facility in use
983 ////////////////////////////////////////////////////////////////////////////////
984 Uint32 Tracer::getTraceFacility()
985 {
986 return _getInstance()->_traceFacility;
987 }
|
988 r.kieninger 1.49
|
989 thilo.boehm 1.52 ////////////////////////////////////////////////////////////////////////////////
990 // Set the size of the memory trace buffer
991 ////////////////////////////////////////////////////////////////////////////////
992 Boolean Tracer::setTraceMemoryBufferSize(Uint32 bufferSize)
993 {
994 Tracer* instance = _getInstance();
|
995 thilo.boehm 1.54 if (instance->_runningOOP)
996 {
997 // in OOP we reduce the trace memory buffer by factor
998 // PEGASUS_TRC_BUFFER_OOP_SIZE_DEVISOR
|
999 kumpf 1.61 instance->_traceMemoryBufferSize =
|
1000 thilo.boehm 1.54 bufferSize / PEGASUS_TRC_BUFFER_OOP_SIZE_DEVISOR;
|
1001 kumpf 1.61 }
|
1002 thilo.boehm 1.54 else
1003 {
1004 instance->_traceMemoryBufferSize = bufferSize;
1005 }
1006
|
1007 thilo.boehm 1.52 // If we decide to dynamically change the trace buffer size,
1008 // this is where it needs to be implemented.
1009 return true;
1010 }
1011
1012 ////////////////////////////////////////////////////////////////////////////////
1013 // Flushes the trace buffer to traceFilePath. This method will only
1014 // have an effect when traceFacility=Memory.
1015 ////////////////////////////////////////////////////////////////////////////////
1016 void Tracer::flushTrace()
1017 {
1018 _getInstance()->_traceHandler->flushTrace();
1019 return;
1020 }
1021
1022
|
1023 kumpf 1.40 void Tracer::traceEnter(
1024 TracerToken& token,
|
1025 karl 1.35 const char* file,
1026 size_t line,
|
1027 kumpf 1.53 TraceComponentId traceComponent,
|
1028 karl 1.35 const char* method)
1029 {
|
1030 marek 1.42 token.component = traceComponent;
1031 token.method = method;
|
1032 kumpf 1.61
|
1033 marek 1.48 if (isTraceEnabled(traceComponent, LEVEL5))
|
1034 karl 1.35 {
|
1035 marek 1.42 _traceMethod(
|
1036 kumpf 1.61 file, (Uint32)line, traceComponent,
|
1037 a.dunfey 1.41 _METHOD_ENTER_MSG, method);
|
1038 karl 1.35 }
1039 }
1040
1041 void Tracer::traceExit(
1042 TracerToken& token,
1043 const char* file,
1044 size_t line)
1045 {
|
1046 marek 1.48 if (isTraceEnabled(token.component, LEVEL5) && token.method)
|
1047 marek 1.42 _traceMethod(
1048 file, (Uint32)line, token.component,
|
1049 kumpf 1.40 _METHOD_EXIT_MSG, token.method);
|
1050 karl 1.35 }
1051
|
1052 marek 1.46 ////////////////////////////////////////////////////////////////////////////////
1053 //Traces the given string - Overloaded to include the fileName and line number
1054 //of trace origin.
1055 ////////////////////////////////////////////////////////////////////////////////
1056 void Tracer::traceCString(
|
1057 karl 1.35 const char* fileName,
1058 const Uint32 lineNum,
|
1059 kumpf 1.53 const TraceComponentId traceComponent,
|
1060 marek 1.46 const char* cstring)
|
1061 karl 1.35 {
|
1062 marek 1.46 char* message;
|
1063 karl 1.35
|
1064 thilo.boehm 1.52 Uint32 msgLen;
1065 Uint32 usec,sec;
1066
1067 // Get the current system time
1068 System::getCurrentTimeUsec(sec,usec);
|
1069 kumpf 1.61
|
1070 marek 1.46 //
1071 // Allocate memory for the message string
1072 // Needs to be updated if additional info is added
1073 //
|
1074 thilo.boehm 1.52 message = new char [strlen(fileName) +
1075 _STRLEN_MAX_UNSIGNED_INT + (_STRLEN_MAX_PID_TID * 2) + 8 +
|
1076 thilo.boehm 1.56 strlen(TRACE_COMPONENT_LIST[traceComponent]) +
|
1077 thilo.boehm 1.52 strlen(cstring) + 30];
1078
1079 msgLen = sprintf(message, "%us-%uus: %s [%u:%s:%s:%u]: %s",
|
1080 kumpf 1.61 sec,
|
1081 thilo.boehm 1.52 usec,
|
1082 thilo.boehm 1.56 TRACE_COMPONENT_LIST[traceComponent],
|
1083 r.kieninger 1.49 System::getPID(),
1084 Threads::id().buffer,
1085 fileName,
|
1086 thilo.boehm 1.52 lineNum,
1087 cstring);
1088
1089 // Call trace file handler to write message
1090 _getInstance()->_traceHandler->handleMessage(message,msgLen);
|
1091 karl 1.35
|
1092 marek 1.46 delete [] message;
|
1093 karl 1.35 }
1094
|
1095 marek 1.42 void Tracer::traceCIMException(
|
1096 kumpf 1.53 const TraceComponentId traceComponent,
|
1097 marek 1.42 const Uint32 traceLevel,
1098 const CIMException& cimException)
|
1099 karl 1.35 {
|
1100 marek 1.46 if (isTraceEnabled(traceComponent, traceLevel))
|
1101 marek 1.42 {
1102 _traceCIMException(traceComponent, cimException);
1103 }
|
1104 karl 1.35 }
1105
1106 #endif /* !PEGASUS_REMOVE_TRACE */
|
1107 mike 1.2
1108 PEGASUS_NAMESPACE_END
|