View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.procedure2.store.wal;
19  
20  import java.io.IOException;
21  import java.io.PrintStream;
22  import java.util.ArrayList;
23  import java.util.List;
24  
25  import org.apache.commons.cli.CommandLine;
26  import org.apache.commons.cli.CommandLineParser;
27  import org.apache.commons.cli.HelpFormatter;
28  import org.apache.commons.cli.Options;
29  import org.apache.commons.cli.ParseException;
30  import org.apache.commons.cli.PosixParser;
31  import org.apache.hadoop.conf.Configuration;
32  import org.apache.hadoop.conf.Configured;
33  import org.apache.hadoop.fs.FSDataInputStream;
34  import org.apache.hadoop.fs.FileStatus;
35  import org.apache.hadoop.fs.FileSystem;
36  import org.apache.hadoop.fs.Path;
37  import org.apache.hadoop.hbase.HBaseConfiguration;
38  import org.apache.hadoop.hbase.HBaseInterfaceAudience;
39  import org.apache.hadoop.hbase.classification.InterfaceAudience;
40  import org.apache.hadoop.hbase.classification.InterfaceStability;
41  import org.apache.hadoop.hbase.procedure2.Procedure;
42  import org.apache.hadoop.hbase.protobuf.generated.ProcedureProtos.ProcedureWALEntry;
43  import org.apache.hadoop.hbase.protobuf.generated.ProcedureProtos.ProcedureWALHeader;
44  import org.apache.hadoop.util.Tool;
45  import org.apache.hadoop.util.ToolRunner;
46  
47  /**
48   * ProcedureWALPrettyPrinter prints the contents of a given ProcedureWAL file
49   */
50  @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.TOOLS)
51  @InterfaceStability.Evolving
52  public class ProcedureWALPrettyPrinter extends Configured implements Tool {
53    private final PrintStream out;
54  
55    public ProcedureWALPrettyPrinter() {
56      out = System.out;
57    }
58  
59    /**
60     * Reads a log file and outputs its contents.
61     *
62     * @param conf   HBase configuration relevant to this log file
63     * @param p       path of the log file to be read
64     * @throws IOException  IOException
65     */
66    public void processFile(final Configuration conf, final Path p)
67        throws IOException {
68  
69      FileSystem fs = p.getFileSystem(conf);
70      if (!fs.exists(p)) {
71        System.err.println("ERROR, file doesnt exist: " + p);
72        return;
73      }
74      if (!fs.isFile(p)) {
75        System.err.println(p + " is not a file");
76        return;
77      }
78  
79      FileStatus logFile = fs.getFileStatus(p);
80      if (logFile.getLen() == 0) {
81        out.println("Zero length file: " + p);
82        return;
83      }
84  
85      out.println("Opening procedure state-log: " + p);
86      ProcedureWALFile log = new ProcedureWALFile(fs, logFile);
87      processProcedureWALFile(log);
88    }
89  
90    public void processProcedureWALFile(ProcedureWALFile log) throws IOException {
91      log.open();
92      ProcedureWALHeader header = log.getHeader();
93      printHeader(header);
94  
95      FSDataInputStream stream = log.getStream();
96      try {
97        boolean hasMore = true;
98        while (hasMore) {
99          ProcedureWALEntry entry = ProcedureWALFormat.readEntry(stream);
100         if (entry == null) {
101           out.println("No more entry, exiting with missing EOF");
102           hasMore = false;
103           break;
104         }
105         switch (entry.getType()) {
106           case EOF:
107             hasMore = false;
108             break;
109           default:
110             printEntry(entry);
111         }
112       }
113     } catch (IOException e) {
114       out.println("got an exception while reading the procedure WAL " + e.getMessage());
115     }
116     finally {
117       log.close();
118     }
119   }
120 
121   private void printEntry(ProcedureWALEntry entry) throws IOException {
122     out.println("EntryType=" + entry.getType());
123     int procCount = entry.getProcedureCount();
124     for (int i = 0; i < procCount; i++) {
125       Procedure<?> proc = Procedure.convert(entry.getProcedure(i));
126       printProcedure(proc);
127     }
128   }
129 
130   private void printProcedure(Procedure<?> proc) {
131     out.println(proc.toStringDetails());
132   }
133 
134   private void printHeader(ProcedureWALHeader header) {
135     out.println("ProcedureWALHeader: ");
136     out.println("  Version: " + header.getVersion());
137     out.println("  Type: " + header.getType());
138     out.println("  LogId: " + header.getLogId());
139     out.println("  MinProcId: " + header.getMinProcId());
140     out.println();
141   }
142 
143   /**
144    * Pass one or more log file names and formatting options and it will dump out
145    * a text version of the contents on <code>stdout</code>.
146    *
147    * @param args
148    *          Command line arguments
149    * @throws IOException
150    *           Thrown upon file system errors etc.
151    */
152   public int run(final String[] args) throws IOException {
153     // create options
154     Options options = new Options();
155     options.addOption("h", "help", false, "Output help message");
156     options.addOption("f", "file", true, "File to print");
157 
158     final List<Path> files = new ArrayList<Path>();
159     try {
160       CommandLine cmd = new PosixParser().parse(options, args);
161 
162       if (cmd.hasOption("f")) {
163         files.add(new Path(cmd.getOptionValue("f")));
164       }
165 
166       if (files.size() == 0 || cmd.hasOption("h")) {
167         HelpFormatter formatter = new HelpFormatter();
168         formatter.printHelp("ProcedureWALPrettyPrinter ", options, true);
169         return(-1);
170       }
171     } catch (ParseException e) {
172       e.printStackTrace();
173       HelpFormatter formatter = new HelpFormatter();
174       formatter.printHelp("ProcedureWALPrettyPrinter ", options, true);
175       return(-1);
176     }
177     // get configuration, file system, and process the given files
178     for (Path file : files) {
179       processFile(getConf(), file);
180     }
181     return(0);
182   }
183 
184   public static void main(String[] args) throws Exception {
185     final Configuration conf = HBaseConfiguration.create();
186     int exitCode = ToolRunner.run(conf, new ProcedureWALPrettyPrinter(), args);
187     System.exit(exitCode);
188   }
189 }