diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/MergeTableRegionsProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/MergeTableRegionsProcedure.java index 20ae444..7351d83 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/MergeTableRegionsProcedure.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/MergeTableRegionsProcedure.java @@ -528,6 +528,20 @@ public class MergeTableRegionsProcedure return false; } + // A safe fence here, if there is a table procedure going on, abort the merge. + // There some cases that may lead to table procedure roll back (more serious + // than roll back the merge procedure here), or the merged regions was brought online + // by the table procedure because of the race between merge procedure and table procedure + if (env.getMasterServices().getProcedures().stream() + .filter(p -> p instanceof AbstractStateMachineTableProcedure) + .map(p -> (AbstractStateMachineTableProcedure) p).filter( + p -> p.getTableName().equals(regionsToMerge[0].getTable()) && !p + .isFinished()).count() > 0) { + throw new MergeRegionException( + "There is a table procedure going on against the same table, abort the merge of " + + this.toString()); + } + // Ask the remote regionserver if regions are mergeable. If we get an IOE, report it // along with the failure, so we can see why regions are not mergeable at this time. IOException mergeableCheckIOE = null; diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/SplitTableRegionProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/SplitTableRegionProcedure.java index 411077f..1138187 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/SplitTableRegionProcedure.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/SplitTableRegionProcedure.java @@ -54,6 +54,7 @@ import org.apache.hadoop.hbase.master.RegionState.State; import org.apache.hadoop.hbase.master.assignment.RegionStates.RegionStateNode; import org.apache.hadoop.hbase.master.normalizer.NormalizationPlan; import org.apache.hadoop.hbase.master.procedure.AbstractStateMachineRegionProcedure; +import org.apache.hadoop.hbase.master.procedure.AbstractStateMachineTableProcedure; import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; import org.apache.hadoop.hbase.master.procedure.MasterProcedureUtil; import org.apache.hadoop.hbase.procedure2.ProcedureMetrics; @@ -162,6 +163,19 @@ public class SplitTableRegionProcedure if(regionToSplit.getReplicaId() != RegionInfo.DEFAULT_REPLICA_ID) { throw new IllegalArgumentException ("Can't invoke split on non-default regions directly"); } + // A safe fence here, if there is a table procedure going on, abort the split. + // There some cases that may lead to table procedure roll back (more serious + // than roll back the split procedure here), or the split parent was brought online + // by the table procedure because of the race between split procedure and table procedure + if (env.getMasterServices().getProcedures().stream() + .filter(p -> p instanceof AbstractStateMachineTableProcedure) + .map(p -> (AbstractStateMachineTableProcedure) p).filter( + p -> p.getTableName().equals(getParentRegion().getTable()) && !p + .isFinished()).count() > 0) { + throw new DoNotRetryIOException( + "There is a table procedure going on against the same table, abort the split of " + + this.toString()); + } RegionStateNode node = env.getAssignmentManager().getRegionStates().getRegionStateNode(getParentRegion()); IOException splittableCheckIOE = null;