|
@@ -30,6 +30,7 @@ import org.apache.jute.BinaryOutputArchive;
|
|
import org.apache.jute.Record;
|
|
import org.apache.jute.Record;
|
|
import org.apache.zookeeper.server.ExitCode;
|
|
import org.apache.zookeeper.server.ExitCode;
|
|
import org.apache.zookeeper.server.TraceFormatter;
|
|
import org.apache.zookeeper.server.TraceFormatter;
|
|
|
|
+import org.apache.zookeeper.server.util.LogChopper;
|
|
import org.apache.zookeeper.server.util.SerializeUtils;
|
|
import org.apache.zookeeper.server.util.SerializeUtils;
|
|
import org.apache.zookeeper.txn.CreateContainerTxn;
|
|
import org.apache.zookeeper.txn.CreateContainerTxn;
|
|
import org.apache.zookeeper.txn.CreateTTLTxn;
|
|
import org.apache.zookeeper.txn.CreateTTLTxn;
|
|
@@ -37,6 +38,8 @@ import org.apache.zookeeper.txn.CreateTxn;
|
|
import org.apache.zookeeper.txn.SetDataTxn;
|
|
import org.apache.zookeeper.txn.SetDataTxn;
|
|
import org.apache.zookeeper.txn.TxnHeader;
|
|
import org.apache.zookeeper.txn.TxnHeader;
|
|
|
|
|
|
|
|
+import java.io.BufferedInputStream;
|
|
|
|
+import java.io.BufferedOutputStream;
|
|
import java.io.Closeable;
|
|
import java.io.Closeable;
|
|
import java.io.EOFException;
|
|
import java.io.EOFException;
|
|
import java.io.File;
|
|
import java.io.File;
|
|
@@ -44,6 +47,8 @@ import java.io.FileInputStream;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.FileOutputStream;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.IOException;
|
|
|
|
+import java.io.InputStream;
|
|
|
|
+import java.io.OutputStream;
|
|
import java.text.DateFormat;
|
|
import java.text.DateFormat;
|
|
import java.util.Date;
|
|
import java.util.Date;
|
|
import java.util.Scanner;
|
|
import java.util.Scanner;
|
|
@@ -96,13 +101,20 @@ public class TxnLogToolkit implements Closeable {
|
|
private FilePadding filePadding = new FilePadding();
|
|
private FilePadding filePadding = new FilePadding();
|
|
private boolean force = false;
|
|
private boolean force = false;
|
|
|
|
|
|
|
|
+ // chop mode
|
|
|
|
+ private long zxid = -1L;
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* @param args Command line arguments
|
|
* @param args Command line arguments
|
|
*/
|
|
*/
|
|
public static void main(String[] args) throws Exception {
|
|
public static void main(String[] args) throws Exception {
|
|
try (final TxnLogToolkit lt = parseCommandLine(args)) {
|
|
try (final TxnLogToolkit lt = parseCommandLine(args)) {
|
|
- lt.dump(new Scanner(System.in));
|
|
|
|
- lt.printStat();
|
|
|
|
|
|
+ if (lt.isDumpMode()) {
|
|
|
|
+ lt.dump(new Scanner(System.in));
|
|
|
|
+ lt.printStat();
|
|
|
|
+ } else {
|
|
|
|
+ lt.chop();
|
|
|
|
+ }
|
|
} catch (TxnLogToolkitParseException e) {
|
|
} catch (TxnLogToolkitParseException e) {
|
|
System.err.println(e.getMessage() + "\n");
|
|
System.err.println(e.getMessage() + "\n");
|
|
printHelpAndExit(e.getExitCode(), e.getOptions());
|
|
printHelpAndExit(e.getExitCode(), e.getOptions());
|
|
@@ -117,10 +129,7 @@ public class TxnLogToolkit implements Closeable {
|
|
this.recoveryMode = recoveryMode;
|
|
this.recoveryMode = recoveryMode;
|
|
this.verbose = verbose;
|
|
this.verbose = verbose;
|
|
this.force = force;
|
|
this.force = force;
|
|
- txnLogFile = new File(txnLogFileName);
|
|
|
|
- if (!txnLogFile.exists() || !txnLogFile.canRead()) {
|
|
|
|
- throw new TxnLogToolkitException(ExitCode.UNEXPECTED_ERROR.getValue(), "File doesn't exist or not readable: %s", txnLogFile);
|
|
|
|
- }
|
|
|
|
|
|
+ txnLogFile = loadTxnFile(txnLogFileName);
|
|
if (recoveryMode) {
|
|
if (recoveryMode) {
|
|
recoveryLogFile = new File(txnLogFile.toString() + ".fixed");
|
|
recoveryLogFile = new File(txnLogFile.toString() + ".fixed");
|
|
if (recoveryLogFile.exists()) {
|
|
if (recoveryLogFile.exists()) {
|
|
@@ -134,6 +143,19 @@ public class TxnLogToolkit implements Closeable {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ public TxnLogToolkit(String txnLogFileName, String zxidName) throws TxnLogToolkitException {
|
|
|
|
+ txnLogFile = loadTxnFile(txnLogFileName);
|
|
|
|
+ zxid = Long.decode(zxidName);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private File loadTxnFile(String txnLogFileName) throws TxnLogToolkitException {
|
|
|
|
+ File logFile = new File(txnLogFileName);
|
|
|
|
+ if (!logFile.exists() || !logFile.canRead()) {
|
|
|
|
+ throw new TxnLogToolkitException(ExitCode.UNEXPECTED_ERROR.getValue(), "File doesn't exist or not readable: %s", logFile);
|
|
|
|
+ }
|
|
|
|
+ return logFile;
|
|
|
|
+ }
|
|
|
|
+
|
|
public void dump(Scanner scanner) throws Exception {
|
|
public void dump(Scanner scanner) throws Exception {
|
|
crcFixed = 0;
|
|
crcFixed = 0;
|
|
|
|
|
|
@@ -204,6 +226,24 @@ public class TxnLogToolkit implements Closeable {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ public void chop() {
|
|
|
|
+ File targetFile = new File(txnLogFile.getParentFile(), txnLogFile.getName() + ".chopped" + zxid);
|
|
|
|
+ try (
|
|
|
|
+ InputStream is = new BufferedInputStream(new FileInputStream(txnLogFile));
|
|
|
|
+ OutputStream os = new BufferedOutputStream(new FileOutputStream(targetFile))
|
|
|
|
+ ) {
|
|
|
|
+ if (!LogChopper.chop(is, os, zxid)) {
|
|
|
|
+ throw new TxnLogToolkitException(ExitCode.INVALID_INVOCATION.getValue(), "Failed to chop %s", txnLogFile.getName());
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ System.out.println("Got exception: " + e.getMessage());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public boolean isDumpMode() {
|
|
|
|
+ return zxid < 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
private boolean askForFix(Scanner scanner) throws TxnLogToolkitException {
|
|
private boolean askForFix(Scanner scanner) throws TxnLogToolkitException {
|
|
while (true) {
|
|
while (true) {
|
|
System.out.print("Would you like to fix it (Yes/No/Abort) ? ");
|
|
System.out.print("Would you like to fix it (Yes/No/Abort) ? ");
|
|
@@ -320,6 +360,12 @@ public class TxnLogToolkit implements Closeable {
|
|
Option forceOpt = new Option("y", "yes", false, "Non-interactive mode: repair all CRC errors without asking");
|
|
Option forceOpt = new Option("y", "yes", false, "Non-interactive mode: repair all CRC errors without asking");
|
|
options.addOption(forceOpt);
|
|
options.addOption(forceOpt);
|
|
|
|
|
|
|
|
+ // Chop mode options
|
|
|
|
+ Option chopOpt = new Option("c", "chop", false, "Chop mode. Chop txn file to a zxid.");
|
|
|
|
+ Option zxidOpt = new Option("z", "zxid", true, "Used with chop. Zxid to which to chop.");
|
|
|
|
+ options.addOption(chopOpt);
|
|
|
|
+ options.addOption(zxidOpt);
|
|
|
|
+
|
|
try {
|
|
try {
|
|
CommandLine cli = parser.parse(options, args);
|
|
CommandLine cli = parser.parse(options, args);
|
|
if (cli.hasOption("help")) {
|
|
if (cli.hasOption("help")) {
|
|
@@ -328,6 +374,9 @@ public class TxnLogToolkit implements Closeable {
|
|
if (cli.getArgs().length < 1) {
|
|
if (cli.getArgs().length < 1) {
|
|
printHelpAndExit(1, options);
|
|
printHelpAndExit(1, options);
|
|
}
|
|
}
|
|
|
|
+ if (cli.hasOption("chop") && cli.hasOption("zxid")) {
|
|
|
|
+ return new TxnLogToolkit(cli.getArgs()[0], cli.getOptionValue("zxid"));
|
|
|
|
+ }
|
|
return new TxnLogToolkit(cli.hasOption("recover"), cli.hasOption("verbose"), cli.getArgs()[0], cli.hasOption("yes"));
|
|
return new TxnLogToolkit(cli.hasOption("recover"), cli.hasOption("verbose"), cli.getArgs()[0], cli.hasOption("yes"));
|
|
} catch (ParseException e) {
|
|
} catch (ParseException e) {
|
|
throw new TxnLogToolkitParseException(options, ExitCode.UNEXPECTED_ERROR.getValue(), e.getMessage());
|
|
throw new TxnLogToolkitParseException(options, ExitCode.UNEXPECTED_ERROR.getValue(), e.getMessage());
|
|
@@ -336,7 +385,7 @@ public class TxnLogToolkit implements Closeable {
|
|
|
|
|
|
private static void printHelpAndExit(int exitCode, Options options) {
|
|
private static void printHelpAndExit(int exitCode, Options options) {
|
|
HelpFormatter help = new HelpFormatter();
|
|
HelpFormatter help = new HelpFormatter();
|
|
- help.printHelp(120,"TxnLogToolkit [-dhrv] <txn_log_file_name>", "", options, "");
|
|
|
|
|
|
+ help.printHelp(120,"TxnLogToolkit [-dhrvc] <txn_log_file_name> (-z <zxid>)", "", options, "");
|
|
System.exit(exitCode);
|
|
System.exit(exitCode);
|
|
}
|
|
}
|
|
|
|
|