diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/handler/TestEnableTableHandler.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/handler/TestEnableTableHandler.java index 5266975eb90..87b6e9b87a0 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/handler/TestEnableTableHandler.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/handler/TestEnableTableHandler.java @@ -18,7 +18,8 @@ */ package org.apache.hadoop.hbase.master.handler; -import java.util.Collections; +import java.io.IOException; +import java.util.concurrent.CountDownLatch; import java.util.List; import org.apache.commons.logging.Log; @@ -32,11 +33,18 @@ import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.MetaTableAccessor; import org.apache.hadoop.hbase.MiniHBaseCluster; import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.Delete; import org.apache.hadoop.hbase.client.HBaseAdmin; +import org.apache.hadoop.hbase.client.Result; +import org.apache.hadoop.hbase.client.ResultScanner; +import org.apache.hadoop.hbase.client.Table; +import org.apache.hadoop.hbase.coprocessor.BaseMasterObserver; +import org.apache.hadoop.hbase.coprocessor.CoprocessorHost; +import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment; +import org.apache.hadoop.hbase.coprocessor.ObserverContext; import org.apache.hadoop.hbase.master.HMaster; import org.apache.hadoop.hbase.testclassification.MediumTests; import org.apache.hadoop.hbase.util.Bytes; -import org.apache.hadoop.hbase.util.FSTableDescriptors; import org.apache.hadoop.hbase.util.JVMClusterUtil; import org.junit.After; import org.junit.Before; @@ -45,13 +53,7 @@ import org.junit.experimental.categories.Category; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; - -import java.io.IOException; -import org.apache.hadoop.hbase.client.Delete; -import org.apache.hadoop.hbase.client.Result; -import org.apache.hadoop.hbase.client.ResultScanner; -import org.apache.hadoop.hbase.client.Scan; -import org.apache.hadoop.hbase.client.Table; +import static org.junit.Assert.fail; @Category({ MediumTests.class }) public class TestEnableTableHandler { @@ -62,6 +64,8 @@ public class TestEnableTableHandler { @Before public void setUp() throws Exception { TEST_UTIL.getConfiguration().set("hbase.balancer.tablesOnMaster", "hbase:meta"); + TEST_UTIL.getConfiguration().set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY, + MasterSyncObserver.class.getName()); TEST_UTIL.startMiniCluster(1); } @@ -122,7 +126,12 @@ public class TestEnableTableHandler { final HBaseAdmin admin = TEST_UTIL.getHBaseAdmin(); final HTableDescriptor desc = new HTableDescriptor(tableName); desc.addFamily(new HColumnDescriptor(FAMILYNAME)); - admin.createTable(desc, HBaseTestingUtility.KEYS_FOR_HBA_CREATE_TABLE); + try { + createTable(TEST_UTIL, desc, HBaseTestingUtility.KEYS_FOR_HBA_CREATE_TABLE); + } catch (Exception e) { + e.printStackTrace(); + fail("Got an exception while creating " + tableName); + } // Now I have a nice table, mangle it by removing the HConstants.REGIONINFO_QUALIFIER_STR // content from a few of the rows. try (Table metaTable = TEST_UTIL.getConnection().getTable(TableName.META_TABLE_NAME)) { @@ -139,8 +148,13 @@ public class TestEnableTableHandler { } admin.disableTable(tableName); TEST_UTIL.waitTableDisabled(tableName.getName()); - // Presume this synchronous all is. - admin.deleteTable(tableName); + // Rely on the coprocessor based latch to make the operation synchronous. + try { + deleteTable(TEST_UTIL, tableName); + } catch (Exception e) { + e.printStackTrace(); + fail("Got an exception while deleting " + tableName); + } int rowCount = 0; try (ResultScanner scanner = metaTable.getScanner(MetaTableAccessor.getScanForTableName(tableName))) { @@ -152,4 +166,75 @@ public class TestEnableTableHandler { assertEquals(0, rowCount); } } + + public static class MasterSyncObserver extends BaseMasterObserver { + volatile CountDownLatch tableCreationLatch = null; + volatile CountDownLatch tableDeletionLatch = null; + + @Override + public void postCreateTableHandler(final ObserverContext ctx, + HTableDescriptor desc, HRegionInfo[] regions) throws IOException { + // the AccessController test, some times calls only and directly the postCreateTableHandler() + if (tableCreationLatch != null) { + tableCreationLatch.countDown(); + } + } + + @Override + public void postDeleteTableHandler(final ObserverContext ctx, + TableName tableName) + throws IOException { + // the AccessController test, some times calls only and directly the postDeleteTableHandler() + if (tableDeletionLatch != null) { + tableDeletionLatch.countDown(); + } + } + } + + public static void createTable(HBaseTestingUtility testUtil, HTableDescriptor htd, + byte [][] splitKeys) + throws Exception { + createTable(testUtil, testUtil.getHBaseAdmin(), htd, splitKeys); + } + + public static void createTable(HBaseTestingUtility testUtil, HBaseAdmin admin, + HTableDescriptor htd, byte [][] splitKeys) + throws Exception { + // NOTE: We need a latch because admin is not sync, + // so the postOp coprocessor method may be called after the admin operation returned. + MasterSyncObserver observer = (MasterSyncObserver)testUtil.getHBaseCluster().getMaster() + .getMasterCoprocessorHost().findCoprocessor(MasterSyncObserver.class.getName()); + observer.tableCreationLatch = new CountDownLatch(1); + if (splitKeys != null) { + admin.createTable(htd, splitKeys); + } else { + admin.createTable(htd); + } + observer.tableCreationLatch.await(); + observer.tableCreationLatch = null; + testUtil.waitUntilAllRegionsAssigned(htd.getTableName()); + } + + public static void deleteTable(HBaseTestingUtility testUtil, TableName tableName) + throws Exception { + deleteTable(testUtil, testUtil.getHBaseAdmin(), tableName); + } + + public static void deleteTable(HBaseTestingUtility testUtil, HBaseAdmin admin, + TableName tableName) + throws Exception { + // NOTE: We need a latch because admin is not sync, + // so the postOp coprocessor method may be called after the admin operation returned. + MasterSyncObserver observer = (MasterSyncObserver)testUtil.getHBaseCluster().getMaster() + .getMasterCoprocessorHost().findCoprocessor(MasterSyncObserver.class.getName()); + observer.tableDeletionLatch = new CountDownLatch(1); + try { + admin.disableTable(tableName); + } catch (Exception e) { + LOG.debug("Table: " + tableName + " already disabled, so just deleting it."); + } + admin.deleteTable(tableName); + observer.tableDeletionLatch.await(); + observer.tableDeletionLatch = null; + } }