4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
33 #include <sys/types.h>
42 * Tracking for the stacks
44 vector
<vector
<Trace
*> > Trace::stacks
;
47 * The indentation string for output
49 vector
<string
> Trace::indent
;
51 #define MAX_MSG_PREFIX_LEN 128
53 #define DEBUG_FILE "/var/adm/sun_fc.debug"
54 #define LOG_FILE "/var/adm/sun_fc"
58 * @param priority The priority of the message (see syslog man page)
59 * @param msg The message string
61 * @doc If the debug file is present, we will log everything to
62 * that file. Otherwise, if the normal log file is present,
63 * we'll log all non-debug messages to that file. Lastly,
64 * if neither file is present, the message will be
67 void Trace::message(int priority
, const char *msg
) {
68 char prefix
[MAX_MSG_PREFIX_LEN
];
69 char message
[MAX_MSG_PREFIX_LEN
+ MAX_MSG_LEN
+ 2];
71 // char time[CTIME_LEN+1];
72 std::string priString
;
75 /* If we can open the log file, write there, else use the cim log */
76 fd
= open(DEBUG_FILE
, O_WRONLY
|O_APPEND
); /* will only open if exists */
78 /* No debug file, how about the log file? */
79 if (priority
== LOG_DEBUG
) {
80 return; /* Ignore debug */
82 fd
= open(LOG_FILE
, O_WRONLY
|O_APPEND
);
83 /* We catch open failures later */
87 /* First interpret the priority value */
90 priString
= "INTERNAL";
105 priString
= "UNKNOWN";
110 /* Format the prefix string for the log file */
111 snprintf(prefix
, MAX_MSG_PREFIX_LEN
, "%d:%d:%s%s:%s",
118 /* Format the message string for the log file */
119 snprintf(message
, strlen(prefix
) + MAX_MSG_LEN
+ 2, "%s:%s\n",
122 write(fd
, message
, strlen(message
));
124 } /* Else discard the log message */
128 * @memo Create a new Trace instance and update stack.
129 * @param myRoutine The name of the routine
131 * @doc This class was developed to provide a Java
132 * like stack trace capability, as C++ does not provide
133 * a run-time stack lookup feature. Instances of the
134 * Trace class should be created on the stack so they
135 * will be automatically freed when the stack is popped
136 * when the function returns.
138 Trace::Trace(std::string myRoutine
) : routine(myRoutine
) {
139 tid
= pthread_self();
140 if (stacks
.size() < tid
+1) {
141 stacks
.resize(tid
+1);
142 indent
.resize(tid
+1);
145 message(LOG_DEBUG
, "entered");
146 stacks
[tid
].push_back(this);
151 * @memo Delete a trace instances and update the stack
154 string::size_type len
= indent
[tid
].size();
156 indent
[tid
].resize(len
- 1);
158 message(LOG_DEBUG
, "exited");
159 stacks
[tid
].pop_back();
163 * @memo Print out the current stack trace information
165 void Trace::stackTrace() {
166 message(STACK_TRACE
, "Stack trace follows");
167 for (vector
<Trace
*>::size_type i
= stacks
[tid
].size() - 1; ; i
--) {
169 msg
+= (stacks
[tid
])[i
]->label();
170 message(STACK_TRACE
, msg
.c_str());