HBASE-24974: Provide a flexibility to print only row key and filter for multiple tables in the WALPrettyPrinter (#2389)
Signed-off-by: Bharath Vissapragada <bharathv@apache.org>
This commit is contained in:
parent
c8d6d7a780
commit
d6f0128c83
|
@ -21,6 +21,7 @@ import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -101,7 +102,8 @@ public class HLogPrettyPrinter extends WALPrettyPrinter {
|
||||||
public HLogPrettyPrinter(boolean outputValues, boolean outputJSON,
|
public HLogPrettyPrinter(boolean outputValues, boolean outputJSON,
|
||||||
long sequence, String table, String region, String row, boolean persistentOutput,
|
long sequence, String table, String region, String row, boolean persistentOutput,
|
||||||
PrintStream out) {
|
PrintStream out) {
|
||||||
super(outputValues, outputJSON, sequence, table, region, row, persistentOutput, out);
|
super(outputValues, outputJSON, sequence, Collections.singleton(table), region, row,
|
||||||
|
false, persistentOutput, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
|
|
|
@ -21,21 +21,20 @@ import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import org.apache.commons.cli.CommandLine;
|
import org.apache.commons.cli.CommandLine;
|
||||||
import org.apache.commons.cli.CommandLineParser;
|
import org.apache.commons.cli.CommandLineParser;
|
||||||
import org.apache.commons.cli.HelpFormatter;
|
import org.apache.commons.cli.HelpFormatter;
|
||||||
import org.apache.commons.cli.Options;
|
import org.apache.commons.cli.Options;
|
||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
import org.apache.commons.cli.PosixParser;
|
import org.apache.commons.cli.PosixParser;
|
||||||
import org.apache.hadoop.hbase.classification.InterfaceAudience;
|
|
||||||
import org.apache.hadoop.hbase.classification.InterfaceStability;
|
|
||||||
import org.apache.hadoop.hbase.util.GsonUtil;
|
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.fs.FileSystem;
|
import org.apache.hadoop.fs.FileSystem;
|
||||||
import org.apache.hadoop.fs.Path;
|
import org.apache.hadoop.fs.Path;
|
||||||
|
@ -43,14 +42,14 @@ import org.apache.hadoop.hbase.Cell;
|
||||||
import org.apache.hadoop.hbase.CellUtil;
|
import org.apache.hadoop.hbase.CellUtil;
|
||||||
import org.apache.hadoop.hbase.HBaseConfiguration;
|
import org.apache.hadoop.hbase.HBaseConfiguration;
|
||||||
import org.apache.hadoop.hbase.HBaseInterfaceAudience;
|
import org.apache.hadoop.hbase.HBaseInterfaceAudience;
|
||||||
import org.apache.hadoop.hbase.TableName;
|
|
||||||
import org.apache.hadoop.hbase.Tag;
|
import org.apache.hadoop.hbase.Tag;
|
||||||
|
import org.apache.hadoop.hbase.classification.InterfaceAudience;
|
||||||
|
import org.apache.hadoop.hbase.classification.InterfaceStability;
|
||||||
|
import org.apache.hadoop.hbase.regionserver.wal.ProtobufLogReader;
|
||||||
|
import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
|
||||||
import org.apache.hadoop.hbase.util.Bytes;
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
import org.apache.hadoop.hbase.util.FSUtils;
|
import org.apache.hadoop.hbase.util.FSUtils;
|
||||||
|
import org.apache.hadoop.hbase.util.GsonUtil;
|
||||||
import org.apache.hadoop.hbase.regionserver.wal.ProtobufLogReader;
|
|
||||||
// imports for things that haven't moved yet.
|
|
||||||
import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
|
|
||||||
import org.apache.hbase.thirdparty.com.google.gson.Gson;
|
import org.apache.hbase.thirdparty.com.google.gson.Gson;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -82,9 +81,12 @@ public class WALPrettyPrinter {
|
||||||
private boolean outputJSON;
|
private boolean outputJSON;
|
||||||
// The following enable filtering by sequence, region, and row, respectively
|
// The following enable filtering by sequence, region, and row, respectively
|
||||||
private long sequence;
|
private long sequence;
|
||||||
private String table;
|
|
||||||
|
// List of tables for filter
|
||||||
|
private final Set<String> tableSet;
|
||||||
private String region;
|
private String region;
|
||||||
private String row;
|
private String row;
|
||||||
|
private boolean outputOnlyRowKey;
|
||||||
// enable in order to output a single list of transactions from several files
|
// enable in order to output a single list of transactions from several files
|
||||||
private boolean persistentOutput;
|
private boolean persistentOutput;
|
||||||
private boolean firstTxn;
|
private boolean firstTxn;
|
||||||
|
@ -92,22 +94,14 @@ public class WALPrettyPrinter {
|
||||||
private PrintStream out;
|
private PrintStream out;
|
||||||
// for JSON encoding
|
// for JSON encoding
|
||||||
private static final Gson GSON = GsonUtil.createGson().create();
|
private static final Gson GSON = GsonUtil.createGson().create();
|
||||||
|
//allows for jumping straight to a given portion of the file
|
||||||
private long position;
|
private long position;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic constructor that simply initializes values to reasonable defaults.
|
* Basic constructor that simply initializes values to reasonable defaults.
|
||||||
*/
|
*/
|
||||||
public WALPrettyPrinter() {
|
public WALPrettyPrinter() {
|
||||||
outputValues = false;
|
this(false, false, -1, new HashSet<String>(), null, null, false, false, System.out);
|
||||||
outputJSON = false;
|
|
||||||
sequence = -1;
|
|
||||||
table = null;
|
|
||||||
region = null;
|
|
||||||
row = null;
|
|
||||||
persistentOutput = false;
|
|
||||||
firstTxn = true;
|
|
||||||
out = System.out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -122,9 +116,9 @@ public class WALPrettyPrinter {
|
||||||
* @param sequence
|
* @param sequence
|
||||||
* when nonnegative, serves as a filter; only log entries with this
|
* when nonnegative, serves as a filter; only log entries with this
|
||||||
* sequence id will be printed
|
* sequence id will be printed
|
||||||
* @param table
|
* @param tableSet
|
||||||
* when non null, serves as a filter. only entries corresponding to this
|
* when non null, serves as a filter. only entries corresponding to tables
|
||||||
* table will be printed.
|
* in the tableSet are printed
|
||||||
* @param region
|
* @param region
|
||||||
* when not null, serves as a filter; only log entries from this
|
* when not null, serves as a filter; only log entries from this
|
||||||
* region will be printed
|
* region will be printed
|
||||||
|
@ -138,15 +132,16 @@ public class WALPrettyPrinter {
|
||||||
* Specifies an alternative to stdout for the destination of this
|
* Specifies an alternative to stdout for the destination of this
|
||||||
* PrettyPrinter's output.
|
* PrettyPrinter's output.
|
||||||
*/
|
*/
|
||||||
public WALPrettyPrinter(boolean outputValues, boolean outputJSON,
|
public WALPrettyPrinter(boolean outputValues, boolean outputJSON, long sequence,
|
||||||
long sequence, String table, String region, String row, boolean persistentOutput,
|
Set<String> tableSet, String region, String row, boolean outputOnlyRowKey,
|
||||||
PrintStream out) {
|
boolean persistentOutput, PrintStream out) {
|
||||||
this.outputValues = outputValues;
|
this.outputValues = outputValues;
|
||||||
this.outputJSON = outputJSON;
|
this.outputJSON = outputJSON;
|
||||||
this.sequence = sequence;
|
this.sequence = sequence;
|
||||||
this.table = table;
|
this.tableSet = tableSet;
|
||||||
this.region = region;
|
this.region = region;
|
||||||
this.row = row;
|
this.row = row;
|
||||||
|
this.outputOnlyRowKey = outputOnlyRowKey;
|
||||||
this.persistentOutput = persistentOutput;
|
this.persistentOutput = persistentOutput;
|
||||||
if (persistentOutput) {
|
if (persistentOutput) {
|
||||||
beginPersistentOutput();
|
beginPersistentOutput();
|
||||||
|
@ -195,11 +190,11 @@ public class WALPrettyPrinter {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the table filter. Only log entries for this table are printed.
|
* Sets the tables filter. Only log entries for these tables are printed.
|
||||||
* @param table table name to set.
|
* @param tablesWithDelimiter table names separated with comma.
|
||||||
*/
|
*/
|
||||||
public void setTableFilter(String table) {
|
public void setTableFilter(String tablesWithDelimiter) {
|
||||||
this.table = table;
|
Collections.addAll(tableSet, tablesWithDelimiter.split(","));
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* sets the region by which output will be filtered
|
* sets the region by which output will be filtered
|
||||||
|
@ -213,7 +208,7 @@ public class WALPrettyPrinter {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sets the region by which output will be filtered
|
* sets the row key by which output will be filtered
|
||||||
*
|
*
|
||||||
* @param row
|
* @param row
|
||||||
* when not null, serves as a filter; only log entries from this row
|
* when not null, serves as a filter; only log entries from this row
|
||||||
|
@ -223,6 +218,22 @@ public class WALPrettyPrinter {
|
||||||
this.row = row;
|
this.row = row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Option to print the row key only in case you just need the row keys from the WAL
|
||||||
|
*/
|
||||||
|
public void setOutputOnlyRowKey() {
|
||||||
|
this.outputOnlyRowKey = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sets the position to start seeking the WAL file
|
||||||
|
* @param position
|
||||||
|
* initial position to start seeking the given WAL file
|
||||||
|
*/
|
||||||
|
public void setPosition(long position) {
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enables output as a single, persistent list. at present, only relevant in
|
* enables output as a single, persistent list. at present, only relevant in
|
||||||
* the case of JSON output.
|
* the case of JSON output.
|
||||||
|
@ -275,7 +286,7 @@ public class WALPrettyPrinter {
|
||||||
}
|
}
|
||||||
|
|
||||||
WAL.Reader log = WALFactory.createReader(fs, p, conf);
|
WAL.Reader log = WALFactory.createReader(fs, p, conf);
|
||||||
|
|
||||||
if (log instanceof ProtobufLogReader) {
|
if (log instanceof ProtobufLogReader) {
|
||||||
List<String> writerClsNames = ((ProtobufLogReader) log).getWriterClsNames();
|
List<String> writerClsNames = ((ProtobufLogReader) log).getWriterClsNames();
|
||||||
if (writerClsNames != null && writerClsNames.size() > 0) {
|
if (writerClsNames != null && writerClsNames.size() > 0) {
|
||||||
|
@ -288,13 +299,13 @@ public class WALPrettyPrinter {
|
||||||
}
|
}
|
||||||
out.println();
|
out.println();
|
||||||
}
|
}
|
||||||
|
|
||||||
String cellCodecClsName = ((ProtobufLogReader) log).getCodecClsName();
|
String cellCodecClsName = ((ProtobufLogReader) log).getCodecClsName();
|
||||||
if (cellCodecClsName != null) {
|
if (cellCodecClsName != null) {
|
||||||
out.println("Cell Codec Class: " + cellCodecClsName);
|
out.println("Cell Codec Class: " + cellCodecClsName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outputJSON && !persistentOutput) {
|
if (outputJSON && !persistentOutput) {
|
||||||
out.print("[");
|
out.print("[");
|
||||||
firstTxn = true;
|
firstTxn = true;
|
||||||
|
@ -313,7 +324,8 @@ public class WALPrettyPrinter {
|
||||||
Map<String, Object> txn = key.toStringMap();
|
Map<String, Object> txn = key.toStringMap();
|
||||||
long writeTime = key.getWriteTime();
|
long writeTime = key.getWriteTime();
|
||||||
// check output filters
|
// check output filters
|
||||||
if (table != null && !((TableName) txn.get("table")).toString().equals(table)) {
|
if (!tableSet.isEmpty() &&
|
||||||
|
!tableSet.contains(txn.get("table").toString())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (sequence >= 0 && ((Long) txn.get("sequence")) != sequence) {
|
if (sequence >= 0 && ((Long) txn.get("sequence")) != sequence) {
|
||||||
|
@ -323,10 +335,10 @@ public class WALPrettyPrinter {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// initialize list into which we will store atomic actions
|
// initialize list into which we will store atomic actions
|
||||||
List<Map<String, Object>> actions = new ArrayList<Map<String, Object>>();
|
List<Map<String, Object>> actions = new ArrayList<>();
|
||||||
for (Cell cell : edit.getCells()) {
|
for (Cell cell : edit.getCells()) {
|
||||||
// add atomic operation to txn
|
// add atomic operation to txn
|
||||||
Map<String, Object> op = new HashMap<>(toStringMap(cell));
|
Map<String, Object> op = new HashMap<>(toStringMap(cell, outputOnlyRowKey));
|
||||||
if (outputValues) {
|
if (outputValues) {
|
||||||
op.put("value", Bytes.toStringBinary(CellUtil.cloneValue(cell)));
|
op.put("value", Bytes.toStringBinary(CellUtil.cloneValue(cell)));
|
||||||
}
|
}
|
||||||
|
@ -335,7 +347,6 @@ public class WALPrettyPrinter {
|
||||||
actions.add(op);
|
actions.add(op);
|
||||||
}
|
}
|
||||||
op.put("total_size_sum", CellUtil.estimatedHeapSizeOf(cell));
|
op.put("total_size_sum", CellUtil.estimatedHeapSizeOf(cell));
|
||||||
|
|
||||||
}
|
}
|
||||||
if (actions.isEmpty()) {
|
if (actions.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -356,15 +367,7 @@ public class WALPrettyPrinter {
|
||||||
txn.get("sequence"), txn.get("table"), txn.get("region"), new Date(writeTime)));
|
txn.get("sequence"), txn.get("table"), txn.get("region"), new Date(writeTime)));
|
||||||
for (int i = 0; i < actions.size(); i++) {
|
for (int i = 0; i < actions.size(); i++) {
|
||||||
Map<String, Object> op = actions.get(i);
|
Map<String, Object> op = actions.get(i);
|
||||||
out.println("row=" + op.get("row") +
|
printCell(out, op, outputValues);
|
||||||
", column=" + op.get("family") + ":" + op.get("qualifier"));
|
|
||||||
if (op.get("tag") != null) {
|
|
||||||
out.println(" tag: " + op.get("tag"));
|
|
||||||
}
|
|
||||||
if (outputValues) {
|
|
||||||
out.println(" value: " + op.get("value"));
|
|
||||||
}
|
|
||||||
out.println("cell total size sum: " + op.get("total_size_sum"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.println("edit heap size: " + entry.getEdit().heapSize());
|
out.println("edit heap size: " + entry.getEdit().heapSize());
|
||||||
|
@ -378,31 +381,51 @@ public class WALPrettyPrinter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<String, Object> toStringMap(Cell cell) {
|
public static void printCell(PrintStream out, Map<String, Object> op, boolean outputValues) {
|
||||||
Map<String, Object> stringMap = new HashMap<String, Object>();
|
out.println("row=" + op.get("row") + ", column=" +
|
||||||
|
op.get("family") + ":" + op.get("qualifier"));
|
||||||
|
if (op.get("tag") != null) {
|
||||||
|
out.println(" tag: " + op.get("tag"));
|
||||||
|
}
|
||||||
|
if (outputValues) {
|
||||||
|
out.println(" value: " + op.get("value"));
|
||||||
|
}
|
||||||
|
out.println("cell total size sum: " + op.get("total_size_sum"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, Object> toStringMap(Cell cell, boolean printRowKeyOnly) {
|
||||||
|
Map<String, Object> stringMap = new HashMap<>();
|
||||||
stringMap.put("row",
|
stringMap.put("row",
|
||||||
Bytes.toStringBinary(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength()));
|
Bytes.toStringBinary(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength()));
|
||||||
stringMap.put("family", Bytes.toStringBinary(cell.getFamilyArray(), cell.getFamilyOffset(),
|
|
||||||
cell.getFamilyLength()));
|
if (printRowKeyOnly) {
|
||||||
stringMap.put("qualifier",
|
return stringMap;
|
||||||
Bytes.toStringBinary(cell.getQualifierArray(), cell.getQualifierOffset(),
|
}
|
||||||
cell.getQualifierLength()));
|
stringMap.put("family",
|
||||||
|
Bytes.toStringBinary(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength()));
|
||||||
|
stringMap.put("qualifier", Bytes
|
||||||
|
.toStringBinary(cell.getQualifierArray(), cell.getQualifierOffset(),
|
||||||
|
cell.getQualifierLength()));
|
||||||
stringMap.put("timestamp", cell.getTimestamp());
|
stringMap.put("timestamp", cell.getTimestamp());
|
||||||
stringMap.put("vlen", cell.getValueLength());
|
stringMap.put("vlen", cell.getValueLength());
|
||||||
if (cell.getTagsLength() > 0) {
|
if (cell.getTagsLength() > 0) {
|
||||||
List<String> tagsString = new ArrayList<String>();
|
List<String> tagsString = new ArrayList<>();
|
||||||
Iterator<Tag> tagsIterator = CellUtil.tagsIterator(cell.getTagsArray(), cell.getTagsOffset(),
|
Iterator<Tag> tagsIterator =
|
||||||
cell.getTagsLength());
|
CellUtil.tagsIterator(cell.getTagsArray(), cell.getTagsOffset(), cell.getTagsLength());
|
||||||
while (tagsIterator.hasNext()) {
|
while (tagsIterator.hasNext()) {
|
||||||
Tag tag = tagsIterator.next();
|
Tag tag = tagsIterator.next();
|
||||||
tagsString.add((tag.getType()) + ":"
|
tagsString.add((tag.getType()) + ":" + Bytes
|
||||||
+ Bytes.toStringBinary(tag.getBuffer(), tag.getTagOffset(), tag.getTagLength()));
|
.toStringBinary(tag.getBuffer(), tag.getTagOffset(), tag.getTagLength()));
|
||||||
}
|
}
|
||||||
stringMap.put("tag", tagsString);
|
stringMap.put("tag", tagsString);
|
||||||
}
|
}
|
||||||
return stringMap;
|
return stringMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Map<String, Object> toStringMap(Cell cell) {
|
||||||
|
return toStringMap(cell, false);
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
run(args);
|
run(args);
|
||||||
}
|
}
|
||||||
|
@ -422,11 +445,14 @@ public class WALPrettyPrinter {
|
||||||
options.addOption("h", "help", false, "Output help message");
|
options.addOption("h", "help", false, "Output help message");
|
||||||
options.addOption("j", "json", false, "Output JSON");
|
options.addOption("j", "json", false, "Output JSON");
|
||||||
options.addOption("p", "printvals", false, "Print values");
|
options.addOption("p", "printvals", false, "Print values");
|
||||||
options.addOption("t", "table", true, "Table name to filter by.");
|
options.addOption("t", "tables", true,
|
||||||
|
"Table names (comma separated) to filter by; eg: test1,test2,test3 ");
|
||||||
options.addOption("r", "region", true,
|
options.addOption("r", "region", true,
|
||||||
"Region to filter by. Pass encoded region name; e.g. '9192caead6a5a20acb4454ffbc79fa14'");
|
"Region to filter by. Pass encoded region name; e.g. '9192caead6a5a20acb4454ffbc79fa14'");
|
||||||
options.addOption("s", "sequence", true,
|
options.addOption("s", "sequence", true,
|
||||||
"Sequence to filter by. Pass sequence number.");
|
"Sequence to filter by. Pass sequence number.");
|
||||||
|
options.addOption("k", "outputOnlyRowKey", false,
|
||||||
|
"Print only row keys");
|
||||||
options.addOption("w", "row", true, "Row to filter by. Pass row name.");
|
options.addOption("w", "row", true, "Row to filter by. Pass row name.");
|
||||||
options.addOption("g", "goto", true, "Position to seek to in the file");
|
options.addOption("g", "goto", true, "Position to seek to in the file");
|
||||||
|
|
||||||
|
@ -448,6 +474,9 @@ public class WALPrettyPrinter {
|
||||||
if (cmd.hasOption("j")) {
|
if (cmd.hasOption("j")) {
|
||||||
printer.enableJSON();
|
printer.enableJSON();
|
||||||
}
|
}
|
||||||
|
if (cmd.hasOption("k")) {
|
||||||
|
printer.setOutputOnlyRowKey();
|
||||||
|
}
|
||||||
if (cmd.hasOption("t")) {
|
if (cmd.hasOption("t")) {
|
||||||
printer.setTableFilter(cmd.getOptionValue("t"));
|
printer.setTableFilter(cmd.getOptionValue("t"));
|
||||||
}
|
}
|
||||||
|
@ -486,8 +515,4 @@ public class WALPrettyPrinter {
|
||||||
}
|
}
|
||||||
printer.endPersistentOutput();
|
printer.endPersistentOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPosition(long position) {
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue