HBASE-13394 Failed to recreate a table when quota is enabled
This commit is contained in:
parent
79db629323
commit
b96952beef
|
@ -1344,8 +1344,7 @@ public class HMaster extends HRegionServer implements MasterServices, Server {
|
||||||
HRegionInfo[] newRegions = ModifyRegionUtils.createHRegionInfos(hTableDescriptor, splitKeys);
|
HRegionInfo[] newRegions = ModifyRegionUtils.createHRegionInfos(hTableDescriptor, splitKeys);
|
||||||
checkInitialized();
|
checkInitialized();
|
||||||
sanityCheckTableDescriptor(hTableDescriptor);
|
sanityCheckTableDescriptor(hTableDescriptor);
|
||||||
this.quotaManager.checkNamespaceTableAndRegionQuota(hTableDescriptor.getTableName(),
|
|
||||||
newRegions.length);
|
|
||||||
if (cpHost != null) {
|
if (cpHost != null) {
|
||||||
cpHost.preCreateTable(hTableDescriptor, newRegions);
|
cpHost.preCreateTable(hTableDescriptor, newRegions);
|
||||||
}
|
}
|
||||||
|
|
|
@ -284,6 +284,11 @@ public class CreateTableProcedure
|
||||||
|
|
||||||
private void preCreate(final MasterProcedureEnv env)
|
private void preCreate(final MasterProcedureEnv env)
|
||||||
throws IOException, InterruptedException {
|
throws IOException, InterruptedException {
|
||||||
|
if (!getTableName().isSystemTable()) {
|
||||||
|
ProcedureSyncWait.getMasterQuotaManager(env)
|
||||||
|
.checkNamespaceTableAndRegionQuota(getTableName(), newRegions.size());
|
||||||
|
}
|
||||||
|
|
||||||
final MasterCoprocessorHost cpHost = env.getMasterCoprocessorHost();
|
final MasterCoprocessorHost cpHost = env.getMasterCoprocessorHost();
|
||||||
if (cpHost != null) {
|
if (cpHost != null) {
|
||||||
final HRegionInfo[] regions = newRegions == null ? null :
|
final HRegionInfo[] regions = newRegions == null ? null :
|
||||||
|
|
|
@ -53,7 +53,6 @@ import org.apache.hadoop.hbase.protobuf.generated.MasterProcedureProtos;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.MasterProcedureProtos.DeleteTableState;
|
import org.apache.hadoop.hbase.protobuf.generated.MasterProcedureProtos.DeleteTableState;
|
||||||
import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
|
import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
|
||||||
import org.apache.hadoop.hbase.procedure2.StateMachineProcedure;
|
import org.apache.hadoop.hbase.procedure2.StateMachineProcedure;
|
||||||
import org.apache.hadoop.hbase.quotas.MasterQuotaManager;
|
|
||||||
import org.apache.hadoop.hbase.util.FSUtils;
|
import org.apache.hadoop.hbase.util.FSUtils;
|
||||||
import org.apache.hadoop.security.UserGroupInformation;
|
import org.apache.hadoop.security.UserGroupInformation;
|
||||||
|
|
||||||
|
@ -406,17 +405,6 @@ public class DeleteTableProcedure
|
||||||
|
|
||||||
protected static void deleteTableStates(final MasterProcedureEnv env, final TableName tableName)
|
protected static void deleteTableStates(final MasterProcedureEnv env, final TableName tableName)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
getMasterQuotaManager(env).removeTableFromNamespaceQuota(tableName);
|
ProcedureSyncWait.getMasterQuotaManager(env).removeTableFromNamespaceQuota(tableName);
|
||||||
}
|
|
||||||
|
|
||||||
private static MasterQuotaManager getMasterQuotaManager(final MasterProcedureEnv env)
|
|
||||||
throws IOException {
|
|
||||||
return ProcedureSyncWait.waitFor(env, "quota manager to be available",
|
|
||||||
new ProcedureSyncWait.Predicate<MasterQuotaManager>() {
|
|
||||||
@Override
|
|
||||||
public MasterQuotaManager evaluate() throws IOException {
|
|
||||||
return env.getMasterServices().getMasterQuotaManager();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ import org.apache.hadoop.hbase.master.ServerManager;
|
||||||
import org.apache.hadoop.hbase.procedure2.Procedure;
|
import org.apache.hadoop.hbase.procedure2.Procedure;
|
||||||
import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
|
import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
|
||||||
import org.apache.hadoop.hbase.procedure2.ProcedureResult;
|
import org.apache.hadoop.hbase.procedure2.ProcedureResult;
|
||||||
|
import org.apache.hadoop.hbase.quotas.MasterQuotaManager;
|
||||||
import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
|
import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
|
||||||
import org.apache.hadoop.hbase.util.Threads;
|
import org.apache.hadoop.hbase.util.Threads;
|
||||||
import org.apache.hadoop.hbase.zookeeper.MetaTableLocator;
|
import org.apache.hadoop.hbase.zookeeper.MetaTableLocator;
|
||||||
|
@ -176,4 +177,15 @@ public final class ProcedureSyncWait {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static MasterQuotaManager getMasterQuotaManager(final MasterProcedureEnv env)
|
||||||
|
throws IOException {
|
||||||
|
return ProcedureSyncWait.waitFor(env, "quota manager to be available",
|
||||||
|
new ProcedureSyncWait.Predicate<MasterQuotaManager>() {
|
||||||
|
@Override
|
||||||
|
public MasterQuotaManager evaluate() throws IOException {
|
||||||
|
return env.getMasterServices().getMasterQuotaManager();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -41,6 +42,7 @@ import org.apache.hadoop.hbase.CoprocessorEnvironment;
|
||||||
import org.apache.hadoop.hbase.DoNotRetryIOException;
|
import org.apache.hadoop.hbase.DoNotRetryIOException;
|
||||||
import org.apache.hadoop.hbase.HBaseTestingUtility;
|
import org.apache.hadoop.hbase.HBaseTestingUtility;
|
||||||
import org.apache.hadoop.hbase.HColumnDescriptor;
|
import org.apache.hadoop.hbase.HColumnDescriptor;
|
||||||
|
import org.apache.hadoop.hbase.HConstants;
|
||||||
import org.apache.hadoop.hbase.HRegionInfo;
|
import org.apache.hadoop.hbase.HRegionInfo;
|
||||||
import org.apache.hadoop.hbase.HTableDescriptor;
|
import org.apache.hadoop.hbase.HTableDescriptor;
|
||||||
import org.apache.hadoop.hbase.MiniHBaseCluster;
|
import org.apache.hadoop.hbase.MiniHBaseCluster;
|
||||||
|
@ -100,6 +102,7 @@ public class TestNamespaceAuditor {
|
||||||
UTIL.getConfiguration().set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY,
|
UTIL.getConfiguration().set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY,
|
||||||
MasterSyncObserver.class.getName());
|
MasterSyncObserver.class.getName());
|
||||||
Configuration conf = UTIL.getConfiguration();
|
Configuration conf = UTIL.getConfiguration();
|
||||||
|
conf.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 5);
|
||||||
conf.setBoolean(QuotaUtil.QUOTA_CONF_KEY, true);
|
conf.setBoolean(QuotaUtil.QUOTA_CONF_KEY, true);
|
||||||
conf.setClass("hbase.coprocessor.regionserver.classes", CPRegionServerObserver.class,
|
conf.setClass("hbase.coprocessor.regionserver.classes", CPRegionServerObserver.class,
|
||||||
RegionServerObserver.class);
|
RegionServerObserver.class);
|
||||||
|
@ -470,6 +473,58 @@ public class TestNamespaceAuditor {
|
||||||
htable.close();
|
htable.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a table and make sure that the table creation fails after adding this table entry into
|
||||||
|
* namespace quota cache. Now correct the failure and recreate the table with same name.
|
||||||
|
* HBASE-13394
|
||||||
|
*/
|
||||||
|
@Test(timeout = 180000)
|
||||||
|
public void testRecreateTableWithSameNameAfterFirstTimeFailure() throws Exception {
|
||||||
|
String nsp1 = prefix + "_testRecreateTable";
|
||||||
|
NamespaceDescriptor nspDesc =
|
||||||
|
NamespaceDescriptor.create(nsp1)
|
||||||
|
.addConfiguration(TableNamespaceManager.KEY_MAX_REGIONS, "20")
|
||||||
|
.addConfiguration(TableNamespaceManager.KEY_MAX_TABLES, "1").build();
|
||||||
|
ADMIN.createNamespace(nspDesc);
|
||||||
|
final TableName tableOne = TableName.valueOf(nsp1 + TableName.NAMESPACE_DELIM + "table1");
|
||||||
|
byte[] columnFamily = Bytes.toBytes("info");
|
||||||
|
HTableDescriptor tableDescOne = new HTableDescriptor(tableOne);
|
||||||
|
tableDescOne.addFamily(new HColumnDescriptor(columnFamily));
|
||||||
|
MasterSyncObserver.throwExceptionInPreCreateTableHandler = true;
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
ADMIN.createTable(tableDescOne);
|
||||||
|
fail("Table " + tableOne.toString() + "creation should fail.");
|
||||||
|
} catch (Exception exp) {
|
||||||
|
LOG.error(exp);
|
||||||
|
}
|
||||||
|
assertFalse(ADMIN.tableExists(tableOne));
|
||||||
|
|
||||||
|
NamespaceTableAndRegionInfo nstate = getNamespaceState(nsp1);
|
||||||
|
assertEquals("First table creation failed in namespace so number of tables in namespace "
|
||||||
|
+ "should be 0.", 0, nstate.getTables().size());
|
||||||
|
|
||||||
|
MasterSyncObserver.throwExceptionInPreCreateTableHandler = false;
|
||||||
|
try {
|
||||||
|
ADMIN.createTable(tableDescOne);
|
||||||
|
} catch (Exception e) {
|
||||||
|
fail("Table " + tableOne.toString() + "creation should succeed.");
|
||||||
|
LOG.error(e);
|
||||||
|
}
|
||||||
|
assertTrue(ADMIN.tableExists(tableOne));
|
||||||
|
nstate = getNamespaceState(nsp1);
|
||||||
|
assertEquals("First table was created successfully so table size in namespace should "
|
||||||
|
+ "be one now.", 1, nstate.getTables().size());
|
||||||
|
} finally {
|
||||||
|
MasterSyncObserver.throwExceptionInPreCreateTableHandler = false;
|
||||||
|
if (ADMIN.tableExists(tableOne)) {
|
||||||
|
ADMIN.disableTable(tableOne);
|
||||||
|
deleteTable(tableOne);
|
||||||
|
}
|
||||||
|
ADMIN.deleteNamespace(nsp1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private NamespaceTableAndRegionInfo getNamespaceState(String namespace) throws KeeperException,
|
private NamespaceTableAndRegionInfo getNamespaceState(String namespace) throws KeeperException,
|
||||||
IOException {
|
IOException {
|
||||||
return getQuotaManager().getState(namespace);
|
return getQuotaManager().getState(namespace);
|
||||||
|
@ -569,6 +624,7 @@ public class TestNamespaceAuditor {
|
||||||
|
|
||||||
public static class MasterSyncObserver extends BaseMasterObserver {
|
public static class MasterSyncObserver extends BaseMasterObserver {
|
||||||
volatile CountDownLatch tableDeletionLatch;
|
volatile CountDownLatch tableDeletionLatch;
|
||||||
|
static boolean throwExceptionInPreCreateTableHandler;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void preDeleteTable(ObserverContext<MasterCoprocessorEnvironment> ctx,
|
public void preDeleteTable(ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||||
|
@ -582,6 +638,14 @@ public class TestNamespaceAuditor {
|
||||||
throws IOException {
|
throws IOException {
|
||||||
tableDeletionLatch.countDown();
|
tableDeletionLatch.countDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void preCreateTableHandler(ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||||
|
HTableDescriptor desc, HRegionInfo[] regions) throws IOException {
|
||||||
|
if (throwExceptionInPreCreateTableHandler) {
|
||||||
|
throw new IOException("Throw exception as it is demanded.");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteTable(final TableName tableName) throws Exception {
|
private void deleteTable(final TableName tableName) throws Exception {
|
||||||
|
|
Loading…
Reference in New Issue