001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.procedure2.store.wal; 019 020import java.io.IOException; 021import java.io.PrintStream; 022import java.util.ArrayList; 023import java.util.List; 024import org.apache.hadoop.conf.Configuration; 025import org.apache.hadoop.conf.Configured; 026import org.apache.hadoop.fs.FSDataInputStream; 027import org.apache.hadoop.fs.FileStatus; 028import org.apache.hadoop.fs.FileSystem; 029import org.apache.hadoop.fs.Path; 030import org.apache.hadoop.hbase.HBaseConfiguration; 031import org.apache.hadoop.hbase.HBaseInterfaceAudience; 032import org.apache.hadoop.hbase.procedure2.Procedure; 033import org.apache.hadoop.hbase.procedure2.ProcedureUtil; 034import org.apache.hadoop.util.Tool; 035import org.apache.hadoop.util.ToolRunner; 036import org.apache.yetus.audience.InterfaceAudience; 037import org.apache.yetus.audience.InterfaceStability; 038 039import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine; 040import org.apache.hbase.thirdparty.org.apache.commons.cli.DefaultParser; 041import org.apache.hbase.thirdparty.org.apache.commons.cli.HelpFormatter; 042import org.apache.hbase.thirdparty.org.apache.commons.cli.Options; 043import org.apache.hbase.thirdparty.org.apache.commons.cli.ParseException; 044 045import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos.ProcedureWALEntry; 046import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos.ProcedureWALHeader; 047 048/** 049 * ProcedureWALPrettyPrinter prints the contents of a given ProcedureWAL file 050 * @see WALProcedureStore#main(String[]) if you want to check parse of a directory of WALs. 051 */ 052@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.TOOLS) 053@InterfaceStability.Evolving 054public class ProcedureWALPrettyPrinter extends Configured implements Tool { 055 private final PrintStream out; 056 057 public ProcedureWALPrettyPrinter() { 058 out = System.out; 059 } 060 061 /** 062 * Reads a log file and outputs its contents. 063 * 064 * @param conf HBase configuration relevant to this log file 065 * @param p path of the log file to be read 066 * @throws IOException IOException 067 */ 068 public void processFile(final Configuration conf, final Path p) 069 throws IOException { 070 071 FileSystem fs = p.getFileSystem(conf); 072 if (!fs.exists(p)) { 073 System.err.println("ERROR, file doesnt exist: " + p); 074 return; 075 } 076 if (!fs.isFile(p)) { 077 System.err.println(p + " is not a file"); 078 return; 079 } 080 081 FileStatus logFile = fs.getFileStatus(p); 082 if (logFile.getLen() == 0) { 083 out.println("Zero length file: " + p); 084 return; 085 } 086 087 out.println("Opening procedure state-log: " + p); 088 ProcedureWALFile log = new ProcedureWALFile(fs, logFile); 089 processProcedureWALFile(log); 090 } 091 092 public void processProcedureWALFile(ProcedureWALFile log) throws IOException { 093 log.open(); 094 ProcedureWALHeader header = log.getHeader(); 095 printHeader(header); 096 097 FSDataInputStream stream = log.getStream(); 098 try { 099 boolean hasMore = true; 100 while (hasMore) { 101 ProcedureWALEntry entry = ProcedureWALFormat.readEntry(stream); 102 if (entry == null) { 103 out.println("No more entry, exiting with missing EOF"); 104 hasMore = false; 105 break; 106 } 107 switch (entry.getType()) { 108 case PROCEDURE_WAL_EOF: 109 hasMore = false; 110 break; 111 default: 112 printEntry(entry); 113 } 114 } 115 } catch (IOException e) { 116 out.println("got an exception while reading the procedure WAL " + e.getMessage()); 117 } 118 finally { 119 log.close(); 120 } 121 } 122 123 private void printEntry(final ProcedureWALEntry entry) throws IOException { 124 out.println("EntryType=" + entry.getType()); 125 int procCount = entry.getProcedureCount(); 126 for (int i = 0; i < procCount; i++) { 127 Procedure<?> proc = ProcedureUtil.convertToProcedure(entry.getProcedure(i)); 128 printProcedure(proc); 129 } 130 } 131 132 private void printProcedure(Procedure<?> proc) { 133 out.println(proc.toStringDetails()); 134 } 135 136 private void printHeader(ProcedureWALHeader header) { 137 out.println("ProcedureWALHeader: "); 138 out.println(" Version: " + header.getVersion()); 139 out.println(" Type: " + header.getType()); 140 out.println(" LogId: " + header.getLogId()); 141 out.println(" MinProcId: " + header.getMinProcId()); 142 out.println(); 143 } 144 145 /** 146 * Pass one or more log file names and formatting options and it will dump out 147 * a text version of the contents on <code>stdout</code>. 148 * 149 * @param args 150 * Command line arguments 151 * @throws IOException 152 * Thrown upon file system errors etc. 153 */ 154 @Override 155 public int run(final String[] args) throws IOException { 156 // create options 157 Options options = new Options(); 158 options.addOption("h", "help", false, "Output help message"); 159 options.addOption("f", "file", true, "File to print"); 160 161 final List<Path> files = new ArrayList<>(); 162 try { 163 CommandLine cmd = new DefaultParser().parse(options, args); 164 165 if (cmd.hasOption("f")) { 166 files.add(new Path(cmd.getOptionValue("f"))); 167 } 168 169 if (files.isEmpty() || cmd.hasOption("h")) { 170 HelpFormatter formatter = new HelpFormatter(); 171 formatter.printHelp("ProcedureWALPrettyPrinter ", options, true); 172 return(-1); 173 } 174 } catch (ParseException e) { 175 e.printStackTrace(); 176 HelpFormatter formatter = new HelpFormatter(); 177 formatter.printHelp("ProcedureWALPrettyPrinter ", options, true); 178 return(-1); 179 } 180 // get configuration, file system, and process the given files 181 for (Path file : files) { 182 processFile(getConf(), file); 183 } 184 return(0); 185 } 186 187 public static void main(String[] args) throws Exception { 188 final Configuration conf = HBaseConfiguration.create(); 189 int exitCode = ToolRunner.run(conf, new ProcedureWALPrettyPrinter(), args); 190 System.exit(exitCode); 191 } 192}