You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by st...@apache.org on 2017/08/23 04:16:57 UTC

hbase git commit: HBASE-18509 Encapsulate all clocks in RS/Master into a new 'Clocks' class

Repository: hbase
Updated Branches:
  refs/heads/HBASE-14070.HLC 4e7c55d99 -> 4c56a3c28


HBASE-18509 Encapsulate all clocks in RS/Master into a new 'Clocks' class

Signed-off-by: Michael Stack <st...@apache.org>


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

Branch: refs/heads/HBASE-14070.HLC
Commit: 4c56a3c28a5eea721f82dae841bb88c48a2bb04e
Parents: 4e7c55d
Author: Amit Patel <ia...@gmail.com>
Authored: Tue Aug 22 13:02:57 2017 -0700
Committer: Michael Stack <st...@apache.org>
Committed: Tue Aug 22 21:16:17 2017 -0700

----------------------------------------------------------------------
 .../hbase/shaded/protobuf/ProtobufUtil.java     |   9 +-
 .../hadoop/hbase/master/MasterServices.java     |   8 +-
 .../master/procedure/RSProcedureDispatcher.java |  48 ++------
 .../hadoop/hbase/regionserver/Clocks.java       | 112 +++++++++++++++++++
 .../hadoop/hbase/regionserver/HRegion.java      |   5 +-
 .../hbase/regionserver/HRegionServer.java       |  46 +-------
 .../hbase/regionserver/RSRpcServices.java       |  32 ++----
 .../regionserver/RegionServerServices.java      |   7 +-
 .../hadoop/hbase/MockRegionServerServices.java  |   5 +-
 .../hadoop/hbase/TestClockWithCluster.java      |   8 +-
 .../hbase/master/MockNoopMasterServices.java    |   5 +-
 .../hadoop/hbase/master/MockRegionServer.java   |   8 +-
 .../regionserver/TestHRegionReplayEvents.java   |   2 +-
 .../regionserver/TestRegionSplitPolicy.java     |   5 +-
 .../hbase/regionserver/TestWALLockup.java       |   2 +-
 .../regionserver/wal/AbstractTestWALReplay.java |   2 +-
 16 files changed, 159 insertions(+), 145 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/4c56a3c2/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java
index 405c438..fa62b6a 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java
@@ -184,7 +184,6 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.ZooKeeperProtos;
 import org.apache.hadoop.hbase.util.Addressing;
 import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.hadoop.hbase.util.DynamicClassLoader;
-import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
 import org.apache.hadoop.hbase.util.ExceptionUtil;
 import org.apache.hadoop.hbase.util.ForeignExceptionUtil;
 import org.apache.hadoop.hbase.util.Methods;
@@ -3344,7 +3343,7 @@ public final class ProtobufUtil {
    }
 
   public static CloseRegionRequest buildCloseRegionRequest(ServerName server,
-    final byte[] regionName, ServerName destinationServer, List<Pair<ClockType, Long>> nodeTimes) {
+    final byte[] regionName, ServerName destinationServer, List<NodeTime> nodeTimes) {
     CloseRegionRequest.Builder builder = CloseRegionRequest.newBuilder();
     RegionSpecifier region = RequestConverter.buildRegionSpecifier(
       RegionSpecifierType.REGION_NAME, regionName);
@@ -3356,11 +3355,7 @@ public final class ProtobufUtil {
       builder.setServerStartCode(server.getStartcode());
     }
     if (nodeTimes != null) {
-      for (Pair<ClockType, Long> nodeTime : nodeTimes) {
-        builder.addNodeTimesBuilder()
-            .setClockType(ProtobufUtil.toClockType(nodeTime.getFirst()))
-            .setTimestamp(nodeTime.getSecond());
-      }
+      builder.addAllNodeTimes(nodeTimes);
     }
     return builder.build();
   }

http://git-wip-us.apache.org/repos/asf/hbase/blob/4c56a3c2/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterServices.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterServices.java
index d57cda0..08940b8 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterServices.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterServices.java
@@ -21,8 +21,6 @@ package org.apache.hadoop.hbase.master;
 import java.io.IOException;
 import java.util.List;
 
-import org.apache.hadoop.hbase.Clock;
-import org.apache.hadoop.hbase.ClockType;
 import org.apache.hadoop.hbase.HColumnDescriptor;
 import org.apache.hadoop.hbase.HRegionInfo;
 import org.apache.hadoop.hbase.HTableDescriptor;
