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 * @deprecated Since 2.3.0, will be removed in 4.0.0. Keep here only for rolling upgrading, now we 052 * use the new region based procedure store. 053 */ 054@Deprecated 055@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.TOOLS) 056@InterfaceStability.Evolving 057public class ProcedureWALPrettyPrinter extends Configured implements Tool { 058 private final PrintStream out; 059 060 public ProcedureWALPrettyPrinter() { 061 out = System.out; 062 } 063 064 /** 065 * Reads a log file and outputs its contents. 066 * @param conf HBase configuration relevant to this log file 067 * @param p path of the log file to be read 068 * @throws IOException IOException 069 */ 070 public void processFile(final Configuration conf, final Path p) throws IOException { 071 072 FileSystem fs = p.getFileSystem(conf); 073 if (!fs.exists(p)) { 074 System.err.println("ERROR, file doesnt exist: " + p); 075 return; 076 } 077 if (!fs.isFile(p)) { 078 System.err.println(p + " is not a file"); 079 return; 080 } 081 082 FileStatus logFile = fs.getFileStatus(p); 083 if (logFile.getLen() == 0) { 084 out.println("Zero length file: " + p); 085 return; 086 } 087 088 out.println("Opening procedure state-log: " + p); 089 ProcedureWALFile log = new ProcedureWALFile(fs, logFile); 090 processProcedureWALFile(log); 091 } 092 093 public void processProcedureWALFile(ProcedureWALFile log) throws IOException { 094 log.open(); 095 ProcedureWALHeader header = log.getHeader(); 096 printHeader(header); 097 098 FSDataInputStream stream = log.getStream(); 099 try { 100 boolean hasMore = true; 101 while (hasMore) { 102 ProcedureWALEntry entry = ProcedureWALFormat.readEntry(stream); 103 if (entry == null) { 104 out.println("No more entry, exiting with missing EOF"); 105 hasMore = false; 106 break; 107 } 108 switch (entry.getType()) { 109 case PROCEDURE_WAL_EOF: 110 hasMore = false; 111 break; 112 default: 113 printEntry(entry); 114 } 115 } 116 } catch (IOException e) { 117 out.println("got an exception while reading the procedure WAL " + e.getMessage()); 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 a text version of 147 * the contents on <code>stdout</code>. n * Command line arguments n * Thrown upon file system 148 * errors etc. 149 */ 150 @Override 151 public int run(final String[] args) throws IOException { 152 // create options 153 Options options = new Options(); 154 options.addOption("h", "help", false, "Output help message"); 155 options.addOption("f", "file", true, "File to print"); 156 157 final List<Path> files = new ArrayList<>(); 158 try { 159 CommandLine cmd = new DefaultParser().parse(options, args); 160 161 if (cmd.hasOption("f")) { 162 files.add(new Path(cmd.getOptionValue("f"))); 163 } 164 165 if (files.isEmpty() || cmd.hasOption("h")) { 166 HelpFormatter formatter = new HelpFormatter(); 167 formatter.printHelp("ProcedureWALPrettyPrinter ", options, true); 168 return (-1); 169 } 170 } catch (ParseException e) { 171 e.printStackTrace(); 172 HelpFormatter formatter = new HelpFormatter(); 173 formatter.printHelp("ProcedureWALPrettyPrinter ", options, true); 174 return (-1); 175 } 176 // get configuration, file system, and process the given files 177 for (Path file : files) { 178 processFile(getConf(), file); 179 } 180 return (0); 181 } 182 183 public static void main(String[] args) throws Exception { 184 final Configuration conf = HBaseConfiguration.create(); 185 int exitCode = ToolRunner.run(conf, new ProcedureWALPrettyPrinter(), args); 186 System.exit(exitCode); 187 } 188}