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.region; 019 020import java.io.IOException; 021import java.io.PrintStream; 022import java.io.UncheckedIOException; 023import java.util.ArrayList; 024import java.util.List; 025import org.apache.hadoop.fs.FileSystem; 026import org.apache.hadoop.fs.Path; 027import org.apache.hadoop.hbase.Cell; 028import org.apache.hadoop.hbase.CellUtil; 029import org.apache.hadoop.hbase.HBaseInterfaceAudience; 030import org.apache.hadoop.hbase.PrivateCellUtil; 031import org.apache.hadoop.hbase.client.RegionInfo; 032import org.apache.hadoop.hbase.io.hfile.CacheConfig; 033import org.apache.hadoop.hbase.io.hfile.HFile; 034import org.apache.hadoop.hbase.io.hfile.HFileScanner; 035import org.apache.hadoop.hbase.master.region.MasterRegionFactory; 036import org.apache.hadoop.hbase.procedure2.Procedure; 037import org.apache.hadoop.hbase.procedure2.ProcedureUtil; 038import org.apache.hadoop.hbase.util.AbstractHBaseTool; 039import org.apache.hadoop.hbase.util.Bytes; 040import org.apache.hadoop.hbase.util.CommonFSUtils; 041import org.apache.yetus.audience.InterfaceAudience; 042import org.apache.yetus.audience.InterfaceStability; 043 044import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine; 045import org.apache.hbase.thirdparty.org.apache.commons.cli.Option; 046import org.apache.hbase.thirdparty.org.apache.commons.cli.OptionGroup; 047 048import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos; 049 050/** 051 * A tool to dump the procedures in the HFiles. 052 * <p/> 053 * The different between this and {@link org.apache.hadoop.hbase.io.hfile.HFilePrettyPrinter} is 054 * that, this class will decode the procedure in the cell for better debugging. You are free to use 055 * {@link org.apache.hadoop.hbase.io.hfile.HFilePrettyPrinter} to dump the same file as well. 056 */ 057@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.TOOLS) 058@InterfaceStability.Evolving 059public class HFileProcedurePrettyPrinter extends AbstractHBaseTool { 060 061 private Long procId; 062 063 private List<Path> files = new ArrayList<>(); 064 065 private final PrintStream out; 066 067 public HFileProcedurePrettyPrinter() { 068 this(System.out); 069 } 070 071 public HFileProcedurePrettyPrinter(PrintStream out) { 072 this.out = out; 073 } 074 075 @Override 076 protected void addOptions() { 077 addOptWithArg("w", "seekToPid", "Seek to this procedure id and print this procedure only"); 078 OptionGroup files = new OptionGroup(); 079 files.addOption(new Option("f", "file", true, 080 "File to scan. Pass full-path; e.g. hdfs://a:9000/MasterProcs/master/local/proc/xxx")); 081 files.addOption(new Option("a", "all", false, "Scan the whole procedure region.")); 082 files.setRequired(true); 083 options.addOptionGroup(files); 084 } 085 086 private void addAllHFiles() throws IOException { 087 Path masterProcDir = new Path(CommonFSUtils.getRootDir(conf), MasterRegionFactory.MASTER_STORE_DIR); 088 Path tableDir = CommonFSUtils.getTableDir(masterProcDir, MasterRegionFactory.TABLE_NAME); 089 FileSystem fs = tableDir.getFileSystem(conf); 090 Path regionDir = 091 fs.listStatus(tableDir, p -> RegionInfo.isEncodedRegionName(Bytes.toBytes(p.getName())))[0] 092 .getPath(); 093 List<Path> regionFiles = HFile.getStoreFiles(fs, regionDir); 094 files.addAll(regionFiles); 095 } 096 097 @Override 098 protected void processOptions(CommandLine cmd) { 099 if (cmd.hasOption("w")) { 100 String key = cmd.getOptionValue("w"); 101 if (key != null && key.length() != 0) { 102 procId = Long.parseLong(key); 103 } else { 104 throw new IllegalArgumentException("Invalid row is specified."); 105 } 106 } 107 if (cmd.hasOption("f")) { 108 files.add(new Path(cmd.getOptionValue("f"))); 109 } 110 if (cmd.hasOption("a")) { 111 try { 112 addAllHFiles(); 113 } catch (IOException e) { 114 throw new UncheckedIOException(e); 115 } 116 } 117 } 118 119 private void printCell(Cell cell) throws IOException { 120 out.print("K: " + CellUtil.getCellKeyAsString(cell, 121 c -> Long.toString(Bytes.toLong(c.getRowArray(), c.getRowOffset(), c.getRowLength())))); 122 if (cell.getType() == Cell.Type.Put) { 123 if (cell.getValueLength() == 0) { 124 out.println(" V: mark deleted"); 125 } else { 126 Procedure<?> proc = ProcedureUtil.convertToProcedure(ProcedureProtos.Procedure.parser() 127 .parseFrom(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength())); 128 out.println(" V: " + proc.toStringDetails()); 129 } 130 } else { 131 out.println(); 132 } 133 } 134 135 private void processFile(Path file) throws IOException { 136 out.println("Scanning -> " + file); 137 FileSystem fs = file.getFileSystem(conf); 138 try (HFile.Reader reader = HFile.createReader(fs, file, CacheConfig.DISABLED, true, conf); 139 HFileScanner scanner = reader.getScanner(false, false, false)) { 140 if (procId != null) { 141 if (scanner 142 .seekTo(PrivateCellUtil.createFirstOnRow(Bytes.toBytes(procId.longValue()))) != -1) { 143 do { 144 Cell cell = scanner.getCell(); 145 long currentProcId = 146 Bytes.toLong(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength()); 147 if (currentProcId != procId.longValue()) { 148 break; 149 } 150 printCell(cell); 151 } while (scanner.next()); 152 } 153 } else { 154 if (scanner.seekTo()) { 155 do { 156 Cell cell = scanner.getCell(); 157 printCell(cell); 158 } while (scanner.next()); 159 } 160 } 161 } 162 } 163 164 @Override 165 protected int doWork() throws Exception { 166 for (Path file : files) { 167 processFile(file); 168 } 169 return 0; 170 } 171 172 public static void main(String[] args) { 173 new HFileProcedurePrettyPrinter().doStaticMain(args); 174 } 175}