下面列出了怎么用org.apache.hadoop.hbase.TableNotDisabledException的API类实例代码及写法,或者点击链接到github查看源代码。
@Test(expected = TableNotDisabledException.class)
public void testModifyRegionReplicasEnabledTable() throws Exception {
final TableName tableName = TableName.valueOf(name.getMethodName());
TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY).close();
// Modify region replication count
TableDescriptor htd = TableDescriptorBuilder.newBuilder(ADMIN.getDescriptor(tableName))
.setRegionReplication(3).build();
try {
// try to modify the region replication count without disabling the table
ADMIN.modifyTable(htd);
fail("Expected an exception");
} finally {
// Delete the table
ADMIN.disableTable(tableName);
ADMIN.deleteTable(tableName);
assertFalse(ADMIN.tableExists(tableName));
}
}
@Test
public void testRestoreSnapshotToEnabledTable() throws Exception {
final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
try {
UTIL.getAdmin().enableTable(snapshotTableName);
long procId = ProcedureTestingUtility.submitAndWait(
procExec,
new RestoreSnapshotProcedure(procExec.getEnvironment(), snapshotHTD, snapshot));
Procedure<?> result = procExec.getResult(procId);
assertTrue(result.isFailed());
LOG.debug("Restore snapshot failed with exception: " + result.getException());
assertTrue(
ProcedureTestingUtility.getExceptionCause(result) instanceof TableNotDisabledException);
} finally {
UTIL.getAdmin().disableTable(snapshotTableName);
}
}
@Test
public void testTruncateNotDisabledTable() throws Exception {
final TableName tableName = TableName.valueOf(name.getMethodName());
final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f");
// HBASE-20178 has us fail-fast, in the constructor, so add try/catch for this case.
// Keep old way of looking at procedure too.
Throwable cause = null;
try {
long procId = ProcedureTestingUtility.submitAndWait(procExec,
new TruncateTableProcedure(procExec.getEnvironment(), tableName, false));
// Second delete should fail with TableNotDisabled
Procedure<?> result = procExec.getResult(procId);
assertTrue(result.isFailed());
cause = ProcedureTestingUtility.getExceptionCause(result);
} catch (Throwable t) {
cause = t;
}
LOG.debug("Truncate failed with exception: " + cause);
assertTrue(cause instanceof TableNotDisabledException);
}
@Test(expected = TableNotDisabledException.class)
public void testEnableNonDisabledTable() throws Exception {
final TableName tableName = TableName.valueOf(name.getMethodName());
final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", "f2");
// Enable the table - expect failure
long procId1 =
procExec.submitProcedure(new EnableTableProcedure(procExec.getEnvironment(), tableName));
ProcedureTestingUtility.waitProcedure(procExec, procId1);
Procedure<?> result = procExec.getResult(procId1);
assertTrue(result.isFailed());
LOG.debug("Enable failed with exception: " + result.getException());
assertTrue(
ProcedureTestingUtility.getExceptionCause(result) instanceof TableNotDisabledException);
// Enable the table - expect failure from ProcedurePrepareLatch
final ProcedurePrepareLatch prepareLatch = new ProcedurePrepareLatch.CompatibilityLatch();
procExec.submitProcedure(
new EnableTableProcedure(procExec.getEnvironment(), tableName, prepareLatch));
prepareLatch.await();
}
@Override
public void clearTable(String tableString, long timestamp) throws IOException
{
TableName tableName = TableName.valueOf(tableString);
if (!adm.tableExists(tableName)) {
log.debug("Attempted to clear table {} before it exists (noop)", tableString);
return;
}
if (!adm.isTableDisabled(tableName))
adm.disableTable(tableName);
if (!adm.isTableDisabled(tableName))
throw new RuntimeException("Unable to disable table " + tableName);
// This API call appears to both truncate and reenable the table.
log.info("Truncating table {}", tableName);
adm.truncateTable(tableName, true /* preserve splits */);
try {
adm.enableTable(tableName);
} catch (TableNotDisabledException e) {
// This triggers seemingly every time in testing with 1.0.2.
log.debug("Table automatically reenabled by truncation: {}", tableName, e);
}
}
@Override
public void clearTable(String tableString, long timestamp) throws IOException
{
TableName tableName = TableName.valueOf(tableString);
if (!adm.tableExists(tableName)) {
log.debug("Attempted to clear table {} before it exists (noop)", tableString);
return;
}
if (!adm.isTableDisabled(tableName))
adm.disableTable(tableName);
if (!adm.isTableDisabled(tableName))
throw new RuntimeException("Unable to disable table " + tableName);
// This API call appears to both truncate and reenable the table.
log.info("Truncating table {}", tableName);
adm.truncateTable(tableName, true /* preserve splits */);
try {
adm.enableTable(tableName);
} catch (TableNotDisabledException e) {
// This triggers seemingly every time in testing with 1.0.2.
log.debug("Table automatically reenabled by truncation: {}", tableName, e);
}
}
@Override
public void clearTable(String tableString, long timestamp) throws IOException
{
TableName tableName = TableName.valueOf(tableString);
if (!adm.tableExists(tableName)) {
log.debug("Attempted to clear table {} before it exists (noop)", tableString);
return;
}
if (!adm.isTableDisabled(tableName))
adm.disableTable(tableName);
if (!adm.isTableDisabled(tableName))
throw new RuntimeException("Unable to disable table " + tableName);
// This API call appears to both truncate and reenable the table.
log.info("Truncating table {}", tableName);
adm.truncateTable(tableName, true /* preserve splits */);
try {
adm.enableTable(tableName);
} catch (TableNotDisabledException e) {
// This triggers seemingly every time in testing with 1.0.2.
log.debug("Table automatically reenabled by truncation: {}", tableName, e);
}
}
/**
* Method to enable a table, if not already enabled. This method suppresses
* {@link TableNotDisabledException} and {@link TableNotFoundException}, if thrown while enabling
* the table.
* @param conn connection to re-use
* @param tableName name of the table to be enabled
*/
public static void enableTableIfNotEnabled(Connection conn, TableName tableName)
throws IOException {
try {
conn.getAdmin().enableTable(tableName);
} catch (TableNotDisabledException | TableNotFoundException e) {
// ignore
}
}
@Override
public void checkTableModifiable(final TableName tableName)
throws IOException, TableNotFoundException, TableNotDisabledException {
if (isCatalogTable(tableName)) {
throw new IOException("Can't modify catalog tables");
}
checkTableExists(tableName);
TableState ts = getTableStateManager().getTableState(tableName);
if (!ts.isDisabled()) {
throw new TableNotDisabledException("Not DISABLED; " + ts);
}
}
/**
* Check that cluster is up and master is running. Check table is modifiable.
* If <code>enabled</code>, check table is enabled else check it is disabled.
* Call in Procedure constructor so can pass any exception to caller.
* @param enabled If true, check table is enabled and throw exception if not. If false, do the
* inverse. If null, do no table checks.
*/
protected void preflightChecks(MasterProcedureEnv env, Boolean enabled) throws HBaseIOException {
MasterServices master = env.getMasterServices();
if (!master.isClusterUp()) {
throw new HBaseIOException("Cluster not up!");
}
if (master.isStopping() || master.isStopped()) {
throw new HBaseIOException("Master stopping=" + master.isStopping() +
", stopped=" + master.isStopped());
}
if (enabled == null) {
// Don't do any table checks.
return;
}
try {
// Checks table exists and is modifiable.
checkTableModifiable(env);
TableName tn = getTableName();
TableStateManager tsm = master.getTableStateManager();
TableState ts = tsm.getTableState(tn);
if (enabled) {
if (!ts.isEnabledOrEnabling()) {
throw new TableNotEnabledException(tn);
}
} else {
if (!ts.isDisabledOrDisabling()) {
throw new TableNotDisabledException(tn);
}
}
} catch (IOException ioe) {
if (ioe instanceof HBaseIOException) {
throw (HBaseIOException)ioe;
}
throw new HBaseIOException(ioe);
}
}
private boolean prepareTruncate(final MasterProcedureEnv env) throws IOException {
try {
env.getMasterServices().checkTableModifiable(getTableName());
} catch (TableNotFoundException|TableNotDisabledException e) {
setFailure("master-truncate-table", e);
return false;
}
return true;
}
/**
* Action before any real action of enabling table. Set the exception in the procedure instead
* of throwing it. This approach is to deal with backward compatible with 1.0.
* @param env MasterProcedureEnv
* @return whether the table passes the necessary checks
* @throws IOException
*/
private boolean prepareEnable(final MasterProcedureEnv env) throws IOException {
boolean canTableBeEnabled = true;
// Check whether table exists
if (!MetaTableAccessor.tableExists(env.getMasterServices().getConnection(), tableName)) {
setFailure("master-enable-table", new TableNotFoundException(tableName));
canTableBeEnabled = false;
} else {
// There could be multiple client requests trying to disable or enable
// the table at the same time. Ensure only the first request is honored
// After that, no other requests can be accepted until the table reaches
// DISABLED or ENABLED.
//
// Note: in 1.0 release, we called TableStateManager.setTableStateIfInStates() to set
// the state to ENABLING from DISABLED. The implementation was done before table lock
// was implemented. With table lock, there is no need to set the state here (it will
// set the state later on). A quick state check should be enough for us to move forward.
TableStateManager tsm = env.getMasterServices().getTableStateManager();
TableState ts = tsm.getTableState(tableName);
if(!ts.isDisabled()){
LOG.info("Not DISABLED tableState={}; skipping enable; {}", ts.getState(), this);
setFailure("master-enable-table", new TableNotDisabledException(ts.toString()));
canTableBeEnabled = false;
}
}
// We are done the check. Future actions in this procedure could be done asynchronously.
releaseSyncLatch();
return canTableBeEnabled;
}
private boolean prepareDelete(final MasterProcedureEnv env) throws IOException {
try {
env.getMasterServices().checkTableModifiable(tableName);
} catch (TableNotFoundException|TableNotDisabledException e) {
setFailure("master-delete-table", e);
return false;
}
return true;
}
/**
* Can't enable a table if the table isn't in disabled state
*/
@Test(expected = TableNotDisabledException.class)
public void testTableNotDisabledExceptionWithATable() throws IOException {
final TableName name = TableName.valueOf(this.name.getMethodName());
try (Table t = TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY)) {
ADMIN.enableTable(name);
}
}
@Test(expected=TableNotDisabledException.class)
public void testDeleteNotDisabledTable() throws Exception {
final TableName tableName = TableName.valueOf(name.getMethodName());
final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f");
ProcedurePrepareLatch latch = new ProcedurePrepareLatch.CompatibilityLatch();
long procId = ProcedureTestingUtility.submitAndWait(procExec,
new DeleteTableProcedure(procExec.getEnvironment(), tableName, latch));
latch.await();
}
/**
* Check conditions before any real action of modifying a table.
*/
private void prepareModify(final MasterProcedureEnv env) throws IOException {
// Checks whether the table exists
if (!MetaTableAccessor.tableExists(env.getMasterServices().getConnection(), getTableName())) {
throw new TableNotFoundException(getTableName());
}
// check that we have at least 1 CF
if (modifiedTableDescriptor.getColumnFamilyCount() == 0) {
throw new DoNotRetryIOException("Table " + getTableName().toString() +
" should have at least one column family.");
}
// If descriptor check is enabled, check whether the table descriptor when procedure was
// submitted matches with the current
// table descriptor of the table, else retrieve the old descriptor
// for comparison in order to update the descriptor.
if (shouldCheckDescriptor) {
if (TableDescriptor.COMPARATOR.compare(unmodifiedTableDescriptor,
env.getMasterServices().getTableDescriptors().get(getTableName())) != 0) {
LOG.error("Error while modifying table '" + getTableName().toString()
+ "' Skipping procedure : " + this);
throw new ConcurrentTableModificationException(
"Skipping modify table operation on table '" + getTableName().toString()
+ "' as it has already been modified by some other concurrent operation, "
+ "Please retry.");
}
} else {
this.unmodifiedTableDescriptor =
env.getMasterServices().getTableDescriptors().get(getTableName());
}
if (env.getMasterServices().getTableStateManager()
.isTableState(getTableName(), TableState.State.ENABLED)) {
if (modifiedTableDescriptor.getRegionReplication() != unmodifiedTableDescriptor
.getRegionReplication()) {
throw new TableNotDisabledException(
"REGION_REPLICATION change is not supported for enabled tables");
}
}
this.deleteColumnFamilyInModify = isDeleteColumnFamily(unmodifiedTableDescriptor,
modifiedTableDescriptor);
if (!unmodifiedTableDescriptor.getRegionServerGroup()
.equals(modifiedTableDescriptor.getRegionServerGroup())) {
Supplier<String> forWhom = () -> "table " + getTableName();
RSGroupInfo rsGroupInfo = MasterProcedureUtil.checkGroupExists(
env.getMasterServices().getRSGroupInfoManager()::getRSGroup,
modifiedTableDescriptor.getRegionServerGroup(), forWhom);
MasterProcedureUtil.checkGroupNotEmpty(rsGroupInfo, forWhom);
}
}
@Override
public CompletableFuture<Void> restoreSnapshot(String snapshotName, boolean takeFailSafeSnapshot,
boolean restoreAcl) {
CompletableFuture<Void> future = new CompletableFuture<>();
addListener(listSnapshots(Pattern.compile(snapshotName)), (snapshotDescriptions, err) -> {
if (err != null) {
future.completeExceptionally(err);
return;
}
TableName tableName = null;
if (snapshotDescriptions != null && !snapshotDescriptions.isEmpty()) {
for (SnapshotDescription snap : snapshotDescriptions) {
if (snap.getName().equals(snapshotName)) {
tableName = snap.getTableName();
break;
}
}
}
if (tableName == null) {
future.completeExceptionally(new RestoreSnapshotException(
"Unable to find the table name for snapshot=" + snapshotName));
return;
}
final TableName finalTableName = tableName;
addListener(tableExists(finalTableName), (exists, err2) -> {
if (err2 != null) {
future.completeExceptionally(err2);
} else if (!exists) {
// if table does not exist, then just clone snapshot into new table.
completeConditionalOnFuture(future,
internalRestoreSnapshot(snapshotName, finalTableName, restoreAcl));
} else {
addListener(isTableDisabled(finalTableName), (disabled, err4) -> {
if (err4 != null) {
future.completeExceptionally(err4);
} else if (!disabled) {
future.completeExceptionally(new TableNotDisabledException(finalTableName));
} else {
completeConditionalOnFuture(future,
restoreSnapshot(snapshotName, finalTableName, takeFailSafeSnapshot, restoreAcl));
}
});
}
});
});
return future;
}
/**
* Check table is modifiable; i.e. exists and is offline.
* @param tableName Name of table to check.
* @throws TableNotDisabledException
* @throws TableNotFoundException
* @throws IOException
*/
// We actually throw the exceptions mentioned in the
void checkTableModifiable(final TableName tableName)
throws IOException, TableNotFoundException, TableNotDisabledException;