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.util;
019
020import java.io.IOException;
021import org.apache.hadoop.hbase.HBaseTestingUtil;
022import org.apache.hadoop.hbase.HConstants;
023import org.apache.hadoop.hbase.TableName;
024import org.apache.hadoop.hbase.client.Connection;
025import org.apache.hadoop.hbase.client.ConnectionFactory;
026import org.apache.hadoop.hbase.client.Result;
027import org.apache.hadoop.hbase.client.ResultScanner;
028import org.apache.hadoop.hbase.client.Scan;
029import org.apache.hadoop.hbase.client.Table;
030import org.apache.hadoop.hbase.io.compress.Compression;
031import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding;
032import org.apache.hadoop.hbase.util.test.LoadTestDataGenerator;
033import org.slf4j.Logger;
034import org.slf4j.LoggerFactory;
035
036import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine;
037
038/**
039 * A command-line tool that spins up a local process-based cluster, loads some data, restarts the
040 * regionserver holding hbase:meta, and verifies that the cluster recovers.
041 */
042public class RestartMetaTest extends AbstractHBaseTool {
043
044  private static final Logger LOG = LoggerFactory.getLogger(RestartMetaTest.class);
045
046  /** Column family used by the test */
047  private static byte[] DEFAULT_COLUMN_FAMILY = Bytes.toBytes("test_cf");
048  /** Column families used by the test */
049  private static final byte[][] DEFAULT_COLUMN_FAMILIES = { DEFAULT_COLUMN_FAMILY };
050
051  /** The number of region servers used if not specified */
052  private static final int DEFAULT_NUM_RS = 2;
053
054  /** Table name for the test */
055  private static TableName TABLE_NAME = TableName.valueOf("load_test");
056
057  /** The number of seconds to sleep after loading the data */
058  private static final int SLEEP_SEC_AFTER_DATA_LOAD = 5;
059
060  /** The actual number of region servers */
061  private int numRegionServers;
062
063  private static final String OPT_NUM_RS = "num_rs";
064
065  private static final int NUM_DATANODES = 3;
066
067  /** Loads data into the table using the multi-threaded writer. */
068  private void loadData() throws IOException {
069    long startKey = 0;
070    long endKey = 100000;
071    int minColsPerKey = 5;
072    int maxColsPerKey = 15;
073    int minColDataSize = 256;
074    int maxColDataSize = 256 * 3;
075    int numThreads = 10;
076
077    // print out the arguments
078    System.out.printf("Key range %d .. %d\n", startKey, endKey);
079    System.out.printf("Number of Columns/Key: %d..%d\n", minColsPerKey, maxColsPerKey);
080    System.out.printf("Data Size/Column: %d..%d bytes\n", minColDataSize, maxColDataSize);
081    System.out.printf("Client Threads: %d\n", numThreads);
082
083    // start the writers
084    LoadTestDataGenerator dataGen = new MultiThreadedAction.DefaultDataGenerator(minColDataSize,
085      maxColDataSize, minColsPerKey, maxColsPerKey, DEFAULT_COLUMN_FAMILY);
086    MultiThreadedWriter writer = new MultiThreadedWriter(dataGen, conf, TABLE_NAME);
087    writer.setMultiPut(true);
088    writer.start(startKey, endKey, numThreads);
089    System.out.printf("Started loading data...");
090    writer.waitForFinish();
091    System.out.printf("Finished loading data...");
092  }
093
094  @Override
095  protected int doWork() throws Exception {
096    ProcessBasedLocalHBaseCluster hbaseCluster =
097      new ProcessBasedLocalHBaseCluster(conf, NUM_DATANODES, numRegionServers);
098    hbaseCluster.startMiniDFS();
099
100    // start the process based HBase cluster
101    hbaseCluster.startHBase();
102
103    // create tables if needed
104    LoadTestUtil.createPreSplitLoadTestTable(conf, TABLE_NAME, DEFAULT_COLUMN_FAMILY,
105      Compression.Algorithm.NONE, DataBlockEncoding.NONE);
106
107    LOG.debug("Loading data....\n\n");
108    loadData();
109
110    LOG.debug("Sleeping for " + SLEEP_SEC_AFTER_DATA_LOAD + " seconds....\n\n");
111    Threads.sleep(5 * SLEEP_SEC_AFTER_DATA_LOAD);
112
113    Connection connection = ConnectionFactory.createConnection(conf);
114
115    int metaRSPort = HBaseTestingUtil.getMetaRSPort(connection);
116
117    LOG.debug("Killing hbase:meta region server running on port " + metaRSPort);
118    hbaseCluster.killRegionServer(metaRSPort);
119    Threads.sleep(2000);
120
121    LOG.debug("Restarting region server running on port metaRSPort");
122    hbaseCluster.startRegionServer(metaRSPort);
123    Threads.sleep(2000);
124
125    LOG.debug("Trying to scan meta");
126
127    Table metaTable = connection.getTable(TableName.META_TABLE_NAME);
128    ResultScanner scanner = metaTable.getScanner(new Scan());
129    Result result;
130    while ((result = scanner.next()) != null) {
131      LOG.info("Region assignment from META: " + Bytes.toStringBinary(result.getRow()) + " => "
132        + Bytes.toStringBinary(
133          result.getFamilyMap(HConstants.CATALOG_FAMILY).get(HConstants.SERVER_QUALIFIER)));
134    }
135    metaTable.close();
136    connection.close();
137    return 0;
138  }
139
140  @Override
141  protected void addOptions() {
142    addOptWithArg(OPT_NUM_RS, "Number of Region Servers");
143    addOptWithArg(LoadTestUtil.OPT_DATA_BLOCK_ENCODING, LoadTestUtil.OPT_DATA_BLOCK_ENCODING_USAGE);
144  }
145
146  @Override
147  protected void processOptions(CommandLine cmd) {
148    numRegionServers =
149      Integer.parseInt(cmd.getOptionValue(OPT_NUM_RS, String.valueOf(DEFAULT_NUM_RS)));
150  }
151
152  public static void main(String[] args) {
153    new RestartMetaTest().doStaticMain(args);
154  }
155
156}