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.hbtop.screen;
019
020import edu.umd.cs.findbugs.annotations.Nullable;
021import java.io.Closeable;
022import java.io.IOException;
023import java.util.List;
024import java.util.concurrent.TimeUnit;
025import org.apache.hadoop.conf.Configuration;
026import org.apache.hadoop.hbase.client.Admin;
027import org.apache.hadoop.hbase.client.Connection;
028import org.apache.hadoop.hbase.client.ConnectionFactory;
029import org.apache.hadoop.hbase.hbtop.RecordFilter;
030import org.apache.hadoop.hbase.hbtop.field.Field;
031import org.apache.hadoop.hbase.hbtop.mode.Mode;
032import org.apache.hadoop.hbase.hbtop.screen.top.TopScreenView;
033import org.apache.hadoop.hbase.hbtop.terminal.KeyPress;
034import org.apache.hadoop.hbase.hbtop.terminal.Terminal;
035import org.apache.hadoop.hbase.hbtop.terminal.impl.TerminalImpl;
036import org.apache.hadoop.hbase.hbtop.terminal.impl.batch.BatchTerminal;
037import org.apache.yetus.audience.InterfaceAudience;
038import org.slf4j.Logger;
039import org.slf4j.LoggerFactory;
040
041
042/**
043 * This dispatches key presses and timers to the current {@link ScreenView}.
044 */
045@InterfaceAudience.Private
046public class Screen implements Closeable {
047  private static final Logger LOGGER = LoggerFactory.getLogger(Screen.class);
048  private static final long SLEEP_TIMEOUT_MILLISECONDS = 100;
049
050  private final Connection connection;
051  private final Admin admin;
052  private final Terminal terminal;
053
054  private ScreenView currentScreenView;
055  private Long timerTimestamp;
056
057  public Screen(Configuration conf, long initialRefreshDelay, Mode initialMode,
058    @Nullable List<Field> initialFields, @Nullable Field initialSortField,
059    @Nullable Boolean initialAscendingSort, @Nullable List<RecordFilter> initialFilters,
060    long numberOfIterations, boolean batchMode)
061    throws IOException {
062    connection = ConnectionFactory.createConnection(conf);
063    admin = connection.getAdmin();
064
065    // The first screen is the top screen
066    if (batchMode) {
067      terminal = new BatchTerminal();
068    } else {
069      terminal = new TerminalImpl("hbtop");
070    }
071    currentScreenView = new TopScreenView(this, terminal, initialRefreshDelay, admin,
072      initialMode, initialFields, initialSortField, initialAscendingSort, initialFilters,
073      numberOfIterations);
074  }
075
076  @Override
077  public void close() throws IOException {
078    try {
079      admin.close();
080    } finally {
081      try {
082        connection.close();
083      } finally {
084        terminal.close();
085      }
086    }
087  }
088
089  public void run() {
090    currentScreenView.init();
091    while (true) {
092      try {
093        KeyPress keyPress = terminal.pollKeyPress();
094
095        ScreenView nextScreenView;
096        if (keyPress != null) {
097          // Dispatch the key press to the current screen
098          nextScreenView = currentScreenView.handleKeyPress(keyPress);
099        } else {
100          if (timerTimestamp != null) {
101            long now = System.currentTimeMillis();
102            if (timerTimestamp <= now) {
103              // Dispatch the timer to the current screen
104              timerTimestamp = null;
105              nextScreenView = currentScreenView.handleTimer();
106            } else {
107              TimeUnit.MILLISECONDS
108                .sleep(Math.min(timerTimestamp - now, SLEEP_TIMEOUT_MILLISECONDS));
109              continue;
110            }
111          } else {
112            TimeUnit.MILLISECONDS.sleep(SLEEP_TIMEOUT_MILLISECONDS);
113            continue;
114          }
115        }
116
117        // If the next screen is null, then exit
118        if (nextScreenView == null) {
119          return;
120        }
121
122        // If the next screen is not the previous, then go to the next screen
123        if (nextScreenView != currentScreenView) {
124          currentScreenView = nextScreenView;
125          currentScreenView.init();
126        }
127      } catch (Exception e) {
128        LOGGER.error("Caught an exception", e);
129      }
130    }
131  }
132
133  public void setTimer(long delay) {
134    timerTimestamp = System.currentTimeMillis() + delay;
135  }
136
137  public void cancelTimer() {
138    timerTimestamp = null;
139  }
140}