alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (debug_trace.c)

This example Java source code file (debug_trace.c) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

dassert, dmutex_enter, dmutex_exit, dtrace_clientprint, dtrace_file, dtrace_getinfo, dtrace_gettraceid, dtrace_line, dtrace_printstderr, dtrace_vprintimpl, dtraceinfo, jniexport, null, pfntracecallback

The debug_trace.c Java example source code

/*
 * Copyright (c) 1999, 2001, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#include "debug_util.h"

static void DTrace_PrintStdErr(const char *msg);

#if defined(DEBUG)
enum {
    MAX_TRACES = 200,           /* max number of defined trace points allowed */
    MAX_TRACE_BUFFER = 512,     /* maximum size of a given trace output */
    MAX_LINE = 100000,          /* reasonable upper limit on line number in source file */
    MAX_ARGC = 8                /* maximum number of arguments to print functions */
};

typedef enum dtrace_scope {
    DTRACE_FILE,
    DTRACE_LINE
} dtrace_scope;

typedef struct dtrace_info {
    char                file[FILENAME_MAX+1];
    int                 line;
    int                 enabled;
    dtrace_scope        scope;
} dtrace_info, * p_dtrace_info;

static dtrace_info      DTraceInfo[MAX_TRACES];
static char             DTraceBuffer[MAX_TRACE_BUFFER*2+1]; /* double the buffer size to catch overruns */
static dmutex_t         DTraceMutex = NULL;
static dbool_t          GlobalTracingEnabled = FALSE;
static int              NumTraces = 0;

static DTRACE_OUTPUT_CALLBACK   PfnTraceCallback = DTrace_PrintStdErr;

static p_dtrace_info DTrace_GetInfo(dtrace_id tid) {
    DASSERT(tid < MAX_TRACES);
    return &DTraceInfo[tid];
}

static dtrace_id DTrace_CreateTraceId(const char * file, int line, dtrace_scope scope) {
    dtrace_id           tid = NumTraces++;
    p_dtrace_info       info = &DTraceInfo[tid];
    DASSERT(NumTraces < MAX_TRACES);

    strcpy(info->file, file);
    info->line = line;
    info->enabled = FALSE;
    info->scope = scope;
    return tid;
}

/*
 * Compares the trailing characters in a filename to see if they match
 * e.g. "src\win32\foobar.c" and "foobar.c" would be considered equal
 * but "src\win32\foo.c" and "src\win32\bar.c" would not.
 */
static dbool_t FileNamesSame(const char * fileOne, const char * fileTwo) {
    size_t      lengthOne = strlen(fileOne);
    size_t      lengthTwo = strlen(fileTwo);
    size_t      numCompareChars;
    dbool_t     tailsEqual;

    if (fileOne == fileTwo) {
        return TRUE;
    } else if (fileOne == NULL || fileTwo == NULL) {
        return FALSE;
    }
    /* compare the tail ends of the strings for equality */
    numCompareChars = lengthOne < lengthTwo ? lengthOne : lengthTwo;
    tailsEqual = strcmp(fileOne + lengthOne - numCompareChars,
                        fileTwo + lengthTwo - numCompareChars) == 0;
    return tailsEqual;
}

/*
 * Finds the trace id for a given file/line location or creates one
 * if it doesn't exist
 */
static dtrace_id DTrace_GetTraceId(const char * file, int line, dtrace_scope scope) {
    dtrace_id           tid;
    p_dtrace_info       info;

    /* check to see if the trace point has already been created */
    for ( tid = 0; tid < NumTraces; tid++ ) {
        info = DTrace_GetInfo(tid);
        if ( info->scope == scope ) {
            dbool_t     sameFile = FileNamesSame(file, info->file);
            dbool_t     sameLine = info->line == line;

            if ( (info->scope == DTRACE_FILE && sameFile) ||
                 (info->scope == DTRACE_LINE && sameFile && sameLine) ) {
                goto Exit;
            }
        }
    }

    /* trace point wasn't created, so force it's creation */
    tid = DTrace_CreateTraceId(file, line, scope);
Exit:
    return tid;
}


