You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by zg...@apache.org on 2017/07/11 06:02:59 UTC

hbase git commit: HBASE-18343 Track the remaining unimplemented methods for async admin

Repository: hbase
Updated Branches:
  refs/heads/master f8e892d7a -> 1978b78cd


HBASE-18343 Track the remaining unimplemented methods for async admin


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

Branch: refs/heads/master
Commit: 1978b78cdf8b31fc627937a3ef9fdd0010fac08c
Parents: f8e892d
Author: Guanghao Zhang <zg...@apache.org>
Authored: Mon Jul 10 13:39:44 2017 +0800
Committer: Guanghao Zhang <zg...@apache.org>
Committed: Tue Jul 11 14:01:56 2017 +0800

----------------------------------------------------------------------
 .../apache/hadoop/hbase/client/AsyncAdmin.java  |  61 +++++++++++
 .../hadoop/hbase/client/AsyncHBaseAdmin.java    |  43 ++++++++
 .../hadoop/hbase/client/RawAsyncHBaseAdmin.java | 106 +++++++++++++++++++
 .../hbase/client/TestAsyncClusterAdminApi.java  |  90 ++++++++++++++++
 .../hbase/client/TestAsyncRegionAdminApi.java   |  78 ++++++++++++++
 5 files changed, 378 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/1978b78c/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java
index 9538a48..7d904b3 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java
@@ -21,6 +21,7 @@ import java.util.List;
 import java.util.Collection;
 import java.util.Map;
 import java.util.Optional;
+import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.regex.Pattern;
 
@@ -32,9 +33,11 @@ import org.apache.hadoop.hbase.ServerName;
 import org.apache.hadoop.hbase.NamespaceDescriptor;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
+import org.apache.hadoop.hbase.procedure2.LockInfo;
 import org.apache.hadoop.hbase.quotas.QuotaFilter;
 import org.apache.hadoop.hbase.quotas.QuotaSettings;
 import org.apache.hadoop.hbase.client.replication.TableCFs;
+import org.apache.hadoop.hbase.client.security.SecurityCapability;
 import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
 import org.apache.hadoop.hbase.replication.ReplicationPeerDescription;
 import org.apache.hadoop.hbase.util.Pair;
