blob: d58fc94791b5b4c0c4d495705d59c829702e7eaa [file] [log] [blame]
/*-
* Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
*
* This file was distributed by Oracle as part of a version of Oracle Berkeley
* DB Java Edition made available at:
*
* http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
*
* Please see the LICENSE file included in the top-level directory of the
* appropriate version of Oracle Berkeley DB Java Edition for a copy of the
* license and additional information.
*/
package com.sleepycat.je.log;
import java.nio.ByteBuffer;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import com.sleepycat.je.dbi.EnvironmentImpl;
import com.sleepycat.je.log.entry.TraceLogEntry;
import com.sleepycat.je.utilint.DbLsn;
import com.sleepycat.je.utilint.Timestamp;
/**
* Trace logs event tracing messages into .jdb files. Only critical messages
* that should always be included in a log should use this functionality.
*/
public class Trace extends BasicVersionedWriteLoggable {
/**
* The log version of the most recent format change for this loggable.
*
* @see #getLastFormatChange
*/
private static final int LAST_FORMAT_CHANGE = 8;
/* Contents of a debug message. */
private Timestamp time;
private String msg;
/** Create a new debug record. */
public Trace(String msg) {
this.time = getCurrentTimestamp();
this.msg = msg;
}
/** Create a trace record that will be filled in from the log. */
public Trace() {
}
/**
* @return message part of trace record.
*/
public String getMessage() {
return msg;
}
/* Generate a timestamp for the current time. */
private Timestamp getCurrentTimestamp() {
Calendar cal = Calendar.getInstance();
return new Timestamp(cal.getTime().getTime());
}
/* Check to see if this Environment supports writing. */
private static boolean isWritePermitted(EnvironmentImpl envImpl) {
if (envImpl == null ||
envImpl.isReadOnly() ||
envImpl.mayNotWrite() ||
envImpl.isDbLoggingDisabled()) {
return false;
}
return true;
}
/** Convenience method to create a log entry containing this trace msg. */
public static void trace(EnvironmentImpl envImpl, String message) {
trace(envImpl, new Trace(message));
}
/** Trace a trace object, unit tests only. */
public static long trace(EnvironmentImpl envImpl, Trace traceMsg) {
if (isWritePermitted(envImpl)) {
return envImpl.getLogManager().log(
new TraceLogEntry(traceMsg),
ReplicationContext.NO_REPLICATE);
}
return DbLsn.NULL_LSN;
}
/**
* Convenience method to create a log entry (lazily) containing this trace
* msg. Lazy tracing is used when tracing is desired, but the .jdb files
* are not initialized.
*/
public static void traceLazily(EnvironmentImpl envImpl,
String message) {
if (isWritePermitted(envImpl)) {
envImpl.getLogManager().logLazily(
new TraceLogEntry(new Trace(message)),
ReplicationContext.NO_REPLICATE);
}
}
@Override
public int getLastFormatChange() {
return LAST_FORMAT_CHANGE;
}
@Override
public Collection<VersionedWriteLoggable> getEmbeddedLoggables() {
return Collections.emptyList();
}
@Override
public int getLogSize(final int logVersion, final boolean forReplication) {
return (LogUtils.getTimestampLogSize(time) +
LogUtils.getStringLogSize(msg));
}
@Override
public void writeToLog(final ByteBuffer logBuffer,
final int logVersion,
final boolean forReplication) {
LogUtils.writeTimestamp(logBuffer, time);
LogUtils.writeString(logBuffer, msg);
}
@Override
public void readFromLog(ByteBuffer itemBuffer, int entryVersion) {
boolean unpacked = (entryVersion < 6);
time = LogUtils.readTimestamp(itemBuffer, unpacked);
msg = LogUtils.readString(itemBuffer, unpacked, entryVersion);
}
@Override
public void dumpLog(StringBuilder sb, boolean verbose) {
sb.append("<Dbg time=\"");
sb.append(time);
sb.append("\">");
sb.append("<msg val=\"");
sb.append(msg);
sb.append("\"/>");
sb.append("</Dbg>");
}
@Override
public long getTransactionId() {
return 0;
}
@Override
public boolean logicalEquals(Loggable other) {
if (!(other instanceof Trace))
return false;
return msg.equals(((Trace) other).msg);
}
@Override
public String toString() {
return (time + "/" + msg);
}
/**
* Just in case it's ever used as a hash key.
*/
@Override
public int hashCode() {
return toString().hashCode();
}
@Override
public boolean equals(Object obj) {
/* Same instance? */
if (this == obj) {
return true;
}
/* Is it another Trace? */
if (!(obj instanceof Trace)) {
return false;
}
/*
* We could compare all the fields individually, but since they're all
* placed in our toString() method, we can just compare the String
* version of each offer.
*/
return (toString().equals(obj.toString()));
}
}