1*fcf3ce44SJohn Forte /* 2*fcf3ce44SJohn Forte * CDDL HEADER START 3*fcf3ce44SJohn Forte * 4*fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5*fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6*fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7*fcf3ce44SJohn Forte * 8*fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10*fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11*fcf3ce44SJohn Forte * and limitations under the License. 12*fcf3ce44SJohn Forte * 13*fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14*fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16*fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17*fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18*fcf3ce44SJohn Forte * 19*fcf3ce44SJohn Forte * CDDL HEADER END 20*fcf3ce44SJohn Forte */ 21*fcf3ce44SJohn Forte /* 22*fcf3ce44SJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*fcf3ce44SJohn Forte * Use is subject to license terms. 24*fcf3ce44SJohn Forte */ 25*fcf3ce44SJohn Forte 26*fcf3ce44SJohn Forte 27*fcf3ce44SJohn Forte 28*fcf3ce44SJohn Forte #include "Trace.h" 29*fcf3ce44SJohn Forte #include <cstdarg> 30*fcf3ce44SJohn Forte #include <string> 31*fcf3ce44SJohn Forte #include <cstdio> 32*fcf3ce44SJohn Forte #include <string> 33*fcf3ce44SJohn Forte #include <sys/types.h> 34*fcf3ce44SJohn Forte #include <sys/stat.h> 35*fcf3ce44SJohn Forte #include <fcntl.h> 36*fcf3ce44SJohn Forte #include <unistd.h> 37*fcf3ce44SJohn Forte 38*fcf3ce44SJohn Forte using namespace std; 39*fcf3ce44SJohn Forte 40*fcf3ce44SJohn Forte /** 41*fcf3ce44SJohn Forte * Tracking for the stacks 42*fcf3ce44SJohn Forte */ 43*fcf3ce44SJohn Forte vector<vector<Trace *> > Trace::stacks; 44*fcf3ce44SJohn Forte 45*fcf3ce44SJohn Forte /** 46*fcf3ce44SJohn Forte * The indentation string for output 47*fcf3ce44SJohn Forte */ 48*fcf3ce44SJohn Forte vector<string> Trace::indent; 49*fcf3ce44SJohn Forte 50*fcf3ce44SJohn Forte #define MAX_MSG_PREFIX_LEN 128 51*fcf3ce44SJohn Forte #define CTIME_LEN 26 52*fcf3ce44SJohn Forte #define DEBUG_FILE "/var/adm/sun_fc.debug" 53*fcf3ce44SJohn Forte #define LOG_FILE "/var/adm/sun_fc" 54*fcf3ce44SJohn Forte 55*fcf3ce44SJohn Forte /** 56*fcf3ce44SJohn Forte * @memo Log a message 57*fcf3ce44SJohn Forte * @param priority The priority of the message (see syslog man page) 58*fcf3ce44SJohn Forte * @param msg The message string 59*fcf3ce44SJohn Forte * 60*fcf3ce44SJohn Forte * @doc If the debug file is present, we will log everything to 61*fcf3ce44SJohn Forte * that file. Otherwise, if the normal log file is present, 62*fcf3ce44SJohn Forte * we'll log all non-debug messages to that file. Lastly, 63*fcf3ce44SJohn Forte * if neither file is present, the message will be 64*fcf3ce44SJohn Forte * silently discarded. 65*fcf3ce44SJohn Forte */ 66*fcf3ce44SJohn Forte void Trace::message(int priority, const char *msg) { 67*fcf3ce44SJohn Forte char prefix[MAX_MSG_PREFIX_LEN]; 68*fcf3ce44SJohn Forte char message[MAX_MSG_PREFIX_LEN + MAX_MSG_LEN + 2]; 69*fcf3ce44SJohn Forte int fd; 70*fcf3ce44SJohn Forte // char time[CTIME_LEN+1]; 71*fcf3ce44SJohn Forte std::string priString; 72*fcf3ce44SJohn Forte 73*fcf3ce44SJohn Forte 74*fcf3ce44SJohn Forte /* If we can open the log file, write there, else use the cim log */ 75*fcf3ce44SJohn Forte fd = open(DEBUG_FILE, O_WRONLY|O_APPEND); /* will only open if exists */ 76*fcf3ce44SJohn Forte if (fd == -1) { 77*fcf3ce44SJohn Forte /* No debug file, how about the log file? */ 78*fcf3ce44SJohn Forte if (priority == LOG_DEBUG) { 79*fcf3ce44SJohn Forte return; /* Ignore debug */ 80*fcf3ce44SJohn Forte } 81*fcf3ce44SJohn Forte fd = open(LOG_FILE, O_WRONLY|O_APPEND); 82*fcf3ce44SJohn Forte /* We catch open failures later */ 83*fcf3ce44SJohn Forte } 84*fcf3ce44SJohn Forte 85*fcf3ce44SJohn Forte // now(time); 86*fcf3ce44SJohn Forte /* First interpret the priority value */ 87*fcf3ce44SJohn Forte switch (priority) { 88*fcf3ce44SJohn Forte case INTERNAL_ERROR: 89*fcf3ce44SJohn Forte priString = "INTERNAL"; 90*fcf3ce44SJohn Forte break; 91*fcf3ce44SJohn Forte case STACK_TRACE: 92*fcf3ce44SJohn Forte priString = "STACK"; 93*fcf3ce44SJohn Forte break; 94*fcf3ce44SJohn Forte case IO_ERROR: 95*fcf3ce44SJohn Forte priString = "IO"; 96*fcf3ce44SJohn Forte break; 97*fcf3ce44SJohn Forte case USER_ERROR: 98*fcf3ce44SJohn Forte priString = "USER"; 99*fcf3ce44SJohn Forte break; 100*fcf3ce44SJohn Forte case LOG_DEBUG: 101*fcf3ce44SJohn Forte priString = "DEBUG"; 102*fcf3ce44SJohn Forte break; 103*fcf3ce44SJohn Forte default: 104*fcf3ce44SJohn Forte priString = "UNKNOWN"; 105*fcf3ce44SJohn Forte break; 106*fcf3ce44SJohn Forte } 107*fcf3ce44SJohn Forte 108*fcf3ce44SJohn Forte if (fd != -1) { 109*fcf3ce44SJohn Forte /* Format the prefix string for the log file */ 110*fcf3ce44SJohn Forte snprintf(prefix, MAX_MSG_PREFIX_LEN, "%d:%d:%s%s:%s", 111*fcf3ce44SJohn Forte time(NULL), 112*fcf3ce44SJohn Forte tid, 113*fcf3ce44SJohn Forte indent[tid].c_str(), 114*fcf3ce44SJohn Forte routine.c_str(), 115*fcf3ce44SJohn Forte priString.c_str()); 116*fcf3ce44SJohn Forte 117*fcf3ce44SJohn Forte /* Format the message string for the log file */ 118*fcf3ce44SJohn Forte snprintf(message, strlen(prefix) + MAX_MSG_LEN + 2, "%s:%s\n", 119*fcf3ce44SJohn Forte prefix, 120*fcf3ce44SJohn Forte msg); 121*fcf3ce44SJohn Forte write(fd, message, strlen(message)); 122*fcf3ce44SJohn Forte close(fd); 123*fcf3ce44SJohn Forte } /* Else discard the log message */ 124*fcf3ce44SJohn Forte } 125*fcf3ce44SJohn Forte 126*fcf3ce44SJohn Forte /** 127*fcf3ce44SJohn Forte * @memo Create a new Trace instance and update stack. 128*fcf3ce44SJohn Forte * @param myRoutine The name of the routine 129*fcf3ce44SJohn Forte * 130*fcf3ce44SJohn Forte * @doc This class was developed to provide a Java 131*fcf3ce44SJohn Forte * like stack trace capability, as C++ does not provide 132*fcf3ce44SJohn Forte * a run-time stack lookup feature. Instances of the 133*fcf3ce44SJohn Forte * Trace class should be created on the stack so they 134*fcf3ce44SJohn Forte * will be automatically freed when the stack is popped 135*fcf3ce44SJohn Forte * when the function returns. 136*fcf3ce44SJohn Forte */ 137*fcf3ce44SJohn Forte Trace::Trace(std::string myRoutine) : routine(myRoutine) { 138*fcf3ce44SJohn Forte tid = pthread_self(); 139*fcf3ce44SJohn Forte if (stacks.size() < tid+1) { 140*fcf3ce44SJohn Forte stacks.resize(tid+1); 141*fcf3ce44SJohn Forte indent.resize(tid+1); 142*fcf3ce44SJohn Forte indent[tid] = ""; 143*fcf3ce44SJohn Forte } 144*fcf3ce44SJohn Forte message(LOG_DEBUG, "entered"); 145*fcf3ce44SJohn Forte stacks[tid].push_back(this); 146*fcf3ce44SJohn Forte indent[tid] += " "; 147*fcf3ce44SJohn Forte } 148*fcf3ce44SJohn Forte 149*fcf3ce44SJohn Forte /** 150*fcf3ce44SJohn Forte * @memo Delete a trace instances and update the stack 151*fcf3ce44SJohn Forte */ 152*fcf3ce44SJohn Forte Trace::~Trace() { 153*fcf3ce44SJohn Forte string::size_type len = indent[tid].size(); 154*fcf3ce44SJohn Forte if (len > 0) { 155*fcf3ce44SJohn Forte indent[tid].resize(len - 1); 156*fcf3ce44SJohn Forte } 157*fcf3ce44SJohn Forte message(LOG_DEBUG, "exited"); 158*fcf3ce44SJohn Forte stacks[tid].pop_back(); 159*fcf3ce44SJohn Forte } 160*fcf3ce44SJohn Forte 161*fcf3ce44SJohn Forte /** 162*fcf3ce44SJohn Forte * @memo Print out the current stack trace information 163*fcf3ce44SJohn Forte */ 164*fcf3ce44SJohn Forte void Trace::stackTrace() { 165*fcf3ce44SJohn Forte message(STACK_TRACE, "Stack trace follows"); 166*fcf3ce44SJohn Forte for (vector<Trace *>::size_type i = stacks[tid].size() - 1; ; i--) { 167*fcf3ce44SJohn Forte string msg = " "; 168*fcf3ce44SJohn Forte msg += (stacks[tid])[i]->label(); 169*fcf3ce44SJohn Forte message(STACK_TRACE, msg.c_str()); 170*fcf3ce44SJohn Forte if (i == 0) { 171*fcf3ce44SJohn Forte break; 172*fcf3ce44SJohn Forte } 173*fcf3ce44SJohn Forte } 174*fcf3ce44SJohn Forte } 175