1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.hbtop.screen.top;
19
20 import edu.umd.cs.findbugs.annotations.Nullable;
21 import java.util.ArrayList;
22 import java.util.List;
23
24 import org.apache.commons.lang3.StringUtils;
25 import org.apache.hadoop.hbase.classification.InterfaceAudience;
26 import org.apache.hadoop.hbase.client.Admin;
27 import org.apache.hadoop.hbase.hbtop.Record;
28 import org.apache.hadoop.hbase.hbtop.RecordFilter;
29 import org.apache.hadoop.hbase.hbtop.field.Field;
30 import org.apache.hadoop.hbase.hbtop.mode.Mode;
31 import org.apache.hadoop.hbase.hbtop.screen.AbstractScreenView;
32 import org.apache.hadoop.hbase.hbtop.screen.Screen;
33 import org.apache.hadoop.hbase.hbtop.screen.ScreenView;
34 import org.apache.hadoop.hbase.hbtop.terminal.KeyPress;
35 import org.apache.hadoop.hbase.hbtop.terminal.Terminal;
36 import org.apache.hadoop.hbase.hbtop.terminal.TerminalPrinter;
37 import org.apache.hadoop.hbase.hbtop.terminal.TerminalSize;
38
39
40
41
42
43
44
45 @InterfaceAudience.Private
46 public class TopScreenView extends AbstractScreenView {
47
48 private static final int SUMMARY_START_ROW = 0;
49 private static final int SUMMARY_ROW_NUM = 7;
50 private static final int MESSAGE_ROW = 7;
51 private static final int RECORD_HEADER_ROW = 8;
52 private static final int RECORD_START_ROW = 9;
53
54 private final TopScreenPresenter topScreenPresenter;
55 private Integer pageSize;
56
57 public TopScreenView(Screen screen, Terminal terminal, long initialRefreshDelay, Admin admin,
58 Mode initialMode, @Nullable List<Field> initialFields, @Nullable Field initialSortField,
59 @Nullable Boolean initialAscendingSort, @Nullable List<RecordFilter> initialFilters,
60 long numberOfIterations) {
61 super(screen, terminal);
62 this.topScreenPresenter = new TopScreenPresenter(this, initialRefreshDelay,
63 new TopScreenModel(admin, initialMode, initialFields, initialSortField,
64 initialAscendingSort, initialFilters), initialFields, numberOfIterations);
65 }
66
67 @Override
68 public void init() {
69 topScreenPresenter.init();
70 long delay = topScreenPresenter.refresh(true);
71 setTimer(delay);
72 }
73
74 @Nullable
75 @Override
76 public ScreenView handleTimer() {
77 long delay = topScreenPresenter.refresh(false);
78 setTimer(delay);
79 return topScreenPresenter.isIterationFinished() ? null : this;
80 }
81
82 @Nullable
83 @Override
84 public ScreenView handleKeyPress(KeyPress keyPress) {
85 switch (keyPress.getType()) {
86 case Enter:
87 topScreenPresenter.refresh(true);
88 return topScreenPresenter.isIterationFinished() ? null : this;
89
90 case ArrowUp:
91 topScreenPresenter.arrowUp();
92 return topScreenPresenter.isIterationFinished() ? null : this;
93
94 case ArrowDown:
95 topScreenPresenter.arrowDown();
96 return topScreenPresenter.isIterationFinished() ? null : this;
97
98 case ArrowLeft:
99 topScreenPresenter.arrowLeft();
100 return topScreenPresenter.isIterationFinished() ? null : this;
101
102 case ArrowRight:
103 topScreenPresenter.arrowRight();
104 return topScreenPresenter.isIterationFinished() ? null : this;
105
106 case PageUp:
107 topScreenPresenter.pageUp();
108 return topScreenPresenter.isIterationFinished() ? null : this;
109
110 case PageDown:
111 topScreenPresenter.pageDown();
112 return topScreenPresenter.isIterationFinished() ? null : this;
113
114 case Home:
115 topScreenPresenter.home();
116 return topScreenPresenter.isIterationFinished() ? null : this;
117
118 case End:
119 topScreenPresenter.end();
120 return topScreenPresenter.isIterationFinished() ? null : this;
121
122 case Escape:
123 return null;
124
125 default:
126
127 break;
128 }
129
130 if (keyPress.getType() != KeyPress.Type.Character) {
131 return unknownCommandMessage();
132 }
133
134 assert keyPress.getCharacter() != null;
135 switch (keyPress.getCharacter()) {
136 case 'R':
137 topScreenPresenter.switchSortOrder();
138 break;
139
140 case 'f':
141 cancelTimer();
142 return topScreenPresenter.transitionToFieldScreen(getScreen(), getTerminal());
143
144 case 'm':
145 cancelTimer();
146 return topScreenPresenter.transitionToModeScreen(getScreen(), getTerminal());
147
148 case 'h':
149 cancelTimer();
150 return topScreenPresenter.transitionToHelpScreen(getScreen(), getTerminal());
151
152 case 'd':
153 cancelTimer();
154 return topScreenPresenter.goToInputModeForRefreshDelay(getScreen(), getTerminal(),
155 MESSAGE_ROW);
156
157 case 'o':
158 cancelTimer();
159 if (keyPress.isCtrl()) {
160 return topScreenPresenter.goToFilterDisplayMode(getScreen(), getTerminal(), MESSAGE_ROW);
161 }
162 return topScreenPresenter.goToInputModeForFilter(getScreen(), getTerminal(), MESSAGE_ROW,
163 true);
164
165 case 'O':
166 cancelTimer();
167 return topScreenPresenter.goToInputModeForFilter(getScreen(), getTerminal(), MESSAGE_ROW,
168 false);
169
170 case '=':
171 topScreenPresenter.clearFilters();
172 break;
173
174 case 'X':
175 topScreenPresenter.adjustFieldLength();
176 break;
177
178 case 'i':
179 topScreenPresenter.drillDown();
180 break;
181
182 case 'q':
183 return null;
184
185 default:
186 return unknownCommandMessage();
187 }
188 return this;
189 }
190
191 @Nullable
192 @Override
193 public TerminalSize getTerminalSize() {
194 TerminalSize terminalSize = super.getTerminalSize();
195 if (terminalSize == null) {
196 return null;
197 }
198 updatePageSize(terminalSize);
199 return terminalSize;
200 }
201
202 @Nullable
203 @Override
204 public TerminalSize doResizeIfNecessary() {
205 TerminalSize terminalSize = super.doResizeIfNecessary();
206 if (terminalSize == null) {
207 return null;
208 }
209 updatePageSize(terminalSize);
210 return terminalSize;
211 }
212
213 private void updatePageSize(TerminalSize terminalSize) {
214 pageSize = terminalSize.getRows() - SUMMARY_ROW_NUM - 2;
215 if (pageSize < 0) {
216 pageSize = 0;
217 }
218 }
219
220 @Nullable
221 public Integer getPageSize() {
222 return pageSize;
223 }
224
225 public void showTopScreen(Summary summary, List<Header> headers, List<Record> records,
226 Record selectedRecord) {
227 showSummary(summary);
228 clearMessage();
229 showHeaders(headers);
230 showRecords(headers, records, selectedRecord);
231 }
232
233 private void showSummary(Summary summary) {
234 TerminalPrinter printer = getTerminalPrinter(SUMMARY_START_ROW);
235 printer.print(String.format("HBase hbtop - %s", summary.getCurrentTime())).endOfLine();
236 printer.print(String.format("Version: %s", summary.getVersion())).endOfLine();
237 printer.print(String.format("Cluster ID: %s", summary.getClusterId())).endOfLine();
238 printer.print("RegionServer(s): ")
239 .startBold().print(Integer.toString(summary.getServers())).stopBold()
240 .print(" total, ")
241 .startBold().print(Integer.toString(summary.getLiveServers())).stopBold()
242 .print(" live, ")
243 .startBold().print(Integer.toString(summary.getDeadServers())).stopBold()
244 .print(" dead").endOfLine();
245 printer.print("RegionCount: ")
246 .startBold().print(Integer.toString(summary.getRegionCount())).stopBold()
247 .print(" total, ")
248 .startBold().print(Integer.toString(summary.getRitCount())).stopBold()
249 .print(" rit").endOfLine();
250 printer.print("Average Cluster Load: ")
251 .startBold().print(String.format("%.2f", summary.getAverageLoad())).stopBold().endOfLine();
252 printer.print("Aggregate Request/s: ")
253 .startBold().print(Long.toString(summary.getAggregateRequestPerSecond())).stopBold()
254 .endOfLine();
255 }
256
257 private void showRecords(List<Header> headers, List<Record> records, Record selectedRecord) {
258 TerminalPrinter printer = getTerminalPrinter(RECORD_START_ROW);
259 int size;
260 if (pageSize != null) {
261 size = pageSize;
262 } else {
263 size = records.size();
264 }
265 List<String> buf = new ArrayList<>(headers.size());
266 for (int i = 0; i < size; i++) {
267 if(i < records.size()) {
268 Record record = records.get(i);
269 buf.clear();
270 for (Header header : headers) {
271 String value = "";
272 if (record.containsKey(header.getField())) {
273 value = record.get(header.getField()).asString();
274 }
275
276 buf.add(limitLineLength(String.format(header.format(), value), header.getLength()));
277 }
278
279 String recordString = StringUtils.join(buf, " ");
280 if (!recordString.isEmpty()) {
281 recordString += " ";
282 }
283
284 if (record == selectedRecord) {
285 printer.startHighlight().print(recordString).stopHighlight().endOfLine();
286 } else {
287 printer.print(recordString).endOfLine();
288 }
289 } else {
290 printer.endOfLine();
291 }
292 }
293 }
294
295 private void showHeaders(List<Header> headers) {
296 List<String> headerStrings = new ArrayList<>();
297 for (Header header : headers) {
298 headerStrings.add(String.format(header.format(), header.getField().getHeader()));
299 }
300 String header = StringUtils.join(headerStrings, " ");
301
302 if (!header.isEmpty()) {
303 header += " ";
304 }
305
306 getTerminalPrinter(RECORD_HEADER_ROW).startHighlight().print(header).stopHighlight()
307 .endOfLine();
308 }
309
310 private String limitLineLength(String line, int length) {
311 if (line.length() > length) {
312 return line.substring(0, length - 1) + "+";
313 }
314 return line;
315 }
316
317 private void clearMessage() {
318 getTerminalPrinter(MESSAGE_ROW).print("").endOfLine();
319 }
320
321 private ScreenView unknownCommandMessage() {
322 cancelTimer();
323 return topScreenPresenter.goToMessageMode(getScreen(), getTerminal(), MESSAGE_ROW,
324 "Unknown command - try 'h' for help");
325 }
326 }