patsonluk commented on code in PR #909:
URL: https://github.com/apache/solr/pull/909#discussion_r911543471


##########
solr/core/src/test/org/apache/solr/cloud/overseer/ZkStateReaderTest.java:
##########
@@ -196,4 +209,251 @@ public void testWatchedCollectionCreation() throws 
Exception {
       server.shutdown();
     }
   }
+
+  public void testForciblyRefreshAllClusterState() throws Exception {
+    Path zkDir = createTempDir("testForciblyRefreshAllClusterState");
+
+    ZkTestServer server = new ZkTestServer(zkDir);
+
+    SolrZkClient zkClient = null;
+    ZkStateReader reader = null;
+
+    try {
+      server.run();
+
+      zkClient = new SolrZkClient(server.getZkAddress(), 
OverseerTest.DEFAULT_CONNECTION_TIMEOUT);
+      ZkController.createClusterZkNodes(zkClient);
+
+      reader = new ZkStateReader(zkClient);
+      reader.createClusterStateWatchersAndUpdate();
+      reader.registerCore("c1"); // watching c1, so it should get non lazy 
reference
+      zkClient.makePath(ZkStateReader.COLLECTIONS_ZKNODE + "/c1", true);
+
+      reader.forciblyRefreshAllClusterStateSlow();
+      // Initially there should be no c1 collection.
+      assertNull(reader.getClusterState().getCollectionRef("c1"));
+
+      ZkStateWriter writer = new ZkStateWriter(reader, new Stats());
+
+      // create new collection
+      DocCollection state =
+          new DocCollection(
+              "c1",
+              new HashMap<>(),
+              Map.of(ZkStateReader.CONFIGNAME_PROP, 
ConfigSetsHandler.DEFAULT_CONFIGSET_NAME),
+              DocRouter.DEFAULT,
+              0);
+      ZkWriteCommand wc = new ZkWriteCommand("c1", state);
+      writer.enqueueUpdate(reader.getClusterState(), 
Collections.singletonList(wc), null);
+      writer.writePendingUpdates();
+
+      assertTrue(zkClient.exists(ZkStateReader.COLLECTIONS_ZKNODE + 
"/c1/state.json", true));
+
+      reader.forciblyRefreshAllClusterStateSlow();
+      ClusterState.CollectionRef ref = 
reader.getClusterState().getCollectionRef("c1");
+      assertNotNull(ref);
+      assertFalse(ref.isLazilyLoaded());
+      assertEquals(0, ref.get().getZNodeVersion());
+
+      // update the collection
+      state =
+          new DocCollection(
+              "c1",
+              new HashMap<>(),
+              Map.of(ZkStateReader.CONFIGNAME_PROP, 
ConfigSetsHandler.DEFAULT_CONFIGSET_NAME),
+              DocRouter.DEFAULT,
+              ref.get().getZNodeVersion());
+      wc = new ZkWriteCommand("c1", state);
+      writer.enqueueUpdate(reader.getClusterState(), 
Collections.singletonList(wc), null);
+      writer.writePendingUpdates();
+
+      reader.forciblyRefreshAllClusterStateSlow();
+      ref = reader.getClusterState().getCollectionRef("c1");
+      assertNotNull(ref);
+      assertFalse(ref.isLazilyLoaded());
+      assertEquals(1, ref.get().getZNodeVersion());
+
+      // delete the collection c1, add a collection c2 that is NOT watched
+      ZkWriteCommand wc1 = new ZkWriteCommand("c1", null);
+
+      zkClient.makePath(ZkStateReader.COLLECTIONS_ZKNODE + "/c2", true);
+      state =
+          new DocCollection(
+              "c2",
+              new HashMap<>(),
+              Map.of(ZkStateReader.CONFIGNAME_PROP, 
ConfigSetsHandler.DEFAULT_CONFIGSET_NAME),
+              DocRouter.DEFAULT,
+              0);
+      ZkWriteCommand wc2 = new ZkWriteCommand("c2", state);
+
+      writer.enqueueUpdate(reader.getClusterState(), Arrays.asList(wc1, wc2), 
null);
+      writer.writePendingUpdates();
+
+      reader.forciblyRefreshAllClusterStateSlow();
+      ref = reader.getClusterState().getCollectionRef("c1");
+      assertNull(ref);
+
+      ref = reader.getClusterState().getCollectionRef("c2");
+      assertNotNull(ref);
+      assert (ref.isLazilyLoaded()); // c2 should be lazily loaded as it's not 
watched
+      assertEquals(0, ref.get().getZNodeVersion());
+    } finally {
+      IOUtils.close(reader, zkClient);
+      server.shutdown();
+    }
+  }
+
+  public void testGetCurrentCollections() throws Exception {
+    Path zkDir = createTempDir("testGetCurrentCollections");
+
+    ZkTestServer server = new ZkTestServer(zkDir);
+
+    SolrZkClient zkClient = null;
+    ZkStateReader reader = null;
+
+    try {
+      server.run();
+
+      zkClient = new SolrZkClient(server.getZkAddress(), 
OverseerTest.DEFAULT_CONNECTION_TIMEOUT);
+      ZkController.createClusterZkNodes(zkClient);
+
+      reader = new ZkStateReader(zkClient);
+      reader.createClusterStateWatchersAndUpdate();
+      reader.registerCore("c1"); // listen to c1. not yet exist
+      zkClient.makePath(ZkStateReader.COLLECTIONS_ZKNODE + "/c1", true);
+      reader.forceUpdateCollection("c1");
+      Set<String> currentCollections = reader.getCurrentCollections();
+      assertEquals(0, currentCollections.size()); // no active collections yet
+
+      // now create both c1 (watched) and c2 (not watched)
+      DocCollection state1 =
+          new DocCollection(
+              "c1",
+              new HashMap<>(),
+              Map.of(ZkStateReader.CONFIGNAME_PROP, 
ConfigSetsHandler.DEFAULT_CONFIGSET_NAME),
+              DocRouter.DEFAULT,
+              0);
+      ZkWriteCommand wc1 = new ZkWriteCommand("c1", state1);
+      DocCollection state2 =
+          new DocCollection(
+              "c2",
+              new HashMap<>(),
+              Map.of(ZkStateReader.CONFIGNAME_PROP, 
ConfigSetsHandler.DEFAULT_CONFIGSET_NAME),
+              DocRouter.DEFAULT,
+              0);
+
+      // do not listen to c2
+      zkClient.makePath(ZkStateReader.COLLECTIONS_ZKNODE + "/c2", true);
+      ZkWriteCommand wc2 = new ZkWriteCommand("c2", state2);
+
+      ZkStateWriter writer = new ZkStateWriter(reader, new Stats());
+      writer.enqueueUpdate(reader.getClusterState(), Arrays.asList(wc1, wc2), 
null);
+      writer.writePendingUpdates();
+
+      reader.forceUpdateCollection("c1");
+      reader.forceUpdateCollection("c2");
+      currentCollections =
+          reader.getCurrentCollections(); // should detect both collections 
(c1 watched, c2 lazy
+      // loaded)
+      assertEquals(2, currentCollections.size());
+    } finally {
+      IOUtils.close(reader, zkClient);
+      server.shutdown();
+    }
+  }
+
+  public void testWatchRaceCondition() throws Exception {
+    final int RUN_COUNT = 10000;
+    Path zkDir = createTempDir("testWatchRaceCondition");
+
+    ZkTestServer server = new ZkTestServer(zkDir);
+
+    SolrZkClient zkClient = null;
+    ZkStateReader reader = null;
+    ExecutorService executorService =
+        ExecutorUtil.newMDCAwareSingleThreadExecutor(
+            new SolrNamedThreadFactory("zkStateReaderTest"));
+
+    try {
+      server.run();
+
+      zkClient = new SolrZkClient(server.getZkAddress(), 
OverseerTest.DEFAULT_CONNECTION_TIMEOUT);
+      ZkController.createClusterZkNodes(zkClient);
+
+      reader = new ZkStateReader(zkClient);
+      final ZkStateReader readerRef = reader;
+      reader.createClusterStateWatchersAndUpdate();
+      zkClient.makePath(ZkStateReader.COLLECTIONS_ZKNODE + "/c1", true);
+
+      // start another thread to constantly updating the state
+      final AtomicBoolean stopMutatingThread = new AtomicBoolean(false);
+      final ZkStateWriter writer = new ZkStateWriter(reader, new Stats());
+      final AtomicInteger updateCounts = new AtomicInteger(0);

Review Comment:
   yep good catch!



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscr...@solr.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscr...@solr.apache.org
For additional commands, e-mail: issues-h...@solr.apache.org

Reply via email to