You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by mb...@apache.org on 2016/09/02 04:24:14 UTC

[2/2] hbase git commit: HBASE-16507 Procedure v2 - Force DDL operation to always roll forward

HBASE-16507 Procedure v2 - Force DDL operation to always roll forward


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

Branch: refs/heads/master
Commit: f6ccae350203ec35f3b7acd75431a5abd7e9f5a8
Parents: 5c7fa12
Author: Matteo Bertozzi <ma...@cloudera.com>
Authored: Thu Sep 1 21:06:32 2016 -0700
Committer: Matteo Bertozzi <ma...@cloudera.com>
Committed: Thu Sep 1 21:06:32 2016 -0700

----------------------------------------------------------------------
 .../hbase/procedure2/StateMachineProcedure.java |  31 +-
 .../procedure/AddColumnFamilyProcedure.java     |  69 ++---
 .../procedure/CloneSnapshotProcedure.java       |  73 ++---
 .../procedure/CreateNamespaceProcedure.java     | 108 ++-----
 .../master/procedure/CreateTableProcedure.java  |  75 ++---
 .../procedure/DeleteColumnFamilyProcedure.java  |  90 ++----
 .../procedure/DeleteNamespaceProcedure.java     |  69 ++---
 .../master/procedure/DeleteTableProcedure.java  |  23 +-
 .../master/procedure/DisableTableProcedure.java |  51 +--
 .../master/procedure/EnableTableProcedure.java  |  73 ++---
 .../procedure/ModifyColumnFamilyProcedure.java  |  66 ++--
 .../procedure/ModifyNamespaceProcedure.java     |  83 ++---
 .../master/procedure/ModifyTableProcedure.java  |  91 ++----
 .../procedure/RestoreSnapshotProcedure.java     |  38 ++-
 .../procedure/TruncateTableProcedure.java       |  17 +-
 .../MasterProcedureTestingUtility.java          | 308 +++++++++----------
 .../procedure/TestAddColumnFamilyProcedure.java |  11 +-
 .../procedure/TestCloneSnapshotProcedure.java   |  21 +-
 .../procedure/TestCreateNamespaceProcedure.java |  14 +-
 .../procedure/TestCreateTableProcedure.java     |  68 +---
 .../TestDeleteColumnFamilyProcedure.java        |  50 +--
 .../procedure/TestDeleteNamespaceProcedure.java |  15 +-
 .../procedure/TestDeleteTableProcedure.java     |   3 +-
 .../procedure/TestDisableTableProcedure.java    |   6 +-
 .../TestDispatchMergingRegionsProcedure.java    |  14 +-
 .../procedure/TestEnableTableProcedure.java     |  14 +-
 .../TestModifyColumnFamilyProcedure.java        |  18 +-
 .../procedure/TestModifyNamespaceProcedure.java |  15 +-
 .../procedure/TestModifyTableProcedure.java     |  66 +---
 .../master/procedure/TestProcedureAdmin.java    |   7 +-
 .../procedure/TestRestoreSnapshotProcedure.java |   6 +-
 .../procedure/TestTruncateTableProcedure.java   |   5 +-
 32 files changed, 523 insertions(+), 1075 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/f6ccae35/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/StateMachineProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/StateMachineProcedure.java b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/StateMachineProcedure.java
index a403193..7eb6465 100644
--- a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/StateMachineProcedure.java
+++ b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/StateMachineProcedure.java
@@ -21,9 +21,12 @@ package org.apache.hadoop.hbase.procedure2;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.ArrayList;
 import java.util.Arrays;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.classification.InterfaceStability;
 import org.apache.hadoop.hbase.protobuf.generated.ProcedureProtos.StateMachineProcedureData;
