This is an automated email from the ASF dual-hosted git repository.

nealsun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/helix.git


The following commit(s) were added to refs/heads/master by this push:
     new eaf8b43a7 Enable MSDS auto refresh for DedicatedZkClient (#2357)
eaf8b43a7 is described below

commit eaf8b43a7de3ec2f262ea3943463323296e4541a
Author: Neal Sun <[email protected]>
AuthorDate: Wed Feb 8 09:59:50 2023 -0800

    Enable MSDS auto refresh for DedicatedZkClient (#2357)
    
    Enable MSDS auto refresh for DedicatedZkClient
---
 .../integration/multizk/TestMultiInMultiZk.java    |   2 +-
 .../multizk/TestMultiZkConnectionConfig.java       |   2 +-
 .../multizk/TestMultiZkHelixJavaApis.java          |   4 +-
 .../helix/task/TestTaskStateModelFactory.java      |   2 +-
 .../apache/helix/rest/server/ServerContext.java    |   2 +-
 .../zookeeper/impl/client/DedicatedZkClient.java   |  67 ++++-
 .../zookeeper/impl/client/FederatedZkClient.java   |  71 +----
 .../zookeeper/routing/RoutingDataManager.java      |  41 ++-
 .../client/RealmAwareZkClientFactoryTestBase.java  |   2 -
 .../impl/client/RealmAwareZkClientTestBase.java    |  12 +-
 .../impl/client/TestDedicatedZkClient.java         | 319 +++++++++++++++++++++
 .../impl/client/TestFederatedZkClient.java         |  19 +-
 .../zookeeper/util/TestRoutingDataManager.java     |   2 +-
 13 files changed, 458 insertions(+), 87 deletions(-)

diff --git 
a/helix-core/src/test/java/org/apache/helix/integration/multizk/TestMultiInMultiZk.java
 
b/helix-core/src/test/java/org/apache/helix/integration/multizk/TestMultiInMultiZk.java
index 697dda3ac..6eea2a9b9 100644
--- 
a/helix-core/src/test/java/org/apache/helix/integration/multizk/TestMultiInMultiZk.java
+++ 
b/helix-core/src/test/java/org/apache/helix/integration/multizk/TestMultiInMultiZk.java
@@ -48,7 +48,7 @@ public class TestMultiInMultiZk extends MultiZkTestBase {
     public void beforeClass() throws Exception {
         super.beforeClass();
         // Routing data may be set by other tests using the same endpoint; 
reset() for good measure
-        RoutingDataManager.getInstance().reset();
+        RoutingDataManager.getInstance().reset(true);
         // Create a FederatedZkClient for admin work
 
         try {
diff --git 
a/helix-core/src/test/java/org/apache/helix/integration/multizk/TestMultiZkConnectionConfig.java
 
b/helix-core/src/test/java/org/apache/helix/integration/multizk/TestMultiZkConnectionConfig.java
index 3b02ddddf..d86905d21 100644
--- 
a/helix-core/src/test/java/org/apache/helix/integration/multizk/TestMultiZkConnectionConfig.java
+++ 
b/helix-core/src/test/java/org/apache/helix/integration/multizk/TestMultiZkConnectionConfig.java
@@ -70,7 +70,7 @@ public class TestMultiZkConnectionConfig extends 
MultiZkTestBase {
   public void beforeClass() throws Exception {
     super.beforeClass();
     // Routing data may be set by other tests using the same endpoint; reset() 
for good measure
-    RoutingDataManager.getInstance().reset();
+    RoutingDataManager.getInstance().reset(true);
     // Create a FederatedZkClient for admin work
     try {
       _zkClient =
diff --git 
a/helix-core/src/test/java/org/apache/helix/integration/multizk/TestMultiZkHelixJavaApis.java
 
b/helix-core/src/test/java/org/apache/helix/integration/multizk/TestMultiZkHelixJavaApis.java
index 3bc0cf6d1..3336c56b7 100644
--- 
a/helix-core/src/test/java/org/apache/helix/integration/multizk/TestMultiZkHelixJavaApis.java
+++ 
b/helix-core/src/test/java/org/apache/helix/integration/multizk/TestMultiZkHelixJavaApis.java
@@ -91,7 +91,7 @@ public class TestMultiZkHelixJavaApis extends 
TestMultiZkConnectionConfig {
     System.setProperty(MetadataStoreRoutingConstants.MSDS_SERVER_ENDPOINT_KEY, 
_msdsEndpoint);
 
     // Routing data may be set by other tests using the same endpoint; reset() 
for good measure
-    RoutingDataManager.getInstance().reset();
+    RoutingDataManager.getInstance().reset(true);
     // Create a FederatedZkClient for admin work
     _zkClient =
         new FederatedZkClient(new 
RealmAwareZkClient.RealmAwareZkConnectionConfig.Builder().build(),
@@ -832,7 +832,7 @@ public class TestMultiZkHelixJavaApis extends 
TestMultiZkConnectionConfig {
             .setRoutingDataSourceEndpoint(_msdsEndpoint).build();
 
     // Reset cached routing data
-    RoutingDataManager.getInstance().reset();
+    RoutingDataManager.getInstance().reset(true);
     // Shutdown MSDS to ensure that these accessors are able to pull routing 
data from ZK
     _msds.stopServer();
 
diff --git 
a/helix-core/src/test/java/org/apache/helix/task/TestTaskStateModelFactory.java 
b/helix-core/src/test/java/org/apache/helix/task/TestTaskStateModelFactory.java
index 38286b497..c0e028028 100644
--- 
a/helix-core/src/test/java/org/apache/helix/task/TestTaskStateModelFactory.java
+++ 
b/helix-core/src/test/java/org/apache/helix/task/TestTaskStateModelFactory.java
@@ -91,7 +91,7 @@ public class TestTaskStateModelFactory extends TaskTestBase {
     System.setProperty(MetadataStoreRoutingConstants.MSDS_SERVER_ENDPOINT_KEY,
         testMSDSServerEndpointKey);
 
-    RoutingDataManager.getInstance().reset();
+    RoutingDataManager.getInstance().reset(true);
     verifyThreadPoolSizeAndZkClientClass(anyParticipantManager, 
TEST_TARGET_TASK_THREAD_POOL_SIZE,
         FederatedZkClient.class);
 
diff --git 
a/helix-rest/src/main/java/org/apache/helix/rest/server/ServerContext.java 
b/helix-rest/src/main/java/org/apache/helix/rest/server/ServerContext.java
index 27921f6e2..d355db0fe 100644
--- a/helix-rest/src/main/java/org/apache/helix/rest/server/ServerContext.java
+++ b/helix-rest/src/main/java/org/apache/helix/rest/server/ServerContext.java
@@ -379,7 +379,7 @@ public class ServerContext implements IZkDataListener, 
IZkChildListener, IZkStat
           _zkAddr);
       try {
         // Reset RoutingDataManager's cache
-        RoutingDataManager.getInstance().reset();
+        RoutingDataManager.getInstance().reset(true);
 
         // Close all ZkClients
         if (_zkClient != null && !_zkClient.isClosed()) {
diff --git 
a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/client/DedicatedZkClient.java
 
b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/client/DedicatedZkClient.java
index 738a070b4..8dba7d81e 100644
--- 
a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/client/DedicatedZkClient.java
+++ 
b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/client/DedicatedZkClient.java
@@ -27,6 +27,10 @@ import 
org.apache.helix.msdcommon.datamodel.MetadataStoreRoutingData;
 import org.apache.helix.msdcommon.exception.InvalidRoutingDataException;
 import org.apache.helix.zookeeper.api.client.ChildrenSubscribeResult;
 import org.apache.helix.zookeeper.api.client.RealmAwareZkClient;
+import org.apache.helix.zookeeper.constant.RoutingDataConstants;
+import org.apache.helix.zookeeper.constant.RoutingSystemPropertyKeys;
+import org.apache.helix.zookeeper.exception.MultiZkException;
+import org.apache.helix.zookeeper.routing.RoutingDataManager;
 import org.apache.helix.zookeeper.zkclient.DataUpdater;
 import org.apache.helix.zookeeper.zkclient.IZkChildListener;
 import org.apache.helix.zookeeper.zkclient.IZkConnection;
@@ -56,10 +60,12 @@ public class DedicatedZkClient implements 
RealmAwareZkClient {
   private static Logger LOG = LoggerFactory.getLogger(DedicatedZkClient.class);
 
   private final ZkClient _rawZkClient;
-  private final MetadataStoreRoutingData _metadataStoreRoutingData;
+  private volatile MetadataStoreRoutingData _metadataStoreRoutingData;
   private final String _zkRealmShardingKey;
   private final RealmAwareZkClient.RealmAwareZkConnectionConfig 
_connectionConfig;
   private final RealmAwareZkClient.RealmAwareZkClientConfig _clientConfig;
+  private final boolean _routingDataUpdateOnCacheMissEnabled = 
Boolean.parseBoolean(
+      
System.getProperty(RoutingSystemPropertyKeys.UPDATE_ROUTING_DATA_ON_CACHE_MISS));
 
   /**
    * DedicatedZkClient connects to a single ZK realm and supports full 
ZkClient functionalities
@@ -86,7 +92,7 @@ public class DedicatedZkClient implements RealmAwareZkClient {
     }
 
     // Get the ZkRealm address based on the ZK path sharding key
-    String zkRealmAddress = 
_metadataStoreRoutingData.getMetadataStoreRealm(_zkRealmShardingKey);
+    String zkRealmAddress = getZkRealm(_zkRealmShardingKey);
     if (zkRealmAddress == null || zkRealmAddress.isEmpty()) {
       throw new IllegalArgumentException(
           "ZK realm address for the given ZK realm sharding key is invalid! ZK 
realm address: "
@@ -582,4 +588,61 @@ public class DedicatedZkClient implements 
RealmAwareZkClient {
           + " does not have a valid sharding key or its ZK sharding key is not 
found in the cached routing data!");
     }
   }
+
+  private String getZkRealm(String path) {
+    if (_routingDataUpdateOnCacheMissEnabled) {
+      try {
+        return updateRoutingDataOnCacheMiss(path);
+      } catch (InvalidRoutingDataException e) {
+        throw new MultiZkException("DedicatedZkClient::getZkRealm: Failed to 
update routing data due to invalid routing "
+            + "data!", e);
+      }
+    }
+    return _metadataStoreRoutingData.getMetadataStoreRealm(path);
+  }
+
+  /**
+   * Perform a 2-tier routing data cache update:
+   * 1. Do an in-memory update from the singleton RoutingDataManager
+   * 2. Do an I/O based read from the routing data source by resetting 
RoutingDataManager
+   * @param path
+   * @return
+   * @throws InvalidRoutingDataException
+   */
+  private String updateRoutingDataOnCacheMiss(String path) throws 
InvalidRoutingDataException {
+    String zkRealm;
+    try {
+      zkRealm = _metadataStoreRoutingData.getMetadataStoreRealm(path);
+    } catch (NoSuchElementException e1) {
+      synchronized (this) {
+        try {
+          zkRealm = _metadataStoreRoutingData.getMetadataStoreRealm(path);
+        } catch (NoSuchElementException e2) {
+          // Try 1) Refresh MetadataStoreRoutingData from RoutingDataManager
+          // This is an in-memory refresh from the Singleton 
RoutingDataManager - other
+          // ZkClient objects may have triggered a cache refresh, so we first 
update the
+          // in-memory reference. This refresh only affects this 
object/thread, so we synchronize
+          // on "this".
+          _metadataStoreRoutingData = 
RealmAwareZkClient.getMetadataStoreRoutingData(_connectionConfig);
+          try {
+            zkRealm = _metadataStoreRoutingData.getMetadataStoreRealm(path);
+          } catch (NoSuchElementException e3) {
+            try {
+              zkRealm = _metadataStoreRoutingData.getMetadataStoreRealm(path);
+            } catch (NoSuchElementException e4) {
+              // Try 2) Reset RoutingDataManager and re-read the routing data 
from routing data
+              // source via I/O, since RoutingDataManager's cache doesn't have 
it either.
+              RoutingDataManager.getInstance().reset(false);
+              _metadataStoreRoutingData = 
RealmAwareZkClient.getMetadataStoreRoutingData(_connectionConfig);
+              // No try-catch for the following call because if this throws a
+              // NoSuchElementException, it means the ZK path sharding key 
doesn't exist even
+              // after a full cache refresh
+              zkRealm = _metadataStoreRoutingData.getMetadataStoreRealm(path);
+            }
+          }
+        }
+      }
+    }
+    return zkRealm;
+  }
 }
diff --git 
a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/client/FederatedZkClient.java
 
b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/client/FederatedZkClient.java
index 16baf1a9b..8069985e3 100644
--- 
a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/client/FederatedZkClient.java
+++ 
b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/client/FederatedZkClient.java
@@ -86,7 +86,6 @@ public class FederatedZkClient implements RealmAwareZkClient {
   private PathBasedZkSerializer _pathBasedZkSerializer;
   private final boolean _routingDataUpdateOnCacheMissEnabled = 
Boolean.parseBoolean(
       
System.getProperty(RoutingSystemPropertyKeys.UPDATE_ROUTING_DATA_ON_CACHE_MISS));
-  private long _routingDataUpdateInterval;
 
   // TODO: support capacity of ZkClient number in one FederatedZkClient and do 
garbage collection.
   public FederatedZkClient(RealmAwareZkClient.RealmAwareZkConnectionConfig 
connectionConfig,
@@ -103,7 +102,6 @@ public class FederatedZkClient implements 
RealmAwareZkClient {
     _clientConfig = clientConfig;
     _pathBasedZkSerializer = clientConfig.getZkSerializer();
     _zkRealmToZkClientMap = new ConcurrentHashMap<>();
-    getRoutingDataUpdateInterval();
   }
 
   @Override
@@ -646,10 +644,8 @@ public class FederatedZkClient implements 
RealmAwareZkClient {
       try {
         return updateRoutingDataOnCacheMiss(path);
       } catch (InvalidRoutingDataException e) {
-        LOG.error(
-            "FederatedZkClient::getZkRealm: Failed to update routing data due 
to invalid routing "
-                + "data!", e);
-        throw new MultiZkException(e);
+        throw new MultiZkException("FederatedZkClient::getZkRealm: Failed to 
update routing data due to invalid routing "
+            + "data!", e);
       }
     }
     return _metadataStoreRoutingData.getMetadataStoreRealm(path);
@@ -674,7 +670,7 @@ public class FederatedZkClient implements 
RealmAwareZkClient {
         } catch (NoSuchElementException e2) {
           // Try 1) Refresh MetadataStoreRoutingData from RoutingDataManager
           // This is an in-memory refresh from the Singleton 
RoutingDataManager - other
-          // FederatedZkClient objects may have triggered a cache refresh, so 
we first update the
+          // ZkClient objects may have triggered a cache refresh, so we first 
update the
           // in-memory reference. This refresh only affects this 
object/thread, so we synchronize
           // on "this".
           _metadataStoreRoutingData =
@@ -682,26 +678,17 @@ public class FederatedZkClient implements 
RealmAwareZkClient {
           try {
             zkRealm = _metadataStoreRoutingData.getMetadataStoreRealm(path);
           } catch (NoSuchElementException e3) {
-            synchronized (FederatedZkClient.class) {
-              try {
-                zkRealm = 
_metadataStoreRoutingData.getMetadataStoreRealm(path);
-              } catch (NoSuchElementException e4) {
-                if (shouldThrottleRead()) {
-                  // If routing data update from routing data source has taken 
place recently,
-                  // then just skip the update and throw the exception
-                  throw e4;
-                }
-                // Try 2) Reset RoutingDataManager and re-read the routing 
data from routing data
-                // source via I/O. Since RoutingDataManager's cache doesn't 
have it either, so we
-                // synchronize on all threads by locking on 
FederatedZkClient.class.
-                RoutingDataManager.getInstance().reset();
-                _metadataStoreRoutingData =
-                    
RealmAwareZkClient.getMetadataStoreRoutingData(_connectionConfig);
-                // No try-catch for the following call because if this throws a
-                // NoSuchElementException, it means the ZK path sharding key 
doesn't exist even
-                // after a full cache refresh
-                zkRealm = 
_metadataStoreRoutingData.getMetadataStoreRealm(path);
-              }
+            try {
+              zkRealm = _metadataStoreRoutingData.getMetadataStoreRealm(path);
+            } catch (NoSuchElementException e4) {
+              // Try 2) Reset RoutingDataManager and re-read the routing data 
from routing data
+              // source via I/O, since RoutingDataManager's cache doesn't have 
it either.
+              RoutingDataManager.getInstance().reset(false);
+              _metadataStoreRoutingData = 
RealmAwareZkClient.getMetadataStoreRoutingData(_connectionConfig);
+              // No try-catch for the following call because if this throws a
+              // NoSuchElementException, it means the ZK path sharding key 
doesn't exist even
+              // after a full cache refresh
+              zkRealm = _metadataStoreRoutingData.getMetadataStoreRealm(path);
             }
           }
         }
@@ -730,34 +717,4 @@ public class FederatedZkClient implements 
RealmAwareZkClient {
             + ". Instead, please use " + DEDICATED_ZK_CLIENT_FACTORY
             + " to create a dedicated RealmAwareZkClient for this operation.");
   }
-
-  /**
-   * Resolves the routing data update interval value from System Properties.
-   */
-  private void getRoutingDataUpdateInterval() {
-    try {
-      _routingDataUpdateInterval = Long.parseLong(
-          
System.getProperty(RoutingSystemPropertyKeys.ROUTING_DATA_UPDATE_INTERVAL_MS));
-      if (_routingDataUpdateInterval < 0) {
-        LOG.warn("FederatedZkClient::shouldThrottleRead(): invalid value: {} 
given for "
-                + "ROUTING_DATA_UPDATE_INTERVAL_MS, using the default value (5 
sec) instead!",
-            _routingDataUpdateInterval);
-        _routingDataUpdateInterval = 
RoutingDataConstants.DEFAULT_ROUTING_DATA_UPDATE_INTERVAL_MS;
-      }
-    } catch (NumberFormatException e) {
-      LOG.warn("FederatedZkClient::shouldThrottleRead(): failed to parse "
-          + "ROUTING_DATA_UPDATE_INTERVAL_MS, using the default value (5 sec) 
instead!", e);
-      _routingDataUpdateInterval = 
RoutingDataConstants.DEFAULT_ROUTING_DATA_UPDATE_INTERVAL_MS;
-    }
-  }
-
-  /**
-   * Return whether the read request to routing data source should be 
throttled using the default
-   * routing data update interval.
-   * @return
-   */
-  private boolean shouldThrottleRead() {
-    return System.currentTimeMillis() - 
RoutingDataManager.getInstance().getLastResetTimestamp()
-        < _routingDataUpdateInterval;
-  }
 }
diff --git 
a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/routing/RoutingDataManager.java
 
b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/routing/RoutingDataManager.java
index 2afd62c9b..9505b8e6a 100644
--- 
a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/routing/RoutingDataManager.java
+++ 
b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/routing/RoutingDataManager.java
@@ -28,7 +28,9 @@ import 
org.apache.helix.msdcommon.constant.MetadataStoreRoutingConstants;
 import org.apache.helix.msdcommon.datamodel.MetadataStoreRoutingData;
 import org.apache.helix.msdcommon.datamodel.TrieRoutingData;
 import org.apache.helix.msdcommon.exception.InvalidRoutingDataException;
+import org.apache.helix.zookeeper.constant.RoutingDataConstants;
 import org.apache.helix.zookeeper.constant.RoutingDataReaderType;
+import org.apache.helix.zookeeper.constant.RoutingSystemPropertyKeys;
 import org.apache.helix.zookeeper.exception.MultiZkException;
 import org.apache.helix.zookeeper.impl.client.SharedZkClient;
 import org.slf4j.Logger;
@@ -59,14 +61,18 @@ public class RoutingDataManager {
   // Tracks the time at which reset() was called last. Used to throttle reset()
   private volatile long _lastResetTimestamp;
 
-  // Singleton instance
-  private static RoutingDataManager _instance;
+  // Interval value used to throttle reset()
+  private long _routingDataUpdateInterval;
+
+  // Singleton instance; volatile for multithread safety
+  private volatile static RoutingDataManager _instance;
 
   /**
    * This class is a Singleton.
    */
   private RoutingDataManager() {
     // Private constructor for Singleton
+    parseRoutingDataUpdateInterval();
   }
 
   /**
@@ -166,8 +172,18 @@ public class RoutingDataManager {
 
   /**
    * Clears the statically-cached routing data and private fields.
+   * @param isForcedReset - if true, ignore throttle settings
    */
-  public synchronized void reset() {
+  public synchronized void reset(boolean isForcedReset) {
+    if (!isForcedReset && System.currentTimeMillis() - 
RoutingDataManager.getInstance().getLastResetTimestamp()
+        < _routingDataUpdateInterval) {
+      return;
+    }
+
+    reset();
+  }
+
+  private synchronized void reset() {
     _rawRoutingDataMap.clear();
     _metadataStoreRoutingDataMap.clear();
     _defaultMsdsEndpoint =
@@ -183,6 +199,25 @@ public class RoutingDataManager {
     return _lastResetTimestamp;
   }
 
+  /**
+   * Resolves the routing data update interval value from System Properties.
+   */
+  public void parseRoutingDataUpdateInterval() {
+    try {
+      _routingDataUpdateInterval =
+          
Long.parseLong(System.getProperty(RoutingSystemPropertyKeys.ROUTING_DATA_UPDATE_INTERVAL_MS));
+      if (_routingDataUpdateInterval < 0) {
+        LOG.warn("FederatedZkClient::shouldThrottleRead(): invalid value: {} 
given for "
+            + "ROUTING_DATA_UPDATE_INTERVAL_MS, using the default value (5 
sec) instead!", _routingDataUpdateInterval);
+        _routingDataUpdateInterval = 
RoutingDataConstants.DEFAULT_ROUTING_DATA_UPDATE_INTERVAL_MS;
+      }
+    } catch (NumberFormatException e) {
+      LOG.warn("FederatedZkClient::shouldThrottleRead(): failed to parse "
+          + "ROUTING_DATA_UPDATE_INTERVAL_MS, using the default value (5 sec) 
instead!", e);
+      _routingDataUpdateInterval = 
RoutingDataConstants.DEFAULT_ROUTING_DATA_UPDATE_INTERVAL_MS;
+    }
+  }
+
   /**
    * Returns an appropriate instance of RoutingDataReader given the type.
    * @param routingDataReaderType
diff --git 
a/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/RealmAwareZkClientFactoryTestBase.java
 
b/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/RealmAwareZkClientFactoryTestBase.java
index ce53464b8..29c2df0f8 100644
--- 
a/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/RealmAwareZkClientFactoryTestBase.java
+++ 
b/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/RealmAwareZkClientFactoryTestBase.java
@@ -45,13 +45,11 @@ public abstract class RealmAwareZkClientFactoryTestBase 
extends RealmAwareZkClie
 
   @BeforeClass
   public void beforeClass() throws IOException, InvalidRoutingDataException {
-    super.beforeClass();
     DUMMY_RECORD.setSimpleField("Dummy", "Value");
   }
 
   @AfterClass
   public void afterClass() {
-    super.afterClass();
     if (_realmAwareZkClient != null && !_realmAwareZkClient.isClosed()) {
       _realmAwareZkClient.close();
       _realmAwareZkClient = null;
diff --git 
a/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/RealmAwareZkClientTestBase.java
 
b/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/RealmAwareZkClientTestBase.java
index 49bb78775..a88a0d582 100644
--- 
a/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/RealmAwareZkClientTestBase.java
+++ 
b/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/RealmAwareZkClientTestBase.java
@@ -35,8 +35,8 @@ import org.apache.zookeeper.Op;
 import org.apache.zookeeper.OpResult;
 import org.apache.zookeeper.ZooDefs;
 import org.testng.Assert;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
 
 
@@ -54,8 +54,8 @@ public abstract class RealmAwareZkClientTestBase extends 
ZkTestBase {
   protected RealmAwareZkClient _realmAwareZkClient;
   protected RealmAwareZkClientFactory _realmAwareZkClientFactory;
 
-  @BeforeClass
-  public void beforeClass() throws IOException, InvalidRoutingDataException {
+  @BeforeTest
+  public void beforeTest() throws IOException, InvalidRoutingDataException {
     // Create a mock MSDS so that HttpRoutingDataReader could fetch the 
routing data
     if (_msdsServer == null) {
       // Do not create again if Mock MSDS server has already been created by 
other tests
@@ -70,8 +70,8 @@ public abstract class RealmAwareZkClientTestBase extends 
ZkTestBase {
     System.setProperty(MetadataStoreRoutingConstants.MSDS_SERVER_ENDPOINT_KEY, 
msdsEndpoint);
   }
 
-  @AfterClass
-  public void afterClass() {
+  @AfterTest
+  public void afterTest() {
     if (_msdsServer != null) {
       _msdsServer.stopServer();
     }
diff --git 
a/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/TestDedicatedZkClient.java
 
b/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/TestDedicatedZkClient.java
index fe8d8bd75..82ffc1f5d 100644
--- 
a/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/TestDedicatedZkClient.java
+++ 
b/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/TestDedicatedZkClient.java
@@ -21,17 +21,336 @@ package org.apache.helix.zookeeper.impl.client;
 
 import java.io.IOException;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import org.apache.helix.msdcommon.constant.MetadataStoreRoutingConstants;
+import org.apache.helix.msdcommon.datamodel.MetadataStoreRoutingData;
 import org.apache.helix.msdcommon.exception.InvalidRoutingDataException;
+import org.apache.helix.msdcommon.mock.MockMetadataStoreDirectoryServer;
+import org.apache.helix.zookeeper.api.client.RealmAwareZkClient;
+import org.apache.helix.zookeeper.constant.RoutingDataReaderType;
+import org.apache.helix.zookeeper.constant.RoutingSystemPropertyKeys;
+import org.apache.helix.zookeeper.constant.TestConstants;
+import org.apache.helix.zookeeper.datamodel.ZNRecord;
+import org.apache.helix.zookeeper.datamodel.serializer.ZNRecordSerializer;
 import org.apache.helix.zookeeper.impl.factory.DedicatedZkClientFactory;
+import org.apache.helix.zookeeper.routing.RoutingDataManager;
+import org.apache.zookeeper.CreateMode;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
 
 
 public class TestDedicatedZkClient extends RealmAwareZkClientFactoryTestBase {
 
   @BeforeClass
   public void beforeClass() throws IOException, InvalidRoutingDataException {
+    System.out.println("Starting " + 
TestDedicatedZkClient.class.getSimpleName());
     super.beforeClass();
     // Set the factory to DedicatedZkClientFactory
     _realmAwareZkClientFactory = DedicatedZkClientFactory.getInstance();
   }
+
+  @AfterClass
+  public void afterClass() {
+    super.afterClass();
+    // Close it as it is created in before class.
+    System.out.println("Ending " + 
TestDedicatedZkClient.class.getSimpleName());
+  }
+
+  /**
+   * This tests the routing data update feature only enabled when
+   * RoutingSystemPropertyKeys.UPDATE_ROUTING_DATA_ON_CACHE_MISS is set to 
true.
+   * Routing data source is MSDS.
+   */
+  @Test
+  public void testUpdateRoutingDataOnCacheMissMSDS()
+      throws IOException, InvalidRoutingDataException {
+    // Enable routing data update upon cache miss
+    
System.setProperty(RoutingSystemPropertyKeys.UPDATE_ROUTING_DATA_ON_CACHE_MISS, 
"true");
+    // Set the routing data update interval to 0 so there's no delay in testing
+    
System.setProperty(RoutingSystemPropertyKeys.ROUTING_DATA_UPDATE_INTERVAL_MS, 
"0");
+    RoutingDataManager.getInstance().parseRoutingDataUpdateInterval();
+
+    RoutingDataManager.getInstance().getMetadataStoreRoutingData();
+    _msdsServer.stopServer();
+    /*
+     * Test is 2-tiered because cache update is 2-tiered
+     * Case 1:
+     * - RoutingDataManager (in-memory) does not have the key
+     * - MSDS has the key
+     * This simulates a case where DedicatedZkClient must do a I/O based 
update.
+     */
+    // Start MSDS with a new key
+    String newShardingKey = "/sharding-key-9";
+    String zkRealm = "localhost:2127";
+    Map<String, Collection<String>> rawRoutingData = new HashMap<>();
+    rawRoutingData.put(zkRealm, new ArrayList<>());
+    rawRoutingData.get(zkRealm).add(newShardingKey); // Add a new key
+    _msdsServer = new MockMetadataStoreDirectoryServer(MSDS_HOSTNAME, 
MSDS_PORT, MSDS_NAMESPACE,
+        rawRoutingData);
+    _msdsServer.startServer();
+
+    // Verify that RoutingDataManager does not have the key
+    MetadataStoreRoutingData routingData =
+        RoutingDataManager.getInstance().getMetadataStoreRoutingData();
+    try {
+      routingData.getMetadataStoreRealm(newShardingKey);
+      Assert.fail("Must throw NoSuchElementException!");
+    } catch (NoSuchElementException e) {
+      // Expected
+    }
+
+    // Create a new DedicatedZkClient
+    DedicatedZkClient dedicatedZkClient = new DedicatedZkClient(
+        new RealmAwareZkClient.RealmAwareZkConnectionConfig.Builder()
+            .setRoutingDataSourceType(RoutingDataReaderType.HTTP.name())
+            .setRoutingDataSourceEndpoint(
+                "http://"; + MSDS_HOSTNAME + ":" + MSDS_PORT + 
"/admin/v2/namespaces/"
+                    + MSDS_NAMESPACE)
+            .setZkRealmShardingKey(newShardingKey).build(), new 
RealmAwareZkClient.RealmAwareZkClientConfig());
+
+    Assert.assertEquals(zkRealm, 
RoutingDataManager.getInstance().getMetadataStoreRoutingData()
+        .getMetadataStoreRealm(newShardingKey));
+
+    /*
+     * Case 2:
+     * - RoutingDataManager has the key
+     * - MSDS does not have the key
+     */
+    _msdsServer.stopServer();
+    // Create an MSDS with the key and reset MSDS so it doesn't contain the key
+    String newShardingKey2 = "/sharding-key-10";
+    rawRoutingData.get(zkRealm).add(newShardingKey2);
+    _msdsServer = new MockMetadataStoreDirectoryServer(MSDS_HOSTNAME, 
MSDS_PORT, MSDS_NAMESPACE,
+        rawRoutingData);
+    _msdsServer.startServer();
+
+    // Make sure RoutingDataManager has the key
+    RoutingDataManager.getInstance().reset(true);
+    Assert.assertEquals(zkRealm, 
RoutingDataManager.getInstance().getMetadataStoreRoutingData()
+        .getMetadataStoreRealm(newShardingKey2));
+
+    // Reset MSDS so it doesn't contain the key
+    _msdsServer.stopServer();
+    _msdsServer = new MockMetadataStoreDirectoryServer(MSDS_HOSTNAME, 
MSDS_PORT, MSDS_NAMESPACE,
+        TestConstants.FAKE_ROUTING_DATA); // FAKE_ROUTING_DATA doesn't contain 
the key
+    _msdsServer.startServer();
+
+    dedicatedZkClient = new DedicatedZkClient(
+        new RealmAwareZkClient.RealmAwareZkConnectionConfig.Builder()
+            .setRoutingDataSourceType(RoutingDataReaderType.HTTP.name())
+            .setRoutingDataSourceEndpoint(
+                "http://"; + MSDS_HOSTNAME + ":" + MSDS_PORT + 
"/admin/v2/namespaces/"
+                    + MSDS_NAMESPACE)
+            .setZkRealmShardingKey(newShardingKey2).build(), new 
RealmAwareZkClient.RealmAwareZkClientConfig());
+
+    Assert.assertEquals(zkRealm, 
RoutingDataManager.getInstance().getMetadataStoreRoutingData()
+        .getMetadataStoreRealm(newShardingKey2));
+    // Also check that MSDS does not have the new sharding key through 
resetting RoutingDataManager
+    // and re-reading from MSDS
+    RoutingDataManager.getInstance().reset(true);
+    try {
+      RoutingDataManager.getInstance().getMetadataStoreRoutingData()
+          .getMetadataStoreRealm(newShardingKey2);
+      Assert.fail("NoSuchElementException expected!");
+    } catch (NoSuchElementException e) {
+      // Expected because MSDS does not contain the key
+    }
+
+    // Clean up dedicatedZkClient
+    dedicatedZkClient.close();
+    // Disable System property
+    
System.clearProperty(RoutingSystemPropertyKeys.UPDATE_ROUTING_DATA_ON_CACHE_MISS);
+    
System.clearProperty(RoutingSystemPropertyKeys.ROUTING_DATA_UPDATE_INTERVAL_MS);
+  }
+
+  /**
+   * This tests the routing data update feature only enabled when
+   * RoutingSystemPropertyKeys.UPDATE_ROUTING_DATA_ON_CACHE_MISS is set to 
true.
+   * Routing data source is ZK.
+   */
+  @Test(dependsOnMethods = "testUpdateRoutingDataOnCacheMissMSDS")
+  public void testUpdateRoutingDataOnCacheMissZK() throws IOException, 
InvalidRoutingDataException {
+    // Set up routing data in ZK with empty sharding key list
+    String zkRealm = "localhost:2127";
+    String newShardingKey = "/sharding-key-9";
+    String newShardingKey2 = "/sharding-key-10";
+    ZkClient zkClient =
+        new ZkClient.Builder().setZkServer(zkRealm).setZkSerializer(new 
ZNRecordSerializer())
+            .build();
+    zkClient.create(MetadataStoreRoutingConstants.ROUTING_DATA_PATH, null, 
CreateMode.PERSISTENT);
+    ZNRecord zkRealmRecord = new ZNRecord(zkRealm);
+    List<String> keyList =
+        new ArrayList<>(TestConstants.TEST_KEY_LIST_1); // Need a non-empty 
keyList
+    
zkRealmRecord.setListField(MetadataStoreRoutingConstants.ZNRECORD_LIST_FIELD_KEY,
 keyList);
+    zkClient.create(MetadataStoreRoutingConstants.ROUTING_DATA_PATH + "/" + 
zkRealm, zkRealmRecord,
+        CreateMode.PERSISTENT);
+
+    // Enable routing data update upon cache miss
+    
System.setProperty(RoutingSystemPropertyKeys.UPDATE_ROUTING_DATA_ON_CACHE_MISS, 
"true");
+    // Set the routing data update interval to 0 so there's no delay in testing
+    
System.setProperty(RoutingSystemPropertyKeys.ROUTING_DATA_UPDATE_INTERVAL_MS, 
"0");
+    RoutingDataManager.getInstance().parseRoutingDataUpdateInterval();
+
+    RoutingDataManager.getInstance().reset(true);
+    
RoutingDataManager.getInstance().getMetadataStoreRoutingData(RoutingDataReaderType.ZK,
 zkRealm);
+    /*
+     * Test is 2-tiered because cache update is 2-tiered
+     * Case 1:
+     * - RoutingDataManager does not have the key
+     * - ZK has the key
+     * This simulates a case where DedicatedZkClient must do a I/O based 
update (must read from ZK).
+     */
+    // Add the key to ZK
+    
zkRealmRecord.getListField(MetadataStoreRoutingConstants.ZNRECORD_LIST_FIELD_KEY)
+        .add(newShardingKey);
+    zkClient
+        .writeData(MetadataStoreRoutingConstants.ROUTING_DATA_PATH + "/" + 
zkRealm, zkRealmRecord);
+
+    // Verify that RoutingDataManager does not have the key
+    MetadataStoreRoutingData routingData = RoutingDataManager.getInstance()
+        .getMetadataStoreRoutingData(RoutingDataReaderType.ZK, zkRealm);
+    try {
+      routingData.getMetadataStoreRealm(newShardingKey);
+      Assert.fail("Must throw NoSuchElementException!");
+    } catch (NoSuchElementException e) {
+      // Expected
+    }
+
+    // Create a new DedicatedZkClient
+    DedicatedZkClient dedicatedZkClient = new DedicatedZkClient(
+        new RealmAwareZkClient.RealmAwareZkConnectionConfig.Builder()
+            .setRoutingDataSourceType(RoutingDataReaderType.ZK.name())
+            .setRoutingDataSourceEndpoint(zkRealm)
+            .setZkRealmShardingKey(newShardingKey).build(),
+        new RealmAwareZkClient.RealmAwareZkClientConfig());
+
+    Assert.assertEquals(zkRealm, RoutingDataManager.getInstance()
+        .getMetadataStoreRoutingData(RoutingDataReaderType.ZK, zkRealm)
+        .getMetadataStoreRealm(newShardingKey));
+
+    /*
+     * Case 2:
+     * - RoutingDataManager has the key
+     * - ZK does not have the key
+     */
+    // Add newShardingKey2 to ZK's routing data (in order to give 
RoutingDataManager the key)
+    
zkRealmRecord.getListField(MetadataStoreRoutingConstants.ZNRECORD_LIST_FIELD_KEY)
+        .add(newShardingKey2);
+    zkClient
+        .writeData(MetadataStoreRoutingConstants.ROUTING_DATA_PATH + "/" + 
zkRealm, zkRealmRecord);
+
+    // Update RoutingDataManager so it has the key
+    RoutingDataManager.getInstance().reset(true);
+    Assert.assertEquals(zkRealm, RoutingDataManager.getInstance()
+        .getMetadataStoreRoutingData(RoutingDataReaderType.ZK, zkRealm)
+        .getMetadataStoreRealm(newShardingKey2));
+
+    // Remove newShardingKey2 from ZK
+    
zkRealmRecord.getListField(MetadataStoreRoutingConstants.ZNRECORD_LIST_FIELD_KEY)
+        .remove(newShardingKey2);
+    zkClient
+        .writeData(MetadataStoreRoutingConstants.ROUTING_DATA_PATH + "/" + 
zkRealm, zkRealmRecord);
+
+    dedicatedZkClient = new DedicatedZkClient(
+        new RealmAwareZkClient.RealmAwareZkConnectionConfig.Builder()
+            .setRoutingDataSourceType(RoutingDataReaderType.ZK.name())
+            .setRoutingDataSourceEndpoint(zkRealm)
+            .setZkRealmShardingKey(newShardingKey2).build(),
+        new RealmAwareZkClient.RealmAwareZkClientConfig());
+
+    Assert.assertEquals(zkRealm, RoutingDataManager.getInstance()
+        .getMetadataStoreRoutingData(RoutingDataReaderType.ZK, zkRealm)
+        .getMetadataStoreRealm(newShardingKey2));
+    // Also check that ZK does not have the new sharding key through resetting 
RoutingDataManager
+    // and re-reading from ZK
+    RoutingDataManager.getInstance().reset(true);
+    try {
+      RoutingDataManager.getInstance()
+          .getMetadataStoreRoutingData(RoutingDataReaderType.ZK, zkRealm)
+          .getMetadataStoreRealm(newShardingKey2);
+      Assert.fail("NoSuchElementException expected!");
+    } catch (NoSuchElementException e) {
+      // Expected because ZK does not contain the key
+    }
+
+    // Clean up dedicatedZkClient
+    dedicatedZkClient.close();
+    // Clean up ZK writes and ZkClient
+    
zkClient.deleteRecursively(MetadataStoreRoutingConstants.ROUTING_DATA_PATH);
+    zkClient.close();
+    // Disable System property
+    
System.clearProperty(RoutingSystemPropertyKeys.UPDATE_ROUTING_DATA_ON_CACHE_MISS);
+    
System.clearProperty(RoutingSystemPropertyKeys.ROUTING_DATA_UPDATE_INTERVAL_MS);
+  }
+
+  /**
+   * Test that throttle based on last reset timestamp works correctly. Here, 
we use ZK as the
+   * routing data source.
+   * Test scenario: set the throttle value to a high value and check that 
routing data update from
+   * the routing data source does NOT happen (because it would be throttled).
+   */
+  @Test(dependsOnMethods = "testUpdateRoutingDataOnCacheMissZK")
+  public void testRoutingDataUpdateThrottle() throws 
InvalidRoutingDataException {
+    // Call reset to set the last reset() timestamp in RoutingDataManager
+    RoutingDataManager.getInstance().reset(true);
+
+    // Set up routing data in ZK with empty sharding key list
+    String zkRealm = "localhost:2127";
+    String newShardingKey = "/throttle";
+    ZkClient zkClient =
+        new ZkClient.Builder().setZkServer(zkRealm).setZkSerializer(new 
ZNRecordSerializer())
+            .build();
+    zkClient.create(MetadataStoreRoutingConstants.ROUTING_DATA_PATH, null, 
CreateMode.PERSISTENT);
+    ZNRecord zkRealmRecord = new ZNRecord(zkRealm);
+    
zkRealmRecord.setListField(MetadataStoreRoutingConstants.ZNRECORD_LIST_FIELD_KEY,
+        new ArrayList<>(TestConstants.TEST_KEY_LIST_1));
+    zkClient.create(MetadataStoreRoutingConstants.ROUTING_DATA_PATH + "/" + 
zkRealm, zkRealmRecord,
+        CreateMode.PERSISTENT);
+
+    // Enable routing data update upon cache miss
+    
System.setProperty(RoutingSystemPropertyKeys.UPDATE_ROUTING_DATA_ON_CACHE_MISS, 
"true");
+    // Set the throttle value to a very long value
+    
System.setProperty(RoutingSystemPropertyKeys.ROUTING_DATA_UPDATE_INTERVAL_MS,
+        String.valueOf(Integer.MAX_VALUE));
+    RoutingDataManager.getInstance().parseRoutingDataUpdateInterval();
+
+    // Create a new DedicatedZkClient, whose _routingDataUpdateInterval should 
be MAX_VALUE
+    DedicatedZkClient dedicatedZkClient = new DedicatedZkClient(
+        new RealmAwareZkClient.RealmAwareZkConnectionConfig.Builder()
+            .setRoutingDataSourceType(RoutingDataReaderType.ZK.name())
+            .setRoutingDataSourceEndpoint(zkRealm)
+            
.setZkRealmShardingKey(TestConstants.TEST_KEY_LIST_1.get(0)).build(),
+        new RealmAwareZkClient.RealmAwareZkClientConfig());
+
+    // Add newShardingKey to ZK's routing data
+    
zkRealmRecord.getListField(MetadataStoreRoutingConstants.ZNRECORD_LIST_FIELD_KEY)
+        .add(newShardingKey);
+    zkClient
+        .writeData(MetadataStoreRoutingConstants.ROUTING_DATA_PATH + "/" + 
zkRealm, zkRealmRecord);
+
+    try {
+      dedicatedZkClient = new DedicatedZkClient(
+        new RealmAwareZkClient.RealmAwareZkConnectionConfig.Builder()
+            .setRoutingDataSourceType(RoutingDataReaderType.ZK.name())
+            .setRoutingDataSourceEndpoint(zkRealm)
+            .setZkRealmShardingKey(newShardingKey).build(),
+        new RealmAwareZkClient.RealmAwareZkClientConfig());
+      Assert.fail("NoSuchElementException expected!");
+    } catch (NoSuchElementException e) {
+      // Expected because it should not read from the routing data source 
because of the throttle
+    }
+
+    // Clean up
+    
zkClient.deleteRecursively(MetadataStoreRoutingConstants.ROUTING_DATA_PATH);
+    zkClient.close();
+    
System.clearProperty(RoutingSystemPropertyKeys.UPDATE_ROUTING_DATA_ON_CACHE_MISS);
+    
System.clearProperty(RoutingSystemPropertyKeys.ROUTING_DATA_UPDATE_INTERVAL_MS);
+  }
 }
diff --git 
a/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/TestFederatedZkClient.java
 
b/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/TestFederatedZkClient.java
index ee45874b7..30335efb1 100644
--- 
a/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/TestFederatedZkClient.java
+++ 
b/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/TestFederatedZkClient.java
@@ -60,7 +60,6 @@ public class TestFederatedZkClient extends 
RealmAwareZkClientTestBase {
   @BeforeClass
   public void beforeClass() throws IOException, InvalidRoutingDataException {
     System.out.println("Starting " + 
TestFederatedZkClient.class.getSimpleName());
-    super.beforeClass();
 
     // Feed the raw routing data into TrieRoutingData to construct an 
in-memory representation
     // of routing information.
@@ -71,7 +70,6 @@ public class TestFederatedZkClient extends 
RealmAwareZkClientTestBase {
 
   @AfterClass
   public void afterClass() {
-    super.afterClass();
     // Close it as it is created in before class.
     _realmAwareZkClient.close();
     System.out.println("Ending " + 
TestFederatedZkClient.class.getSimpleName());
@@ -344,6 +342,7 @@ public class TestFederatedZkClient extends 
RealmAwareZkClientTestBase {
     
System.setProperty(RoutingSystemPropertyKeys.UPDATE_ROUTING_DATA_ON_CACHE_MISS, 
"true");
     // Set the routing data update interval to 0 so there's no delay in testing
     
System.setProperty(RoutingSystemPropertyKeys.ROUTING_DATA_UPDATE_INTERVAL_MS, 
"0");
+    RoutingDataManager.getInstance().parseRoutingDataUpdateInterval();
 
     RoutingDataManager.getInstance().getMetadataStoreRoutingData();
     _msdsServer.stopServer();
@@ -406,7 +405,7 @@ public class TestFederatedZkClient extends 
RealmAwareZkClientTestBase {
     _msdsServer.startServer();
 
     // Make sure RoutingDataManager has the key
-    RoutingDataManager.getInstance().reset();
+    RoutingDataManager.getInstance().reset(true);
     Assert.assertEquals(zkRealm, 
RoutingDataManager.getInstance().getMetadataStoreRoutingData()
         .getMetadataStoreRealm(newShardingKey2));
 
@@ -426,7 +425,7 @@ public class TestFederatedZkClient extends 
RealmAwareZkClientTestBase {
         .getMetadataStoreRealm(newShardingKey2));
     // Also check that MSDS does not have the new sharding key through 
resetting RoutingDataManager
     // and re-reading from MSDS
-    RoutingDataManager.getInstance().reset();
+    RoutingDataManager.getInstance().reset(true);
     try {
       RoutingDataManager.getInstance().getMetadataStoreRoutingData()
           .getMetadataStoreRealm(newShardingKey2);
@@ -437,8 +436,6 @@ public class TestFederatedZkClient extends 
RealmAwareZkClientTestBase {
 
     // Clean up federatedZkClient
     federatedZkClient.close();
-    // Shut down MSDS
-    _msdsServer.stopServer();
     // Disable System property
     
System.clearProperty(RoutingSystemPropertyKeys.UPDATE_ROUTING_DATA_ON_CACHE_MISS);
     
System.clearProperty(RoutingSystemPropertyKeys.ROUTING_DATA_UPDATE_INTERVAL_MS);
@@ -470,8 +467,9 @@ public class TestFederatedZkClient extends 
RealmAwareZkClientTestBase {
     
System.setProperty(RoutingSystemPropertyKeys.UPDATE_ROUTING_DATA_ON_CACHE_MISS, 
"true");
     // Set the routing data update interval to 0 so there's no delay in testing
     
System.setProperty(RoutingSystemPropertyKeys.ROUTING_DATA_UPDATE_INTERVAL_MS, 
"0");
+    RoutingDataManager.getInstance().parseRoutingDataUpdateInterval();
 
-    RoutingDataManager.getInstance().reset();
+    RoutingDataManager.getInstance().reset(true);
     
RoutingDataManager.getInstance().getMetadataStoreRoutingData(RoutingDataReaderType.ZK,
 zkRealm);
     /*
      * Test is 2-tiered because cache update is 2-tiered
@@ -526,7 +524,7 @@ public class TestFederatedZkClient extends 
RealmAwareZkClientTestBase {
         .writeData(MetadataStoreRoutingConstants.ROUTING_DATA_PATH + "/" + 
zkRealm, zkRealmRecord);
 
     // Update RoutingDataManager so it has the key
-    RoutingDataManager.getInstance().reset();
+    RoutingDataManager.getInstance().reset(true);
     Assert.assertEquals(zkRealm, RoutingDataManager.getInstance()
         .getMetadataStoreRoutingData(RoutingDataReaderType.ZK, zkRealm)
         .getMetadataStoreRealm(newShardingKey2));
@@ -548,7 +546,7 @@ public class TestFederatedZkClient extends 
RealmAwareZkClientTestBase {
         .getMetadataStoreRealm(newShardingKey2));
     // Also check that ZK does not have the new sharding key through resetting 
RoutingDataManager
     // and re-reading from ZK
-    RoutingDataManager.getInstance().reset();
+    RoutingDataManager.getInstance().reset(true);
     try {
       RoutingDataManager.getInstance()
           .getMetadataStoreRoutingData(RoutingDataReaderType.ZK, zkRealm)
@@ -577,7 +575,7 @@ public class TestFederatedZkClient extends 
RealmAwareZkClientTestBase {
   @Test(dependsOnMethods = "testUpdateRoutingDataOnCacheMissZK")
   public void testRoutingDataUpdateThrottle() throws 
InvalidRoutingDataException {
     // Call reset to set the last reset() timestamp in RoutingDataManager
-    RoutingDataManager.getInstance().reset();
+    RoutingDataManager.getInstance().reset(true);
 
     // Set up routing data in ZK with empty sharding key list
     String zkRealm = "localhost:2127";
@@ -597,6 +595,7 @@ public class TestFederatedZkClient extends 
RealmAwareZkClientTestBase {
     // Set the throttle value to a very long value
     
System.setProperty(RoutingSystemPropertyKeys.ROUTING_DATA_UPDATE_INTERVAL_MS,
         String.valueOf(Integer.MAX_VALUE));
+    RoutingDataManager.getInstance().parseRoutingDataUpdateInterval();
 
     // Create a new FederatedZkClient, whose _routingDataUpdateInterval should 
be MAX_VALUE
     FederatedZkClient federatedZkClient = new FederatedZkClient(
diff --git 
a/zookeeper-api/src/test/java/org/apache/helix/zookeeper/util/TestRoutingDataManager.java
 
b/zookeeper-api/src/test/java/org/apache/helix/zookeeper/util/TestRoutingDataManager.java
index 19ced01c5..fbdd76610 100644
--- 
a/zookeeper-api/src/test/java/org/apache/helix/zookeeper/util/TestRoutingDataManager.java
+++ 
b/zookeeper-api/src/test/java/org/apache/helix/zookeeper/util/TestRoutingDataManager.java
@@ -61,7 +61,7 @@ public class TestRoutingDataManager extends ZkTestBase {
     System.setProperty(MetadataStoreRoutingConstants.MSDS_SERVER_ENDPOINT_KEY, 
MSDS_ENDPOINT);
 
     // Reset RoutingDataManager
-    RoutingDataManager.getInstance().reset();
+    RoutingDataManager.getInstance().reset(true);
   }
 
   @AfterClass


Reply via email to