ICU-2403 tracing, changes from code review

X-SVN-Rev: 13792
This commit is contained in:
Andy Heninger 2003-11-20 20:04:34 +00:00
parent 5538a4c0b7
commit 9ded263c4a
6 changed files with 145 additions and 120 deletions

View File

@ -31,21 +31,20 @@ U_CDECL_BEGIN
* @draft ICU 2.8
*/
enum UTraceLevel {
/** Disable all tracing */
typedef enum UTraceLevel {
/** Disable all tracing @draft ICU 2.8*/
UTRACE_OFF=-1,
/** Trace error conditions only */
/** Trace error conditions only @draft ICU 2.8*/
UTRACE_ERROR=0,
/** Trace errors and warnings */
/** Trace errors and warnings @draft ICU 2.8*/
UTRACE_WARNING=3,
/** Trace opens and closes of ICU services */
/** Trace opens and closes of ICU services @draft ICU 2.8*/
UTRACE_OPEN_CLOSE=5,
/** Trace an intermediate number of ICU operations */
/** Trace an intermediate number of ICU operations @draft ICU 2.8*/
UTRACE_INFO=7,
/** Trace the maximum number of ICU operations */
/** Trace the maximum number of ICU operations @draft ICU 2.8*/
UTRACE_VERBOSE=9
};
typedef enum UTraceLevel UTraceLevel;
} UTraceLevel;
/**
@ -89,7 +88,7 @@ UTraceEntry(const void *context, int32_t fnNumber);
*/
typedef void U_CALLCONV
UTraceExit(const void *context, int32_t fnNumber,
int32_t argType, va_list args);
const char *fmt, va_list args);
/**
* Type signature for the trace function to be called from within an ICU function
@ -109,6 +108,12 @@ UTraceData(const void *context, int32_t fnNumber, int32_t level,
* of the use of ICU. Passing a NULL pointer for a tracing function
* is allowed, and inhibits tracing action at points where that function
* would be called.
* <p>
* Tracing and Threads: Tracing functions are global to a process, and
* will be called in response to ICU operations performed by any
* thread. If tracing of an individual thread is desired, the
* tracing functions must themselves filter by checking that the
* current thread is the desired thread.
*
* @param context an uninterpretted pointer. Whatever is passed in
* here will in turn be passed to each of the tracing
@ -244,8 +249,8 @@ utrace_getFunctions(const void **context,
/**
* Trace output Formatter. An application's UTraceData tracing functions may call
* back to this function to format the trace output in a
* human readable form. Note that a UTraceData function is not
* required to format the data; it could, for example, save it in
* human readable form. Note that a UTraceData function may choose
* to not format the data; it could, for example, save it in
* in the raw form it was received (more compact), leaving
* formatting for a later trace analyis tool.
* @param outBuf pointer to a buffer to receive the formatted output. Output
@ -264,56 +269,28 @@ U_CAPI int32_t U_EXPORT2
utrace_format(char *outBuf, int32_t capacity,
int32_t indent, const char *fmt, va_list args);
/**
* Traced Function Exit return types.
* Flags indicating the number and types of varargs included in a call
* to a UTraceExit function.
* Bits 0-3: The function return type. First variable param.
* Bit 4: Flag for presence of U_ErrorCode status param.
* @draft ICU 2.8
*/
enum UTraceExitVal {
/** The traced function returns no value */
UTRACE_EXITV_NONE = 0,
/** The traced function returns an int32_t, or compatible, type. */
UTRACE_EXITV_I32 = 1,
/** The traced function returns a pointer */
UTRACE_EXITV_PTR = 2,
/** The traced function returns a UBool */
UTRACE_EXITV_BOOL = 3,
/** Mask to extract the return type values from a UTraceExitVal */
UTRACE_EXITV_MASK = 0xf,
/** Bit indicating that the traced function includes a UErrorCode parameter */
UTRACE_EXITV_STATUS = 0x10
};
typedef enum UTraceExitVal UTraceExitVal;
/**
* Trace formatter for UTraceExit, function exit tracing.
* UTraceExit may optionally receive two data items: a function return value
* and a UErrorCode status value.
*
* @param outBuf pointer to a buffer to receive the formatted output.Output
* Trace output Formatter. An application's UTraceData tracing functions may call
* this function to format any additional trace data, beyond that
* provided by default, in human readable form with the same
* formatting conventions used by utrace_format().
* @param outBuf pointer to a buffer to receive the formatted output. Output
* will be nul terminated if there is space in the buffer -
* if the length of the requested output < the output buffer size.
* @param capacity Length of the output buffer.
* @param indent Number of spaces to indent the output. Intended to allow
* data displayed from nested functions to be indented for readability.
* @param fnNumber An index specifying the function that is exiting.
* @param argType Flags specifying the number and types of data values.
* @param args Data to be formatted. If argType parameter indicates that a function
* return value exists, it will be the first varargs param. The
* function's UErrorCode status will be next, when applicable.
* @param fmt Format specification for the data to output
* @param ... Data to be formatted.
* @return Length of formatted output, including the terminating NUL.
* If buffer capacity is insufficient, the required capacity is returned.
* @draft ICU 2.8
*/
U_CAPI int32_t U_EXPORT2
utrace_formatA(char *outBuf, int32_t capacity,
int32_t indent, const char *fmt, ...);
U_CAPI void U_EXPORT2
utrace_formatExit(char *outBuf, int32_t capacity, int32_t indent,
int32_t fnNumber, int32_t argtype, va_list args);
/* Trace function numbers --------------------------------------------------- */
@ -331,8 +308,9 @@ utrace_functionName(int32_t fnNumber);
/**
* These are the ICU functions that will be traced when tracing is enabled.
* @draft ICU 2.8
*/
enum UTraceFunctionNumber {
typedef enum UTraceFunctionNumber {
UTRACE_FUNCTION_START=0,
UTRACE_U_INIT=UTRACE_FUNCTION_START,
UTRACE_U_CLEANUP,
@ -353,8 +331,7 @@ enum UTraceFunctionNumber {
UTRACE_UCOL_NEXTSORTKEYPART,
UTRACE_UCOL_STRCOLLITER,
UTRACE_COLLATION_LIMIT
};
typedef enum UTraceFunctionNumber UTraceFunctionNumber;
} UTraceFunctionNumber;
U_CDECL_END

View File

@ -11,6 +11,7 @@
#define UTRACE_IMPL
#include "unicode/utrace.h"
#include "utracimp.h"
#include "cstring.h"
#include "uassert.h"
@ -31,13 +32,41 @@ utrace_entry(int32_t fnNumber) {
}
static const char gExitFmt[] = "Returns.";
static const char gExitFmtValue[] = "Returns %d.";
static const char gExitFmtStatus[] = "Returns. Status = %d.";
static const char gExitFmtValueStatus[] = "Returns %d. Status = %d.";
static const char gExitFmtPtrStatus[] = "Returns %d. Status = %p.";
U_CAPI void U_EXPORT2
utrace_exit(int32_t fnNumber, int32_t returnType, ...) {
if (pTraceExitFunc != NULL) {
va_list args;
const char *fmt;
switch (returnType) {
case 0:
fmt = gExitFmt;
break;
case UTRACE_EXITV_I32:
fmt = gExitFmtValue;
break;
case UTRACE_EXITV_STATUS:
fmt = gExitFmtStatus;
break;
case UTRACE_EXITV_I32 | UTRACE_EXITV_STATUS:
fmt = gExitFmtValueStatus;
break;
case UTRACE_EXITV_PTR | UTRACE_EXITV_STATUS:
fmt = gExitFmtPtrStatus;
break;
default:
U_ASSERT(FALSE);
fmt = gExitFmt;
}
va_start(args, returnType);
(*pTraceExitFunc)(gTraceContext, fnNumber, returnType, args);
(*pTraceExitFunc)(gTraceContext, fnNumber, fmt, args);
va_end(args);
}
}
@ -57,6 +86,28 @@ utrace_data(int32_t fnNumber, int32_t level, const char *fmt, ...) {
static void outputChar(char c, char *outBuf, int32_t *outIx, int32_t capacity, int32_t indent) {
int32_t i;
/* Check whether a start of line indenting is needed. Three cases:
* 1. At the start of the first line (output index == 0).
* 2. At the start of subsequent lines (preceeding char in buffer == '\n')
* 3. When preflighting buffer len (buffer capacity is exceeded), when
* a \n is output. Ideally we wouldn't do the indent until the following char
* is received, but that won't work because there's no place to remember that
* the preceding char was \n. Meaning that we may overstimate the
* buffer size needed. No harm done.
*/
if (*outIx==0 || /* case 1. */
c!='\n' && c!=0 && *outIx < capacity && outBuf[(*outIx)-1]=='\n' || /* case 2. */
c=='\n' && *outIx>=capacity) /* case 3 */
{
/* At the start of a line. Indent. */
for(i=0; i<indent; i++) {
if (*outIx < capacity) {
outBuf[*outIx] = ' ';
}
(*outIx)++;
}
}
if (*outIx < capacity) {
outBuf[*outIx] = c;
}
@ -66,16 +117,6 @@ static void outputChar(char c, char *outBuf, int32_t *outIx, int32_t capacity, i
* following output will overwrite the null. */
(*outIx)++;
}
/* Handle indenting at the start of lines */
if (c == '\n') {
for(i=0; i<indent; i++) {
if (*outIx < capacity) {
outBuf[*outIx] = ' ';
}
(*outIx)++;
}
}
}
static void outputHexBytes(int64_t val, int32_t charsToOutput,
@ -261,7 +302,7 @@ utrace_format(char *outBuf, int32_t capacity, int32_t indent, const char *fmt, v
ptrPtr = (void **)i8Ptr;
vectorLen =(int32_t)va_arg(args, int32_t);
if (ptrPtr == NULL) {
outputString("NULL", outBuf, &outIx, capacity, indent);
outputString("*NULL* ", outBuf, &outIx, capacity, indent);
} else {
for (i=0; i<vectorLen || vectorLen==-1; i++) {
switch (vectorType) {
@ -340,41 +381,17 @@ utrace_format(char *outBuf, int32_t capacity, int32_t indent, const char *fmt, v
}
U_CAPI void U_EXPORT2
utrace_formatExit(char *outBuf, int32_t capacity, int32_t indent,
int32_t fnNumber, int32_t argType, va_list args) {
int32_t outIx = 0;
int32_t intVal;
UBool boolVal;
void *ptrVal;
UErrorCode status;
outputString(utrace_functionName(fnNumber), outBuf, &outIx, capacity, indent);
outputString(" returns", outBuf, &outIx, capacity, indent);
switch (argType & UTRACE_EXITV_MASK) {
case UTRACE_EXITV_I32:
outputChar(' ', outBuf, &outIx, capacity, indent);
intVal = (int32_t)va_arg(args, int32_t);
outputHexBytes(intVal, 8, outBuf, &outIx, capacity);
break;
case UTRACE_EXITV_PTR:
outputChar(' ', outBuf, &outIx, capacity, indent);
ptrVal = (void *)va_arg(args, void *);
outputPtrBytes(ptrVal, outBuf, &outIx, capacity);
break;
case UTRACE_EXITV_BOOL:
outputChar(' ', outBuf, &outIx, capacity, indent);
boolVal = (UBool)va_arg(args, int32_t); /* gcc wants int, not UBool */
outputString(boolVal? "TRUE": "FALSE", outBuf, &outIx, capacity, indent);
}
outputString(".", outBuf, &outIx, capacity, indent);
if (argType & UTRACE_EXITV_STATUS) {
outputString(" Status = ", outBuf, &outIx, capacity, indent);
status = (UErrorCode)va_arg(args, UErrorCode);
outputString(u_errorName(status), outBuf, &outIx, capacity, indent);
}
outputChar(0, outBuf, &outIx, capacity, indent);
U_CAPI int32_t U_EXPORT2
utrace_formatA(char *outBuf, int32_t capacity,
int32_t indent, const char *fmt, ...) {
int32_t retVal;
va_list args;
va_start(args, fmt );
retVal = utrace_format(outBuf, capacity, indent, fmt, args);
va_end(args);
return retVal;
}

View File

@ -127,6 +127,31 @@ utrace_level;
}
/**
* Traced Function Exit return types.
* Flags indicating the number and types of varargs included in a call
* to a UTraceExit function.
* Bits 0-3: The function return type. First variable param.
* Bit 4: Flag for presence of U_ErrorCode status param.
* @internal
*/
typedef enum UTraceExitVal {
/** The traced function returns no value @internal */
UTRACE_EXITV_NONE = 0,
/** The traced function returns an int32_t, or compatible, type. @internal */
UTRACE_EXITV_I32 = 1,
/** The traced function returns a pointer @internal */
UTRACE_EXITV_PTR = 2,
/** The traced function returns a UBool @internal */
UTRACE_EXITV_BOOL = 3,
/** Mask to extract the return type values from a UTraceExitVal @internal */
UTRACE_EXITV_MASK = 0xf,
/** Bit indicating that the traced function includes a UErrorCode parameter @internal */
UTRACE_EXITV_STATUS = 0x10
} UTraceExitVal;
/**
* Trace statement for each exit point of a function that has a UTRACE_ENTRY()
* statement.

View File

@ -8613,16 +8613,8 @@ ucol_strcoll( const UCollator *coll,
UTRACE_ENTRY(UTRACE_UCOL_STRCOLL);
if (UTRACE_LEVEL(UTRACE_VERBOSE)) {
UTRACE_DATA3(UTRACE_VERBOSE, "coll=%p, source=%p, target=%p", coll, source, target);
int32_t actualLen = sourceLength;
if (actualLen==-1 && source!=NULL) {
actualLen = u_strlen(source);
}
UTRACE_DATA2(UTRACE_VERBOSE, "source string = %vh ", source, actualLen);
actualLen = targetLength;
if (actualLen==-1 && target!=NULL) {
actualLen = u_strlen(target);
}
UTRACE_DATA2(UTRACE_VERBOSE, "target string = %vh ", target, actualLen);
UTRACE_DATA2(UTRACE_VERBOSE, "source string = %vh ", source, sourceLength);
UTRACE_DATA2(UTRACE_VERBOSE, "target string = %vh ", target, targetLength);
}
UErrorCode status = U_ZERO_ERROR;

View File

@ -64,24 +64,31 @@ void ctest_setICU_DATA(void);
*/
static int traceFnNestingDepth = 0;
void U_CALLCONV TraceEntry(const void *context, int32_t fnNumber) {
fprintf(stdout, "%s() Enter \n", utrace_functionName(fnNumber));
char buf[500];
utrace_formatA(buf, sizeof(buf), traceFnNestingDepth*3, "%s() enter.\n", utrace_functionName(fnNumber));
fputs(buf, stdout);
traceFnNestingDepth++;
}
void U_CALLCONV TraceExit(const void *context, int32_t fnNumber, int32_t type, va_list args) {
char buf[2000];
void U_CALLCONV TraceExit(const void *context, int32_t fnNumber, const char *fmt, va_list args) {
char buf[500];
if (traceFnNestingDepth>0) {
traceFnNestingDepth--;
}
utrace_formatExit(buf, sizeof(buf), traceFnNestingDepth*3, fnNumber, type, args);
fprintf(stdout, "%s\n", buf);
utrace_formatA(buf, sizeof(buf), traceFnNestingDepth*3, "%s() ", utrace_functionName(fnNumber));
fputs(buf, stdout);
utrace_format(buf, sizeof(buf), traceFnNestingDepth*3, fmt, args);
fputs(buf, stdout);
putc('\n', stdout);
}
void U_CALLCONV TraceData(const void *context, int32_t fnNumber,
int32_t level, const char *fmt, va_list args) {
char buf[2000];
char buf[500];
utrace_format(buf, sizeof(buf), traceFnNestingDepth*3, fmt, args);
fprintf(stdout, "%s\n", buf);
fputs(buf, stdout);
putc('\n', stdout);
}

View File

@ -95,7 +95,7 @@ void testTraceEntry(const void *context, int32_t fnNumber) {
}
void testTraceExit(const void *context, int32_t fnNumber,
int32_t argType, va_list args) {
const char *fmt, va_list args) {
}
void testTraceData(const void *context, int32_t fnNumber, int32_t level,
@ -185,11 +185,12 @@ static void TestTraceAPI() {
test_format("a 32 bit val %d...", 50, 0, "a 32 bit val 6789abcd...", __LINE__, 0x6789abcd);
test_format("a 64 bit val %l", 50, 0, "a 64 bit val 123456780abcdef0"
, __LINE__, INT64_C(0x123456780abcdef0));
if (sizeof(ptr) == 4) {
ptr = (void *)0xdeadbeef;
test_format("a 32 bit ptr %p", 50, 0, "a 32 bit ptr deadbeef", __LINE__, ptr);
} else if (sizeof(ptr) == 8) {
ptr = (void *)0x1000200030004000;
} else if (sizeof(void *) == 8) {
ptr = (void *) INT64_C(0x1000200030004000);
test_format("a 64 bit ptr %p", 50, 0, "a 64 bit ptr 1000200030004000", __LINE__, ptr);
} else {
TEST_ASSERT(FALSE);
@ -202,6 +203,12 @@ static void TestTraceAPI() {
test_format("%vb", 100, 0, "41 42 43 [00000003]", __LINE__, "ABC", 3);
/* Null ptrs for strings, vectors */
test_format("Null string - %s", 50, 0, "Null string - *NULL*", __LINE__, NULL);
test_format("Null string - %S", 50, 0, "Null string - *NULL*", __LINE__, NULL);
test_format("Null vector - %vc", 50, 0, "Null vector - *NULL* [00000002]", __LINE__, NULL, 2);
test_format("Null vector - %vC", 50, 0, "Null vector - *NULL* [00000002]", __LINE__, NULL, 2);
test_format("Null vector - %vd", 50, 0, "Null vector - *NULL* [00000002]", __LINE__, NULL, 2);
}