You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by md...@apache.org on 2022/03/28 16:52:25 UTC
[solr] branch main updated: SOLR-16114 Remove SolrZookeeper (#759)
This is an automated email from the ASF dual-hosted git repository.
mdrob pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/main by this push:
new 98aa52b SOLR-16114 Remove SolrZookeeper (#759)
98aa52b is described below
commit 98aa52b9b2a258bd0971997798aa2949e7511af7
Author: Mike Drob <md...@apache.org>
AuthorDate: Mon Mar 28 11:52:20 2022 -0500
SOLR-16114 Remove SolrZookeeper (#759)
---
solr/CHANGES.txt | 2 +
solr/core/build.gradle | 1 +
.../java/org/apache/solr/cloud/LeaderElector.java | 4 +-
.../src/java/org/apache/solr/cloud/Overseer.java | 7 +-
.../java/org/apache/solr/cloud/ZkController.java | 19 ++--
.../java/org/apache/solr/core/CoreContainer.java | 2 +-
.../apache/solr/cloud/ConnectionManagerTest.java | 12 ++-
.../apache/solr/cloud/DistributedQueueTest.java | 4 +-
.../solr/cloud/LeaderElectionIntegrationTest.java | 5 +-
.../org/apache/solr/cloud/LeaderElectionTest.java | 44 ++++----
.../OutOfBoxZkACLAndCredentialsProvidersTest.java | 2 +-
...OverriddenZkACLAndCredentialsProvidersTest.java | 2 +-
.../solr/cloud/TestLeaderElectionZkExpiry.java | 3 +-
.../org/apache/solr/cloud/ZkSolrClientTest.java | 3 +-
solr/licenses/zookeeper-3.7.0-tests.jar.sha1 | 1 +
.../security/hadoop/SaslZkACLProviderTest.java | 3 +-
.../solr/common/cloud/ConnectionManager.java | 29 +++---
.../common/cloud/DefaultConnectionStrategy.java | 5 +-
.../org/apache/solr/common/cloud/SolrZkClient.java | 72 +++----------
.../apache/solr/common/cloud/SolrZooKeeper.java | 113 ---------------------
.../common/cloud/ZkClientConnectionStrategy.java | 38 ++++++-
.../apache/solr/common/cloud/ZkStateReader.java | 2 +-
solr/test-framework/build.gradle | 10 +-
.../src/java/org/apache/solr/SolrTestCaseJ4.java | 2 +
...ParamsZkACLAndCredentialsProvidersTestBase.java | 11 +-
.../java/org/apache/solr/cloud/ChaosMonkey.java | 22 +++-
.../apache/solr/cloud/MiniSolrCloudCluster.java | 10 +-
.../apache/solr/cloud/TestConnectionStrategy.java | 35 +++++++
.../java/org/apache/solr/cloud/ZkTestServer.java | 76 ++------------
.../solr/cloud/MiniSolrCloudClusterTest.java | 7 +-
30 files changed, 205 insertions(+), 341 deletions(-)
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 6a1a1e5..e5bca4a 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -63,6 +63,8 @@ Other Changes
* SOLR-15886: Remove deprecated showItems configuration value from solrconfig.xml files (Andy Lester via Eric Pugh)
+* SOLR-16114: SolrZooKeeper has been removed in favor of using ZooKeeper directly. (Mike Drob)
+
Build
---------------------
* SOLR-16053: Upgrade scriptDepVersions (Kevin Risden)
diff --git a/solr/core/build.gradle b/solr/core/build.gradle
index 2a04dbb..2e4a565 100644
--- a/solr/core/build.gradle
+++ b/solr/core/build.gradle
@@ -130,6 +130,7 @@ dependencies {
implementation ('org.apache.zookeeper:zookeeper-jute') {
exclude group: 'org.apache.yetus', module: 'audience-annotations'
}
+ testImplementation 'org.apache.zookeeper:zookeeper::tests'
// required for instantiating a Zookeeper server (for embedding ZK or running tests)
runtimeOnly ('org.xerial.snappy:snappy-java')
diff --git a/solr/core/src/java/org/apache/solr/cloud/LeaderElector.java b/solr/core/src/java/org/apache/solr/cloud/LeaderElector.java
index f5a3eba..650d21f 100644
--- a/solr/core/src/java/org/apache/solr/cloud/LeaderElector.java
+++ b/solr/core/src/java/org/apache/solr/cloud/LeaderElector.java
@@ -112,7 +112,7 @@ public class LeaderElector {
// If any double-registrations exist for me, remove all but this latest one!
// TODO: can we even get into this state?
- String prefix = zkClient.getSolrZooKeeper().getSessionId() + "-" + context.id + "-";
+ String prefix = zkClient.getZooKeeper().getSessionId() + "-" + context.id + "-";
Iterator<String> it = seqs.iterator();
while (it.hasNext()) {
String elec = it.next();
@@ -232,7 +232,7 @@ public class LeaderElector {
final String shardsElectZkPath = context.electionPath + LeaderElector.ELECTION_NODE;
- long sessionId = zkClient.getSolrZooKeeper().getSessionId();
+ long sessionId = zkClient.getZooKeeper().getSessionId();
String id = sessionId + "-" + context.id;
String leaderSeqPath = null;
boolean cont = true;
diff --git a/solr/core/src/java/org/apache/solr/cloud/Overseer.java b/solr/core/src/java/org/apache/solr/cloud/Overseer.java
index 1f76e48..838ec5d 100644
--- a/solr/core/src/java/org/apache/solr/cloud/Overseer.java
+++ b/solr/core/src/java/org/apache/solr/cloud/Overseer.java
@@ -53,7 +53,6 @@ import org.apache.solr.common.AlreadyClosedException;
import org.apache.solr.common.SolrCloseable;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.ClusterState;
-import org.apache.solr.common.cloud.ConnectionManager;
import org.apache.solr.common.cloud.DocCollection;
import org.apache.solr.common.cloud.Slice;
import org.apache.solr.common.cloud.SolrZkClient;
@@ -1022,11 +1021,7 @@ public class Overseer implements SolrCloseable {
"/overseer/queue",
zkStats,
STATE_UPDATE_MAX_QUEUE,
- new ConnectionManager.IsClosed() {
- public boolean isClosed() {
- return Overseer.this.isClosed() || zkController.getCoreContainer().isShutDown();
- }
- });
+ () -> Overseer.this.isClosed() || zkController.getCoreContainer().isShutDown());
}
/**
diff --git a/solr/core/src/java/org/apache/solr/cloud/ZkController.java b/solr/core/src/java/org/apache/solr/cloud/ZkController.java
index 9e151f2..0778f7e 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ZkController.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ZkController.java
@@ -317,7 +317,11 @@ public class ZkController implements Closeable {
this.leaderConflictResolveWait = cloudConfig.getLeaderConflictResolveWait();
this.clientTimeout = cloudConfig.getZkClientTimeout();
- DefaultConnectionStrategy strat = new DefaultConnectionStrategy();
+
+ String connectionStrategy = System.getProperty("solr.zookeeper.connectionStrategy");
+ ZkClientConnectionStrategy strat =
+ ZkClientConnectionStrategy.forName(connectionStrategy, new DefaultConnectionStrategy());
+
String zkACLProviderClass = cloudConfig.getZkACLProviderClass();
ZkACLProvider zkACLProvider = null;
if (zkACLProviderClass != null && zkACLProviderClass.trim().length() > 0) {
@@ -471,13 +475,7 @@ public class ZkController implements Closeable {
}
},
zkACLProvider,
- new ConnectionManager.IsClosed() {
-
- @Override
- public boolean isClosed() {
- return cc.isShutDown();
- }
- });
+ cc::isShutDown);
// Refuse to start if ZK has a non empty /clusterstate.json
checkNoOldClusterstate(zkClient);
@@ -1057,8 +1055,7 @@ public class ZkController implements Closeable {
}
boolean deleted =
- deletedLatch.await(
- zkClient.getSolrZooKeeper().getSessionTimeout() * 2, TimeUnit.MILLISECONDS);
+ deletedLatch.await(zkClient.getZooKeeper().getSessionTimeout() * 2, TimeUnit.MILLISECONDS);
if (!deleted) {
throw new SolrException(
ErrorCode.SERVER_ERROR,
@@ -1159,7 +1156,7 @@ public class ZkController implements Closeable {
String chrootPath = zkHost.substring(zkHost.indexOf("/"), zkHost.length());
SolrZkClient tmpClient =
- new SolrZkClient(zkHost.substring(0, zkHost.indexOf("/")), 60000, 30000, null, null, null);
+ new SolrZkClient(zkHost.substring(0, zkHost.indexOf("/")), 60000, 30000);
boolean exists = tmpClient.exists(chrootPath, true);
if (!exists && create) {
log.info("creating chroot {}", chrootPath);
diff --git a/solr/core/src/java/org/apache/solr/core/CoreContainer.java b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
index d4e46fb..e30ca21 100644
--- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java
+++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
@@ -1886,7 +1886,7 @@ public class CoreContainer {
if (docCollection != null) {
Replica replica = docCollection.getReplica(cd.getCloudDescriptor().getCoreNodeName());
- assert replica != null;
+ assert replica != null : cd.getCloudDescriptor().getCoreNodeName() + " had no replica";
if (replica.getType() == Replica.Type.TLOG) { // TODO: needed here?
getZkController().stopReplicationFromLeader(core.getName());
if (!cd.getCloudDescriptor().isLeader()) {
diff --git a/solr/core/src/test/org/apache/solr/cloud/ConnectionManagerTest.java b/solr/core/src/test/org/apache/solr/cloud/ConnectionManagerTest.java
index daf0e95..83fce07 100644
--- a/solr/core/src/test/org/apache/solr/cloud/ConnectionManagerTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/ConnectionManagerTest.java
@@ -24,13 +24,14 @@ import java.util.concurrent.TimeoutException;
import org.apache.lucene.util.LuceneTestCase.Slow;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.cloud.ConnectionManager;
-import org.apache.solr.common.cloud.DefaultConnectionStrategy;
import org.apache.solr.common.cloud.SolrZkClient;
import org.apache.solr.common.util.SolrNamedThreadFactory;
+import org.apache.zookeeper.TestableZooKeeper;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
+import org.apache.zookeeper.ZooKeeper;
import org.junit.Ignore;
import org.junit.Test;
@@ -53,10 +54,11 @@ public class ConnectionManagerTest extends SolrTestCaseJ4 {
try {
assertFalse(cm.isLikelyExpired());
- zkClient.getSolrZooKeeper().closeCnxn();
+ ZooKeeper zk = zkClient.getZooKeeper();
+ assertTrue(zk instanceof TestableZooKeeper);
+ ((TestableZooKeeper) zk).testableConnloss();
+ server.expire(zkClient.getZooKeeper().getSessionId());
- long sessionId = zkClient.getSolrZooKeeper().getSessionId();
- server.expire(sessionId);
Thread.sleep(TIMEOUT);
assertTrue(cm.isLikelyExpired());
@@ -145,7 +147,7 @@ public class ConnectionManagerTest extends SolrTestCaseJ4 {
}
}
- private static class MockZkClientConnectionStrategy extends DefaultConnectionStrategy {
+ private static class MockZkClientConnectionStrategy extends TestConnectionStrategy {
int called = 0;
boolean exceptionThrown = false;
diff --git a/solr/core/src/test/org/apache/solr/cloud/DistributedQueueTest.java b/solr/core/src/test/org/apache/solr/cloud/DistributedQueueTest.java
index ac0afec..8e37f4c 100644
--- a/solr/core/src/test/org/apache/solr/cloud/DistributedQueueTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/DistributedQueueTest.java
@@ -288,7 +288,7 @@ public class DistributedQueueTest extends SolrTestCaseJ4 {
}
private void forceSessionExpire() throws InterruptedException, TimeoutException {
- long sessionId = zkClient.getSolrZooKeeper().getSessionId();
+ long sessionId = zkClient.getZooKeeper().getSessionId();
zkServer.expire(sessionId);
zkClient.getConnectionManager().waitForDisconnected(10000);
zkClient.getConnectionManager().waitForConnected(10000);
@@ -299,7 +299,7 @@ public class DistributedQueueTest extends SolrTestCaseJ4 {
Thread.sleep(50);
}
assertTrue(zkClient.isConnected());
- assertFalse(sessionId == zkClient.getSolrZooKeeper().getSessionId());
+ assertNotEquals(sessionId, zkClient.getZooKeeper().getSessionId());
}
protected ZkDistributedQueue makeDistributedQueue(String dqZNode) throws Exception {
diff --git a/solr/core/src/test/org/apache/solr/cloud/LeaderElectionIntegrationTest.java b/solr/core/src/test/org/apache/solr/cloud/LeaderElectionIntegrationTest.java
index d2df697..0c901b0 100644
--- a/solr/core/src/test/org/apache/solr/cloud/LeaderElectionIntegrationTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/LeaderElectionIntegrationTest.java
@@ -101,10 +101,7 @@ public class LeaderElectionIntegrationTest extends SolrCloudTestCase {
// timeout the leader
String leader = getLeader(collection);
JettySolrRunner jetty = getRunner(leader);
- ZkController zkController = jetty.getCoreContainer().getZkController();
-
- zkController.getZkClient().getSolrZooKeeper().closeCnxn();
- cluster.getZkServer().expire(zkController.getZkClient().getSolrZooKeeper().getSessionId());
+ cluster.expireZkSession(jetty);
for (int i = 0; i < 60; i++) { // wait till leader is changed
if (jetty != getRunner(getLeader(collection))) {
diff --git a/solr/core/src/test/org/apache/solr/cloud/LeaderElectionTest.java b/solr/core/src/test/org/apache/solr/cloud/LeaderElectionTest.java
index 1ef1260..38b4dc5 100644
--- a/solr/core/src/test/org/apache/solr/cloud/LeaderElectionTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/LeaderElectionTest.java
@@ -41,6 +41,8 @@ import org.apache.solr.common.util.Utils;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.KeeperException.NoNodeException;
import org.apache.zookeeper.KeeperException.SessionExpiredException;
+import org.apache.zookeeper.TestableZooKeeper;
+import org.apache.zookeeper.ZooKeeper;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -531,32 +533,30 @@ public class LeaderElectionTest extends SolrTestCaseJ4 {
};
Thread connLossThread =
- new Thread() {
- @Override
- public void run() {
-
- while (!stopStress) {
- try {
- Thread.sleep(50);
- int j;
- j = random().nextInt(threads.size());
+ new Thread(
+ () -> {
+ while (!stopStress) {
try {
- threads.get(j).es.zkClient.getSolrZooKeeper().closeCnxn();
- if (random().nextBoolean()) {
- long sessionId = zkClient.getSolrZooKeeper().getSessionId();
- server.expire(sessionId);
+ Thread.sleep(50);
+ int j;
+ j = random().nextInt(threads.size());
+ try {
+ ZooKeeper zk = threads.get(j).es.zkClient.getZooKeeper();
+ assertTrue(zk instanceof TestableZooKeeper);
+ ((TestableZooKeeper) zk).testableConnloss();
+ if (random().nextBoolean()) {
+ server.expire(zk.getSessionId());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
}
- } catch (Exception e) {
- e.printStackTrace();
- }
- Thread.sleep(500);
+ Thread.sleep(500);
- } catch (Exception e) {
+ } catch (Exception e) {
+ }
}
- }
- }
- };
+ });
scheduleThread.start();
connLossThread.start();
@@ -582,7 +582,7 @@ public class LeaderElectionTest extends SolrTestCaseJ4 {
// cleanup any threads still running
for (ClientThread thread : threads) {
- thread.es.zkClient.getSolrZooKeeper().close();
+ thread.es.zkClient.getZooKeeper().close();
thread.close();
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/OutOfBoxZkACLAndCredentialsProvidersTest.java b/solr/core/src/test/org/apache/solr/cloud/OutOfBoxZkACLAndCredentialsProvidersTest.java
index d17f6ec..0a4ebf0 100644
--- a/solr/core/src/test/org/apache/solr/cloud/OutOfBoxZkACLAndCredentialsProvidersTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/OutOfBoxZkACLAndCredentialsProvidersTest.java
@@ -134,7 +134,7 @@ public class OutOfBoxZkACLAndCredentialsProvidersTest extends SolrTestCaseJ4 {
protected void assertOpenACLUnsafeAllover(
SolrZkClient zkClient, String path, List<String> verifiedList) throws Exception {
- List<ACL> acls = zkClient.getSolrZooKeeper().getACL(path, new Stat());
+ List<ACL> acls = zkClient.getZooKeeper().getACL(path, new Stat());
if (log.isInfoEnabled()) {
log.info("Verifying {}", path);
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/OverriddenZkACLAndCredentialsProvidersTest.java b/solr/core/src/test/org/apache/solr/cloud/OverriddenZkACLAndCredentialsProvidersTest.java
index 0a741c1..610c294 100644
--- a/solr/core/src/test/org/apache/solr/cloud/OverriddenZkACLAndCredentialsProvidersTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/OverriddenZkACLAndCredentialsProvidersTest.java
@@ -107,7 +107,7 @@ public class OverriddenZkACLAndCredentialsProvidersTest extends SolrTestCaseJ4 {
new SolrZkClientFactoryUsingCompletelyNewProviders(null, null, null, null)
.getSolrZkClient(zkServer.getZkAddress(), AbstractZkTestCase.TIMEOUT);
zkClient
- .getSolrZooKeeper()
+ .getZooKeeper()
.addAuthInfo(
"digest",
("connectAndAllACLUsername:connectAndAllACLPassword").getBytes(DATA_ENCODING));
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestLeaderElectionZkExpiry.java b/solr/core/src/test/org/apache/solr/cloud/TestLeaderElectionZkExpiry.java
index 3328da1..7e043bd 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestLeaderElectionZkExpiry.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestLeaderElectionZkExpiry.java
@@ -66,8 +66,7 @@ public class TestLeaderElectionZkExpiry extends SolrTestCaseJ4 {
long timeout =
System.nanoTime() + TimeUnit.NANOSECONDS.convert(10, TimeUnit.SECONDS);
while (System.nanoTime() < timeout) {
- long sessionId = zkController.getZkClient().getSolrZooKeeper().getSessionId();
- server.expire(sessionId);
+ server.expire(zkController.getZkClient().getZooKeeper().getSessionId());
try {
Thread.sleep(10);
} catch (InterruptedException e) {
diff --git a/solr/core/src/test/org/apache/solr/cloud/ZkSolrClientTest.java b/solr/core/src/test/org/apache/solr/cloud/ZkSolrClientTest.java
index 3992c19c..95758a6 100644
--- a/solr/core/src/test/org/apache/solr/cloud/ZkSolrClientTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/ZkSolrClientTest.java
@@ -182,8 +182,7 @@ public class ZkSolrClientTest extends SolrTestCaseJ4 {
// simulate session expiration
// one option
- long sessionId = zkClient.getSolrZooKeeper().getSessionId();
- server.expire(sessionId);
+ server.expire(zkClient.getZooKeeper().getSessionId());
// another option
// zkClient.getSolrZooKeeper().getConnection().disconnect();
diff --git a/solr/licenses/zookeeper-3.7.0-tests.jar.sha1 b/solr/licenses/zookeeper-3.7.0-tests.jar.sha1
new file mode 100644
index 0000000..ec7eff7
--- /dev/null
+++ b/solr/licenses/zookeeper-3.7.0-tests.jar.sha1
@@ -0,0 +1 @@
+093f2c34c33ee16f9ff3f9352c79eafd3cd9040a
diff --git a/solr/modules/hadoop-auth/src/test/org/apache/solr/security/hadoop/SaslZkACLProviderTest.java b/solr/modules/hadoop-auth/src/test/org/apache/solr/security/hadoop/SaslZkACLProviderTest.java
index 530aab2..4d200d5 100644
--- a/solr/modules/hadoop-auth/src/test/org/apache/solr/security/hadoop/SaslZkACLProviderTest.java
+++ b/solr/modules/hadoop-auth/src/test/org/apache/solr/security/hadoop/SaslZkACLProviderTest.java
@@ -91,8 +91,7 @@ public class SaslZkACLProviderTest extends SolrTestCaseJ4 {
try (SolrZkClient zkClient =
new SolrZkClientWithACLs(zkServer.getZkHost(), AbstractZkTestCase.TIMEOUT)) {
- ZooKeeperSaslClient saslClient =
- zkClient.getSolrZooKeeper().getConnection().zooKeeperSaslClient;
+ ZooKeeperSaslClient saslClient = zkClient.getZooKeeper().getSaslClient();
assumeFalse("Could not set up ZK with SASL", saslClient.isFailed());
zkClient.makePath("/solr", false, true);
} catch (KeeperException e) {
diff --git a/solr/solrj/src/java/org/apache/solr/common/cloud/ConnectionManager.java b/solr/solrj/src/java/org/apache/solr/common/cloud/ConnectionManager.java
index c2c3594..a437a6b 100644
--- a/solr/solrj/src/java/org/apache/solr/common/cloud/ConnectionManager.java
+++ b/solr/solrj/src/java/org/apache/solr/common/cloud/ConnectionManager.java
@@ -27,6 +27,7 @@ import org.apache.solr.common.SolrException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
+import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -76,8 +77,8 @@ public class ConnectionManager implements Watcher {
}
}
- public abstract static class IsClosed {
- public abstract boolean isClosed();
+ public interface IsClosed {
+ boolean isClosed();
}
private volatile LikelyExpiredState likelyExpiredState = LikelyExpiredState.EXPIRED;
@@ -181,7 +182,7 @@ public class ConnectionManager implements Watcher {
this,
new ZkClientConnectionStrategy.ZkUpdate() {
@Override
- public void update(SolrZooKeeper keeper) {
+ public void update(ZooKeeper keeper) {
try {
waitForConnected(Long.MAX_VALUE);
@@ -206,6 +207,17 @@ public class ConnectionManager implements Watcher {
throw new RuntimeException(e1);
}
}
+
+ private void closeKeeper(ZooKeeper keeper) {
+ try {
+ keeper.close();
+ } catch (InterruptedException e) {
+ // Restore the interrupted status
+ Thread.currentThread().interrupt();
+ log.error("", e);
+ throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR, "", e);
+ }
+ }
});
break;
@@ -304,15 +316,4 @@ public class ConnectionManager implements Watcher {
throw new TimeoutException("Did not disconnect");
}
}
-
- private void closeKeeper(SolrZooKeeper keeper) {
- try {
- keeper.close();
- } catch (InterruptedException e) {
- // Restore the interrupted status
- Thread.currentThread().interrupt();
- log.error("", e);
- throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR, "", e);
- }
- }
}
diff --git a/solr/solrj/src/java/org/apache/solr/common/cloud/DefaultConnectionStrategy.java b/solr/solrj/src/java/org/apache/solr/common/cloud/DefaultConnectionStrategy.java
index d0797a6..42d8cbe 100644
--- a/solr/solrj/src/java/org/apache/solr/common/cloud/DefaultConnectionStrategy.java
+++ b/solr/solrj/src/java/org/apache/solr/common/cloud/DefaultConnectionStrategy.java
@@ -21,6 +21,7 @@ import java.lang.invoke.MethodHandles;
import java.util.concurrent.TimeoutException;
import org.apache.solr.common.AlreadyClosedException;
import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,7 +33,7 @@ public class DefaultConnectionStrategy extends ZkClientConnectionStrategy {
@Override
public void connect(String serverAddress, int timeout, Watcher watcher, ZkUpdate updater)
throws IOException, InterruptedException, TimeoutException {
- SolrZooKeeper zk = createSolrZooKeeper(serverAddress, timeout, watcher);
+ ZooKeeper zk = createZooKeeper(serverAddress, timeout, watcher);
boolean success = false;
try {
updater.update(zk);
@@ -52,7 +53,7 @@ public class DefaultConnectionStrategy extends ZkClientConnectionStrategy {
final ZkUpdate updater)
throws IOException, InterruptedException, TimeoutException {
log.warn("Connection expired - starting a new one...");
- SolrZooKeeper zk = createSolrZooKeeper(serverAddress, zkClientTimeout, watcher);
+ ZooKeeper zk = createZooKeeper(serverAddress, zkClientTimeout, watcher);
boolean success = false;
try {
updater.update(zk);
diff --git a/solr/solrj/src/java/org/apache/solr/common/cloud/SolrZkClient.java b/solr/solrj/src/java/org/apache/solr/common/cloud/SolrZkClient.java
index e3b2bc9..0222e2f 100644
--- a/solr/solrj/src/java/org/apache/solr/common/cloud/SolrZkClient.java
+++ b/solr/solrj/src/java/org/apache/solr/common/cloud/SolrZkClient.java
@@ -57,6 +57,7 @@ import org.slf4j.LoggerFactory;
* All Solr ZooKeeper interactions should go through this class rather than ZooKeeper. This class
* handles synchronous connects and reconnections.
*/
+// The constructor overloads are a little awkward, it would be nice to move this to a builder
public class SolrZkClient implements Closeable {
static final String NEWL = System.getProperty("line.separator");
@@ -67,7 +68,7 @@ public class SolrZkClient implements Closeable {
private ConnectionManager connManager;
- private volatile SolrZooKeeper keeper;
+ private volatile ZooKeeper keeper;
private ZkCmdExecutor zkCmdExecutor;
@@ -93,29 +94,19 @@ public class SolrZkClient implements Closeable {
public SolrZkClient() {}
public SolrZkClient(String zkServerAddress, int zkClientTimeout) {
- this(zkServerAddress, zkClientTimeout, new DefaultConnectionStrategy(), null);
+ this(zkServerAddress, zkClientTimeout, DEFAULT_CLIENT_CONNECT_TIMEOUT);
}
public SolrZkClient(String zkServerAddress, int zkClientTimeout, int zkClientConnectTimeout) {
- this(
- zkServerAddress,
- zkClientTimeout,
- zkClientConnectTimeout,
- new DefaultConnectionStrategy(),
- null);
+ this(zkServerAddress, zkClientTimeout, zkClientConnectTimeout, null);
}
public SolrZkClient(
String zkServerAddress,
int zkClientTimeout,
int zkClientConnectTimeout,
- OnReconnect onReonnect) {
- this(
- zkServerAddress,
- zkClientTimeout,
- zkClientConnectTimeout,
- new DefaultConnectionStrategy(),
- onReonnect);
+ OnReconnect onReconnect) {
+ this(zkServerAddress, zkClientTimeout, zkClientConnectTimeout, null, onReconnect);
}
public SolrZkClient(
@@ -149,31 +140,15 @@ public class SolrZkClient implements Closeable {
int clientConnectTimeout,
ZkClientConnectionStrategy strat,
final OnReconnect onReconnect,
- BeforeReconnect beforeReconnect) {
- this(
- zkServerAddress,
- zkClientTimeout,
- clientConnectTimeout,
- strat,
- onReconnect,
- beforeReconnect,
- null,
- null);
- }
-
- public SolrZkClient(
- String zkServerAddress,
- int zkClientTimeout,
- int clientConnectTimeout,
- ZkClientConnectionStrategy strat,
- final OnReconnect onReconnect,
BeforeReconnect beforeReconnect,
ZkACLProvider zkACLProvider,
IsClosed higherLevelIsClosed) {
this.zkServerAddress = zkServerAddress;
this.higherLevelIsClosed = higherLevelIsClosed;
if (strat == null) {
- strat = new DefaultConnectionStrategy();
+ String connectionStrategy = System.getProperty("solr.zookeeper.connectionStrategy");
+ strat =
+ ZkClientConnectionStrategy.forName(connectionStrategy, new DefaultConnectionStrategy());
}
this.zkClientConnectionStrategy = strat;
@@ -185,16 +160,7 @@ public class SolrZkClient implements Closeable {
this.zkClientTimeout = zkClientTimeout;
// we must retry at least as long as the session timeout
- zkCmdExecutor =
- new ZkCmdExecutor(
- zkClientTimeout,
- new IsClosed() {
-
- @Override
- public boolean isClosed() {
- return SolrZkClient.this.isClosed();
- }
- });
+ zkCmdExecutor = new ZkCmdExecutor(zkClientTimeout, SolrZkClient.this::isClosed);
connManager =
new ConnectionManager(
"ZooKeeperConnection Watcher:" + zkServerAddress,
@@ -203,13 +169,7 @@ public class SolrZkClient implements Closeable {
strat,
onReconnect,
beforeReconnect,
- new IsClosed() {
-
- @Override
- public boolean isClosed() {
- return SolrZkClient.this.isClosed();
- }
- });
+ SolrZkClient.this::isClosed);
try {
strat.connect(
@@ -217,7 +177,7 @@ public class SolrZkClient implements Closeable {
zkClientTimeout,
wrapWatcher(connManager),
zooKeeper -> {
- SolrZooKeeper oldKeeper = keeper;
+ ZooKeeper oldKeeper = keeper;
keeper = zooKeeper;
try {
closeKeeper(oldKeeper);
@@ -738,8 +698,8 @@ public class SolrZkClient implements Closeable {
}
/** Allows package private classes to update volatile ZooKeeper. */
- void updateKeeper(SolrZooKeeper keeper) throws InterruptedException {
- SolrZooKeeper oldKeeper = this.keeper;
+ void updateKeeper(ZooKeeper keeper) throws InterruptedException {
+ ZooKeeper oldKeeper = this.keeper;
this.keeper = keeper;
if (oldKeeper != null) {
oldKeeper.close();
@@ -748,11 +708,11 @@ public class SolrZkClient implements Closeable {
if (isClosed) this.keeper.close();
}
- public SolrZooKeeper getSolrZooKeeper() {
+ public ZooKeeper getZooKeeper() {
return keeper;
}
- private void closeKeeper(SolrZooKeeper keeper) {
+ private void closeKeeper(ZooKeeper keeper) {
if (keeper != null) {
try {
keeper.close();
diff --git a/solr/solrj/src/java/org/apache/solr/common/cloud/SolrZooKeeper.java b/solr/solrj/src/java/org/apache/solr/common/cloud/SolrZooKeeper.java
deleted file mode 100644
index 4d126b4..0000000
--- a/solr/solrj/src/java/org/apache/solr/common/cloud/SolrZooKeeper.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.common.cloud;
-
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.SocketAddress;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.Set;
-import java.util.concurrent.CopyOnWriteArraySet;
-import org.apache.solr.common.util.SuppressForbidden;
-import org.apache.zookeeper.ClientCnxn;
-import org.apache.zookeeper.Watcher;
-import org.apache.zookeeper.ZooKeeper;
-
-// we use this class to expose nasty stuff for tests
-@SuppressWarnings({"try"})
-public class SolrZooKeeper extends ZooKeeper {
- final Set<Thread> spawnedThreads = new CopyOnWriteArraySet<>();
-
- // for test debug
- // static Map<SolrZooKeeper,Exception> clients = new ConcurrentHashMap<SolrZooKeeper,Exception>();
-
- public SolrZooKeeper(String connectString, int sessionTimeout, Watcher watcher)
- throws IOException {
- super(connectString, sessionTimeout, watcher);
- // clients.put(this, new RuntimeException());
- }
-
- public ClientCnxn getConnection() {
- return cnxn;
- }
-
- public SocketAddress getSocketAddress() {
- return testableLocalSocketAddress();
- }
-
- public void closeCnxn() {
- final Thread t =
- new Thread(
- new Runnable() {
- @Override
- public void run() {
- try {
- AccessController.doPrivileged(
- (PrivilegedAction<Void>) this::closeZookeeperChannel);
- } finally {
- spawnedThreads.remove(Thread.currentThread());
- }
- }
-
- @SuppressForbidden(reason = "Hack for Zookeeper needs access to private methods.")
- private Void closeZookeeperChannel() {
- final ClientCnxn cnxn = getConnection();
- synchronized (cnxn) {
- try {
- final Field sendThreadFld = cnxn.getClass().getDeclaredField("sendThread");
- sendThreadFld.setAccessible(true);
- Object sendThread = sendThreadFld.get(cnxn);
- if (sendThread != null) {
- Method method =
- sendThread.getClass().getDeclaredMethod("testableCloseSocket");
- method.setAccessible(true);
- try {
- method.invoke(sendThread);
- } catch (InvocationTargetException e) {
- // is fine
- }
- }
- } catch (Exception e) {
- throw new RuntimeException("Closing Zookeeper send channel failed.", e);
- }
- }
- return null; // Void
- }
- },
- "closeCnxn");
- spawnedThreads.add(t);
- t.start();
- }
-
- @Override
- public synchronized void close() throws InterruptedException {
- super.close();
- }
-
- // public static void assertCloses() {
- // if (clients.size() > 0) {
- // Iterator<Exception> stacktraces = clients.values().iterator();
- // Exception cause = null;
- // cause = stacktraces.next();
- // throw new RuntimeException("Found a bad one!", cause);
- // }
- // }
-
-}
diff --git a/solr/solrj/src/java/org/apache/solr/common/cloud/ZkClientConnectionStrategy.java b/solr/solrj/src/java/org/apache/solr/common/cloud/ZkClientConnectionStrategy.java
index 1ca3b55..47776b4 100644
--- a/solr/solrj/src/java/org/apache/solr/common/cloud/ZkClientConnectionStrategy.java
+++ b/solr/solrj/src/java/org/apache/solr/common/cloud/ZkClientConnectionStrategy.java
@@ -24,6 +24,7 @@ import java.util.concurrent.TimeoutException;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.ZkCredentialsProvider.ZkCredentials;
import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -90,7 +91,7 @@ public abstract class ZkClientConnectionStrategy {
}
public interface ZkUpdate {
- void update(SolrZooKeeper zooKeeper) throws InterruptedException, TimeoutException, IOException;
+ void update(ZooKeeper zooKeeper) throws InterruptedException, TimeoutException, IOException;
}
public void setZkCredentialsToAddAutomatically(
@@ -109,10 +110,10 @@ public abstract class ZkClientConnectionStrategy {
return zkCredentialsToAddAutomatically;
}
- protected SolrZooKeeper createSolrZooKeeper(
+ protected ZooKeeper createZooKeeper(
final String serverAddress, final int zkClientTimeout, final Watcher watcher)
throws IOException {
- SolrZooKeeper result = new SolrZooKeeper(serverAddress, zkClientTimeout, watcher);
+ ZooKeeper result = newZooKeeperInstance(serverAddress, zkClientTimeout, watcher);
zkCredentialsToAddAutomaticallyUsed = true;
for (ZkCredentials zkCredentials : zkCredentialsToAddAutomatically.getCredentials()) {
@@ -121,4 +122,35 @@ public abstract class ZkClientConnectionStrategy {
return result;
}
+
+ // Override for testing
+ protected ZooKeeper newZooKeeperInstance(
+ final String serverAddress, final int zkClientTimeout, final Watcher watcher)
+ throws IOException {
+ return new ZooKeeper(serverAddress, zkClientTimeout, watcher);
+ }
+
+ /**
+ * Instantiate a new connection strategy for the given class name
+ *
+ * @param name the name of the strategy to use
+ * @return the strategy instance, or null if it could not be loaded
+ */
+ public static ZkClientConnectionStrategy forName(String name, ZkClientConnectionStrategy def) {
+ log.debug("Attempting to load zk connection strategy '{}'", name);
+ if (name == null) {
+ return def;
+ }
+
+ try {
+ // TODO should this use SolrResourceLoader?
+ return Class.forName(name)
+ .asSubclass(ZkClientConnectionStrategy.class)
+ .getConstructor()
+ .newInstance();
+ } catch (Exception e) {
+ log.warn("Exception when loading '{}' ZK connection strategy.", name, e);
+ return def;
+ }
+ }
}
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 649091c..c4d3b6c 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
@@ -2221,7 +2221,7 @@ public class ZkStateReader implements SolrCloseable {
public boolean update() throws KeeperException, InterruptedException {
log.debug("Checking ZK for most up to date Aliases {}", ALIASES);
// Call sync() first to ensure the subsequent read (getData) is up to date.
- zkClient.getSolrZooKeeper().sync(ALIASES, null, null);
+ zkClient.getZooKeeper().sync(ALIASES, null, null);
Stat stat = new Stat();
final byte[] data = zkClient.getData(ALIASES, null, stat, true);
return setIfNewer(Aliases.fromJSON(data, stat.getVersion()));
diff --git a/solr/test-framework/build.gradle b/solr/test-framework/build.gradle
index 569f0e2..bdb0785 100644
--- a/solr/test-framework/build.gradle
+++ b/solr/test-framework/build.gradle
@@ -38,15 +38,17 @@ dependencies {
implementation 'org.apache.lucene:lucene-queries'
implementation 'org.apache.lucene:lucene-suggest'
- implementation('org.apache.zookeeper:zookeeper', {
+
+ var zkExcludes = {
exclude group: "org.apache.yetus", module: "audience-annotations"
exclude group: "log4j", module: "log4j"
exclude group: "org.slf4j", module: "slf4j-log4j12"
- })
- implementation ('org.apache.zookeeper:zookeeper-jute') {
- exclude group: 'org.apache.yetus', module: 'audience-annotations'
}
+ implementation('org.apache.zookeeper:zookeeper', zkExcludes)
+ implementation('org.apache.zookeeper:zookeeper-jute', zkExcludes)
+ implementation('org.apache.zookeeper:zookeeper::tests', zkExcludes)
+
implementation 'commons-io:commons-io'
implementation 'org.slf4j:slf4j-api'
implementation 'org.apache.logging.log4j:log4j-api'
diff --git a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
index 99a6960..bdd1273 100644
--- a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
+++ b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
@@ -108,6 +108,7 @@ import org.apache.solr.client.solrj.response.SolrResponseBase;
import org.apache.solr.client.solrj.util.ClientUtils;
import org.apache.solr.cloud.IpTables;
import org.apache.solr.cloud.MiniSolrCloudCluster;
+import org.apache.solr.cloud.TestConnectionStrategy;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrException;
@@ -301,6 +302,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
System.setProperty("solr.v2RealPath", "true");
System.setProperty("zookeeper.forceSync", "no");
System.setProperty("jetty.testMode", "true");
+ System.setProperty("solr.zookeeper.connectionStrategy", TestConnectionStrategy.class.getName());
System.setProperty("enable.update.log", Boolean.toString(usually()));
System.setProperty("tests.shardhandler.randomSeed", Long.toString(random().nextLong()));
System.setProperty("solr.clustering.enabled", "false");
diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractVMParamsZkACLAndCredentialsProvidersTestBase.java b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractVMParamsZkACLAndCredentialsProvidersTestBase.java
index 35247b5..21e9b13 100644
--- a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractVMParamsZkACLAndCredentialsProvidersTestBase.java
+++ b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractVMParamsZkACLAndCredentialsProvidersTestBase.java
@@ -77,12 +77,7 @@ public class AbstractVMParamsZkACLAndCredentialsProvidersTestBase extends SolrTe
SolrZkClient zkClient =
new SolrZkClient(
- zkServer.getZkHost(),
- AbstractZkTestCase.TIMEOUT,
- AbstractZkTestCase.TIMEOUT,
- null,
- null,
- null);
+ zkServer.getZkHost(), AbstractZkTestCase.TIMEOUT, AbstractZkTestCase.TIMEOUT);
zkClient.makePath("/solr", false, true);
zkClient.close();
@@ -107,7 +102,7 @@ public class AbstractVMParamsZkACLAndCredentialsProvidersTestBase extends SolrTe
// no (or completely open) ACLs added. Therefore hack your way into being authorized for
// creating anyway
zkClient
- .getSolrZooKeeper()
+ .getZooKeeper()
.addAuthInfo(
"digest",
("connectAndAllACLUsername:connectAndAllACLPassword").getBytes(StandardCharsets.UTF_8));
@@ -204,7 +199,7 @@ public class AbstractVMParamsZkACLAndCredentialsProvidersTestBase extends SolrTe
// no (or completely open) ACLs added. Therefore hack your way into being authorized for
// creating anyway
zkClient
- .getSolrZooKeeper()
+ .getZooKeeper()
.addAuthInfo(
"digest",
("connectAndAllACLUsername:connectAndAllACLPassword")
diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/ChaosMonkey.java b/solr/test-framework/src/java/org/apache/solr/cloud/ChaosMonkey.java
index 0204451..25babc2 100644
--- a/solr/test-framework/src/java/org/apache/solr/cloud/ChaosMonkey.java
+++ b/solr/test-framework/src/java/org/apache/solr/cloud/ChaosMonkey.java
@@ -16,6 +16,7 @@
*/
package org.apache.solr.cloud;
+import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.List;
@@ -47,6 +48,8 @@ import org.apache.solr.util.RTimer;
import org.apache.solr.util.TestInjection;
import org.apache.solr.util.TimeOut;
import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.TestableZooKeeper;
+import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -149,8 +152,7 @@ public class ChaosMonkey {
if (cores != null) {
monkeyLog("expire session for " + jetty.getLocalPort() + " !");
causeConnectionLoss(jetty);
- long sessionId = cores.getZkController().getZkClient().getSolrZooKeeper().getSessionId();
- zkServer.expire(sessionId);
+ zkServer.expire(cores.getZkController().getZkClient().getZooKeeper().getSessionId());
}
}
@@ -180,7 +182,21 @@ public class ChaosMonkey {
if (cores != null) {
monkeyLog("Will cause connection loss on " + jetty.getLocalPort());
SolrZkClient zkClient = cores.getZkController().getZkClient();
- zkClient.getSolrZooKeeper().closeCnxn();
+ causeConnectionLoss(zkClient.getZooKeeper());
+ }
+ }
+
+ public static void causeConnectionLoss(ZooKeeper zooKeeper) {
+ assert zooKeeper instanceof TestableZooKeeper
+ : "Can only cause connection loss for TestableZookeeper";
+ if (zooKeeper instanceof TestableZooKeeper) {
+ try {
+ ((TestableZooKeeper) zooKeeper).testableConnloss();
+ } catch (IOException ignored) {
+ // best effort
+ }
+ } else {
+ // TODO what now?
}
}
diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/MiniSolrCloudCluster.java b/solr/test-framework/src/java/org/apache/solr/cloud/MiniSolrCloudCluster.java
index cc4c230..5cb076e 100644
--- a/solr/test-framework/src/java/org/apache/solr/cloud/MiniSolrCloudCluster.java
+++ b/solr/test-framework/src/java/org/apache/solr/cloud/MiniSolrCloudCluster.java
@@ -790,16 +790,14 @@ public class MiniSolrCloudCluster {
"Cannot find Jetty for a replica with core url " + replica.getCoreUrl());
}
- /** Make the zookeeper session on a particular jetty expire */
+ /** Make the zookeeper session on a particular jetty lose connection and expire */
public void expireZkSession(JettySolrRunner jetty) {
CoreContainer cores = jetty.getCoreContainer();
if (cores != null) {
- SolrZkClient zkClient = cores.getZkController().getZkClient();
- zkClient.getSolrZooKeeper().closeCnxn();
- long sessionId = zkClient.getSolrZooKeeper().getSessionId();
- zkServer.expire(sessionId);
+ ChaosMonkey.causeConnectionLoss(jetty);
+ zkServer.expire(cores.getZkController().getZkClient().getZooKeeper().getSessionId());
if (log.isInfoEnabled()) {
- log.info("Expired zookeeper session {} from node {}", sessionId, jetty.getBaseUrl());
+ log.info("Expired zookeeper session from node {}", jetty.getBaseUrl());
}
}
}
diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/TestConnectionStrategy.java b/solr/test-framework/src/java/org/apache/solr/cloud/TestConnectionStrategy.java
new file mode 100644
index 0000000..88d94fa
--- /dev/null
+++ b/solr/test-framework/src/java/org/apache/solr/cloud/TestConnectionStrategy.java
@@ -0,0 +1,35 @@
+/*
+ * 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.solr.cloud;
+
+import java.io.IOException;
+import org.apache.solr.common.cloud.DefaultConnectionStrategy;
+import org.apache.zookeeper.TestableZooKeeper;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooKeeper;
+
+/**
+ * Connection strategy that creates instances of {@link TestableZooKeeper} instead of plain {@link
+ * ZooKeeper} objects. Useful for adding pause and disconnect events.
+ */
+public class TestConnectionStrategy extends DefaultConnectionStrategy {
+ @Override
+ protected ZooKeeper newZooKeeperInstance(
+ String serverAddress, int zkClientTimeout, Watcher watcher) throws IOException {
+ return new TestableZooKeeper(serverAddress, zkClientTimeout, watcher);
+ }
+}
diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/ZkTestServer.java b/solr/test-framework/src/java/org/apache/solr/cloud/ZkTestServer.java
index ed6d8ba..1271baa 100644
--- a/solr/test-framework/src/java/org/apache/solr/cloud/ZkTestServer.java
+++ b/solr/test-framework/src/java/org/apache/solr/cloud/ZkTestServer.java
@@ -36,7 +36,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import javax.management.JMException;
import org.apache.solr.SolrTestCaseJ4;
@@ -44,25 +43,25 @@ import org.apache.solr.common.cloud.SolrZkClient;
import org.apache.solr.common.cloud.ZkNodeProps;
import org.apache.solr.common.util.IOUtils;
import org.apache.solr.common.util.ObjectReleaseTracker;
-import org.apache.solr.common.util.TimeSource;
import org.apache.solr.common.util.Utils;
-import org.apache.solr.util.TimeOut;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.Op;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.Stat;
import org.apache.zookeeper.jmx.ManagedUtil;
import org.apache.zookeeper.server.NIOServerCnxnFactory;
+import org.apache.zookeeper.server.Request;
import org.apache.zookeeper.server.ServerCnxn;
import org.apache.zookeeper.server.ServerCnxnFactory;
import org.apache.zookeeper.server.ServerConfig;
-import org.apache.zookeeper.server.SessionTracker.Session;
import org.apache.zookeeper.server.ZKDatabase;
import org.apache.zookeeper.server.ZooKeeperServer;
import org.apache.zookeeper.server.persistence.FileTxnSnapLog;
import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException;
+import org.apache.zookeeper.test.ClientBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -383,7 +382,7 @@ public class ZkTestServer {
try {
int port = cnxnFactory.getLocalPort();
if (port > 0) {
- waitForServerDown(getZkHost(), 30000);
+ ClientBase.waitForServerDown(getZkHost(), 30000);
}
} catch (NullPointerException ignored) {
// server never successfully started
@@ -498,23 +497,9 @@ public class ZkTestServer {
}
public void expire(final long sessionId) {
- zkServer.zooKeeperServer.expire(
- new Session() {
- @Override
- public long getSessionId() {
- return sessionId;
- }
-
- @Override
- public int getTimeout() {
- return 4000;
- }
-
- @Override
- public boolean isClosing() {
- return false;
- }
- });
+ log.debug("Closing zookeeper connection for session {}", sessionId);
+ Request si = new Request(null, sessionId, 0, ZooDefs.OpCode.closeSession, null, null);
+ zkServer.zooKeeperServer.submitRequest(si);
}
public ZKDatabase getZKDatabase() {
@@ -605,7 +590,7 @@ public class ZkTestServer {
}
log.info("start zk server on port: {}", port);
- waitForServerUp(getZkHost(), 30000);
+ ClientBase.waitForServerUp(getZkHost(), 30000);
init(solrFormat);
} catch (Exception e) {
@@ -658,51 +643,6 @@ public class ZkTestServer {
ObjectReleaseTracker.release(this);
}
- public static boolean waitForServerDown(String hp, long timeoutMs) {
- log.info("waitForServerDown: {}", hp);
- final TimeOut timeout = new TimeOut(timeoutMs, TimeUnit.MILLISECONDS, TimeSource.NANO_TIME);
- while (true) {
- try {
- HostPort hpobj = parseHostPortList(hp).get(0);
- send4LetterWord(hpobj.host, hpobj.port, "stat");
- } catch (IOException e) {
- return true;
- }
-
- if (timeout.hasTimedOut()) {
- throw new RuntimeException("Time out waiting for ZooKeeper shutdown!");
- }
- try {
- Thread.sleep(250);
- } catch (InterruptedException e) {
- // ignore
- }
- }
- }
-
- public static boolean waitForServerUp(String hp, long timeoutMs) {
- log.info("waitForServerUp: {}", hp);
- final TimeOut timeout = new TimeOut(timeoutMs, TimeUnit.MILLISECONDS, TimeSource.NANO_TIME);
- while (true) {
- try {
- HostPort hpobj = parseHostPortList(hp).get(0);
- send4LetterWord(hpobj.host, hpobj.port, "stat");
- return true;
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- if (timeout.hasTimedOut()) {
- throw new RuntimeException("Time out waiting for ZooKeeper to startup!");
- }
- try {
- Thread.sleep(250);
- } catch (InterruptedException e) {
- // ignore
- }
- }
- }
-
public static class HostPort {
String host;
int port;
diff --git a/solr/test-framework/src/test/org/apache/solr/cloud/MiniSolrCloudClusterTest.java b/solr/test-framework/src/test/org/apache/solr/cloud/MiniSolrCloudClusterTest.java
index 0c19564..0c0bb53 100644
--- a/solr/test-framework/src/test/org/apache/solr/cloud/MiniSolrCloudClusterTest.java
+++ b/solr/test-framework/src/test/org/apache/solr/cloud/MiniSolrCloudClusterTest.java
@@ -65,9 +65,12 @@ public class MiniSolrCloudClusterTest extends SolrTestCaseJ4 {
};
fail("Expected an exception to be thrown from MiniSolrCloudCluster");
} catch (Exception e) {
- assertEquals("Error starting up MiniSolrCloudCluster", e.getMessage());
+ assertEquals("Incorrect exception", "Error starting up MiniSolrCloudCluster", e.getMessage());
assertEquals("Expected one suppressed exception", 1, e.getSuppressed().length);
- assertEquals("Fake exception on startup!", e.getSuppressed()[0].getMessage());
+ assertEquals(
+ "Incorrect suppressed exception",
+ "Fake exception on startup!",
+ e.getSuppressed()[0].getMessage());
} finally {
if (cluster != null) cluster.shutdown();
}