content: /*
   * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
   * (the "License"). You may not use this work except in compliance with the License, which is
   * available at www.apache.org/licenses/LICENSE-2.0
   *
   * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
   * either express or implied, as more fully set forth in the License.
   *
   * See the NOTICE file distributed with this work for information regarding copyright ownership.
   */
  
  package alluxio.master.journalv0;
  
  import alluxio.RuntimeConstants;
  import alluxio.proto.journal.Journal.JournalEntry;
  import alluxio.util.CommonUtils;
  
  import org.apache.commons.cli.BasicParser;
  import org.apache.commons.cli.CommandLine;
  import org.apache.commons.cli.CommandLineParser;
  import org.apache.commons.cli.HelpFormatter;
  import org.apache.commons.cli.Options;
  import org.apache.commons.cli.ParseException;
  import org.apache.commons.lang3.StringUtils;
  
  import java.io.IOException;
  import javax.annotation.concurrent.NotThreadSafe;
  
  /**
   * Tool for reading the journal. It reads binary journal entries and prints human-readable ones to
   * standard out. Example usage below.
   *
   * <pre>
   * java -cp \
   *   assembly/server/target/alluxio-assembly-server-&lt;ALLUXIO-VERSION&gt;
   *   -jar-with-dependencies.jar \
   *   alluxio.master.journal.JournalTool < journal/FileSystemMaster/log.out
   * </pre>
   */
  @NotThreadSafe
  public final class JournalTool {
    /** Separator to place at the end of each journal entry. */
    private static final String ENTRY_SEPARATOR = StringUtils.repeat('-', 80);
    /** Amount of time to wait before giving up on the user supplying a journal log via stdin. */
    private static final long TIMEOUT_MS = 2000;
    private static final int EXIT_FAILED = -1;
    private static final int EXIT_SUCCEEDED = 0;
    private static final Options OPTIONS = new Options()
        .addOption("help", false, "Show help for this test")
        .addOption("noTimeout", false, "Wait indefinitely for stdin to supply input");
  
    private static boolean sNoTimeout = false;
    private static boolean sHelp = false;
  
    private JournalTool() {} // prevent instantiation
  
    /**
     * Reads a journal via
     * {@code java -cp \
     * assembly/server/target/alluxio-assembly-server-<ALLUXIO-VERSION>-jar-with-dependencies.jar \
     * alluxio.master.journal.JournalTool < journal/FileSystemMaster/log.out}.
     *
     * @param args arguments passed to the tool
     */
    public static void main(String[] args) throws IOException {
      if (!parseInputArgs(args)) {
        usage();
        System.exit(EXIT_FAILED);
      }
      if (sHelp) {
        usage();
        System.exit(EXIT_SUCCEEDED);
      }
      if (!sNoTimeout && !stdinHasData()) {
        System.exit(EXIT_FAILED);
      }
  
      JournalFormatter formatter = new ProtoBufJournalFormatter();
      try (JournalInputStream journalStream = formatter.deserialize(System.in)) {
        JournalEntry entry;
        while ((entry = journalStream.read()) != null) {
          System.out.print(entry);
          System.out.println(ENTRY_SEPARATOR);
        }
      }
    }
  
    /**
     * Parses the input args with a command line format, using
     * {@link org.apache.commons.cli.CommandLineParser}.
     *
     * @param args the input args
     * @return true if parsing succeeded
     */
    private static boolean parseInputArgs(String[] args) {
      CommandLineParser parser = new BasicParser();
      CommandLine cmd;
      try {
        cmd = parser.parse(OPTIONS, args);
      } catch (ParseException e) {
        System.out.println("Failed to parse input args: " + e);
        return false;
      }
      sNoTimeout = cmd.hasOption("noTimeout");
      sHelp = cmd.hasOption("help");
      return true;
    }
  
    /**
     * @return true if stdin has data before {@link #TIMEOUT_MS} elapses
     */
    private static boolean stdinHasData() throws IOException {
      long start = System.currentTimeMillis();
      while (System.in.available() == 0) {
        if (System.currentTimeMillis() - start > TIMEOUT_MS) {
          System.out.println(
              "Timed out waiting for input from stdin. Use -noTimeout to wait longer.");
          return false;
        }
        CommonUtils.sleepMs(50);
      }
      return true;
    }
  
    private static void usage() {
      new HelpFormatter().printHelp(
          "java -cp alluxio-" + RuntimeConstants.VERSION
              + "-jar-with-dependencies.jar alluxio.master.journal.JournalTool",
          "Read an Alluxio journal from stdin and write it human-readably to stdout", OPTIONS, "",
          true);
    }
  }
  