static dbool_t DTrace_IsEnabledAt(dtrace_id * pfileid, dtrace_id * plineid, const char * file, int line) {
    DASSERT(pfileid != NULL && plineid != NULL);

    if ( *pfileid == UNDEFINED_TRACE_ID ) {
    /* first time calling the trace for this file, so obtain a trace id */
         *pfileid = DTrace_GetTraceId(file, -1, DTRACE_FILE);
    }
    if ( *plineid == UNDEFINED_TRACE_ID ) {
    /* first time calling the trace for this line, so obtain a trace id */
         *plineid = DTrace_GetTraceId(file, line, DTRACE_LINE);
    }

    return GlobalTracingEnabled || DTraceInfo[*pfileid].enabled || DTraceInfo[*plineid].enabled;
}

/*
 * Initialize trace functionality. This MUST BE CALLED before any
 * tracing function is called.
 */
void DTrace_Initialize() {
    DTraceMutex = DMutex_Create();
}

/*
 * Cleans up tracing system. Should be called when tracing functionality
 * is no longer needed.
 */
void DTrace_Shutdown() {
    DMutex_Destroy(DTraceMutex);
}

void DTrace_DisableMutex() {
    DTraceMutex = NULL;
}

/*
 * Enable tracing for all modules.
 */
void DTrace_EnableAll(dbool_t enabled) {
    DMutex_Enter(DTraceMutex);
    GlobalTracingEnabled = enabled;
    DMutex_Exit(DTraceMutex);
}

/*
 * Enable tracing for a specific module. Filename may
 * be fully or partially qualified.
 * e.g. awt_Component.cpp
 *              or
 *      src\win32\native\sun\windows\awt_Component.cpp
 */
void DTrace_EnableFile(const char * file, dbool_t enabled) {
    dtrace_id tid;
    p_dtrace_info info;

    DASSERT(file != NULL);
    DMutex_Enter(DTraceMutex);
    tid = DTrace_GetTraceId(file, -1, DTRACE_FILE);
    info = DTrace_GetInfo(tid);
    info->enabled = enabled;
    DMutex_Exit(DTraceMutex);
}

/*
 * Enable tracing for a specific line in a specific module.
 * See comments above regarding filename argument.
 */
void DTrace_EnableLine(const char * file, int line, dbool_t enabled) {
    dtrace_id tid;
    p_dtrace_info info;

    DASSERT(file != NULL && (line > 0 && line < MAX_LINE));
    DMutex_Enter(DTraceMutex);
    tid = DTrace_GetTraceId(file, line, DTRACE_LINE);
    info = DTrace_GetInfo(tid);
    info->enabled = enabled;
    DMutex_Exit(DTraceMutex);
}

static void DTrace_ClientPrint(const char * msg) {
    DASSERT(msg != NULL && PfnTraceCallback != NULL);
    (*PfnTraceCallback)(msg);
}

/*
 * Print implementation for the use of client defined trace macros. Unsynchronized so it must
 * be used from within a DTRACE_PRINT_CALLBACK function.
 */
void DTrace_VPrintImpl(const char * fmt, va_list arglist) {
    DASSERT(fmt != NULL);

    /* format the trace message */
    vsprintf(DTraceBuffer, fmt, arglist);
    /* not a real great overflow check (memory would already be hammered) but better than nothing */
    DASSERT(strlen(DTraceBuffer) < MAX_TRACE_BUFFER);
    /* output the trace message */
    DTrace_ClientPrint(DTraceBuffer);
}

/*
 * Print implementation for the use of client defined trace macros. Unsynchronized so it must
 * be used from within a DTRACE_PRINT_CALLBACK function.
 */
void DTrace_PrintImpl(const char * fmt, ...) {
    va_list     arglist;

    va_start(arglist, fmt);
    DTrace_VPrintImpl(fmt, arglist);
    va_end(arglist);
}

/*
 * Called via DTRACE_PRINT macro. Outputs printf style formatted text.
 */
void DTrace_VPrint( const char * file, int line, int argc, const char * fmt, va_list arglist ) {
    DASSERT(fmt != NULL);
    DTrace_VPrintImpl(fmt, arglist);
}

/*
 * Called via DTRACE_PRINTLN macro. Outputs printf style formatted text with an automatic newline.
 */
