blob: d82522119051f5e8662d894f50e21e42c3a20bad [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.recovery;
import java.nio.ByteBuffer;
import java.util.Calendar;
import com.sleepycat.je.log.LogUtils;
import com.sleepycat.je.log.Loggable;
import com.sleepycat.je.utilint.DbLsn;
import com.sleepycat.je.utilint.Timestamp;
/**
* CheckpointEnd encapsulates the information needed by a checkpoint end log
* entry.
*/
public class CheckpointEnd implements Loggable {
private static final byte ROOT_LSN_MASK = (byte) 0x1;
private static final byte CLEANED_FILES_MASK = (byte) 0x2;
/*
* invoker is just a way to tag each checkpoint in the log for easier log
* based debugging. It will tell us whether the checkpoint was invoked by
* recovery, the daemon, the api, or the cleaner.
*/
private String invoker;
private Timestamp endTime;
private long checkpointStartLsn;
private boolean rootLsnExists;
private long rootLsn;
private long firstActiveLsn;
private long lastLocalNodeId;
private long lastReplicatedNodeId;
private long lastLocalDbId;
private long lastReplicatedDbId;
private long lastLocalTxnId;
private long lastReplicatedTxnId;
private long lastLocalExtinctionId;
private long lastReplicatedExtinctionId;
private long id;
/*
* True if there were cleaned files to delete after this checkpoint.
* Used to govern HA recovery truncation. Defaults to true.
*/
private boolean cleanedFilesToDelete;
public CheckpointEnd(String invoker,
long checkpointStartLsn,
long rootLsn,
long firstActiveLsn,
long lastLocalNodeId,
long lastReplicatedNodeId,
long lastLocalDbId,
long lastReplicatedDbId,
long lastLocalTxnId,
long lastReplicatedTxnId,
long lastLocalExtinctionId,
long lastReplicatedExtinctionId,
long id,
boolean cleanedFilesToDelete) {
if (invoker == null) {
this.invoker = "";
} else {
this.invoker = invoker;
}
Calendar cal = Calendar.getInstance();
this.endTime = new Timestamp(cal.getTime().getTime());
this.checkpointStartLsn = checkpointStartLsn;
this.rootLsn = rootLsn;
if (rootLsn == DbLsn.NULL_LSN) {
rootLsnExists = false;
} else {
rootLsnExists = true;
}
if (firstActiveLsn == DbLsn.NULL_LSN) {
this.firstActiveLsn = checkpointStartLsn;
} else {
this.firstActiveLsn = firstActiveLsn;
}
this.lastLocalNodeId = lastLocalNodeId;
this.lastReplicatedNodeId = lastReplicatedNodeId;
this.lastLocalDbId = lastLocalDbId;
this.lastReplicatedDbId = lastReplicatedDbId;
this.lastLocalTxnId = lastLocalTxnId;
this.lastReplicatedTxnId = lastReplicatedTxnId;
this.lastLocalExtinctionId = lastLocalExtinctionId;
this.lastReplicatedExtinctionId = lastReplicatedExtinctionId;
this.id = id;
this.cleanedFilesToDelete = cleanedFilesToDelete;
}
/* For logging only */
public CheckpointEnd() {
checkpointStartLsn = DbLsn.NULL_LSN;
rootLsn = DbLsn.NULL_LSN;
firstActiveLsn = DbLsn.NULL_LSN;
}
public String getInvoker() {
return invoker;
}
/*
* Logging support for writing to the log
*/
/**
* @see Loggable#getLogSize
*/
public int getLogSize() {
int size =
LogUtils.getStringLogSize(invoker) + // invoker
LogUtils.getTimestampLogSize(endTime) + // endTime
LogUtils.getPackedLongLogSize(checkpointStartLsn) +
1 + // flags: rootLsnExists, cleanedFilesToDelete
LogUtils.getPackedLongLogSize(firstActiveLsn) +
LogUtils.getPackedLongLogSize(lastLocalNodeId) +
LogUtils.getPackedLongLogSize(lastReplicatedNodeId) +
LogUtils.getPackedLongLogSize(lastLocalDbId) +
LogUtils.getPackedLongLogSize(lastReplicatedDbId) +
LogUtils.getPackedLongLogSize(lastLocalTxnId) +
LogUtils.getPackedLongLogSize(lastReplicatedTxnId) +
LogUtils.getPackedLongLogSize(lastLocalExtinctionId) +
LogUtils.getPackedLongLogSize(lastReplicatedExtinctionId) +
LogUtils.getPackedLongLogSize(id);
if (rootLsnExists) {
size += LogUtils.getPackedLongLogSize(rootLsn);
}
return size;
}
/**
* @see Loggable#writeToLog
*/
public void writeToLog(ByteBuffer logBuffer) {
LogUtils.writeString(logBuffer, invoker);
LogUtils.writeTimestamp(logBuffer, endTime);
LogUtils.writePackedLong(logBuffer, checkpointStartLsn);
byte flags = 0;
if (rootLsnExists) {
flags |= ROOT_LSN_MASK;
}
if (cleanedFilesToDelete) {
flags |= CLEANED_FILES_MASK;
}
logBuffer.put(flags);
if (rootLsnExists) {
LogUtils.writePackedLong(logBuffer, rootLsn);
}
LogUtils.writePackedLong(logBuffer, firstActiveLsn);
LogUtils.writePackedLong(logBuffer, lastLocalNodeId);
LogUtils.writePackedLong(logBuffer, lastReplicatedNodeId);
LogUtils.writePackedLong(logBuffer, lastLocalDbId);
LogUtils.writePackedLong(logBuffer, lastReplicatedDbId);
LogUtils.writePackedLong(logBuffer, lastLocalTxnId);
LogUtils.writePackedLong(logBuffer, lastReplicatedTxnId);
LogUtils.writePackedLong(logBuffer, lastLocalExtinctionId);
LogUtils.writePackedLong(logBuffer, lastReplicatedExtinctionId);
LogUtils.writePackedLong(logBuffer, id);
}
/**
* @see Loggable#readFromLog
*/
public void readFromLog(ByteBuffer logBuffer, int entryVersion) {
boolean version6OrLater = (entryVersion >= 6);
invoker = LogUtils.readString(logBuffer, !version6OrLater,
entryVersion);
endTime = LogUtils.readTimestamp(logBuffer, !version6OrLater);
checkpointStartLsn = LogUtils.readLong(logBuffer, !version6OrLater);
byte flags = logBuffer.get();
rootLsnExists = (flags & ROOT_LSN_MASK) != 0;
if (rootLsnExists) {
rootLsn = LogUtils.readLong(logBuffer, !version6OrLater);
}
if (entryVersion >= 7) {
cleanedFilesToDelete = ((flags & CLEANED_FILES_MASK) != 0);
} else {
cleanedFilesToDelete = true;
}
firstActiveLsn = LogUtils.readLong(logBuffer, !version6OrLater);
lastLocalNodeId = LogUtils.readLong(logBuffer, !version6OrLater);
if (version6OrLater) {
lastReplicatedNodeId = LogUtils.readPackedLong(logBuffer);
}
if (version6OrLater) {
lastLocalDbId = LogUtils.readPackedLong(logBuffer);
lastReplicatedDbId = LogUtils.readPackedLong(logBuffer);
} else {
lastLocalDbId = LogUtils.readInt(logBuffer);
}
lastLocalTxnId = LogUtils.readLong(logBuffer, !version6OrLater);
if (version6OrLater) {
lastReplicatedTxnId = LogUtils.readPackedLong(logBuffer);
}
if (entryVersion >= 17) {
lastLocalExtinctionId = LogUtils.readPackedLong(logBuffer);
lastReplicatedExtinctionId = LogUtils.readPackedLong(logBuffer);
}
id = LogUtils.readLong(logBuffer, !version6OrLater);
if (entryVersion >= 8 && entryVersion <= 10) {
/* Read defunct CleanerLogSummary. */
LogUtils.readPackedLong(logBuffer);
LogUtils.readPackedInt(logBuffer);
final int nAvgLNSizes = LogUtils.readPackedInt(logBuffer);
for (int i = 0; i < nAvgLNSizes; i += 1) {
LogUtils.readPackedInt(logBuffer);
LogUtils.readPackedInt(logBuffer);
LogUtils.readPackedInt(logBuffer);
LogUtils.readPackedInt(logBuffer);
}
}
}
/**
* @see Loggable#dumpLog
*/
public void dumpLog(StringBuilder sb, boolean verbose) {
sb.append("<CkptEnd invoker=\"").append(invoker);
sb.append("\" time=\"").append(endTime);
sb.append("\" lastLocalNodeId=\"").append(lastLocalNodeId);
sb.append("\" lastReplicatedNodeId=\"").append(lastReplicatedNodeId);
sb.append("\" lastLocalDbId=\"").append(lastLocalDbId);
sb.append("\" lastReplicatedDbId=\"").append(lastReplicatedDbId);
sb.append("\" lastLocalTxnId=\"").append(lastLocalTxnId);
sb.append("\" lastReplicatedTxnId=\"").append(lastReplicatedTxnId);
sb.append("\" lastLocalExtinctionId=\"").append(lastLocalExtinctionId);
sb.append("\" lastReplicatedExtinctionId=\"").
append(lastReplicatedExtinctionId);
sb.append("\" id=\"").append(id);
sb.append("\" rootExists=\"").append(rootLsnExists);
sb.append("\">");
sb.append("<ckptStart>");
sb.append(DbLsn.toString(checkpointStartLsn));
sb.append("</ckptStart>");
if (rootLsnExists) {
sb.append("<root>");
sb.append(DbLsn.toString(rootLsn));
sb.append("</root>");
}
sb.append("<firstActive>");
sb.append(DbLsn.toString(firstActiveLsn));
sb.append("</firstActive>");
sb.append("</CkptEnd>");
}
/**
* @see Loggable#getTransactionId
*/
public long getTransactionId() {
return 0;
}
/**
* @see Loggable#logicalEquals
* Always return false, this item should never be compared.
*/
public boolean logicalEquals(Loggable other) {
return false;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("time=").append(endTime);
sb.append(" lastLocalNodeId=").append(lastLocalNodeId);
sb.append(" lastReplicatedNodeId=").append(lastReplicatedNodeId);
sb.append(" lastLocalDbId=").append(lastLocalDbId);
sb.append(" lastReplicatedDbId=").append(lastReplicatedDbId);
sb.append(" lastLocalTxnId=").append(lastLocalTxnId);
sb.append(" lastReplicatedTxnId=").append(lastReplicatedTxnId);
sb.append(" lastLocalExtinctionId=").append(lastLocalExtinctionId);
sb.append(" lastReplicatedExtinctionId=").
append(lastReplicatedExtinctionId);
sb.append(" id=").append(id);
sb.append(" rootExists=").append(rootLsnExists);
sb.append(" ckptStartLsn=").append
(DbLsn.getNoFormatString(checkpointStartLsn));
if (rootLsnExists) {
sb.append(" root=").append(DbLsn.getNoFormatString(rootLsn));
}
sb.append(" firstActive=").
append(DbLsn.getNoFormatString(firstActiveLsn));
return sb.toString();
}
/*
* Accessors
*/
long getCheckpointStartLsn() {
return checkpointStartLsn;
}
long getRootLsn() {
return rootLsn;
}
long getFirstActiveLsn() {
return firstActiveLsn;
}
long getLastLocalNodeId() {
return lastLocalNodeId;
}
long getLastReplicatedNodeId() {
return lastReplicatedNodeId;
}
long getLastLocalDbId() {
return lastLocalDbId;
}
long getLastReplicatedDbId() {
return lastReplicatedDbId;
}
long getLastLocalTxnId() {
return lastLocalTxnId;
}
long getLastReplicatedTxnId() {
return lastReplicatedTxnId;
}
long getLastLocalExtinctionId() {
return lastLocalExtinctionId;
}
long getLastReplicatedExtinctionId() {
return lastReplicatedExtinctionId;
}
public long getId() {
return id;
}
public boolean getCleanedFilesToDelete() {
return cleanedFilesToDelete;
}
}