@@ -43,6 +46,10 @@ import org.apache.hadoop.hbase.protobuf.generated.ProcedureProtos.StateMachinePr
 @InterfaceStability.Evolving
 public abstract class StateMachineProcedure<TEnvironment, TState>
     extends Procedure<TEnvironment> {
+  private static final Log LOG = LogFactory.getLog(StateMachineProcedure.class);
+
+  private final AtomicBoolean aborted = new AtomicBoolean(false);
+
   private Flow stateFlow = Flow.HAS_MORE_STATE;
   private int stateCount = 0;
   private int[] states = null;
@@ -96,6 +103,9 @@ public abstract class StateMachineProcedure<TEnvironment, TState>
    * @param state the state enum object
    */
   protected void setNextState(final TState state) {
+    if (aborted.get() && isRollbackSupported(getCurrentState())) {
+      setAbortFailure(getClass().getSimpleName(), "abort requested");
+    }
     setNextState(getStateId(state));
   }
 
@@ -129,7 +139,7 @@ public abstract class StateMachineProcedure<TEnvironment, TState>
       throws ProcedureSuspendedException, ProcedureYieldException, InterruptedException {
     updateTimestamp();
     try {
-      if (!hasMoreState()) return null;
+      if (!hasMoreState() || isFailed()) return null;
 
       TState state = getCurrentState();
       if (stateCount == 0) {
@@ -163,6 +173,25 @@ public abstract class StateMachineProcedure<TEnvironment, TState>
   }
 
   @Override
+  protected boolean abort(final TEnvironment env) {
+    final TState state = getCurrentState();
+    if (isRollbackSupported(state)) {
+      LOG.debug("abort requested for " + getClass().getSimpleName() + " state=" + state);
+      aborted.set(true);
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * Used by the default implementation of abort() to know if the current state can be aborted
+   * and rollback can be triggered.
+   */
+  protected boolean isRollbackSupported(final TState state) {
+    return false;
+  }
+
+  @Override
   protected boolean isYieldAfterExecutionStep(final TEnvironment env) {
     return isYieldBeforeExecuteFromState(env, getCurrentState());
   }

http://git-wip-us.apache.org/repos/asf/hbase/blob/f6ccae35/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/AddColumnFamilyProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/AddColumnFamilyProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/AddColumnFamilyProcedure.java
index 7c0b691..237db1a 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/AddColumnFamilyProcedure.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/AddColumnFamilyProcedure.java
@@ -22,7 +22,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -49,8 +48,6 @@ public class AddColumnFamilyProcedure
     implements TableProcedureInterface {
   private static final Log LOG = LogFactory.getLog(AddColumnFamilyProcedure.class);
 
-  private final AtomicBoolean aborted = new AtomicBoolean(false);
-
   private TableName tableName;
   private HTableDescriptor unmodifiedHTableDescriptor;
   private HColumnDescriptor cfDescriptor;
@@ -118,10 +115,12 @@ public class AddColumnFamilyProcedure
         throw new UnsupportedOperationException(this + " unhandled state=" + state);
       }
     } catch (IOException e) {
-      LOG.warn("Error trying to add the column family" + getColumnFamilyName() + " to the table "
-          + tableName + " (in state=" + state + ")", e);
-
-      setFailure("master-add-columnfamily", e);
+      if (isRollbackSupported(state)) {
+        setFailure("master-add-columnfamily", e);
+      } else {
+        LOG.warn("Retriable error trying to add the column family " + getColumnFamilyName() +
+          " to the table " + tableName + " (in state=" + state + ")", e);
+      }
     }
     return Flow.HAS_MORE_STATE;
   }
@@ -129,33 +128,26 @@ public class AddColumnFamilyProcedure
   @Override
   protected void rollbackState(final MasterProcedureEnv env, final AddColumnFamilyState state)
       throws IOException {
-    if (isTraceEnabled()) {
-      LOG.trace(this + " rollback state=" + state);
+    if (state == AddColumnFamilyState.ADD_COLUMN_FAMILY_PREPARE ||
+        state == AddColumnFamilyState.ADD_COLUMN_FAMILY_PRE_OPERATION) {
+      // nothing to rollback, pre is just table-state checks.
+      // We can fail if the table does not exist or is not disabled.
+      // TODO: coprocessor rollback semantic is still undefined.
+      return;
     }
-    try {
-      switch (state) {
-      case ADD_COLUMN_FAMILY_REOPEN_ALL_REGIONS:
-        break; // Nothing to undo.
-      case ADD_COLUMN_FAMILY_POST_OPERATION:
-        // TODO-MAYBE: call the coprocessor event to undo?
-        break;
-      case ADD_COLUMN_FAMILY_UPDATE_TABLE_DESCRIPTOR:
-        restoreTableDescriptor(env);
-        break;
-      case ADD_COLUMN_FAMILY_PRE_OPERATION:
-        // TODO-MAYBE: call the coprocessor event to undo?
-        break;
+
+    // The procedure doesn't have a rollback. The execution will succeed, at some point.
+    throw new UnsupportedOperationException("unhandled state=" + state);
+  }
+
+  @Override
+  protected boolean isRollbackSupported(final AddColumnFamilyState state) {
+    switch (state) {
       case ADD_COLUMN_FAMILY_PREPARE:
-        break; // nothing to do
+      case ADD_COLUMN_FAMILY_PRE_OPERATION:
+        return true;
       default:
-        throw new UnsupportedOperationException(this + " unhandled state=" + state);
-      }
-    } catch (IOException e) {
-      // This will be retried. Unless there is a bug in the code,
-      // this should be just a "temporary error" (e.g. network down)
-      LOG.warn("Failed rollback attempt step " + state + " for adding the column family"
-          + getColumnFamilyName() + " to the table " + tableName, e);
-      throw e;
+        return false;
     }
   }
 
@@ -180,21 +172,6 @@ public class AddColumnFamilyProcedure
   }
 
   @Override
-  protected void setNextState(AddColumnFamilyState state) {
-    if (aborted.get()) {
-      setAbortFailure("add-columnfamily", "abort requested");
-    } else {
-      super.setNextState(state);
-    }
-  }
-
-  @Override
-  public boolean abort(final MasterProcedureEnv env) {
-    aborted.set(true);
-    return true;
-  }
-
-  @Override
   protected boolean acquireLock(final MasterProcedureEnv env) {
     if (env.waitInitialized(this)) return false;
     return env.getProcedureQueue().tryAcquireTableExclusiveLock(this, tableName);

http://git-wip-us.apache.org/repos/asf/hbase/blob/f6ccae35/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CloneSnapshotProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CloneSnapshotProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CloneSnapshotProcedure.java
index 1212072..331faed 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CloneSnapshotProcedure.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CloneSnapshotProcedure.java
@@ -27,7 +27,6 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -72,8 +71,6 @@ public class CloneSnapshotProcedure
     implements TableProcedureInterface {
   private static final Log LOG = LogFactory.getLog(CloneSnapshotProcedure.class);
 
-  private final AtomicBoolean aborted = new AtomicBoolean(false);
-
   private User user;
   private HTableDescriptor hTableDescriptor;
   private SnapshotDescription snapshot;
@@ -162,8 +159,12 @@ public class CloneSnapshotProcedure
           throw new UnsupportedOperationException("unhandled state=" + state);
       }
     } catch (IOException e) {
-      LOG.error("Error trying to create table=" + getTableName() + " state=" + state, e);
-      setFailure("master-create-table", e);
+      if (isRollbackSupported(state)) {
+        setFailure("master-clone-snapshot", e);
+      } else {
+        LOG.warn("Retriable error trying to clone snapshot=" + snapshot.getName() +
+          " to table=" + getTableName() + " state=" + state, e);
+      }
     }
     return Flow.HAS_MORE_STATE;
   }
@@ -171,38 +172,23 @@ public class CloneSnapshotProcedure
   @Override
   protected void rollbackState(final MasterProcedureEnv env, final CloneSnapshotState state)
       throws IOException {
-    if (isTraceEnabled()) {
-      LOG.trace(this + " rollback state=" + state);
+    if (state == CloneSnapshotState.CLONE_SNAPSHOT_PRE_OPERATION) {
+      DeleteTableProcedure.deleteTableStates(env, getTableName());
+      // TODO-MAYBE: call the deleteTable coprocessor event?
+      return;
     }
-    try {
-      switch (state) {
-        case CLONE_SNAPSHOT_POST_OPERATION:
-          // TODO-MAYBE: call the deleteTable coprocessor event?
-          break;
-        case CLONE_SNAPSHOT_UPDATE_DESC_CACHE:
-          DeleteTableProcedure.deleteTableDescriptorCache(env, getTableName());
-          break;
-        case CLONE_SNAPSHOT_ASSIGN_REGIONS:
-          DeleteTableProcedure.deleteAssignmentState(env, getTableName());
-          break;
-        case CLONE_SNAPSHOT_ADD_TO_META:
-          DeleteTableProcedure.deleteFromMeta(env, getTableName(), newRegions);
-          break;
-        case CLONE_SNAPSHOT_WRITE_FS_LAYOUT:
-          DeleteTableProcedure.deleteFromFs(env, getTableName(), newRegions, false);
-          break;
-        case CLONE_SNAPSHOT_PRE_OPERATION:
-          DeleteTableProcedure.deleteTableStates(env, getTableName());
-          // TODO-MAYBE: call the deleteTable coprocessor event?
-          break;
-        default:
-          throw new UnsupportedOperationException("unhandled state=" + state);
-      }
-    } catch (IOException e) {
-      // This will be retried. Unless there is a bug in the code,
-      // this should be just a "temporary error" (e.g. network down)
-      LOG.warn("Failed rollback attempt step=" + state + " table=" + getTableName(), e);
-      throw e;
+
+    // The procedure doesn't have a rollback. The execution will succeed, at some point.
+    throw new UnsupportedOperationException("unhandled state=" + state);
+  }
+
+  @Override
+  protected boolean isRollbackSupported(final CloneSnapshotState state) {
+    switch (state) {
+      case CLONE_SNAPSHOT_PRE_OPERATION:
+        return true;
+      default:
+        return false;
     }
   }
 
@@ -222,15 +208,6 @@ public class CloneSnapshotProcedure
   }
 
   @Override
-  protected void setNextState(final CloneSnapshotState state) {
-    if (aborted.get()) {
-      setAbortFailure("clone-snapshot", "abort requested");
-    } else {
-      super.setNextState(state);
-    }
-  }
-
-  @Override
   public TableName getTableName() {
     return hTableDescriptor.getTableName();
   }
@@ -241,12 +218,6 @@ public class CloneSnapshotProcedure
   }
 
   @Override
-  public boolean abort(final MasterProcedureEnv env) {
-    aborted.set(true);
-    return true;
-  }
-
-  @Override
   public void toStringClassDetails(StringBuilder sb) {
     sb.append(getClass().getSimpleName());
     sb.append(" (table=");

http://git-wip-us.apache.org/repos/asf/hbase/blob/f6ccae35/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateNamespaceProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateNamespaceProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateNamespaceProcedure.java
index 7c8bf9c..1937528 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateNamespaceProcedure.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateNamespaceProcedure.java
@@ -21,7 +21,6 @@ package org.apache.hadoop.hbase.master.procedure;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -46,8 +45,6 @@ public class CreateNamespaceProcedure
     implements TableProcedureInterface {
   private static final Log LOG = LogFactory.getLog(CreateNamespaceProcedure.class);
 
-  private final AtomicBoolean aborted = new AtomicBoolean(false);
-
   private NamespaceDescriptor nsDescriptor;
   private Boolean traceEnabled;
 
@@ -94,10 +91,12 @@ public class CreateNamespaceProcedure
         throw new UnsupportedOperationException(this + " unhandled state=" + state);
       }
     } catch (IOException e) {
-      LOG.warn("Error trying to create the namespace" + nsDescriptor.getName()
-        + " (in state=" + state + ")", e);
-
-      setFailure("master-create-namespace", e);
+      if (isRollbackSupported(state)) {
+        setFailure("master-create-namespace", e);
+      } else {
+        LOG.warn("Retriable error trying to create namespace=" + nsDescriptor.getName() +
+          " (in state=" + state + ")", e);
+      }
     }
     return Flow.HAS_MORE_STATE;
   }
@@ -105,34 +104,22 @@ public class CreateNamespaceProcedure
   @Override
   protected void rollbackState(final MasterProcedureEnv env, final CreateNamespaceState state)
       throws IOException {
-    if (isTraceEnabled()) {
-      LOG.trace(this + " rollback state=" + state);
+    if (state == CreateNamespaceState.CREATE_NAMESPACE_PREPARE) {
+      // nothing to rollback, pre-create is just state checks.
+      // TODO: coprocessor rollback semantic is still undefined.
+      return;
     }
-    try {
-      switch (state) {
-      case CREATE_NAMESPACE_SET_NAMESPACE_QUOTA:
-        rollbackSetNamespaceQuota(env);
-        break;
-      case CREATE_NAMESPACE_UPDATE_ZK:
-        rollbackZKNamespaceManagerChange(env);
-        break;
-      case CREATE_NAMESPACE_INSERT_INTO_NS_TABLE:
-        rollbackInsertIntoNSTable(env);
-        break;
-      case CREATE_NAMESPACE_CREATE_DIRECTORY:
-        rollbackCreateDirectory(env);
-        break;
+    // The procedure doesn't have a rollback. The execution will succeed, at some point.
+    throw new UnsupportedOperationException("unhandled state=" + state);
+  }
+
+  @Override
+  protected boolean isRollbackSupported(final CreateNamespaceState state) {
+    switch (state) {
       case CREATE_NAMESPACE_PREPARE:
-        break; // nothing to do
+        return true;
       default:
-        throw new UnsupportedOperationException(this + " unhandled state=" + state);
-      }
-    } catch (IOException e) {
-      // This will be retried. Unless there is a bug in the code,
-      // this should be just a "temporary error" (e.g. network down)
-      LOG.warn("Failed rollback attempt step " + state + " for creating the namespace "
-          + nsDescriptor.getName(), e);
-      throw e;
+        return false;
     }
   }
 
@@ -152,21 +139,6 @@ public class CreateNamespaceProcedure
   }
 
   @Override
-  protected void setNextState(CreateNamespaceState state) {
-    if (aborted.get()) {
-      setAbortFailure("create-namespace", "abort requested");
-    } else {
-      super.setNextState(state);
-    }
-  }
-
-  @Override
-  public boolean abort(final MasterProcedureEnv env) {
-    aborted.set(true);
-    return true;
-  }
-
-  @Override
   public void serializeStateData(final OutputStream stream) throws IOException {
     super.serializeStateData(stream);
 
@@ -257,20 +229,6 @@ public class CreateNamespaceProcedure
   }
 
   /**
-   * undo create directory
-   * @param env MasterProcedureEnv
-   * @throws IOException
-   */
-  private void rollbackCreateDirectory(final MasterProcedureEnv env) throws IOException {
-    try {
-      DeleteNamespaceProcedure.deleteDirectory(env, nsDescriptor.getName());
-    } catch (Exception e) {
-      // Ignore exception
-      LOG.debug("Rollback of createDirectory throws exception: " + e);
-    }
-  }
-
-  /**
    * Insert the row into ns table
    * @param env MasterProcedureEnv
    * @param nsDescriptor NamespaceDescriptor
@@ -283,20 +241,6 @@ public class CreateNamespaceProcedure
   }
 
   /**
-   * Undo the insert.
-   * @param env MasterProcedureEnv
-   * @throws IOException
-   */
-  private void rollbackInsertIntoNSTable(final MasterProcedureEnv env) throws IOException {
-    try {
-      DeleteNamespaceProcedure.deleteFromNSTable(env, nsDescriptor.getName());
-    } catch (Exception e) {
-      // Ignore exception
-      LOG.debug("Rollback of insertIntoNSTable throws exception: " + e);
-    }
-  }
-
-  /**
    * Update ZooKeeper.
    * @param env MasterProcedureEnv
    * @param nsDescriptor NamespaceDescriptor
@@ -309,20 +253,6 @@ public class CreateNamespaceProcedure
   }
 
   /**
-   * rollback ZooKeeper update.
-   * @param env MasterProcedureEnv
-   * @throws IOException
-   */
-  private void rollbackZKNamespaceManagerChange(final MasterProcedureEnv env) throws IOException {
-    try {
-      DeleteNamespaceProcedure.removeFromZKNamespaceManager(env, nsDescriptor.getName());
-    } catch (Exception e) {
-      // Ignore exception
-      LOG.debug("Rollback of updateZKNamespaceManager throws exception: " + e);
-    }
-  }
-
-  /**
    * Set quota for the namespace
    * @param env MasterProcedureEnv
    * @param nsDescriptor NamespaceDescriptor

http://git-wip-us.apache.org/repos/asf/hbase/blob/f6ccae35/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java
index ae8d2fb..f77c249 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java
@@ -24,7 +24,6 @@ import java.io.IOException;
 import java.security.PrivilegedExceptionAction;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -61,8 +60,6 @@ public class CreateTableProcedure
     implements TableProcedureInterface {
   private static final Log LOG = LogFactory.getLog(CreateTableProcedure.class);
 
-  private final AtomicBoolean aborted = new AtomicBoolean(false);
-
   // used for compatibility with old clients
   private final ProcedurePrepareLatch syncLatch;
 
@@ -137,8 +134,11 @@ public class CreateTableProcedure
           throw new UnsupportedOperationException("unhandled state=" + state);
       }
     } catch (IOException e) {
-      LOG.error("Error trying to create table=" + getTableName() + " state=" + state, e);
-      setFailure("master-create-table", e);
+      if (isRollbackSupported(state)) {
+        setFailure("master-create-table", e);
+      } else {
+        LOG.warn("Retriable error trying to create table=" + getTableName() + " state=" + state, e);
+      }
     }
     return Flow.HAS_MORE_STATE;
   }
@@ -146,38 +146,26 @@ public class CreateTableProcedure
   @Override
   protected void rollbackState(final MasterProcedureEnv env, final CreateTableState state)
       throws IOException {
-    if (LOG.isTraceEnabled()) {
-      LOG.trace(this + " rollback state=" + state);
+    if (state == CreateTableState.CREATE_TABLE_PRE_OPERATION) {
+      // nothing to rollback, pre-create is just table-state checks.
+      // We can fail if the table does exist or the descriptor is malformed.
+      // TODO: coprocessor rollback semantic is still undefined.
+      DeleteTableProcedure.deleteTableStates(env, getTableName());
+      ProcedurePrepareLatch.releaseLatch(syncLatch, this);
+      return;
     }
-    try {
-      switch (state) {
-        case CREATE_TABLE_POST_OPERATION:
-          break;
-        case CREATE_TABLE_UPDATE_DESC_CACHE:
-          DeleteTableProcedure.deleteTableDescriptorCache(env, getTableName());
-          break;
-        case CREATE_TABLE_ASSIGN_REGIONS:
-          DeleteTableProcedure.deleteAssignmentState(env, getTableName());
-          break;
-        case CREATE_TABLE_ADD_TO_META:
-          DeleteTableProcedure.deleteFromMeta(env, getTableName(), newRegions);
-          break;
-        case CREATE_TABLE_WRITE_FS_LAYOUT:
-          DeleteTableProcedure.deleteFromFs(env, getTableName(), newRegions, false);
-          break;
-        case CREATE_TABLE_PRE_OPERATION:
-          DeleteTableProcedure.deleteTableStates(env, getTableName());
-          // TODO-MAYBE: call the deleteTable coprocessor event?
-          ProcedurePrepareLatch.releaseLatch(syncLatch, this);
-          break;
-        default:
-          throw new UnsupportedOperationException("unhandled state=" + state);
-      }
-    } catch (IOException e) {
-      // This will be retried. Unless there is a bug in the code,
-      // this should be just a "temporary error" (e.g. network down)
-      LOG.warn("Failed rollback attempt step=" + state + " table=" + getTableName(), e);
-      throw e;
+
+    // The procedure doesn't have a rollback. The execution will succeed, at some point.
+    throw new UnsupportedOperationException("unhandled state=" + state);
+  }
+
+  @Override
+  protected boolean isRollbackSupported(final CreateTableState state) {
+    switch (state) {
+      case CREATE_TABLE_PRE_OPERATION:
+        return true;
+      default:
+        return false;
     }
   }
 
@@ -197,15 +185,6 @@ public class CreateTableProcedure
   }
 
   @Override
-  protected void setNextState(final CreateTableState state) {
-    if (aborted.get()) {
-      setAbortFailure("create-table", "abort requested");
-    } else {
-      super.setNextState(state);
-    }
-  }
-
-  @Override
   public TableName getTableName() {
     return hTableDescriptor.getTableName();
   }
@@ -216,12 +195,6 @@ public class CreateTableProcedure
   }
 
   @Override
-  public boolean abort(final MasterProcedureEnv env) {
-    aborted.set(true);
-    return true;
-  }
-
-  @Override
   public void toStringClassDetails(StringBuilder sb) {
     sb.append(getClass().getSimpleName());
     sb.append(" (table=");

http://git-wip-us.apache.org/repos/asf/hbase/blob/f6ccae35/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteColumnFamilyProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteColumnFamilyProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteColumnFamilyProcedure.java
index 9df9c0d..00a1c70 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteColumnFamilyProcedure.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteColumnFamilyProcedure.java
@@ -23,7 +23,6 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.security.PrivilegedExceptionAction;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -51,8 +50,6 @@ public class DeleteColumnFamilyProcedure
     implements TableProcedureInterface {
   private static final Log LOG = LogFactory.getLog(DeleteColumnFamilyProcedure.class);
 
-  private final AtomicBoolean aborted = new AtomicBoolean(false);
-
   private HTableDescriptor unmodifiedHTableDescriptor;
   private TableName tableName;
   private byte [] familyName;
@@ -125,14 +122,11 @@ public class DeleteColumnFamilyProcedure
         throw new UnsupportedOperationException(this + " unhandled state=" + state);
       }
     } catch (IOException e) {
-      if (!isRollbackSupported(state)) {
-        // We reach a state that cannot be rolled back. We just need to keep retry.
-        LOG.warn("Error trying to delete the column family " + getColumnFamilyName()
-          + " from table " + tableName + "(in state=" + state + ")", e);
+      if (isRollbackSupported(state)) {
+        setFailure("master-delete-columnfamily", e);
       } else {
-        LOG.error("Error trying to delete the column family " + getColumnFamilyName()
-          + " from table " + tableName + "(in state=" + state + ")", e);
-        setFailure("master-delete-column-family", e);
+        LOG.warn("Retriable error trying to delete the column family " + getColumnFamilyName() +
+          " from table " + tableName + " (in state=" + state + ")", e);
       }
     }
     return Flow.HAS_MORE_STATE;
@@ -141,39 +135,26 @@ public class DeleteColumnFamilyProcedure
   @Override
   protected void rollbackState(final MasterProcedureEnv env, final DeleteColumnFamilyState state)
       throws IOException {
-    if (isTraceEnabled()) {
-      LOG.trace(this + " rollback state=" + state);
+    if (state == DeleteColumnFamilyState.DELETE_COLUMN_FAMILY_PREPARE ||
+        state == DeleteColumnFamilyState.DELETE_COLUMN_FAMILY_PRE_OPERATION) {
+      // nothing to rollback, pre is just table-state checks.
+      // We can fail if the table does not exist or is not disabled.
+      // TODO: coprocessor rollback semantic is still undefined.
+      return;
     }
-    try {
-      switch (state) {
-      case DELETE_COLUMN_FAMILY_REOPEN_ALL_REGIONS:
-        break; // Nothing to undo.
-      case DELETE_COLUMN_FAMILY_POST_OPERATION:
-        // TODO-MAYBE: call the coprocessor event to undo?
-        break;
-      case DELETE_COLUMN_FAMILY_DELETE_FS_LAYOUT:
-        // Once we reach to this state - we could NOT rollback - as it is tricky to undelete
-        // the deleted files. We are not suppose to reach here, throw exception so that we know
-        // there is a code bug to investigate.
-        throw new UnsupportedOperationException(this + " rollback of state=" + state
-            + " is unsupported.");
-      case DELETE_COLUMN_FAMILY_UPDATE_TABLE_DESCRIPTOR:
-        restoreTableDescriptor(env);
-        break;
+
+    // The procedure doesn't have a rollback. The execution will succeed, at some point.
+    throw new UnsupportedOperationException("unhandled state=" + state);
+  }
+
+  @Override
+  protected boolean isRollbackSupported(final DeleteColumnFamilyState state) {
+    switch (state) {
       case DELETE_COLUMN_FAMILY_PRE_OPERATION:
-        // TODO-MAYBE: call the coprocessor event to undo?
-        break;
       case DELETE_COLUMN_FAMILY_PREPARE:
-        break; // nothing to do
+        return true;
       default:
-        throw new UnsupportedOperationException(this + " unhandled state=" + state);
-      }
-    } catch (IOException e) {
-      // This will be retried. Unless there is a bug in the code,
-      // this should be just a "temporary error" (e.g. network down)
-      LOG.warn("Failed rollback attempt step " + state + " for deleting the column family"
-          + getColumnFamilyName() + " to the table " + tableName, e);
-      throw e;
+        return false;
     }
   }
 
@@ -198,21 +179,6 @@ public class DeleteColumnFamilyProcedure
   }
 
   @Override
-  protected void setNextState(DeleteColumnFamilyState state) {
-    if (aborted.get() && isRollbackSupported(state)) {
-      setAbortFailure("delete-columnfamily", "abort requested");
-    } else {
-      super.setNextState(state);
-    }
-  }
-
-  @Override
-  public boolean abort(final MasterProcedureEnv env) {
-    aborted.set(true);
-    return true;
-  }
-
-  @Override
   protected boolean acquireLock(final MasterProcedureEnv env) {
     if (env.waitInitialized(this)) return false;
     return env.getProcedureQueue().tryAcquireTableExclusiveLock(this, tableName);
@@ -429,22 +395,6 @@ public class DeleteColumnFamilyProcedure
     }
   }
 
-  /*
-   * Check whether we are in the state that can be rollback
-   */
-  private boolean isRollbackSupported(final DeleteColumnFamilyState state) {
-    switch (state) {
-    case DELETE_COLUMN_FAMILY_REOPEN_ALL_REGIONS:
-    case DELETE_COLUMN_FAMILY_POST_OPERATION:
-    case DELETE_COLUMN_FAMILY_DELETE_FS_LAYOUT:
-        // It is not safe to rollback if we reach to these states.
-        return false;
-      default:
-        break;
-    }
-    return true;
-  }
-
   private List<HRegionInfo> getRegionInfoList(final MasterProcedureEnv env) throws IOException {
     if (regionInfoList == null) {
       regionInfoList = ProcedureSyncWait.getRegionsFromMeta(env, getTableName());

http://git-wip-us.apache.org/repos/asf/hbase/blob/f6ccae35/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteNamespaceProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteNamespaceProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteNamespaceProcedure.java
index 3f4de12..8333919 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteNamespaceProcedure.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteNamespaceProcedure.java
@@ -22,7 +22,6 @@ import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -52,8 +51,6 @@ public class DeleteNamespaceProcedure
     implements TableProcedureInterface {
   private static final Log LOG = LogFactory.getLog(DeleteNamespaceProcedure.class);
 
-  private final AtomicBoolean aborted = new AtomicBoolean(false);
-
   private NamespaceDescriptor nsDescriptor;
   private String namespaceName;
   private Boolean traceEnabled;
@@ -76,6 +73,7 @@ public class DeleteNamespaceProcedure
     if (isTraceEnabled()) {
       LOG.trace(this + " execute state=" + state);
     }
+    LOG.info(this + " execute state=" + state);
 
     try {
       switch (state) {
@@ -102,10 +100,12 @@ public class DeleteNamespaceProcedure
         throw new UnsupportedOperationException(this + " unhandled state=" + state);
       }
     } catch (IOException e) {
-      LOG.warn("Error trying to delete the namespace " + namespaceName
-        + " (in state=" + state + ")", e);
-
-      setFailure("master-delete-namespace", e);
+      if (isRollbackSupported(state)) {
+        setFailure("master-delete-namespace", e);
+      } else {
+        LOG.warn("Retriable error trying to delete namespace " + namespaceName +
+          " (in state=" + state + ")", e);
+      }
     }
     return Flow.HAS_MORE_STATE;
   }
@@ -113,34 +113,24 @@ public class DeleteNamespaceProcedure
   @Override
   protected void rollbackState(final MasterProcedureEnv env, final DeleteNamespaceState state)
       throws IOException {
-    if (isTraceEnabled()) {
-      LOG.trace(this + " rollback state=" + state);
+    if (state == DeleteNamespaceState.DELETE_NAMESPACE_PREPARE) {
+      // nothing to rollback, pre is just table-state checks.
+      // We can fail if the table does not exist or is not disabled.
+      // TODO: coprocessor rollback semantic is still undefined.
+      return;
     }
-    try {
-      switch (state) {
-      case DELETE_NAMESPACE_REMOVE_NAMESPACE_QUOTA:
-        rollbacRemoveNamespaceQuota(env);
-        break;
-      case DELETE_NAMESPACE_DELETE_DIRECTORIES:
-        rollbackDeleteDirectory(env);
-        break;
-      case DELETE_NAMESPACE_REMOVE_FROM_ZK:
-        undoRemoveFromZKNamespaceManager(env);
-        break;
-      case DELETE_NAMESPACE_DELETE_FROM_NS_TABLE:
-        undoDeleteFromNSTable(env);
-        break;
+
+    // The procedure doesn't have a rollback. The execution will succeed, at some point.
+    throw new UnsupportedOperationException("unhandled state=" + state);
+  }
+
+  @Override
+  protected boolean isRollbackSupported(final DeleteNamespaceState state) {
+    switch (state) {
       case DELETE_NAMESPACE_PREPARE:
-        break; // nothing to do
+        return true;
       default:
-        throw new UnsupportedOperationException(this + " unhandled state=" + state);
-      }
-    } catch (IOException e) {
-      // This will be retried. Unless there is a bug in the code,
-      // this should be just a "temporary error" (e.g. network down)
-      LOG.warn("Failed rollback attempt step " + state + " for deleting the namespace "
-        + namespaceName, e);
-      throw e;
+        return false;
     }
   }
 
@@ -160,21 +150,6 @@ public class DeleteNamespaceProcedure
   }
 
   @Override
-  protected void setNextState(DeleteNamespaceState state) {
-    if (aborted.get()) {
-      setAbortFailure("delete-namespace", "abort requested");
-    } else {
-      super.setNextState(state);
-    }
-  }
-
-  @Override
-  public boolean abort(final MasterProcedureEnv env) {
-    aborted.set(true);
-    return true;
-  }
-
-  @Override
   public void serializeStateData(final OutputStream stream) throws IOException {
     super.serializeStateData(stream);
 

http://git-wip-us.apache.org/repos/asf/hbase/blob/f6ccae35/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java
index 64bdccc..d3b2aa5 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java
@@ -148,7 +148,11 @@ public class DeleteTableProcedure
           throw new UnsupportedOperationException("unhandled state=" + state);
       }
     } catch (HBaseException|IOException e) {
-      LOG.warn("Retriable error trying to delete table=" + getTableName() + " state=" + state, e);
+      if (isRollbackSupported(state)) {
+        setFailure("master-delete-table", e);
+      } else {
+        LOG.warn("Retriable error trying to delete table=" + getTableName() + " state=" + state, e);
+      }
     }
     return Flow.HAS_MORE_STATE;
   }
@@ -158,6 +162,7 @@ public class DeleteTableProcedure
     if (state == DeleteTableState.DELETE_TABLE_PRE_OPERATION) {
       // nothing to rollback, pre-delete is just table-state checks.
       // We can fail if the table does not exist or is not disabled.
+      // TODO: coprocessor rollback semantic is still undefined.
       ProcedurePrepareLatch.releaseLatch(syncLatch, this);
       return;
     }
@@ -167,6 +172,16 @@ public class DeleteTableProcedure
   }
 
   @Override
+  protected boolean isRollbackSupported(final DeleteTableState state) {
+    switch (state) {
+      case DELETE_TABLE_PRE_OPERATION:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  @Override
   protected DeleteTableState getState(final int stateId) {
     return DeleteTableState.valueOf(stateId);
   }
@@ -192,12 +207,6 @@ public class DeleteTableProcedure
   }
 
   @Override
-  public boolean abort(final MasterProcedureEnv env) {
-    // TODO: We may be able to abort if the procedure is not started yet.
-    return false;
-  }
-
-  @Override
   protected boolean acquireLock(final MasterProcedureEnv env) {
     if (env.waitInitialized(this)) return false;
     return env.getProcedureQueue().tryAcquireTableExclusiveLock(this, getTableName());

http://git-wip-us.apache.org/repos/asf/hbase/blob/f6ccae35/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DisableTableProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DisableTableProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DisableTableProcedure.java
index e2d7d16..c13f322 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DisableTableProcedure.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DisableTableProcedure.java
@@ -24,7 +24,6 @@ import java.io.OutputStream;
 import java.security.PrivilegedExceptionAction;
 import java.util.List;
 import java.util.concurrent.ExecutorService;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -57,8 +56,6 @@ public class DisableTableProcedure
     implements TableProcedureInterface {
   private static final Log LOG = LogFactory.getLog(DisableTableProcedure.class);
 
-  private final AtomicBoolean aborted = new AtomicBoolean(false);
-
   // This is for back compatible with 1.0 asynchronized operations.
   private final ProcedurePrepareLatch syncLatch;
 
@@ -157,7 +154,12 @@ public class DisableTableProcedure
         throw new UnsupportedOperationException("unhandled state=" + state);
       }
     } catch (IOException e) {
-      LOG.warn("Retriable error trying to disable table=" + tableName + " state=" + state, e);
+      if (isRollbackSupported(state)) {
+        setFailure("master-disable-table", e);
+      } else {
+        LOG.warn("Retriable error trying to disable table=" + tableName +
+          " (in state=" + state + ")", e);
+      }
     }
     return Flow.HAS_MORE_STATE;
   }
@@ -165,11 +167,16 @@ public class DisableTableProcedure
   @Override
   protected void rollbackState(final MasterProcedureEnv env, final DisableTableState state)
       throws IOException {
-    if (state == DisableTableState.DISABLE_TABLE_PREPARE) {
-      // nothing to rollback, prepare-disable is just table-state checks.
-      // We can fail if the table does not exist or is not disabled.
-      ProcedurePrepareLatch.releaseLatch(syncLatch, this);
-      return;
+    // nothing to rollback, prepare-disable is just table-state checks.
+    // We can fail if the table does not exist or is not disabled.
+    switch (state) {
+      case DISABLE_TABLE_PRE_OPERATION:
+        return;
+      case DISABLE_TABLE_PREPARE:
+        ProcedurePrepareLatch.releaseLatch(syncLatch, this);
+        return;
+      default:
+        break;
     }
 
     // The delete doesn't have a rollback. The execution will succeed, at some point.
@@ -177,6 +184,17 @@ public class DisableTableProcedure
   }
 
   @Override
+  protected boolean isRollbackSupported(final DisableTableState state) {
+    switch (state) {
+      case DISABLE_TABLE_PREPARE:
+      case DISABLE_TABLE_PRE_OPERATION:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  @Override
   protected DisableTableState getState(final int stateId) {
     return DisableTableState.valueOf(stateId);
   }
@@ -192,21 +210,6 @@ public class DisableTableProcedure
   }
 
   @Override
-  protected void setNextState(final DisableTableState state) {
-    if (aborted.get()) {
-      setAbortFailure("disable-table", "abort requested");
-    } else {
-      super.setNextState(state);
-    }
-  }
-
-  @Override
-  public boolean abort(final MasterProcedureEnv env) {
-    aborted.set(true);
-    return true;
-  }
-
-  @Override
   protected boolean acquireLock(final MasterProcedureEnv env) {
     if (env.waitInitialized(this)) return false;
     return env.getProcedureQueue().tryAcquireTableExclusiveLock(this, tableName);

http://git-wip-us.apache.org/repos/asf/hbase/blob/f6ccae35/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/EnableTableProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/EnableTableProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/EnableTableProcedure.java
index 1817a16..55a7103 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/EnableTableProcedure.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/EnableTableProcedure.java
@@ -26,7 +26,6 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -60,8 +59,6 @@ public class EnableTableProcedure
     implements TableProcedureInterface {
   private static final Log LOG = LogFactory.getLog(EnableTableProcedure.class);
 
-  private final AtomicBoolean aborted = new AtomicBoolean(false);
-
   // This is for back compatible with 1.0 asynchronized operations.
   private final ProcedurePrepareLatch syncLatch;
 
@@ -150,8 +147,12 @@ public class EnableTableProcedure
         throw new UnsupportedOperationException("unhandled state=" + state);
       }
     } catch (IOException e) {
-      LOG.error("Error trying to enable table=" + tableName + " state=" + state, e);
-      setFailure("master-enable-table", e);
+      if (isRollbackSupported(state)) {
+        setFailure("master-enable-table", e);
+      } else {
+        LOG.warn("Retriable error trying to enable table=" + tableName +
+          " (in state=" + state + ")", e);
+      }
     }
     return Flow.HAS_MORE_STATE;
   }
@@ -159,39 +160,30 @@ public class EnableTableProcedure
   @Override
   protected void rollbackState(final MasterProcedureEnv env, final EnableTableState state)
       throws IOException {
-    if (isTraceEnabled()) {
-      LOG.trace(this + " rollback state=" + state);
-    }
-    try {
-      switch (state) {
-      case ENABLE_TABLE_POST_OPERATION:
-        // TODO-MAYBE: call the coprocessor event to undo (eg. DisableTableProcedure.preDisable())?
-        break;
-      case ENABLE_TABLE_SET_ENABLED_TABLE_STATE:
-        DisableTableProcedure.setTableStateToDisabling(env, tableName);
-        break;
-      case ENABLE_TABLE_MARK_REGIONS_ONLINE:
-        markRegionsOfflineDuringRecovery(env);
-        break;
-      case ENABLE_TABLE_SET_ENABLING_TABLE_STATE:
-        DisableTableProcedure.setTableStateToDisabled(env, tableName);
-        break;
+    // nothing to rollback, prepare-disable is just table-state checks.
+    // We can fail if the table does not exist or is not disabled.
+    switch (state) {
       case ENABLE_TABLE_PRE_OPERATION:
-        // TODO-MAYBE: call the coprocessor event to undo (eg. DisableTableProcedure.postDisable())?
-        break;
+        return;
       case ENABLE_TABLE_PREPARE:
-        // Nothing to undo for this state.
-        // We do need to count down the latch count so that we don't stuck.
         ProcedurePrepareLatch.releaseLatch(syncLatch, this);
+        return;
+      default:
         break;
+    }
+
+    // The delete doesn't have a rollback. The execution will succeed, at some point.
+    throw new UnsupportedOperationException("unhandled state=" + state);
+  }
+
+  @Override
+  protected boolean isRollbackSupported(final EnableTableState state) {
+    switch (state) {
+      case ENABLE_TABLE_PREPARE:
+      case ENABLE_TABLE_PRE_OPERATION:
+        return true;
       default:
-        throw new UnsupportedOperationException("unhandled state=" + state);
-      }
-    } catch (IOException e) {
-      // This will be retried. Unless there is a bug in the code,
-      // this should be just a "temporary error" (e.g. network down)
-      LOG.warn("Failed enable table rollback attempt step=" + state + " table=" + tableName, e);
-      throw e;
+        return false;
     }
   }
 
@@ -211,21 +203,6 @@ public class EnableTableProcedure
   }
 
   @Override
-  protected void setNextState(final EnableTableState state) {
-    if (aborted.get()) {
-      setAbortFailure("Enable-table", "abort requested");
-    } else {
-      super.setNextState(state);
-    }
-  }
-
-  @Override
-  public boolean abort(final MasterProcedureEnv env) {
-    aborted.set(true);
-    return true;
-  }
-
-  @Override
   protected boolean acquireLock(final MasterProcedureEnv env) {
     if (env.waitInitialized(this)) return false;
     return env.getProcedureQueue().tryAcquireTableExclusiveLock(this, tableName);

http://git-wip-us.apache.org/repos/asf/hbase/blob/f6ccae35/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ModifyColumnFamilyProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ModifyColumnFamilyProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ModifyColumnFamilyProcedure.java
index b06ffe8..2c7badf 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ModifyColumnFamilyProcedure.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ModifyColumnFamilyProcedure.java
@@ -23,7 +23,6 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.security.PrivilegedExceptionAction;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -50,8 +49,6 @@ public class ModifyColumnFamilyProcedure
     implements TableProcedureInterface {
   private static final Log LOG = LogFactory.getLog(ModifyColumnFamilyProcedure.class);
 
-  private final AtomicBoolean aborted = new AtomicBoolean(false);
-
   private TableName tableName;
   private HTableDescriptor unmodifiedHTableDescriptor;
   private HColumnDescriptor cfDescriptor;
@@ -116,10 +113,12 @@ public class ModifyColumnFamilyProcedure
         throw new UnsupportedOperationException(this + " unhandled state=" + state);
       }
     } catch (IOException e) {
-      LOG.warn("Error trying to modify the column family " + getColumnFamilyName()
-          + " of the table " + tableName + "(in state=" + state + ")", e);
-
-      setFailure("master-modify-columnfamily", e);
+      if (isRollbackSupported(state)) {
+        setFailure("master-modify-columnfamily", e);
+      } else {
+        LOG.warn("Retriable error trying to disable table=" + tableName +
+          " (in state=" + state + ")", e);
+      }
     }
     return Flow.HAS_MORE_STATE;
   }
@@ -127,33 +126,25 @@ public class ModifyColumnFamilyProcedure
   @Override
   protected void rollbackState(final MasterProcedureEnv env, final ModifyColumnFamilyState state)
       throws IOException {
-    if (isTraceEnabled()) {
-      LOG.trace(this + " rollback state=" + state);
+    if (state == ModifyColumnFamilyState.MODIFY_COLUMN_FAMILY_PREPARE ||
+        state == ModifyColumnFamilyState.MODIFY_COLUMN_FAMILY_PRE_OPERATION) {
+      // nothing to rollback, pre-modify is just checks.
+      // TODO: coprocessor rollback semantic is still undefined.
+      return;
     }
-    try {
-      switch (state) {
-      case MODIFY_COLUMN_FAMILY_REOPEN_ALL_REGIONS:
-        break; // Nothing to undo.
-      case MODIFY_COLUMN_FAMILY_POST_OPERATION:
-        // TODO-MAYBE: call the coprocessor event to undo?
-        break;
-      case MODIFY_COLUMN_FAMILY_UPDATE_TABLE_DESCRIPTOR:
-        restoreTableDescriptor(env);
-        break;
+
+    // The delete doesn't have a rollback. The execution will succeed, at some point.
+    throw new UnsupportedOperationException("unhandled state=" + state);
+  }
+
+  @Override
+  protected boolean isRollbackSupported(final ModifyColumnFamilyState state) {
+    switch (state) {
       case MODIFY_COLUMN_FAMILY_PRE_OPERATION:
-        // TODO-MAYBE: call the coprocessor event to undo?
-        break;
       case MODIFY_COLUMN_FAMILY_PREPARE:
-        break; // nothing to do
+        return true;
       default:
-        throw new UnsupportedOperationException(this + " unhandled state=" + state);
-      }
-    } catch (IOException e) {
-      // This will be retried. Unless there is a bug in the code,
-      // this should be just a "temporary error" (e.g. network down)
-      LOG.warn("Failed rollback attempt step " + state + " for adding the column family"
-          + getColumnFamilyName() + " to the table " + tableName, e);
-      throw e;
+        return false;
     }
   }
 
@@ -178,21 +169,6 @@ public class ModifyColumnFamilyProcedure
   }
 
   @Override
-  protected void setNextState(ModifyColumnFamilyState state) {
-    if (aborted.get()) {
-      setAbortFailure("modify-columnfamily", "abort requested");
-    } else {
-      super.setNextState(state);
-    }
-  }
-
-  @Override
-  public boolean abort(final MasterProcedureEnv env) {
-    aborted.set(true);
-    return true;
-  }
-
-  @Override
   protected boolean acquireLock(final MasterProcedureEnv env) {
     if (env.waitInitialized(this)) return false;
     return env.getProcedureQueue().tryAcquireTableExclusiveLock(this, tableName);

http://git-wip-us.apache.org/repos/asf/hbase/blob/f6ccae35/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ModifyNamespaceProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ModifyNamespaceProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ModifyNamespaceProcedure.java
index a16c8d1..197290c 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ModifyNamespaceProcedure.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ModifyNamespaceProcedure.java
@@ -21,7 +21,6 @@ package org.apache.hadoop.hbase.master.procedure;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -44,8 +43,6 @@ public class ModifyNamespaceProcedure
     implements TableProcedureInterface {
   private static final Log LOG = LogFactory.getLog(ModifyNamespaceProcedure.class);
 
-  private final AtomicBoolean aborted = new AtomicBoolean(false);
-
   private NamespaceDescriptor oldNsDescriptor;
   private NamespaceDescriptor newNsDescriptor;
   private Boolean traceEnabled;
@@ -87,10 +84,12 @@ public class ModifyNamespaceProcedure
         throw new UnsupportedOperationException(this + " unhandled state=" + state);
       }
     } catch (IOException e) {
-      LOG.warn("Error trying to modify the namespace" + newNsDescriptor.getName()
-        + " (in state=" + state + ")", e);
-
-      setFailure("master-modify-namespace", e);
+      if (isRollbackSupported(state)) {
+        setFailure("master-modify-namespace", e);
+      } else {
+        LOG.warn("Retriable error trying to modify namespace=" + newNsDescriptor.getName() +
+          " (in state=" + state + ")", e);
+      }
     }
     return Flow.HAS_MORE_STATE;
   }
@@ -98,28 +97,23 @@ public class ModifyNamespaceProcedure
   @Override
   protected void rollbackState(final MasterProcedureEnv env, final ModifyNamespaceState state)
       throws IOException {
-    if (isTraceEnabled()) {
-      LOG.trace(this + " rollback state=" + state);
+    if (state == ModifyNamespaceState.MODIFY_NAMESPACE_PREPARE) {
+      // nothing to rollback, pre-modify is just checks.
+      // TODO: coprocessor rollback semantic is still undefined.
+      return;
     }
-    try {
-      switch (state) {
-      case MODIFY_NAMESPACE_UPDATE_ZK:
-        rollbackZKNamespaceManagerChange(env);
-        break;
-      case MODIFY_NAMESPACE_UPDATE_NS_TABLE:
-        rollbackUpdateInNSTable(env);
-        break;
+
+    // The procedure doesn't have a rollback. The execution will succeed, at some point.
+    throw new UnsupportedOperationException("unhandled state=" + state);
+  }
+
+  @Override
+  protected boolean isRollbackSupported(final ModifyNamespaceState state) {
+    switch (state) {
       case MODIFY_NAMESPACE_PREPARE:
-        break; // nothing to do
+        return true;
       default:
-        throw new UnsupportedOperationException(this + " unhandled state=" + state);
-      }
-    } catch (IOException e) {
-      // This will be retried. Unless there is a bug in the code,
-      // this should be just a "temporary error" (e.g. network down)
-      LOG.warn("Failed rollback attempt step " + state + " for creating the namespace "
-          + newNsDescriptor.getName(), e);
-      throw e;
+        return false;
     }
   }
 
@@ -139,21 +133,6 @@ public class ModifyNamespaceProcedure
   }
 
   @Override
-  protected void setNextState(ModifyNamespaceState state) {
-    if (aborted.get()) {
-      setAbortFailure("modify-namespace", "abort requested");
-    } else {
-      super.setNextState(state);
-    }
-  }
-
-  @Override
-  public boolean abort(final MasterProcedureEnv env) {
-    aborted.set(true);
-    return true;
-  }
-
-  @Override
   public void serializeStateData(final OutputStream stream) throws IOException {
     super.serializeStateData(stream);
 
@@ -239,17 +218,6 @@ public class ModifyNamespaceProcedure
   }
 
   /**
-   * rollback the row into namespace table
-   * @param env MasterProcedureEnv
-   * @throws IOException
-   */
-  private void rollbackUpdateInNSTable(final MasterProcedureEnv env) throws IOException {
-    if (oldNsDescriptor != null) {
-      getTableNamespaceManager(env).insertIntoNSTable(oldNsDescriptor);
-    }
-  }
-
-  /**
    * Update ZooKeeper.
    * @param env MasterProcedureEnv
    * @throws IOException
@@ -258,17 +226,6 @@ public class ModifyNamespaceProcedure
     getTableNamespaceManager(env).updateZKNamespaceManager(newNsDescriptor);
   }
 
-  /**
-   * Update ZooKeeper during undo.
-   * @param env MasterProcedureEnv
-   * @throws IOException
-   */
-  private void rollbackZKNamespaceManagerChange(final MasterProcedureEnv env) throws IOException {
-    if (oldNsDescriptor != null) {
-      getTableNamespaceManager(env).updateZKNamespaceManager(oldNsDescriptor);
-    }
-  }
-
   private TableNamespaceManager getTableNamespaceManager(final MasterProcedureEnv env) {
     return env.getMasterServices().getClusterSchema().getTableNamespaceManager();
   }

http://git-wip-us.apache.org/repos/asf/hbase/blob/f6ccae35/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ModifyTableProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ModifyTableProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ModifyTableProcedure.java
index 64c26b9..83017bf 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ModifyTableProcedure.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ModifyTableProcedure.java
@@ -25,7 +25,6 @@ import java.security.PrivilegedExceptionAction;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -58,8 +57,6 @@ public class ModifyTableProcedure
     implements TableProcedureInterface {
   private static final Log LOG = LogFactory.getLog(ModifyTableProcedure.class);
 
-  private final AtomicBoolean aborted = new AtomicBoolean(false);
-
   private HTableDescriptor unmodifiedHTableDescriptor = null;
   private HTableDescriptor modifiedHTableDescriptor;
   private User user;
@@ -140,12 +137,11 @@ public class ModifyTableProcedure
         throw new UnsupportedOperationException("unhandled state=" + state);
       }
     } catch (IOException e) {
-      if (!isRollbackSupported(state)) {
-        // We reach a state that cannot be rolled back. We just need to keep retry.
-        LOG.warn("Error trying to modify table=" + getTableName() + " state=" + state, e);
-      } else {
-        LOG.error("Error trying to modify table=" + getTableName() + " state=" + state, e);
+      if (isRollbackSupported(state)) {
         setFailure("master-modify-table", e);
+      } else {
+        LOG.warn("Retriable error trying to modify table=" + getTableName() +
+          " (in state=" + state + ")", e);
       }
     }
     return Flow.HAS_MORE_STATE;
@@ -154,41 +150,25 @@ public class ModifyTableProcedure
   @Override
   protected void rollbackState(final MasterProcedureEnv env, final ModifyTableState state)
       throws IOException {
-    if (isTraceEnabled()) {
-      LOG.trace(this + " rollback state=" + state);
+    if (state == ModifyTableState.MODIFY_TABLE_PREPARE ||
+        state == ModifyTableState.MODIFY_TABLE_PRE_OPERATION) {
+      // nothing to rollback, pre-modify is just checks.
+      // TODO: coprocessor rollback semantic is still undefined.
+      return;
     }
-    try {
-      switch (state) {
-      case MODIFY_TABLE_REOPEN_ALL_REGIONS:
-        break; // Nothing to undo.
-      case MODIFY_TABLE_POST_OPERATION:
-        // TODO-MAYBE: call the coprocessor event to un-modify?
-        break;
-      case MODIFY_TABLE_DELETE_FS_LAYOUT:
-        // Once we reach to this state - we could NOT rollback - as it is tricky to undelete
-        // the deleted files. We are not suppose to reach here, throw exception so that we know
-        // there is a code bug to investigate.
-        assert deleteColumnFamilyInModify;
-        throw new UnsupportedOperationException(this + " rollback of state=" + state
-            + " is unsupported.");
-      case MODIFY_TABLE_REMOVE_REPLICA_COLUMN:
-        // Undo the replica column update.
-        updateReplicaColumnsIfNeeded(env, modifiedHTableDescriptor, unmodifiedHTableDescriptor);
-        break;
-      case MODIFY_TABLE_UPDATE_TABLE_DESCRIPTOR:
-        restoreTableDescriptor(env);
-        break;
+
+    // The delete doesn't have a rollback. The execution will succeed, at some point.
+    throw new UnsupportedOperationException("unhandled state=" + state);
+  }
+
+  @Override
+  protected boolean isRollbackSupported(final ModifyTableState state) {
+    switch (state) {
       case MODIFY_TABLE_PRE_OPERATION:
-        // TODO-MAYBE: call the coprocessor event to un-modify?
-        break;
       case MODIFY_TABLE_PREPARE:
-        break; // Nothing to undo.
+        return true;
       default:
-        throw new UnsupportedOperationException("unhandled state=" + state);
-      }
-    } catch (IOException e) {
-      LOG.warn("Fail trying to rollback modify table=" + getTableName() + " state=" + state, e);
-      throw e;
+        return false;
     }
   }
 
@@ -213,21 +193,6 @@ public class ModifyTableProcedure
   }
 
   @Override
-  protected void setNextState(final ModifyTableState state) {
-    if (aborted.get() && isRollbackSupported(state)) {
-      setAbortFailure("modify-table", "abort requested");
-    } else {
-      super.setNextState(state);
-    }
-  }
-
-  @Override
-  public boolean abort(final MasterProcedureEnv env) {
-    aborted.set(true);
-    return true;
-  }
-
-  @Override
   protected boolean acquireLock(final MasterProcedureEnv env) {
     if (env.waitInitialized(this)) return false;
     return env.getProcedureQueue().tryAcquireTableExclusiveLock(this, getTableName());
@@ -493,24 +458,6 @@ public class ModifyTableProcedure
     }
   }
 
-  /*
-   * Check whether we are in the state that can be rollback
-   */
-  private boolean isRollbackSupported(final ModifyTableState state) {
-    if (deleteColumnFamilyInModify) {
-      switch (state) {
-      case MODIFY_TABLE_DELETE_FS_LAYOUT:
-      case MODIFY_TABLE_POST_OPERATION:
-      case MODIFY_TABLE_REOPEN_ALL_REGIONS:
-        // It is not safe to rollback if we reach to these states.
-        return false;
-      default:
-        break;
-      }
-    }
-    return true;
-  }
-
   private List<HRegionInfo> getRegionInfoList(final MasterProcedureEnv env) throws IOException {
     if (regionInfoList == null) {
       regionInfoList = ProcedureSyncWait.getRegionsFromMeta(env, getTableName());

http://git-wip-us.apache.org/repos/asf/hbase/blob/f6ccae35/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/RestoreSnapshotProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/RestoreSnapshotProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/RestoreSnapshotProcedure.java
index 6ac6fe7..7b058d2 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/RestoreSnapshotProcedure.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/RestoreSnapshotProcedure.java
@@ -26,7 +26,6 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -66,8 +65,6 @@ public class RestoreSnapshotProcedure
     implements TableProcedureInterface {
   private static final Log LOG = LogFactory.getLog(RestoreSnapshotProcedure.class);
 
-  private final AtomicBoolean aborted = new AtomicBoolean(false);
-
   private HTableDescriptor modifiedHTableDescriptor;
   private List<HRegionInfo> regionsToRestore = null;
   private List<HRegionInfo> regionsToRemove = null;
@@ -155,8 +152,12 @@ public class RestoreSnapshotProcedure
           throw new UnsupportedOperationException("unhandled state=" + state);
       }
     } catch (IOException e) {
-      LOG.error("Error trying to restore snapshot=" + getTableName() + " state=" + state, e);
-      setFailure("master-restore-snapshot", e);
+      if (isRollbackSupported(state)) {
+        setFailure("master-restore-snapshot", e);
+      } else {
+        LOG.warn("Retriable error trying to restore snapshot=" + snapshot.getName() +
+          " to table=" + getTableName() + " (in state=" + state + ")", e);
+      }
     }
     return Flow.HAS_MORE_STATE;
   }
@@ -164,10 +165,6 @@ public class RestoreSnapshotProcedure
   @Override
   protected void rollbackState(final MasterProcedureEnv env, final RestoreSnapshotState state)
       throws IOException {
-    if (isTraceEnabled()) {
-      LOG.trace(this + " rollback state=" + state);
-    }
-
     if (state == RestoreSnapshotState.RESTORE_SNAPSHOT_PRE_OPERATION) {
       // nothing to rollback
       return;
@@ -178,6 +175,16 @@ public class RestoreSnapshotProcedure
   }
 
   @Override
+  protected boolean isRollbackSupported(final RestoreSnapshotState state) {
+    switch (state) {
+      case RESTORE_SNAPSHOT_PRE_OPERATION:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  @Override
   protected RestoreSnapshotState getState(final int stateId) {
     return RestoreSnapshotState.valueOf(stateId);
   }
@@ -193,15 +200,6 @@ public class RestoreSnapshotProcedure
   }
 
   @Override
-  protected void setNextState(final RestoreSnapshotState state) {
-    if (aborted.get()) {
-      setAbortFailure("create-table", "abort requested");
-    } else {
-      super.setNextState(state);
-    }
-  }
-
-  @Override
   public TableName getTableName() {
     return modifiedHTableDescriptor.getTableName();
   }
@@ -213,8 +211,8 @@ public class RestoreSnapshotProcedure
 
   @Override
   public boolean abort(final MasterProcedureEnv env) {
-    aborted.set(true);
-    return true;
+    // TODO: We may be able to abort if the procedure is not started yet.
+    return false;
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/hbase/blob/f6ccae35/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TruncateTableProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TruncateTableProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TruncateTableProcedure.java
index 75606c2..4b06740 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TruncateTableProcedure.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TruncateTableProcedure.java
@@ -142,7 +142,11 @@ public class TruncateTableProcedure
           throw new UnsupportedOperationException("unhandled state=" + state);
       }
     } catch (HBaseException|IOException e) {
-      LOG.warn("Retriable error trying to truncate table=" + getTableName() + " state=" + state, e);
+      if (isRollbackSupported(state)) {
+        setFailure("master-truncate-table", e);
+      } else {
+        LOG.warn("Retriable error trying to truncate table=" + getTableName() + " state=" + state, e);
+      }
     }
     return Flow.HAS_MORE_STATE;
   }
@@ -152,6 +156,7 @@ public class TruncateTableProcedure
     if (state == TruncateTableState.TRUNCATE_TABLE_PRE_OPERATION) {
       // nothing to rollback, pre-truncate is just table-state checks.
       // We can fail if the table does not exist or is not disabled.
+      // TODO: coprocessor rollback semantic is still undefined.
       return;
     }
 
@@ -165,6 +170,16 @@ public class TruncateTableProcedure
   }
 
   @Override
+  protected boolean isRollbackSupported(final TruncateTableState state) {
+    switch (state) {
+      case TRUNCATE_TABLE_PRE_OPERATION:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  @Override
   protected TruncateTableState getState(final int stateId) {
     return TruncateTableState.valueOf(stateId);
   }

http://git-wip-us.apache.org/repos/asf/hbase/blob/f6ccae35/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureTestingUtility.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureTestingUtility.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureTestingUtility.java
index 2d054d8..e9e8bdc 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureTestingUtility.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureTestingUtility.java
@@ -43,6 +43,7 @@ import org.apache.hadoop.hbase.client.Result;
 import org.apache.hadoop.hbase.client.TableState;
 import org.apache.hadoop.hbase.master.HMaster;
 import org.apache.hadoop.hbase.master.TableStateManager;
+import org.apache.hadoop.hbase.procedure2.Procedure;
 import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
 import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility;
 import org.apache.hadoop.hbase.util.ModifyRegionUtils;
@@ -189,6 +190,85 @@ public class MasterProcedureTestingUtility {
     assertTrue(tsm.getTableState(tableName).equals(TableState.State.DISABLED));
   }
 
+  public static void validateColumnFamilyAddition(final HMaster master, final TableName tableName,
+      final String family) throws IOException {
+    HTableDescriptor htd = master.getTableDescriptors().get(tableName);
+    assertTrue(htd != null);
+
+    assertTrue(htd.hasFamily(family.getBytes()));
+  }
+
+  public static void validateColumnFamilyDeletion(final HMaster master, final TableName tableName,
+      final String family) throws IOException {
+    // verify htd
+    HTableDescriptor htd = master.getTableDescriptors().get(tableName);
+    assertTrue(htd != null);
+    assertFalse(htd.hasFamily(family.getBytes()));
+
+    // verify fs
+    final FileSystem fs = master.getMasterFileSystem().getFileSystem();
+    final Path tableDir = FSUtils.getTableDir(master.getMasterFileSystem().getRootDir(), tableName);
+    for (Path regionDir: FSUtils.getRegionDirs(fs, tableDir)) {
+      final Path familyDir = new Path(regionDir, family);
+      assertFalse(family + " family dir should not exist", fs.exists(familyDir));
+    }
+  }
+
+  public static void validateColumnFamilyModification(final HMaster master,
+      final TableName tableName, final String family, HColumnDescriptor columnDescriptor)
+      throws IOException {
+    HTableDescriptor htd = master.getTableDescriptors().get(tableName);
+    assertTrue(htd != null);
+
+    HColumnDescriptor hcfd = htd.getFamily(family.getBytes());
+    assertTrue(hcfd.equals(columnDescriptor));
+  }
+
+  public static void loadData(final Connection connection, final TableName tableName,
+      int rows, final byte[][] splitKeys,  final String... sfamilies) throws IOException {
+    byte[][] families = new byte[sfamilies.length][];
+    for (int i = 0; i < families.length; ++i) {
+      families[i] = Bytes.toBytes(sfamilies[i]);
+    }
+
+    BufferedMutator mutator = connection.getBufferedMutator(tableName);
+
+    // Ensure one row per region
+    assertTrue(rows >= splitKeys.length);
+    for (byte[] k: splitKeys) {
+      byte[] value = Bytes.add(Bytes.toBytes(System.currentTimeMillis()), k);
+      byte[] key = Bytes.add(k, Bytes.toBytes(MD5Hash.getMD5AsHex(value)));
+      mutator.mutate(createPut(families, key, value));
+      rows--;
+    }
+
+    // Add other extra rows. more rows, more files
+    while (rows-- > 0) {
+      byte[] value = Bytes.add(Bytes.toBytes(System.currentTimeMillis()), Bytes.toBytes(rows));
+      byte[] key = Bytes.toBytes(MD5Hash.getMD5AsHex(value));
+      mutator.mutate(createPut(families, key, value));
+    }
+    mutator.flush();
+  }
+
+  private static Put createPut(final byte[][] families, final byte[] key, final byte[] value) {
+    byte[] q = Bytes.toBytes("q");
+    Put put = new Put(key);
+    put.setDurability(Durability.SKIP_WAL);
+    for (byte[] family: families) {
+      put.addColumn(family, q, value);
+    }
+    return put;
+  }
+
+  public static long generateNonceGroup(final HMaster master) {
+    return master.getClusterConnection().getNonceGenerator().getNonceGroup();
+  }
+
+  public static long generateNonce(final HMaster master) {
+    return master.getClusterConnection().getNonceGenerator().newNonce();
+  }
+
   /**
    * Run through all procedure flow states TWICE while also restarting procedure executor at each
    * step; i.e force a reread of procedure store.
@@ -204,24 +284,37 @@ public class MasterProcedureTestingUtility {
    * finish.
    * @see #testRecoveryAndDoubleExecution(ProcedureExecutor, long)
    */
-  public static <TState> void testRecoveryAndDoubleExecution(
+  public static void testRecoveryAndDoubleExecution(
+      final ProcedureExecutor<MasterProcedureEnv> procExec, final long procId,
+      final int numSteps) throws Exception {
+    testRecoveryAndDoubleExecution(procExec, procId, numSteps, true);
+    ProcedureTestingUtility.assertProcNotFailed(procExec, procId);
+  }
+
+  private static void testRecoveryAndDoubleExecution(
       final ProcedureExecutor<MasterProcedureEnv> procExec, final long procId,
-      final int numSteps, final TState[] states) throws Exception {
+      final int numSteps, final boolean expectExecRunning) throws Exception {
+    final Procedure proc = procExec.getProcedure(procId);
     ProcedureTestingUtility.waitProcedure(procExec, procId);
     assertEquals(false, procExec.isRunning());
+
+    // Restart the executor and execute the step twice
+    //   execute step N - kill before store update
+    //   restart executor/store
+    //   execute step N - save on store
     for (int i = 0; i < numSteps; ++i) {
-      LOG.info("Restart "+ i +" exec state: " + states[i]);
+      LOG.info("Restart " + i + " exec state: " + proc);
       ProcedureTestingUtility.assertProcNotYetCompleted(procExec, procId);
       ProcedureTestingUtility.restart(procExec);
       ProcedureTestingUtility.waitProcedure(procExec, procId);
     }
-    assertEquals(true, procExec.isRunning());
-    ProcedureTestingUtility.assertProcNotFailed(procExec, procId);
+
+    assertEquals(expectExecRunning, procExec.isRunning());
   }
 
   /**
-   * Run through all procedure flow states TWICE while also restarting procedure executor at each
-   * step; i.e force a reread of procedure store.
+   * Run through all procedure flow states TWICE while also restarting
+   * procedure executor at each step; i.e force a reread of procedure store.
    *
    *<p>It does
    * <ol><li>Execute step N - kill the executor before store update
@@ -233,14 +326,15 @@ public class MasterProcedureTestingUtility {
    * idempotent. Use this version of the test when the order in which flow steps are executed is
    * not start to finish; where the procedure may vary the flow steps dependent on circumstance
    * found.
-   * @see #testRecoveryAndDoubleExecution(ProcedureExecutor, long, int, Object[])
+   * @see #testRecoveryAndDoubleExecution(ProcedureExecutor, long, int)
    */
-  public static <TState> void testRecoveryAndDoubleExecution(
-      final ProcedureExecutor<MasterProcedureEnv> procExec, final long procId)
-  throws Exception {
+  public static void testRecoveryAndDoubleExecution(
+      final ProcedureExecutor<MasterProcedureEnv> procExec, final long procId) throws Exception {
+    final Procedure proc = procExec.getProcedure(procId);
     ProcedureTestingUtility.waitProcedure(procExec, procId);
     assertEquals(false, procExec.isRunning());
-    while (!procExec.isFinished(procId)) {
+    for (int i = 0; !procExec.isFinished(procId); ++i) {
+      LOG.info("Restart " + i + " exec state: " + proc);
       ProcedureTestingUtility.restart(procExec);
       ProcedureTestingUtility.waitProcedure(procExec, procId);
     }
@@ -248,21 +342,21 @@ public class MasterProcedureTestingUtility {
     ProcedureTestingUtility.assertProcNotFailed(procExec, procId);
   }
 
-  public static <TState> void testRollbackAndDoubleExecution(
+  /**
+   * Execute the procedure up to "lastStep" and then the ProcedureExecutor
+   * is restarted and an abort() is injected.
+   * If the procedure implement abort() this should result in rollback being triggered.
+   * Each rollback step is called twice, by restarting the executor after every step.
+   * At the end of this call the procedure should be finished and rolledback.
+   * This method assert on the procedure being terminated with an AbortException.
+   */
+  public static void testRollbackAndDoubleExecution(
       final ProcedureExecutor<MasterProcedureEnv> procExec, final long procId,
-      final int lastStep, final TState[] states) throws Exception {
-    ProcedureTestingUtility.waitProcedure(procExec, procId);
+      final int lastStep) throws Exception {
+    final Procedure proc = procExec.getProcedure(procId);
 
-    // Restart the executor and execute the step twice
-    //   execute step N - kill before store update
-    //   restart executor/store
-    //   execute step N - save on store
-    for (int i = 0; i < lastStep; ++i) {
-      LOG.info("Restart "+ i +" exec state: " + states[i]);
-      ProcedureTestingUtility.assertProcNotYetCompleted(procExec, procId);
-      ProcedureTestingUtility.restart(procExec);
-      ProcedureTestingUtility.waitProcedure(procExec, procId);
-    }
+    // Execute up to last step
+    testRecoveryAndDoubleExecution(procExec, procId, lastStep, false);
 
     // Restart the executor and rollback the step twice
     //   rollback step N - kill before store update
@@ -271,8 +365,8 @@ public class MasterProcedureTestingUtility {
     InjectAbortOnLoadListener abortListener = new InjectAbortOnLoadListener(procExec);
     procExec.registerListener(abortListener);
     try {
-      for (int i = lastStep + 1; i >= 0; --i) {
-        LOG.info("Restart " + i +" rollback state: "+ states[i]);
+      for (int i = 0; !procExec.isFinished(procId); ++i) {
+        LOG.info("Restart " + i + " rollback state: " + proc);
         ProcedureTestingUtility.assertProcNotYetCompleted(procExec, procId);
         ProcedureTestingUtility.restart(procExec);
         ProcedureTestingUtility.waitProcedure(procExec, procId);
@@ -281,81 +375,44 @@ public class MasterProcedureTestingUtility {
       assertTrue(procExec.unregisterListener(abortListener));
     }
 
-    ProcedureTestingUtility.assertIsAbortException(procExec.getResult(procId));
-  }
-
-  public static <TState> void testRollbackAndDoubleExecutionAfterPONR(
-      final ProcedureExecutor<MasterProcedureEnv> procExec, final long procId,
-      final int lastStep, final TState[] states) throws Exception {
-    ProcedureTestingUtility.waitProcedure(procExec, procId);
-
-    // Restart the executor and execute the step twice
-    //   execute step N - kill before store update
-    //   restart executor/store
-    //   execute step N - save on store
-    for (int i = 0; i < lastStep; ++i) {
-      LOG.info("Restart "+ i +" exec state: " + states[i]);
-      ProcedureTestingUtility.assertProcNotYetCompleted(procExec, procId);
-      ProcedureTestingUtility.restart(procExec);
-      ProcedureTestingUtility.waitProcedure(procExec, procId);
-    }
-
-    // try to inject the abort
-    ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, false);
-    InjectAbortOnLoadListener abortListener = new InjectAbortOnLoadListener(procExec);
-    procExec.registerListener(abortListener);
-    try {
-      ProcedureTestingUtility.assertProcNotYetCompleted(procExec, procId);
-      ProcedureTestingUtility.restart(procExec);
-      LOG.info("Restart and execute");
-      ProcedureTestingUtility.waitProcedure(procExec, procId);
-    } finally {
-      assertTrue(procExec.unregisterListener(abortListener));
-    }
-
     assertEquals(true, procExec.isRunning());
-    ProcedureTestingUtility.assertProcNotFailed(procExec, procId);
+    ProcedureTestingUtility.assertIsAbortException(procExec.getResult(procId));
   }
 
-  public static <TState> void testRollbackRetriableFailure(
+  /**
+   * Execute the procedure up to "lastStep" and then the ProcedureExecutor
+   * is restarted and an abort() is injected.
+   * If the procedure implement abort() this should result in rollback being triggered.
+   * At the end of this call the procedure should be finished and rolledback.
+   * This method assert on the procedure being terminated with an AbortException.
+   */
+  public static void testRollbackRetriableFailure(
       final ProcedureExecutor<MasterProcedureEnv> procExec, final long procId,
-      final int lastStep, final TState[] states) throws Exception {
-    ProcedureTestingUtility.waitProcedure(procExec, procId);
-
-    // Restart the executor and execute the step twice
-    //   execute step N - kill before store update
-    //   restart executor/store
-    //   execute step N - save on store
-    for (int i = 0; i < lastStep; ++i) {
-      LOG.info("Restart "+ i +" exec state: " + states[i]);
-      ProcedureTestingUtility.assertProcNotYetCompleted(procExec, procId);
-      ProcedureTestingUtility.restart(procExec);
-      ProcedureTestingUtility.waitProcedure(procExec, procId);
-    }
+      final int lastStep) throws Exception {
+    // Execute up to last step
+    testRecoveryAndDoubleExecution(procExec, procId, lastStep, false);
 
     // execute the rollback
-    ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, false);
-    InjectAbortOnLoadListener abortListener = new InjectAbortOnLoadListener(procExec);
-    procExec.registerListener(abortListener);
-    try {
-      ProcedureTestingUtility.assertProcNotYetCompleted(procExec, procId);
-      ProcedureTestingUtility.restart(procExec);
-      LOG.info("Restart and rollback");
-      ProcedureTestingUtility.waitProcedure(procExec, procId);
-    } finally {
-      assertTrue(procExec.unregisterListener(abortListener));
-    }
+    testRestartWithAbort(procExec, procId);
 
+    assertEquals(true, procExec.isRunning());
     ProcedureTestingUtility.assertIsAbortException(procExec.getResult(procId));
   }
 
+  /**
+   * Restart the ProcedureExecutor and inject an abort to the specified procedure.
+   * If the procedure implement abort() this should result in rollback being triggered.
+   * At the end of this call the procedure should be finished and rolledback, if abort is implemnted
+   */
   public static void testRestartWithAbort(ProcedureExecutor<MasterProcedureEnv> procExec,
       long procId) throws Exception {
+    ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, false);
     InjectAbortOnLoadListener abortListener = new InjectAbortOnLoadListener(procExec);
     abortListener.addProcId(procId);
     procExec.registerListener(abortListener);
     try {
-      ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, false);
+      ProcedureTestingUtility.assertProcNotYetCompleted(procExec, procId);
+      LOG.info("Restart and rollback procId=" + procId);
       ProcedureTestingUtility.restart(procExec);
       ProcedureTestingUtility.waitProcedure(procExec, procId);
     } finally {
@@ -363,85 +420,6 @@ public class MasterProcedureTestingUtility {
     }
   }
 
-  public static void validateColumnFamilyAddition(final HMaster master, final TableName tableName,
-      final String family) throws IOException {
-    HTableDescriptor htd = master.getTableDescriptors().get(tableName);
-    assertTrue(htd != null);
-
-    assertTrue(htd.hasFamily(family.getBytes()));
-  }
-
-  public static void validateColumnFamilyDeletion(final HMaster master, final TableName tableName,
-      final String family) throws IOException {
-    // verify htd
-    HTableDescriptor htd = master.getTableDescriptors().get(tableName);
-    assertTrue(htd != null);
-    assertFalse(htd.hasFamily(family.getBytes()));
-
-    // verify fs
-    final FileSystem fs = master.getMasterFileSystem().getFileSystem();
-    final Path tableDir = FSUtils.getTableDir(master.getMasterFileSystem().getRootDir(), tableName);
-    for (Path regionDir: FSUtils.getRegionDirs(fs, tableDir)) {
-      final Path familyDir = new Path(regionDir, family);
-      assertFalse(family + " family dir should not exist", fs.exists(familyDir));
-    }
-  }
-
-  public static void validateColumnFamilyModification(final HMaster master,
-      final TableName tableName, final String family, HColumnDescriptor columnDescriptor)
-      throws IOException {
-    HTableDescriptor htd = master.getTableDescriptors().get(tableName);
-    assertTrue(htd != null);
-
-    HColumnDescriptor hcfd = htd.getFamily(family.getBytes());
-    assertTrue(hcfd.equals(columnDescriptor));
-  }
-
-  public static void loadData(final Connection connection, final TableName tableName,
-      int rows, final byte[][] splitKeys,  final String... sfamilies) throws IOException {
-    byte[][] families = new byte[sfamilies.length][];
-    for (int i = 0; i < families.length; ++i) {
-      families[i] = Bytes.toBytes(sfamilies[i]);
-    }
-
-    BufferedMutator mutator = connection.getBufferedMutator(tableName);
-
-    // Ensure one row per region
-    assertTrue(rows >= splitKeys.length);
-    for (byte[] k: splitKeys) {
-      byte[] value = Bytes.add(Bytes.toBytes(System.currentTimeMillis()), k);
-      byte[] key = Bytes.add(k, Bytes.toBytes(MD5Hash.getMD5AsHex(value)));
-      mutator.mutate(createPut(families, key, value));
-      rows--;
-    }
-
-    // Add other extra rows. more rows, more files
-    while (rows-- > 0) {
-      byte[] value = Bytes.add(Bytes.toBytes(System.currentTimeMillis()), Bytes.toBytes(rows));
-      byte[] key = Bytes.toBytes(MD5Hash.getMD5AsHex(value));
-      mutator.mutate(createPut(families, key, value));
-    }
-    mutator.flush();
-  }
-
-  private static Put createPut(final byte[][] families, final byte[] key, final byte[] value) {
-    byte[] q = Bytes.toBytes("q");
-    Put put = new Put(key);
-    put.setDurability(Durability.SKIP_WAL);
-    for (byte[] family: families) {
-      put.addColumn(family, q, value);
-    }
-    return put;
-  }
-
-  public static long generateNonceGroup(final HMaster master) {
-    return master.getClusterConnection().getNonceGenerator().getNonceGroup();
-  }
-
-  public static long generateNonce(final HMaster master) {
-    return master.getClusterConnection().getNonceGenerator().newNonce();
-  }
-
   public static class InjectAbortOnLoadListener
       implements ProcedureExecutor.ProcedureExecutorListener {
     private final ProcedureExecutor<MasterProcedureEnv> procExec;