You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by ap...@apache.org on 2017/07/17 17:58:48 UTC

[55/94] [abbrv] hbase git commit: HBASE-18317 Implement async admin operations for Normalizer/CleanerChore/CatalogJanitor

HBASE-18317 Implement async admin operations for Normalizer/CleanerChore/CatalogJanitor


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

Branch: refs/heads/HBASE-14070.HLC
Commit: 7f937297821f5fb27c5ed32a4c0d4e5bc4a18956
Parents: 48d28c7
Author: Guanghao Zhang <zg...@apache.org>
Authored: Fri Jul 7 21:13:38 2017 +0800
Committer: Guanghao Zhang <zg...@apache.org>
Committed: Sat Jul 8 10:55:10 2017 +0800

----------------------------------------------------------------------
 .../apache/hadoop/hbase/client/AsyncAdmin.java  | 131 +++++++++----
 .../hadoop/hbase/client/AsyncHBaseAdmin.java    |  75 ++++++--
 .../hadoop/hbase/client/RawAsyncHBaseAdmin.java | 190 +++++++++++++++----
 .../hbase/client/TestAsyncBalancerAdminApi.java |  54 ------
 .../hbase/client/TestAsyncToolAdminApi.java     | 127 +++++++++++++
 5 files changed, 441 insertions(+), 136 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/7f937297/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 8ade209..8411a5b 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
