Repository: hbase
Updated Branches:
  refs/heads/branch-2.0 32c0cf32c -> 564406ec5


HBASE-21291 Add a test for bypassing stuck state-machine procedures

Signed-off-by: Michael Stack <st...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/564406ec
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/564406ec
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/564406ec

Branch: refs/heads/branch-2.0
Commit: 564406ec5e48644ad233a94b4c146f1ee69ebe09
Parents: 32c0cf3
Author: tianjingyun <tianjy1...@gmail.com>
Authored: Sat Oct 13 18:43:40 2018 +0800
Committer: Michael Stack <st...@apache.org>
Committed: Thu Oct 18 14:28:11 2018 -0700

----------------------------------------------------------------------
 .../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/564406ec/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 b1f6900..faad84e 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 override, boolean 
recursive)
       throws IOException {
+    Preconditions.checkArgument(lockWait > 0, "lockWait should be positive");
     final Procedure<TEnvironment> procedure = getProcedure(pid);
     if (procedure == null) {
       LOG.debug("Procedure pid={} does not exist, skipping bypass", pid);

http://git-wip-us.apache.org/repos/asf/hbase/blob/564406ec/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 138215b..52ffa57 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
@@ -389,6 +389,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/564406ec/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 739d161..fa40631 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;
@@ -133,6 +135,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, false));
+    assertTrue(procExecutor.bypassProcedure(id, 1000, true, false));
+
+    htu.waitFor(5000, () -> proc.isSuccess() && proc.isBypass());
+    LOG.info("{} finished", proc);
+  }
+
   @AfterClass
   public static void tearDown() throws Exception {
     procExecutor.stop();
@@ -191,4 +207,51 @@ 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();
+    }
+  }
 }

Reply via email to