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 */ 051@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.TOOLS) 052@InterfaceStability.Evolving 053public class ProcedureWALPrettyPrinter extends Configured implements Tool { 054 private final PrintStream out; 055 056 public ProcedureWALPrettyPrinter() { 057 out = System.out; 058 } 059 060 /** 061 * Reads a log file and outputs its contents. 062 * 063 * @param conf HBase configuration relevant to this log file 064 * @param p path of the log file to be read 065 * @throws IOException IOException 066 */ 067 public void processFile(final Configuration conf, final Path p) 068 throws IOException { 069 070 FileSystem fs = p.getFileSystem(conf); 071 if (!fs.exists(p)) { 072 System.err.println("ERROR, file doesnt exist: " + p); 073 return; 074 } 075 if (!fs.isFile(p)) { 076 System.err.println(p + " is not a file"); 077 return; 078 } 079 080 FileStatus logFile = fs.getFileStatus(p); 081 if (logFile.getLen() == 0) { 082 out.println("Zero length file: " + p); 083 return; 084 } 085 086 out.println("Opening procedure state-log: " + p); 087 ProcedureWALFile log = new ProcedureWALFile(fs, logFile); 088 processProcedureWALFile(log); 089 } 090 091 public void processProcedureWALFile(ProcedureWALFile log) throws IOException { 092 log.open(); 093 ProcedureWALHeader header = log.getHeader(); 094 printHeader(header); 095 096 FSDataInputStream stream = log.getStream(); 097 try { 098 boolean hasMore = true; 099 while (hasMore) { 100 ProcedureWALEntry entry = ProcedureWALFormat.readEntry(stream); 101 if (entry == null) { 102 out.println("No more entry, exiting with missing EOF"); 103 hasMore = false; 104 break; 105 } 106 switch (entry.getType()) { 107 case PROCEDURE_WAL_EOF: 108 hasMore = false; 109 break; 110 default: 111 printEntry(entry); 112 } 113 } 114 } catch (IOException e) { 115 out.println("got an exception while reading the procedure WAL " + e.getMessage()); 116 } 117 finally { 118 log.close(); 119 } 120 } 121 122 private void printEntry(final ProcedureWALEntry entry) throws IOException { 123 out.println("EntryType=" + entry.getType()); 124 int procCount = entry.getProcedureCount(); 125 for (int i = 0; i < procCount; i++) { 126 Procedure<?> proc = ProcedureUtil.convertToProcedure(entry.getProcedure(i)); 127 printProcedure(proc); 128 } 129 } 130 131 private void printProcedure(Procedure<?> proc) { 132 out.println(proc.toStringDetails()); 133 } 134 135 private void printHeader(ProcedureWALHeader header) { 136 out.println("ProcedureWALHeader: "); 137 out.println(" Version: " + header.getVersion()); 138 out.println(" Type: " + header.getType()); 139 out.println(" LogId: " + header.getLogId()); 140 out.println(" MinProcId: " + header.getMinProcId()); 141 out.println(); 142 } 143 144 /** 145 * Pass one or more log file names and formatting options and it will dump out 146 * a text version of the contents on <code>stdout</code>. 147 * 148 * @param args 149 * Command line arguments 150 * @throws IOException 151 * Thrown upon file system errors etc. 152 */ 153 @Override 154 public int run(final String[] args) throws IOException { 155 // create options 156 Options options = new Options(); 157 options.addOption("h", "help", false, "Output help message"); 158 options.addOption("f", "file", true, "File to print"); 159 160 final List<Path> files = new ArrayList<>(); 161 try { 162 CommandLine cmd = new DefaultParser().parse(options, args); 163 164 if (cmd.hasOption("f")) { 165 files.add(new Path(cmd.getOptionValue("f"))); 166 } 167 168 if (files.isEmpty() || cmd.hasOption("h")) { 169 HelpFormatter formatter = new HelpFormatter(); 170 formatter.printHelp("ProcedureWALPrettyPrinter ", options, true); 171 return(-1); 172 } 173 } catch (ParseException e) { 174 e.printStackTrace(); 175 HelpFormatter formatter = new HelpFormatter(); 176 formatter.printHelp("ProcedureWALPrettyPrinter ", options, true); 177 return(-1); 178 } 179 // get configuration, file system, and process the given files 180 for (Path file : files) { 181 processFile(getConf(), file); 182 } 183 return(0); 184 } 185 186 public static void main(String[] args) throws Exception { 187 final Configuration conf = HBaseConfiguration.create(); 188 int exitCode = ToolRunner.run(conf, new ProcedureWALPrettyPrinter(), args); 189 System.exit(exitCode); 190 } 191}