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`*::
 +