You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ab...@apache.org on 2019/06/11 10:14:02 UTC

[lucene-solr] branch master updated: Improve the test by actually checking that the version of Aliases is more recent, instead of simply waiting.

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

ab pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git


The following commit(s) were added to refs/heads/master by this push:
     new 6527e74  Improve the test by actually checking that the version of Aliases is more recent, instead of simply waiting.
6527e74 is described below

commit 6527e74ed8742ef2acbc1bcfaf1ef1a82ae0f4f9
Author: Andrzej Bialecki <ab...@apache.org>
AuthorDate: Tue Jun 11 12:13:22 2019 +0200

    Improve the test by actually checking that the version of Aliases is
    more recent, instead of simply waiting.
---
 .../apache/solr/cloud/AliasIntegrationTest.java    | 80 +++++++++++++++-------
 .../apache/solr/common/cloud/ZkStateReader.java    |  1 +
 2 files changed, 55 insertions(+), 26 deletions(-)

diff --git a/solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java b/solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java
index a64ed7a..c0d63ba 100644
--- a/solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java
@@ -19,6 +19,7 @@ package org.apache.solr.cloud;
 import java.io.IOException;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 import java.util.function.UnaryOperator;
 
@@ -51,7 +52,9 @@ import org.apache.solr.common.cloud.ZkStateReader;
 import org.apache.solr.common.params.CollectionAdminParams;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.util.TimeSource;
 import org.apache.solr.common.util.Utils;
+import org.apache.solr.util.TimeOut;
 import org.apache.zookeeper.KeeperException;
 import org.junit.After;
 import org.junit.Before;
@@ -275,7 +278,14 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
   @Test
   public void testClusterStateProviderAPI() throws Exception {
     final String aliasName = getSaferTestName();
-    ZkStateReader zkStateReader = createColectionsAndAlias(aliasName);
+    ZkStateReader zkStateReader = cluster.getSolrClient().getZkStateReader();
+    Aliases aliases = zkStateReader.getAliases();
+    int lastVersion = aliases.getZNodeVersion();
+
+    createColectionsAndAlias(aliasName);
+
+    lastVersion = waitForAliasesUpdate(lastVersion, zkStateReader);
+
     CollectionAdminRequest.SetAliasProperty setAliasProperty = CollectionAdminRequest.setAliasProperty(aliasName);
     setAliasProperty.addProperty("foo","baz");
     setAliasProperty.addProperty("bar","bam");
@@ -283,7 +293,7 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
     checkFooAndBarMeta(aliasName, zkStateReader);
     SolrCloudManager cloudManager = cluster.getJettySolrRunner(0).getCoreContainer().getZkController().getSolrCloudManager();
     // make sure we have the latest version in cache
-    zkStateReader.aliasesManager.update();
+    lastVersion = waitForAliasesUpdate(lastVersion, zkStateReader);
     ClusterStateProvider stateProvider = cloudManager.getClusterStateProvider();
     List<String> collections = stateProvider.resolveAlias(aliasName);
     assertEquals(collections.toString(), 2, collections.size());
@@ -300,7 +310,7 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
     setAliasProperty.addProperty(CollectionAdminParams.ROUTER_PREFIX + "foo","baz");
     setAliasProperty.process(cluster.getSolrClient());
     // refresh
-    zkStateReader.aliasesManager.update();
+    lastVersion = waitForAliasesUpdate(lastVersion, zkStateReader);
     stateProvider = cloudManager.getClusterStateProvider();
     assertTrue("should be a routed alias", stateProvider.isRoutedAlias(aliasName));
 
@@ -312,6 +322,24 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
     }
   }
 