void DTrace_VPrintln( const char * file, int line, int argc, const char * fmt, va_list arglist ) {
    DTrace_VPrintImpl(fmt, arglist);
    DTrace_PrintImpl("\n");
}

/*
 * Called via DTRACE_ macros. If tracing is enabled at the given location, it enters
 * the trace mutex and invokes the callback function to output the trace.
 */
void DTrace_PrintFunction( DTRACE_PRINT_CALLBACK pfn, dtrace_id * pFileTraceId, dtrace_id * pLineTraceId,
                           const char * file, int line,
                           int argc, const char * fmt, ... ) {
    va_list     arglist;

    DASSERT(file != NULL);
    DASSERT(line > 0 && line < MAX_LINE);
    DASSERT(argc <= MAX_ARGC);
    DASSERT(fmt != NULL);

    DMutex_Enter(DTraceMutex);
    if ( DTrace_IsEnabledAt(pFileTraceId, pLineTraceId, file, line) ) {
        va_start(arglist, fmt);
        (*pfn)(file, line, argc, fmt, arglist);
        va_end(arglist);
    }
    DMutex_Exit(DTraceMutex);
}

/*
 * Sets a callback function to be used to output
 * trace statements.
 */
void DTrace_SetOutputCallback(DTRACE_OUTPUT_CALLBACK pfn) {
    DASSERT(pfn != NULL);

    DMutex_Enter(DTraceMutex);
    PfnTraceCallback = pfn;
    DMutex_Exit(DTraceMutex);
}

#endif /* DEBUG */

/**********************************************************************************
 * Support for Java tracing in release or debug mode builds
 */

static void DTrace_PrintStdErr(const char *msg) {
    fprintf(stderr, "%s", msg);
    fflush(stderr);
}

static void DTrace_JavaPrint(const char * msg) {
#if defined(DEBUG)
    DMutex_Enter(DTraceMutex);
    DTrace_ClientPrint(msg);
    DMutex_Exit(DTraceMutex);
#else
    DTrace_PrintStdErr(msg);
#endif
}

static void DTrace_JavaPrintln(const char * msg) {
#if defined(DEBUG)
    DMutex_Enter(DTraceMutex);
    DTrace_ClientPrint(msg);
    DTrace_ClientPrint("\n");
    DMutex_Exit(DTraceMutex);
#else
    DTrace_PrintStdErr(msg);
    DTrace_PrintStdErr("\n");
#endif
}

/*********************************************************************************
 * Native method implementations. Java print trace calls are functional in
 * release builds, but functions to enable/disable native tracing are not.
 */

/* Implementation of DebugSettings.setCTracingOn*/
JNIEXPORT void JNICALL
Java_sun_awt_DebugSettings_setCTracingOn__Z(JNIEnv *env, jobject self, jboolean enabled) {
#if defined(DEBUG)
    DTrace_EnableAll(enabled == JNI_TRUE);
#endif
}

/* Implementation of DebugSettings.setCTracingOn*/
JNIEXPORT void JNICALL
Java_sun_awt_DebugSettings_setCTracingOn__ZLjava_lang_String_2(
    JNIEnv *env,
    jobject self,
    jboolean enabled,
    jstring file ) {
#if defined(DEBUG)
    const char *        cfile;
    cfile = JNU_GetStringPlatformChars(env, file, NULL);
    if ( cfile == NULL ) {
        return;
    }
    DTrace_EnableFile(cfile, enabled == JNI_TRUE);
    JNU_ReleaseStringPlatformChars(env, file, cfile);
#endif
}

/* Implementation of DebugSettings.setCTracingOn*/
JNIEXPORT void JNICALL
Java_sun_awt_DebugSettings_setCTracingOn__ZLjava_lang_String_2I(
    JNIEnv *env,
    jobject self,
    jboolean enabled,
    jstring file,
    jint line ) {
#if defined(DEBUG)
    const char *        cfile;
    cfile = JNU_GetStringPlatformChars(env, file, NULL);
    if ( cfile == NULL ) {
        return;
    }
    DTrace_EnableLine(cfile, line, enabled == JNI_TRUE);
    JNU_ReleaseStringPlatformChars(env, file, cfile);
#endif
}

Other Java examples (source code examples)

Here is a short list of links related to this Java debug_trace.c source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.