@@ -284,40 +284,6 @@ public interface AsyncAdmin {
   CompletableFuture<List<NamespaceDescriptor>> listNamespaceDescriptors();
 
   /**
-   * Turn the load balancer on or off.
-   * @param on
-   * @return Previous balancer value wrapped by a {@link CompletableFuture}.
-   */
-  CompletableFuture<Boolean> setBalancerOn(boolean on);
-
-  /**
-   * Invoke the balancer. Will run the balancer and if regions to move, it will go ahead and do the
-   * reassignments. Can NOT run for various reasons. Check logs.
-   * @return True if balancer ran, false otherwise. The return value will be wrapped by a
-   *         {@link CompletableFuture}.
-   */
-  default CompletableFuture<Boolean> balance() {
-    return balance(false);
-  }
-
-  /**
-   * Invoke the balancer. Will run the balancer and if regions to move, it will go ahead and do the
-   * reassignments. If there is region in transition, force parameter of true would still run
-   * balancer. Can *not* run for other reasons. Check logs.
-   * @param forcible whether we should force balance even if there is region in transition.
-   * @return True if balancer ran, false otherwise. The return value will be wrapped by a
-   *         {@link CompletableFuture}.
-   */
-  CompletableFuture<Boolean> balance(boolean forcible);
-
-  /**
-   * Query the current state of the balancer.
-   * @return true if the balance switch is on, false otherwise The return value will be wrapped by a
-   *         {@link CompletableFuture}.
-   */
-  CompletableFuture<Boolean> isBalancerOn();
-
-  /**
    * Close a region. For expert-admins Runs close on the regionserver. The master will not be
    * informed of the close.
    * @param regionName region name to close
@@ -891,4 +857,101 @@ public interface AsyncAdmin {
    * @return the last major compaction timestamp wrapped by a {@link CompletableFuture}
    */
   CompletableFuture<Optional<Long>> getLastMajorCompactionTimestampForRegion(byte[] regionName);
+
+  /**
+   * Turn the load balancer on or off.
+   * @param on
+   * @return Previous balancer value wrapped by a {@link CompletableFuture}.
+   */
+  CompletableFuture<Boolean> setBalancerOn(boolean on);
+
+  /**
+   * Invoke the balancer. Will run the balancer and if regions to move, it will go ahead and do the
+   * reassignments. Can NOT run for various reasons. Check logs.
+   * @return True if balancer ran, false otherwise. The return value will be wrapped by a
+   *         {@link CompletableFuture}.
+   */
+  default CompletableFuture<Boolean> balance() {
+    return balance(false);
+  }
+
+  /**
+   * Invoke the balancer. Will run the balancer and if regions to move, it will go ahead and do the
+   * reassignments. If there is region in transition, force parameter of true would still run
+   * balancer. Can *not* run for other reasons. Check logs.
+   * @param forcible whether we should force balance even if there is region in transition.
+   * @return True if balancer ran, false otherwise. The return value will be wrapped by a
+   *         {@link CompletableFuture}.
+   */
+  CompletableFuture<Boolean> balance(boolean forcible);
+
+  /**
+   * Query the current state of the balancer.
+   * @return true if the balance switch is on, false otherwise. The return value will be wrapped by a
+   *         {@link CompletableFuture}.
+   */
+  CompletableFuture<Boolean> isBalancerOn();
+
+  /**
+   * Set region normalizer on/off.
+   * @param on whether normalizer should be on or off
+   * @return Previous normalizer value wrapped by a {@link CompletableFuture}
+   */
+  CompletableFuture<Boolean> setNormalizerOn(boolean on);
+
+  /**
+   * Query the current state of the region normalizer
+   * @return true if region normalizer is on, false otherwise. The return value will be wrapped by a
+   *         {@link CompletableFuture}
+   */
+  CompletableFuture<Boolean> isNormalizerOn();
+
+  /**
+   * Invoke region normalizer. Can NOT run for various reasons. Check logs.
+   * @return true if region normalizer ran, false otherwise. The return value will be wrapped by a
+   *         {@link CompletableFuture}
+   */
+  CompletableFuture<Boolean> normalize();
+
+  /**
+   * Turn the cleaner chore on/off.
+   * @param on
+   * @return Previous cleaner state wrapped by a {@link CompletableFuture}
+   */
+  CompletableFuture<Boolean> setCleanerChoreOn(boolean on);
+
+  /**
+   * Query the current state of the cleaner chore.
+   * @return true if cleaner chore is on, false otherwise. The return value will be wrapped by
+   *         a {@link CompletableFuture}
+   */
+  CompletableFuture<Boolean> isCleanerChoreOn();
+
+  /**
+   * Ask for cleaner chore to run.
+   * @return true if cleaner chore ran, false otherwise. The return value will be wrapped by a
+   *         {@link CompletableFuture}
+   */
+  CompletableFuture<Boolean> runCleanerChore();
+
+  /**
+   * Turn the catalog janitor on/off.
+   * @param on
+   * @return the previous state wrapped by a {@link CompletableFuture}
+   */
+  CompletableFuture<Boolean> setCatalogJanitorOn(boolean on);
+
+  /**
+   * Query on the catalog janitor state.
+   * @return true if the catalog janitor is on, false otherwise. The return value will be
+   *         wrapped by a {@link CompletableFuture}
+   */
+  CompletableFuture<Boolean> isCatalogJanitorOn();
+
+  /**
+   * Ask for a scan of the catalog table.
+   * @return the number of entries cleaned. The return value will be wrapped by a
+   *         {@link CompletableFuture}
+   */
+  CompletableFuture<Integer> runCatalogJanitor();
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/7f937297/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 2998133..7c572db 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
@@ -202,21 +202,6 @@ public class AsyncHBaseAdmin implements AsyncAdmin {
   }
 
   @Override
-  public CompletableFuture<Boolean> setBalancerOn(boolean on) {
-    return wrap(rawAdmin.setBalancerOn(on));
-  }
-
-  @Override
-  public CompletableFuture<Boolean> balance(boolean forcible) {
-    return wrap(rawAdmin.balance(forcible));
-  }
-
-  @Override
-  public CompletableFuture<Boolean> isBalancerOn() {
-    return wrap(rawAdmin.isBalancerOn());
-  }
-
-  @Override
   public CompletableFuture<Boolean> closeRegion(byte[] regionName, Optional<ServerName> serverName) {
     return wrap(rawAdmin.closeRegion(regionName, serverName));
   }
@@ -489,4 +474,64 @@ public class AsyncHBaseAdmin implements AsyncAdmin {
       byte[] regionName) {
     return wrap(rawAdmin.getLastMajorCompactionTimestampForRegion(regionName));
   }
+
+  @Override
+  public CompletableFuture<Boolean> setBalancerOn(boolean on) {
+    return wrap(rawAdmin.setBalancerOn(on));
+  }
+
+  @Override
+  public CompletableFuture<Boolean> balance(boolean forcible) {
+    return wrap(rawAdmin.balance(forcible));
+  }
+
+  @Override
+  public CompletableFuture<Boolean> isBalancerOn() {
+    return wrap(rawAdmin.isBalancerOn());
+  }
+
+  @Override
+  public CompletableFuture<Boolean> setNormalizerOn(boolean on) {
+    return wrap(rawAdmin.setNormalizerOn(on));
+  }
+
+  @Override
+  public CompletableFuture<Boolean> isNormalizerOn() {
+    return wrap(rawAdmin.isNormalizerOn());
+  }
+
+  @Override
+  public CompletableFuture<Boolean> normalize() {
+    return wrap(rawAdmin.normalize());
+  }
+
+  @Override
+  public CompletableFuture<Boolean> setCleanerChoreOn(boolean enabled) {
+    return wrap(rawAdmin.setCleanerChoreOn(enabled));
+  }
+
+  @Override
+  public CompletableFuture<Boolean> isCleanerChoreOn() {
+    return wrap(rawAdmin.isCleanerChoreOn());
+  }
+
+  @Override
+  public CompletableFuture<Boolean> runCleanerChore() {
+    return wrap(rawAdmin.runCleanerChore());
+  }
+
+  @Override
+  public CompletableFuture<Boolean> setCatalogJanitorOn(boolean enabled) {
+    return wrap(rawAdmin.setCatalogJanitorOn(enabled));
+  }
+
+  @Override
+  public CompletableFuture<Boolean> isCatalogJanitorOn() {
+    return wrap(rawAdmin.isCatalogJanitorOn());
+  }
+
+  @Override
+  public CompletableFuture<Integer> runCatalogJanitor() {
+    return wrap(rawAdmin.runCatalogJanitor());
+  }
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/7f937297/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 b119754..e8c15a5 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
@@ -116,6 +116,8 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteSnap
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteSnapshotResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DisableTableRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DisableTableResponse;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.EnableCatalogJanitorRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.EnableCatalogJanitorResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.EnableTableRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.EnableTableResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteColumnRequest;
@@ -142,8 +144,14 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteTabl
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteTableResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsBalancerEnabledRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsBalancerEnabledResponse;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsCatalogJanitorEnabledRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsCatalogJanitorEnabledResponse;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsCleanerChoreEnabledRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsCleanerChoreEnabledResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsInMaintenanceModeRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsInMaintenanceModeResponse;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsNormalizerEnabledRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsNormalizerEnabledResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsProcedureDoneRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsProcedureDoneResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsSnapshotDoneRequest;
@@ -164,12 +172,22 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyName
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyNamespaceResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MoveRegionRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MoveRegionResponse;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.NormalizeRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.NormalizeResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.OfflineRegionRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.OfflineRegionResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RestoreSnapshotRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RestoreSnapshotResponse;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunCatalogScanRequest;
+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.SetBalancerRunningRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetBalancerRunningResponse;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetCleanerChoreRunningRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetCleanerChoreRunningResponse;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetNormalizerRunningRequest;
+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.SnapshotRequest;
@@ -674,39 +692,6 @@ public class RawAsyncHBaseAdmin implements AsyncAdmin {
   }
 
   @Override
-  public CompletableFuture<Boolean> setBalancerOn(final boolean on) {
-    return this
-        .<Boolean> newMasterCaller()
-        .action(
-          (controller, stub) -> this
-              .<SetBalancerRunningRequest, SetBalancerRunningResponse, Boolean> call(controller,
-                stub, RequestConverter.buildSetBalancerRunningRequest(on, true),
-                (s, c, req, done) -> s.setBalancerRunning(c, req, done),
-                (resp) -> resp.getPrevBalanceValue())).call();
-  }
-
-  @Override
-  public CompletableFuture<Boolean> balance(boolean forcible) {
-    return this
-        .<Boolean> newMasterCaller()
-        .action(
-          (controller, stub) -> this.<BalanceRequest, BalanceResponse, Boolean> call(controller,
-            stub, RequestConverter.buildBalanceRequest(forcible),
-            (s, c, req, done) -> s.balance(c, req, done), (resp) -> resp.getBalancerRan())).call();
-  }
-
-  @Override
-  public CompletableFuture<Boolean> isBalancerOn() {
-    return this
-        .<Boolean> newMasterCaller()
-        .action(
-          (controller, stub) -> this.<IsBalancerEnabledRequest, IsBalancerEnabledResponse, Boolean> call(
-            controller, stub, RequestConverter.buildIsBalancerEnabledRequest(),
-            (s, c, req, done) -> s.isBalancerEnabled(c, req, done), (resp) -> resp.getEnabled()))
-        .call();
-  }
-
-  @Override
   public CompletableFuture<Boolean> closeRegion(byte[] regionName, Optional<ServerName> serverName) {
     CompletableFuture<Boolean> future = new CompletableFuture<>();
     getRegionLocation(regionName).whenComplete((location, err) -> {
@@ -2486,4 +2471,143 @@ public class RawAsyncHBaseAdmin implements AsyncAdmin {
           });
     return future;
   }
+
+  @Override
+  public CompletableFuture<Boolean> setBalancerOn(final boolean on) {
+    return this
+        .<Boolean> newMasterCaller()
+        .action(
+          (controller, stub) -> this
+              .<SetBalancerRunningRequest, SetBalancerRunningResponse, Boolean> call(controller,
+                stub, RequestConverter.buildSetBalancerRunningRequest(on, true),
+                (s, c, req, done) -> s.setBalancerRunning(c, req, done),
+                (resp) -> resp.getPrevBalanceValue())).call();
+  }
+
+  @Override
+  public CompletableFuture<Boolean> balance(boolean forcible) {
+    return this
+        .<Boolean> newMasterCaller()
+        .action(
+          (controller, stub) -> this.<BalanceRequest, BalanceResponse, Boolean> call(controller,
+            stub, RequestConverter.buildBalanceRequest(forcible),
+            (s, c, req, done) -> s.balance(c, req, done), (resp) -> resp.getBalancerRan())).call();
+  }
+
+  @Override
+  public CompletableFuture<Boolean> isBalancerOn() {
+    return this
+        .<Boolean> newMasterCaller()
+        .action(
+          (controller, stub) -> this.<IsBalancerEnabledRequest, IsBalancerEnabledResponse, Boolean> call(
+            controller, stub, RequestConverter.buildIsBalancerEnabledRequest(),
+            (s, c, req, done) -> s.isBalancerEnabled(c, req, done), (resp) -> resp.getEnabled()))
+        .call();
+  }
+
+  @Override
+  public CompletableFuture<Boolean> setNormalizerOn(boolean on) {
+    return this
+        .<Boolean> newMasterCaller()
+        .action(
+          (controller, stub) -> this
+              .<SetNormalizerRunningRequest, SetNormalizerRunningResponse, Boolean> call(
+                controller, stub, RequestConverter.buildSetNormalizerRunningRequest(on), (s, c,
+                    req, done) -> s.setNormalizerRunning(c, req, done), (resp) -> resp
+                    .getPrevNormalizerValue())).call();
+  }
+
+  @Override
+  public CompletableFuture<Boolean> isNormalizerOn() {
+    return this
+        .<Boolean> newMasterCaller()
+        .action(
+          (controller, stub) -> this
+              .<IsNormalizerEnabledRequest, IsNormalizerEnabledResponse, Boolean> call(controller,
+                stub, RequestConverter.buildIsNormalizerEnabledRequest(),
+                (s, c, req, done) -> s.isNormalizerEnabled(c, req, done),
+                (resp) -> resp.getEnabled())).call();
+  }
+
+  @Override
+  public CompletableFuture<Boolean> normalize() {
+    return this
+        .<Boolean> newMasterCaller()
+        .action(
+          (controller, stub) -> this.<NormalizeRequest, NormalizeResponse, Boolean> call(
+            controller, stub, RequestConverter.buildNormalizeRequest(),
+            (s, c, req, done) -> s.normalize(c, req, done), (resp) -> resp.getNormalizerRan()))
+        .call();
+  }
+
+  @Override
+  public CompletableFuture<Boolean> setCleanerChoreOn(boolean enabled) {
+    return this
+        .<Boolean> newMasterCaller()
+        .action(
+          (controller, stub) -> this
+              .<SetCleanerChoreRunningRequest, SetCleanerChoreRunningResponse, Boolean> call(
+                controller, stub, RequestConverter.buildSetCleanerChoreRunningRequest(enabled), (s,
+                    c, req, done) -> s.setCleanerChoreRunning(c, req, done), (resp) -> resp
+                    .getPrevValue())).call();
+  }
+
+  @Override
+  public CompletableFuture<Boolean> isCleanerChoreOn() {
+    return this
+        .<Boolean> newMasterCaller()
+        .action(
+          (controller, stub) -> this
+              .<IsCleanerChoreEnabledRequest, IsCleanerChoreEnabledResponse, Boolean> call(
+                controller, stub, RequestConverter.buildIsCleanerChoreEnabledRequest(), (s, c, req,
+                    done) -> s.isCleanerChoreEnabled(c, req, done), (resp) -> resp.getValue()))
+        .call();
+  }
+
+  @Override
+  public CompletableFuture<Boolean> runCleanerChore() {
+    return this
+        .<Boolean> newMasterCaller()
+        .action(
+          (controller, stub) -> this
+              .<RunCleanerChoreRequest, RunCleanerChoreResponse, Boolean> call(controller, stub,
+                RequestConverter.buildRunCleanerChoreRequest(),
+                (s, c, req, done) -> s.runCleanerChore(c, req, done),
+                (resp) -> resp.getCleanerChoreRan())).call();
+  }
+
+  @Override
+  public CompletableFuture<Boolean> setCatalogJanitorOn(boolean enabled) {
+    return this
+        .<Boolean> newMasterCaller()
+        .action(
+          (controller, stub) -> this
+              .<EnableCatalogJanitorRequest, EnableCatalogJanitorResponse, Boolean> call(
+                controller, stub, RequestConverter.buildEnableCatalogJanitorRequest(enabled), (s,
+                    c, req, done) -> s.enableCatalogJanitor(c, req, done), (resp) -> resp
+                    .getPrevValue())).call();
+  }
+
+  @Override
+  public CompletableFuture<Boolean> isCatalogJanitorOn() {
+    return this
+        .<Boolean> newMasterCaller()
+        .action(
+          (controller, stub) -> this
+              .<IsCatalogJanitorEnabledRequest, IsCatalogJanitorEnabledResponse, Boolean> call(
+                controller, stub, RequestConverter.buildIsCatalogJanitorEnabledRequest(), (s, c,
+                    req, done) -> s.isCatalogJanitorEnabled(c, req, done), (resp) -> resp
+                    .getValue())).call();
+  }
+
+  @Override
+  public CompletableFuture<Integer> runCatalogJanitor() {
+    return this
+        .<Integer> newMasterCaller()
+        .action(
+          (controller, stub) -> this.<RunCatalogScanRequest, RunCatalogScanResponse, Integer> call(
+            controller, stub, RequestConverter.buildCatalogScanRequest(),
+            (s, c, req, done) -> s.runCatalogScan(c, req, done), (resp) -> resp.getScanResult()))
+        .call();
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hbase/blob/7f937297/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncBalancerAdminApi.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncBalancerAdminApi.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncBalancerAdminApi.java
deleted file mode 100644
index 995e0aa..0000000
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncBalancerAdminApi.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * 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.client;
-
-import static org.junit.Assert.assertEquals;
-
-import org.apache.hadoop.hbase.testclassification.ClientTests;
-import org.apache.hadoop.hbase.testclassification.MediumTests;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-@RunWith(Parameterized.class)
-@Category({ MediumTests.class, ClientTests.class })
-public class TestAsyncBalancerAdminApi extends TestAsyncAdminBase {
-
-  @Test
-  public void testBalancer() throws Exception {
-    boolean initialState = admin.isBalancerOn().get();
-
-    // Start the balancer, wait for it.
-    boolean prevState = admin.setBalancerOn(!initialState).get();
-
-    // The previous state should be the original state we observed
-    assertEquals(initialState, prevState);
-
-    // Current state should be opposite of the original
-    assertEquals(!initialState, admin.isBalancerOn().get());
-
-    // Reset it back to what it was
-    prevState = admin.setBalancerOn(initialState).get();
-
-    // The previous state should be the opposite of the initial state
-    assertEquals(!initialState, prevState);
-    // Current state should be the original state again
-    assertEquals(initialState, admin.isBalancerOn().get());
-  }
-}

http://git-wip-us.apache.org/repos/asf/hbase/blob/7f937297/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncToolAdminApi.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncToolAdminApi.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncToolAdminApi.java
new file mode 100644
index 0000000..a773188
--- /dev/null
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncToolAdminApi.java
@@ -0,0 +1,127 @@
+/**
+ * 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.client;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.hadoop.hbase.testclassification.ClientTests;
+import org.apache.hadoop.hbase.testclassification.MediumTests;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ * Test the admin operations for Balancer, Normalizer, CleanerChore, and CatalogJanitor.
+ */
+@RunWith(Parameterized.class)
+@Category({ MediumTests.class, ClientTests.class })
+public class TestAsyncToolAdminApi extends TestAsyncAdminBase {
+
+  @Test
+  public void testBalancer() throws Exception {
+    boolean initialState = admin.isBalancerOn().get();
+
+    // Start the balancer, wait for it.
+    boolean prevState = admin.setBalancerOn(!initialState).get();
+
+    // The previous state should be the original state we observed
+    assertEquals(initialState, prevState);
+
+    // Current state should be opposite of the original
+    assertEquals(!initialState, admin.isBalancerOn().get());
+
+    // Reset it back to what it was
+    prevState = admin.setBalancerOn(initialState).get();
+
+    // The previous state should be the opposite of the initial state
+    assertEquals(!initialState, prevState);
+
+    // Current state should be the original state again
+    assertEquals(initialState, admin.isBalancerOn().get());
+  }
+
+  @Test
+  public void testNormalizer() throws Exception {
+    boolean initialState = admin.isNormalizerOn().get();
+
+    // flip state
+    boolean prevState = admin.setNormalizerOn(!initialState).get();
+
+    // The previous state should be the original state we observed
+    assertEquals(initialState, prevState);
+
+    // Current state should be opposite of the original
+    assertEquals(!initialState, admin.isNormalizerOn().get());
+
+    // Reset it back to what it was
+    prevState = admin.setNormalizerOn(initialState).get();
+
+    // The previous state should be the opposite of the initial state
+    assertEquals(!initialState, prevState);
+
+    // Current state should be the original state again
+    assertEquals(initialState, admin.isNormalizerOn().get());
+  }
+
+  @Test
+  public void testCleanerChore() throws Exception {
+    boolean initialState = admin.isCleanerChoreOn().get();
+
+    // flip state
+    boolean prevState = admin.setCleanerChoreOn(!initialState).get();
+
+    // The previous state should be the original state we observed
+    assertEquals(initialState, prevState);
+
+    // Current state should be opposite of the original
+    assertEquals(!initialState, admin.isCleanerChoreOn().get());
+
+    // Reset it back to what it was
+    prevState = admin.setCleanerChoreOn(initialState).get();
+
+    // The previous state should be the opposite of the initial state
+    assertEquals(!initialState, prevState);
+
+    // Current state should be the original state again
+    assertEquals(initialState, admin.isCleanerChoreOn().get());
+  }
+
+  @Test
+  public void testCatalogJanitor() throws Exception {
+    boolean initialState = admin.isCatalogJanitorOn().get();
+
+    // flip state
+    boolean prevState = admin.setCatalogJanitorOn(!initialState).get();
+
+    // The previous state should be the original state we observed
+    assertEquals(initialState, prevState);
+
+    // Current state should be opposite of the original
+    assertEquals(!initialState, admin.isCatalogJanitorOn().get());
+
+    // Reset it back to what it was
+    prevState = admin.setCatalogJanitorOn(initialState).get();
+
+    // The previous state should be the opposite of the initial state
+    assertEquals(!initialState, prevState);
+
+    // Current state should be the original state again
+    assertEquals(initialState, admin.isCatalogJanitorOn().get());
+  }
+}