+  private int waitForAliasesUpdate(int lastVersion, ZkStateReader zkStateReader) throws Exception {
+    TimeOut timeOut = new TimeOut(30, TimeUnit.SECONDS, TimeSource.NANO_TIME);
+    while (!timeOut.hasTimedOut()) {
+      zkStateReader.aliasesManager.update();
+      Aliases aliases = zkStateReader.getAliases();
+      if (aliases.getZNodeVersion() > lastVersion) {
+        return aliases.getZNodeVersion();
+      } else if (aliases.getZNodeVersion() < lastVersion) {
+        fail("unexpected znode version, expected  greater than " + lastVersion + " but was " + aliases.getZNodeVersion());
+      }
+      timeOut.sleep(1000);
+    }
+    if (timeOut.hasTimedOut()) {
+      fail("timed out waiting for aliases to update");
+    }
+    return -1;
+  }
+
   private void checkFooAndBarMeta(String aliasName, ZkStateReader zkStateReader) throws Exception {
     zkStateReader.aliasesManager.update(); // ensure our view is up to date
     Map<String, String> meta = zkStateReader.getAliases().getCollectionAliasProperties(aliasName);
@@ -397,11 +425,15 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
     QueryResponse res = cluster.getSolrClient().query("collection_old", new SolrQuery("*:*"));
     assertEquals(3, res.getResults().getNumFound());
 
+    ZkStateReader zkStateReader = cluster.getSolrClient().getZkStateReader();
+    int lastVersion = zkStateReader.aliasesManager.getAliases().getZNodeVersion();
     // Let's insure we have a "handle" to the old collection
     CollectionAdminRequest.createAlias("collection_old_reserve", "collection_old").process(cluster.getSolrClient());
+    lastVersion = waitForAliasesUpdate(lastVersion, zkStateReader);
 
     // This is the critical bit. The alias uses the _old collection name.
     CollectionAdminRequest.createAlias("collection_old", "collection_new").process(cluster.getSolrClient());
+    lastVersion = waitForAliasesUpdate(lastVersion, zkStateReader);
 
     // aliases: collection_old->collection_new, collection_old_reserve -> collection_old -> collection_new
     // collections: collection_new and collection_old
@@ -433,7 +465,9 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
 
     // Clean up
     CollectionAdminRequest.deleteAlias("collection_old_reserve").processAndWait(cluster.getSolrClient(), 60);
+    lastVersion = waitForAliasesUpdate(lastVersion, zkStateReader);
     CollectionAdminRequest.deleteAlias("collection_old").processAndWait(cluster.getSolrClient(), 60);
+    lastVersion = waitForAliasesUpdate(lastVersion, zkStateReader);
     CollectionAdminRequest.deleteCollection("collection_new").processAndWait(cluster.getSolrClient(), 60);
     CollectionAdminRequest.deleteCollection("collection_old").processAndWait(cluster.getSolrClient(), 60);
     // collection_old already deleted as well as collection_old_reserve
@@ -471,8 +505,12 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
         .add("id", "11", "a_t", "humpty dumpy sat on a low wall")
         .commit(cluster.getSolrClient(), "collection_two");
 
+    ZkStateReader zkStateReader = cluster.getSolrClient().getZkStateReader();
+    int lastVersion = zkStateReader.aliasesManager.getAliases().getZNodeVersion();
+
     // Create an alias pointing to both
     CollectionAdminRequest.createAlias("collection_alias_pair", "collection_one,collection_two").process(cluster.getSolrClient());
+    lastVersion = waitForAliasesUpdate(lastVersion, zkStateReader);
 
     QueryResponse res = cluster.getSolrClient().query("collection_alias_pair", new SolrQuery("*:*"));
     assertEquals(3, res.getResults().getNumFound());
@@ -484,6 +522,7 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
 
     // Now redefine the alias to only point to colletion two
     CollectionAdminRequest.createAlias("collection_alias_pair", "collection_two").process(cluster.getSolrClient());
+    lastVersion = waitForAliasesUpdate(lastVersion, zkStateReader);
 
     //Delete collection_one.
     delResp = CollectionAdminRequest.deleteCollection("collection_one").processAndWait(cluster.getSolrClient(), 60);
@@ -507,6 +546,7 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
     CollectionAdminRequest.deleteAlias("collection_alias_pair").processAndWait(cluster.getSolrClient(), 60);
     CollectionAdminRequest.deleteCollection("collection_two").processAndWait(cluster.getSolrClient(), 60);
     // collection_one already deleted
+    lastVersion = waitForAliasesUpdate(lastVersion, zkStateReader);
 
     assertNull("collection_alias_pair should be gone",
         cluster.getSolrClient().getZkStateReader().getAliases().getCollectionAliasMap().get("collection_alias_pair"));
@@ -544,12 +584,15 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
 
     ///////////////
     // make sure there's only one level of alias
+    ZkStateReader zkStateReader = cluster.getSolrClient().getZkStateReader();
+    int lastVersion = zkStateReader.aliasesManager.getAliases().getZNodeVersion();
+
     CollectionAdminRequest.deleteAlias("collection1").process(cluster.getSolrClient());
     CollectionAdminRequest.createAlias("testalias1", "collection1").process(cluster.getSolrClient());
 
     // verify proper resolution on the server-side
-    ZkStateReader zkStateReader = cluster.getSolrClient().getZkStateReader();
-    zkStateReader.aliasesManager.update();
+    lastVersion = waitForAliasesUpdate(lastVersion, zkStateReader);
+
     Aliases aliases = zkStateReader.getAliases();
     List<String> collections = aliases.resolveAliases("testalias1");
     assertEquals(collections.toString(), 1, collections.size());
@@ -569,27 +612,29 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
     // test alias pointing to two collections.  collection2 first because it's not on every node
     CollectionAdminRequest.createAlias("testalias2", "collection2,collection1").process(cluster.getSolrClient());
 
-    Thread.sleep(100);
+    lastVersion = waitForAliasesUpdate(lastVersion, zkStateReader);
     
     searchSeveralWays("testalias2", new SolrQuery("*:*"), 5);
 
     ///////////////
     // update alias
     CollectionAdminRequest.createAlias("testalias2", "collection2").process(cluster.getSolrClient());
-    sleepToAllowZkPropagation();
+    lastVersion = waitForAliasesUpdate(lastVersion, zkStateReader);
 
     searchSeveralWays("testalias2", new SolrQuery("*:*"), 2);
 
     ///////////////
     // alias pointing to alias.  One level of indirection is supported; more than that is not (may or may not work)
-    // TODO dubious; remove?
     CollectionAdminRequest.createAlias("testalias3", "testalias2").process(cluster.getSolrClient());
+    lastVersion = waitForAliasesUpdate(lastVersion, zkStateReader);
     searchSeveralWays("testalias3", new SolrQuery("*:*"), 2);
 
     ///////////////
     // Test 2 aliases pointing to the same collection
     CollectionAdminRequest.createAlias("testalias4", "collection2").process(cluster.getSolrClient());
+    lastVersion = waitForAliasesUpdate(lastVersion, zkStateReader);
     CollectionAdminRequest.createAlias("testalias5", "collection2").process(cluster.getSolrClient());
+    lastVersion = waitForAliasesUpdate(lastVersion, zkStateReader);
 
     // add one document to testalias4, thus to collection2
     new UpdateRequest()
@@ -622,8 +667,8 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
     ///////////////
     for (int i = 1; i <= 6 ; i++) {
       CollectionAdminRequest.deleteAlias("testalias" + i).process(cluster.getSolrClient());
+      lastVersion = waitForAliasesUpdate(lastVersion, zkStateReader);
     }
-    sleepToAllowZkPropagation();
 
     SolrException e = expectThrows(SolrException.class, () -> {
       SolrQuery q = new SolrQuery("*:*");
@@ -633,23 +678,6 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
     assertTrue("Unexpected exception message: " + e.getMessage(), e.getMessage().contains("Collection not found: testalias1"));
   }
 
-  /**
-   * Sleep a bit to allow Zookeeper state propagation.
-   *
-   * Solr's view of the cluster is eventually consistent. *Eventually* all nodes and CloudSolrClients will be aware of
-   * alias changes, but not immediately. If a newly created alias is queried, things should work right away since Solr
-   * will attempt to see if it needs to get the latest aliases when it can't otherwise resolve the name.  However
-   * modifications to an alias will take some time.
-   */
-  private void sleepToAllowZkPropagation() {
-    try {
-      Thread.sleep(100);
-    } catch (InterruptedException e) {
-      Thread.currentThread().interrupt();
-      throw new RuntimeException(e);
-    }
-  }
-
   private void searchSeveralWays(String collectionList, SolrParams solrQuery, int expectedNumFound) throws IOException, SolrServerException {
     searchSeveralWays(collectionList, solrQuery, res -> assertEquals(expectedNumFound, res.getResults().getNumFound()));
   }
diff --git a/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java b/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java
index cf914e4..f00cdff 100644
--- a/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java
+++ b/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java
@@ -1950,6 +1950,7 @@ public class ZkStateReader implements SolrCloseable {
      * Update the internal aliases reference with a new one, provided that its ZK version has increased.
      *
      * @param newAliases the potentially newer version of Aliases
+     * @return true if aliases have been updated to a new version, false otherwise
      */
     private boolean setIfNewer(Aliases newAliases) {
       assert newAliases.getZNodeVersion() >= 0;