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/06/08 20:14:06 UTC
[1/2] hbase git commit: HBASE-15107 Procedure v2 - Procedure Queue
with Region locks
Repository: hbase
Updated Branches:
refs/heads/master d05a3722c -> d9463bcce
HBASE-15107 Procedure v2 - Procedure Queue with Region locks
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/d5d9b7d5
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/d5d9b7d5
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/d5d9b7d5
Branch: refs/heads/master
Commit: d5d9b7d500c4e2bdf67abed462eeee966f7bf7df
Parents: d05a372
Author: Matteo Bertozzi <ma...@cloudera.com>
Authored: Wed Jun 8 12:52:58 2016 -0700
Committer: Matteo Bertozzi <ma...@cloudera.com>
Committed: Wed Jun 8 12:52:58 2016 -0700
----------------------------------------------------------------------
.../hadoop/hbase/procedure2/Procedure.java | 31 +-
.../hbase/procedure2/ProcedureExecutor.java | 19 +-
.../procedure2/ProcedureSuspendedException.java | 39 +++
.../hbase/procedure2/SequentialProcedure.java | 2 +-
.../procedure/MasterProcedureScheduler.java | 286 +++++++++++++++++--
.../procedure/TableProcedureInterface.java | 1 +
.../procedure/TestMasterProcedureScheduler.java | 228 ++++++++++++++-
7 files changed, 580 insertions(+), 26 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hbase/blob/d5d9b7d5/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/Procedure.java
----------------------------------------------------------------------
diff --git a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/Procedure.java b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/Procedure.java
index 7e58420..ee61841 100644
--- a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/Procedure.java
+++ b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/Procedure.java
@@ -79,6 +79,9 @@ public abstract class Procedure<TEnvironment> implements Comparable<Procedure> {
private int childrenLatch = 0;
private long lastUpdate;
+ // TODO: it will be nice having pointers to allow the scheduler doing suspend/resume tricks
+ private boolean suspended = false;
+
private RemoteProcedureException exception = null;
private byte[] result = null;
@@ -94,7 +97,7 @@ public abstract class Procedure<TEnvironment> implements Comparable<Procedure> {
* @throws InterruptedException the procedure will be added back to the queue and retried later
*/
protected abstract Procedure[] execute(TEnvironment env)
- throws ProcedureYieldException, InterruptedException;
+ throws ProcedureYieldException, ProcedureSuspendedException, InterruptedException;
/**
* The code to undo what done by the execute() code.
@@ -276,6 +279,9 @@ public abstract class Procedure<TEnvironment> implements Comparable<Procedure> {
*/
protected void toStringState(StringBuilder builder) {
builder.append(getState());
+ if (isSuspended()) {
+ builder.append("|SUSPENDED");
+ }
}
/**
@@ -319,7 +325,7 @@ public abstract class Procedure<TEnvironment> implements Comparable<Procedure> {
}
public long getParentProcId() {
- return parentProcId;
+ return parentProcId.longValue();
}
public NonceKey getNonceKey() {
@@ -371,6 +377,23 @@ public abstract class Procedure<TEnvironment> implements Comparable<Procedure> {
return false;
}
+ /**
+ * @return true if the procedure is in a suspended state,
+ * waiting for the resources required to execute the procedure will become available.
+ */
+ public synchronized boolean isSuspended() {
+ return suspended;
+ }
+
+ public synchronized void suspend() {
+ suspended = true;
+ }
+
+ public synchronized void resume() {
+ assert isSuspended() : this + " expected suspended state, got " + state;
+ suspended = false;
+ }
+
public synchronized RemoteProcedureException getException() {
return exception;
}
@@ -398,7 +421,7 @@ public abstract class Procedure<TEnvironment> implements Comparable<Procedure> {
* @return the timeout in msec
*/
public int getTimeout() {
- return timeout;
+ return timeout.intValue();
}
/**
@@ -494,7 +517,7 @@ public abstract class Procedure<TEnvironment> implements Comparable<Procedure> {
*/
@InterfaceAudience.Private
protected Procedure[] doExecute(final TEnvironment env)
- throws ProcedureYieldException, InterruptedException {
+ throws ProcedureYieldException, ProcedureSuspendedException, InterruptedException {
try {
updateTimestamp();
return execute(env);
http://git-wip-us.apache.org/repos/asf/hbase/blob/d5d9b7d5/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureExecutor.java
----------------------------------------------------------------------
diff --git a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureExecutor.java b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureExecutor.java
index f43b65f..9d71f65 100644
--- a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureExecutor.java
+++ b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureExecutor.java
@@ -505,15 +505,25 @@ public class ProcedureExecutor<TEnvironment> {
}
};
+ long st, et;
+
// Acquire the store lease.
+ st = EnvironmentEdgeManager.currentTime();
store.recoverLease();
+ et = EnvironmentEdgeManager.currentTime();
+ LOG.info(String.format("recover procedure store (%s) lease: %s",
+ store.getClass().getSimpleName(), StringUtils.humanTimeDiff(et - st)));
// TODO: Split in two steps.
// TODO: Handle corrupted procedures (currently just a warn)
// The first one will make sure that we have the latest id,
// so we can start the threads and accept new procedures.
// The second step will do the actual load of old procedures.
+ st = EnvironmentEdgeManager.currentTime();
load(abortOnCorruption);
+ et = EnvironmentEdgeManager.currentTime();
+ LOG.info(String.format("load procedure store (%s): %s",
+ store.getClass().getSimpleName(), StringUtils.humanTimeDiff(et - st)));
// Start the executors. Here we must have the lastProcId set.
for (int i = 0; i < threads.length; ++i) {
@@ -840,7 +850,7 @@ public class ProcedureExecutor<TEnvironment> {
}
// Execute the procedure
- assert proc.getState() == ProcedureState.RUNNABLE;
+ assert proc.getState() == ProcedureState.RUNNABLE : proc;
if (proc.acquireLock(getEnvironment())) {
execProcedure(procStack, proc);
proc.releaseLock(getEnvironment());
@@ -1042,6 +1052,7 @@ public class ProcedureExecutor<TEnvironment> {
Preconditions.checkArgument(procedure.getState() == ProcedureState.RUNNABLE);
// Execute the procedure
+ boolean isSuspended = false;
boolean reExecute = false;
Procedure[] subprocs = null;
do {
@@ -1051,6 +1062,8 @@ public class ProcedureExecutor<TEnvironment> {
if (subprocs != null && subprocs.length == 0) {
subprocs = null;
}
+ } catch (ProcedureSuspendedException e) {
+ isSuspended = true;
} catch (ProcedureYieldException e) {
if (LOG.isTraceEnabled()) {
LOG.trace("Yield procedure: " + procedure + ": " + e.getMessage());
@@ -1086,7 +1099,7 @@ public class ProcedureExecutor<TEnvironment> {
break;
}
- assert subproc.getState() == ProcedureState.INITIALIZING;
+ assert subproc.getState() == ProcedureState.INITIALIZING : subproc;
subproc.setParentProcId(procedure.getProcId());
subproc.setProcId(nextProcId());
}
@@ -1107,7 +1120,7 @@ public class ProcedureExecutor<TEnvironment> {
}
} else if (procedure.getState() == ProcedureState.WAITING_TIMEOUT) {
waitingTimeout.add(procedure);
- } else {
+ } else if (!isSuspended) {
// No subtask, so we are done
procedure.setState(ProcedureState.FINISHED);
}
http://git-wip-us.apache.org/repos/asf/hbase/blob/d5d9b7d5/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureSuspendedException.java
----------------------------------------------------------------------
diff --git a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureSuspendedException.java b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureSuspendedException.java
new file mode 100644
index 0000000..f28d57a
--- /dev/null
+++ b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/ProcedureSuspendedException.java
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hbase.procedure2;
+
+import org.apache.hadoop.hbase.classification.InterfaceAudience;
+import org.apache.hadoop.hbase.classification.InterfaceStability;
+
+@InterfaceAudience.Private
+@InterfaceStability.Stable
+public class ProcedureSuspendedException extends ProcedureException {
+ /** default constructor */
+ public ProcedureSuspendedException() {
+ super();
+ }
+
+ /**
+ * Constructor
+ * @param s message
+ */
+ public ProcedureSuspendedException(String s) {
+ super(s);
+ }
+}
http://git-wip-us.apache.org/repos/asf/hbase/blob/d5d9b7d5/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/SequentialProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/SequentialProcedure.java b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/SequentialProcedure.java
index 636a037..f0bcdea 100644
--- a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/SequentialProcedure.java
+++ b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/SequentialProcedure.java
@@ -42,7 +42,7 @@ public abstract class SequentialProcedure<TEnvironment> extends Procedure<TEnvir
@Override
protected Procedure[] doExecute(final TEnvironment env)
- throws ProcedureYieldException, InterruptedException {
+ throws ProcedureYieldException, ProcedureSuspendedException, InterruptedException {
updateTimestamp();
try {
Procedure[] children = !executed ? execute(env) : null;
http://git-wip-us.apache.org/repos/asf/hbase/blob/d5d9b7d5/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureScheduler.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureScheduler.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureScheduler.java
index 5f37720..d4791fe 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureScheduler.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureScheduler.java
@@ -20,12 +20,15 @@ package org.apache.hadoop.hbase.master.procedure;
import java.io.IOException;
import java.util.ArrayDeque;
+import java.util.Arrays;
+import java.util.HashMap;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.ServerName;
import org.apache.hadoop.hbase.TableExistsException;
import org.apache.hadoop.hbase.TableName;
@@ -103,6 +106,10 @@ public class MasterProcedureScheduler implements ProcedureRunnableSet {
}
private void doAdd(final Procedure proc, final boolean addFront) {
+ doAdd(proc, addFront, true);
+ }
+
+ private void doAdd(final Procedure proc, final boolean addFront, final boolean notify) {
schedLock.lock();
try {
if (isTableProcedure(proc)) {
@@ -117,7 +124,9 @@ public class MasterProcedureScheduler implements ProcedureRunnableSet {
throw new UnsupportedOperationException(
"RQs for non-table/non-server procedures are not implemented yet");
}
- schedWaitCond.signal();
+ if (notify) {
+ schedWaitCond.signal();
+ }
} finally {
schedLock.unlock();
}
@@ -125,12 +134,28 @@ public class MasterProcedureScheduler implements ProcedureRunnableSet {
private <T extends Comparable<T>> void doAdd(final FairQueue<T> fairq,
final Queue<T> queue, final Procedure proc, final boolean addFront) {
+ if (proc.isSuspended()) return;
+
queue.add(proc, addFront);
+
if (!(queue.isSuspended() || queue.hasExclusiveLock())) {
+ // the queue is not suspended or removed from the fairq (run-queue)
+ // because someone has an xlock on it.
+ // so, if the queue is not-linked we should add it
if (queue.size() == 1 && !IterableList.isLinked(queue)) {
fairq.add(queue);
}
queueSize++;
+ } else if (proc.hasParent() && queue.isLockOwner(proc.getParentProcId())) {
+ assert addFront : "expected to add a child in the front";
+ assert !queue.isSuspended() : "unexpected suspended state for the queue";
+ // our (proc) parent has the xlock,
+ // so the queue is not in the fairq (run-queue)
+ // add it back to let the child run (inherit the lock)
+ if (!IterableList.isLinked(queue)) {
+ fairq.add(queue);
+ }
+ queueSize++;
}
}
@@ -140,7 +165,7 @@ public class MasterProcedureScheduler implements ProcedureRunnableSet {
}
@edu.umd.cs.findbugs.annotations.SuppressWarnings("WA_AWAIT_NOT_IN_LOOP")
- Procedure poll(long waitNsec) {
+ protected Procedure poll(long waitNsec) {
Procedure pollResult = null;
schedLock.lock();
try {
@@ -185,7 +210,16 @@ public class MasterProcedureScheduler implements ProcedureRunnableSet {
this.queueSize--;
if (rq.isEmpty() || rq.requireExclusiveLock(pollResult)) {
removeFromRunQueue(fairq, rq);
+ } else if (pollResult.hasParent() && rq.isLockOwner(pollResult.getParentProcId())) {
+ // if the rq is in the fairq because of runnable child
+ // check if the next procedure is still a child.
+ // if not, remove the rq from the fairq and go back to the xlock state
+ Procedure nextProc = rq.peek();
+ if (nextProc != null && nextProc.getParentProcId() != pollResult.getParentProcId()) {
+ removeFromRunQueue(fairq, rq);
+ }
}
+
return pollResult;
}
@@ -300,18 +334,25 @@ public class MasterProcedureScheduler implements ProcedureRunnableSet {
}
public boolean waitEvent(ProcedureEvent event, Procedure procedure, boolean suspendQueue) {
+ return waitEvent(event, /* lockEvent= */false, procedure, suspendQueue);
+ }
+
+ private boolean waitEvent(ProcedureEvent event, boolean lockEvent,
+ Procedure procedure, boolean suspendQueue) {
synchronized (event) {
if (event.isReady()) {
+ if (lockEvent) {
+ event.setReady(false);
+ }
return false;
}
- // TODO: Suspend single procedure not implemented yet, fallback to suspending the queue
- if (!suspendQueue) suspendQueue = true;
-
- if (isTableProcedure(procedure)) {
- waitTableEvent(event, procedure, suspendQueue);
+ if (!suspendQueue) {
+ suspendProcedure(event, procedure);
+ } else if (isTableProcedure(procedure)) {
+ waitTableEvent(event, procedure);
} else if (isServerProcedure(procedure)) {
- waitServerEvent(event, procedure, suspendQueue);
+ waitServerEvent(event, procedure);
} else {
// TODO: at the moment we only have Table and Server procedures
// if you are implementing a non-table/non-server procedure, you have two options: create
@@ -324,17 +365,16 @@ public class MasterProcedureScheduler implements ProcedureRunnableSet {
return true;
}
- private void waitTableEvent(ProcedureEvent event, Procedure procedure, boolean suspendQueue) {
+ private void waitTableEvent(ProcedureEvent event, Procedure procedure) {
final TableName tableName = getTableName(procedure);
final boolean isDebugEnabled = LOG.isDebugEnabled();
schedLock.lock();
try {
TableQueue queue = getTableQueue(tableName);
+ queue.addFront(procedure);
if (queue.isSuspended()) return;
- // TODO: if !suspendQueue
-
if (isDebugEnabled) {
LOG.debug("Suspend table queue " + tableName);
}
@@ -346,7 +386,7 @@ public class MasterProcedureScheduler implements ProcedureRunnableSet {
}
}
- private void waitServerEvent(ProcedureEvent event, Procedure procedure, boolean suspendQueue) {
+ private void waitServerEvent(ProcedureEvent event, Procedure procedure) {
final ServerName serverName = getServerName(procedure);
final boolean isDebugEnabled = LOG.isDebugEnabled();
@@ -354,10 +394,9 @@ public class MasterProcedureScheduler implements ProcedureRunnableSet {
try {
// TODO: This will change once we have the new AM
ServerQueue queue = getServerQueue(serverName);
+ queue.addFront(procedure);
if (queue.isSuspended()) return;
- // TODO: if !suspendQueue
-
if (isDebugEnabled) {
LOG.debug("Suspend server queue " + serverName);
}
@@ -399,6 +438,10 @@ public class MasterProcedureScheduler implements ProcedureRunnableSet {
addToRunQueue(serverRunQueue, queue);
}
+ while (event.hasWaitingProcedures()) {
+ wakeProcedure(event.popWaitingProcedure(false));
+ }
+
if (queueSize > 1) {
schedWaitCond.signalAll();
} else if (queueSize > 0) {
@@ -410,7 +453,41 @@ public class MasterProcedureScheduler implements ProcedureRunnableSet {
}
}
- public static class ProcedureEvent {
+ private void suspendProcedure(BaseProcedureEvent event, Procedure procedure) {
+ procedure.suspend();
+ event.suspendProcedure(procedure);
+ }
+
+ private void wakeProcedure(Procedure procedure) {
+ procedure.resume();
+ doAdd(procedure, /* addFront= */ true, /* notify= */false);
+ }
+
+ private static abstract class BaseProcedureEvent {
+ private ArrayDeque<Procedure> waitingProcedures = null;
+
+ protected void suspendProcedure(Procedure proc) {
+ if (waitingProcedures == null) {
+ waitingProcedures = new ArrayDeque<Procedure>();
+ }
+ waitingProcedures.addLast(proc);
+ }
+
+ protected boolean hasWaitingProcedures() {
+ return waitingProcedures != null;
+ }
+
+ protected Procedure popWaitingProcedure(boolean popFront) {
+ // it will be nice to use IterableList on a procedure and avoid allocations...
+ Procedure proc = popFront ? waitingProcedures.removeFirst() : waitingProcedures.removeLast();
+ if (waitingProcedures.isEmpty()) {
+ waitingProcedures = null;
+ }
+ return proc;
+ }
+ }
+
+ public static class ProcedureEvent extends BaseProcedureEvent {
private final String description;
private Queue<ServerName> waitingServers = null;
@@ -585,9 +662,47 @@ public class MasterProcedureScheduler implements ProcedureRunnableSet {
}
}
+ private static class RegionEvent extends BaseProcedureEvent {
+ private final HRegionInfo regionInfo;
+ private long exclusiveLockProcIdOwner = Long.MIN_VALUE;
+
+ public RegionEvent(HRegionInfo regionInfo) {
+ this.regionInfo = regionInfo;
+ }
+
+ public boolean hasExclusiveLock() {
+ return exclusiveLockProcIdOwner != Long.MIN_VALUE;
+ }
+
+ public boolean isLockOwner(long procId) {
+ return exclusiveLockProcIdOwner == procId;
+ }
+
+ public boolean tryExclusiveLock(long procIdOwner) {
+ assert procIdOwner != Long.MIN_VALUE;
+ if (hasExclusiveLock()) return false;
+ exclusiveLockProcIdOwner = procIdOwner;
+ return true;
+ }
+
+ private void releaseExclusiveLock() {
+ exclusiveLockProcIdOwner = Long.MIN_VALUE;
+ }
+
+ public HRegionInfo getRegionInfo() {
+ return regionInfo;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("region %s event", regionInfo.getRegionNameAsString());
+ }
+ }
+
public static class TableQueue extends QueueImpl<TableName> {
private final NamespaceQueue namespaceQueue;
+ private HashMap<HRegionInfo, RegionEvent> regionEventMap;
private TableLock tableLock = null;
public TableQueue(TableName tableName, NamespaceQueue namespaceQueue, int priority) {
@@ -601,7 +716,41 @@ public class MasterProcedureScheduler implements ProcedureRunnableSet {
@Override
public synchronized boolean isAvailable() {
- return super.isAvailable() && !namespaceQueue.hasExclusiveLock();
+ // if there are no items in the queue, or the namespace is locked.
+ // we can't execute operation on this table
+ if (isEmpty() || namespaceQueue.hasExclusiveLock()) {
+ return false;
+ }
+
+ if (hasExclusiveLock()) {
+ // if we have an exclusive lock already taken
+ // only child of the lock owner can be executed
+ Procedure availProc = peek();
+ return availProc != null && availProc.hasParent() &&
+ isLockOwner(availProc.getParentProcId());
+ }
+
+ // no xlock
+ return true;
+ }
+
+ public synchronized RegionEvent getRegionEvent(final HRegionInfo regionInfo) {
+ if (regionEventMap == null) {
+ regionEventMap = new HashMap<HRegionInfo, RegionEvent>();
+ }
+ RegionEvent event = regionEventMap.get(regionInfo);
+ if (event == null) {
+ event = new RegionEvent(regionInfo);
+ regionEventMap.put(regionInfo, event);
+ }
+ return event;
+ }
+
+ public synchronized void removeRegionEvent(final RegionEvent event) {
+ regionEventMap.remove(event.getRegionInfo());
+ if (regionEventMap.isEmpty()) {
+ regionEventMap = null;
+ }
}
// TODO: We can abort pending/in-progress operation if the new call is
@@ -630,6 +779,13 @@ public class MasterProcedureScheduler implements ProcedureRunnableSet {
return !tpi.getTableName().equals(TableName.NAMESPACE_TABLE_NAME);
case READ:
return false;
+ // region operations are using the shared-lock on the table
+ // and then they will grab an xlock on the region.
+ case SPLIT:
+ case MERGE:
+ case ASSIGN:
+ case UNASSIGN:
+ return false;
default:
break;
}
@@ -883,6 +1039,100 @@ public class MasterProcedureScheduler implements ProcedureRunnableSet {
}
// ============================================================================
+ // Region Locking Helpers
+ // ============================================================================
+ public boolean waitRegion(final Procedure procedure, final HRegionInfo regionInfo) {
+ return waitRegions(procedure, regionInfo.getTable(), regionInfo);
+ }
+
+ public boolean waitRegions(final Procedure procedure, final TableName table,
+ final HRegionInfo... regionInfo) {
+ Arrays.sort(regionInfo);
+
+ final TableQueue queue;
+ if (procedure.hasParent()) {
+ // the assumption is that the parent procedure have already the table xlock
+ queue = getTableQueueWithLock(table);
+ } else {
+ // acquire the table shared-lock
+ queue = tryAcquireTableQueueSharedLock(procedure, table);
+ if (queue == null) return false;
+ }
+
+ // acquire region xlocks or wait
+ boolean hasLock = true;
+ final RegionEvent[] event = new RegionEvent[regionInfo.length];
+ synchronized (queue) {
+ for (int i = 0; i < regionInfo.length; ++i) {
+ assert regionInfo[i].getTable().equals(table);
+ event[i] = queue.getRegionEvent(regionInfo[i]);
+ if (!event[i].tryExclusiveLock(procedure.getProcId())) {
+ suspendProcedure(event[i], procedure);
+ hasLock = false;
+ while (i-- > 0) {
+ event[i].releaseExclusiveLock();
+ }
+ break;
+ }
+ }
+ }
+
+ if (!hasLock && !procedure.hasParent()) {
+ releaseTableSharedLock(procedure, table);
+ }
+ return hasLock;
+ }
+
+ public void wakeRegion(final Procedure procedure, final HRegionInfo regionInfo) {
+ wakeRegions(procedure, regionInfo.getTable(), regionInfo);
+ }
+
+ public void wakeRegions(final Procedure procedure,final TableName table,
+ final HRegionInfo... regionInfo) {
+ Arrays.sort(regionInfo);
+
+ final TableQueue queue = getTableQueueWithLock(table);
+
+ int numProcs = 0;
+ final Procedure[] nextProcs = new Procedure[regionInfo.length];
+ synchronized (queue) {
+ for (int i = 0; i < regionInfo.length; ++i) {
+ assert regionInfo[i].getTable().equals(table);
+ RegionEvent event = queue.getRegionEvent(regionInfo[i]);
+ event.releaseExclusiveLock();
+ if (event.hasWaitingProcedures()) {
+ // release one procedure at the time since regions has an xlock
+ nextProcs[numProcs++] = event.popWaitingProcedure(true);
+ } else {
+ queue.removeRegionEvent(event);
+ }
+ }
+ }
+
+ // awake procedures if any
+ schedLock.lock();
+ try {
+ for (int i = numProcs - 1; i >= 0; --i) {
+ wakeProcedure(nextProcs[i]);
+ }
+
+ if (numProcs > 1) {
+ schedWaitCond.signalAll();
+ } else if (numProcs > 0) {
+ schedWaitCond.signal();
+ }
+
+ if (!procedure.hasParent()) {
+ // release the table shared-lock.
+ // (if we have a parent, it is holding an xlock so we didn't take the shared-lock)
+ releaseTableSharedLock(procedure, table);
+ }
+ } finally {
+ schedLock.unlock();
+ }
+ }
+
+ // ============================================================================
// Namespace Locking Helpers
// ============================================================================
/**
@@ -1080,6 +1330,10 @@ public class MasterProcedureScheduler implements ProcedureRunnableSet {
return sharedLock == 1;
}
+ public synchronized boolean isLockOwner(long procId) {
+ return exclusiveLockProcIdOwner == procId;
+ }
+
public synchronized boolean tryExclusiveLock(long procIdOwner) {
assert procIdOwner != Long.MIN_VALUE;
if (isLocked()) return false;
http://git-wip-us.apache.org/repos/asf/hbase/blob/d5d9b7d5/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TableProcedureInterface.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TableProcedureInterface.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TableProcedureInterface.java
index cc088f3..deaf406 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TableProcedureInterface.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TableProcedureInterface.java
@@ -31,6 +31,7 @@ import org.apache.hadoop.hbase.classification.InterfaceStability;
public interface TableProcedureInterface {
public enum TableOperationType {
CREATE, DELETE, DISABLE, EDIT, ENABLE, READ,
+ SPLIT, MERGE, ASSIGN, UNASSIGN, /* region operations */
};
/**
http://git-wip-us.apache.org/repos/asf/hbase/blob/d5d9b7d5/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestMasterProcedureScheduler.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestMasterProcedureScheduler.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestMasterProcedureScheduler.java
index 12042d8..9c37404 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestMasterProcedureScheduler.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestMasterProcedureScheduler.java
@@ -18,7 +18,6 @@
package org.apache.hadoop.hbase.master.procedure;
-
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
@@ -29,12 +28,15 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.master.TableLockManager;
+import org.apache.hadoop.hbase.master.procedure.MasterProcedureScheduler.ProcedureEvent;
import org.apache.hadoop.hbase.procedure2.Procedure;
import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility.TestProcedure;
import org.apache.hadoop.hbase.testclassification.SmallTests;
import org.apache.hadoop.hbase.testclassification.MasterTests;
+import org.apache.hadoop.hbase.util.Bytes;
import org.junit.After;
import org.junit.Before;
@@ -60,7 +62,8 @@ public class TestMasterProcedureScheduler {
@After
public void tearDown() throws IOException {
- assertEquals(0, queue.size());
+ assertEquals("proc-queue expected to be empty", 0, queue.size());
+ queue.clear();
}
@Test
@@ -346,6 +349,201 @@ public class TestMasterProcedureScheduler {
assertEquals(4, procId);
}
+ @Test
+ public void testVerifyRegionLocks() throws Exception {
+ final TableName tableName = TableName.valueOf("testtb");
+ final HRegionInfo regionA = new HRegionInfo(tableName, Bytes.toBytes("a"), Bytes.toBytes("b"));
+ final HRegionInfo regionB = new HRegionInfo(tableName, Bytes.toBytes("b"), Bytes.toBytes("c"));
+ final HRegionInfo regionC = new HRegionInfo(tableName, Bytes.toBytes("c"), Bytes.toBytes("d"));
+
+ queue.addBack(new TestTableProcedure(1, tableName,
+ TableProcedureInterface.TableOperationType.EDIT));
+ queue.addBack(new TestRegionProcedure(2, tableName,
+ TableProcedureInterface.TableOperationType.MERGE, regionA, regionB));
+ queue.addBack(new TestRegionProcedure(3, tableName,
+ TableProcedureInterface.TableOperationType.SPLIT, regionA));
+ queue.addBack(new TestRegionProcedure(4, tableName,
+ TableProcedureInterface.TableOperationType.SPLIT, regionB));
+ queue.addBack(new TestRegionProcedure(5, tableName,
+ TableProcedureInterface.TableOperationType.UNASSIGN, regionC));
+
+ // Fetch the 1st item and take the write lock
+ Procedure proc = queue.poll();
+ assertEquals(1, proc.getProcId());
+ assertEquals(true, queue.tryAcquireTableExclusiveLock(proc, tableName));
+
+ // everything is locked by the table operation
+ assertEquals(null, queue.poll(0));
+
+ // release the table lock
+ queue.releaseTableExclusiveLock(proc, tableName);
+
+ // Fetch the 2nd item and the the lock on regionA and regionB
+ Procedure mergeProc = queue.poll();
+ assertEquals(2, mergeProc.getProcId());
+ assertEquals(true, queue.waitRegions(mergeProc, tableName, regionA, regionB));
+
+ // Fetch the 3rd item and the try to lock region A which will fail
+ // because already locked. this procedure will go in waiting.
+ // (this stuff will be explicit until we get rid of the zk-lock)
+ Procedure procA = queue.poll();
+ assertEquals(3, procA.getProcId());
+ assertEquals(false, queue.waitRegions(procA, tableName, regionA));
+
+ // Fetch the 4th item, same story as the 3rd
+ Procedure procB = queue.poll();
+ assertEquals(4, procB.getProcId());
+ assertEquals(false, queue.waitRegions(procB, tableName, regionB));
+
+ // Fetch the 5th item, since it is a non-locked region we are able to execute it
+ Procedure procC = queue.poll();
+ assertEquals(5, procC.getProcId());
+ assertEquals(true, queue.waitRegions(procC, tableName, regionC));
+
+ // 3rd and 4th are in the region suspended queue
+ assertEquals(null, queue.poll(0));
+
+ // Release region A-B from merge operation (procId=2)
+ queue.wakeRegions(mergeProc, tableName, regionA, regionB);
+
+ // Fetch the 3rd item, now the lock on the region is available
+ procA = queue.poll();
+ assertEquals(3, procA.getProcId());
+ assertEquals(true, queue.waitRegions(procA, tableName, regionA));
+
+ // Fetch the 4th item, now the lock on the region is available
+ procB = queue.poll();
+ assertEquals(4, procB.getProcId());
+ assertEquals(true, queue.waitRegions(procB, tableName, regionB));
+
+ // release the locks on the regions
+ queue.wakeRegions(procA, tableName, regionA);
+ queue.wakeRegions(procB, tableName, regionB);
+ queue.wakeRegions(procC, tableName, regionC);
+ }
+
+ @Test
+ public void testVerifySubProcRegionLocks() throws Exception {
+ final TableName tableName = TableName.valueOf("testVerifySubProcRegionLocks");
+ final HRegionInfo regionA = new HRegionInfo(tableName, Bytes.toBytes("a"), Bytes.toBytes("b"));
+ final HRegionInfo regionB = new HRegionInfo(tableName, Bytes.toBytes("b"), Bytes.toBytes("c"));
+ final HRegionInfo regionC = new HRegionInfo(tableName, Bytes.toBytes("c"), Bytes.toBytes("d"));
+
+ queue.addBack(new TestTableProcedure(1, tableName,
+ TableProcedureInterface.TableOperationType.ENABLE));
+
+ // Fetch the 1st item from the queue, "the root procedure" and take the table lock
+ Procedure rootProc = queue.poll();
+ assertEquals(1, rootProc.getProcId());
+ assertEquals(true, queue.tryAcquireTableExclusiveLock(rootProc, tableName));
+ assertEquals(null, queue.poll(0));
+
+ // Execute the 1st step of the root-proc.
+ // we should get 3 sub-proc back, one for each region.
+ // (this step is done by the executor/rootProc, we are simulating it)
+ Procedure[] subProcs = new Procedure[] {
+ new TestRegionProcedure(1, 2, tableName,
+ TableProcedureInterface.TableOperationType.ASSIGN, regionA),
+ new TestRegionProcedure(1, 3, tableName,
+ TableProcedureInterface.TableOperationType.ASSIGN, regionB),
+ new TestRegionProcedure(1, 4, tableName,
+ TableProcedureInterface.TableOperationType.ASSIGN, regionC),
+ };
+
+ // at this point the rootProc is going in a waiting state
+ // and the sub-procedures will be added in the queue.
+ // (this step is done by the executor, we are simulating it)
+ for (int i = subProcs.length - 1; i >= 0; --i) {
+ queue.addFront(subProcs[i]);
+ }
+ assertEquals(subProcs.length, queue.size());
+
+ // we should be able to fetch and execute all the sub-procs,
+ // since they are operating on different regions
+ for (int i = 0; i < subProcs.length; ++i) {
+ TestRegionProcedure regionProc = (TestRegionProcedure)queue.poll(0);
+ assertEquals(subProcs[i].getProcId(), regionProc.getProcId());
+ assertEquals(true, queue.waitRegions(regionProc, tableName, regionProc.getRegionInfo()));
+ }
+
+ // nothing else in the queue
+ assertEquals(null, queue.poll(0));
+
+ // release all the region locks
+ for (int i = 0; i < subProcs.length; ++i) {
+ TestRegionProcedure regionProc = (TestRegionProcedure)subProcs[i];
+ queue.wakeRegions(regionProc, tableName, regionProc.getRegionInfo());
+ }
+
+ // nothing else in the queue
+ assertEquals(null, queue.poll(0));
+
+ // release the table lock (for the root procedure)
+ queue.releaseTableExclusiveLock(rootProc, tableName);
+ }
+
+ @Test
+ public void testSuspendedTableQueue() throws Exception {
+ final TableName tableName = TableName.valueOf("testSuspendedQueue");
+
+ queue.addBack(new TestTableProcedure(1, tableName,
+ TableProcedureInterface.TableOperationType.EDIT));
+ queue.addBack(new TestTableProcedure(2, tableName,
+ TableProcedureInterface.TableOperationType.EDIT));
+
+ Procedure proc = queue.poll();
+ assertEquals(1, proc.getProcId());
+ assertTrue(queue.tryAcquireTableExclusiveLock(proc, tableName));
+
+ // Suspend
+ // TODO: If we want to keep the zk-lock we need to retain the lock on suspend
+ ProcedureEvent event = new ProcedureEvent("testSuspendedTableQueueEvent");
+ queue.waitEvent(event, proc, true);
+ queue.releaseTableExclusiveLock(proc, tableName);
+ assertEquals(null, queue.poll(0));
+
+ // Resume
+ queue.wake(event);
+
+ proc = queue.poll();
+ assertTrue(queue.tryAcquireTableExclusiveLock(proc, tableName));
+ assertEquals(1, proc.getProcId());
+ queue.releaseTableExclusiveLock(proc, tableName);
+
+ proc = queue.poll();
+ assertTrue(queue.tryAcquireTableExclusiveLock(proc, tableName));
+ assertEquals(2, proc.getProcId());
+ queue.releaseTableExclusiveLock(proc, tableName);
+ }
+
+ @Test
+ public void testSuspendedProcedure() throws Exception {
+ final TableName tableName = TableName.valueOf("testSuspendedProcedure");
+
+ queue.addBack(new TestTableProcedure(1, tableName,
+ TableProcedureInterface.TableOperationType.READ));
+ queue.addBack(new TestTableProcedure(2, tableName,
+ TableProcedureInterface.TableOperationType.READ));
+
+ Procedure proc = queue.poll();
+ assertEquals(1, proc.getProcId());
+
+ // suspend
+ ProcedureEvent event = new ProcedureEvent("testSuspendedProcedureEvent");
+ queue.waitEvent(event, proc);
+
+ proc = queue.poll();
+ assertEquals(2, proc.getProcId());
+ assertEquals(null, queue.poll(0));
+
+ // resume
+ queue.wake(event);
+
+ proc = queue.poll();
+ assertEquals(1, proc.getProcId());
+ assertEquals(null, queue.poll(0));
+ }
+
/**
* Verify that "write" operations for a single table are serialized,
* but different tables can be executed in parallel.
@@ -522,6 +720,32 @@ public class TestMasterProcedureScheduler {
}
}
+ public static class TestRegionProcedure extends TestTableProcedure {
+ private final HRegionInfo[] regionInfo;
+
+ public TestRegionProcedure() {
+ throw new UnsupportedOperationException("recovery should not be triggered here");
+ }
+
+ public TestRegionProcedure(long procId, TableName tableName, TableOperationType opType,
+ HRegionInfo... regionInfo) {
+ this(-1, procId, tableName, opType, regionInfo);
+ }
+
+ public TestRegionProcedure(long parentProcId, long procId, TableName tableName,
+ TableOperationType opType, HRegionInfo... regionInfo) {
+ super(procId, tableName, opType);
+ this.regionInfo = regionInfo;
+ if (parentProcId > 0) {
+ setParentProcId(parentProcId);
+ }
+ }
+
+ public HRegionInfo[] getRegionInfo() {
+ return regionInfo;
+ }
+ }
+
public static class TestNamespaceProcedure extends TestProcedure
implements TableProcedureInterface {
private final TableOperationType opType;
[2/2] hbase git commit: HBASE-15989 Remove
hbase.online.schema.update.enable
Posted by mb...@apache.org.
HBASE-15989 Remove hbase.online.schema.update.enable
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/d9463bcc
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/d9463bcc
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/d9463bcc
Branch: refs/heads/master
Commit: d9463bcce0e36bfb67c82acd1d7483f63b2764b7
Parents: d5d9b7d
Author: Matteo Bertozzi <ma...@cloudera.com>
Authored: Wed Jun 8 13:09:31 2016 -0700
Committer: Matteo Bertozzi <ma...@cloudera.com>
Committed: Wed Jun 8 13:09:31 2016 -0700
----------------------------------------------------------------------
.../client/replication/ReplicationAdmin.java | 13 +-----
.../src/main/resources/hbase-default.xml | 9 +----
.../procedure/MasterDDLOperationHelper.java | 15 -------
.../master/procedure/ModifyTableProcedure.java | 5 ---
.../apache/hadoop/hbase/client/TestAdmin1.java | 42 --------------------
.../apache/hadoop/hbase/client/TestAdmin2.java | 1 -
.../client/TestCloneSnapshotFromClient.java | 1 -
.../hbase/client/TestFromClientSide3.java | 2 -
.../client/TestRestoreSnapshotFromClient.java | 1 -
.../hbase/io/encoding/TestChangingEncoding.java | 1 -
.../hbase/master/TestTableLockManager.java | 1 -
.../regionserver/TestEncryptionKeyRotation.java | 4 +-
...sibilityLabelReplicationWithExpAsString.java | 1 -
.../TestVisibilityLabelsReplication.java | 1 -
...ibilityLabelsWithDefaultVisLabelService.java | 1 -
.../TestRestoreFlushSnapshotFromClient.java | 1 -
.../src/main/ruby/shell/commands/alter.rb | 16 ++++----
.../hadoop/hbase/client/AbstractTestShell.java | 1 -
.../hbase/client/rsgroup/TestShellRSGroups.java | 1 -
src/main/asciidoc/_chapters/hbase-default.adoc | 10 -----
20 files changed, 12 insertions(+), 115 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hbase/blob/d9463bcc/hbase-client/src/main/java/org/apache/hadoop/hbase/client/replication/ReplicationAdmin.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/replication/ReplicationAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/replication/ReplicationAdmin.java
index a2ad2e7..d062448 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/replication/ReplicationAdmin.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/replication/ReplicationAdmin.java
@@ -516,9 +516,9 @@ public class ReplicationAdmin implements Closeable {
if (repPeers == null || repPeers.size() <= 0) {
throw new IllegalArgumentException("Found no peer cluster for replication.");
}
-
+
final TableName onlyTableNameQualifier = TableName.valueOf(tableName.getQualifierAsString());
-
+
for (ReplicationPeer repPeer : repPeers) {
Map<TableName, List<String>> tableCFMap = repPeer.getTableCFs();
// TODO Currently peer TableCFs will not include namespace so we need to check only for table
@@ -595,20 +595,11 @@ public class ReplicationAdmin implements Closeable {
admin = this.connection.getAdmin();
HTableDescriptor htd = admin.getTableDescriptor(tableName);
if (isTableRepEnabled(htd) ^ isRepEnabled) {
- boolean isOnlineSchemaUpdateEnabled =
- this.connection.getConfiguration()
- .getBoolean("hbase.online.schema.update.enable", true);
- if (!isOnlineSchemaUpdateEnabled) {
- admin.disableTable(tableName);
- }
for (HColumnDescriptor hcd : htd.getFamilies()) {
hcd.setScope(isRepEnabled ? HConstants.REPLICATION_SCOPE_GLOBAL
: HConstants.REPLICATION_SCOPE_LOCAL);
}
admin.modifyTable(tableName, htd);
- if (!isOnlineSchemaUpdateEnabled) {
- admin.enableTable(tableName);
- }
}
} finally {
if (admin != null) {
http://git-wip-us.apache.org/repos/asf/hbase/blob/d9463bcc/hbase-common/src/main/resources/hbase-default.xml
----------------------------------------------------------------------
diff --git a/hbase-common/src/main/resources/hbase-default.xml b/hbase-common/src/main/resources/hbase-default.xml
index 62a6b62..55ac497 100644
--- a/hbase-common/src/main/resources/hbase-default.xml
+++ b/hbase-common/src/main/resources/hbase-default.xml
@@ -562,7 +562,7 @@ possible configurations would overwhelm and obscure the important.
<property>
<name>hbase.regions.slop</name>
<value>0.001</value>
- <description>Rebalance if any regionserver has average + (average * slop) regions.
+ <description>Rebalance if any regionserver has average + (average * slop) regions.
The default value of this parameter is 0.001 in StochasticLoadBalancer (the default load balancer),
while the default is 0.2 in other load balancers (i.e., SimpleLoadBalancer).</description>
</property>
@@ -865,7 +865,7 @@ possible configurations would overwhelm and obscure the important.
Must be a multiple of 1024 else you will run into
'java.io.IOException: Invalid HFile block magic' when you go to read from cache.
If you specify no values here, then you pick up the default bucketsizes set
- in code (See BucketAllocator#DEFAULT_BUCKET_SIZES).
+ in code (See BucketAllocator#DEFAULT_BUCKET_SIZES).
</description>
</property>
<property>
@@ -1132,11 +1132,6 @@ possible configurations would overwhelm and obscure the important.
of servers, so this is most useful for debugging only.</description>
</property>
<property>
- <name>hbase.online.schema.update.enable</name>
- <value>true</value>
- <description>Set true to enable online schema changes.</description>
- </property>
- <property>
<name>hbase.table.lock.enable</name>
<value>true</value>
<description>Set to true to enable locking the table in zookeeper for schema change operations.
http://git-wip-us.apache.org/repos/asf/hbase/blob/d9463bcc/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/MasterDDLOperationHelper.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/MasterDDLOperationHelper.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/MasterDDLOperationHelper.java
index f2ee97f..1214268 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/MasterDDLOperationHelper.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/MasterDDLOperationHelper.java
@@ -56,14 +56,6 @@ public final class MasterDDLOperationHelper {
private MasterDDLOperationHelper() {}
/**
- * Check whether online schema change is allowed from config
- **/
- public static boolean isOnlineSchemaChangeAllowed(final MasterProcedureEnv env) {
- return env.getMasterServices().getConfiguration()
- .getBoolean("hbase.online.schema.update.enable", false);
- }
-
- /**
* Check whether a table is modifiable - exists and either offline or online with config set
* @param env MasterProcedureEnv
* @param tableName name of the table
@@ -75,13 +67,6 @@ public final class MasterDDLOperationHelper {
if (!MetaTableAccessor.tableExists(env.getMasterServices().getConnection(), tableName)) {
throw new TableNotFoundException(tableName);
}
-
- // We only execute this procedure with table online if online schema change config is set.
- if (!env.getMasterServices().getTableStateManager()
- .isTableState(tableName, TableState.State.DISABLED)
- && !MasterDDLOperationHelper.isOnlineSchemaChangeAllowed(env)) {
- throw new TableNotDisabledException(tableName);
- }
}
/**
http://git-wip-us.apache.org/repos/asf/hbase/blob/d9463bcc/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 3f76df3..6c65718 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
@@ -300,11 +300,6 @@ public class ModifyTableProcedure
if (env.getMasterServices().getTableStateManager()
.isTableState(getTableName(), TableState.State.ENABLED)) {
- // We only execute this procedure with table online if online schema change config is set.
- if (!MasterDDLOperationHelper.isOnlineSchemaChangeAllowed(env)) {
- throw new TableNotDisabledException(getTableName());
- }
-
if (modifiedHTableDescriptor.getRegionReplication() != unmodifiedHTableDescriptor
.getRegionReplication()) {
throw new IOException("REGION_REPLICATION change is not supported for enabled tables");
http://git-wip-us.apache.org/repos/asf/hbase/blob/d9463bcc/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin1.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin1.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin1.java
index 545fccd..fd55f66 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin1.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin1.java
@@ -85,7 +85,6 @@ public class TestAdmin1 {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
- TEST_UTIL.getConfiguration().setBoolean("hbase.online.schema.update.enable", true);
TEST_UTIL.getConfiguration().setInt("hbase.regionserver.msginterval", 100);
TEST_UTIL.getConfiguration().setInt("hbase.client.pause", 250);
TEST_UTIL.getConfiguration().setInt("hbase.client.retries.number", 6);
@@ -503,8 +502,6 @@ public class TestAdmin1 {
public void testOnlineChangeTableSchema() throws IOException, InterruptedException {
final TableName tableName =
TableName.valueOf("changeTableSchemaOnline");
- TEST_UTIL.getMiniHBaseCluster().getMaster().getConfiguration().setBoolean(
- "hbase.online.schema.update.enable", true);
HTableDescriptor [] tables = admin.listTables();
int numTables = tables.length;
TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY).close();
@@ -588,45 +585,6 @@ public class TestAdmin1 {
assertFalse(this.admin.tableExists(tableName));
}
- @Test (timeout=300000)
- public void testShouldFailOnlineSchemaUpdateIfOnlineSchemaIsNotEnabled()
- throws Exception {
- final TableName tableName = TableName.valueOf("changeTableSchemaOnlineFailure");
- TEST_UTIL.getMiniHBaseCluster().getMaster().getConfiguration().setBoolean(
- "hbase.online.schema.update.enable", false);
- HTableDescriptor[] tables = admin.listTables();
- int numTables = tables.length;
- TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY).close();
- tables = this.admin.listTables();
- assertEquals(numTables + 1, tables.length);
-
- // FIRST, do htabledescriptor changes.
- HTableDescriptor htd = this.admin.getTableDescriptor(tableName);
- // Make a copy and assert copy is good.
- HTableDescriptor copy = new HTableDescriptor(htd);
- assertTrue(htd.equals(copy));
- // Now amend the copy. Introduce differences.
- long newFlushSize = htd.getMemStoreFlushSize() / 2;
- if (newFlushSize <=0) {
- newFlushSize = HTableDescriptor.DEFAULT_MEMSTORE_FLUSH_SIZE / 2;
- }
- copy.setMemStoreFlushSize(newFlushSize);
- final String key = "anyoldkey";
- assertTrue(htd.getValue(key) == null);
- copy.setValue(key, key);
- boolean expectedException = false;
- try {
- admin.modifyTable(tableName, copy);
- } catch (TableNotDisabledException re) {
- expectedException = true;
- }
- assertTrue("Online schema update should not happen.", expectedException);
-
- // Reset the value for the other tests
- TEST_UTIL.getMiniHBaseCluster().getMaster().getConfiguration().setBoolean(
- "hbase.online.schema.update.enable", true);
- }
-
protected void verifyRoundRobinDistribution(ClusterConnection c, RegionLocator regionLocator, int
expectedRegions) throws IOException {
int numRS = c.getCurrentNrHRS();
http://git-wip-us.apache.org/repos/asf/hbase/blob/d9463bcc/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin2.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin2.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin2.java
index ff53c49..d088fc4 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin2.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin2.java
@@ -83,7 +83,6 @@ public class TestAdmin2 {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
- TEST_UTIL.getConfiguration().setBoolean("hbase.online.schema.update.enable", true);
TEST_UTIL.getConfiguration().setInt("hbase.regionserver.msginterval", 100);
TEST_UTIL.getConfiguration().setInt("hbase.client.pause", 250);
TEST_UTIL.getConfiguration().setInt("hbase.client.retries.number", 6);
http://git-wip-us.apache.org/repos/asf/hbase/blob/d9463bcc/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestCloneSnapshotFromClient.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestCloneSnapshotFromClient.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestCloneSnapshotFromClient.java
index aeb82f4..65a67d0 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestCloneSnapshotFromClient.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestCloneSnapshotFromClient.java
@@ -61,7 +61,6 @@ public class TestCloneSnapshotFromClient {
protected static void setupConfiguration() {
TEST_UTIL.getConfiguration().setBoolean(SnapshotManager.HBASE_SNAPSHOT_ENABLED, true);
- TEST_UTIL.getConfiguration().setBoolean("hbase.online.schema.update.enable", true);
TEST_UTIL.getConfiguration().setInt("hbase.hstore.compactionThreshold", 10);
TEST_UTIL.getConfiguration().setInt("hbase.regionserver.msginterval", 100);
TEST_UTIL.getConfiguration().setInt("hbase.client.pause", 250);
http://git-wip-us.apache.org/repos/asf/hbase/blob/d9463bcc/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide3.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide3.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide3.java
index a967d97..a918ce6 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide3.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide3.java
@@ -70,8 +70,6 @@ public class TestFromClientSide3 {
*/
@BeforeClass
public static void setUpBeforeClass() throws Exception {
- TEST_UTIL.getConfiguration().setBoolean(
- "hbase.online.schema.update.enable", true);
TEST_UTIL.startMiniCluster(SLAVES);
}
http://git-wip-us.apache.org/repos/asf/hbase/blob/d9463bcc/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestRestoreSnapshotFromClient.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestRestoreSnapshotFromClient.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestRestoreSnapshotFromClient.java
index d31df42..a3fc640 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestRestoreSnapshotFromClient.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestRestoreSnapshotFromClient.java
@@ -83,7 +83,6 @@ public class TestRestoreSnapshotFromClient {
protected static void setupConf(Configuration conf) {
TEST_UTIL.getConfiguration().setBoolean(SnapshotManager.HBASE_SNAPSHOT_ENABLED, true);
- TEST_UTIL.getConfiguration().setBoolean("hbase.online.schema.update.enable", true);
TEST_UTIL.getConfiguration().setInt("hbase.hstore.compactionThreshold", 10);
TEST_UTIL.getConfiguration().setInt("hbase.regionserver.msginterval", 100);
TEST_UTIL.getConfiguration().setInt("hbase.client.pause", 250);
http://git-wip-us.apache.org/repos/asf/hbase/blob/d9463bcc/hbase-server/src/test/java/org/apache/hadoop/hbase/io/encoding/TestChangingEncoding.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/io/encoding/TestChangingEncoding.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/encoding/TestChangingEncoding.java
index 6359bef..6cf4d68 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/io/encoding/TestChangingEncoding.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/encoding/TestChangingEncoding.java
@@ -103,7 +103,6 @@ public class TestChangingEncoding {
conf.setInt(HConstants.HREGION_MEMSTORE_FLUSH_SIZE, 1024 * 1024);
// ((Log4JLogger)RpcServerImplementation.LOG).getLogger().setLevel(Level.TRACE);
// ((Log4JLogger)RpcClient.LOG).getLogger().setLevel(Level.TRACE);
- conf.setBoolean("hbase.online.schema.update.enable", true);
TEST_UTIL.startMiniCluster();
}
http://git-wip-us.apache.org/repos/asf/hbase/blob/d9463bcc/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestTableLockManager.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestTableLockManager.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestTableLockManager.java
index 573fdcb..36f505b 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestTableLockManager.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestTableLockManager.java
@@ -88,7 +88,6 @@ public class TestTableLockManager {
private static final CountDownLatch addColumn = new CountDownLatch(1);
public void prepareMiniCluster() throws Exception {
- TEST_UTIL.getConfiguration().setBoolean("hbase.online.schema.update.enable", true);
TEST_UTIL.startMiniCluster(2);
TEST_UTIL.createTable(TABLE_NAME, FAMILY);
}
http://git-wip-us.apache.org/repos/asf/hbase/blob/d9463bcc/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestEncryptionKeyRotation.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestEncryptionKeyRotation.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestEncryptionKeyRotation.java
index 82be1db..cee64e0 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestEncryptionKeyRotation.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestEncryptionKeyRotation.java
@@ -80,8 +80,6 @@ public class TestEncryptionKeyRotation {
conf.setInt("hfile.format.version", 3);
conf.set(HConstants.CRYPTO_KEYPROVIDER_CONF_KEY, KeyProviderForTesting.class.getName());
conf.set(HConstants.CRYPTO_MASTERKEY_NAME_CONF_KEY, "hbase");
- // Enable online schema updates
- conf.setBoolean("hbase.online.schema.update.enable", true);
// Start the minicluster
TEST_UTIL.startMiniCluster(1);
@@ -229,7 +227,7 @@ public class TestEncryptionKeyRotation {
}
}
}
-
+
private static List<Path> findStorefilePaths(TableName tableName) throws Exception {
List<Path> paths = new ArrayList<Path>();
for (Region region:
http://git-wip-us.apache.org/repos/asf/hbase/blob/d9463bcc/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestVisibilityLabelReplicationWithExpAsString.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestVisibilityLabelReplicationWithExpAsString.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestVisibilityLabelReplicationWithExpAsString.java
index 18a1088..9483ac9 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestVisibilityLabelReplicationWithExpAsString.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestVisibilityLabelReplicationWithExpAsString.java
@@ -80,7 +80,6 @@ public class TestVisibilityLabelReplicationWithExpAsString extends TestVisibilit
// setup configuration
conf = HBaseConfiguration.create();
conf.setBoolean(HConstants.DISTRIBUTED_LOG_REPLAY_KEY, false);
- conf.setBoolean("hbase.online.schema.update.enable", true);
conf.setInt("hfile.format.version", 3);
conf.set(HConstants.ZOOKEEPER_ZNODE_PARENT, "/1");
conf.setInt("replication.source.size.capacity", 10240);
http://git-wip-us.apache.org/repos/asf/hbase/blob/d9463bcc/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestVisibilityLabelsReplication.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestVisibilityLabelsReplication.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestVisibilityLabelsReplication.java
index c9d9530..4ed47b0 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestVisibilityLabelsReplication.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestVisibilityLabelsReplication.java
@@ -130,7 +130,6 @@ public class TestVisibilityLabelsReplication {
// setup configuration
conf = HBaseConfiguration.create();
conf.setBoolean(HConstants.DISTRIBUTED_LOG_REPLAY_KEY, false);
- conf.setBoolean("hbase.online.schema.update.enable", true);
conf.setInt("hfile.format.version", 3);
conf.set(HConstants.ZOOKEEPER_ZNODE_PARENT, "/1");
conf.setInt("replication.source.size.capacity", 10240);
http://git-wip-us.apache.org/repos/asf/hbase/blob/d9463bcc/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestVisibilityLabelsWithDefaultVisLabelService.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestVisibilityLabelsWithDefaultVisLabelService.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestVisibilityLabelsWithDefaultVisLabelService.java
index a229bdb..63c08a2 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestVisibilityLabelsWithDefaultVisLabelService.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestVisibilityLabelsWithDefaultVisLabelService.java
@@ -67,7 +67,6 @@ public class TestVisibilityLabelsWithDefaultVisLabelService extends TestVisibili
// setup configuration
conf = TEST_UTIL.getConfiguration();
conf.setBoolean(HConstants.DISTRIBUTED_LOG_REPLAY_KEY, false);
- conf.setBoolean("hbase.online.schema.update.enable", true);
VisibilityTestUtil.enableVisiblityLabels(conf);
conf.setClass(VisibilityUtils.VISIBILITY_LABEL_GENERATOR_CLASS, SimpleScanLabelGenerator.class,
ScanLabelGenerator.class);
http://git-wip-us.apache.org/repos/asf/hbase/blob/d9463bcc/hbase-server/src/test/java/org/apache/hadoop/hbase/snapshot/TestRestoreFlushSnapshotFromClient.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/snapshot/TestRestoreFlushSnapshotFromClient.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/snapshot/TestRestoreFlushSnapshotFromClient.java
index 04fce5c..bf26c69 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/snapshot/TestRestoreFlushSnapshotFromClient.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/snapshot/TestRestoreFlushSnapshotFromClient.java
@@ -70,7 +70,6 @@ public class TestRestoreFlushSnapshotFromClient {
}
protected static void setupConf(Configuration conf) {
- UTIL.getConfiguration().setBoolean("hbase.online.schema.update.enable", true);
UTIL.getConfiguration().setInt("hbase.regionserver.msginterval", 100);
UTIL.getConfiguration().setInt("hbase.client.pause", 250);
UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 6);
http://git-wip-us.apache.org/repos/asf/hbase/blob/d9463bcc/hbase-shell/src/main/ruby/shell/commands/alter.rb
----------------------------------------------------------------------
diff --git a/hbase-shell/src/main/ruby/shell/commands/alter.rb b/hbase-shell/src/main/ruby/shell/commands/alter.rb
index 91b3e2e..8d6b6ca 100644
--- a/hbase-shell/src/main/ruby/shell/commands/alter.rb
+++ b/hbase-shell/src/main/ruby/shell/commands/alter.rb
@@ -22,19 +22,17 @@ module Shell
class Alter < Command
def help
return <<-EOF
-Alter a table. If the "hbase.online.schema.update.enable" property is set to
-false, then the table must be disabled (see help 'disable'). If the
-"hbase.online.schema.update.enable" property is set to true, tables can be
-altered without disabling them first. Altering enabled tables has caused problems
-in the past, so use caution and test it before using in production.
+Alter a table. Tables can be altered without disabling them first.
+Altering enabled tables has caused problems
+in the past, so use caution and test it before using in production.
-You can use the alter command to add,
+You can use the alter command to add,
modify or delete column families or change table configuration options.
Column families work in a similar way as the 'create' command. The column family
specification can either be a name string, or a dictionary with the NAME attribute.
Dictionaries are described in the output of the 'help' command, with no arguments.
-For example, to change or add the 'f1' column family in table 't1' from
+For example, to change or add the 'f1' column family in table 't1' from
current value to keep a maximum of 5 cell VERSIONS, do:
hbase> alter 't1', NAME => 'f1', VERSIONS => 5
@@ -48,7 +46,7 @@ To delete the 'f1' column family in table 'ns1:t1', use one of:
hbase> alter 'ns1:t1', NAME => 'f1', METHOD => 'delete'
hbase> alter 'ns1:t1', 'delete' => 'f1'
-You can also change table-scope attributes like MAX_FILESIZE, READONLY,
+You can also change table-scope attributes like MAX_FILESIZE, READONLY,
MEMSTORE_FLUSHSIZE, DURABILITY, etc. These can be put at the end;
for example, to change the max size of a region to 128MB, do:
@@ -85,7 +83,7 @@ You can also set REGION_REPLICATION:
There could be more than one alteration in one command:
- hbase> alter 't1', { NAME => 'f1', VERSIONS => 3 },
+ hbase> alter 't1', { NAME => 'f1', VERSIONS => 3 },
{ MAX_FILESIZE => '134217728' }, { METHOD => 'delete', NAME => 'f2' },
OWNER => 'johndoe', METADATA => { 'mykey' => 'myvalue' }
EOF
http://git-wip-us.apache.org/repos/asf/hbase/blob/d9463bcc/hbase-shell/src/test/java/org/apache/hadoop/hbase/client/AbstractTestShell.java
----------------------------------------------------------------------
diff --git a/hbase-shell/src/test/java/org/apache/hadoop/hbase/client/AbstractTestShell.java b/hbase-shell/src/test/java/org/apache/hadoop/hbase/client/AbstractTestShell.java
index 87d14dd..074b9f7 100644
--- a/hbase-shell/src/test/java/org/apache/hadoop/hbase/client/AbstractTestShell.java
+++ b/hbase-shell/src/test/java/org/apache/hadoop/hbase/client/AbstractTestShell.java
@@ -37,7 +37,6 @@ public abstract class AbstractTestShell {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
// Start mini cluster
- TEST_UTIL.getConfiguration().setBoolean("hbase.online.schema.update.enable", true);
TEST_UTIL.getConfiguration().setInt("hbase.regionserver.msginterval", 100);
TEST_UTIL.getConfiguration().setInt("hbase.client.pause", 250);
TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 6);
http://git-wip-us.apache.org/repos/asf/hbase/blob/d9463bcc/hbase-shell/src/test/rsgroup/org/apache/hadoop/hbase/client/rsgroup/TestShellRSGroups.java
----------------------------------------------------------------------
diff --git a/hbase-shell/src/test/rsgroup/org/apache/hadoop/hbase/client/rsgroup/TestShellRSGroups.java b/hbase-shell/src/test/rsgroup/org/apache/hadoop/hbase/client/rsgroup/TestShellRSGroups.java
index 155bdb4..5f3720e 100644
--- a/hbase-shell/src/test/rsgroup/org/apache/hadoop/hbase/client/rsgroup/TestShellRSGroups.java
+++ b/hbase-shell/src/test/rsgroup/org/apache/hadoop/hbase/client/rsgroup/TestShellRSGroups.java
@@ -54,7 +54,6 @@ public class TestShellRSGroups {
basePath = System.getProperty("basedir");
// Start mini cluster
- TEST_UTIL.getConfiguration().setBoolean("hbase.online.schema.update.enable", true);
TEST_UTIL.getConfiguration().setInt("hbase.regionserver.msginterval", 100);
TEST_UTIL.getConfiguration().setInt("hbase.client.pause", 250);
TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 6);
http://git-wip-us.apache.org/repos/asf/hbase/blob/d9463bcc/src/main/asciidoc/_chapters/hbase-default.adoc
----------------------------------------------------------------------
diff --git a/src/main/asciidoc/_chapters/hbase-default.adoc b/src/main/asciidoc/_chapters/hbase-default.adoc
index df750e0..7a65446 100644
--- a/src/main/asciidoc/_chapters/hbase-default.adoc
+++ b/src/main/asciidoc/_chapters/hbase-default.adoc
@@ -1585,16 +1585,6 @@ Set to true to cause the hosting server (master or regionserver)
`true`
-[[hbase.online.schema.update.enable]]
-*`hbase.online.schema.update.enable`*::
-+
-.Description
-Set true to enable online schema changes.
-+
-.Default
-`true`
-
-
[[hbase.table.lock.enable]]
*`hbase.table.lock.enable`*::
+