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 */ 018 019package org.apache.hadoop.hbase; 020 021import java.io.IOException; 022import java.util.concurrent.TimeUnit; 023 024import org.apache.hadoop.hbase.client.Admin; 025import org.apache.hadoop.hbase.testclassification.IntegrationTests; 026import org.apache.hadoop.hbase.util.RegionSplitter; 027import org.apache.hadoop.hbase.util.RegionSplitter.SplitAlgorithm; 028import org.junit.After; 029import org.junit.Before; 030import org.junit.ClassRule; 031import org.junit.Test; 032import org.junit.experimental.categories.Category; 033import org.junit.rules.TestRule; 034import org.junit.rules.Timeout; 035import org.slf4j.Logger; 036import org.slf4j.LoggerFactory; 037 038/** 039 * An integration test to detect regressions in HBASE-7220. Create 040 * a table with many regions and verify it completes within a 041 * reasonable amount of time. 042 * @see <a href="https://issues.apache.org/jira/browse/HBASE-7220">HBASE-7220</a> 043 */ 044@Category(IntegrationTests.class) 045public class IntegrationTestManyRegions { 046 private static final String CLASS_NAME 047 = IntegrationTestManyRegions.class.getSimpleName(); 048 049 protected static final Logger LOG 050 = LoggerFactory.getLogger(IntegrationTestManyRegions.class); 051 protected static final TableName TABLE_NAME = TableName.valueOf(CLASS_NAME); 052 protected static final String REGION_COUNT_KEY 053 = String.format("hbase.%s.regions", CLASS_NAME); 054 protected static final String REGIONSERVER_COUNT_KEY 055 = String.format("hbase.%s.regionServers", CLASS_NAME); 056 protected static final String TIMEOUT_MINUTES_KEY 057 = String.format("hbase.%s.timeoutMinutes", CLASS_NAME); 058 059 protected static final IntegrationTestingUtility UTIL 060 = new IntegrationTestingUtility(); 061 062 protected static final int DEFAULT_REGION_COUNT = 1000; 063 protected static final int REGION_COUNT = UTIL.getConfiguration() 064 .getInt(REGION_COUNT_KEY, DEFAULT_REGION_COUNT); 065 protected static final int DEFAULT_REGIONSERVER_COUNT = 1; 066 protected static final int REGION_SERVER_COUNT = UTIL.getConfiguration() 067 .getInt(REGIONSERVER_COUNT_KEY, DEFAULT_REGIONSERVER_COUNT); 068 // running on laptop, consistently takes about 2.5 minutes. 069 // A timeout of 5 minutes should be reasonably safe. 070 protected static final int DEFAULT_TIMEOUT_MINUTES = 5; 071 protected static final int TIMEOUT_MINUTES = UTIL.getConfiguration() 072 .getInt(TIMEOUT_MINUTES_KEY, DEFAULT_TIMEOUT_MINUTES); 073// This timeout is suitable since there is only single testcase in this test. 074 @ClassRule 075 public static final TestRule timeout = Timeout.builder() 076 .withTimeout(TIMEOUT_MINUTES, TimeUnit.MINUTES).withLookingForStuckThread(true) 077 .build(); 078 079 private Admin admin; 080 081 @Before 082 public void setUp() throws Exception { 083 LOG.info(String.format("Initializing cluster with %d region servers.", 084 REGION_SERVER_COUNT)); 085 UTIL.initializeCluster(REGION_SERVER_COUNT); 086 LOG.info("Cluster initialized"); 087 088 admin = UTIL.getAdmin(); 089 if (admin.tableExists(TABLE_NAME)) { 090 LOG.info(String.format("Deleting existing table %s.", TABLE_NAME)); 091 if (admin.isTableEnabled(TABLE_NAME)) admin.disableTable(TABLE_NAME); 092 admin.deleteTable(TABLE_NAME); 093 LOG.info(String.format("Existing table %s deleted.", TABLE_NAME)); 094 } 095 LOG.info("Cluster ready"); 096 } 097 098 @After 099 public void tearDown() throws IOException { 100 LOG.info("Cleaning up after test."); 101 if (admin.tableExists(TABLE_NAME)) { 102 if (admin.isTableEnabled(TABLE_NAME)) admin.disableTable(TABLE_NAME); 103 admin.deleteTable(TABLE_NAME); 104 } 105 LOG.info("Restoring cluster."); 106 UTIL.restoreCluster(); 107 LOG.info("Cluster restored."); 108 } 109 110 @Test 111 public void testCreateTableWithRegions() throws Exception { 112 HTableDescriptor desc = new HTableDescriptor(TABLE_NAME); 113 desc.addFamily(new HColumnDescriptor("cf")); 114 SplitAlgorithm algo = new RegionSplitter.HexStringSplit(); 115 byte[][] splits = algo.split(REGION_COUNT); 116 117 LOG.info(String.format("Creating table %s with %d splits.", TABLE_NAME, REGION_COUNT)); 118 long startTime = System.currentTimeMillis(); 119 try { 120 admin.createTable(desc, splits); 121 LOG.info(String.format("Pre-split table created successfully in %dms.", 122 (System.currentTimeMillis() - startTime))); 123 } catch (IOException e) { 124 LOG.error("Failed to create table", e); 125 } 126 } 127}