Repository: hbase Updated Branches: refs/heads/branch-2 deae1316a -> 85d81fe08
HBASE-21291 Add a test for bypassing stuck state-machine procedures Signed-off-by: Allan Yang <allan...@apache.org> Project: http://git-wip-us.apache.org/repos/asf/hbase/repo Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/85d81fe0 Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/85d81fe0 Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/85d81fe0 Branch: refs/heads/branch-2 Commit: 85d81fe083380f142ae554b5f97f79214b1edb28 Parents: deae131 Author: Jingyun Tian <tianjy1...@gmail.com> Authored: Tue Oct 16 22:57:50 2018 +0800 Committer: Allan Yang <allan...@apache.org> Committed: Tue Oct 16 22:57:50 2018 +0800 ---------------------------------------------------------------------- .../hbase/procedure2/ProcedureExecutor.java | 1 + .../procedure2/ProcedureTestingUtility.java | 40 +++++++++++++ .../hbase/procedure2/TestProcedureBypass.java | 63 ++++++++++++++++++++ 3 files changed, 104 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hbase/blob/85d81fe0/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureExecutor.java ---------------------------------------------------------------------- diff --git a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureExecutor.java b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureExecutor.java index 7c33284..d57fcb5 100644 --- a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureExecutor.java +++ b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureExecutor.java @@ -1054,6 +1054,7 @@ public class ProcedureExecutor<TEnvironment> { } boolean bypassProcedure(long pid, long lockWait, boolean force) throws IOException { + Preconditions.checkArgument(lockWait > 0, "lockWait should be positive"); Procedure<TEnvironment> procedure = getProcedure(pid); if (procedure == null) { LOG.debug("Procedure with id={} does not exist, skipping bypass", pid); http://git-wip-us.apache.org/repos/asf/hbase/blob/85d81fe0/hbase-procedure/src/test/java/org/apache/hadoop/hbase/procedure2/ProcedureTestingUtility.java ---------------------------------------------------------------------- diff --git a/hbase-procedure/src/test/java/org/apache/hadoop/hbase/procedure2/ProcedureTestingUtility.java b/hbase-procedure/src/test/java/org/apache/hadoop/hbase/procedure2/ProcedureTestingUtility.java index d52b6bb..4d06e2f 100644 --- a/hbase-procedure/src/test/java/org/apache/hadoop/hbase/procedure2/ProcedureTestingUtility.java +++ b/hbase-procedure/src/test/java/org/apache/hadoop/hbase/procedure2/ProcedureTestingUtility.java @@ -400,6 +400,46 @@ public class ProcedureTestingUtility { } } + public static class NoopStateMachineProcedure<TEnv, TState> + extends StateMachineProcedure<TEnv, TState> { + private TState initialState; + private TEnv env; + + public NoopStateMachineProcedure() { + } + + public NoopStateMachineProcedure(TEnv env, TState initialState) { + this.env = env; + this.initialState = initialState; + } + + @Override + protected Flow executeFromState(TEnv env, TState tState) + throws ProcedureSuspendedException, ProcedureYieldException, InterruptedException { + return null; + } + + @Override + protected void rollbackState(TEnv env, TState tState) throws IOException, InterruptedException { + + } + + @Override + protected TState getState(int stateId) { + return null; + } + + @Override + protected int getStateId(TState tState) { + return 0; + } + + @Override + protected TState getInitialState() { + return initialState; + } + } + public static class TestProcedure extends NoopProcedure<Void> { private byte[] data = null; http://git-wip-us.apache.org/repos/asf/hbase/blob/85d81fe0/hbase-procedure/src/test/java/org/apache/hadoop/hbase/procedure2/TestProcedureBypass.java ---------------------------------------------------------------------- diff --git a/hbase-procedure/src/test/java/org/apache/hadoop/hbase/procedure2/TestProcedureBypass.java b/hbase-procedure/src/test/java/org/apache/hadoop/hbase/procedure2/TestProcedureBypass.java index d58d57e..0c59f30 100644 --- a/hbase-procedure/src/test/java/org/apache/hadoop/hbase/procedure2/TestProcedureBypass.java +++ b/hbase-procedure/src/test/java/org/apache/hadoop/hbase/procedure2/TestProcedureBypass.java @@ -17,8 +17,10 @@ */ package org.apache.hadoop.hbase.procedure2; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; import org.apache.hadoop.fs.FileSystem; @@ -119,6 +121,20 @@ public class TestProcedureBypass { LOG.info("{} finished", proc); } + @Test + public void testBypassingStuckStateMachineProcedure() throws Exception { + final StuckStateMachineProcedure proc = + new StuckStateMachineProcedure(procEnv, StuckStateMachineState.START); + long id = procExecutor.submitProcedure(proc); + Thread.sleep(500); + // bypass the procedure + assertFalse(procExecutor.bypassProcedure(id, 1000, false)); + assertTrue(procExecutor.bypassProcedure(id, 1000, true)); + + htu.waitFor(5000, () -> proc.isSuccess() && proc.isBypass()); + LOG.info("{} finished", proc); + } + @AfterClass @@ -181,5 +197,52 @@ public class TestProcedureBypass { } + public enum StuckStateMachineState { + START, THEN, END + } + + public static class StuckStateMachineProcedure extends + ProcedureTestingUtility.NoopStateMachineProcedure<TestProcEnv, StuckStateMachineState> { + private AtomicBoolean stop = new AtomicBoolean(false); + + public StuckStateMachineProcedure() { + super(); + } + + public StuckStateMachineProcedure(TestProcEnv env, StuckStateMachineState initialState) { + super(env, initialState); + } + + @Override + protected Flow executeFromState(TestProcEnv env, StuckStateMachineState tState) + throws ProcedureSuspendedException, ProcedureYieldException, InterruptedException { + switch (tState) { + case START: + LOG.info("PHASE 1: START"); + setNextState(StuckStateMachineState.THEN); + return Flow.HAS_MORE_STATE; + case THEN: + if (stop.get()) { + setNextState(StuckStateMachineState.END); + } + return Flow.HAS_MORE_STATE; + case END: + return Flow.NO_MORE_STATE; + default: + throw new UnsupportedOperationException("unhandled state=" + tState); + } + } + + @Override + protected StuckStateMachineState getState(int stateId) { + return StuckStateMachineState.values()[stateId]; + } + + @Override + protected int getStateId(StuckStateMachineState tState) { + return tState.ordinal(); + } + } + }