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