fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER START
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The contents of this file are subject to the terms of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Common Development and Distribution License (the "License").
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You may not use this file except in compliance with the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * or http://www.opensolaris.org/os/licensing.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * See the License for the specific language governing permissions
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and limitations under the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If applicable, add the following below this CDDL HEADER, with the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER END
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Use is subject to license terms.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include "Trace.h"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <cstdarg>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <string>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <cstdio>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <string>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/types.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/stat.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <fcntl.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <unistd.h>
f3aaec0a97c3584095582719a0149d5e94c06ea2Richard Lowe#include <cstring>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteusing namespace std;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/**
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Tracking for the stacks
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevector<vector<Trace *> > Trace::stacks;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/**
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The indentation string for output
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevector<string> Trace::indent;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#define MAX_MSG_PREFIX_LEN 128
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#define CTIME_LEN 26
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#define DEBUG_FILE "/var/adm/sun_fc.debug"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#define LOG_FILE "/var/adm/sun_fc"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/**
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @memo Log a message
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param priority The priority of the message (see syslog man page)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param msg The message string
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @doc If the debug file is present, we will log everything to
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * that file. Otherwise, if the normal log file is present,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * we'll log all non-debug messages to that file. Lastly,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * if neither file is present, the message will be
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * silently discarded.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid Trace::message(int priority, const char *msg) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte char prefix[MAX_MSG_PREFIX_LEN];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte char message[MAX_MSG_PREFIX_LEN + MAX_MSG_LEN + 2];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int fd;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte // char time[CTIME_LEN+1];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte std::string priString;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* If we can open the log file, write there, else use the cim log */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fd = open(DEBUG_FILE, O_WRONLY|O_APPEND); /* will only open if exists */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (fd == -1) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* No debug file, how about the log file? */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (priority == LOG_DEBUG) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return; /* Ignore debug */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fd = open(LOG_FILE, O_WRONLY|O_APPEND);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* We catch open failures later */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte // now(time);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* First interpret the priority value */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (priority) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case INTERNAL_ERROR:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte priString = "INTERNAL";
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case STACK_TRACE:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte priString = "STACK";
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case IO_ERROR:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte priString = "IO";
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case USER_ERROR:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte priString = "USER";
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case LOG_DEBUG:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte priString = "DEBUG";
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte default:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte priString = "UNKNOWN";
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (fd != -1) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Format the prefix string for the log file */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte snprintf(prefix, MAX_MSG_PREFIX_LEN, "%d:%d:%s%s:%s",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte time(NULL),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte tid,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte indent[tid].c_str(),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte routine.c_str(),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte priString.c_str());
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Format the message string for the log file */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte snprintf(message, strlen(prefix) + MAX_MSG_LEN + 2, "%s:%s\n",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte prefix,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte write(fd, message, strlen(message));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte close(fd);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } /* Else discard the log message */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/**
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @memo Create a new Trace instance and update stack.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param myRoutine The name of the routine
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @doc This class was developed to provide a Java
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * like stack trace capability, as C++ does not provide
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * a run-time stack lookup feature. Instances of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Trace class should be created on the stack so they
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * will be automatically freed when the stack is popped
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * when the function returns.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn ForteTrace::Trace(std::string myRoutine) : routine(myRoutine) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte tid = pthread_self();
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stacks.size() < tid+1) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stacks.resize(tid+1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte indent.resize(tid+1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte indent[tid] = "";
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte message(LOG_DEBUG, "entered");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stacks[tid].push_back(this);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte indent[tid] += " ";
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/**
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @memo Delete a trace instances and update the stack
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn ForteTrace::~Trace() {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte string::size_type len = indent[tid].size();
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (len > 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte indent[tid].resize(len - 1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte message(LOG_DEBUG, "exited");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stacks[tid].pop_back();
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/**
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @memo Print out the current stack trace information
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid Trace::stackTrace() {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte message(STACK_TRACE, "Stack trace follows");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (vector<Trace *>::size_type i = stacks[tid].size() - 1; ; i--) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte string msg = " ";
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg += (stacks[tid])[i]->label();
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte message(STACK_TRACE, msg.c_str());
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (i == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}