@@ -405,6 +408,34 @@ public interface AsyncAdmin {
   CompletableFuture<Void> majorCompactRegionServer(ServerName serverName);
 
   /**
+   * Turn the Merge switch on or off.
+   * @param on
+   * @return Previous switch value wrapped by a {@link CompletableFuture}
+   */
+  CompletableFuture<Boolean> setMergeOn(boolean on);
+
+  /**
+   * Query the current state of the Merge switch.
+   * @return true if the switch is on, false otherwise. The return value will be wrapped by a
+   *         {@link CompletableFuture}
+   */
+  CompletableFuture<Boolean> isMergeOn();
+
+  /**
+   * Turn the Split switch on or off.
+   * @param on
+   * @return Previous switch value wrapped by a {@link CompletableFuture}
+   */
+  CompletableFuture<Boolean> setSplitOn(boolean on);
+
+  /**
+   * Query the current state of the Split switch.
+   * @return true if the switch is on, false otherwise. The return value will be wrapped by a
+   *         {@link CompletableFuture}
+   */
+  CompletableFuture<Boolean> isSplitOn();
+
+  /**
    * Merge two regions.
    * @param nameOfRegionA encoded or full name of region a
    * @param nameOfRegionB encoded or full name of region b
@@ -771,6 +802,12 @@ public interface AsyncAdmin {
   CompletableFuture<List<ProcedureInfo>> listProcedures();
 
   /**
+   * List procedure locks.
+   * @return lock list wrapped by {@link CompletableFuture}
+   */
+  CompletableFuture<List<LockInfo>> listProcedureLocks();
+
+  /**
    * Mark a region server as draining to prevent additional regions from getting assigned to it.
    * @param servers
    */
@@ -852,6 +889,24 @@ public interface AsyncAdmin {
   CompletableFuture<Void> updateConfiguration();
 
   /**
+   * Roll the log writer. I.e. for filesystem based write ahead logs, start writing to a new file.
+   * <p>
+   * When the returned CompletableFuture is done, it only means the rollWALWriter request was sent
+   * to the region server and may need some time to finish the rollWALWriter operation. As a side
+   * effect of this call, the named region server may schedule store flushes at the request of the
+   * wal.
+   * @param serverName The servername of the region server.
+   */
+  CompletableFuture<Void> rollWALWriter(ServerName serverName);
+
+  /**
+   * Clear compacting queues on a region server.
+   * @param serverName
+   * @param queues the set of queue name
+   */
+  CompletableFuture<Void> clearCompactionQueues(ServerName serverName, Set<String> queues);
+
+  /**
    * Get a list of {@link RegionLoad} of all regions hosted on a region seerver for a table.
    * @param serverName
    * @param tableName
@@ -904,6 +959,12 @@ public interface AsyncAdmin {
   CompletableFuture<Optional<Long>> getLastMajorCompactionTimestampForRegion(byte[] regionName);
 
   /**
+   * @return the list of supported security capabilities. The return value will be wrapped by a
+   *         {@link CompletableFuture}.
+   */
+  CompletableFuture<List<SecurityCapability>> getSecurityCapabilities();
+
+  /**
    * Turn the load balancer on or off.
    * @param on
    * @return Previous balancer value wrapped by a {@link CompletableFuture}.

http://git-wip-us.apache.org/repos/asf/hbase/blob/1978b78c/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java
index 8e2b3c0..8e5a28c 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java
@@ -21,6 +21,7 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutorService;
 import java.util.regex.Pattern;
@@ -36,6 +37,8 @@ import org.apache.hadoop.hbase.NamespaceDescriptor;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.client.replication.TableCFs;
+import org.apache.hadoop.hbase.client.security.SecurityCapability;
+import org.apache.hadoop.hbase.procedure2.LockInfo;
 import org.apache.hadoop.hbase.quotas.QuotaFilter;
 import org.apache.hadoop.hbase.quotas.QuotaSettings;
 import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
@@ -258,6 +261,26 @@ public class AsyncHBaseAdmin implements AsyncAdmin {
   }
 
   @Override
+  public CompletableFuture<Boolean> setMergeOn(boolean on) {
+    return wrap(rawAdmin.setMergeOn(on));
+  }
+
+  @Override
+  public CompletableFuture<Boolean> isMergeOn() {
+    return wrap(rawAdmin.isMergeOn());
+  }
+
+  @Override
+  public CompletableFuture<Boolean> setSplitOn(boolean on) {
+    return wrap(rawAdmin.setSplitOn(on));
+  }
+
+  @Override
+  public CompletableFuture<Boolean> isSplitOn() {
+    return wrap(rawAdmin.isSplitOn());
+  }
+
+  @Override
   public CompletableFuture<Void> mergeRegions(byte[] nameOfRegionA, byte[] nameOfRegionB,
       boolean forcible) {
     return wrap(rawAdmin.mergeRegions(nameOfRegionA, nameOfRegionB, forcible));
@@ -439,6 +462,11 @@ public class AsyncHBaseAdmin implements AsyncAdmin {
   }
 
   @Override
+  public CompletableFuture<List<LockInfo>> listProcedureLocks() {
+    return wrap(rawAdmin.listProcedureLocks());
+  }
+
+  @Override
   public CompletableFuture<Void> drainRegionServers(List<ServerName> servers) {
     return wrap(rawAdmin.drainRegionServers(servers));
   }
@@ -484,6 +512,21 @@ public class AsyncHBaseAdmin implements AsyncAdmin {
   }
 
   @Override
+  public CompletableFuture<Void> rollWALWriter(ServerName serverName) {
+    return wrap(rawAdmin.rollWALWriter(serverName));
+  }
+
+  @Override
+  public CompletableFuture<Void> clearCompactionQueues(ServerName serverName, Set<String> queues) {
+    return wrap(rawAdmin.clearCompactionQueues(serverName, queues));
+  }
+
+  @Override
+  public CompletableFuture<List<SecurityCapability>> getSecurityCapabilities() {
+    return wrap(rawAdmin.getSecurityCapabilities());
+  }
+
+  @Override
   public CompletableFuture<List<RegionLoad>> getRegionLoads(ServerName serverName,
       Optional<TableName> tableName) {
     return wrap(rawAdmin.getRegionLoads(serverName, tableName));

http://git-wip-us.apache.org/repos/asf/hbase/blob/1978b78c/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java
index 2c6dd77..0271a50 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java
@@ -29,6 +29,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
@@ -71,8 +72,10 @@ import org.apache.hadoop.hbase.client.AsyncRpcRetryingCallerFactory.MasterReques
 import org.apache.hadoop.hbase.client.Scan.ReadType;
 import org.apache.hadoop.hbase.client.replication.ReplicationSerDeHelper;
 import org.apache.hadoop.hbase.client.replication.TableCFs;
+import org.apache.hadoop.hbase.client.security.SecurityCapability;
 import org.apache.hadoop.hbase.exceptions.DeserializationException;
 import org.apache.hadoop.hbase.ipc.HBaseRpcController;
+import org.apache.hadoop.hbase.procedure2.LockInfo;
 import org.apache.hadoop.hbase.quotas.QuotaFilter;
 import org.apache.hadoop.hbase.quotas.QuotaSettings;
 import org.apache.hadoop.hbase.quotas.QuotaTableUtil;
@@ -83,6 +86,8 @@ import org.apache.hadoop.hbase.shaded.com.google.protobuf.RpcCallback;
 import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
 import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.AdminService;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ClearCompactionQueuesRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ClearCompactionQueuesResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.CloseRegionRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.CloseRegionResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.CompactRegionRequest;
@@ -95,6 +100,8 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionIn
 import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionInfoResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionLoadRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionLoadResponse;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.RollWALWriterRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.RollWALWriterResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.SplitRegionRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.SplitRegionResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.StopServerRequest;
@@ -162,8 +169,12 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsProcedur
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsProcedureDoneResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsSnapshotDoneRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsSnapshotDoneResponse;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsSplitOrMergeEnabledRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsSplitOrMergeEnabledResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListDrainingRegionServersRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListDrainingRegionServersResponse;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListLocksRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListLocksResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListNamespaceDescriptorsRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListNamespaceDescriptorsResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListProceduresRequest;
@@ -192,6 +203,8 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunCatalog
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunCatalogScanResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunCleanerChoreRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunCleanerChoreResponse;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SecurityCapabilitiesRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SecurityCapabilitiesResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetBalancerRunningRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetBalancerRunningResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetCleanerChoreRunningRequest;
@@ -200,6 +213,8 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetNormali
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetNormalizerRunningResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetQuotaRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetQuotaResponse;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetSplitOrMergeEnabledRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetSplitOrMergeEnabledResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ShutdownRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ShutdownResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SnapshotRequest;
@@ -1034,6 +1049,51 @@ public class RawAsyncHBaseAdmin implements AsyncAdmin {
   }
 
   @Override
+  public CompletableFuture<Boolean> setMergeOn(boolean on) {
+    return setSplitOrMergeOn(on, MasterSwitchType.MERGE);
+  }
+
+  @Override
+  public CompletableFuture<Boolean> isMergeOn() {
+    return isSplitOrMergeOn(MasterSwitchType.MERGE);
+  }
+
+  @Override
+  public CompletableFuture<Boolean> setSplitOn(boolean on) {
+    return setSplitOrMergeOn(on, MasterSwitchType.SPLIT);
+  }
+
+  @Override
+  public CompletableFuture<Boolean> isSplitOn() {
+    return isSplitOrMergeOn(MasterSwitchType.SPLIT);
+  }
+
+  private CompletableFuture<Boolean> setSplitOrMergeOn(boolean on, MasterSwitchType switchType) {
+    SetSplitOrMergeEnabledRequest request =
+        RequestConverter.buildSetSplitOrMergeEnabledRequest(on, false, switchType);
+    return this
+        .<Boolean> newMasterCaller()
+        .action(
+          (controller, stub) -> this
+              .<SetSplitOrMergeEnabledRequest, SetSplitOrMergeEnabledResponse, Boolean> call(
+                controller, stub, request, (s, c, req, done) -> s.setSplitOrMergeEnabled(c, req,
+                  done), (resp) -> resp.getPrevValueList().get(0))).call();
+  }
+
+  private CompletableFuture<Boolean> isSplitOrMergeOn(MasterSwitchType switchType) {
+    IsSplitOrMergeEnabledRequest request =
+        RequestConverter.buildIsSplitOrMergeEnabledRequest(switchType);
+    return this
+        .<Boolean> newMasterCaller()
+        .action(
+          (controller, stub) -> this
+              .<IsSplitOrMergeEnabledRequest, IsSplitOrMergeEnabledResponse, Boolean> call(
+                controller, stub, request,
+                (s, c, req, done) -> s.isSplitOrMergeEnabled(c, req, done),
+                (resp) -> resp.getEnabled())).call();
+  }
+
+  @Override
   public CompletableFuture<Void> mergeRegions(byte[] nameOfRegionA, byte[] nameOfRegionB,
       boolean forcible) {
     CompletableFuture<Void> future = new CompletableFuture<>();
@@ -1930,6 +1990,17 @@ public class RawAsyncHBaseAdmin implements AsyncAdmin {
   }
 
   @Override
+  public CompletableFuture<List<LockInfo>> listProcedureLocks() {
+    return this
+        .<List<LockInfo>> newMasterCaller()
+        .action(
+          (controller, stub) -> this.<ListLocksRequest, ListLocksResponse, List<LockInfo>> call(
+            controller, stub, ListLocksRequest.newBuilder().build(),
+            (s, c, req, done) -> s.listLocks(c, req, done), resp -> resp.getLockList().stream()
+                .map(ProtobufUtil::toLockInfo).collect(Collectors.toList()))).call();
+  }
+
+  @Override
   public CompletableFuture<Void> drainRegionServers(List<ServerName> servers) {
     return this
         .<Void> newMasterCaller()
@@ -2422,6 +2493,41 @@ public class RawAsyncHBaseAdmin implements AsyncAdmin {
   }
 
   @Override
+  public CompletableFuture<Void> rollWALWriter(ServerName serverName) {
+    return this
+        .<Void> newAdminCaller()
+        .action(
+          (controller, stub) -> this.<RollWALWriterRequest, RollWALWriterResponse, Void> adminCall(
+            controller, stub, RequestConverter.buildRollWALWriterRequest(),
+            (s, c, req, done) -> s.rollWALWriter(controller, req, done), resp -> null))
+        .serverName(serverName).call();
+  }
+
+  @Override
+  public CompletableFuture<Void> clearCompactionQueues(ServerName serverName, Set<String> queues) {
+    return this
+        .<Void> newAdminCaller()
+        .action(
+          (controller, stub) -> this
+              .<ClearCompactionQueuesRequest, ClearCompactionQueuesResponse, Void> adminCall(
+                controller, stub, RequestConverter.buildClearCompactionQueuesRequest(queues), (s,
+                    c, req, done) -> s.clearCompactionQueues(controller, req, done), resp -> null))
+        .serverName(serverName).call();
+  }
+
+  @Override
+  public CompletableFuture<List<SecurityCapability>> getSecurityCapabilities() {
+    return this
+        .<List<SecurityCapability>> newMasterCaller()
+        .action(
+          (controller, stub) -> this
+              .<SecurityCapabilitiesRequest, SecurityCapabilitiesResponse, List<SecurityCapability>> call(
+                controller, stub, SecurityCapabilitiesRequest.newBuilder().build(), (s, c, req,
+                    done) -> s.getSecurityCapabilities(c, req, done), (resp) -> ProtobufUtil
+                    .toSecurityCapabilityList(resp.getCapabilitiesList()))).call();
+  }
+
+  @Override
   public CompletableFuture<List<RegionLoad>> getRegionLoads(ServerName serverName,
       Optional<TableName> tableName) {
     return this

http://git-wip-us.apache.org/repos/asf/hbase/blob/1978b78c/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncClusterAdminApi.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncClusterAdminApi.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncClusterAdminApi.java
index 6a3c8e1..3d3f049 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncClusterAdminApi.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncClusterAdminApi.java
@@ -34,14 +34,18 @@ import java.util.Optional;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hbase.ClusterStatus;
 import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.HRegionInfo;
 import org.apache.hadoop.hbase.RegionLoad;
 import org.apache.hadoop.hbase.ServerLoad;
 import org.apache.hadoop.hbase.ServerName;
 import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.regionserver.HRegionServer;
+import org.apache.hadoop.hbase.regionserver.Region;
 import org.apache.hadoop.hbase.testclassification.ClientTests;
 import org.apache.hadoop.hbase.testclassification.MediumTests;
 import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.hbase.wal.AbstractFSWALProvider;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
@@ -122,6 +126,92 @@ public class TestAsyncClusterAdminApi extends TestAsyncAdminBase {
   }
 
   @Test
+  public void testRollWALWALWriter() throws Exception {
+    setUpforLogRolling();
+    String className = this.getClass().getName();
+    StringBuilder v = new StringBuilder(className);
+    while (v.length() < 1000) {
+      v.append(className);
+    }
+    byte[] value = Bytes.toBytes(v.toString());
+    HRegionServer regionServer = startAndWriteData(tableName, value);
+    LOG.info("after writing there are "
+        + AbstractFSWALProvider.getNumRolledLogFiles(regionServer.getWAL(null)) + " log files");
+
+    // flush all regions
+    for (Region r : regionServer.getOnlineRegionsLocalContext()) {
+      r.flush(true);
+    }
+    admin.rollWALWriter(regionServer.getServerName()).join();
+    int count = AbstractFSWALProvider.getNumRolledLogFiles(regionServer.getWAL(null));
+    LOG.info("after flushing all regions and rolling logs there are " +
+        count + " log files");
+    assertTrue(("actual count: " + count), count <= 2);
+  }
+
+  private void setUpforLogRolling() {
+    // Force a region split after every 768KB
+    TEST_UTIL.getConfiguration().setLong(HConstants.HREGION_MAX_FILESIZE,
+        768L * 1024L);
+
+    // We roll the log after every 32 writes
+    TEST_UTIL.getConfiguration().setInt("hbase.regionserver.maxlogentries", 32);
+
+    TEST_UTIL.getConfiguration().setInt(
+        "hbase.regionserver.logroll.errors.tolerated", 2);
+    TEST_UTIL.getConfiguration().setInt("hbase.rpc.timeout", 10 * 1000);
+
+    // For less frequently updated regions flush after every 2 flushes
+    TEST_UTIL.getConfiguration().setInt(
+        "hbase.hregion.memstore.optionalflushcount", 2);
+
+    // We flush the cache after every 8192 bytes
+    TEST_UTIL.getConfiguration().setInt(HConstants.HREGION_MEMSTORE_FLUSH_SIZE,
+        8192);
+
+    // Increase the amount of time between client retries
+    TEST_UTIL.getConfiguration().setLong("hbase.client.pause", 10 * 1000);
+
+    // Reduce thread wake frequency so that other threads can get
+    // a chance to run.
+    TEST_UTIL.getConfiguration().setInt(HConstants.THREAD_WAKE_FREQUENCY,
+        2 * 1000);
+
+    /**** configuration for testLogRollOnDatanodeDeath ****/
+    // lower the namenode & datanode heartbeat so the namenode
+    // quickly detects datanode failures
+    TEST_UTIL.getConfiguration().setInt("dfs.namenode.heartbeat.recheck-interval", 5000);
+    TEST_UTIL.getConfiguration().setInt("dfs.heartbeat.interval", 1);
+    // the namenode might still try to choose the recently-dead datanode
+    // for a pipeline, so try to a new pipeline multiple times
+    TEST_UTIL.getConfiguration().setInt("dfs.client.block.write.retries", 30);
+    TEST_UTIL.getConfiguration().setInt(
+        "hbase.regionserver.hlog.tolerable.lowreplication", 2);
+    TEST_UTIL.getConfiguration().setInt(
+        "hbase.regionserver.hlog.lowreplication.rolllimit", 3);
+  }
+
+  private HRegionServer startAndWriteData(TableName tableName, byte[] value) throws Exception {
+    createTableWithDefaultConf(tableName);
+    RawAsyncTable table = ASYNC_CONN.getRawTable(tableName);
+    HRegionServer regionServer = TEST_UTIL.getRSForFirstRegionInTable(tableName);
+    for (int i = 1; i <= 256; i++) { // 256 writes should cause 8 log rolls
+      Put put = new Put(Bytes.toBytes("row" + String.format("%1$04d", i)));
+      put.addColumn(FAMILY, null, value);
+      table.put(put).join();
+      if (i % 32 == 0) {
+        // After every 32 writes sleep to let the log roller run
+        try {
+          Thread.sleep(2000);
+        } catch (InterruptedException e) {
+          // continue
+        }
+      }
+    }
+    return regionServer;
+  }
+
+  @Test
   public void testGetRegionLoads() throws Exception {
     // Turn off the balancer
     admin.setBalancerOn(false).join();

http://git-wip-us.apache.org/repos/asf/hbase/blob/1978b78c/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncRegionAdminApi.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncRegionAdminApi.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncRegionAdminApi.java
index 7752d37..fcd3d01 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncRegionAdminApi.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncRegionAdminApi.java
@@ -355,6 +355,79 @@ public class TestAsyncRegionAdminApi extends TestAsyncAdminBase {
   }
 
   @Test
+  public void testSplitSwitch() throws Exception {
+    createTableWithDefaultConf(tableName);
+    byte[][] families = { FAMILY };
+    loadData(tableName, families, 1000);
+
+    RawAsyncTable metaTable = ASYNC_CONN.getRawTable(META_TABLE_NAME);
+    List<HRegionLocation> regionLocations =
+        AsyncMetaTableAccessor.getTableHRegionLocations(metaTable, Optional.of(tableName)).get();
+    int originalCount = regionLocations.size();
+
+    initSplitMergeSwitch();
+    assertTrue(admin.setSplitOn(false).get());
+    admin.split(tableName).join();
+    int count = admin.getTableRegions(tableName).get().size();
+    assertTrue(originalCount == count);
+
+    assertFalse(admin.setSplitOn(true).get());
+    admin.split(tableName).join();
+    while ((count = admin.getTableRegions(tableName).get().size()) == originalCount) {
+      Threads.sleep(100);
+    }
+    assertTrue(originalCount < count);
+  }
+
+  @Test
+  @Ignore
+  // It was ignored in TestSplitOrMergeStatus, too
+  public void testMergeSwitch() throws Exception {
+    createTableWithDefaultConf(tableName);
+    byte[][] families = { FAMILY };
+    loadData(tableName, families, 1000);
+
+    RawAsyncTable metaTable = ASYNC_CONN.getRawTable(META_TABLE_NAME);
+    List<HRegionLocation> regionLocations =
+        AsyncMetaTableAccessor.getTableHRegionLocations(metaTable, Optional.of(tableName)).get();
+    int originalCount = regionLocations.size();
+
+    initSplitMergeSwitch();
+    admin.split(tableName).join();
+    int postSplitCount = originalCount;
+    while ((postSplitCount = admin.getTableRegions(tableName).get().size()) == originalCount) {
+      Threads.sleep(100);
+    }
+    assertTrue("originalCount=" + originalCount + ", postSplitCount=" + postSplitCount,
+      originalCount != postSplitCount);
+
+    // Merge switch is off so merge should NOT succeed.
+    assertTrue(admin.setMergeOn(false).get());
+    List<HRegionInfo> regions = admin.getTableRegions(tableName).get();
+    assertTrue(regions.size() > 1);
+    admin.mergeRegions(regions.get(0).getRegionName(), regions.get(1).getRegionName(), true).join();
+    int count = admin.getTableRegions(tableName).get().size();
+    assertTrue("postSplitCount=" + postSplitCount + ", count=" + count, postSplitCount == count);
+
+    // Merge switch is on so merge should succeed.
+    assertFalse(admin.setMergeOn(true).get());
+    admin.mergeRegions(regions.get(0).getRegionName(), regions.get(1).getRegionName(), true).join();
+    count = admin.getTableRegions(tableName).get().size();
+    assertTrue((postSplitCount / 2) == count);
+  }
+
+  private void initSplitMergeSwitch() throws Exception {
+    if (!admin.isSplitOn().get()) {
+      admin.setSplitOn(true).get();
+    }
+    if (!admin.isMergeOn().get()) {
+      admin.setMergeOn(true).get();
+    }
+    assertTrue(admin.isSplitOn().get());
+    assertTrue(admin.isMergeOn().get());
+  }
+
+  @Test
   public void testMergeRegions() throws Exception {
     byte[][] splitRows = new byte[][] { Bytes.toBytes("3"), Bytes.toBytes("6") };
     createTableWithDefaultConf(tableName, Optional.of(splitRows));
@@ -569,6 +642,11 @@ public class TestAsyncRegionAdminApi extends TestAsyncAdminBase {
     return count;
   }
 
+  private static void loadData(final TableName tableName, final byte[][] families, final int rows)
+      throws IOException {
+    loadData(tableName, families, rows, 1);
+  }
+
   private static void loadData(final TableName tableName, final byte[][] families, final int rows,
       final int flushes) throws IOException {
     RawAsyncTable table = ASYNC_CONN.getRawTable(tableName);