/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2002-2006
* Sleepycat Software. All rights reserved.
*
* $Id: DbDump.java,v 1.1 2006/05/06 09:00:39 ckaestne Exp $
*/
package com.sleepycat.je.util;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import com.sleepycat.je.Cursor;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseConfig;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.DbInternal;
import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
import com.sleepycat.je.JEVersion;
import com.sleepycat.je.LockMode;
import com.sleepycat.je.OperationStatus;
import com.sleepycat.je.config.EnvironmentParams;
import com.sleepycat.je.utilint.CmdUtil;
import com.sleepycat.je.utilint.DbScavenger;
import com.sleepycat.je.utilint.Tracer;
public class DbDump {
private static final int VERSION = 3;
protected File envHome = null;
protected Environment env;
protected String dbName = null;
protected boolean formatUsingPrintable;
private boolean dupSort;
private String outputFileName = null;
protected String outputDirectory = null;
protected PrintStream outputFile = null;
protected boolean doScavengerRun = false;
protected boolean doAggressiveScavengerRun = false;
protected boolean verbose = false;
private static final String usageString =
"usage: " + CmdUtil.getJavaCommand(DbDump.class) + "\n" +
" -h <dir> # environment home directory\n" +
" [-f <fileName>] # output file, for non -rR dumps\n" +
" [-l] # list databases in the environment\n" +
" [-p] # output printable characters\n" +
" [-r] # salvage mode\n" +
" [-R] # aggressive salvage mode\n" +
" [-d] <directory> # directory for *.dump files (salvage mode)\n" +
" [-s <databaseName>] # database to dump\n" +
" [-v] # verbose in salvage mode\n" +
" [-V] # print JE version number\n";
private DbDump() {
}
public DbDump(Environment env,
String dbName,
PrintStream outputFile,
String outputDirectory,
boolean formatUsingPrintable) {
try {
this.envHome = env.getHome();
} catch (DatabaseException e) {
IllegalArgumentException iae = new IllegalArgumentException();
iae.initCause(e);
throw iae;
}
this.env = env;
this.dbName = dbName;
this.outputFile = outputFile;
this.outputDirectory = outputDirectory;
this.formatUsingPrintable = formatUsingPrintable;
}
public static void main(String argv[])
throws DatabaseException, IOException {
DbDump dumper = new DbDump();
boolean listDbs = dumper.parseArgs(argv);
if (dumper.doScavengerRun) {
dumper.openEnv(false);
dumper = new DbScavenger(dumper.env,
dumper.outputFile,
dumper.outputDirectory,
dumper.formatUsingPrintable,
dumper.doAggressiveScavengerRun,
dumper.verbose);
((DbScavenger) dumper).setDumpCorruptedBounds(true);
}
if (listDbs) {
dumper.listDbs();
System.exit(0);
}
try {
dumper.dump();
} catch (Throwable T) {
T.printStackTrace();
} finally {
dumper.env.close();
if (dumper.outputFile != null &&
dumper.outputFile != System.out) {
dumper.outputFile.close();
}
}
}
private void listDbs()
throws DatabaseException {
openEnv(true);
List dbNames = env.getDatabaseNames();
Iterator iter = dbNames.iterator();
while (iter.hasNext()) {
String name = (String) iter.next();
System.out.println(name);
}
}
protected void printUsage(String msg) {
System.err.println(msg);
System.err.println(usageString);
System.exit(-1);
}
protected boolean parseArgs(String argv[])
throws IOException {
int argc = 0;
int nArgs = argv.length;
boolean listDbs = false;
while (argc < nArgs) {
String thisArg = argv[argc++];
if (thisArg.equals("-p")) {
formatUsingPrintable = true;
} else if (thisArg.equals("-V")) {
System.out.println(JEVersion.CURRENT_VERSION);
System.exit(0);
} else if (thisArg.equals("-l")) {
listDbs = true;
} else if (thisArg.equals("-r")) {
doScavengerRun = true;
} else if (thisArg.equals("-R")) {
doScavengerRun = true;
doAggressiveScavengerRun = true;
} else if (thisArg.equals("-f")) {
if (argc < nArgs) {
outputFileName = argv[argc++];
} else {
printUsage("-f requires an argument");
}
} else if (thisArg.equals("-h")) {
if (argc < nArgs) {
String envDir = argv[argc++];
envHome = new File(envDir);
} else {
printUsage("-h requires an argument");
}
} else if (thisArg.equals("-d")) {
if (argc < nArgs) {
outputDirectory = argv[argc++];
} else {
printUsage("-d requires an argument");
}
} else if (thisArg.equals("-s")) {
if (argc < nArgs) {
dbName = argv[argc++];
} else {
printUsage("-s requires an argument");
}
} else if (thisArg.equals("-v")) {
verbose = true;
} else {
printUsage(thisArg + " is not a valid option.");
}
}
if (envHome == null) {
printUsage("-h is a required argument");
}
if (!listDbs &&
!doScavengerRun) {
if (dbName == null) {
printUsage("Must supply a database name if -l not supplied.");
}
}
if (outputFileName == null) {
outputFile = System.out;
} else {
outputFile = new PrintStream(new FileOutputStream(outputFileName));
}
return listDbs;
}
/*
* Begin DbDump API. From here on there should be no calls to printUsage,
* System.xxx.print, or System.exit.
*/
protected void openEnv(boolean doRecovery)
throws DatabaseException {
if (env == null) {
EnvironmentConfig envConfiguration = new EnvironmentConfig();
envConfiguration.setReadOnly(true);
/* Don't run recovery. */
envConfiguration.setConfigParam
(EnvironmentParams.ENV_RECOVERY.getName(),
doRecovery ? "true" : "false");
env = new Environment(envHome, envConfiguration);
}
}
public void dump()
throws IOException, DatabaseException {
openEnv(true);
Tracer.trace(Level.INFO, DbInternal.envGetEnvironmentImpl(env),
"DbDump.dump of " + dbName + " starting");
DatabaseEntry foundKey = new DatabaseEntry();
DatabaseEntry foundData = new DatabaseEntry();
DatabaseConfig dbConfig = new DatabaseConfig();
dbConfig.setReadOnly(true);
DbInternal.setUseExistingConfig(dbConfig, true);
Database db = env.openDatabase(null, dbName, dbConfig);
dupSort = db.getConfig().getSortedDuplicates();
printHeader(outputFile, dupSort, formatUsingPrintable);
Cursor cursor = db.openCursor(null, null);
while (cursor.getNext(foundKey, foundData, LockMode.DEFAULT) ==
OperationStatus.SUCCESS) {
dumpOne(outputFile, foundKey.getData(), formatUsingPrintable);
dumpOne(outputFile, foundData.getData(), formatUsingPrintable);
}
cursor.close();
db.close();
outputFile.println("DATA=END");
Tracer.trace(Level.INFO, DbInternal.envGetEnvironmentImpl(env),
"DbDump.dump of " + dbName + " ending");
}
protected void printHeader(PrintStream o,
boolean dupSort,
boolean formatUsingPrintable) {
o.println("VERSION=" + VERSION);
if (formatUsingPrintable) {
o.println("format=print");
} else {
o.println("format=bytevalue");
}
o.println("type=btree");
o.println("dupsort=" + (dupSort ? "1" : "0"));
o.println("HEADER=END");
}
protected void dumpOne(PrintStream o, byte[] ba,
boolean formatUsingPrintable) {
StringBuffer sb = new StringBuffer();
sb.append(' ');
CmdUtil.formatEntry(sb, ba, formatUsingPrintable);
o.println(sb.toString());
}
}