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