version 1.1, 2008/09/02 17:33:37
|
version 1.13, 2008/12/16 18:56:00
|
|
|
//%2006//////////////////////////////////////////////////////////////////////// |
//%LICENSE//////////////////////////////////////////////////////////////// |
// | // |
// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development |
// Licensed to The Open Group (TOG) under one or more contributor license |
// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems. |
// agreements. Refer to the OpenPegasusNOTICE.txt file distributed with |
// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.; |
// this work for additional information regarding copyright ownership. |
// IBM Corp.; EMC Corporation, The Open Group. |
// Each contributor licenses this file to you under the OpenPegasus Open |
// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.; |
// Source License; you may not use this file except in compliance with the |
// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group. |
// License. |
// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.; |
|
// EMC Corporation; VERITAS Software Corporation; The Open Group. |
|
// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.; |
|
// EMC Corporation; Symantec Corporation; The Open Group. |
|
// | // |
// Permission is hereby granted, free of charge, to any person obtaining a copy |
// Permission is hereby granted, free of charge, to any person obtaining a |
// of this software and associated documentation files (the "Software"), to |
// copy of this software and associated documentation files (the "Software"), |
// deal in the Software without restriction, including without limitation the |
// to deal in the Software without restriction, including without limitation |
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
// the rights to use, copy, modify, merge, publish, distribute, sublicense, |
// sell copies of the Software, and to permit persons to whom the Software is |
// and/or sell copies of the Software, and to permit persons to whom the |
// furnished to do so, subject to the following conditions: |
// Software is furnished to do so, subject to the following conditions: |
// | // |
// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN |
// The above copyright notice and this permission notice shall be included |
// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED |
// in all copies or substantial portions of the Software. |
// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT |
|
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
|
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
|
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
// | // |
//============================================================================== |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
|
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
|
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
|
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
|
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
// |
|
////////////////////////////////////////////////////////////////////////// |
// | // |
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
| |
#ifdef PEGASUS_PLATFORM_ZOS_ZSERIES_IBM |
// This _ISOC99_SOURCE definition and inclusion of stdio.h and stdarg.h |
|
// must precede the other file contents on z/OS. |
|
#if defined(PEGASUS_OS_ZOS) |
#define _ISOC99_SOURCE | #define _ISOC99_SOURCE |
|
#endif |
#include <stdio.h> | #include <stdio.h> |
#include <stdarg.h> | #include <stdarg.h> |
#endif |
|
| |
#include <Pegasus/Common/TraceMemoryHandler.h> | #include <Pegasus/Common/TraceMemoryHandler.h> |
#include <iostream> | #include <iostream> |
#include <fstream> | #include <fstream> |
| |
#define PEGASUS_TRC_BUFFER_WRAP_MARKER "" |
// ATTN: This is a workaround to allow HP-UX and Windows builds to succeed. |
#define PEGASUS_TRC_BUFFER_EOT_MARKER "*EOTRACE*" |
// It appears to work, but it may not be reliable. A better solution would be |
#define PEGASUS_TRC_BUFFER_EOT_MARKER_LEN 9 |
// preferred. |
|
#if defined(PEGASUS_OS_HPUX) || defined(PEGASUS_OS_TYPE_WINDOWS) |
|
# ifndef va_copy |
|
# define va_copy(dest, src) (void)((dest) = (src)) |
|
# endif |
|
#endif |
| |
//#define DBG(output) output |
|
#define DBG(output) |
|
| |
PEGASUS_USING_STD; | PEGASUS_USING_STD; |
| |
PEGASUS_NAMESPACE_BEGIN | PEGASUS_NAMESPACE_BEGIN |
| |
//////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// |
// Constructs TraceMemoryHandler with a default buffer size |
|
//////////////////////////////////////////////////////////////////////////////// |
|
TraceMemoryHandler::TraceMemoryHandler() |
|
{ |
|
Uint32 traceAreaSize = PEGASUS_TRC_DEFAULT_BUFFER_SIZE_KB * 1024; |
|
|
|
_initialize(traceAreaSize); |
|
} |
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
// Constructs TraceMemoryHandler with a custom buffer size | // Constructs TraceMemoryHandler with a custom buffer size |
//////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// |
TraceMemoryHandler::TraceMemoryHandler( Uint32 bufferSize ) |
TraceMemoryHandler::TraceMemoryHandler(): |
|
_overflowBuffer(0), |
|
_overflowBufferSize(0), |
|
_traceArea(0), |
|
_leftBytesInBuffer(0), |
|
_inUseCounter(0), |
|
_lockCounter(1), |
|
_dying(false), |
|
_contentionCount(0), |
|
_numberOfLocksObtained(0), |
|
_traceFileName(0) |
{ | { |
Uint32 traceAreaSize = bufferSize * 1024; |
|
| |
_initialize(traceAreaSize); |
|
} | } |
| |
//////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// |
// Private method to (re-)initialize the memory buffer | // Private method to (re-)initialize the memory buffer |
//////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// |
void TraceMemoryHandler::_initialize( Uint32 traceAreaSize ) |
void TraceMemoryHandler::_initializeTraceArea() |
{ | { |
_dying = false; |
if (_traceArea) |
_inUseCounter = 0; |
{ |
_lockCounter = 1; |
delete _traceArea; |
_contentionCount = 0; |
} |
_numberOfLocksObtained = 0; |
|
_traceFileName = 0; |
|
|
|
| |
_overflowBuffer = 0; |
// get the memory buffer size from the tracer instance. |
_overflowBufferSize = 0; |
Uint32 traceAreaSize = |
|
Tracer::_getInstance()->_traceMemoryBufferSize * 1024; |
| |
_traceArea = (struct traceArea_t*) new char[traceAreaSize]; | _traceArea = (struct traceArea_t*) new char[traceAreaSize]; |
| |
// The final buffer size is the size of the allocated area, less the | // The final buffer size is the size of the allocated area, less the |
// size of the header struct, less one byte reseved for a terminating 0 | // size of the header struct, less one byte reseved for a terminating 0 |
_traceArea->bufferSize = traceAreaSize - sizeof(struct traceArea_t); |
_traceArea->bufferSize = traceAreaSize - sizeof(struct traceArea_t) - 1; |
_traceArea->bufferSize--; |
|
_traceArea->nextPos = 0; | _traceArea->nextPos = 0; |
|
_traceArea->traceBuffer = (char*) (&(_traceArea->traceBuffer) + 1); |
_leftBytesInBuffer = _traceArea->bufferSize-1; | _leftBytesInBuffer = _traceArea->bufferSize-1; |
| |
memcpy(_traceArea->eyeCatcher, | memcpy(_traceArea->eyeCatcher, |
|
|
// The memory tracing is about to end. | // The memory tracing is about to end. |
// The caller will never get the lock. | // The caller will never get the lock. |
_inUseCounter.dec(); | _inUseCounter.dec(); |
return false; |
break; |
} | } |
| |
// If the lock counter not 1,an other caller is in the critical section. | // If the lock counter not 1,an other caller is in the critical section. |
|
|
//////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// |
void TraceMemoryHandler::dumpTraceBuffer(const char* filename) | void TraceMemoryHandler::dumpTraceBuffer(const char* filename) |
{ | { |
|
if (!filename) |
|
{ |
|
// if the file name is empty/NULL pointer do nothing |
|
return; |
|
} |
|
#ifdef PEGASUS_DEBUG |
cerr << "Number of lock contentions is <"<< _contentionCount.get() | cerr << "Number of lock contentions is <"<< _contentionCount.get() |
<< ">" << endl; | << ">" << endl; |
cerr << "Number of obtained locks is <"<< _numberOfLocksObtained | cerr << "Number of obtained locks is <"<< _numberOfLocksObtained |
<< ">" << endl; | << ">" << endl; |
|
#endif |
| |
ofstream ofile(filename,ios::app&ios::out); | ofstream ofile(filename,ios::app&ios::out); |
if( ofile.good() ) | if( ofile.good() ) |
|
|
return; | return; |
} | } |
| |
|
|
|
// If the trace memory is not initialized. |
|
if(!_traceArea) |
|
{ |
|
_initializeTraceArea(); |
|
} |
|
|
|
Uint32 msgStart = _traceArea->nextPos; |
// Handle the static part of the message | // Handle the static part of the message |
_appendSimpleMessage(message, msgLen); | _appendSimpleMessage(message, msgLen); |
| |
|
|
// buffer. | // buffer. |
// To save memory allocations, the overflow buffer is kept around | // To save memory allocations, the overflow buffer is kept around |
// until it becomes to small and needs to be reallocated. | // until it becomes to small and needs to be reallocated. |
if ((Uint32)ttlMsgLen > _overflowBufferSize) |
if (ttlMsgLen == -1 || (msgLen + ttlMsgLen) > _traceArea->bufferSize) |
|
{ |
|
// The message does not fit in the remaining buffer and |
|
// vsnprintf() did not return the bytes needed |
|
// or the message is larger then the treace Buffer. |
|
|
|
// The message does not fit in the remaining buffer, |
|
// clean up the the message fragment. |
|
_traceArea->traceBuffer[msgStart] = 0; |
|
|
|
// Wrap the buffer |
|
_traceArea->nextPos = 0; |
|
_leftBytesInBuffer = _traceArea->bufferSize; |
|
|
|
// Rewrite the static part of the message |
|
_appendSimpleMessage(message, msgLen); |
|
|
|
// Rewrite the variable part of the message |
|
#ifdef PEGASUS_OS_TYPE_WINDOWS |
|
// Windows until VC 8 does not support vsnprintf |
|
// need to use Windows equivalent function with the underscore |
|
ttlMsgLen = |
|
_vsnprintf(&(_traceArea->traceBuffer[_traceArea->nextPos]), |
|
_leftBytesInBuffer, |
|
fmt, |
|
argListCopy); |
|
#else |
|
ttlMsgLen = |
|
vsnprintf(&(_traceArea->traceBuffer[_traceArea->nextPos]), |
|
_leftBytesInBuffer, |
|
fmt, |
|
argListCopy); |
|
#endif |
|
if (ttlMsgLen == -1 || |
|
(msgLen + ttlMsgLen) > _traceArea->bufferSize) |
|
{ |
|
// The message still does not fit in the buffer, but know |
|
// we know that the most part of the message is in the buffer. |
|
// Truncate the message using the truncation marker and leave |
|
// space for the EOT marker + '\n'. |
|
_leftBytesInBuffer = PEGASUS_TRC_BUFFER_TRUNC_MARKER_LEN + |
|
PEGASUS_TRC_BUFFER_EOT_MARKER_LEN + 1 ; |
|
|
|
_traceArea->nextPos = |
|
_traceArea->bufferSize - _leftBytesInBuffer ; |
|
|
|
// copy the marker including the trailing '0' ! |
|
memcpy(&(_traceArea->traceBuffer[_traceArea->nextPos]), |
|
PEGASUS_TRC_BUFFER_TRUNC_MARKER, |
|
PEGASUS_TRC_BUFFER_TRUNC_MARKER_LEN + 1 ); |
|
|
|
_traceArea->nextPos += PEGASUS_TRC_BUFFER_TRUNC_MARKER_LEN + 1; |
|
} |
|
else |
|
{ |
|
// Now the message fits into the buffer. |
|
ttlMsgLen++; //Include the '/0' |
|
|
|
_traceArea->nextPos += ttlMsgLen; |
|
_leftBytesInBuffer -= ttlMsgLen; |
|
} |
|
} // End of vsnprintf() == -1 or message > buffer size |
|
else |
|
{ |
|
// vsnprintf() retuns number of bytes of the variable message and |
|
// the Message fits in the buffer. |
|
if ((Uint32)ttlMsgLen >= _overflowBufferSize) |
{ | { |
if (_overflowBuffer != NULL ) | if (_overflowBuffer != NULL ) |
{ | { |
delete[] _overflowBuffer; | delete[] _overflowBuffer; |
} | } |
_overflowBufferSize = ttlMsgLen; |
_overflowBufferSize = ttlMsgLen+1; |
_overflowBuffer = new char[_overflowBufferSize]; | _overflowBuffer = new char[_overflowBufferSize]; |
} | } |
| |
|
|
argListCopy); | argListCopy); |
#endif | #endif |
| |
|
// The actual number of characters written to the buffer is the |
|
// number of bytes left in the buffer minus the trailing '/0'. |
|
Uint32 numCharsWritten = _leftBytesInBuffer-1; |
| |
// Now calculate how much data we have to copy from the overflow | // Now calculate how much data we have to copy from the overflow |
// buffer back to the trace buffer. | // buffer back to the trace buffer. |
ttlMsgLen -= _leftBytesInBuffer; |
ttlMsgLen -= numCharsWritten; |
| |
// Copy the remainder of the trace message to the trace buffer | // Copy the remainder of the trace message to the trace buffer |
memcpy(&(_traceArea->traceBuffer[0]), | memcpy(&(_traceArea->traceBuffer[0]), |
&(_overflowBuffer[_leftBytesInBuffer]), |
&(_overflowBuffer[numCharsWritten]), |
ttlMsgLen ); | ttlMsgLen ); |
| |
_traceArea->nextPos = ttlMsgLen+1; | _traceArea->nextPos = ttlMsgLen+1; |
_leftBytesInBuffer = _traceArea->bufferSize - _traceArea->nextPos; | _leftBytesInBuffer = _traceArea->bufferSize - _traceArea->nextPos; |
} | } |
|
} // End of reached end of buffer and need to wrap. |
| |
// replace null terminator with line break | // replace null terminator with line break |
_traceArea->traceBuffer[_traceArea->nextPos-1] = '\n'; | _traceArea->traceBuffer[_traceArea->nextPos-1] = '\n'; |
|
|
return; | return; |
} | } |
| |
|
// If the trace memory is not initialized. |
|
if(!_traceArea) |
|
{ |
|
_initializeTraceArea(); |
|
} |
|
|
// We include the terminating 0 in the message for easier handling | // We include the terminating 0 in the message for easier handling |
msgLen++; | msgLen++; |
| |
|
|
} | } |
| |
//////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// |
// Checks if a given message file is usable |
|
//////////////////////////////////////////////////////////////////////////////// |
|
Boolean TraceMemoryHandler::isValidMessageDestination(const char* traceFileName) |
|
{ |
|
TraceFileHandler traceFileHandler; |
|
|
|
return traceFileHandler.isValidMessageDestination( traceFileName ); |
|
} |
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
// Sets the message file in case we need to flush out the trace |
|
//////////////////////////////////////////////////////////////////////////////// |
|
Uint32 TraceMemoryHandler::setMessageDestination(const char* destination) |
|
{ |
|
delete[] _traceFileName; |
|
|
|
_traceFileName = new char[strlen(destination)+1]; |
|
strcpy(_traceFileName, destination); |
|
|
|
return 0; |
|
} |
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
// Flushes the trace | // Flushes the trace |
//////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// |
void TraceMemoryHandler::flushTrace() | void TraceMemoryHandler::flushTrace() |
{ | { |
dumpTraceBuffer(_traceFileName); |
dumpTraceBuffer((const char*)Tracer::_getInstance() |
|
->_traceFile.getCString()); |
} | } |
| |
PEGASUS_NAMESPACE_END | PEGASUS_NAMESPACE_END |