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.thrift;
019
020import static org.apache.hadoop.hbase.thrift.Constants.INFOPORT_OPTION;
021
022import java.io.IOException;
023import java.util.ArrayList;
024import java.util.List;
025import org.apache.hadoop.conf.Configuration;
026import org.apache.hadoop.hbase.HBaseTestingUtility;
027import org.apache.hadoop.hbase.thrift.ThriftMetrics.ThriftServerType;
028import org.slf4j.Logger;
029import org.slf4j.LoggerFactory;
030
031import org.apache.hbase.thirdparty.com.google.common.base.Joiner;
032
033public class HBaseThriftTestingUtility {
034
035  private static final Logger LOG = LoggerFactory.getLogger(HBaseThriftTestingUtility.class);
036  private Thread thriftServerThread;
037  private volatile Exception thriftServerException;
038  private ThriftServer thriftServer;
039  private int port;
040
041  public int getServerPort() {
042    return port;
043  }
044
045  /**
046   * start thrift server
047   * @param conf configuration
048   * @param type the type of thrift server
049   * @throws Exception When starting the thrift server fails.
050   */
051  public void startThriftServer(Configuration conf, ThriftServerType type) throws Exception {
052    List<String> args = new ArrayList<>();
053    port = HBaseTestingUtility.randomFreePort();
054    args.add("-" + Constants.PORT_OPTION);
055    args.add(String.valueOf(port));
056    args.add("-" + INFOPORT_OPTION);
057    int infoPort = HBaseTestingUtility.randomFreePort();
058    args.add(String.valueOf(infoPort));
059
060    LOG.info("Starting Thrift Server {} on port: {} ", type, port);
061    thriftServer = createThriftServer(conf, type);
062    startThriftServerThread(args.toArray(new String[args.size()]));
063    // wait up to 10s for the server to start
064    waitForThriftServer();
065    LOG.info("Started Thrift Server {} on port {}", type, port);
066  }
067
068  private void startThriftServerThread(final String[] args) {
069    LOG.info("Starting HBase Thrift server with command line: " + Joiner.on(" ").join(args));
070
071    thriftServerException = null;
072    thriftServerThread = new Thread(() -> {
073      try {
074        thriftServer.run(args);
075      } catch (Exception e) {
076        thriftServerException = e;
077      }
078    });
079    thriftServerThread.setName(ThriftServer.class.getSimpleName());
080    thriftServerThread.start();
081  }
082
083  /**
084   * create a new thrift server
085   * @param conf configuration
086   * @param type the type of thrift server
087   * @return the instance of ThriftServer
088   */
089  private ThriftServer createThriftServer(Configuration conf, ThriftServerType type) {
090    switch (type) {
091      case ONE:
092        return new ThriftServer(conf);
093      case TWO:
094        return new org.apache.hadoop.hbase.thrift2.ThriftServer(conf);
095      default:
096        throw new IllegalArgumentException("Unknown type: " + type);
097    }
098  }
099
100  private void waitForThriftServer() throws Exception {
101    boolean isServing = false;
102    int i = 0;
103    while (i++ < 100) {
104      if (thriftServer.tserver == null) {
105        Thread.sleep(100);
106      } else {
107        isServing = true;
108        break;
109      }
110    }
111
112    if (!isServing) {
113      if (thriftServer != null) {
114        thriftServer.stop();
115      }
116      throw new IOException("Failed to start thrift server ");
117    }
118  }
119
120  public void stopThriftServer() throws Exception {
121    LOG.debug("Stopping Thrift Server");
122    thriftServer.stop();
123    thriftServerThread.join();
124    if (thriftServerException != null) {
125      LOG.error("HBase Thrift server threw an exception ", thriftServerException);
126      throw new Exception(thriftServerException);
127    }
128  }
129}