From a8989542e954d53c0ca0c747ed53b0ffb91c55b7 Mon Sep 17 00:00:00 2001 From: jingyuntian Date: Fri, 12 Oct 2018 10:57:14 +0800 Subject: [PATCH] HBASE-21291 Add a test for bypassing stuck state-machine procedures --- .../hbase/procedure2/ProcedureTestingUtility.java | 37 ++++++++++++++ .../hbase/procedure2/TestProcedureBypass.java | 58 ++++++++++++++++++++++ 2 files changed, 95 insertions(+) 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..31d9f72 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,43 @@ public class ProcedureTestingUtility { } } + public static class NoopStateMachineProcedure + extends StateMachineProcedure { + 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 { private byte[] data = null; 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..312e6fc 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,21 @@ 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, 5000, false)); + assertTrue(procExecutor.bypassProcedure(id, 5000, true)); + + //Since the procedure is stuck there, we need to restart the executor to recovery. + ProcedureTestingUtility.restart(procExecutor); + htu.waitFor(5000, () -> proc.isSuccess() && proc.isBypass()); + LOG.info("{} finished", proc); + } + @AfterClass @@ -181,5 +198,46 @@ public class TestProcedureBypass { } + public enum StuckStateMachineState{ + START,THEN,END + } + + public static class StuckStateMachineProcedure extends ProcedureTestingUtility.NoopStateMachineProcedure{ + 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(); + } + } + } -- 2.7.4