HBASE-20024 Fixed flakyness of TestMergeTableRegionsProcedure
We assumed that we can run for loop from 0 to lastStep sequentially. MergeTableRegionProcedure skips step 2. So, when i is 0 the procedure is already at step 3. Added a method StateMachineProcedure#getCurrentStateId that can be used from test code only.
This commit is contained in:
parent
ee3a469641
commit
974200fca1
|
@ -28,6 +28,9 @@ import org.apache.yetus.audience.InterfaceAudience;
|
||||||
import org.apache.yetus.audience.InterfaceStability;
|
import org.apache.yetus.audience.InterfaceStability;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting;
|
||||||
|
|
||||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos.StateMachineProcedureData;
|
import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos.StateMachineProcedureData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -253,6 +256,16 @@ public abstract class StateMachineProcedure<TEnvironment, TState>
|
||||||
return stateCount > 0 ? getState(states[stateCount-1]) : getInitialState();
|
return stateCount > 0 ? getState(states[stateCount-1]) : getInitialState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is used from test code as it cannot be assumed that state transition will happen
|
||||||
|
* sequentially. Some procedures may skip steps/ states, some may add intermediate steps in
|
||||||
|
* future.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
public int getCurrentStateId() {
|
||||||
|
return getStateId(getCurrentState());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the next state for the procedure.
|
* Set the next state for the procedure.
|
||||||
* @param stateId the ordinal() of the state enum (or state id)
|
* @param stateId the ordinal() of the state enum (or state id)
|
||||||
|
|
|
@ -54,8 +54,10 @@ import org.apache.hadoop.hbase.master.RegionState;
|
||||||
import org.apache.hadoop.hbase.master.TableStateManager;
|
import org.apache.hadoop.hbase.master.TableStateManager;
|
||||||
import org.apache.hadoop.hbase.master.assignment.AssignmentManager;
|
import org.apache.hadoop.hbase.master.assignment.AssignmentManager;
|
||||||
import org.apache.hadoop.hbase.monitoring.TaskMonitor;
|
import org.apache.hadoop.hbase.monitoring.TaskMonitor;
|
||||||
|
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.ProcedureTestingUtility;
|
import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility;
|
||||||
|
import org.apache.hadoop.hbase.procedure2.StateMachineProcedure;
|
||||||
import org.apache.hadoop.hbase.util.Bytes;
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
import org.apache.hadoop.hbase.util.FSUtils;
|
import org.apache.hadoop.hbase.util.FSUtils;
|
||||||
import org.apache.hadoop.hbase.util.MD5Hash;
|
import org.apache.hadoop.hbase.util.MD5Hash;
|
||||||
|
@ -377,11 +379,28 @@ public class MasterProcedureTestingUtility {
|
||||||
// execute step N - kill before store update
|
// execute step N - kill before store update
|
||||||
// restart executor/store
|
// restart executor/store
|
||||||
// execute step N - save on store
|
// execute step N - save on store
|
||||||
for (int i = 0; i < numSteps; ++i) {
|
// NOTE: currently we make assumption that states/ steps are sequential. There are already
|
||||||
LOG.info("Restart " + i + " exec state=" + procExec.getProcedure(procId));
|
// instances of a procedures which skip (don't use) intermediate states/ steps. In future,
|
||||||
|
// intermediate states/ steps can be added with ordinal greater than lastStep. If and when
|
||||||
|
// that happens the states can not be treated as sequential steps and the condition in
|
||||||
|
// following while loop needs to be changed. We can use euqals/ not equals operator to check
|
||||||
|
// if the procedure has reached the user specified state. But there is a possibility that
|
||||||
|
// while loop may not get the control back exaclty when the procedure is in lastStep. Proper
|
||||||
|
// fix would be get all visited states by the procedure and then check if user speccified
|
||||||
|
// state is in that list. Current assumption of sequential proregression of steps/ states is
|
||||||
|
// made at multiple places so we can keep while condition below for simplicity.
|
||||||
|
Procedure proc = procExec.getProcedure(procId);
|
||||||
|
int stepNum = proc instanceof StateMachineProcedure ?
|
||||||
|
((StateMachineProcedure) proc).getCurrentStateId() : 0;
|
||||||
|
while (stepNum < numSteps) {
|
||||||
|
LOG.info("Restart " + stepNum + " exec state=" + proc);
|
||||||
ProcedureTestingUtility.assertProcNotYetCompleted(procExec, procId);
|
ProcedureTestingUtility.assertProcNotYetCompleted(procExec, procId);
|
||||||
restartMasterProcedureExecutor(procExec);
|
restartMasterProcedureExecutor(procExec);
|
||||||
ProcedureTestingUtility.waitProcedure(procExec, procId);
|
ProcedureTestingUtility.waitProcedure(procExec, procId);
|
||||||
|
// Old proc object is stale, need to get the new one after ProcedureExecutor restart
|
||||||
|
proc = procExec.getProcedure(procId);
|
||||||
|
stepNum = proc instanceof StateMachineProcedure ?
|
||||||
|
((StateMachineProcedure) proc).getCurrentStateId() : stepNum + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(expectExecRunning, procExec.isRunning());
|
assertEquals(expectExecRunning, procExec.isRunning());
|
||||||
|
|
Loading…
Reference in New Issue