@@ -48,6 +46,7 @@ import org.apache.hadoop.hbase.procedure2.LockInfo;
 import org.apache.hadoop.hbase.procedure2.ProcedureEvent;
 import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
 import org.apache.hadoop.hbase.quotas.MasterQuotaManager;
+import org.apache.hadoop.hbase.regionserver.Clocks;
 import org.apache.hadoop.hbase.replication.ReplicationException;
 import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
 import org.apache.hadoop.hbase.replication.ReplicationPeerDescription;
@@ -61,10 +60,9 @@ import com.google.protobuf.Service;
 @InterfaceAudience.Private
 public interface MasterServices extends Server {
   /**
-   * @param clockType The clock type
-   * @return Master's instance of {@link Clock}
+   * @return the underlying clocks instance
    */
-  Clock getClock(ClockType clockType);
+  Clocks getClocks();
 
   /**
    * @return the underlying snapshot manager

http://git-wip-us.apache.org/repos/asf/hbase/blob/4c56a3c2/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/RSProcedureDispatcher.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/RSProcedureDispatcher.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/RSProcedureDispatcher.java
index f29a7f2..1a8ca44 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/RSProcedureDispatcher.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/RSProcedureDispatcher.java
@@ -22,7 +22,6 @@ import org.apache.hadoop.hbase.shaded.com.google.common.collect.ArrayListMultima
 
 import java.io.IOException;
 import java.net.SocketTimeoutException;
-import java.util.ArrayList;
 import java.util.concurrent.Callable;
 import java.util.concurrent.TimeUnit;
 import java.util.List;
@@ -30,13 +29,10 @@ import java.util.Set;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.hbase.ClockType;
-import org.apache.hadoop.hbase.util.Pair;
 import org.apache.hadoop.ipc.RemoteException;
 import org.apache.hadoop.hbase.HRegionInfo;
 import org.apache.hadoop.hbase.ServerName;
 import org.apache.hadoop.hbase.DoNotRetryIOException;
-import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.NodeTime;
 import org.apache.hadoop.hbase.ipc.ServerNotRunningYetException;
 import org.apache.hadoop.hbase.master.MasterServices;
 import org.apache.hadoop.hbase.master.ServerListener;
@@ -271,16 +267,10 @@ public class RSProcedureDispatcher
         final ExecuteProceduresResponse response = sendRequest(getServerName(), request.build());
         // TODO: consider updating clock with just top timestamp from both loops
         for (OpenRegionResponse orr : response.getOpenRegionList()) {
-          for (NodeTime nodeTime : orr.getNodeTimesList()) {
-            env.getMasterServices().getClock(ProtobufUtil.toClockType(nodeTime.getClockType()))
-                .update(nodeTime.getTimestamp());
-          }
+          env.getMasterServices().getClocks().updateAll(orr.getNodeTimesList());
         }
         for (CloseRegionResponse crr : response.getCloseRegionList()) {
-          for (NodeTime nodeTime : crr.getNodeTimesList()) {
-            env.getMasterServices().getClock(ProtobufUtil.toClockType(nodeTime.getClockType()))
-                .update(nodeTime.getTimestamp());
-          }
+          env.getMasterServices().getClocks().updateAll(crr.getNodeTimesList());
         }
         remoteCallCompleted(env, response);
       } catch (IOException e) {
@@ -340,15 +330,8 @@ public class RSProcedureDispatcher
       final ServerName serverName, final List<RegionOpenOperation> operations) {
     final OpenRegionRequest.Builder builder = OpenRegionRequest.newBuilder();
     builder.setServerStartCode(serverName.getStartcode());
-
-    // Set master clock time for send event
-    builder.addNodeTimesBuilder()
-        .setClockType(ProtobufUtil.toClockType(ClockType.SYSTEM_MONOTONIC))
-        .setTimestamp(env.getMasterServices().getClock(ClockType.SYSTEM_MONOTONIC).now());
-    builder.addNodeTimesBuilder()
-        .setClockType(ProtobufUtil.toClockType(ClockType.HYBRID_LOGICAL))
-        .setTimestamp(env.getMasterServices().getClock(ClockType.HYBRID_LOGICAL).now());
-
+    // Set master clock times for send event
+    builder.addAllNodeTimes(env.getMasterServices().getClocks().nowAll());
     for (RegionOpenOperation op: operations) {
       builder.addOpenInfo(op.buildRegionOpenInfoRequest(env));
     }
@@ -371,11 +354,8 @@ public class RSProcedureDispatcher
       try {
         final OpenRegionRequest request = buildOpenRegionRequest(env, getServerName(), operations);
         OpenRegionResponse response = sendRequest(getServerName(), request);
-        for (NodeTime nodeTime : response.getNodeTimesList()) {
-          // Update master clock upon receiving open region response from region server
-          env.getMasterServices().getClock(ProtobufUtil.toClockType(nodeTime.getClockType()))
-              .update(nodeTime.getTimestamp());
-        }
+        // Update master clocks upon receiving open region response from region server
+        env.getMasterServices().getClocks().updateAll(response.getNodeTimesList());
         remoteCallCompleted(env, response);
       } catch (IOException e) {
         e = unwrapException(e);
@@ -429,11 +409,8 @@ public class RSProcedureDispatcher
       final CloseRegionRequest request = operation.buildCloseRegionRequest(env, getServerName());
       try {
         CloseRegionResponse response = sendRequest(getServerName(), request);
-        for (NodeTime nodeTime : response.getNodeTimesList()) {
-          // Update master clock upon receiving close region response from region server
-          env.getMasterServices().getClock(ProtobufUtil.toClockType(nodeTime.getClockType()))
-              .update(nodeTime.getTimestamp());
-        }
+        // Update master clock upon receiving close region response from region server
+        env.getMasterServices().getClocks().updateAll(response.getNodeTimesList());
         remoteCallCompleted(env, response);
       } catch (IOException e) {
         e = unwrapException(e);
@@ -572,14 +549,9 @@ public class RSProcedureDispatcher
 
     public CloseRegionRequest buildCloseRegionRequest(final MasterProcedureEnv env,
         final ServerName serverName) {
-      // Set master clock time for send event
-      List<Pair<ClockType, Long>> nodeTimes = new ArrayList<>();
-      nodeTimes.add(new Pair<>(ClockType.SYSTEM_MONOTONIC,
-          env.getMasterServices().getClock(ClockType.SYSTEM_MONOTONIC).now()));
-      nodeTimes.add(new Pair<>(ClockType.HYBRID_LOGICAL,
-          env.getMasterServices().getClock(ClockType.HYBRID_LOGICAL).now()));
       return ProtobufUtil.buildCloseRegionRequest(serverName,
-        getRegionInfo().getRegionName(), getDestinationServer(), nodeTimes);
+        getRegionInfo().getRegionName(), getDestinationServer(),
+          env.getMasterServices().getClocks().nowAll());
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/4c56a3c2/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/Clocks.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/Clocks.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/Clocks.java
new file mode 100644
index 0000000..a401007
--- /dev/null
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/Clocks.java
@@ -0,0 +1,112 @@
+/**
+ *
+ * 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.regionserver;
+
+import com.google.common.annotations.VisibleForTesting;
+import org.apache.hadoop.hbase.Clock;
+import org.apache.hadoop.hbase.ClockType;
+import org.apache.hadoop.hbase.HybridLogicalClock;
+import org.apache.hadoop.hbase.SystemClock;
+import org.apache.hadoop.hbase.SystemMonotonicClock;
+import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.NodeTime;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Clocks encapsulates each instance of a {@link Clock} to facilitate doing batch now() or update()
+ * on all of the clocks.
+ */
+public class Clocks {
+  private Clock systemClock;
+  private Clock systemMonotonicClock;
+  private Clock hybridLogicalClock;
+  private List<ClockType> clockTypes = new ArrayList<>();
+
+  public Clocks(long maxClockSkew) {
+    systemClock = new SystemClock();
+    systemMonotonicClock = new SystemMonotonicClock(maxClockSkew);
+    hybridLogicalClock = new HybridLogicalClock(maxClockSkew);
+
+    clockTypes.add(systemClock.getClockType());
+    clockTypes.add(systemMonotonicClock.getClockType());
+    clockTypes.add(hybridLogicalClock.getClockType());
+  }
+
+  public long update(ClockType clockType, long timestamp) {
+    return getClock(clockType).update(timestamp);
+  }
+
+  public long now(ClockType clockType) {
+    return getClock(clockType).now();
+  }
+
+  public List<Long> updateAll(List<NodeTime> nodeTimes) {
+    List<Long> updatedNodeTimes = new ArrayList<>();
+    for (NodeTime nodeTime : nodeTimes) {
+      ClockType clockType = ProtobufUtil.toClockType(nodeTime.getClockType());
+      updatedNodeTimes.add(update(clockType, nodeTime.getTimestamp()));
+    }
+    return updatedNodeTimes;
+  }
+
+  public List<NodeTime> nowAll() {
+    List<NodeTime> nodeTimes = new ArrayList<>();
+    for (ClockType clockType : clockTypes) {
+      NodeTime nodeTime = NodeTime.newBuilder()
+          .setClockType(ProtobufUtil.toClockType(clockType))
+          .setTimestamp(now(clockType))
+          .build();
+      nodeTimes.add(nodeTime);
+    }
+    return nodeTimes;
+  }
+
+  public Clock getClock(ClockType clockType) {
+    switch (clockType) {
+      case HYBRID_LOGICAL:
+        return hybridLogicalClock;
+      case SYSTEM_MONOTONIC:
+        return systemMonotonicClock;
+      case SYSTEM:
+        return systemClock;
+      default:
+        throw new IllegalArgumentException("Wrong clock type: " + clockType.toString());
+    }
+  }
+
+  @VisibleForTesting
+  public void setClock(Clock clock) {
+    switch (clock.getClockType()) {
+      case HYBRID_LOGICAL:
+        hybridLogicalClock = clock;
+        break;
+      case SYSTEM_MONOTONIC:
+        systemMonotonicClock = clock;
+        break;
+      case SYSTEM:
+        systemClock = clock;
+        break;
+      default:
+        throw new IllegalArgumentException("Wrong clock type: " + clock.getClockType().toString());
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/hbase/blob/4c56a3c2/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
index 1c1b26a..6119483 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
@@ -389,8 +389,7 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
   @Override
   public Clock getClock() {
     if (this.clock == null) {
-      return this.getRegionServerServices().getClock(
-          getTableDescriptor().getClockType());
+      return this.getRegionServerServices().getClocks().getClock(htableDescriptor.getClockType());
     }
     return this.clock;
   }
@@ -800,7 +799,7 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
         ? DEFAULT_DURABILITY
         : htd.getDurability();
     if (rsServices != null) {
-      this.clock = rsServices.getClock(htd.getClockType());
+      this.clock = rsServices.getClocks().getClock(htd.getClockType());
       this.rsAccounting = this.rsServices.getRegionServerAccounting();
       // don't initialize coprocessors if not running within a regionserver
       // TODO: revisit if coprocessors should load in other cases

http://git-wip-us.apache.org/repos/asf/hbase/blob/4c56a3c2/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
index fad0d96..fbf78d5 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
@@ -73,17 +73,13 @@ import org.apache.hadoop.hbase.HBaseInterfaceAudience;
 import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.HRegionInfo;
 import org.apache.hadoop.hbase.Clock;
-import org.apache.hadoop.hbase.ClockType;
 import org.apache.hadoop.hbase.HealthCheckChore;
-import org.apache.hadoop.hbase.HybridLogicalClock;
 import org.apache.hadoop.hbase.MetaTableAccessor;
 import org.apache.hadoop.hbase.NotServingRegionException;
 import org.apache.hadoop.hbase.PleaseHoldException;
 import org.apache.hadoop.hbase.ScheduledChore;
 import org.apache.hadoop.hbase.ServerName;
 import org.apache.hadoop.hbase.Stoppable;
-import org.apache.hadoop.hbase.SystemClock;
-import org.apache.hadoop.hbase.SystemMonotonicClock;
 import org.apache.hadoop.hbase.TableDescriptors;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.YouAreDeadException;
@@ -341,9 +337,7 @@ public class HRegionServer extends HasThread implements
   // Region server contains instances of all three clock clocks. Regions have a set
   // clock type so depending on the clock type needed by a region, the appropriate
   // one can be accessed.
-  protected Clock hybridLogicalClock;
-  protected Clock systemMonotonicClock;
-  protected Clock systemClock;
+  protected Clocks clocks;
 
   ConcurrentMap<String, Integer> rowlocks = new ConcurrentHashMap<>();
 
@@ -605,9 +599,7 @@ public class HRegionServer extends HasThread implements
 
     final long maxClockSkew =
         conf.getLong("hbase.max.clock.skew.in.ms", Clock.DEFAULT_MAX_CLOCK_SKEW_IN_MS);
-    this.hybridLogicalClock = new HybridLogicalClock(maxClockSkew);
-    this.systemMonotonicClock = new SystemMonotonicClock(maxClockSkew);
-    this.systemClock = new SystemClock();
+    this.clocks = new Clocks(maxClockSkew);
 
     rpcServices = createRpcServices();
     if (this instanceof HMaster) {
@@ -2094,38 +2086,8 @@ public class HRegionServer extends HasThread implements
   }
 
   @Override
-  public Clock getClock(ClockType clockType) {
-    switch (clockType) {
-      case HYBRID_LOGICAL:
-        return this.hybridLogicalClock;
-      case SYSTEM_MONOTONIC:
-        return this.systemMonotonicClock;
-      case SYSTEM:
-        return this.systemClock;
-      default:
-        throw new IllegalArgumentException("Wrong clock type: " + clockType.toString());
-    }
-  }
-
-  /**
-   * Only for the purpose of testing
-   * @param clock
-   */
-  @VisibleForTesting
-  public void setClock(Clock clock) {
-    switch (clock.getClockType()) {
-      case HYBRID_LOGICAL:
-        this.hybridLogicalClock = clock;
-        break;
-      case SYSTEM_MONOTONIC:
-        this.systemMonotonicClock = clock;
-        break;
-      case SYSTEM:
-        this.systemClock = clock;
-        break;
-      default:
-        throw new IllegalArgumentException("Wrong clock type: " + clock.getClockType().toString());
-    }
+  public Clocks getClocks() {
+    return clocks;
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/hbase/blob/4c56a3c2/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java
index fb33187..8c3dd2e 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java
@@ -53,7 +53,6 @@ import org.apache.hadoop.hbase.Cell;
 import org.apache.hadoop.hbase.CellScannable;
 import org.apache.hadoop.hbase.CellScanner;
 import org.apache.hadoop.hbase.CellUtil;
-import org.apache.hadoop.hbase.ClockType;
 import org.apache.hadoop.hbase.DoNotRetryIOException;
 import org.apache.hadoop.hbase.DroppedSnapshotException;
 import org.apache.hadoop.hbase.HBaseIOException;
@@ -209,7 +208,6 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.RegionLoad;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.NameBytesPair;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.NameInt64Pair;
-import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.NodeTime;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.RegionInfo;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.RegionSpecifier;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType;
@@ -1516,11 +1514,8 @@ public class RSRpcServices implements HBaseRPCErrorHandler,
       }
       final String encodedRegionName = ProtobufUtil.getRegionEncodedName(request.getRegion());
 
-      for (NodeTime nodeTime : request.getNodeTimesList()) {
-        // Update master clock upon receiving open region response from region server
-        regionServer.getClock(ProtobufUtil.toClockType(nodeTime.getClockType()))
-            .update(nodeTime.getTimestamp());
-      }
+      // Update master clocks upon receiving open region response from region server
+      regionServer.getClocks().updateAll(request.getNodeTimesList());
 
       requestCount.increment();
       if (sn == null) {
@@ -1532,12 +1527,7 @@ public class RSRpcServices implements HBaseRPCErrorHandler,
 
       CloseRegionResponse.Builder builder = CloseRegionResponse.newBuilder()
           .setClosed(closed)
-          .addNodeTimes(NodeTime.newBuilder()
-            .setClockType(ProtobufUtil.toClockType(ClockType.SYSTEM_MONOTONIC))
-            .setTimestamp(regionServer.getClock(ClockType.SYSTEM_MONOTONIC).now()).build())
-          .addNodeTimes(NodeTime.newBuilder()
-            .setClockType(ProtobufUtil.toClockType(ClockType.HYBRID_LOGICAL))
-            .setTimestamp(regionServer.getClock(ClockType.HYBRID_LOGICAL).now()).build());
+          .addAllNodeTimes(regionServer.getClocks().nowAll());
       return builder.build();
     } catch (IOException ie) {
       throw new ServiceException(ie);
@@ -1910,11 +1900,8 @@ public class RSRpcServices implements HBaseRPCErrorHandler,
       }
     }
 
-    for (NodeTime nodeTime : request.getNodeTimesList()) {
-      // Update region server clock on receive event
-      regionServer.getClock(ProtobufUtil.toClockType(nodeTime.getClockType()))
-          .update(nodeTime.getTimestamp());
-    }
+    // Update region server clocks on receive event
+    regionServer.getClocks().updateAll(request.getNodeTimesList());
 
     for (RegionOpenInfo regionOpenInfo : request.getOpenInfoList()) {
       final HRegionInfo region = HRegionInfo.convert(regionOpenInfo.getRegion());
@@ -2021,13 +2008,8 @@ public class RSRpcServices implements HBaseRPCErrorHandler,
       }
     }
 
-    // Set clock for send event
-    builder.addNodeTimes(NodeTime.newBuilder()
-        .setClockType(ProtobufUtil.toClockType(ClockType.SYSTEM_MONOTONIC))
-        .setTimestamp(regionServer.getClock(ClockType.SYSTEM_MONOTONIC).now()).build())
-      .addNodeTimes(NodeTime.newBuilder()
-        .setClockType(ProtobufUtil.toClockType(ClockType.HYBRID_LOGICAL))
-        .setTimestamp(regionServer.getClock(ClockType.HYBRID_LOGICAL).now()).build());
+    // Set node times for send event
+    builder.addAllNodeTimes(regionServer.getClocks().nowAll());
 
     return builder.build();
   }

http://git-wip-us.apache.org/repos/asf/hbase/blob/4c56a3c2/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionServerServices.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionServerServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionServerServices.java
index 8e9c742..375cce0 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionServerServices.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionServerServices.java
@@ -39,8 +39,6 @@ import org.apache.hadoop.hbase.quotas.RegionServerRpcQuotaManager;
 import org.apache.hadoop.hbase.quotas.RegionServerSpaceQuotaManager;
 import org.apache.hadoop.hbase.regionserver.throttle.ThroughputController;
 import org.apache.hadoop.hbase.wal.WAL;
-import org.apache.hadoop.hbase.Clock;
-import org.apache.hadoop.hbase.ClockType;
 import org.apache.zookeeper.KeeperException;
 
 import com.google.protobuf.Service;
@@ -61,10 +59,9 @@ public interface RegionServerServices extends OnlineRegions, FavoredNodesForRegi
   WAL getWAL(HRegionInfo regionInfo) throws IOException;
 
   /**
-   * @param clockType The clock type
-   * @return Region server's instance of {@link Clock}
+   * @return the underlying clocks instance
    */
-  Clock getClock(ClockType clockType);
+  Clocks getClocks();
 
   /** @return the List of WALs that are used by this server
    *  Doesn't include the meta WAL

http://git-wip-us.apache.org/repos/asf/hbase/blob/4c56a3c2/hbase-server/src/test/java/org/apache/hadoop/hbase/MockRegionServerServices.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/MockRegionServerServices.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/MockRegionServerServices.java
index 86ae056..77472e4 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/MockRegionServerServices.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/MockRegionServerServices.java
@@ -36,6 +36,7 @@ import org.apache.hadoop.hbase.client.locking.EntityLock;
 import org.apache.hadoop.hbase.executor.ExecutorService;
 import org.apache.hadoop.hbase.fs.HFileSystem;
 import org.apache.hadoop.hbase.ipc.RpcServerInterface;
+import org.apache.hadoop.hbase.regionserver.Clocks;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionStateTransition.TransitionCode;
 import org.apache.hadoop.hbase.quotas.RegionServerRpcQuotaManager;
@@ -253,8 +254,8 @@ public class MockRegionServerServices implements RegionServerServices {
   }
 
   @Override
-  public Clock getClock(ClockType clockType) {
-    return Clock.getDummyClockOfGivenClockType(clockType);
+  public Clocks getClocks() {
+    return null;
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/hbase/blob/4c56a3c2/hbase-server/src/test/java/org/apache/hadoop/hbase/TestClockWithCluster.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/TestClockWithCluster.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/TestClockWithCluster.java
index c1cca09..c107607 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/TestClockWithCluster.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/TestClockWithCluster.java
@@ -222,7 +222,7 @@ public class TestClockWithCluster {
 
     // Set meta region clock so that region state transitions are timestamped with mocked clock
     regionMeta.setClock(masterHLC);
-    master.setClock(masterHLC);
+    master.getClocks().setClock(masterHLC);
 
     HRegion userRegion = null;
     for (Region region : regions) {
@@ -234,7 +234,7 @@ public class TestClockWithCluster {
 
     // Only mock the region server clock because the region clock does not get used during
     // unassignment and assignment
-    rs.setClock(masterHLC);
+    rs.getClocks().setClock(masterHLC);
 
     // Repeatedly unassign and assign region while tracking the timestamps of the region state
     // transitions from the meta table
@@ -330,7 +330,7 @@ public class TestClockWithCluster {
     when(masterMockSystemClock.getTimeUnit()).thenReturn(TimeUnit.MILLISECONDS);
     HybridLogicalClock masterHLC =
         new HybridLogicalClock(new SystemMonotonicClock(masterMockSystemClock));
-    master.setClock(masterHLC);
+    master.getClocks().setClock(masterHLC);
     regionMeta.setClock(masterHLC);
 
     Clock rsMockSystemClock = mock(Clock.class);
@@ -341,7 +341,7 @@ public class TestClockWithCluster {
         new HybridLogicalClock(new SystemMonotonicClock(rsMockSystemClock));
     // We only mock the region server clock here because the region clock does not get used
     // during unassignment and assignment
-    rs.setClock(rsHLC);
+    rs.getClocks().setClock(rsHLC);
 
     // Increment master physical clock time
     expectedPhysicalTime += 1000;

http://git-wip-us.apache.org/repos/asf/hbase/blob/4c56a3c2/hbase-server/src/test/java/org/apache/hadoop/hbase/master/MockNoopMasterServices.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/MockNoopMasterServices.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/MockNoopMasterServices.java
index aea9093..ad655a3 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/MockNoopMasterServices.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/MockNoopMasterServices.java
@@ -22,8 +22,6 @@ import java.util.List;
 
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hbase.ChoreService;
-import org.apache.hadoop.hbase.Clock;
-import org.apache.hadoop.hbase.ClockType;
 import org.apache.hadoop.hbase.CoordinatedStateManager;
 import org.apache.hadoop.hbase.HColumnDescriptor;
 import org.apache.hadoop.hbase.HRegionInfo;
@@ -48,6 +46,7 @@ import org.apache.hadoop.hbase.procedure2.LockInfo;
 import org.apache.hadoop.hbase.procedure2.ProcedureEvent;
 import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
 import org.apache.hadoop.hbase.quotas.MasterQuotaManager;
+import org.apache.hadoop.hbase.regionserver.Clocks;
 import org.apache.hadoop.hbase.replication.ReplicationException;
 import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
 import org.apache.hadoop.hbase.replication.ReplicationPeerDescription;
@@ -91,7 +90,7 @@ public class MockNoopMasterServices implements MasterServices, Server {
   }
 
   @Override
-  public Clock getClock(ClockType clockType) { return null; };
+  public Clocks getClocks() { return null; };
 
   @Override
   public AssignmentManager getAssignmentManager() {

http://git-wip-us.apache.org/repos/asf/hbase/blob/4c56a3c2/hbase-server/src/test/java/org/apache/hadoop/hbase/master/MockRegionServer.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/MockRegionServer.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/MockRegionServer.java
index d4a07f5..84b58ca 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/MockRegionServer.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/MockRegionServer.java
@@ -34,13 +34,10 @@ import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.hbase.Abortable;
 import org.apache.hadoop.hbase.CellScannable;
 import org.apache.hadoop.hbase.CellUtil;
-import org.apache.hadoop.hbase.ClockType;
-import org.apache.hadoop.hbase.Clock;
 import org.apache.hadoop.hbase.ChoreService;
 import org.apache.hadoop.hbase.CoordinatedStateManager;
 import org.apache.hadoop.hbase.HRegionInfo;
 import org.apache.hadoop.hbase.ServerName;
-import org.apache.hadoop.hbase.SystemClock;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.ZooKeeperConnectionException;
 import org.apache.hadoop.hbase.client.ClusterConnection;
@@ -50,6 +47,7 @@ import org.apache.hadoop.hbase.client.locking.EntityLock;
 import org.apache.hadoop.hbase.executor.ExecutorService;
 import org.apache.hadoop.hbase.ipc.HBaseRpcController;
 import org.apache.hadoop.hbase.ipc.RpcServerInterface;
+import org.apache.hadoop.hbase.regionserver.Clocks;
 import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ClearCompactionQueuesRequest;
@@ -572,8 +570,8 @@ ClientProtos.ClientService.BlockingInterface, RegionServerServices {
   }
 
   @Override
-  public Clock getClock(ClockType clockType) {
-    return new SystemClock();
+  public Clocks getClocks() {
+    return null;
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/hbase/blob/4c56a3c2/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegionReplayEvents.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegionReplayEvents.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegionReplayEvents.java
index aeef694..54eaa57 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegionReplayEvents.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegionReplayEvents.java
@@ -173,7 +173,7 @@ public class TestHRegionReplayEvents {
     when(rss.getServerName()).thenReturn(ServerName.valueOf("foo", 1, 1));
     when(rss.getConfiguration()).thenReturn(CONF);
     when(rss.getRegionServerAccounting()).thenReturn(new RegionServerAccounting(CONF));
-    when(rss.getClock((ClockType)any())).thenReturn(new SystemClock());
+    when(rss.getClocks().getClock(any())).thenReturn(new SystemClock());
     String string = org.apache.hadoop.hbase.executor.EventType.RS_COMPACTED_FILES_DISCHARGER
         .toString();
     ExecutorService es = new ExecutorService(string);

http://git-wip-us.apache.org/repos/asf/hbase/blob/4c56a3c2/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionSplitPolicy.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionSplitPolicy.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionSplitPolicy.java
index 7120ab9..ecc2d8d 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionSplitPolicy.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionSplitPolicy.java
@@ -108,7 +108,7 @@ public class TestRegionSplitPolicy {
     final List<Region> regions = new ArrayList<>();
     Mockito.when(rss.getOnlineRegions(TABLENAME)).thenReturn(regions);
     Mockito.when(mockRegion.getRegionServerServices()).thenReturn(rss);
-    Mockito.when(rss.getClock(ClockType.SYSTEM)).thenReturn(new SystemClock());
+    Mockito.when(rss.getClocks().getClock(ClockType.SYSTEM)).thenReturn(new SystemClock());
     // Set max size for this 'table'.
     long maxSplitSize = 1024L;
     htd.setMaxFileSize(maxSplitSize);
@@ -170,8 +170,7 @@ public class TestRegionSplitPolicy {
     Mockito.when(mockRegion.getRegionServerServices()).thenReturn(rss);
     Mockito.when(mockRegion.getBlockedRequestsCount()).thenReturn(0L);
     Mockito.when(mockRegion.getWriteRequestsCount()).thenReturn(0L);
-    Mockito.when(rss.getClock(ClockType.SYSTEM)).thenReturn(new SystemClock());
-
+    Mockito.when(rss.getClocks().getClock(ClockType.SYSTEM)).thenReturn(new SystemClock());
 
     BusyRegionSplitPolicy policy =
         (BusyRegionSplitPolicy)RegionSplitPolicy.create(mockRegion, conf);

http://git-wip-us.apache.org/repos/asf/hbase/blob/4c56a3c2/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestWALLockup.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestWALLockup.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestWALLockup.java
index 4b448e6..cf535c8 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestWALLockup.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestWALLockup.java
@@ -205,7 +205,7 @@ public class TestWALLockup {
     Mockito.when(server.isStopped()).thenReturn(false);
     Mockito.when(server.isAborted()).thenReturn(false);
     RegionServerServices services = Mockito.mock(RegionServerServices.class);
-    Mockito.when(services.getClock(ClockType.SYSTEM)).thenReturn(new SystemClock());
+    Mockito.when(services.getClocks().getClock(ClockType.SYSTEM)).thenReturn(new SystemClock());
 
     // OK. Now I have my mocked up Server & RegionServerServices and dodgy WAL, go ahead with test.
     FileSystem fs = FileSystem.get(CONF);

http://git-wip-us.apache.org/repos/asf/hbase/blob/4c56a3c2/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/wal/AbstractTestWALReplay.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/wal/AbstractTestWALReplay.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/wal/AbstractTestWALReplay.java
index bed393f..ebbcf2e 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/wal/AbstractTestWALReplay.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/wal/AbstractTestWALReplay.java
@@ -687,7 +687,7 @@ public abstract class AbstractTestWALReplay {
     WAL wal = createWAL(this.conf, hbaseRootDir, logName);
     RegionServerServices rsServices = Mockito.mock(RegionServerServices.class);
     Mockito.doReturn(false).when(rsServices).isAborted();
-    when(rsServices.getClock(clock.getClockType())).thenReturn(clock);
+    when(rsServices.getClocks().getClock(clock.getClockType())).thenReturn(clock);
     when(rsServices.getServerName()).thenReturn(ServerName.valueOf("foo", 10, 10));
     Configuration customConf = new Configuration(this.conf);
     customConf.set(DefaultStoreEngine.DEFAULT_STORE_FLUSHER_CLASS_KEY,