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