HBASE-21550 Add a new method preCreateTableRegionInfos for MasterObserver which allows CPs to modify the TableDescriptor
This commit is contained in:
parent
8bf966c8e9
commit
f49baf259e
|
@ -70,6 +70,21 @@ import org.apache.yetus.audience.InterfaceStability;
|
|||
@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
|
||||
@InterfaceStability.Evolving
|
||||
public interface MasterObserver {
|
||||
|
||||
/**
|
||||
* Called before we create the region infos for this table. Called as part of create table RPC
|
||||
* call.
|
||||
* @param ctx the environment to interact with the framework and master
|
||||
* @param desc the TableDescriptor for the table
|
||||
* @return the TableDescriptor used to create the table. Default is the one passed in. Return
|
||||
* {@code null} means cancel the creation.
|
||||
*/
|
||||
default TableDescriptor preCreateTableRegionsInfos(
|
||||
final ObserverContext<MasterCoprocessorEnvironment> ctx, TableDescriptor desc)
|
||||
throws IOException {
|
||||
return desc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before a new table is created by
|
||||
* {@link org.apache.hadoop.hbase.master.HMaster}. Called as part of create
|
||||
|
|
|
@ -2030,45 +2030,45 @@ public class HMaster extends HRegionServer implements MasterServices {
|
|||
}
|
||||
|
||||
@Override
|
||||
public long createTable(
|
||||
final TableDescriptor tableDescriptor,
|
||||
final byte [][] splitKeys,
|
||||
final long nonceGroup,
|
||||
final long nonce) throws IOException {
|
||||
public long createTable(final TableDescriptor tableDescriptor, final byte[][] splitKeys,
|
||||
final long nonceGroup, final long nonce) throws IOException {
|
||||
checkInitialized();
|
||||
|
||||
String namespace = tableDescriptor.getTableName().getNamespaceAsString();
|
||||
TableDescriptor desc = getMasterCoprocessorHost().preCreateTableRegionsInfos(tableDescriptor);
|
||||
if (desc == null) {
|
||||
throw new IOException("Creation for " + tableDescriptor + " is canceled by CP");
|
||||
}
|
||||
String namespace = desc.getTableName().getNamespaceAsString();
|
||||
this.clusterSchemaService.getNamespace(namespace);
|
||||
|
||||
RegionInfo[] newRegions = ModifyRegionUtils.createRegionInfos(tableDescriptor, splitKeys);
|
||||
sanityCheckTableDescriptor(tableDescriptor);
|
||||
RegionInfo[] newRegions = ModifyRegionUtils.createRegionInfos(desc, splitKeys);
|
||||
sanityCheckTableDescriptor(desc);
|
||||
|
||||
return MasterProcedureUtil.submitProcedure(
|
||||
new MasterProcedureUtil.NonceProcedureRunnable(this, nonceGroup, nonce) {
|
||||
@Override
|
||||
protected void run() throws IOException {
|
||||
getMaster().getMasterCoprocessorHost().preCreateTable(tableDescriptor, newRegions);
|
||||
return MasterProcedureUtil
|
||||
.submitProcedure(new MasterProcedureUtil.NonceProcedureRunnable(this, nonceGroup, nonce) {
|
||||
@Override
|
||||
protected void run() throws IOException {
|
||||
getMaster().getMasterCoprocessorHost().preCreateTable(desc, newRegions);
|
||||
|
||||
LOG.info(getClientIdAuditPrefix() + " create " + tableDescriptor);
|
||||
LOG.info(getClientIdAuditPrefix() + " create " + desc);
|
||||
|
||||
// TODO: We can handle/merge duplicate requests, and differentiate the case of
|
||||
// TableExistsException by saying if the schema is the same or not.
|
||||
//
|
||||
// We need to wait for the procedure to potentially fail due to "prepare" sanity
|
||||
// checks. This will block only the beginning of the procedure. See HBASE-19953.
|
||||
ProcedurePrepareLatch latch = ProcedurePrepareLatch.createBlockingLatch();
|
||||
submitProcedure(new CreateTableProcedure(
|
||||
procedureExecutor.getEnvironment(), tableDescriptor, newRegions, latch));
|
||||
latch.await();
|
||||
// TODO: We can handle/merge duplicate requests, and differentiate the case of
|
||||
// TableExistsException by saying if the schema is the same or not.
|
||||
//
|
||||
// We need to wait for the procedure to potentially fail due to "prepare" sanity
|
||||
// checks. This will block only the beginning of the procedure. See HBASE-19953.
|
||||
ProcedurePrepareLatch latch = ProcedurePrepareLatch.createBlockingLatch();
|
||||
submitProcedure(
|
||||
new CreateTableProcedure(procedureExecutor.getEnvironment(), desc, newRegions, latch));
|
||||
latch.await();
|
||||
|
||||
getMaster().getMasterCoprocessorHost().postCreateTable(tableDescriptor, newRegions);
|
||||
}
|
||||
getMaster().getMasterCoprocessorHost().postCreateTable(desc, newRegions);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDescription() {
|
||||
return "CreateTableProcedure";
|
||||
}
|
||||
});
|
||||
@Override
|
||||
protected String getDescription() {
|
||||
return "CreateTableProcedure";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -317,6 +317,20 @@ public class MasterCoprocessorHost
|
|||
|
||||
/* Implementation of hooks for invoking MasterObservers */
|
||||
|
||||
public TableDescriptor preCreateTableRegionsInfos(TableDescriptor desc) throws IOException {
|
||||
if (coprocEnvironments.isEmpty()) {
|
||||
return desc;
|
||||
}
|
||||
return execOperationWithResult(
|
||||
new ObserverOperationWithResult<MasterObserver, TableDescriptor>(masterObserverGetter, desc) {
|
||||
|
||||
@Override
|
||||
protected TableDescriptor call(MasterObserver observer) throws IOException {
|
||||
return observer.preCreateTableRegionsInfos(this, getResult());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void preCreateTable(final TableDescriptor htd, final RegionInfo[] regions)
|
||||
throws IOException {
|
||||
execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() {
|
||||
|
|
|
@ -94,6 +94,7 @@ public class TestMasterObserver {
|
|||
|
||||
public static class CPMasterObserver implements MasterCoprocessor, MasterObserver {
|
||||
|
||||
private boolean preCreateTableRegionInfosCalled;
|
||||
private boolean preCreateTableCalled;
|
||||
private boolean postCreateTableCalled;
|
||||
private boolean preDeleteTableCalled;
|
||||
|
@ -186,6 +187,7 @@ public class TestMasterObserver {
|
|||
private boolean postLockHeartbeatCalled;
|
||||
|
||||
public void resetStates() {
|
||||
preCreateTableRegionInfosCalled = false;
|
||||
preCreateTableCalled = false;
|
||||
postCreateTableCalled = false;
|
||||
preDeleteTableCalled = false;
|
||||
|
@ -297,6 +299,14 @@ public class TestMasterObserver {
|
|||
return preMergeRegionsCalled && postMergeRegionsCalled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableDescriptor preCreateTableRegionsInfos(
|
||||
ObserverContext<MasterCoprocessorEnvironment> ctx, TableDescriptor desc)
|
||||
throws IOException {
|
||||
preCreateTableRegionInfosCalled = true;
|
||||
return desc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preCreateTable(ObserverContext<MasterCoprocessorEnvironment> env,
|
||||
TableDescriptor desc, RegionInfo[] regions) throws IOException {
|
||||
|
@ -310,11 +320,11 @@ public class TestMasterObserver {
|
|||
}
|
||||
|
||||
public boolean wasCreateTableCalled() {
|
||||
return preCreateTableCalled && postCreateTableCalled;
|
||||
return preCreateTableRegionInfosCalled && preCreateTableCalled && postCreateTableCalled;
|
||||
}
|
||||
|
||||
public boolean preCreateTableCalledOnly() {
|
||||
return preCreateTableCalled && !postCreateTableCalled;
|
||||
return preCreateTableRegionInfosCalled && preCreateTableCalled && !postCreateTableCalled;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue