diff --git a/.gitignore b/.gitignore
index 7d712b42377..8091ecdba71 100644
--- a/.gitignore
+++ b/.gitignore
@@ -48,5 +48,7 @@ solr/contrib/morphlines-core/test-lib/
solr/core/test-lib/
+solr/server/logs/
+solr/server/solr/zoo_data/
solr/server/solr-webapp
solr/server/start.jar
diff --git a/dev-tools/idea/.idea/modules.xml b/dev-tools/idea/.idea/modules.xml
index 75da2f588eb..6fbe496772f 100644
--- a/dev-tools/idea/.idea/modules.xml
+++ b/dev-tools/idea/.idea/modules.xml
@@ -43,6 +43,7 @@
+
diff --git a/dev-tools/idea/.idea/workspace.xml b/dev-tools/idea/.idea/workspace.xml
index a7c68dec105..7750e90e15b 100644
--- a/dev-tools/idea/.idea/workspace.xml
+++ b/dev-tools/idea/.idea/workspace.xml
@@ -340,8 +340,16 @@
-
-
+
+
+
+
+
+
+
+
+
+
@@ -383,6 +391,7 @@
+
diff --git a/dev-tools/idea/solr/server/server.iml b/dev-tools/idea/solr/server/server.iml
new file mode 100644
index 00000000000..3b742a68f38
--- /dev/null
+++ b/dev-tools/idea/solr/server/server.iml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index a0814d0e055..b0abbc108f4 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -19,6 +19,9 @@ New Features
* LUCENE-7069: Add LatLonPoint.nearest, to find nearest N points to a
provided query point (Mike McCandless)
+* LUCENE-7234: Added InetAddressPoint.nextDown/nextUp to easily generate range
+ queries with excluded bounds. (Adrien Grand)
+
API Changes
* LUCENE-7184: Refactor LatLonPoint encoding methods to new GeoEncodingUtils
@@ -88,6 +91,11 @@ Bug Fixes
match the underlying queries' (lower|upper)Term optionality logic.
(Kaneshanathan Srivisagan, Christine Poerschke)
+* LUCENE-7209: Fixed explanations of FunctionScoreQuery. (Adrien Grand)
+
+* LUCENE-7232: Fixed InetAddressPoint.newPrefixQuery, which was generating an
+ incorrect query when the prefix length was not a multiple of 8. (Adrien Grand)
+
Documentation
* LUCENE-7223: Improve XXXPoint javadocs to make it clear that you
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionQuery.java b/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionQuery.java
index 6f9ecd8dd39..85eac268dfd 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionQuery.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionQuery.java
@@ -55,7 +55,7 @@ public class FunctionQuery extends Query {
protected class FunctionWeight extends Weight {
protected final IndexSearcher searcher;
- protected float queryNorm = 1f;
+ protected float queryNorm, boost, queryWeight;
protected final Map context;
public FunctionWeight(IndexSearcher searcher) throws IOException {
@@ -63,6 +63,7 @@ public class FunctionQuery extends Query {
this.searcher = searcher;
this.context = ValueSource.newContext(searcher);
func.createWeight(context, searcher);
+ normalize(1f, 1f);;
}
@Override
@@ -70,22 +71,24 @@ public class FunctionQuery extends Query {
@Override
public float getValueForNormalization() throws IOException {
- return queryNorm * queryNorm;
+ return queryWeight * queryWeight;
}
@Override
public void normalize(float norm, float boost) {
- this.queryNorm = norm * boost;
+ this.queryNorm = norm;
+ this.boost = boost;
+ this.queryWeight = norm * boost;
}
@Override
public Scorer scorer(LeafReaderContext context) throws IOException {
- return new AllScorer(context, this, queryNorm);
+ return new AllScorer(context, this, queryWeight);
}
@Override
public Explanation explain(LeafReaderContext context, int doc) throws IOException {
- return ((AllScorer)scorer(context)).explain(doc, queryNorm);
+ return ((AllScorer)scorer(context)).explain(doc);
}
}
@@ -132,13 +135,13 @@ public class FunctionQuery extends Query {
return 1;
}
- public Explanation explain(int doc, float queryNorm) throws IOException {
+ public Explanation explain(int doc) throws IOException {
float sc = qWeight * vals.floatVal(doc);
return Explanation.match(sc, "FunctionQuery(" + func + "), product of:",
vals.explain(doc),
- Explanation.match(queryNorm, "boost"),
- Explanation.match(weight.queryNorm = 1f, "queryNorm"));
+ Explanation.match(weight.boost, "boost"),
+ Explanation.match(weight.queryNorm, "queryNorm"));
}
}
diff --git a/lucene/queries/src/test/org/apache/lucene/queries/TestCustomScoreExplanations.java b/lucene/queries/src/test/org/apache/lucene/queries/TestCustomScoreExplanations.java
index fc649984523..9ab90a4a0b7 100644
--- a/lucene/queries/src/test/org/apache/lucene/queries/TestCustomScoreExplanations.java
+++ b/lucene/queries/src/test/org/apache/lucene/queries/TestCustomScoreExplanations.java
@@ -16,6 +16,8 @@
*/
package org.apache.lucene.queries;
+import java.io.IOException;
+
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.function.FunctionQuery;
import org.apache.lucene.queries.function.valuesource.ConstValueSource;
@@ -23,9 +25,14 @@ import org.apache.lucene.search.BaseExplanationTestCase;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery;
+import org.apache.lucene.search.Explanation;
+import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.similarities.BM25Similarity;
+import org.apache.lucene.search.similarities.ClassicSimilarity;
+import org.apache.lucene.search.similarities.Similarity;
public class TestCustomScoreExplanations extends BaseExplanationTestCase {
public void testOneTerm() throws Exception {
@@ -49,4 +56,43 @@ public class TestCustomScoreExplanations extends BaseExplanationTestCase {
BooleanQuery bq = bqB.build();
qtest(new BoostQuery(bq, 6), new int[] { 0,1,2,3 });
}
+
+ public void testSubExplanations() throws IOException {
+ Query query = new FunctionQuery(new ConstValueSource(5));
+ IndexSearcher searcher = newSearcher(BaseExplanationTestCase.searcher.getIndexReader());
+ searcher.setSimilarity(new BM25Similarity());
+
+ Explanation expl = searcher.explain(query, 0);
+ // function
+ assertEquals(5f, expl.getDetails()[0].getValue(), 0f);
+ // boost
+ assertEquals("boost", expl.getDetails()[1].getDescription());
+ assertEquals(1f, expl.getDetails()[1].getValue(), 0f);
+ // norm
+ assertEquals("queryNorm", expl.getDetails()[2].getDescription());
+ assertEquals(1f, expl.getDetails()[2].getValue(), 0f);
+
+ query = new BoostQuery(query, 2);
+ expl = searcher.explain(query, 0);
+ // function
+ assertEquals(5f, expl.getDetails()[0].getValue(), 0f);
+ // boost
+ assertEquals("boost", expl.getDetails()[1].getDescription());
+ assertEquals(2f, expl.getDetails()[1].getValue(), 0f);
+ // norm
+ assertEquals("queryNorm", expl.getDetails()[2].getDescription());
+ assertEquals(1f, expl.getDetails()[2].getValue(), 0f);
+
+ searcher.setSimilarity(new ClassicSimilarity()); // in order to have a queryNorm != 1
+ expl = searcher.explain(query, 0);
+ // function
+ assertEquals(5f, expl.getDetails()[0].getValue(), 0f);
+ // boost
+ assertEquals("boost", expl.getDetails()[1].getDescription());
+ assertEquals(2f, expl.getDetails()[1].getValue(), 0f);
+ // norm
+ assertEquals("queryNorm", expl.getDetails()[2].getDescription());
+ assertEquals(0.5f, expl.getDetails()[2].getValue(), 0f);
+ }
}
+
diff --git a/lucene/sandbox/src/java/org/apache/lucene/document/InetAddressPoint.java b/lucene/sandbox/src/java/org/apache/lucene/document/InetAddressPoint.java
index 7ebabab02eb..88684f6bec1 100644
--- a/lucene/sandbox/src/java/org/apache/lucene/document/InetAddressPoint.java
+++ b/lucene/sandbox/src/java/org/apache/lucene/document/InetAddressPoint.java
@@ -26,6 +26,7 @@ import org.apache.lucene.search.PointInSetQuery;
import org.apache.lucene.search.PointRangeQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.NumericUtils;
import org.apache.lucene.util.StringHelper;
/**
@@ -65,6 +66,53 @@ public class InetAddressPoint extends Field {
TYPE.freeze();
}
+ /** The minimum value that an ip address can hold. */
+ public static final InetAddress MIN_VALUE;
+ /** The maximum value that an ip address can hold. */
+ public static final InetAddress MAX_VALUE;
+ static {
+ MIN_VALUE = decode(new byte[BYTES]);
+ byte[] maxValueBytes = new byte[BYTES];
+ Arrays.fill(maxValueBytes, (byte) 0xFF);
+ MAX_VALUE = decode(maxValueBytes);
+ }
+
+ /**
+ * Return the {@link InetAddress} that compares immediately greater than
+ * {@code address}.
+ * @throws ArithmeticException if the provided address is the
+ * {@link #MAX_VALUE maximum ip address}
+ */
+ public static InetAddress nextUp(InetAddress address) {
+ if (address.equals(MAX_VALUE)) {
+ throw new ArithmeticException("Overflow: there is no greater InetAddress than "
+ + address.getHostAddress());
+ }
+ byte[] delta = new byte[BYTES];
+ delta[BYTES-1] = 1;
+ byte[] nextUpBytes = new byte[InetAddressPoint.BYTES];
+ NumericUtils.add(InetAddressPoint.BYTES, 0, encode(address), delta, nextUpBytes);
+ return decode(nextUpBytes);
+ }
+
+ /**
+ * Return the {@link InetAddress} that compares immediately less than
+ * {@code address}.
+ * @throws ArithmeticException if the provided address is the
+ * {@link #MIN_VALUE minimum ip address}
+ */
+ public static InetAddress nextDown(InetAddress address) {
+ if (address.equals(MIN_VALUE)) {
+ throw new ArithmeticException("Underflow: there is no smaller InetAddress than "
+ + address.getHostAddress());
+ }
+ byte[] delta = new byte[BYTES];
+ delta[BYTES-1] = 1;
+ byte[] nextDownBytes = new byte[InetAddressPoint.BYTES];
+ NumericUtils.subtract(InetAddressPoint.BYTES, 0, encode(address), delta, nextDownBytes);
+ return decode(nextDownBytes);
+ }
+
/** Change the values of this field */
public void setInetAddressValue(InetAddress value) {
if (value == null) {
@@ -174,8 +222,9 @@ public class InetAddressPoint extends Field {
byte lower[] = value.getAddress();
byte upper[] = value.getAddress();
for (int i = prefixLength; i < 8 * lower.length; i++) {
- lower[i >> 3] &= ~(1 << (i & 7));
- upper[i >> 3] |= 1 << (i & 7);
+ int m = 1 << (7 - (i & 7));
+ lower[i >> 3] &= ~m;
+ upper[i >> 3] |= m;
}
try {
return newRangeQuery(field, InetAddress.getByAddress(lower), InetAddress.getByAddress(upper));
@@ -186,6 +235,12 @@ public class InetAddressPoint extends Field {
/**
* Create a range query for network addresses.
+ *
+ * You can have half-open ranges (which are in fact </≤ or >/≥ queries)
+ * by setting {@code lowerValue = InetAddressPoint.MIN_VALUE} or
+ * {@code upperValue = InetAddressPoint.MAX_VALUE}.
+ *
Ranges are inclusive. For exclusive ranges, pass {@code InetAddressPoint#nextUp(lowerValue)}
+ * or {@code InetAddressPoint#nexDown(upperValue)}.
*
* @param field field name. must not be {@code null}.
* @param lowerValue lower portion of the range (inclusive). must not be null.
diff --git a/lucene/sandbox/src/test/org/apache/lucene/document/TestInetAddressPoint.java b/lucene/sandbox/src/test/org/apache/lucene/document/TestInetAddressPoint.java
index 673ee296a48..0e0901be64b 100644
--- a/lucene/sandbox/src/test/org/apache/lucene/document/TestInetAddressPoint.java
+++ b/lucene/sandbox/src/test/org/apache/lucene/document/TestInetAddressPoint.java
@@ -119,4 +119,58 @@ public class TestInetAddressPoint extends LuceneTestCase {
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(InetAddressPoint.newSetQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.7"))));
}
+
+ public void testPrefixQuery() throws Exception {
+ assertEquals(
+ InetAddressPoint.newRangeQuery("a", InetAddress.getByName("1.2.3.0"), InetAddress.getByName("1.2.3.255")),
+ InetAddressPoint.newPrefixQuery("a", InetAddress.getByName("1.2.3.127"), 24));
+ assertEquals(
+ InetAddressPoint.newRangeQuery("a", InetAddress.getByName("1.2.3.128"), InetAddress.getByName("1.2.3.255")),
+ InetAddressPoint.newPrefixQuery("a", InetAddress.getByName("1.2.3.213"), 25));
+ assertEquals(
+ InetAddressPoint.newRangeQuery("a", InetAddress.getByName("2001::a000:0"), InetAddress.getByName("2001::afff:ffff")),
+ InetAddressPoint.newPrefixQuery("a", InetAddress.getByName("2001::a6bd:fc80"), 100));
+ }
+
+ public void testNextUp() throws Exception {
+ assertEquals(InetAddress.getByName("::1"),
+ InetAddressPoint.nextUp(InetAddress.getByName("::")));
+
+ assertEquals(InetAddress.getByName("::1:0"),
+ InetAddressPoint.nextUp(InetAddress.getByName("::ffff")));
+
+ assertEquals(InetAddress.getByName("1.2.4.0"),
+ InetAddressPoint.nextUp(InetAddress.getByName("1.2.3.255")));
+
+ assertEquals(InetAddress.getByName("0.0.0.0"),
+ InetAddressPoint.nextUp(InetAddress.getByName("::fffe:ffff:ffff")));
+
+ assertEquals(InetAddress.getByName("::1:0:0:0"),
+ InetAddressPoint.nextUp(InetAddress.getByName("255.255.255.255")));
+
+ ArithmeticException e = expectThrows(ArithmeticException.class,
+ () -> InetAddressPoint.nextUp(InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")));
+ assertEquals("Overflow: there is no greater InetAddress than ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", e.getMessage());
+ }
+
+ public void testNextDown() throws Exception {
+ assertEquals(InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe"),
+ InetAddressPoint.nextDown(InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")));
+
+ assertEquals(InetAddress.getByName("::ffff"),
+ InetAddressPoint.nextDown(InetAddress.getByName("::1:0")));
+
+ assertEquals(InetAddress.getByName("1.2.3.255"),
+ InetAddressPoint.nextDown(InetAddress.getByName("1.2.4.0")));
+
+ assertEquals(InetAddress.getByName("::fffe:ffff:ffff"),
+ InetAddressPoint.nextDown(InetAddress.getByName("0.0.0.0")));
+
+ assertEquals(InetAddress.getByName("255.255.255.255"),
+ InetAddressPoint.nextDown(InetAddress.getByName("::1:0:0:0")));
+
+ ArithmeticException e = expectThrows(ArithmeticException.class,
+ () -> InetAddressPoint.nextDown(InetAddress.getByName("::")));
+ assertEquals("Underflow: there is no smaller InetAddress than 0:0:0:0:0:0:0:0", e.getMessage());
+ }
}
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 89eb91f7c95..31ae74c9b87 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -103,6 +103,13 @@ New Features
* SOLR-8918: Adds Streaming to the admin page under the collections section. Includes
ability to see graphically the expression explanation (Dennis Gove)
+
+* SOLR-8913: When using a shared filesystem we should store data dir and tlog dir locations in
+ the cluster state. (Mark Miller)
+
+* SOLR-8809: Implement Connection.prepareStatement (Kevin Risden)
+
+* SOLR-9020: Implement StatementImpl/ResultSetImpl get/set fetch* methods and proper errors for traversal methods (Kevin Risden)
Bug Fixes
----------------------
@@ -158,6 +165,8 @@ Optimizations
* SOLR-8937: bin/post (SimplePostTool) now streams the standard input instead of buffering fully.
(David Smiley)
+* SOLR-8973: Zookeeper frenzy when a core is first created. (Janmejay Singh, Scott Blum, shalin)
+
Other Changes
----------------------
* SOLR-7516: Improve javadocs for JavaBinCodec, ObjectResolver and enforce the single-usage policy.
@@ -188,6 +197,10 @@ Other Changes
* SOLR-8985: Added back support for 'includeDynamic' flag to /schema/fields endpoint (noble)
+* SOLR-9015: Adds SelectStream as a default function in the StreamHandler (Dennis Gove)
+
+* SOLR-8929: Add an idea module for solr/server to enable launching start.jar (Scott Blum, Steve Rowe)
+
================== 6.0.0 ==================
Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this release
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 ab9422d8ead..3afc3b99892 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ZkController.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ZkController.java
@@ -1165,9 +1165,8 @@ public final class ZkController {
if (coreNodeName != null) {
props.put(ZkStateReader.CORE_NODE_NAME_PROP, coreNodeName);
}
-
- if (ClusterStateUtil.isAutoAddReplicas(getZkStateReader(), collection)) {
- try (SolrCore core = cc.getCore(cd.getName())) {
+ try (SolrCore core = cc.getCore(cd.getName())) {
+ if (core != null && core.getDirectoryFactory().isSharedStorage()) {
if (core != null && core.getDirectoryFactory().isSharedStorage()) {
props.put("dataDir", core.getDataDir());
UpdateLog ulog = core.getUpdateHandler().getUpdateLog();
@@ -1478,11 +1477,13 @@ public final class ZkController {
}
publish(cd, Replica.State.DOWN, false, true);
- DocCollection collection = zkStateReader.getClusterState().getCollectionOrNull(cd.getCloudDescriptor().getCollectionName());
- if (collection != null) {
- log.info("Registering watch for collection {}", cd.getCloudDescriptor().getCollectionName());
- zkStateReader.addCollectionWatch(cd.getCloudDescriptor().getCollectionName());
- }
+ String collectionName = cd.getCloudDescriptor().getCollectionName();
+ DocCollection collection = zkStateReader.getClusterState().getCollectionOrNull(collectionName);
+ log.info(collection == null ?
+ "Collection {} not visible yet, but flagging it so a watch is registered when it becomes visible" :
+ "Registering watch for collection {}",
+ collectionName);
+ zkStateReader.addCollectionWatch(collectionName);
} catch (KeeperException e) {
log.error("", e);
throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR, "", e);
diff --git a/solr/core/src/java/org/apache/solr/handler/StreamHandler.java b/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
index 6922fc490df..65e5834362b 100644
--- a/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
@@ -121,10 +121,11 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
.withFunctionName("outerHashJoin", OuterHashJoinStream.class)
.withFunctionName("intersect", IntersectStream.class)
.withFunctionName("complement", ComplementStream.class)
- .withFunctionName("sort", SortStream.class)
- .withFunctionName("daemon", DaemonStream.class)
- .withFunctionName("shortestPath", ShortestPathStream.class)
- .withFunctionName("gatherNodes", GatherNodesStream.class)
+ .withFunctionName("sort", SortStream.class)
+ .withFunctionName("daemon", DaemonStream.class)
+ .withFunctionName("shortestPath", ShortestPathStream.class)
+ .withFunctionName("gatherNodes", GatherNodesStream.class)
+ .withFunctionName("select", SelectStream.class)
// metrics
.withFunctionName("min", MinMetric.class)
diff --git a/solr/core/src/test/org/apache/solr/cloud/hdfs/StressHdfsTest.java b/solr/core/src/test/org/apache/solr/cloud/hdfs/StressHdfsTest.java
index aeb4cb7803c..b2dba108f3f 100644
--- a/solr/core/src/test/org/apache/solr/cloud/hdfs/StressHdfsTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/hdfs/StressHdfsTest.java
@@ -32,6 +32,9 @@ import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.request.QueryRequest;
import org.apache.solr.cloud.BasicDistributedZkTest;
import org.apache.solr.cloud.ChaosMonkey;
+import org.apache.solr.common.cloud.ClusterState;
+import org.apache.solr.common.cloud.Replica;
+import org.apache.solr.common.cloud.Slice;
import org.apache.solr.common.params.CollectionParams.CollectionAction;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.util.NamedList;
@@ -46,6 +49,7 @@ import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
@@ -106,7 +110,7 @@ public class StressHdfsTest extends BasicDistributedZkTest {
createCollection(DELETE_DATA_DIR_COLLECTION, 1, 1, 1);
waitForRecoveriesToFinish(DELETE_DATA_DIR_COLLECTION, false);
-
+
ChaosMonkey.stop(jettys.get(0));
// enter safe mode and restart a node
@@ -153,6 +157,17 @@ public class StressHdfsTest extends BasicDistributedZkTest {
createCollection(DELETE_DATA_DIR_COLLECTION, nShards, rep, maxReplicasPerNode);
waitForRecoveriesToFinish(DELETE_DATA_DIR_COLLECTION, false);
+
+ // data dirs should be in zk, SOLR-8913
+ ClusterState clusterState = cloudClient.getZkStateReader().getClusterState();
+ Slice slice = clusterState.getSlice(DELETE_DATA_DIR_COLLECTION, "shard1");
+ assertNotNull(clusterState.getSlices(DELETE_DATA_DIR_COLLECTION).toString(), slice);
+ Collection replicas = slice.getReplicas();
+ for (Replica replica : replicas) {
+ assertNotNull(replica.getProperties().toString(), replica.get("dataDir"));
+ assertNotNull(replica.getProperties().toString(), replica.get("ulogDir"));
+ }
+
cloudClient.setDefaultCollection(DELETE_DATA_DIR_COLLECTION);
cloudClient.getZkStateReader().forceUpdateCollection(DELETE_DATA_DIR_COLLECTION);
diff --git a/solr/core/src/test/org/apache/solr/cloud/overseer/ZkStateReaderTest.java b/solr/core/src/test/org/apache/solr/cloud/overseer/ZkStateReaderTest.java
index 8581995d5e9..fd8d4939176 100644
--- a/solr/core/src/test/org/apache/solr/cloud/overseer/ZkStateReaderTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/overseer/ZkStateReaderTest.java
@@ -26,6 +26,7 @@ import org.apache.solr.cloud.Overseer;
import org.apache.solr.cloud.OverseerTest;
import org.apache.solr.cloud.ZkController;
import org.apache.solr.cloud.ZkTestServer;
+import org.apache.solr.common.cloud.ClusterState;
import org.apache.solr.common.cloud.DocCollection;
import org.apache.solr.common.cloud.DocRouter;
import org.apache.solr.common.cloud.Slice;
@@ -179,4 +180,63 @@ public class ZkStateReaderTest extends SolrTestCaseJ4 {
server.shutdown();
}
}
+
+ public void testWatchedCollectionCreation() throws Exception {
+ String zkDir = createTempDir("testWatchedCollectionCreation").toFile().getAbsolutePath();
+
+ ZkTestServer server = new ZkTestServer(zkDir);
+
+ SolrZkClient zkClient = null;
+
+ try {
+ server.run();
+ AbstractZkTestCase.tryCleanSolrZkNode(server.getZkHost());
+ AbstractZkTestCase.makeSolrZkNode(server.getZkHost());
+
+ zkClient = new SolrZkClient(server.getZkAddress(), OverseerTest.DEFAULT_CONNECTION_TIMEOUT);
+ ZkController.createClusterZkNodes(zkClient);
+
+ ZkStateReader reader = new ZkStateReader(zkClient);
+ reader.createClusterStateWatchersAndUpdate();
+ reader.addCollectionWatch("c1");
+
+ // Initially there should be no c1 collection.
+ assertNull(reader.getClusterState().getCollectionRef("c1"));
+
+ zkClient.makePath(ZkStateReader.COLLECTIONS_ZKNODE + "/c1", true);
+ reader.forceUpdateCollection("c1");
+
+ // Still no c1 collection, despite a collection path.
+ assertNull(reader.getClusterState().getCollectionRef("c1"));
+
+ ZkStateWriter writer = new ZkStateWriter(reader, new Overseer.Stats());
+
+
+ // create new collection with stateFormat = 2
+ DocCollection state = new DocCollection("c1", new HashMap(), new HashMap(), DocRouter.DEFAULT, 0, ZkStateReader.CLUSTER_STATE + "/c1/state.json");
+ ZkWriteCommand wc = new ZkWriteCommand("c1", state);
+ writer.enqueueUpdate(reader.getClusterState(), wc, null);
+ writer.writePendingUpdates();
+
+ assertTrue(zkClient.exists(ZkStateReader.COLLECTIONS_ZKNODE + "/c1/state.json", true));
+
+ //reader.forceUpdateCollection("c1");
+
+ for (int i = 0; i < 100; ++i) {
+ Thread.sleep(50);
+ ClusterState.CollectionRef ref = reader.getClusterState().getCollectionRef("c1");
+ if (ref != null) {
+ break;
+ }
+ }
+ ClusterState.CollectionRef ref = reader.getClusterState().getCollectionRef("c1");
+ assertNotNull(ref);
+ assertFalse(ref.isLazilyLoaded());
+ assertEquals(2, ref.get().getStateFormat());
+ } finally {
+ IOUtils.close(zkClient);
+ server.shutdown();
+
+ }
+ }
}
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/ConnectionImpl.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/ConnectionImpl.java
index aa78e14ecb5..5139527f181 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/ConnectionImpl.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/ConnectionImpl.java
@@ -88,17 +88,17 @@ class ConnectionImpl implements Connection {
@Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
- return null;
+ return new PreparedStatementImpl(this, sql);
}
@Override
public CallableStatement prepareCall(String sql) throws SQLException {
- return null;
+ throw new UnsupportedOperationException();
}
@Override
public String nativeSQL(String sql) throws SQLException {
- return null;
+ throw new UnsupportedOperationException();
}
@Override
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/PreparedStatementImpl.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/PreparedStatementImpl.java
new file mode 100644
index 00000000000..b3e7c9ec81d
--- /dev/null
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/PreparedStatementImpl.java
@@ -0,0 +1,394 @@
+/*
+ * 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.client.solrj.io.sql;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+import java.sql.NClob;
+import java.sql.ParameterMetaData;
+import java.sql.PreparedStatement;
+import java.sql.Ref;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.RowId;
+import java.sql.SQLException;
+import java.sql.SQLXML;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+
+class PreparedStatementImpl extends StatementImpl implements PreparedStatement {
+ private final String sql;
+
+ PreparedStatementImpl(ConnectionImpl connection, String sql) {
+ super(connection);
+ this.sql = sql;
+ }
+
+ @Override
+ public ResultSet executeQuery() throws SQLException {
+ return super.executeQuery(this.sql);
+ }
+
+ @Override
+ public int executeUpdate() throws SQLException {
+ return super.executeUpdate(this.sql);
+ }
+
+ @Override
+ public boolean execute() throws SQLException {
+ return super.execute(this.sql);
+ }
+
+ @Override
+ public void clearParameters() throws SQLException {
+
+ }
+
+ @Override
+ public ResultSetMetaData getMetaData() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ParameterMetaData getParameterMetaData() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void addBatch() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setNull(int parameterIndex, int sqlType) throws SQLException {
+
+ }
+
+ @Override
+ public void setBoolean(int parameterIndex, boolean x) throws SQLException {
+
+ }
+
+ @Override
+ public void setByte(int parameterIndex, byte x) throws SQLException {
+
+ }
+
+ @Override
+ public void setShort(int parameterIndex, short x) throws SQLException {
+
+ }
+
+ @Override
+ public void setInt(int parameterIndex, int x) throws SQLException {
+
+ }
+
+ @Override
+ public void setLong(int parameterIndex, long x) throws SQLException {
+
+ }
+
+ @Override
+ public void setFloat(int parameterIndex, float x) throws SQLException {
+
+ }
+
+ @Override
+ public void setDouble(int parameterIndex, double x) throws SQLException {
+
+ }
+
+ @Override
+ public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {
+
+ }
+
+ @Override
+ public void setString(int parameterIndex, String x) throws SQLException {
+
+ }
+
+ @Override
+ public void setBytes(int parameterIndex, byte[] x) throws SQLException {
+
+ }
+
+ @Override
+ public void setDate(int parameterIndex, Date x) throws SQLException {
+
+ }
+
+ @Override
+ public void setTime(int parameterIndex, Time x) throws SQLException {
+
+ }
+
+ @Override
+ public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {
+
+ }
+
+ @Override
+ public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {
+
+ }
+
+ @Override
+ public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {
+
+ }
+
+ @Override
+ public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {
+
+ }
+
+ @Override
+ public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {
+
+ }
+
+ @Override
+ public void setObject(int parameterIndex, Object x) throws SQLException {
+
+ }
+
+ @Override
+ public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException {
+
+ }
+
+ @Override
+ public void setRef(int parameterIndex, Ref x) throws SQLException {
+
+ }
+
+ @Override
+ public void setBlob(int parameterIndex, Blob x) throws SQLException {
+
+ }
+
+ @Override
+ public void setClob(int parameterIndex, Clob x) throws SQLException {
+
+ }
+
+ @Override
+ public void setArray(int parameterIndex, Array x) throws SQLException {
+
+ }
+
+ @Override
+ public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {
+
+ }
+
+ @Override
+ public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {
+
+ }
+
+ @Override
+ public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {
+
+ }
+
+ @Override
+ public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException {
+
+ }
+
+ @Override
+ public void setURL(int parameterIndex, URL x) throws SQLException {
+
+ }
+
+ @Override
+ public void setRowId(int parameterIndex, RowId x) throws SQLException {
+
+ }
+
+ @Override
+ public void setNString(int parameterIndex, String value) throws SQLException {
+
+ }
+
+ @Override
+ public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException {
+
+ }
+
+ @Override
+ public void setNClob(int parameterIndex, NClob value) throws SQLException {
+
+ }
+
+ @Override
+ public void setClob(int parameterIndex, Reader reader, long length) throws SQLException {
+
+ }
+
+ @Override
+ public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException {
+
+ }
+
+ @Override
+ public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException {
+
+ }
+
+ @Override
+ public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
+
+ }
+
+ @Override
+ public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException {
+
+ }
+
+ @Override
+ public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {
+
+ }
+
+ @Override
+ public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException {
+
+ }
+
+ @Override
+ public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException {
+
+ }
+
+ @Override
+ public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {
+
+ }
+
+ @Override
+ public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {
+
+ }
+
+ @Override
+ public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {
+
+ }
+
+ @Override
+ public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
+
+ }
+
+ @Override
+ public void setClob(int parameterIndex, Reader reader) throws SQLException {
+
+ }
+
+ @Override
+ public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {
+
+ }
+
+ @Override
+ public void setNClob(int parameterIndex, Reader reader) throws SQLException {
+
+ }
+
+ // Methods below cannot be called from a PreparedStatement based on JDBC spec
+
+ @Override
+ public ResultSet executeQuery(String sql) throws SQLException {
+ throw new SQLException("Cannot be called from PreparedStatement");
+ }
+
+ @Override
+ public int executeUpdate(String sql) throws SQLException {
+ throw new SQLException("Cannot be called from PreparedStatement");
+ }
+
+ @Override
+ public boolean execute(String sql) throws SQLException {
+ throw new SQLException("Cannot be called from PreparedStatement");
+ }
+
+ @Override
+ public void addBatch( String sql ) throws SQLException {
+ throw new SQLException("Cannot be called from PreparedStatement");
+ }
+
+ @Override
+ public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
+ throw new SQLException("Cannot be called from PreparedStatement");
+ }
+
+ @Override
+ public int executeUpdate(String sql, int columnIndexes[]) throws SQLException {
+ throw new SQLException("Cannot be called from PreparedStatement");
+ }
+
+ @Override
+ public int executeUpdate(String sql, String columnNames[]) throws SQLException {
+ throw new SQLException("Cannot be called from PreparedStatement");
+ }
+
+ @Override
+ public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
+ throw new SQLException("Cannot be called from PreparedStatement");
+ }
+
+ @Override
+ public boolean execute(String sql, int columnIndexes[]) throws SQLException {
+ throw new SQLException("Cannot be called from PreparedStatement");
+ }
+
+ @Override
+ public boolean execute(String sql, String columnNames[]) throws SQLException {
+ throw new SQLException("Cannot be called from PreparedStatement");
+ }
+
+ @Override
+ public long executeLargeUpdate(String sql) throws SQLException {
+ throw new SQLException("Cannot be called from PreparedStatement");
+ }
+
+ @Override
+ public long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
+ throw new SQLException("Cannot be called from PreparedStatement");
+ }
+
+ @Override
+ public long executeLargeUpdate(String sql, int columnIndexes[]) throws SQLException {
+ throw new SQLException("Cannot be called from PreparedStatement");
+ }
+
+ @Override
+ public long executeLargeUpdate(String sql, String columnNames[]) throws SQLException {
+ throw new SQLException("Cannot be called from PreparedStatement");
+ }
+}
\ No newline at end of file
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/ResultSetImpl.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/ResultSetImpl.java
index e4dcaed8200..91b99b9b837 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/ResultSetImpl.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/ResultSetImpl.java
@@ -31,6 +31,7 @@ import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.RowId;
import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Statement;
@@ -480,92 +481,133 @@ class ResultSetImpl implements ResultSet {
@Override
public boolean isBeforeFirst() throws SQLException {
- throw new UnsupportedOperationException();
+ checkClosed();
+
+ throw new SQLFeatureNotSupportedException();
}
@Override
public boolean isAfterLast() throws SQLException {
- throw new UnsupportedOperationException();
+ checkClosed();
+
+ throw new SQLFeatureNotSupportedException();
}
@Override
public boolean isFirst() throws SQLException {
- throw new UnsupportedOperationException();
+ checkClosed();
+
+ throw new SQLFeatureNotSupportedException();
}
@Override
public boolean isLast() throws SQLException {
- throw new UnsupportedOperationException();
+ checkClosed();
+
+ throw new SQLFeatureNotSupportedException();
}
@Override
public void beforeFirst() throws SQLException {
- throw new UnsupportedOperationException();
+ checkClosed();
+
+ throw new SQLException("beforeFirst() not supported on ResultSet with type TYPE_FORWARD_ONLY");
}
@Override
public void afterLast() throws SQLException {
- throw new UnsupportedOperationException();
+ checkClosed();
+
+ throw new SQLException("afterLast() not supported on ResultSet with type TYPE_FORWARD_ONLY");
}
@Override
public boolean first() throws SQLException {
- throw new UnsupportedOperationException();
+ checkClosed();
+
+ throw new SQLException("first() not supported on ResultSet with type TYPE_FORWARD_ONLY");
}
@Override
public boolean last() throws SQLException {
- throw new UnsupportedOperationException();
+ checkClosed();
+
+ throw new SQLException("last() not supported on ResultSet with type TYPE_FORWARD_ONLY");
}
@Override
public int getRow() throws SQLException {
- throw new UnsupportedOperationException();
+ checkClosed();
+
+ throw new SQLFeatureNotSupportedException();
}
@Override
public boolean absolute(int row) throws SQLException {
- throw new UnsupportedOperationException();
+ checkClosed();
+
+ throw new SQLException("absolute() not supported on ResultSet with type TYPE_FORWARD_ONLY");
}
@Override
public boolean relative(int rows) throws SQLException {
- throw new UnsupportedOperationException();
+ checkClosed();
+
+ throw new SQLException("relative() not supported on ResultSet with type TYPE_FORWARD_ONLY");
}
@Override
public boolean previous() throws SQLException {
- throw new UnsupportedOperationException();
+ checkClosed();
+
+ throw new SQLException("previous() not supported on ResultSet with type TYPE_FORWARD_ONLY");
}
@Override
public void setFetchDirection(int direction) throws SQLException {
- throw new UnsupportedOperationException();
+ checkClosed();
+
+ if(direction != ResultSet.FETCH_FORWARD) {
+ throw new SQLException("Direction must be FETCH_FORWARD since ResultSet " +
+ "type is TYPE_FORWARD_ONLY");
+ }
}
@Override
public int getFetchDirection() throws SQLException {
- throw new UnsupportedOperationException();
+ checkClosed();
+
+ return ResultSet.FETCH_FORWARD;
}
@Override
public void setFetchSize(int rows) throws SQLException {
- throw new UnsupportedOperationException();
+ checkClosed();
+
+ if(rows < 0) {
+ throw new SQLException("Rows must be >= 0");
+ }
}
@Override
public int getFetchSize() throws SQLException {
- throw new UnsupportedOperationException();
+ checkClosed();
+
+ return 0;
}
@Override
public int getType() throws SQLException {
+ checkClosed();
+
return ResultSet.TYPE_FORWARD_ONLY;
}
@Override
public int getConcurrency() throws SQLException {
- throw new UnsupportedOperationException();
+ checkClosed();
+
+ return ResultSet.CONCUR_READ_ONLY;
}
@Override
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/StatementImpl.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/StatementImpl.java
index 6af58dae527..1b1200d2842 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/StatementImpl.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/StatementImpl.java
@@ -51,8 +51,13 @@ class StatementImpl implements Statement {
this.connection = connection;
}
- @Override
- public ResultSet executeQuery(String sql) throws SQLException {
+ private void checkClosed() throws SQLException {
+ if(isClosed()) {
+ throw new SQLException("Statement is closed.");
+ }
+ }
+
+ private ResultSet executeQueryImpl(String sql) throws SQLException {
try {
if(this.currentResultSet != null) {
this.currentResultSet.close();
@@ -107,6 +112,11 @@ class StatementImpl implements Statement {
}
}
+ @Override
+ public ResultSet executeQuery(String sql) throws SQLException {
+ return this.executeQueryImpl(sql);
+ }
+
@Override
public int executeUpdate(String sql) throws SQLException {
return 0;
@@ -167,18 +177,14 @@ class StatementImpl implements Statement {
@Override
public SQLWarning getWarnings() throws SQLException {
- if(isClosed()) {
- throw new SQLException("Statement is closed.");
- }
+ checkClosed();
return this.currentWarning;
}
@Override
public void clearWarnings() throws SQLException {
- if(isClosed()) {
- throw new SQLException("Statement is closed.");
- }
+ checkClosed();
this.currentWarning = null;
}
@@ -203,14 +209,12 @@ class StatementImpl implements Statement {
@Override
public ResultSet getResultSet() throws SQLException {
- return this.executeQuery(this.currentSQL);
+ return this.executeQueryImpl(this.currentSQL);
}
@Override
public int getUpdateCount() throws SQLException {
- if(isClosed()) {
- throw new SQLException("Statement is closed");
- }
+ checkClosed();
// TODO Add logic when update statements are added to JDBC.
return -1;
@@ -218,9 +222,7 @@ class StatementImpl implements Statement {
@Override
public boolean getMoreResults() throws SQLException {
- if(isClosed()) {
- throw new SQLException("Statement is closed");
- }
+ checkClosed();
// Currently multiple result sets are not possible yet
this.currentResultSet.close();
@@ -229,32 +231,48 @@ class StatementImpl implements Statement {
@Override
public void setFetchDirection(int direction) throws SQLException {
- throw new UnsupportedOperationException();
+ checkClosed();
+
+ if(direction != ResultSet.FETCH_FORWARD) {
+ throw new SQLException("Direction must be ResultSet.FETCH_FORWARD currently");
+ }
}
@Override
public int getFetchDirection() throws SQLException {
- throw new UnsupportedOperationException();
+ checkClosed();
+
+ return ResultSet.FETCH_FORWARD;
}
@Override
public void setFetchSize(int rows) throws SQLException {
+ checkClosed();
+ if(rows < 0) {
+ throw new SQLException("Rows must be >= 0");
+ }
}
@Override
public int getFetchSize() throws SQLException {
+ checkClosed();
+
return 0;
}
@Override
public int getResultSetConcurrency() throws SQLException {
- throw new UnsupportedOperationException();
+ checkClosed();
+
+ return ResultSet.CONCUR_READ_ONLY;
}
@Override
public int getResultSetType() throws SQLException {
- throw new UnsupportedOperationException();
+ checkClosed();
+
+ return ResultSet.TYPE_FORWARD_ONLY;
}
@Override
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 e8d95c3c67e..c6f88c06b4b 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
@@ -443,13 +443,6 @@ public class ZkStateReader implements Closeable {
// To move a collection's state to format2, first create the new state2 format node, then remove legacy entry.
Map result = new LinkedHashMap<>(legacyCollectionStates);
- // Are there any interesting collections that disappeared from the legacy cluster state?
- for (String coll : interestingCollections) {
- if (!result.containsKey(coll) && !watchedCollectionStates.containsKey(coll)) {
- new StateWatcher(coll).refreshAndWatch(true);
- }
- }
-
// Add state format2 collections, but don't override legacy collection states.
for (Map.Entry entry : watchedCollectionStates.entrySet()) {
result.putIfAbsent(entry.getKey(), new ClusterState.CollectionRef(entry.getValue()));
@@ -1048,15 +1041,26 @@ public class ZkStateReader implements Closeable {
private DocCollection fetchCollectionState(String coll, Watcher watcher) throws KeeperException, InterruptedException {
String collectionPath = getCollectionPath(coll);
- try {
- Stat stat = new Stat();
- byte[] data = zkClient.getData(collectionPath, watcher, stat, true);
- ClusterState state = ClusterState.load(stat.getVersion(), data,
- Collections.emptySet(), collectionPath);
- ClusterState.CollectionRef collectionRef = state.getCollectionStates().get(coll);
- return collectionRef == null ? null : collectionRef.get();
- } catch (KeeperException.NoNodeException e) {
- return null;
+ while (true) {
+ try {
+ Stat stat = new Stat();
+ byte[] data = zkClient.getData(collectionPath, watcher, stat, true);
+ ClusterState state = ClusterState.load(stat.getVersion(), data,
+ Collections.emptySet(), collectionPath);
+ ClusterState.CollectionRef collectionRef = state.getCollectionStates().get(coll);
+ return collectionRef == null ? null : collectionRef.get();
+ } catch (KeeperException.NoNodeException e) {
+ if (watcher != null) {
+ // Leave an exists watch in place in case a state.json is created later.
+ Stat exists = zkClient.exists(collectionPath, watcher, true);
+ if (exists != null) {
+ // Rare race condition, we tried to fetch the data and couldn't find it, then we found it exists.
+ // Loop and try again.
+ continue;
+ }
+ }
+ return null;
+ }
}
}
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/io/sql/JdbcTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/io/sql/JdbcTest.java
index 200c971c4bf..90500927f26 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/io/sql/JdbcTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/io/sql/JdbcTest.java
@@ -20,6 +20,7 @@ import java.io.File;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
+import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
@@ -500,16 +501,9 @@ public class JdbcTest extends AbstractFullDistribZkTestBase {
con.clearWarnings();
assertNull(con.getWarnings());
+
try (Statement statement = con.createStatement()) {
- assertEquals(con, statement.getConnection());
-
- assertNull(statement.getWarnings());
- statement.clearWarnings();
- assertNull(statement.getWarnings());
-
- assertEquals(0, statement.getFetchSize());
- statement.setFetchSize(0);
- assertEquals(0, statement.getFetchSize());
+ checkStatement(con, statement);
try (ResultSet rs = statement.executeQuery(sql)) {
assertEquals(statement, rs.getStatement());
@@ -530,9 +524,51 @@ public class JdbcTest extends AbstractFullDistribZkTestBase {
assertFalse(statement.getMoreResults());
}
+
+ try (PreparedStatement statement = con.prepareStatement(sql)) {
+ checkStatement(con, statement);
+
+ try (ResultSet rs = statement.executeQuery()) {
+ assertEquals(statement, rs.getStatement());
+
+ checkResultSetMetadata(rs);
+ checkResultSet(rs);
+ }
+
+ assertTrue(statement.execute());
+ assertEquals(-1, statement.getUpdateCount());
+
+ try (ResultSet rs = statement.getResultSet()) {
+ assertEquals(statement, rs.getStatement());
+
+ checkResultSetMetadata(rs);
+ checkResultSet(rs);
+ }
+
+ assertFalse(statement.getMoreResults());
+ }
}
}
+ private void checkStatement(Connection con, Statement statement) throws Exception {
+ assertEquals(con, statement.getConnection());
+
+ assertNull(statement.getWarnings());
+ statement.clearWarnings();
+ assertNull(statement.getWarnings());
+
+ assertEquals(ResultSet.TYPE_FORWARD_ONLY, statement.getResultSetType());
+ assertEquals(ResultSet.CONCUR_READ_ONLY, statement.getResultSetConcurrency());
+
+ assertEquals(ResultSet.FETCH_FORWARD, statement.getFetchDirection());
+ statement.setFetchDirection(ResultSet.FETCH_FORWARD);
+ assertEquals(ResultSet.FETCH_FORWARD, statement.getFetchDirection());
+
+ assertEquals(0, statement.getFetchSize());
+ statement.setFetchSize(0);
+ assertEquals(0, statement.getFetchSize());
+ }
+
private void checkResultSetMetadata(ResultSet rs) throws Exception {
ResultSetMetaData resultSetMetaData = rs.getMetaData();
@@ -572,12 +608,21 @@ public class JdbcTest extends AbstractFullDistribZkTestBase {
}
private void checkResultSet(ResultSet rs) throws Exception {
- assertEquals(ResultSet.TYPE_FORWARD_ONLY, rs.getType());
-
assertNull(rs.getWarnings());
rs.clearWarnings();
assertNull(rs.getWarnings());
+ assertEquals(ResultSet.TYPE_FORWARD_ONLY, rs.getType());
+ assertEquals(ResultSet.CONCUR_READ_ONLY, rs.getConcurrency());
+
+ assertEquals(ResultSet.FETCH_FORWARD, rs.getFetchDirection());
+ rs.setFetchDirection(ResultSet.FETCH_FORWARD);
+ assertEquals(ResultSet.FETCH_FORWARD, rs.getFetchDirection());
+
+ assertEquals(0, rs.getFetchSize());
+ rs.setFetchSize(10);
+ assertEquals(0, rs.getFetchSize());
+
assertTrue(rs.next());
assertEquals(14L, rs.getObject("a_i"));
diff --git a/solr/webapp/web/css/angular/stream.css b/solr/webapp/web/css/angular/stream.css
index c007425316e..0ebb5924334 100644
--- a/solr/webapp/web/css/angular/stream.css
+++ b/solr/webapp/web/css/angular/stream.css
@@ -184,20 +184,20 @@ limitations under the License.
top: 2px;
}
-#content #stream #result #explanation #graph-content
+#content #stream #result #explanation #explanation-content
{
min-height: 50px;
width: 100%
}
-#content #stream #result #explanation #graph-content .node circle
+#content #stream #result #explanation #explanation-content .node circle
{
color: #c48f00;
stroke: #c48f00;
fill: #c48f00;
}
-#content #stream #result #explanation #graph-content .link
+#content #stream #result #explanation #explanation-content .link
{
fill: none;
stroke: #e0e0e0;
@@ -205,28 +205,28 @@ limitations under the License.
}
#content #stream #result #explanation #legend .datastore circle,
-#content #stream #result #explanation #graph-content .node.datastore circle
+#content #stream #result #explanation #explanation-content .node.datastore circle
{
stroke: #3800c4;
fill: #3800c4;
}
#content #stream #result #explanation #legend .stream-source circle,
-#content #stream #result #explanation #graph-content .node.stream-source circle
+#content #stream #result #explanation #explanation-content .node.stream-source circle
{
stroke: #21a9ec;
fill: #21a9ec;
}
#content #stream #result #explanation #legend .stream-decorator circle,
-#content #stream #result #explanation #graph-content .node.stream-decorator circle
+#content #stream #result #explanation #explanation-content .node.stream-decorator circle
{
stroke: #cb21ec;
fill: #cb21ec;
}
#content #stream #result #explanation #legend .graph-source circle,
-#content #stream #result #explanation #graph-content .node.graph-source circle
+#content #stream #result #explanation #explanation-content .node.graph-source circle
{
stroke: #21eca9;
fill: #21eca9;
diff --git a/solr/webapp/web/js/angular/controllers/stream.js b/solr/webapp/web/js/angular/controllers/stream.js
index f99f24f0376..7c3bcce83ca 100644
--- a/solr/webapp/web/js/angular/controllers/stream.js
+++ b/solr/webapp/web/js/angular/controllers/stream.js
@@ -29,8 +29,6 @@ solrAdminApp.controller('StreamController',
$scope.doStream = function() {
- // alert("doing stream")
-
var params = {};
params.core = $routeParams.core;
params.handler = $scope.qt;
@@ -51,7 +49,7 @@ solrAdminApp.controller('StreamController',
if (undefined != jsonData["explanation"]) {
$scope.showExplanation = true;
- graphSubController($scope, jsonData["explanation"])
+ streamGraphSubController($scope, jsonData["explanation"])
delete jsonData["explanation"]
} else {
$scope.showExplanation = false;
@@ -76,18 +74,10 @@ solrAdminApp.controller('StreamController',
}
);
-
-var graphSubController = function($scope, explanation) {
+var streamGraphSubController = function($scope, explanation) {
$scope.showGraph = true;
$scope.pos = 0;
$scope.rows = 8;
- $scope.helperData = {
- protocol: [],
- host: [],
- hostname: [],
- port: [],
- pathname: []
- };
$scope.resetGraph = function() {
$scope.pos = 0;
@@ -134,7 +124,7 @@ var graphSubController = function($scope, explanation) {
$scope.showPaging = false;
$scope.isRadial = false;
- $scope.graphData = recurse(data, 1);
+ $scope.explanationData = recurse(data, 1);
$scope.depth = maxDepth + 1;
$scope.leafCount = leafCount;
@@ -143,17 +133,16 @@ var graphSubController = function($scope, explanation) {
$scope.initGraph(explanation);
};
-solrAdminApp.directive('foograph', function(Constants) {
+solrAdminApp.directive('explanationGraph', function(Constants) {
return {
restrict: 'EA',
scope: {
data: "=",
leafCount: "=",
- depth: "=",
- helperData: "=",
- isRadial: "="
+ depth: "="
},
link: function(scope, element, attrs) {
+
var helper_path_class = function(p) {
var classes = ['link'];
diff --git a/solr/webapp/web/partials/stream.html b/solr/webapp/web/partials/stream.html
index f62007fd1df..0d1154ec014 100644
--- a/solr/webapp/web/partials/stream.html
+++ b/solr/webapp/web/partials/stream.html
@@ -38,7 +38,7 @@ limitations under the License.