
com.sleepycat.je.util.DbVerifyLog Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of je Show documentation
Show all versions of je Show documentation
Berkeley DB Java Edition is a open source, transactional storage solution for Java applications. The Direct Persistence Layer (DPL) API is faster and easier to develop, deploy, and manage than serialized object files or ORM-based Java persistence solutions. The Collections API enhances the standard java.util.collections classes allowing them to be persisted to a local file system and accessed concurrently while protected by ACID transactions. Data is stored by serializing objects and managing class and instance data separately so as not to waste space. Berkeley DB Java Edition is the reliable drop-in solution for complex, fast, and scalable storage. Source for this release is in 'je-4.0.92-sources.jar', the Javadoc is located at 'http://download.oracle.com/berkeley-db/docs/je/4.0.92/'.
/*-
* 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.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import com.sleepycat.je.DbInternal;
import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
import com.sleepycat.je.EnvironmentFailureException;
import com.sleepycat.je.JEVersion;
import com.sleepycat.je.ThreadInterruptedException;
import com.sleepycat.je.config.EnvironmentParams;
import com.sleepycat.je.dbi.EnvironmentFailureReason;
import com.sleepycat.je.dbi.EnvironmentImpl;
import com.sleepycat.je.log.FileManager;
import com.sleepycat.je.log.entry.RestoreRequired;
import com.sleepycat.je.util.verify.VerifierUtils;
import com.sleepycat.je.utilint.CmdUtil;
import com.sleepycat.je.utilint.LoggerUtils;
import com.sleepycat.je.utilint.PropUtil;
/**
* Verifies the checksums in one or more log files.
*
* This class may be instantiated and used programmatically, or used as a
* command line utility as described below.
*
*
* usage: java { com.sleepycat.je.util.DbVerifyLog |
* -jar je-<version>.jar DbVerifyLog }
* [-h <dir>] # environment home directory
* [-s <file>] # starting (minimum) file number
* [-e <file>] # ending (one past the maximum) file number
* [-d <millis>] # delay in ms between reads (default is zero)
* [-V] # print JE version number"
*
*
* All arguments are optional. The current directory is used if {@code -h}
* is not specified. File numbers may be specified in hex (preceded by {@code
* 0x}) or decimal format. For convenience when copy/pasting from other
* output, LSN format (<file>/<offset>) is also allowed.
*/
public class DbVerifyLog {
private static final String USAGE =
"usage: " + CmdUtil.getJavaCommand(DbVerifyLog.class) + "\n" +
" [-h ] # environment home directory\n" +
" [-s ] # starting (minimum) file number\n" +
" [-e ] # ending (one past the maximum) file number\n" +
" [-d ] # delay in ms between reads (default is zero)\n" +
" [-V] # print JE version number";
private final EnvironmentImpl envImpl;
private final int readBufferSize;
private volatile boolean stopVerify = false;
private volatile int filesToVerify = 0;
private volatile int filesVerified = 0;
private volatile int filesDeleted = 0;
private long delayMs = 0;
/**
* Creates a utility object for verifying the checksums in log files.
*
* The read buffer size is {@link
* EnvironmentConfig#LOG_ITERATOR_READ_SIZE}.
*
* @param env the {@code Environment} associated with the log.
*
* @throws EnvironmentFailureException if an unexpected, internal or
* environment-wide failure occurs.
*/
public DbVerifyLog(final Environment env) {
this(env, 0);
}
/**
* Creates a utility object for verifying log files.
*
* @param env the {@code Environment} associated with the log.
*
* @param readBufferSize is the buffer size to use. If a value less than
* or equal to zero is specified, {@link
* EnvironmentConfig#LOG_ITERATOR_READ_SIZE} is used.
*
* @throws EnvironmentFailureException if an unexpected, internal or
* environment-wide failure occurs.
*/
public DbVerifyLog(final Environment env, final int readBufferSize) {
this(DbInternal.getNonNullEnvImpl(env), readBufferSize);
}
/**
* @hidden
*/
public DbVerifyLog(final EnvironmentImpl envImpl,
final int readBufferSize) {
this.readBufferSize = (readBufferSize > 0) ?
readBufferSize :
envImpl.getConfigManager().getInt
(EnvironmentParams.LOG_ITERATOR_READ_SIZE);
this.envImpl = envImpl;
}
/**
* Verifies all log files in the environment.
*
* @throws LogVerificationException if a checksum cannot be verified or a
* log entry is determined to be invalid by examining its contents.
*
* @throws IOException if an IOException occurs while reading a log file.
*
* @throws EnvironmentFailureException if an unexpected, internal or
* environment-wide failure occurs.
*/
public void verifyAll()
throws LogVerificationException, IOException {
/* The same reason with BtreeVerifier.verifyAll. */
if (stopVerify) {
return;
}
LoggerUtils.envLogMsg(
Level.INFO, envImpl, "Start verify of data files");
verify(0, Long.MAX_VALUE);
LoggerUtils.envLogMsg(
Level.INFO, envImpl, "End verify of data files");
}
/**
* Verifies the given range of log files in the environment.
*
* @param startFile is the lowest numbered log file to be verified.
*
* @param endFile is one greater than the highest numbered log file to be
* verified.
*
* @throws LogVerificationException if a checksum cannot be verified or a
* log entry is determined to be invalid by examining its contents.
*
* @throws IOException if an IOException occurs while reading a log file.
*
* @throws EnvironmentFailureException if an unexpected, internal or
* environment-wide failure occurs.
*/
public void verify(final long startFile, final long endFile)
throws LogVerificationException, IOException {
try {
final FileManager fileManager = envImpl.getFileManager();
final File homeDir = envImpl.getEnvironmentHome();
final String[] fileNames =
fileManager.listFileNames(startFile, endFile - 1);
filesToVerify = fileNames.length;
final ByteBuffer buf = ByteBuffer.allocateDirect(readBufferSize);
for (final String fileName : fileNames) {
/*
* When env is closed, the current executing dataVerifier task
* should be canceled asap. So when env is closed,
* setStopVerifyFlag() is called in DataVerifier.shutdown().
* Here stopVerify is checked to determine whether dataVerifier
* task continues.
*/
if (stopVerify) {
return;
}
final File file = new File(homeDir, fileName);
/*
* If JE enables Cleaner, then it is possible that Cleaner
* deletes one or more files, whose fileNum is between
* startFile and endFile, during the for-loop. So for each
* loop, the current 'file' may be deleted by the Cleaner, then
* 'new FileInputStream' will throw FileNotFoundException.
*
* In addition, now JE has a daemon thread to detect the
* unexpected log file deletion. So if FileNotFoundException is
* caused by unexpected log deletion, then that daemon thread
* will catch this abnormal situation. Here, we just ignore
* this exception.
*/
FileInputStream fis;
try {
fis = new FileInputStream(file);
} catch (FileNotFoundException fne) {
filesDeleted += 1;
continue;
}
final FileChannel fic = fis.getChannel();
final LogVerificationReadableByteChannel vic =
new LogVerificationReadableByteChannel(
envImpl, fic, fileName);
IOException ioe = null;
try {
while (vic.read(buf) != -1) {
buf.clear();
/* Return as soon as possible if shutdown. */
if (stopVerify) {
return;
}
if (delayMs > 0) {
try {
Thread.sleep(delayMs);
} catch (InterruptedException e) {
throw new ThreadInterruptedException(
envImpl, e);
}
}
}
filesVerified += 1;
} catch (IOException e) {
ioe = e;
throw ioe;
} finally {
try {
/*
* vic.close aims to close associated channel fic, but
* it may be redundant because fis.close also closes
* fic.
*/
fis.close();
vic.close();
} catch (IOException e) {
if (ioe == null) {
throw e;
}
}
}
}
} catch (LogVerificationException lve) {
VerifierUtils.createMarkerFileFromException(
RestoreRequired.FailureType.LOG_CHECKSUM,
lve,
envImpl,
EnvironmentFailureReason.LOG_CHECKSUM);
throw lve;
}
}
/**
* Returns the number of files to be verified. Returns zero when called
* prior to calling {@link #verifyAll} or {@link #verify}.
*/
public int getNFilesToVerify() {
return filesToVerify;
}
/**
* Returns the number of files verified so far.
*/
public int getNFilesVerified() {
return filesVerified;
}
/**
* Returns the number of files deleted so far. This can happen when a
* file to be verified is deleted by the cleaner.
*/
public int getNFilesDeleted() {
return filesDeleted;
}
public static void main(String[] argv) {
try {
File envHome = new File(".");
long startFile = 0;
long endFile = Long.MAX_VALUE;
long delayMs = 0;
for (int whichArg = 0; whichArg < argv.length; whichArg += 1) {
final String nextArg = argv[whichArg];
if (nextArg.equals("-h")) {
whichArg++;
envHome = new File(CmdUtil.getArg(argv, whichArg));
} else if (nextArg.equals("-s")) {
whichArg++;
String arg = CmdUtil.getArg(argv, whichArg);
final int slashOff = arg.indexOf("/");
if (slashOff >= 0) {
arg = arg.substring(0, slashOff);
}
startFile = CmdUtil.readLongNumber(arg);
} else if (nextArg.equals("-e")) {
whichArg++;
String arg = CmdUtil.getArg(argv, whichArg);
final int slashOff = arg.indexOf("/");
if (slashOff >= 0) {
arg = arg.substring(0, slashOff);
}
endFile = CmdUtil.readLongNumber(arg);
} else if (nextArg.equals("-d")) {
whichArg++;
delayMs =
CmdUtil.readLongNumber(CmdUtil.getArg(argv, whichArg));
} else if (nextArg.equals("-V")) {
System.out.println(JEVersion.CURRENT_VERSION);
System.exit(0);
} else {
printUsageAndExit("Unknown argument: " + nextArg);
}
}
final EnvironmentImpl envImpl =
CmdUtil.makeUtilityEnvironment(envHome, true /*readOnly*/);
final DbVerifyLog verifier = new DbVerifyLog(envImpl, 0);
/* Set the delay time specified by -d flag. */
verifier.setReadDelay(delayMs, TimeUnit.MILLISECONDS);
verifier.verify(startFile, endFile);
System.exit(0);
} catch (Throwable e) {
e.printStackTrace();
printUsageAndExit(e.toString());
}
}
private static void printUsageAndExit(String msg) {
if (msg != null) {
System.err.println(msg);
}
System.err.println(USAGE);
System.exit(1);
}
/**
* Configures the delay between file reads during verification. A delay
* between reads is needed to allow other JE components, such as HA, to
* make timely progress.
*
* By default there is no read delay (it is zero).
*
* Note that when using the {@link EnvironmentConfig#ENV_RUN_VERIFIER
* background data verifier}, the delay between reads is
* {@link EnvironmentConfig#VERIFY_LOG_READ_DELAY}.
*
* @param delay the delay between reads or zero for no delay.
*
* @param unit the {@code TimeUnit} of the delay value. May be
* null only if delay is zero.
*/
public void setReadDelay(long delay, TimeUnit unit) {
delayMs = PropUtil.durationToMillis(delay, unit);
}
/**
* @hidden
* For internal use only.
*/
public void setStopVerifyFlag(boolean val) {
stopVerify = val;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy