blob: 63b6221021da71cda86343552efa663dd00594c4 [file] [log] [blame]
/**********************************************************************
// @@@ 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 @@@
**********************************************************************/
/* -*-C++-*-
*****************************************************************************
*
* File: ComExeTrace.cpp
* Description: Common interface for all executor (run-time) traces
*
* Created: 10/26/2011
* Language: C++
*
*
*****************************************************************************
*/
#include "ComExeTrace.h"
// must match with ExeTrace::FieldType, see ComExeTrace.h
static const char * TraceFieldTypeName[] =
{
"NOTYPE ",
"CHAR ",
"INT16 ",
"INT32 ",
"INT64 ",
"STRING ",
"PTR32 ",
"PTR64 ",
"TRANSID", // transaction id (64-bit)
"TMSTAMP" // time stamp
};
// not really used
ExeTrace::ExeTrace(char *name, void *id, void *target,
GetALineProcPtr getALineProc,
void *indexLoc, Int32 numEntries, Int32 lineLen,
const char *desc)
: traceId_(id),
target_(target),
getALineProc_(getALineProc),
indexLoc_(indexLoc),
numEntries_(numEntries),
lineWidth_(lineLen)
{
describes_ = (char*) malloc(strlen(desc)+1);
strcpy(describes_, desc);
strncpy(name_, name, MAX_TRACE_NAME_LEN - 1);
};
//
// getTitleLineWidth - returned formatted line width based on the field name
//
Int32
ExeTrace::getTitleLineWidth()
{
Int32 len = 0;
for (CollIndex i = 0; i < (UInt32) numFields_; i++) {
len += (strlen(fields_[i].name_) + 1); // add 1 as field separator
}
return --len; // remove the last field separator just added
};
ExeTraceInfo::ExeTraceInfo()
: exeTraces_(NULL) // on C++ heap
{
};
ExeTraceInfo::~ExeTraceInfo()
{
};
//----------------------------------------------------------------
// getExeTraceInfoAll -- query all trace info registered and save to the buffer
//
// return value: >0 - the sequence number for next trace
// =0 - no more trace info to return
// parameters: outBuf - (i/o) give buffer to store trace info
// maxBufLen - (i) max buffer length
// bufLen - (o) actual buffer size filled
// startTid - (i) starting trace info to query
//
// The buffer contains trace information in ascii:
//
// e.g.
// <trace1_name> (id=<id>):
// <trace_desc>
// Number of entries: <value>
// Fields:
// <field1_name> <data_type>
// <field2_name> <data_type>
// ...
// End
//
// <trace2_name>:
// ...
//
//----------------------------------------------------------------
Int32
ExeTraceInfo::getExeTraceInfoAll(char *outBuf, Int32 maxBufLen,
Int32 *bufLen, Int32 startTid)
{
CollIndex curr = startTid;
Int32 len = 0;
*bufLen = 0;
if (exeTraces_.entries() <= curr)
return 0; // no more traces
for (; curr < exeTraces_.entries(); curr++)
{
ExeTrace *t = exeTraces_.at(curr);
// get the size of one exeTrace info first
Int32 totalSize = MAX_TRACE_NAME_LEN + 13 + sizeof(t->describes_) + 2;
totalSize += 2 + sizeof("Number of entries: ") + 4;
for (Int32 i = 0; i < t->numFields_; i++)
{
// 2 tabs + field name length + field type
totalSize += 4 + t->fields_[i].nameLen_ + 8;
}
totalSize += 4; // plus "End"
if (totalSize + *bufLen > maxBufLen)
return curr; // buffer not large enough and return what we had
// now start dump this trace info to the buffer
len += sprintf((outBuf+len),
"%s (id=%p):\n\t%s\n\tNumber of entries: %4d\n\tFields:\n",
t->name_, t->traceId_, t->describes_, t->numEntries_);
for (Int32 i = 0; i < t->numFields_; i++)
{
len += sprintf((outBuf+len), "\t\t%s %s\n",
TraceFieldTypeName[t->fields_[i].fieldType_],
t->fields_[i].name_);
}
len += sprintf((outBuf+len), "End\n");
*bufLen = len;
}
return (Int32) curr;
};
//----------------------------------------------------------------
// getExeTraceAll -- save all registered trace data in the buffer
//
// return value: >0 - the sequence number for next trace
// =0 - no more trace info to return
// parameters: outBuf - (i/o) give buffer to store trace info
// maxBufLen - (i) max buffer length
// bufLen - (o) actual buffer size filled
// startTid - (i) starting trace id to query
//
// The buffer contains formatted trace data one line per trace
// entry, followed by trace index value
//
// e.g.
// <trace1_name> (nid=<nid>, pid=<pid>, <value> entries):
// <field1_name> <field2_name> ...
// <field1_value> <field2_value> ...
// ......
// Current Index: <index>
//
// <trace2_name> (nid=<nid>, pid=<pid>, <value> entries):
// ...
//
// Note, given buffer outBuf should be big enough to hold data for
// at least one trace
//----------------------------------------------------------------
Int32
ExeTraceInfo::getExeTraceAll(char *outBuf, Int32 maxBufLen, Int32 *bufLen,
Int32 startTid)
{
*bufLen = 0;
return startTid;
};
//----------------------------------------------------------------
// getExeTraceId -- return trace id with given trace name
// return value: >0 - valid trace id
// =0 - no trace match the name
// parameters: name - trace name
// nameLen - length of the name
//----------------------------------------------------------------
void *
ExeTraceInfo::getExeTraceId(char *name, Int32 nameLen) const
{
UInt32 noTraces = exeTraces_.entries();
if (noTraces) {
for (CollIndex i = 0; i < noTraces; i++) {
if (strncmp(exeTraces_[i]->getTraceName(), name, nameLen) == 0)
// a match
return exeTraces_[i]->getTraceId();
}
// found no match
}
return 0;
};
//----------------------------------------------------------------
// getExeTraceInfoById -- query trace parameters with given trace id
// return value: <0 - no trace info for this trace id
// =0 - trace info returned completely
// >0 - returned partial info only, buffer too small
// parameters:
// traceId - (i) trace id to query
// outBuf - (i/o) give buffer to store trace info
// maxBufLen - (i) max buffer length
// bufLen - (o) actual buffer size filled
//
// Note, the buffer contents have the same format as in getExeTraceInfoAll
//
//----------------------------------------------------------------
Int32
ExeTraceInfo::getExeTraceInfoById(void *traceId, char *buf,
Int32 maxBufLen, Int32 *bufLen)
{
return 0;
};
//----------------------------------------------------------------
// getExeTraceById -- retreive trace data for given trace id
// return value: <0 - no trace data for this trace id
// =0 - trace data returned
// >0 - returned partial data only, buffer too small
// parameters:
// traceId - (i) trace id to query
// outBuf - (i/o) give buffer to store trace info
// maxBufLen - (i) max buffer length
// bufLen - (o) actual buffer size filled
//
// The buffer contains formatted trace data one line per trace
// entry, followed by trace index value
//
// e.g.
// Trace ID: <id>
// (<trace description>)
// <trace1_name> (<value> entries):
// <field1_name> <field2_name> ...
// <field1_value> <field2_value> ...
// ......
// Current Index: <index>
// End
//
//----------------------------------------------------------------
Int32
ExeTraceInfo::getExeTraceById(void *traceId, char *buf, Int32 maxBufLen,
Int32 *bufLen)
{
CollIndex curr = FIRST_COLL_INDEX;
Int32 len = 0;
*bufLen = len; // initializing
if (exeTraces_.entries() == 0)
{
return -1; // no more traces
}
ExeTrace *t = 0;
for (; curr < exeTraces_.entries(); curr++)
{
t = exeTraces_.at(curr);
if (t->getTraceId() == traceId)
break;
}
if (curr >= exeTraces_.entries())
return -1; // no such trace
// get the size of one exeTrace info first
// length of first and second lines, see above
Int32 totalSize = 21 + sizeof(t->describes_) + MAX_TRACE_NAME_LEN + 51;
// get the number of entries
Int32 nEntries = t->getNumEntries();
// the field name line
for (Int32 i = 0; i < t->numFields_; i++)
{
// field name length + space
totalSize += t->fields_[i].nameLen_ + 1;
}
totalSize += 6; // the field name line is adjusted to allow index column
// all lines of trace entries
totalSize += t->getLineWidth() + 1; // plus newline char
totalSize += 22; // current index
totalSize += 4; // plus "End"
if (totalSize + *bufLen > maxBufLen)
return totalSize; // buffer not large enough and return what we had
// now start dump this trace info to the buffer
if (nEntries >= 0)
len += sprintf((buf+len),
"\nTrace ID: %p\n(%s)\n%s Trace (%d entries):\n",
traceId, t->describes_, t->name_, nEntries);
else // the number of entries for this trace is not fixed
len += sprintf((buf+len),
"\nTrace ID: %p\n(%s)\n%s Trace (variable entries):\n",
traceId, t->describes_, t->name_);
// field name line
len += sprintf((buf+len), "Indx ");
for (Int32 i = 0; i < t->numFields_; i++)
{
len += sprintf((buf+len), "%s ", t->fields_[i].name_);
}
len += sprintf((buf+len), "\n");
// print trace entries
Int32 j = 0, plen = 0;
do {
plen = (t->getLineProc())(t->getTarget(), j++, (buf+len));
len += plen;
} while (plen); // keep printing until exhausted
Int32 idx = t->getIndex();
if (idx >= 0) // idx < 0 means that the trace has no cyclic buffer
len += sprintf((buf+len), "Current Index: %8d\n", idx);
len += sprintf((buf+len), "End\n");
*bufLen = len;
return 0;
};
//----------------------------------------------------------------
// addTrace - add trace to the trace info list
//----------------------------------------------------------------
Int32
ExeTraceInfo::addTrace(const char * traceName, void * traceId,
Int32 numEntries, Int32 numFields, void *target,
GetALineProcPtr getALineProc, void * indexLoc,
Int32 lineWidth, const char *desc,
void **exeTrace)
{
// to do: use globalheap?
ExeTrace *t = (ExeTrace *) malloc(sizeof(ExeTrace) +
numFields * sizeof(ExeTrace::TraceField));
*exeTrace = 0; // set to 0 initially
// in general, we don't like any of the followings to be 0
if (!t || !traceId || !getALineProc || !numFields || !lineWidth)
return -1;
// check if trace id already exists!
if (!isValidTraceId(traceId))
return -1;
strncpy(t->name_, traceName, MAX_TRACE_NAME_LEN-1);
t->name_[MAX_TRACE_NAME_LEN-1] = '\0';
t->traceId_ = traceId;
t->target_ = target;
t->getALineProc_ = getALineProc;
t->indexLoc_ = indexLoc;
t->numEntries_ = numEntries;
t->numFields_ = numFields;
t->lineWidth_ = lineWidth;
t->describes_ = (char*) malloc(strlen(desc)+1);
strcpy(t->describes_, desc);
// nullifies all field name and lenth
memset((char*)(t->fields_), 0, sizeof(ExeTrace::TraceField) * t->getNumFields());
// insert it to the list
exeTraces_.insert(t);
// give the trace back to caller as reference for later use
*exeTrace = t;
return 0;
};
void
ExeTraceInfo::addTraceField(void * exeTrace, const char * name,
UInt32 fieldIdx, ExeTrace::FieldType fType)
{
ExeTrace *t = (ExeTrace*) exeTrace;
if (!isRegistered(t))
return; // ignore error for now
if (fieldIdx >= (UInt32)t->getNumFields())
return; // ignore error for now
strncpy(t->fields_[fieldIdx].name_, name, MAX_FIELD_NAME_LEN-1);
t->fields_[fieldIdx].name_[MAX_FIELD_NAME_LEN-1] = '\0'; //null terminate
t->fields_[fieldIdx].nameLen_ = MINOF(strlen(name), MAX_FIELD_NAME_LEN-1);
t->fields_[fieldIdx].fieldType_ = fType;
};
void
ExeTraceInfo::removeTrace(void * exeTrace)
{
ExeTrace *t = (ExeTrace*) exeTrace;
if (!t)
return;
if (!isRegistered(t))
return;
exeTraces_.remove(t);
free(t->describes_);
free(t);
};