Repository: hbase
Updated Branches:
  refs/heads/branch-1.2 883e3cdc3 -> cbd4e5a1f


http://git-wip-us.apache.org/repos/asf/hbase/blob/cbd4e5a1/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterServices.java
----------------------------------------------------------------------
diff --git 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterServices.java 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterServices.java
index c22f0ed..2a3f71a 100644
--- 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterServices.java
+++ 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterServices.java
@@ -284,6 +284,14 @@ public interface MasterServices extends Server {
   public void deleteNamespace(String name) throws IOException;
 
   /**
+   * Abort a procedure.
+   * @param procId ID of the procedure
+   * @param mayInterruptIfRunning if the proc completed at least one step, 
should it be aborted?
+   * @return true if aborted, false if procedure already completed or does not 
exist
+   */
+  public boolean abortProcedure(final long procId, final boolean 
mayInterruptIfRunning);
+
+  /**
    * Get a namespace descriptor by name
    * @param name name of namespace descriptor
    * @return A descriptor

http://git-wip-us.apache.org/repos/asf/hbase/blob/cbd4e5a1/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin2.java
----------------------------------------------------------------------
diff --git 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin2.java 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin2.java
index 44f6f50..83a51a8 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin2.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin2.java
@@ -25,6 +25,7 @@ import static org.junit.Assert.fail;
 
 import java.io.IOException;
 import java.util.List;
+import java.util.Random;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.commons.logging.Log;
@@ -66,7 +67,6 @@ import org.junit.experimental.categories.Category;
 
 import com.google.protobuf.ServiceException;
 
-
 /**
  * Class to test HBaseAdmin.
  * Spins up the minicluster once at test start and then takes it down 
afterward.
@@ -774,4 +774,13 @@ public class TestAdmin2 {
     // Current state should be the original state again
     assertEquals(initialState, admin.isNormalizerEnabled());
   }
+
+  @Test(timeout = 30000)
+  public void testAbortProcedureFail() throws Exception {
+    Random randomGenerator = new Random();
+    long procId = randomGenerator.nextLong();
+
+    boolean abortResult = admin.abortProcedure(procId, true);
+    assertFalse(abortResult);
+  }
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/cbd4e5a1/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestCatalogJanitor.java
----------------------------------------------------------------------
diff --git 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestCatalogJanitor.java
 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestCatalogJanitor.java
index fbdf6a2..a19eaf4 100644
--- 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestCatalogJanitor.java
+++ 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestCatalogJanitor.java
@@ -402,6 +402,11 @@ public class TestCatalogJanitor {
     }
 
     @Override
+    public boolean abortProcedure(final long procId, final boolean 
mayInterruptIfRunning) {
+      return false;  //To change body of implemented methods use File | 
Settings | File Templates.
+    }
+
+    @Override
     public List<HTableDescriptor> listTableDescriptorsByNamespace(String name) 
throws IOException {
       return null;  //To change body of implemented methods use File | 
Settings | File Templates.
     }

http://git-wip-us.apache.org/repos/asf/hbase/blob/cbd4e5a1/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestProcedureAdmin.java
----------------------------------------------------------------------
diff --git 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestProcedureAdmin.java
 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestProcedureAdmin.java
new file mode 100644
index 0000000..eea22ce
--- /dev/null
+++ 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestProcedureAdmin.java
@@ -0,0 +1,186 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hbase.master.procedure;
+
+import java.util.Random;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.HRegionInfo;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
+import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility;
+import org.apache.hadoop.hbase.testclassification.MediumTests;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import static org.junit.Assert.*;
+
+@Category(MediumTests.class)
+public class TestProcedureAdmin {
+  private static final Log LOG = LogFactory.getLog(TestProcedureAdmin.class);
+
+  protected static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
+
+  private long nonceGroup = HConstants.NO_NONCE;
+  private long nonce = HConstants.NO_NONCE;
+
+  private static void setupConf(Configuration conf) {
+    conf.setInt(MasterProcedureConstants.MASTER_PROCEDURE_THREADS, 1);
+  }
+
+  @BeforeClass
+  public static void setupCluster() throws Exception {
+    setupConf(UTIL.getConfiguration());
+    UTIL.startMiniCluster(1);
+  }
+
+  @AfterClass
+  public static void cleanupTest() throws Exception {
+    try {
+      UTIL.shutdownMiniCluster();
+    } catch (Exception e) {
+      LOG.warn("failure shutting down cluster", e);
+    }
+  }
+
+  @Before
+  public void setup() throws Exception {
+    final ProcedureExecutor<MasterProcedureEnv> procExec = 
getMasterProcedureExecutor();
+    ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, false);
+    assertTrue("expected executor to be running", procExec.isRunning());
+
+    nonceGroup =
+        
MasterProcedureTestingUtility.generateNonceGroup(UTIL.getHBaseCluster().getMaster());
+    nonce = 
MasterProcedureTestingUtility.generateNonce(UTIL.getHBaseCluster().getMaster());
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    
ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(getMasterProcedureExecutor(),
 false);
+    for (HTableDescriptor htd: UTIL.getHBaseAdmin().listTables()) {
+      LOG.info("Tear down, remove table=" + htd.getTableName());
+      UTIL.deleteTable(htd.getTableName());
+    }
+  }
+
+  @Test(timeout=60000)
+  public void testAbortProcedureSuccess() throws Exception {
+    final TableName tableName = TableName.valueOf("testAbortProcedureSuccess");
+    final ProcedureExecutor<MasterProcedureEnv> procExec = 
getMasterProcedureExecutor();
+
+    MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f");
+    ProcedureTestingUtility.waitNoProcedureRunning(procExec);
+    ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
+    // Submit an abortable procedure
+    long procId = procExec.submitProcedure(
+        new DisableTableProcedure(procExec.getEnvironment(), tableName, 
false), nonceGroup, nonce);
+
+    boolean abortResult = procExec.abort(procId, true);
+    assertTrue(abortResult);
+
+    ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, false);
+    ProcedureTestingUtility.restart(procExec);
+    ProcedureTestingUtility.waitNoProcedureRunning(procExec);
+    // Validate the disable table procedure was aborted successfully
+    MasterProcedureTestingUtility.validateTableIsEnabled(
+      UTIL.getHBaseCluster().getMaster(),
+      tableName);
+  }
+
+  @Test(timeout=60000)
+  public void testAbortProcedureFailure() throws Exception {
+    final TableName tableName = TableName.valueOf("testAbortProcedureFailure");
+    final ProcedureExecutor<MasterProcedureEnv> procExec = 
getMasterProcedureExecutor();
+
+    HRegionInfo[] regions =
+        MasterProcedureTestingUtility.createTable(procExec, tableName, null, 
"f");
+    UTIL.getHBaseAdmin().disableTable(tableName);
+    ProcedureTestingUtility.waitNoProcedureRunning(procExec);
+    ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
+    // Submit an un-abortable procedure
+    long procId = procExec.submitProcedure(
+        new DeleteTableProcedure(procExec.getEnvironment(), tableName), 
nonceGroup, nonce);
+
+    boolean abortResult = procExec.abort(procId, true);
+    assertFalse(abortResult);
+
+    ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, false);
+    ProcedureTestingUtility.restart(procExec);
+    ProcedureTestingUtility.waitNoProcedureRunning(procExec);
+    ProcedureTestingUtility.assertProcNotFailed(procExec, procId);
+    // Validate the delete table procedure was not aborted
+    MasterProcedureTestingUtility.validateTableDeletion(
+      UTIL.getHBaseCluster().getMaster(), tableName, regions, "f");
+  }
+
+  @Test(timeout=60000)
+  public void testAbortProcedureInterruptedNotAllowed() throws Exception {
+    final TableName tableName = 
TableName.valueOf("testAbortProcedureInterruptedNotAllowed");
+    final ProcedureExecutor<MasterProcedureEnv> procExec = 
getMasterProcedureExecutor();
+
+    HRegionInfo[] regions =
+        MasterProcedureTestingUtility.createTable(procExec, tableName, null, 
"f");
+    ProcedureTestingUtility.waitNoProcedureRunning(procExec);
+    ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
+    // Submit a procedure
+    long procId = procExec.submitProcedure(
+        new DisableTableProcedure(procExec.getEnvironment(), tableName, true), 
nonceGroup, nonce);
+    // Wait for one step to complete
+    ProcedureTestingUtility.waitProcedure(procExec, procId);
+
+    // Set the mayInterruptIfRunning flag to false
+    boolean abortResult = procExec.abort(procId, false);
+    assertFalse(abortResult);
+
+    ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, false);
+    ProcedureTestingUtility.restart(procExec);
+    ProcedureTestingUtility.waitNoProcedureRunning(procExec);
+    ProcedureTestingUtility.assertProcNotFailed(procExec, procId);
+    // Validate the delete table procedure was not aborted
+    MasterProcedureTestingUtility.validateTableIsDisabled(
+      UTIL.getHBaseCluster().getMaster(), tableName);
+  }
+
+  @Test(timeout=60000)
+  public void testAbortNonExistProcedure() throws Exception {
+    final ProcedureExecutor<MasterProcedureEnv> procExec = 
getMasterProcedureExecutor();
+    Random randomGenerator = new Random();
+    long procId;
+    // Generate a non-existing procedure
+    do {
+      procId = randomGenerator.nextLong();
+    } while (procExec.getResult(procId) != null);
+
+    boolean abortResult = procExec.abort(procId, true);
+    assertFalse(abortResult);
+  }
+
+  private ProcedureExecutor<MasterProcedureEnv> getMasterProcedureExecutor() {
+    return UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor();
+  }
+}

Reply via email to