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;