HBASE-24776 [hbtop] Support Batch mode (#2291)
Signed-off-by: stack <stack@apache.org>
This commit is contained in:
parent
f36c55c6e8
commit
bc15b61927
|
@ -17,11 +17,17 @@
|
|||
*/
|
||||
package org.apache.hadoop.hbase.hbtop;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.conf.Configured;
|
||||
import org.apache.hadoop.hbase.HBaseConfiguration;
|
||||
import org.apache.hadoop.hbase.HBaseInterfaceAudience;
|
||||
import org.apache.hadoop.hbase.hbtop.field.Field;
|
||||
import org.apache.hadoop.hbase.hbtop.field.FieldInfo;
|
||||
import org.apache.hadoop.hbase.hbtop.mode.Mode;
|
||||
import org.apache.hadoop.hbase.hbtop.screen.Screen;
|
||||
import org.apache.hadoop.util.Tool;
|
||||
|
@ -56,17 +62,14 @@ public class HBTop extends Configured implements Tool {
|
|||
public int run(String[] args) throws Exception {
|
||||
long initialRefreshDelay = 3 * 1000;
|
||||
Mode initialMode = Mode.REGION;
|
||||
List<Field> initialFields = null;
|
||||
Field initialSortField = null;
|
||||
Boolean initialAscendingSort = null;
|
||||
List<RecordFilter> initialFilters = null;
|
||||
long numberOfIterations = Long.MAX_VALUE;
|
||||
boolean batchMode = false;
|
||||
try {
|
||||
// Command line options
|
||||
Options opts = new Options();
|
||||
opts.addOption("h", "help", false,
|
||||
"Print usage; for help while the tool is running press 'h'");
|
||||
opts.addOption("d", "delay", true,
|
||||
"The refresh delay (in seconds); default is 3 seconds");
|
||||
opts.addOption("m", "mode", true,
|
||||
"The mode; n (Namespace)|t (Table)|r (Region)|s (RegionServer)"
|
||||
+ ", default is r (Region)");
|
||||
|
||||
Options opts = getOptions();
|
||||
CommandLine commandLine = new DefaultParser().parse(opts, args);
|
||||
|
||||
if (commandLine.hasOption("help")) {
|
||||
|
@ -74,20 +77,6 @@ public class HBTop extends Configured implements Tool {
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (commandLine.hasOption("delay")) {
|
||||
int delay = 0;
|
||||
try {
|
||||
delay = Integer.parseInt(commandLine.getOptionValue("delay"));
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
|
||||
if (delay < 1) {
|
||||
LOGGER.warn("Delay set too low or invalid, using default");
|
||||
} else {
|
||||
initialRefreshDelay = delay * 1000L;
|
||||
}
|
||||
}
|
||||
|
||||
if (commandLine.hasOption("mode")) {
|
||||
String mode = commandLine.getOptionValue("mode");
|
||||
switch (mode) {
|
||||
|
@ -107,23 +96,148 @@ public class HBTop extends Configured implements Tool {
|
|||
initialMode = Mode.REGION_SERVER;
|
||||
break;
|
||||
|
||||
case "u":
|
||||
initialMode = Mode.USER;
|
||||
break;
|
||||
|
||||
case "c":
|
||||
initialMode = Mode.CLIENT;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOGGER.warn("Mode set invalid, using default");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (commandLine.hasOption("outputFieldNames")) {
|
||||
initialMode.getFieldInfos().forEach(f -> System.out.println(f.getField().getHeader()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (commandLine.hasOption("delay")) {
|
||||
int delay = 0;
|
||||
try {
|
||||
delay = Integer.parseInt(commandLine.getOptionValue("delay"));
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
|
||||
if (delay < 1) {
|
||||
LOGGER.warn("Delay set too low or invalid, using default");
|
||||
} else {
|
||||
initialRefreshDelay = delay * 1000L;
|
||||
}
|
||||
}
|
||||
|
||||
if (commandLine.hasOption("numberOfIterations")) {
|
||||
try {
|
||||
numberOfIterations = Long.parseLong(commandLine.getOptionValue("numberOfIterations"));
|
||||
} catch (NumberFormatException ignored) {
|
||||
LOGGER.warn("The number of iterations set invalid, ignoring");
|
||||
}
|
||||
}
|
||||
|
||||
if (commandLine.hasOption("sortField")) {
|
||||
String sortField = commandLine.getOptionValue("sortField");
|
||||
|
||||
String field;
|
||||
boolean ascendingSort;
|
||||
if (sortField.startsWith("+")) {
|
||||
field = sortField.substring(1);
|
||||
ascendingSort = false;
|
||||
} else if (sortField.startsWith("-")) {
|
||||
field = sortField.substring(1);
|
||||
ascendingSort = true;
|
||||
} else {
|
||||
field = sortField;
|
||||
ascendingSort = false;
|
||||
}
|
||||
|
||||
Optional<FieldInfo> fieldInfo = initialMode.getFieldInfos().stream()
|
||||
.filter(f -> f.getField().getHeader().equals(field)).findFirst();
|
||||
if (fieldInfo.isPresent()) {
|
||||
initialSortField = fieldInfo.get().getField();
|
||||
initialAscendingSort = ascendingSort;
|
||||
} else {
|
||||
LOGGER.warn("The specified sort field " + field + " is not found, using default");
|
||||
}
|
||||
}
|
||||
|
||||
if (commandLine.hasOption("fields")) {
|
||||
String[] fields = commandLine.getOptionValue("fields").split(",");
|
||||
initialFields = new ArrayList<>();
|
||||
for (String field : fields) {
|
||||
Optional<FieldInfo> fieldInfo = initialMode.getFieldInfos().stream()
|
||||
.filter(f -> f.getField().getHeader().equals(field)).findFirst();
|
||||
if (fieldInfo.isPresent()) {
|
||||
initialFields.add(fieldInfo.get().getField());
|
||||
} else {
|
||||
LOGGER.warn("The specified field " + field + " is not found, ignoring");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (commandLine.hasOption("filters")) {
|
||||
String[] filters = commandLine.getOptionValue("filters").split(",");
|
||||
List<Field> fields = initialMode.getFieldInfos().stream().map(FieldInfo::getField)
|
||||
.collect(Collectors.toList());
|
||||
for (String filter : filters) {
|
||||
RecordFilter f = RecordFilter.parse(filter, fields, false);
|
||||
if (f != null) {
|
||||
if (initialFilters == null) {
|
||||
initialFilters = new ArrayList<>();
|
||||
}
|
||||
initialFilters.add(f);
|
||||
} else {
|
||||
LOGGER.warn("The specified filter " + filter + " is invalid, ignoring");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (commandLine.hasOption("batchMode")) {
|
||||
batchMode = true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Unable to parse options", e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
try (Screen screen = new Screen(getConf(), initialRefreshDelay, initialMode)) {
|
||||
try (Screen screen = new Screen(getConf(), initialRefreshDelay, initialMode, initialFields,
|
||||
initialSortField, initialAscendingSort, initialFilters, numberOfIterations, batchMode)) {
|
||||
screen.run();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private Options getOptions() {
|
||||
Options opts = new Options();
|
||||
opts.addOption("h", "help", false,
|
||||
"Print usage; for help while the tool is running press 'h'");
|
||||
opts.addOption("d", "delay", true,
|
||||
"The refresh delay (in seconds); default is 3 seconds");
|
||||
opts.addOption("m", "mode", true,
|
||||
"The mode; n (Namespace)|t (Table)|r (Region)|s (RegionServer)|u (User)"
|
||||
+ "|c (Client), default is r");
|
||||
opts.addOption("n", "numberOfIterations", true,
|
||||
"The number of iterations");
|
||||
opts.addOption("s", "sortField", true,
|
||||
"The initial sort field. You can prepend a `+' or `-' to the field name to also override"
|
||||
+ " the sort direction. A leading `+' will force sorting high to low, whereas a `-' will"
|
||||
+ " ensure a low to high ordering");
|
||||
opts.addOption("O", "outputFieldNames", false,
|
||||
"Print each of the available field names on a separate line, then quit");
|
||||
opts.addOption("f", "fields", true,
|
||||
"Show only the given fields. Specify comma separated fields to show multiple fields");
|
||||
opts.addOption("i", "filters", true,
|
||||
"The initial filters. Specify comma separated filters to set multiple filters");
|
||||
opts.addOption("b", "batchMode", false,
|
||||
"Starts hbtop in Batch mode, which could be useful for sending output from hbtop to other"
|
||||
+ " programs or to a file. In this mode, hbtop will not accept input and runs until the"
|
||||
+ " iterations limit you've set with the `-n' command-line option or until killed");
|
||||
return opts;
|
||||
}
|
||||
|
||||
private void printUsage(Options opts) {
|
||||
new HelpFormatter().printHelp("hbase hbtop [opts] [-D<property=value>]*", opts);
|
||||
System.out.println("");
|
||||
|
|
|
@ -75,6 +75,7 @@ public abstract class AbstractScreenView implements ScreenView {
|
|||
return terminal.getTerminalPrinter(startRow);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected TerminalSize getTerminalSize() {
|
||||
return terminal.getSize();
|
||||
}
|
||||
|
|
|
@ -17,18 +17,23 @@
|
|||
*/
|
||||
package org.apache.hadoop.hbase.hbtop.screen;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.Nullable;
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.hbase.client.Admin;
|
||||
import org.apache.hadoop.hbase.client.Connection;
|
||||
import org.apache.hadoop.hbase.client.ConnectionFactory;
|
||||
import org.apache.hadoop.hbase.hbtop.RecordFilter;
|
||||
import org.apache.hadoop.hbase.hbtop.field.Field;
|
||||
import org.apache.hadoop.hbase.hbtop.mode.Mode;
|
||||
import org.apache.hadoop.hbase.hbtop.screen.top.TopScreenView;
|
||||
import org.apache.hadoop.hbase.hbtop.terminal.KeyPress;
|
||||
import org.apache.hadoop.hbase.hbtop.terminal.Terminal;
|
||||
import org.apache.hadoop.hbase.hbtop.terminal.impl.TerminalImpl;
|
||||
import org.apache.hadoop.hbase.hbtop.terminal.impl.batch.BatchTerminal;
|
||||
import org.apache.yetus.audience.InterfaceAudience;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -49,15 +54,23 @@ public class Screen implements Closeable {
|
|||
private ScreenView currentScreenView;
|
||||
private Long timerTimestamp;
|
||||
|
||||
public Screen(Configuration conf, long initialRefreshDelay, Mode initialMode)
|
||||
public Screen(Configuration conf, long initialRefreshDelay, Mode initialMode,
|
||||
@Nullable List<Field> initialFields, @Nullable Field initialSortField,
|
||||
@Nullable Boolean initialAscendingSort, @Nullable List<RecordFilter> initialFilters,
|
||||
long numberOfIterations, boolean batchMode)
|
||||
throws IOException {
|
||||
connection = ConnectionFactory.createConnection(conf);
|
||||
admin = connection.getAdmin();
|
||||
|
||||
// The first screen is the top screen
|
||||
this.terminal = new TerminalImpl("hbtop");
|
||||
if (batchMode) {
|
||||
terminal = new BatchTerminal();
|
||||
} else {
|
||||
terminal = new TerminalImpl("hbtop");
|
||||
}
|
||||
currentScreenView = new TopScreenView(this, terminal, initialRefreshDelay, admin,
|
||||
initialMode);
|
||||
initialMode, initialFields, initialSortField, initialAscendingSort, initialFilters,
|
||||
numberOfIterations);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -91,11 +104,8 @@ public class Screen implements Closeable {
|
|||
timerTimestamp = null;
|
||||
nextScreenView = currentScreenView.handleTimer();
|
||||
} else {
|
||||
if (timerTimestamp - now < SLEEP_TIMEOUT_MILLISECONDS) {
|
||||
TimeUnit.MILLISECONDS.sleep(timerTimestamp - now);
|
||||
} else {
|
||||
TimeUnit.MILLISECONDS.sleep(SLEEP_TIMEOUT_MILLISECONDS);
|
||||
}
|
||||
TimeUnit.MILLISECONDS
|
||||
.sleep(Math.min(timerTimestamp - now, SLEEP_TIMEOUT_MILLISECONDS));
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -19,13 +19,13 @@ package org.apache.hadoop.hbase.hbtop.screen.top;
|
|||
|
||||
import static org.apache.commons.lang3.time.DateFormatUtils.ISO_8601_EXTENDED_TIME_FORMAT;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.hadoop.hbase.ClusterMetrics;
|
||||
import org.apache.hadoop.hbase.client.Admin;
|
||||
import org.apache.hadoop.hbase.hbtop.Record;
|
||||
|
@ -64,29 +64,56 @@ public class TopScreenModel {
|
|||
|
||||
private boolean ascendingSort;
|
||||
|
||||
public TopScreenModel(Admin admin, Mode initialMode) {
|
||||
public TopScreenModel(Admin admin, Mode initialMode, @Nullable List<Field> initialFields,
|
||||
@Nullable Field initialSortField, @Nullable Boolean initialAscendingSort,
|
||||
@Nullable List<RecordFilter> initialFilters) {
|
||||
this.admin = Objects.requireNonNull(admin);
|
||||
switchMode(Objects.requireNonNull(initialMode), null, false);
|
||||
switchMode(Objects.requireNonNull(initialMode), initialSortField, false, initialFields,
|
||||
initialAscendingSort, initialFilters);
|
||||
}
|
||||
|
||||
public void switchMode(Mode nextMode, List<RecordFilter> initialFilters,
|
||||
boolean keepSortFieldAndSortOrderIfPossible) {
|
||||
public void switchMode(Mode nextMode, boolean keepSortFieldAndSortOrderIfPossible,
|
||||
List<RecordFilter> initialFilters) {
|
||||
switchMode(nextMode, null, keepSortFieldAndSortOrderIfPossible, null, null, initialFilters);
|
||||
}
|
||||
|
||||
public void switchMode(Mode nextMode, Field initialSortField,
|
||||
boolean keepSortFieldAndSortOrderIfPossible, @Nullable List<Field> initialFields,
|
||||
@Nullable Boolean initialAscendingSort, @Nullable List<RecordFilter> initialFilters) {
|
||||
currentMode = nextMode;
|
||||
fieldInfos = Collections.unmodifiableList(new ArrayList<>(currentMode.getFieldInfos()));
|
||||
|
||||
if (initialFields != null) {
|
||||
List<Field> tmp = new ArrayList<>(initialFields);
|
||||
tmp.addAll(currentMode.getFieldInfos().stream().map(FieldInfo::getField)
|
||||
.filter(f -> !initialFields.contains(f))
|
||||
.collect(Collectors.toList()));
|
||||
fields = Collections.unmodifiableList(tmp);
|
||||
} else {
|
||||
fields = Collections.unmodifiableList(currentMode.getFieldInfos().stream()
|
||||
.map(FieldInfo::getField).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
if (keepSortFieldAndSortOrderIfPossible) {
|
||||
boolean match = fields.stream().anyMatch(f -> f == currentSortField);
|
||||
if (!match) {
|
||||
currentSortField = nextMode.getDefaultSortField();
|
||||
ascendingSort = false;
|
||||
}
|
||||
if (initialSortField != null && initialAscendingSort != null) {
|
||||
currentSortField = initialSortField;
|
||||
ascendingSort = initialAscendingSort;
|
||||
} else {
|
||||
currentSortField = nextMode.getDefaultSortField();
|
||||
ascendingSort = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (initialSortField != null && initialAscendingSort != null) {
|
||||
currentSortField = initialSortField;
|
||||
ascendingSort = initialAscendingSort;
|
||||
} else {
|
||||
currentSortField = nextMode.getDefaultSortField();
|
||||
ascendingSort = false;
|
||||
}
|
||||
}
|
||||
|
||||
clearFilters();
|
||||
if (initialFilters != null) {
|
||||
|
@ -173,7 +200,7 @@ public class TopScreenModel {
|
|||
if (drillDownInfo == null) {
|
||||
return false;
|
||||
}
|
||||
switchMode(drillDownInfo.getNextMode(), drillDownInfo.getInitialFilters(), true);
|
||||
switchMode(drillDownInfo.getNextMode(), true, drillDownInfo.getInitialFilters());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
package org.apache.hadoop.hbase.hbtop.screen.top;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
|
@ -57,21 +58,38 @@ public class TopScreenPresenter {
|
|||
private final EnumMap<Field, Boolean> fieldDisplayMap = new EnumMap<>(Field.class);
|
||||
private final EnumMap<Field, Integer> fieldLengthMap = new EnumMap<>(Field.class);
|
||||
|
||||
private final long numberOfIterations;
|
||||
private long iterations;
|
||||
|
||||
public TopScreenPresenter(TopScreenView topScreenView, long initialRefreshDelay,
|
||||
TopScreenModel topScreenModel) {
|
||||
TopScreenModel topScreenModel, @Nullable List<Field> initialFields, long numberOfIterations) {
|
||||
this.topScreenView = Objects.requireNonNull(topScreenView);
|
||||
this.refreshDelay = new AtomicLong(initialRefreshDelay);
|
||||
this.topScreenModel = Objects.requireNonNull(topScreenModel);
|
||||
this.numberOfIterations = numberOfIterations;
|
||||
|
||||
initFieldDisplayMapAndFieldLengthMap();
|
||||
initFieldDisplayMapAndFieldLengthMap(initialFields);
|
||||
}
|
||||
|
||||
public void init() {
|
||||
terminalLength = topScreenView.getTerminalSize().getColumns();
|
||||
paging.updatePageSize(topScreenView.getPageSize());
|
||||
updateTerminalLengthAndPageSize(topScreenView.getTerminalSize(), topScreenView.getPageSize());
|
||||
topScreenView.hideCursor();
|
||||
}
|
||||
|
||||
private void updateTerminalLengthAndPageSize(@Nullable TerminalSize terminalSize,
|
||||
@Nullable Integer pageSize) {
|
||||
if (terminalSize != null) {
|
||||
terminalLength = terminalSize.getColumns();
|
||||
} else {
|
||||
terminalLength = Integer.MAX_VALUE;
|
||||
}
|
||||
if (pageSize != null) {
|
||||
paging.updatePageSize(pageSize);
|
||||
} else {
|
||||
paging.updatePageSize(Integer.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
public long refresh(boolean force) {
|
||||
if (!force) {
|
||||
long delay = System.currentTimeMillis() - lastRefreshTimestamp;
|
||||
|
@ -82,8 +100,7 @@ public class TopScreenPresenter {
|
|||
|
||||
TerminalSize newTerminalSize = topScreenView.doResizeIfNecessary();
|
||||
if (newTerminalSize != null) {
|
||||
terminalLength = newTerminalSize.getColumns();
|
||||
paging.updatePageSize(topScreenView.getPageSize());
|
||||
updateTerminalLengthAndPageSize(newTerminalSize, topScreenView.getPageSize());
|
||||
topScreenView.clearTerminal();
|
||||
}
|
||||
|
||||
|
@ -98,6 +115,7 @@ public class TopScreenPresenter {
|
|||
topScreenView.refreshTerminal();
|
||||
|
||||
lastRefreshTimestamp = System.currentTimeMillis();
|
||||
iterations++;
|
||||
return refreshDelay.get();
|
||||
}
|
||||
|
||||
|
@ -242,7 +260,7 @@ public class TopScreenPresenter {
|
|||
}
|
||||
|
||||
private void switchMode(Mode nextMode) {
|
||||
topScreenModel.switchMode(nextMode, null, false);
|
||||
topScreenModel.switchMode(nextMode, false, null);
|
||||
reset();
|
||||
}
|
||||
|
||||
|
@ -258,18 +276,22 @@ public class TopScreenPresenter {
|
|||
}
|
||||
|
||||
private void reset() {
|
||||
initFieldDisplayMapAndFieldLengthMap();
|
||||
initFieldDisplayMapAndFieldLengthMap(null);
|
||||
adjustFieldLength.set(true);
|
||||
paging.init();
|
||||
horizontalScroll = 0;
|
||||
topScreenView.clearTerminal();
|
||||
}
|
||||
|
||||
private void initFieldDisplayMapAndFieldLengthMap() {
|
||||
private void initFieldDisplayMapAndFieldLengthMap(@Nullable List<Field> initialFields) {
|
||||
fieldDisplayMap.clear();
|
||||
fieldLengthMap.clear();
|
||||
for (FieldInfo fieldInfo : topScreenModel.getFieldInfos()) {
|
||||
if (initialFields != null) {
|
||||
fieldDisplayMap.put(fieldInfo.getField(), initialFields.contains(fieldInfo.getField()));
|
||||
} else {
|
||||
fieldDisplayMap.put(fieldInfo.getField(), fieldInfo.isDisplayByDefault());
|
||||
}
|
||||
fieldLengthMap.put(fieldInfo.getField(), fieldInfo.getDefaultLength());
|
||||
}
|
||||
}
|
||||
|
@ -288,7 +310,7 @@ public class TopScreenPresenter {
|
|||
|
||||
double delay;
|
||||
try {
|
||||
delay = Double.valueOf(inputString);
|
||||
delay = Double.parseDouble(inputString);
|
||||
} catch (NumberFormatException e) {
|
||||
return goToMessageMode(screen, terminal, row, "Unacceptable floating point");
|
||||
}
|
||||
|
@ -329,4 +351,8 @@ public class TopScreenPresenter {
|
|||
filters.addAll(topScreenModel.getPushDownFilters());
|
||||
return new FilterDisplayModeScreenView(screen, terminal, row, filters, topScreenView);
|
||||
}
|
||||
|
||||
public boolean isIterationFinished() {
|
||||
return iterations >= numberOfIterations;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ import java.util.List;
|
|||
import java.util.stream.Collectors;
|
||||
import org.apache.hadoop.hbase.client.Admin;
|
||||
import org.apache.hadoop.hbase.hbtop.Record;
|
||||
import org.apache.hadoop.hbase.hbtop.RecordFilter;
|
||||
import org.apache.hadoop.hbase.hbtop.field.Field;
|
||||
import org.apache.hadoop.hbase.hbtop.mode.Mode;
|
||||
import org.apache.hadoop.hbase.hbtop.screen.AbstractScreenView;
|
||||
import org.apache.hadoop.hbase.hbtop.screen.Screen;
|
||||
|
@ -50,13 +52,16 @@ public class TopScreenView extends AbstractScreenView {
|
|||
private static final int RECORD_START_ROW = 9;
|
||||
|
||||
private final TopScreenPresenter topScreenPresenter;
|
||||
private int pageSize;
|
||||
private Integer pageSize;
|
||||
|
||||
public TopScreenView(Screen screen, Terminal terminal, long initialRefreshDelay, Admin admin,
|
||||
Mode initialMode) {
|
||||
Mode initialMode, @Nullable List<Field> initialFields, @Nullable Field initialSortField,
|
||||
@Nullable Boolean initialAscendingSort, @Nullable List<RecordFilter> initialFilters,
|
||||
long numberOfIterations) {
|
||||
super(screen, terminal);
|
||||
this.topScreenPresenter = new TopScreenPresenter(this, initialRefreshDelay,
|
||||
new TopScreenModel(admin, initialMode));
|
||||
new TopScreenModel(admin, initialMode, initialFields, initialSortField,
|
||||
initialAscendingSort, initialFilters), initialFields, numberOfIterations);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -66,11 +71,12 @@ public class TopScreenView extends AbstractScreenView {
|
|||
setTimer(delay);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ScreenView handleTimer() {
|
||||
long delay = topScreenPresenter.refresh(false);
|
||||
setTimer(delay);
|
||||
return this;
|
||||
return topScreenPresenter.isIterationFinished() ? null : this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -79,39 +85,39 @@ public class TopScreenView extends AbstractScreenView {
|
|||
switch (keyPress.getType()) {
|
||||
case Enter:
|
||||
topScreenPresenter.refresh(true);
|
||||
return this;
|
||||
return topScreenPresenter.isIterationFinished() ? null : this;
|
||||
|
||||
case ArrowUp:
|
||||
topScreenPresenter.arrowUp();
|
||||
return this;
|
||||
return topScreenPresenter.isIterationFinished() ? null : this;
|
||||
|
||||
case ArrowDown:
|
||||
topScreenPresenter.arrowDown();
|
||||
return this;
|
||||
return topScreenPresenter.isIterationFinished() ? null : this;
|
||||
|
||||
case ArrowLeft:
|
||||
topScreenPresenter.arrowLeft();
|
||||
return this;
|
||||
return topScreenPresenter.isIterationFinished() ? null : this;
|
||||
|
||||
case ArrowRight:
|
||||
topScreenPresenter.arrowRight();
|
||||
return this;
|
||||
return topScreenPresenter.isIterationFinished() ? null : this;
|
||||
|
||||
case PageUp:
|
||||
topScreenPresenter.pageUp();
|
||||
return this;
|
||||
return topScreenPresenter.isIterationFinished() ? null : this;
|
||||
|
||||
case PageDown:
|
||||
topScreenPresenter.pageDown();
|
||||
return this;
|
||||
return topScreenPresenter.isIterationFinished() ? null : this;
|
||||
|
||||
case Home:
|
||||
topScreenPresenter.home();
|
||||
return this;
|
||||
return topScreenPresenter.isIterationFinished() ? null : this;
|
||||
|
||||
case End:
|
||||
topScreenPresenter.end();
|
||||
return this;
|
||||
return topScreenPresenter.isIterationFinished() ? null : this;
|
||||
|
||||
case Escape:
|
||||
return null;
|
||||
|
@ -182,13 +188,18 @@ public class TopScreenView extends AbstractScreenView {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public TerminalSize getTerminalSize() {
|
||||
TerminalSize terminalSize = super.getTerminalSize();
|
||||
if (terminalSize == null) {
|
||||
return null;
|
||||
}
|
||||
updatePageSize(terminalSize);
|
||||
return terminalSize;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public TerminalSize doResizeIfNecessary() {
|
||||
TerminalSize terminalSize = super.doResizeIfNecessary();
|
||||
|
@ -206,7 +217,8 @@ public class TopScreenView extends AbstractScreenView {
|
|||
}
|
||||
}
|
||||
|
||||
public int getPageSize() {
|
||||
@Nullable
|
||||
public Integer getPageSize() {
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
|
@ -244,8 +256,14 @@ public class TopScreenView extends AbstractScreenView {
|
|||
|
||||
private void showRecords(List<Header> headers, List<Record> records, Record selectedRecord) {
|
||||
TerminalPrinter printer = getTerminalPrinter(RECORD_START_ROW);
|
||||
int size;
|
||||
if (pageSize != null) {
|
||||
size = pageSize;
|
||||
} else {
|
||||
size = records.size();
|
||||
}
|
||||
List<String> buf = new ArrayList<>(headers.size());
|
||||
for (int i = 0; i < pageSize; i++) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
if(i < records.size()) {
|
||||
Record record = records.get(i);
|
||||
buf.clear();
|
||||
|
|
|
@ -29,7 +29,7 @@ import org.apache.yetus.audience.InterfaceAudience;
|
|||
public interface Terminal extends Closeable {
|
||||
void clear();
|
||||
void refresh();
|
||||
TerminalSize getSize();
|
||||
@Nullable TerminalSize getSize();
|
||||
@Nullable TerminalSize doResizeIfNecessary();
|
||||
@Nullable KeyPress pollKeyPress();
|
||||
CursorPosition getCursorPosition();
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.hadoop.hbase.hbtop.terminal.impl.batch;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.Nullable;
|
||||
import org.apache.hadoop.hbase.hbtop.terminal.CursorPosition;
|
||||
import org.apache.hadoop.hbase.hbtop.terminal.KeyPress;
|
||||
import org.apache.hadoop.hbase.hbtop.terminal.Terminal;
|
||||
import org.apache.hadoop.hbase.hbtop.terminal.TerminalPrinter;
|
||||
import org.apache.hadoop.hbase.hbtop.terminal.TerminalSize;
|
||||
|
||||
public class BatchTerminal implements Terminal {
|
||||
|
||||
private static final TerminalPrinter TERMINAL_PRINTER = new BatchTerminalPrinter();
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
// Add a new line
|
||||
TERMINAL_PRINTER.endOfLine();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public TerminalSize getSize() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public TerminalSize doResizeIfNecessary() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public KeyPress pollKeyPress() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CursorPosition getCursorPosition() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCursorPosition(int column, int row) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideCursor() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerminalPrinter getTerminalPrinter(int startRow) {
|
||||
return TERMINAL_PRINTER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.hadoop.hbase.hbtop.terminal.impl.batch;
|
||||
|
||||
import org.apache.hadoop.hbase.hbtop.terminal.TerminalPrinter;
|
||||
|
||||
public class BatchTerminalPrinter implements TerminalPrinter {
|
||||
|
||||
@Override
|
||||
public TerminalPrinter print(String value) {
|
||||
System.out.print(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerminalPrinter startHighlight() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerminalPrinter stopHighlight() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerminalPrinter startBold() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerminalPrinter stopBold() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endOfLine() {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
|
@ -63,7 +63,7 @@ public class TestTopScreenModel {
|
|||
@Before
|
||||
public void setup() throws IOException {
|
||||
when(admin.getClusterMetrics()).thenReturn(TestUtils.createDummyClusterMetrics());
|
||||
topScreenModel = new TopScreenModel(admin, Mode.REGION);
|
||||
topScreenModel = new TopScreenModel(admin, Mode.REGION, null, null, null, null);
|
||||
|
||||
fields = Mode.REGION.getFieldInfos().stream()
|
||||
.map(FieldInfo::getField)
|
||||
|
@ -84,17 +84,17 @@ public class TestTopScreenModel {
|
|||
TestUtils.assertRecordsInRegionMode(topScreenModel.getRecords());
|
||||
|
||||
// Namespace Mode
|
||||
topScreenModel.switchMode(Mode.NAMESPACE, null, false);
|
||||
topScreenModel.switchMode(Mode.NAMESPACE, false, null);
|
||||
topScreenModel.refreshMetricsData();
|
||||
TestUtils.assertRecordsInNamespaceMode(topScreenModel.getRecords());
|
||||
|
||||
// Table Mode
|
||||
topScreenModel.switchMode(Mode.TABLE, null, false);
|
||||
topScreenModel.switchMode(Mode.TABLE, false, null);
|
||||
topScreenModel.refreshMetricsData();
|
||||
TestUtils.assertRecordsInTableMode(topScreenModel.getRecords());
|
||||
|
||||
// Namespace Mode
|
||||
topScreenModel.switchMode(Mode.REGION_SERVER, null, false);
|
||||
topScreenModel.switchMode(Mode.REGION_SERVER, false, null);
|
||||
topScreenModel.refreshMetricsData();
|
||||
TestUtils.assertRecordsInRegionServerMode(topScreenModel.getRecords());
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ public class TestTopScreenModel {
|
|||
|
||||
@Test
|
||||
public void testSwitchMode() {
|
||||
topScreenModel.switchMode(Mode.TABLE, null, false);
|
||||
topScreenModel.switchMode(Mode.TABLE, false, null);
|
||||
assertThat(topScreenModel.getCurrentMode(), is(Mode.TABLE));
|
||||
|
||||
// Test for initialFilters
|
||||
|
@ -176,7 +176,7 @@ public class TestTopScreenModel {
|
|||
RecordFilter.parse("TABLE==table1", fields, true),
|
||||
RecordFilter.parse("TABLE==table2", fields, true));
|
||||
|
||||
topScreenModel.switchMode(Mode.TABLE, initialFilters, false);
|
||||
topScreenModel.switchMode(Mode.TABLE, false, initialFilters);
|
||||
|
||||
assertThat(topScreenModel.getFilters().size(), is(initialFilters.size()));
|
||||
for (int i = 0; i < topScreenModel.getFilters().size(); i++) {
|
||||
|
@ -186,13 +186,13 @@ public class TestTopScreenModel {
|
|||
|
||||
// Test when keepSortFieldAndSortOrderIfPossible is true
|
||||
topScreenModel.setSortFieldAndFields(Field.NAMESPACE, fields);
|
||||
topScreenModel.switchMode(Mode.NAMESPACE, null, true);
|
||||
topScreenModel.switchMode(Mode.NAMESPACE, true, null);
|
||||
assertThat(topScreenModel.getCurrentSortField(), is(Field.NAMESPACE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDrillDown() {
|
||||
topScreenModel.switchMode(Mode.TABLE, null, false);
|
||||
topScreenModel.switchMode(Mode.TABLE, false, null);
|
||||
topScreenModel.setSortFieldAndFields(Field.NAMESPACE, fields);
|
||||
topScreenModel.refreshMetricsData();
|
||||
|
||||
|
|
|
@ -95,7 +95,8 @@ public class TestTopScreenPresenter {
|
|||
when(topScreenModel.getRecords()).thenReturn(TEST_RECORDS);
|
||||
when(topScreenModel.getSummary()).thenReturn(TEST_SUMMARY);
|
||||
|
||||
topScreenPresenter = new TopScreenPresenter(topScreenView, 3000, topScreenModel);
|
||||
topScreenPresenter = new TopScreenPresenter(topScreenView, 3000, topScreenModel,
|
||||
null, Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue