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