001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2002,2008 Oracle. All rights reserved.
005: *
006: * $Id: Tracer.java,v 1.43.2.3 2008/01/07 15:14:18 cwl Exp $
007: */
008:
009: package com.sleepycat.je.utilint;
010:
011: import java.io.PrintWriter;
012: import java.io.StringWriter;
013: import java.nio.ByteBuffer;
014: import java.sql.Timestamp;
015: import java.util.Calendar;
016: import java.util.logging.Level;
017:
018: import com.sleepycat.je.DatabaseException;
019: import com.sleepycat.je.config.ConfigParam;
020: import com.sleepycat.je.dbi.EnvironmentImpl;
021: import com.sleepycat.je.log.LogEntryType;
022: import com.sleepycat.je.log.LogManager;
023: import com.sleepycat.je.log.LogUtils;
024: import com.sleepycat.je.log.Loggable;
025: import com.sleepycat.je.log.entry.SingleItemEntry;
026:
027: /**
028: * The Tracer generates debug messages that are sent to the java.util.Logging
029: * facility. There are three log handlers set up for logging -- the database
030: * log itself, an output file, and stdout (the "console"). By default, only
031: * the database file is enabled.
032: */
033: public class Tracer implements Loggable {
034:
035: /*
036: * Name pattern for tracing output that's been directed into a log file by
037: * enabling the file handler.
038: */
039: public static final String INFO_FILES = "je.info";
040:
041: /*
042: * Contents of a debug message.
043: */
044: private Timestamp time;
045: private String msg;
046:
047: /**
048: * Create a new debug record.
049: */
050: public Tracer(String msg) {
051: this .time = getCurrentTimestamp();
052: this .msg = msg;
053: }
054:
055: /**
056: * Create trace record that will be filled in from the log.
057: */
058: public Tracer() {
059: }
060:
061: /*
062: * Static utility methods for submitting information for logging in the
063: * text log file, the database log, and stdout.
064: */
065:
066: /**
067: * Logger method for recording a general message.
068: */
069: public static void trace(Level logLevel, EnvironmentImpl envImpl,
070: String msg) {
071: envImpl.getLogger().log(logLevel, msg);
072: }
073:
074: /**
075: * Logger method for recording an exception and stacktrace.
076: */
077: public static void trace(EnvironmentImpl envImpl,
078: String sourceClass, String sourceMethod, String msg,
079: Throwable t) {
080:
081: /*
082: * Give it to the Logger, which will funnel it to stdout and/or the
083: * text file and/or the database log file
084: */
085: envImpl.getLogger().logp(Level.SEVERE, sourceClass,
086: sourceMethod, msg + "\n" + Tracer.getStackTrace(t));
087: }
088:
089: /**
090: * Parse a logging level config parameter, and return a more explanatory
091: * error message if it doesn't parse.
092: */
093: public static Level parseLevel(EnvironmentImpl envImpl,
094: ConfigParam configParam) throws DatabaseException {
095:
096: Level level = null;
097: try {
098: String levelVal = envImpl.getConfigManager().get(
099: configParam);
100: level = Level.parse(levelVal);
101: } catch (IllegalArgumentException e) {
102: throw new DatabaseException("Problem parsing parameter "
103: + configParam.getName() + ": " + e.getMessage(), e);
104: }
105: return level;
106: }
107:
108: /*
109: * Helpers
110: */
111: public String getMessage() {
112: return msg;
113: }
114:
115: /**
116: * @return a timestamp for "now"
117: */
118: private Timestamp getCurrentTimestamp() {
119: Calendar cal = Calendar.getInstance();
120: return new Timestamp(cal.getTime().getTime());
121: }
122:
123: /**
124: * @return the stacktrace for an exception
125: */
126: public static String getStackTrace(Throwable t) {
127: StringWriter s = new StringWriter();
128: t.printStackTrace(new PrintWriter(s));
129: String stackTrace = s.toString();
130: stackTrace = stackTrace.replaceAll("<", "<");
131: stackTrace = stackTrace.replaceAll(">", ">");
132: return stackTrace;
133: }
134:
135: /*
136: * Logging support
137: */
138:
139: /**
140: * Convenience method to create a log entry containing this trace msg.
141: */
142: public long log(LogManager logManager) throws DatabaseException {
143: return logManager.log(new SingleItemEntry(
144: LogEntryType.LOG_TRACE, this ));
145: }
146:
147: /**
148: * @see Loggable#getLogSize()
149: */
150: public int getLogSize() {
151: return (LogUtils.getTimestampLogSize() + LogUtils
152: .getStringLogSize(msg));
153: }
154:
155: /**
156: * @see Loggable#writeToLog
157: */
158: public void writeToLog(ByteBuffer logBuffer) {
159: /* Load the header. */
160: LogUtils.writeTimestamp(logBuffer, time);
161: LogUtils.writeString(logBuffer, msg);
162: }
163:
164: /**
165: * @see Loggable#readFromLog
166: */
167: public void readFromLog(ByteBuffer itemBuffer, byte entryTypeVersion) {
168: /* See how many we want to read direct. */
169: time = LogUtils.readTimestamp(itemBuffer);
170: msg = LogUtils.readString(itemBuffer);
171: }
172:
173: /**
174: * @see Loggable#dumpLog
175: */
176: public void dumpLog(StringBuffer sb, boolean verbose) {
177: sb.append("<Dbg time=\"");
178: sb.append(time);
179: sb.append("\">");
180: sb.append("<msg val=\"");
181: sb.append(msg);
182: sb.append("\"/>");
183: sb.append("</Dbg>");
184: }
185:
186: /**
187: * @see Loggable#getTransactionId
188: */
189: public long getTransactionId() {
190: return 0;
191: }
192:
193: public String toString() {
194: return (time + "/" + msg);
195: }
196:
197: /**
198: * For unit tests.
199: */
200:
201: /**
202: * Just in case it's ever used as a hash key.
203: */
204: public int hashCode() {
205: return toString().hashCode();
206: }
207:
208: /**
209: * Override Object.equals
210: */
211: public boolean equals(Object obj) {
212: /* Same instance? */
213: if (this == obj) {
214: return true;
215: }
216:
217: /* Is it another Tracer? */
218: if (!(obj instanceof Tracer)) {
219: return false;
220: }
221:
222: /*
223: * We could compare all the fields individually, but since they're all
224: * placed in our toString() method, we can just compare the String
225: * version of each offer.
226: */
227: return (toString().equals(obj.toString()));
228: }
229: }
|