/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hadoop.hdfs.tools.offlineEditsViewer; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.conf.Configured; import org.apache.hadoop.hdfs.tools.offlineEditsViewer.OfflineEditsLoader.OfflineEditsLoaderFactory; import org.apache.hadoop.util.Tool; import org.apache.hadoop.util.ToolRunner; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.PosixParser; /** * This class implements an offline edits viewer, tool that * can be used to view edit logs. */ @InterfaceAudience.Private @InterfaceStability.Unstable public class OfflineEditsViewer extends Configured implements Tool { private final static String defaultProcessor = "xml"; /** * Print help. */ private void printHelp() { String summary = "Usage: bin/hdfs oev [OPTIONS] -i INPUT_FILE -o OUTPUT_FILE\n" + "Offline edits viewer\n" + "Parse a Hadoop edits log file INPUT_FILE and save results\n" + "in OUTPUT_FILE.\n" + "Required command line arguments:\n" + "-i,--inputFile <arg> edits file to process, xml (case\n" + " insensitive) extension means XML format,\n" + " any other filename means binary format\n" + "-o,--outputFile <arg> Name of output file. If the specified\n" + " file exists, it will be overwritten,\n" + " format of the file is determined\n" + " by -p option\n" + "\n" + "Optional command line arguments:\n" + "-p,--processor <arg> Select which type of processor to apply\n" + " against image file, currently supported\n" + " processors are: binary (native binary format\n" + " that Hadoop uses), xml (default, XML\n" + " format), stats (prints statistics about\n" + " edits file)\n" + "-h,--help Display usage information and exit\n" + "-f,--fix-txids Renumber the transaction IDs in the input,\n" + " so that there are no gaps or invalid " + " transaction IDs.\n" + "-r,--recover When reading binary edit logs, use recovery \n" + " mode. This will give you the chance to skip \n" + " corrupt parts of the edit log.\n" + "-v,--verbose More verbose output, prints the input and\n" + " output filenames, for processors that write\n" + " to a file, also output to screen. On large\n" + " image files this will dramatically increase\n" + " processing time (default is false).\n"; System.out.println(summary); System.out.println(); ToolRunner.printGenericCommandUsage(System.out); } /** * Build command-line options and descriptions * * @return command line options */ public static Options buildOptions() { Options options = new Options(); // Build in/output file arguments, which are required, but there is no // addOption method that can specify this OptionBuilder.isRequired(); OptionBuilder.hasArgs(); OptionBuilder.withLongOpt("outputFilename"); options.addOption(OptionBuilder.create("o")); OptionBuilder.isRequired(); OptionBuilder.hasArgs(); OptionBuilder.withLongOpt("inputFilename"); options.addOption(OptionBuilder.create("i")); options.addOption("p", "processor", true, ""); options.addOption("v", "verbose", false, ""); options.addOption("f", "fix-txids", false, ""); options.addOption("r", "recover", false, ""); options.addOption("h", "help", false, ""); return options; } /** Process an edit log using the chosen processor or visitor. * * @param inputFilename The file to process * @param outputFilename The output file name * @param processor If visitor is null, the processor to use * @param visitor If non-null, the visitor to use. * * @return 0 on success; error code otherwise */ public int go(String inputFileName, String outputFileName, String processor, Flags flags, OfflineEditsVisitor visitor) { if (flags.getPrintToScreen()) { System.out.println("input [" + inputFileName + "]"); System.out.println("output [" + outputFileName + "]"); } try { if (visitor == null) { visitor = OfflineEditsVisitorFactory.getEditsVisitor( outputFileName, processor, flags.getPrintToScreen()); } boolean xmlInput = inputFileName.endsWith(".xml"); OfflineEditsLoader loader = OfflineEditsLoaderFactory. createLoader(visitor, inputFileName, xmlInput, flags); loader.loadEdits(); } catch(Exception e) { System.err.println("Encountered exception. Exiting: " + e.getMessage()); e.printStackTrace(System.err); return -1; } return 0; } public static class Flags { private boolean printToScreen = false; private boolean fixTxIds = false; private boolean recoveryMode = false; public Flags() { } public boolean getPrintToScreen() { return printToScreen; } public void setPrintToScreen() { printToScreen = true; } public boolean getFixTxIds() { return fixTxIds; } public void setFixTxIds() { fixTxIds = true; } public boolean getRecoveryMode() { return recoveryMode; } public void setRecoveryMode() { recoveryMode = true; } } /** * Main entry point for ToolRunner (see ToolRunner docs) * * @param argv The parameters passed to this program. * @return 0 on success, non zero on error. */ @Override public int run(String[] argv) throws Exception { Options options = buildOptions(); if(argv.length == 0) { printHelp(); return -1; } CommandLineParser parser = new PosixParser(); CommandLine cmd; try { cmd = parser.parse(options, argv); } catch (ParseException e) { System.out.println( "Error parsing command-line options: " + e.getMessage()); printHelp(); return -1; } if(cmd.hasOption("h")) { // print help and exit printHelp(); return -1; } String inputFileName = cmd.getOptionValue("i"); String outputFileName = cmd.getOptionValue("o"); String processor = cmd.getOptionValue("p"); if(processor == null) { processor = defaultProcessor; } Flags flags = new Flags(); if (cmd.hasOption("r")) { flags.setRecoveryMode(); } if (cmd.hasOption("f")) { flags.setFixTxIds(); } if (cmd.hasOption("v")) { flags.setPrintToScreen(); } return go(inputFileName, outputFileName, processor, flags, null); } /** * main() runs the offline edits viewer using ToolRunner * * @param argv Command line parameters. */ public static void main(String[] argv) throws Exception { int res = ToolRunner.run(new OfflineEditsViewer(), argv); System.exit(res); } }