blob: 7b038855e9b57cf352aacd0cb4cd49a671799d74 [file]
///////////////////////////////////////////////////////////////////////////////
//
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
//
///////////////////////////////////////////////////////////////////////////////
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
using namespace std;
#include "tctrace.h"
#define TC_PROCESS_PATH_MAX 256
const char *CTrafConfigTrace::strTraceEnable_ = "TC_TRACE_ENABLE";
const char *CTrafConfigTrace::strTraceFile_ = "TC_TRACE_FILE";
const char *CTrafConfigTrace::strTraceFileFb_ = "TC_TRACE_FILE_FB";
const CTrafConfigTrace::TraceArea_t CTrafConfigTrace::traceAreaList_[] =
{
{"TC_TRACE_REQUEST", TC_TRACE_REQUEST},
{"TC_TRACE_NODE", TC_TRACE_NODE},
{"TC_TRACE_PERSIST", TC_TRACE_PERSIST},
{"TC_TRACE_PROCESS", TC_TRACE_PROCESS},
{"TC_TRACE_REGISTRY", TC_TRACE_REGISTRY},
{"TC_TRACE_INIT", TC_TRACE_INIT},
{"TC_TRACE_LOG_MSG", TC_TRACE_LOG_MSG},
{"TC_TRACE_ENTRY_EXIT", TC_TRACE_ENTRY_EXIT}
};
// Global trace flags
long TcTraceSettings = 0;
CTrafConfigTrace::CTrafConfigTrace()
: tracingEnabled_(false)
, traceSettingsSaved_(0)
, traceFileFb_(0)
, traceFileBase_(NULL)
{
numTraceAreas_ = (int)(sizeof(traceAreaList_)/sizeof(TraceArea_t));
}
const char *CTrafConfigTrace::GetEnvStr(const char *key)
{
const char *value;
value = getenv(key);
return value;
}
void CTrafConfigTrace::GetEnvInt(const char *key, int &val)
{
const char *p = GetEnvStr(key);
if (p != NULL)
{
val = atoi(p);
}
}
bool CTrafConfigTrace::GetEnvBool(const char *key)
{
const char *p = GetEnvStr(key);
bool val = false;
if (p != NULL)
{
val = atoi(p);
}
return val;
}
void CTrafConfigTrace::TraceClose( void )
{
trace_close();
}
void CTrafConfigTrace::TraceInit( bool traceEnabled
, const char *traceLevel
, const char *pfname)
{
bool pathnameUsed = false;
char trace_file_name[TC_PROCESS_PATH_MAX];
char hostname[TC_PROCESS_PATH_MAX];
tracingEnabled_ = traceEnabled;
if (gethostname(hostname,sizeof(hostname)) == -1)
{
sprintf( hostname,"TC");
}
if (pfname == NULL)
{ // Caller did not specify a trace file name, get name from
// environment variable if specified.
pfname = GetEnvStr(strTraceFile_);
}
if (pfname == NULL)
{ // Use default prefix
pfname = "tctrace";
}
if (pfname != NULL)
{ // User specified trace file name
if ( pfname[0] == '/')
{
// Use filename passed in
strcpy(trace_file_name, pfname);
pathnameUsed = true;
}
else
{
// Format default trace file name and remove any existing trace file.
if( getenv("SQ_VIRTUAL_NODES") )
{
sprintf( trace_file_name,"%s/trafconfig.trace.%d.%s"
, getenv("MPI_TMPDIR")
, getpid()
, hostname);
}
else
{
sprintf( trace_file_name,"%s/trafconfig.trace.%s"
, getenv("MPI_TMPDIR")
, hostname);
}
if ((strcmp(pfname, "STDOUT") == 0)
|| strcmp(pfname, "STDERR") == 0)
{
strcpy(trace_file_name, pfname);
}
else // Make user specified file name unique per node
{
sprintf(trace_file_name,"%s/%s.%d.%s"
, getenv("MPI_TMPDIR")
, pfname
, getpid()
, hostname);
}
}
}
if (!pathnameUsed)
{
remove(trace_file_name);
}
// Get any trace settings that were specified via environment variables
const char *value;
for (int i=0; i<numTraceAreas_; i++)
{
value = getenv(traceAreaList_[i].id);
if (value != NULL)
{
if (atoi(value) != 0)
// set the enabled flag for this trace area
TcTraceSettings |= traceAreaList_[i].bitFlag;
}
}
if (!tracingEnabled_)
{
// Get environment variable specifying whether tracing is enabled
tracingEnabled_ = GetEnvBool(strTraceEnable_);
// Get environment variable value for trace buffer size if specified
GetEnvInt(strTraceFileFb_, traceFileFb_);
}
// Convert the user specified trace level string to a number. The
// number can be specified as a decimal, octal or hexadecimal
// constant. Combine these flags with current TcTraceSettings that
// may have been set via environment variables.
long trace_flags;
trace_flags = strtol(traceLevel, NULL, 0);
if (errno != ERANGE)
{
TcTraceSettings |= trace_flags;
}
// If any trace settings were specified initialize the trace file
if (TcTraceSettings != 0 || tracingEnabled_)
{
traceSettingsSaved_ = TcTraceSettings;
if (pfname != NULL)
{
trace_init(trace_file_name,
false, // don't append pid to file name
pathnameUsed?(char*)"":(char*)"trafconfig", // file prefix
false);
if (traceFileFb_ > 0)
{
trace_set_mem(traceFileFb_);
}
}
}
}
void CTrafConfigTrace::TraceHelpBool( const char *key
, const char *value
, const char *key_cmp
, bool &value_ret )
{
if ((key != NULL) && (strcasecmp(key, key_cmp) == 0))
{
value_ret = atoi(value);
}
}
void CTrafConfigTrace::TraceHelpInt( const char *key
, const char *value
, const char *key_cmp
, int &value_ret )
{
if ((key != NULL) && (strcasecmp(key, key_cmp) == 0))
{
value_ret = atoi(value);
}
}
const char *CTrafConfigTrace::TraceHelpStr( const char *key
, const char *value
, const char *key_cmp )
{
if ((key != NULL) && (strcasecmp(key, key_cmp) == 0))
{
return value;
}
return NULL;
}
void CTrafConfigTrace::TraceChange(const char *key, const char *value)
{
bool trace_was_enabled = tracingEnabled_;
const char *pfname;
int old_fb = traceFileFb_;
if (key == NULL)
return;
// Restore saved trace settings in case trace flags get modified
TcTraceSettings = traceSettingsSaved_;
// Compare the key with each of the trace flag strings. When
// there is an equal compare, assign the value to the appropriate flag.
for (int i=0; i<numTraceAreas_; i++)
{
if (strcasecmp(key, traceAreaList_[i].id) == 0)
{
if (atoi(value) != 0)
{
// set the enabled flag for this trace area
TcTraceSettings |= traceAreaList_[i].bitFlag;
}
else // clear the enabled flag for this trace area
{
TcTraceSettings &= ~traceAreaList_[i].bitFlag;
}
break;
}
}
// Save current trace settings
traceSettingsSaved_ = TcTraceSettings;
// Check if tracing is being enabled/disabled
TraceHelpBool(key, value, strTraceEnable_, tracingEnabled_);
// Check if trace file buffer size is being specified
TraceHelpInt(key, value, strTraceFileFb_, traceFileFb_);
// Check if trace file base name is being specified
pfname = TraceHelpStr(key, value, strTraceFile_);
if (pfname != NULL)
{ // Save trace file base name
delete [] traceFileBase_;
traceFileBase_ = new char[strlen(pfname) + 1];
strcpy(traceFileBase_, pfname);
}
if (!trace_was_enabled && tracingEnabled_)
{
char fname[TC_PROCESS_PATH_MAX];
char hostname[TC_PROCESS_PATH_MAX];
if (gethostname(hostname,sizeof(hostname)) == -1)
{
sprintf( hostname,"TC");
}
// Formulate trace file name
if (traceFileBase_ != NULL)
{ // User specified trace file name
if ((strcmp(traceFileBase_, "STDOUT") == 0)
|| strcmp(traceFileBase_, "STDERR") == 0)
{
strcpy(fname, traceFileBase_);
}
else
{ // Make user specified file name unique per node
sprintf( fname,"%s/%s.%d.%s"
, getenv("MPI_TMPDIR")
, traceFileBase_
, getpid()
, hostname);
}
}
else
{ // No user specified trace file name, use default
if( getenv("SQ_VIRTUAL_NODES") )
{
sprintf( fname,"%s/trafconfig.trace.%d.%s"
, getenv("MPI_TMPDIR")
, getpid()
, hostname);
}
else
{
sprintf( fname,"%s/trafconfig.trace.%s"
, getenv("MPI_TMPDIR")
, hostname);
}
}
// Tracing was disabled and is now enabled, initialize trace
trace_init(fname,
false, // don't append pid to file name
hostname, // prefix
false);
}
if (trace_was_enabled && !tracingEnabled_)
{
// Tracing was enabled and now is disabled, flush trace. Save
// current trace settings.
trace_flush();
TcTraceSettings = 0;
}
// If a new trace file buffer size was specified, set it
if ((traceFileFb_ > 0) && (old_fb != traceFileFb_))
trace_set_mem(traceFileFb_);
}