diff --git a/build.gradle b/build.gradle
index aa2389cec04..bc93b1098c4 100644
--- a/build.gradle
+++ b/build.gradle
@@ -19,15 +19,15 @@ import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
plugins {
- id "base"
- id "com.palantir.consistent-versions" version "2.16.0"
- id "org.owasp.dependencycheck" version "8.0.1"
- id 'ca.cutterslade.analyze' version "1.9.0"
+ id 'base'
+ id 'com.palantir.consistent-versions' version '2.16.0'
+ id 'org.owasp.dependencycheck' version '8.4.0'
+ id 'ca.cutterslade.analyze' version '1.9.1'
id 'de.thetaphi.forbiddenapis' version '3.6' apply false
- id "de.undercouch.download" version "5.2.0" apply false
- id "net.ltgt.errorprone" version "3.0.1" apply false
- id 'com.diffplug.spotless' version "6.5.2" apply false
- id 'com.github.node-gradle.node' version '3.4.0' apply false
+ id 'de.undercouch.download' version '5.5.0' apply false
+ id 'net.ltgt.errorprone' version '3.1.0' apply false
+ id 'com.diffplug.spotless' version '6.5.2' apply false
+ id 'com.github.node-gradle.node' version '7.0.1' apply false
}
apply from: file('gradle/globals.gradle')
diff --git a/buildSrc/scriptDepVersions.gradle b/buildSrc/scriptDepVersions.gradle
index 802aa2a6275..a1d2bc9467d 100644
--- a/buildSrc/scriptDepVersions.gradle
+++ b/buildSrc/scriptDepVersions.gradle
@@ -21,11 +21,11 @@
ext {
scriptDepVersions = [
- "apache-rat": "0.14",
- "commons-codec": "1.15",
- "ecj": "3.30.0",
+ "apache-rat": "0.15",
+ "commons-codec": "1.16.0",
+ "ecj": "3.33.0",
"javacc": "7.0.12",
- "jgit": "5.13.1.202206130422-r",
- "flexmark": "0.64.0",
+ "jgit": "6.7.0.202309050840-r",
+ "flexmark": "0.64.8",
]
}
diff --git a/dev-tools/doap/solr.rdf b/dev-tools/doap/solr.rdf
index 7ad4861d183..e0a1c43a3ab 100644
--- a/dev-tools/doap/solr.rdf
+++ b/dev-tools/doap/solr.rdf
@@ -68,6 +68,13 @@
+
+
+ solr-9.4.0
+ 2023-10-14
+ 9.4.0
+
+
solr-9.3.0
diff --git a/dev-tools/scripts/addVersion.py b/dev-tools/scripts/addVersion.py
index 30964b72dcf..53a5f02e777 100755
--- a/dev-tools/scripts/addVersion.py
+++ b/dev-tools/scripts/addVersion.py
@@ -44,7 +44,7 @@ def edit(buffer, match, line):
print('done' if changed else 'uptodate')
def update_solrversion_class(new_version):
- filename = 'solr/core/src/java/org/apache/solr/util/SolrVersion.java'
+ filename = 'solr/api/src/java/org/apache/solr/client/api/util/SolrVersion.java'
print(' changing version to %s...' % new_version.dot, end='', flush=True)
constant_prefix = 'public static final String LATEST_STRING = "(.*?)"'
matcher = re.compile(constant_prefix)
@@ -104,7 +104,7 @@ def edit(buffer, match, line):
def check_solr_version_class_tests():
print(' checking solr version tests...', end='', flush=True)
- run('./gradlew -p solr/core test --tests TestSolrVersion')
+ run('./gradlew -p solr/api test --tests TestSolrVersion')
print('ok')
def check_lucene_match_version_tests():
diff --git a/dev-tools/scripts/releaseWizard.yaml b/dev-tools/scripts/releaseWizard.yaml
index eafd4cd1621..ddc7f744bbe 100644
--- a/dev-tools/scripts/releaseWizard.yaml
+++ b/dev-tools/scripts/releaseWizard.yaml
@@ -205,7 +205,7 @@ groups:
title: Prerequisites
description: |
Releasing software requires thorough understanding of the process and careful execution,
- as it is easy to make mistakes. It also requires an environtment and tools such as gpg
+ as it is easy to make mistakes. It also requires an environment and tools such as gpg
correctly setup. This section makes sure you're in good shape for the job!
todos:
- !Todo
@@ -526,7 +526,7 @@ groups:
- major
- minor
links:
- - https://cwiki.apache.org/confluence/display/LUCENEJAVA/JenkinsReleaseBuilds
+ - https://cwiki.apache.org/confluence/display/SOLR/JenkinsReleaseBuilds+-+Solr
- !Todo
id: inform_devs
title: Inform Devs of the new Release Branch
@@ -544,7 +544,7 @@ groups:
NOTICE:
- Branch {{ release_branch }} has been cut and versions updated to {{ release_version_major }}.{{ release_version_minor + 1 }} on stable branch.
+ Branch {{ release_branch }} has been cut and versions updated to {{ release_version_major }}.{{ release_version_minor + 1 }} on the stable branch.
Please observe the normal rules:
@@ -636,7 +636,7 @@ groups:
Ask on dev@ for input. Ideally the timing of this request mostly coincides with the
release branch creation. It's a good idea to remind the devs of this later in the release too.
- NOTE: Do not add every single JIRA issue, but distill the Release note into important changes!
+ NOTE: Do not add every single JIRA issue, but distill the release notes into important changes!
links:
- https://cwiki.apache.org/confluence/display/SOLR/Release+Notes
- !Todo
@@ -660,7 +660,7 @@ groups:
description: |-
To make sure a new release is not announced before the reference guide is complete, add a new
Blocker JIRA issue for version {{ release_version }} with subject
- "Complete Major changes and Upgrade Notes in RefGudie for {{ release_version }}".
+ "Complete Major changes and Upgrade Notes in RefGuide for {{ release_version }}".
Note that this does not block the RC and voting process, but will block announcing the release.
types:
- major
@@ -1588,6 +1588,7 @@ groups:
Fill in the same date that you used for the release in previous steps.
Do not use a product name prefix for the version, as this is the main release of the Solr PMC.
Just use the version of this release: {{ release_version }}
+ Note: you have to be a member of the Solr PMC to be able to complete this step.
links:
- https://reporter.apache.org/addrelease.html?solr
- !TodoGroup
diff --git a/gradle/validation/error-prone.gradle b/gradle/validation/error-prone.gradle
index d2800242425..de8ee8d1de0 100644
--- a/gradle/validation/error-prone.gradle
+++ b/gradle/validation/error-prone.gradle
@@ -305,6 +305,7 @@ allprojects { prj ->
// '-Xep:DoNotMockAutoValue:OFF', // we don't use autovalue
// '-Xep:DoNotUseRuleChain:OFF', // todo could be fixed but not easy
// '-Xep:DoubleCheckedLocking:OFF', // todo check if useful or comment why not
+ '-Xep:DuplicateDateFormatField:WARN',
'-Xep:EmptyBlockTag:WARN',
// '-Xep:EmptyCatch:OFF', // todo check if useful or comment why not - might be handled by ECJ?
// '-Xep:EmptySetMultibindingContributions:OFF', // we don't use this annotation
@@ -420,6 +421,7 @@ allprojects { prj ->
// '-Xep:NonAtomicVolatileUpdate:OFF', // todo check if useful or comment why not
'-Xep:NonCanonicalType:WARN',
'-Xep:NonOverridingEquals:WARN',
+ //'-Xep:NonFinalStaticField:WARN', // todo there are problems that should be fixed
'-Xep:NotJavadoc:WARN',
'-Xep:NullOptional:WARN',
// '-Xep:NullableConstructor:OFF', // we don't use this annotation
@@ -464,7 +466,10 @@ allprojects { prj ->
// '-Xep:StreamResourceLeak:OFF', // todo check if useful or comment why not
'-Xep:StreamToIterable:WARN',
// '-Xep:StringCaseLocaleUsage:OFF', // we have forbiddenapis for that
+ '-Xep:StringCharset:WARN',
+ '-Xep:StringFormatWithLiteral:WARN',
// '-Xep:StringSplitter:OFF', // todo check if useful or comment why not - might be able to use forbidden-apis for this?
+ '-Xep:SuperEqualsIsObjectEquals:WARN',
// '-Xep:SwigMemoryLeak:OFF', // we don't use swig
// '-Xep:SynchronizeOnNonFinalField:OFF', // todo check if useful or comment why not
// '-Xep:ThreadJoinLoop:OFF', // todo check if useful or comment why not
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index c8dad544cc7..83389922a52 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -8,7 +8,8 @@ https://github.com/apache/solr/blob/main/solr/solr-ref-guide/modules/upgrade-not
New Features
---------------------
-(No changes)
+
+* SOLR-16943: Extend Solr client tracing coverage to both Jetty Client and Apache HttpClient (Alex Deparvu, David Smiley)
Improvements
---------------------
@@ -25,7 +26,7 @@ Optimizations
Bug Fixes
---------------------
-(No changes)
+
Deprecation Removals
----------------------
@@ -42,6 +43,8 @@ Deprecation Removals
* SOLR-16893: Remove bin/solr create_core and create_collection commands in favour of bin/solr create command. (Eric Pugh)
+* SOLR-17042: Remove deprecated `V2RequestSupport` and associated `SolrRequest` methods `setUseV2` and `setUseBinaryV2`. (Jason Gerlowski)
+
Dependency Upgrades
---------------------
(No changes)
@@ -65,25 +68,30 @@ Other Changes
* SOLR-16911: Establish /solr as the only host context supported by Solr, removing legacy ability to change this. Solr paths will only be either /solr or /api now. (Eric Pugh)
+* SOLR-16995: Add a ReplicaCount class to keep track of replicas per type (Vincent Primault)
+
================== 9.5.0 ==================
New Features
---------------------
-(No changes)
+* SOLR-14496: Solr CLI commands now can interact with a Solr secured using Basic Authentication. (Eric Pugh)
+
+* SOLR-17006: Collection creation & adding replicas: User-defined properties are persisted to state.json and
+ applied to new replicas, available for use as property substitution in configuration files. (Vincent Primault)
Improvements
---------------------
* SOLR-16924: RESTORECORE now sets the UpdateLog to ACTIVE state instead of requiring a separate
REQUESTAPPLYUPDATES call in Collection restore. (Julia Lamoine, David Smiley)
-* SOLR-17019: ZkCli should create chroot when necessary (Houston Putman)
-
Optimizations
---------------------
(No changes)
Bug Fixes
---------------------
-(No changes)
+* SOLR-6853: Allow '/' characters in the text managed by Managed Resources API. (Nikita Rusetskii via Eric Pugh)
+
+* SOLR-17039: Entropy calculation in bin/solr script fails in Docker due to missing 'bc' cmd (janhoy)
Dependency Upgrades
---------------------
@@ -93,7 +101,7 @@ Dependency Upgrades
Other Changes
---------------------
-(No changes)
+* SOLR-17024: Remove support for the long-defunct "collectionDefaults" clusterprops key (Jason Gerlowski)
================== 9.4.0 ==================
New Features
diff --git a/solr/benchmark/src/java/org/apache/solr/bench/BaseBenchState.java b/solr/benchmark/src/java/org/apache/solr/bench/BaseBenchState.java
index 4db40c05112..e3b5012366b 100644
--- a/solr/benchmark/src/java/org/apache/solr/bench/BaseBenchState.java
+++ b/solr/benchmark/src/java/org/apache/solr/bench/BaseBenchState.java
@@ -41,11 +41,9 @@
@State(Scope.Benchmark)
public class BaseBenchState {
- private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+ private static final long RANDOM_SEED = System.nanoTime();
- private static final long RANDOM_SEED = 6624420638116043983L;
-
- private static final SplittableRandom random = new SplittableRandom(getInitRandomeSeed());
+ private static final SplittableRandom random = new SplittableRandom(getInitRandomSeed());
/**
* Gets random seed.
@@ -137,13 +135,14 @@ public static void dumpHeap(BenchmarkParams benchmarkParams) throws IOException
}
}
- private static Long getInitRandomeSeed() {
+ private static Long getInitRandomSeed() {
Long seed = Long.getLong("solr.bench.seed");
if (seed == null) {
seed = RANDOM_SEED;
}
+ log("");
log("benchmark random seed: " + seed);
return seed;
diff --git a/solr/benchmark/src/java/org/apache/solr/bench/CircularIterator.java b/solr/benchmark/src/java/org/apache/solr/bench/CircularIterator.java
new file mode 100644
index 00000000000..529d5812442
--- /dev/null
+++ b/solr/benchmark/src/java/org/apache/solr/bench/CircularIterator.java
@@ -0,0 +1,51 @@
+/*
+ * 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.bench;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class CircularIterator implements Iterator {
+
+ private final Object[] collection;
+ private final AtomicInteger idx;
+
+ public CircularIterator(Collection collection) {
+ this.collection = Objects.requireNonNull(collection).toArray();
+ if (this.collection.length == 0) {
+ throw new IllegalArgumentException("This iterator doesn't support empty collections");
+ }
+ this.idx = new AtomicInteger();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return true;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public T next() {
+ return (T) collection[idx.incrementAndGet() % collection.length];
+ }
+
+ public int cycles() {
+ return ((idx.get() - 1) / collection.length) + 1;
+ }
+}
diff --git a/solr/benchmark/src/java/org/apache/solr/bench/Docs.java b/solr/benchmark/src/java/org/apache/solr/bench/Docs.java
index cfaca270571..5c3b889c7a6 100644
--- a/solr/benchmark/src/java/org/apache/solr/bench/Docs.java
+++ b/solr/benchmark/src/java/org/apache/solr/bench/Docs.java
@@ -18,7 +18,6 @@
import static org.apache.solr.bench.BaseBenchState.log;
-import java.lang.invoke.MethodHandles;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
@@ -38,8 +37,6 @@
import org.apache.solr.common.util.SuppressForbidden;
import org.quicktheories.core.Gen;
import org.quicktheories.impl.BenchmarkRandomSource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* A tool to generate controlled random data for a benchmark. {@link SolrInputDocument}s are created
@@ -50,8 +47,6 @@
* them via {@link #generatedDocsIterator}.
*/
public class Docs {
- private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
private final ThreadLocal random;
private final Queue docs = new ConcurrentLinkedQueue<>();
@@ -104,7 +99,7 @@ private Docs(Long seed) {
*/
@SuppressForbidden(reason = "This module does not need to deal with logging context")
public Iterator preGenerate(int numDocs) throws InterruptedException {
- log("preGenerate docs " + numDocs + " ...");
+ log("preGenerate docs=" + numDocs + " ...");
docs.clear();
executorService =
Executors.newFixedThreadPool(
@@ -114,14 +109,7 @@ public Iterator preGenerate(int numDocs) throws InterruptedEx
for (int i = 0; i < numDocs; i++) {
executorService.submit(
() -> {
- try {
- SolrInputDocument doc = Docs.this.inputDocument();
- docs.add(doc);
- } catch (Exception e) {
- log.error("error adding doc", e);
- executorService.shutdownNow();
- throw new RuntimeException(e);
- }
+ docs.add(Docs.this.inputDocument());
});
}
@@ -144,7 +132,7 @@ public Iterator preGenerate(int numDocs) throws InterruptedEx
}
/**
- * Generated docs iterator iterator.
+ * Generated docs iterator.
*
* @return the iterator
*/
@@ -152,6 +140,15 @@ public Iterator generatedDocsIterator() {
return docs.iterator();
}
+ /**
+ * Generated docs circular iterator.
+ *
+ * @return the iterator that never ends
+ */
+ public CircularIterator generatedDocsCircularIterator() {
+ return new CircularIterator<>(docs);
+ }
+
/**
* Input document solr input document.
*
diff --git a/solr/benchmark/src/java/org/apache/solr/bench/MiniClusterState.java b/solr/benchmark/src/java/org/apache/solr/bench/MiniClusterState.java
index dd1c0afe639..5a793448c5c 100755
--- a/solr/benchmark/src/java/org/apache/solr/bench/MiniClusterState.java
+++ b/solr/benchmark/src/java/org/apache/solr/bench/MiniClusterState.java
@@ -24,7 +24,6 @@
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
-import java.lang.invoke.MethodHandles;
import java.lang.management.ManagementFactory;
import java.net.URL;
import java.nio.charset.StandardCharsets;
@@ -61,21 +60,14 @@
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.infra.BenchmarkParams;
import org.openjdk.jmh.infra.Control;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/** The base class for Solr JMH benchmarks that operate against a {@code MiniSolrCloudCluster}. */
public class MiniClusterState {
- /** The constant DEBUG_OUTPUT. */
- public static final boolean DEBUG_OUTPUT = false;
-
/** The constant PROC_COUNT. */
public static final int PROC_COUNT =
ManagementFactory.getOperatingSystemMXBean().getAvailableProcessors();
- private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
/** The type Mini cluster bench state. */
@State(Scope.Benchmark)
public static class MiniClusterBenchState {
@@ -118,7 +110,7 @@ public static class MiniClusterBenchState {
private SplittableRandom random;
private String workDir;
- private boolean useHttp1 = false;
+ private boolean useHttp1 = Boolean.getBoolean("solr.http1");
/**
* Tear down.
@@ -163,14 +155,30 @@ public void checkWarmUp(Control control) throws Exception {
@TearDown(Level.Trial)
public void shutdownMiniCluster(BenchmarkParams benchmarkParams, BaseBenchState baseBenchState)
throws Exception {
-
- log.info("MiniClusterState tear down - baseBenchState is {}", baseBenchState);
-
BaseBenchState.dumpHeap(benchmarkParams);
- if (DEBUG_OUTPUT) log("closing client and shutting down minicluster");
IOUtils.closeQuietly(client);
cluster.shutdown();
+ logClusterDirectorySize();
+ }
+
+ private void logClusterDirectorySize() throws IOException {
+ log("");
+ Files.list(miniClusterBaseDir.toAbsolutePath())
+ .forEach(
+ (node) -> {
+ try {
+ long clusterSize =
+ Files.walk(node)
+ .filter(Files::isRegularFile)
+ .map(Path::toFile)
+ .mapToLong(File::length)
+ .sum();
+ log("mini cluster node size (bytes) " + node + " " + clusterSize);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ });
}
/**
@@ -191,7 +199,6 @@ public void doSetup(BenchmarkParams benchmarkParams, BaseBenchState baseBenchSta
workDir = System.getProperty("workBaseDir", "build/work");
- log("");
Path currentRelativePath = Paths.get("");
String s = currentRelativePath.toAbsolutePath().toString();
log("current relative path is: " + s);
@@ -373,9 +380,7 @@ public void index(String collection, Docs docs, int docCount, boolean parallel)
queryRequest.setBasePath(nodes.get(random.nextInt(cluster.getJettySolrRunners().size())));
NamedList result = client.request(queryRequest, collection);
-
- if (DEBUG_OUTPUT) log("result: " + result);
-
+ log("sanity check of single row query result: " + result);
log("");
log("Dump Core Info");
@@ -443,7 +448,7 @@ private void indexBatch(String collection, Docs docs, int docCount, int batchSiz
throws SolrServerException, IOException {
Meter meter = new Meter();
List batch = new ArrayList<>(batchSize);
- for (int i = 0; i < docCount; i++) {
+ for (int i = 1; i <= docCount; i++) {
batch.add(docs.inputDocument());
if (i % batchSize == 0) {
UpdateRequest updateRequest = new UpdateRequest();
@@ -452,7 +457,7 @@ private void indexBatch(String collection, Docs docs, int docCount, int batchSiz
client.request(updateRequest, collection);
meter.mark(batch.size());
batch.clear();
- log(meter.getCount() + " docs at " + meter.getMeanRate() + " doc/s");
+ log(meter.getCount() + " docs at " + (long) meter.getMeanRate() + " doc/s");
}
}
if (!batch.isEmpty()) {
@@ -463,7 +468,7 @@ private void indexBatch(String collection, Docs docs, int docCount, int batchSiz
meter.mark(batch.size());
batch = null;
}
- log(meter.getCount() + " docs at " + meter.getMeanRate() + " doc/s");
+ log(meter.getCount() + " docs at " + (long) meter.getMeanRate() + " doc/s");
}
/**
diff --git a/solr/benchmark/src/java/org/apache/solr/bench/index/CloudIndexing.java b/solr/benchmark/src/java/org/apache/solr/bench/index/CloudIndexing.java
index 981ce0dc455..820f2130a60 100755
--- a/solr/benchmark/src/java/org/apache/solr/bench/index/CloudIndexing.java
+++ b/solr/benchmark/src/java/org/apache/solr/bench/index/CloudIndexing.java
@@ -23,6 +23,7 @@
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
+import org.apache.solr.bench.Docs;
import org.apache.solr.bench.MiniClusterState;
import org.apache.solr.client.solrj.request.UpdateRequest;
import org.apache.solr.common.SolrInputDocument;
@@ -37,19 +38,15 @@
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
-import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Threads;
-import org.openjdk.jmh.annotations.Timeout;
import org.openjdk.jmh.annotations.Warmup;
-import org.openjdk.jmh.infra.BenchmarkParams;
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
-@Threads(4)
-@Warmup(time = 10, iterations = 3)
-@Measurement(time = 20, iterations = 4)
+@Threads(16)
+@Warmup(time = 15, iterations = 2)
+@Measurement(time = 60, iterations = 4)
@Fork(value = 1)
-@Timeout(time = 60)
// A benchmark to experiment with the performance of distributed indexing.
public class CloudIndexing {
@@ -58,32 +55,26 @@ public static class BenchState {
static final String COLLECTION = "testCollection";
- @Param({"1"})
- public int scale;
-
@Param("4")
int nodeCount;
- @Param("5")
+ @Param("4")
int numShards;
@Param({"1", "3"})
int numReplicas;
- @Param({"0", "15", "30", "70", "100", "500", "1000"})
- int useStringUtf8Over;
-
@Param({"true", "false"})
- boolean directBuffer;
+ boolean useSmallDocs;
- private final org.apache.solr.bench.Docs largeDocs;
- private Iterator largeDocIterator;
+ @Param({"50000"})
+ int preGenerate;
- private final org.apache.solr.bench.Docs smallDocs;
- private Iterator smallDocIterator;
+ private final Docs largeDocs;
+ private final Docs smallDocs;
+ private Iterator docIterator;
public BenchState() {
-
largeDocs =
docs()
.field("id", integers().incrementing())
@@ -94,81 +85,51 @@ public BenchState() {
.field(integers().all())
.field(longs().all())
.field(longs().all());
+ smallDocs =
+ docs()
+ .field("id", integers().incrementing())
+ .field("text", strings().basicLatinAlphabet().multi(2).ofLengthBetween(20, 32))
+ .field("int1_i", integers().all())
+ .field("int2_i", integers().all())
+ .field("long1_l", longs().all());
+ }
- try {
- largeDocIterator = largeDocs.preGenerate(50000);
-
- smallDocs =
- docs()
- .field("id", integers().incrementing())
- .field("text", strings().basicLatinAlphabet().multi(2).ofLengthBetween(20, 32))
- .field("int1_i", integers().all())
- .field("int2_i", integers().all())
- .field("long1_l", longs().all());
+ private SolrInputDocument getNextDoc() {
+ return docIterator.next();
+ }
- smallDocIterator = smallDocs.preGenerate(50000);
+ private void preGenerate() {
+ try {
+ if (useSmallDocs) {
+ smallDocs.preGenerate(preGenerate);
+ docIterator = smallDocs.generatedDocsCircularIterator();
+ } else {
+ largeDocs.preGenerate(preGenerate);
+ docIterator = largeDocs.generatedDocsCircularIterator();
+ }
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
}
- public SolrInputDocument getLargeDoc() {
- if (!largeDocIterator.hasNext()) {
- largeDocIterator = largeDocs.generatedDocsIterator();
- }
- return largeDocIterator.next();
- }
-
- public SolrInputDocument getSmallDoc() {
- if (!smallDocIterator.hasNext()) {
- smallDocIterator = smallDocs.generatedDocsIterator();
- }
- return smallDocIterator.next();
- }
-
@Setup(Level.Trial)
public void doSetup(MiniClusterState.MiniClusterBenchState miniClusterState) throws Exception {
- System.setProperty("useStringUtf8Over", Integer.toString(useStringUtf8Over));
- System.setProperty("httpClientDirectBuffer", Boolean.toString(directBuffer));
+ preGenerate();
System.setProperty("mergePolicyFactory", "org.apache.solr.index.NoMergePolicyFactory");
miniClusterState.startMiniCluster(nodeCount);
miniClusterState.createCollection(COLLECTION, numShards, numReplicas);
}
-
- @TearDown(Level.Trial)
- public void doTearDown(
- MiniClusterState.MiniClusterBenchState miniClusterState, BenchmarkParams benchmarkParams)
- throws Exception {
-
- // miniClusterState.shutdownMiniCluster(benchmarkParams);
- }
- }
-
- @Benchmark
- @Timeout(time = 300)
- public Object indexLargeDoc(
- MiniClusterState.MiniClusterBenchState miniClusterState, BenchState state) throws Exception {
- UpdateRequest updateRequest = new UpdateRequest();
- updateRequest.setBasePath(
- miniClusterState.nodes.get(miniClusterState.getRandom().nextInt(state.nodeCount)));
- SolrInputDocument doc = state.getLargeDoc();
- updateRequest.add(doc);
-
- return miniClusterState.client.request(updateRequest, BenchState.COLLECTION);
}
@Benchmark
- @Timeout(time = 300)
- public Object indexSmallDoc(
- MiniClusterState.MiniClusterBenchState miniClusterState, BenchState state) throws Exception {
+ public Object indexDoc(MiniClusterState.MiniClusterBenchState miniClusterState, BenchState state)
+ throws Exception {
UpdateRequest updateRequest = new UpdateRequest();
updateRequest.setBasePath(
miniClusterState.nodes.get(miniClusterState.getRandom().nextInt(state.nodeCount)));
- SolrInputDocument doc = state.getSmallDoc();
- updateRequest.add(doc);
-
+ updateRequest.add(state.getNextDoc());
return miniClusterState.client.request(updateRequest, BenchState.COLLECTION);
}
}
diff --git a/solr/benchmark/src/java/org/apache/solr/bench/search/NumericSearch.java b/solr/benchmark/src/java/org/apache/solr/bench/search/NumericSearch.java
index a96a714ebef..3c7a72385f9 100644
--- a/solr/benchmark/src/java/org/apache/solr/bench/search/NumericSearch.java
+++ b/solr/benchmark/src/java/org/apache/solr/bench/search/NumericSearch.java
@@ -21,13 +21,11 @@
import static org.apache.solr.bench.generators.SourceDSL.strings;
import java.io.IOException;
-import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
-import java.util.Objects;
import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
+import org.apache.solr.bench.CircularIterator;
import org.apache.solr.bench.Docs;
import org.apache.solr.bench.MiniClusterState;
import org.apache.solr.bench.generators.SolrGen;
@@ -177,31 +175,6 @@ QueryRequest setQuery(String field) {
q.setBasePath(basePath);
return q;
}
-
- private static class CircularIterator implements Iterator {
-
- private final Object[] collection;
- private final AtomicInteger idx;
-
- CircularIterator(Collection collection) {
- this.collection = Objects.requireNonNull(collection).toArray();
- if (this.collection.length == 0) {
- throw new IllegalArgumentException("This iterator doesn't support empty collections");
- }
- this.idx = new AtomicInteger();
- }
-
- @Override
- public boolean hasNext() {
- return true;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public T next() {
- return (T) collection[idx.incrementAndGet() % collection.length];
- }
- }
}
@Benchmark
diff --git a/solr/bin/solr b/solr/bin/solr
index 30c3e3aa52b..3db7f1c7731 100644
--- a/solr/bin/solr
+++ b/solr/bin/solr
@@ -1926,10 +1926,10 @@ function start_solr() {
# Check if entropy is available and pool size is non-zero
if [[ $entropy_avail -gt 0 && $pool_size -ne 0 ]]; then
# Compute the ratio of entropy available to pool size
- ratio=$(awk -v ea="$entropy_avail" -v ps="$pool_size" 'BEGIN {print (ea/ps)*100}')
+ ratio=$(awk -v ea="$entropy_avail" -v ps="$pool_size" 'BEGIN {print int((ea/ps)*100)}')
# Check if the ratio is less than 25%
- if (( $(echo "$ratio < 25" | bc -l) )); then
+ if (( ratio < 25 )); then
echo "Warning: Available entropy is low. As a result, use of the UUIDField, SSL, or any other features that require"
echo "RNG might not work properly. To check for the amount of available entropy, use 'cat /proc/sys/kernel/random/entropy_avail'."
fi
diff --git a/solr/core/src/java/org/apache/solr/cli/ApiTool.java b/solr/core/src/java/org/apache/solr/cli/ApiTool.java
index 8ecfcd36a40..2b760cc7f76 100644
--- a/solr/core/src/java/org/apache/solr/cli/ApiTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/ApiTool.java
@@ -57,7 +57,8 @@ public List getOptions() {
.hasArg()
.required(true)
.desc("Send a GET request to a Solr API endpoint.")
- .build());
+ .build(),
+ SolrCLI.OPTION_CREDENTIALS);
}
@Override
@@ -65,7 +66,7 @@ public void runImpl(CommandLine cli) throws Exception {
String response = null;
String getUrl = cli.getOptionValue("get");
if (getUrl != null) {
- response = callGet(getUrl);
+ response = callGet(getUrl, cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt()));
}
if (response != null) {
// pretty-print the response to stdout
@@ -73,11 +74,11 @@ public void runImpl(CommandLine cli) throws Exception {
}
}
- protected String callGet(String url) throws Exception {
+ protected String callGet(String url, String credentials) throws Exception {
URI uri = new URI(url.replace("+", "%20"));
String solrUrl = getSolrUrlFromUri(uri);
String path = uri.getPath();
- try (var solrClient = SolrCLI.getSolrClient(solrUrl)) {
+ try (var solrClient = SolrCLI.getSolrClient(solrUrl, credentials)) {
// For path parameter we need the path without the root so from the second / char
// (because root can be configured)
// E.g URL is http://localhost:8983/solr/admin/info/system path is
diff --git a/solr/core/src/java/org/apache/solr/cli/AssertTool.java b/solr/core/src/java/org/apache/solr/cli/AssertTool.java
index 44b4dce1250..8976212778f 100644
--- a/solr/core/src/java/org/apache/solr/cli/AssertTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/AssertTool.java
@@ -34,8 +34,10 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-/** Supports assert command in the bin/solr script. */
-/** Asserts various conditions and exists with error code if fails, else continues with no output */
+/**
+ * Supports assert command in the bin/solr script. Asserts various conditions and exists with error
+ * code if there are failures, else continues with no output.
+ */
public class AssertTool extends ToolBase {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private static String message = null;
@@ -123,6 +125,14 @@ public List getOptions() {
Option.builder("e")
.desc("Return an exit code instead of printing error message on assert fail.")
.longOpt("exitcode")
+ .build(),
+ // u was taken, can we change that instead?
+ Option.builder("credentials")
+ .argName("credentials")
+ .hasArg()
+ .required(false)
+ .desc(
+ "Credentials in the format username:password. Example: --credentials solr:SolrRocks")
.build());
}
@@ -190,24 +200,34 @@ protected int runAssert(CommandLine cli) throws Exception {
ret += sameUser(cli.getOptionValue("u"));
}
if (cli.hasOption("s")) {
- ret += assertSolrRunning(cli.getOptionValue("s"));
+ ret +=
+ assertSolrRunning(
+ cli.getOptionValue("s"), cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt()));
}
if (cli.hasOption("S")) {
- ret += assertSolrNotRunning(cli.getOptionValue("S"));
+ ret +=
+ assertSolrNotRunning(
+ cli.getOptionValue("S"), cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt()));
}
if (cli.hasOption("c")) {
- ret += assertSolrRunningInCloudMode(SolrCLI.normalizeSolrUrl(cli.getOptionValue("c")));
+ ret +=
+ assertSolrRunningInCloudMode(
+ SolrCLI.normalizeSolrUrl(cli.getOptionValue("c")),
+ cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt()));
}
if (cli.hasOption("C")) {
- ret += assertSolrNotRunningInCloudMode(SolrCLI.normalizeSolrUrl(cli.getOptionValue("C")));
+ ret +=
+ assertSolrNotRunningInCloudMode(
+ SolrCLI.normalizeSolrUrl(cli.getOptionValue("C")),
+ cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt()));
}
return ret;
}
- public static int assertSolrRunning(String url) throws Exception {
+ public static int assertSolrRunning(String url, String credentials) throws Exception {
StatusTool status = new StatusTool();
try {
- status.waitToSeeSolrUp(url, timeoutMs, TimeUnit.MILLISECONDS);
+ status.waitToSeeSolrUp(url, credentials, timeoutMs, TimeUnit.MILLISECONDS);
} catch (Exception se) {
if (SolrCLI.exceptionIsAuthRelated(se)) {
throw se;
@@ -222,11 +242,11 @@ public static int assertSolrRunning(String url) throws Exception {
return 0;
}
- public static int assertSolrNotRunning(String url) throws Exception {
+ public static int assertSolrNotRunning(String url, String credentials) throws Exception {
StatusTool status = new StatusTool();
long timeout =
System.nanoTime() + TimeUnit.NANOSECONDS.convert(timeoutMs, TimeUnit.MILLISECONDS);
- try (SolrClient solrClient = SolrCLI.getSolrClient(url)) {
+ try (SolrClient solrClient = SolrCLI.getSolrClient(url, credentials)) {
NamedList response = solrClient.request(new HealthCheckRequest());
Integer statusCode = (Integer) response.findRecursive("responseHeader", "status");
SolrCLI.checkCodeForAuthError(statusCode);
@@ -236,7 +256,7 @@ public static int assertSolrNotRunning(String url) throws Exception {
}
while (System.nanoTime() < timeout) {
try {
- status.waitToSeeSolrUp(url, 1, TimeUnit.SECONDS);
+ status.waitToSeeSolrUp(url, credentials, 1, TimeUnit.SECONDS);
try {
log.debug("Solr still up. Waiting before trying again to see if it was stopped");
Thread.sleep(1000L);
@@ -258,8 +278,8 @@ public static int assertSolrNotRunning(String url) throws Exception {
+ " seconds");
}
- public static int assertSolrRunningInCloudMode(String url) throws Exception {
- if (!isSolrRunningOn(url)) {
+ public static int assertSolrRunningInCloudMode(String url, String credentials) throws Exception {
+ if (!isSolrRunningOn(url, credentials)) {
return exitOrException(
"Solr is not running on url "
+ url
@@ -268,14 +288,15 @@ public static int assertSolrRunningInCloudMode(String url) throws Exception {
+ " seconds");
}
- if (!runningSolrIsCloud(url)) {
+ if (!runningSolrIsCloud(url, credentials)) {
return exitOrException("Solr is not running in cloud mode on " + url);
}
return 0;
}
- public static int assertSolrNotRunningInCloudMode(String url) throws Exception {
- if (!isSolrRunningOn(url)) {
+ public static int assertSolrNotRunningInCloudMode(String url, String credentials)
+ throws Exception {
+ if (!isSolrRunningOn(url, credentials)) {
return exitOrException(
"Solr is not running on url "
+ url
@@ -284,7 +305,7 @@ public static int assertSolrNotRunningInCloudMode(String url) throws Exception {
+ " seconds");
}
- if (runningSolrIsCloud(url)) {
+ if (runningSolrIsCloud(url, credentials)) {
return exitOrException("Solr is not running in standalone mode on " + url);
}
return 0;
@@ -352,10 +373,10 @@ private static int exitOrException(String msg) throws AssertionFailureException
}
}
- private static boolean isSolrRunningOn(String url) throws Exception {
+ private static boolean isSolrRunningOn(String url, String credentials) throws Exception {
StatusTool status = new StatusTool();
try {
- status.waitToSeeSolrUp(url, timeoutMs, TimeUnit.MILLISECONDS);
+ status.waitToSeeSolrUp(url, credentials, timeoutMs, TimeUnit.MILLISECONDS);
return true;
} catch (Exception se) {
if (SolrCLI.exceptionIsAuthRelated(se)) {
@@ -365,8 +386,8 @@ private static boolean isSolrRunningOn(String url) throws Exception {
}
}
- private static boolean runningSolrIsCloud(String url) throws Exception {
- try (final SolrClient client = SolrCLI.getSolrClient(url)) {
+ private static boolean runningSolrIsCloud(String url, String credentials) throws Exception {
+ try (final SolrClient client = SolrCLI.getSolrClient(url, credentials)) {
return SolrCLI.isCloudMode(client);
}
}
diff --git a/solr/core/src/java/org/apache/solr/cli/AuthTool.java b/solr/core/src/java/org/apache/solr/cli/AuthTool.java
index 2afd71706b6..abaeb0a84f9 100644
--- a/solr/core/src/java/org/apache/solr/cli/AuthTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/AuthTool.java
@@ -74,12 +74,7 @@ public List getOptions() {
.desc(
"The authentication mechanism to enable (basicAuth or kerberos). Defaults to 'basicAuth'.")
.build(),
- Option.builder("credentials")
- .argName("credentials")
- .hasArg()
- .desc(
- "Credentials in the format username:password. Example: -credentials solr:SolrRocks")
- .build(),
+ SolrCLI.OPTION_CREDENTIALS,
Option.builder("prompt")
.argName("prompt")
.hasArg()
@@ -292,8 +287,8 @@ private int handleBasicAuth(CommandLine cli) throws Exception {
.printHelp("bin/solr auth [OPTIONS]", SolrCLI.getToolOptions(this));
SolrCLI.exit(1);
} else if (!prompt
- && (cli.getOptionValue("credentials") == null
- || !cli.getOptionValue("credentials").contains(":"))) {
+ && (cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt()) == null
+ || !cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt()).contains(":"))) {
CLIO.out("Option -credentials is not in correct format.");
new HelpFormatter()
.printHelp("bin/solr auth [OPTIONS]", SolrCLI.getToolOptions(this));
@@ -337,8 +332,8 @@ private int handleBasicAuth(CommandLine cli) throws Exception {
}
String username, password;
- if (cli.hasOption("credentials")) {
- String credentials = cli.getOptionValue("credentials");
+ if (cli.hasOption(SolrCLI.OPTION_CREDENTIALS.getLongOpt())) {
+ String credentials = cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt());
username = credentials.split(":")[0];
password = credentials.split(":")[1];
} else {
diff --git a/solr/core/src/java/org/apache/solr/cli/ConfigTool.java b/solr/core/src/java/org/apache/solr/cli/ConfigTool.java
index 5221a28325f..39ed60697c0 100644
--- a/solr/core/src/java/org/apache/solr/cli/ConfigTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/ConfigTool.java
@@ -79,7 +79,8 @@ public List getOptions() {
.desc("Set the property to this value; accepts JSON objects and strings.")
.build(),
SolrCLI.OPTION_SOLRURL,
- SolrCLI.OPTION_ZKHOST);
+ SolrCLI.OPTION_ZKHOST,
+ SolrCLI.OPTION_CREDENTIALS);
}
@Override
@@ -108,7 +109,9 @@ public void runImpl(CommandLine cli) throws Exception {
echo("\nPOSTing request to Config API: " + solrUrl + updatePath);
echo(jsonBody);
- try (SolrClient solrClient = SolrCLI.getSolrClient(solrUrl)) {
+ try (SolrClient solrClient =
+ SolrCLI.getSolrClient(
+ solrUrl, cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt()))) {
NamedList result = SolrCLI.postJsonToSolr(solrClient, updatePath, jsonBody);
Integer statusCode = (Integer) result.findRecursive("responseHeader", "status");
if (statusCode == 0) {
diff --git a/solr/core/src/java/org/apache/solr/cli/CreateTool.java b/solr/core/src/java/org/apache/solr/cli/CreateTool.java
index e62c42d185a..5eca1c272ed 100644
--- a/solr/core/src/java/org/apache/solr/cli/CreateTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/CreateTool.java
@@ -112,15 +112,15 @@ public List getOptions() {
.required(false)
.desc("Configuration name; default is the collection name.")
.build(),
+ SolrCLI.OPTION_CREDENTIALS,
SolrCLI.OPTION_VERBOSE);
}
@Override
public void runImpl(CommandLine cli) throws Exception {
SolrCLI.raiseLogLevelUnlessVerbose(cli);
- String solrUrl = SolrCLI.normalizeSolrUrl(cli);
- try (var solrClient = SolrCLI.getSolrClient(solrUrl)) {
+ try (var solrClient = SolrCLI.getSolrClient(cli)) {
if (SolrCLI.isCloudMode(solrClient)) {
createCollection(cli);
} else {
@@ -155,7 +155,8 @@ protected void createCore(CommandLine cli, SolrClient solrClient) throws Excepti
// convert raw JSON into user-friendly output
coreRootDirectory = (String) systemInfo.get("core_root");
- if (SolrCLI.safeCheckCoreExists(solrUrl, coreName)) {
+ if (SolrCLI.safeCheckCoreExists(
+ solrUrl, coreName, cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt()))) {
throw new IllegalArgumentException(
"\nCore '"
+ coreName
@@ -197,13 +198,16 @@ protected void createCore(CommandLine cli, SolrClient solrClient) throws Excepti
}
protected void createCollection(CommandLine cli) throws Exception {
+ Http2SolrClient.Builder builder =
+ new Http2SolrClient.Builder()
+ .withIdleTimeout(30, TimeUnit.SECONDS)
+ .withConnectionTimeout(15, TimeUnit.SECONDS)
+ .withOptionalBasicAuthCredentials(
+ cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt()));
String zkHost = SolrCLI.getZkHost(cli);
try (CloudSolrClient cloudSolrClient =
new CloudHttp2SolrClient.Builder(Collections.singletonList(zkHost), Optional.empty())
- .withInternalClientBuilder(
- new Http2SolrClient.Builder()
- .withIdleTimeout(30, TimeUnit.SECONDS)
- .withConnectionTimeout(15, TimeUnit.SECONDS))
+ .withInternalClientBuilder(builder)
.build()) {
echoIfVerbose("Connecting to ZooKeeper at " + zkHost, cli);
cloudSolrClient.connect();
@@ -275,7 +279,8 @@ protected void createCollection(CloudSolrClient cloudSolrClient, CommandLine cli
}
// since creating a collection is a heavy-weight operation, check for existence first
- if (SolrCLI.safeCheckCollectionExists(solrUrl, collectionName)) {
+ if (SolrCLI.safeCheckCollectionExists(
+ solrUrl, collectionName, cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt()))) {
throw new IllegalStateException(
"\nCollection '"
+ collectionName
diff --git a/solr/core/src/java/org/apache/solr/cli/DeleteTool.java b/solr/core/src/java/org/apache/solr/cli/DeleteTool.java
index bae371226ae..f709c9defa2 100644
--- a/solr/core/src/java/org/apache/solr/cli/DeleteTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/DeleteTool.java
@@ -84,6 +84,7 @@ public List getOptions() {
"Skip safety checks when deleting the configuration directory used by a collection.")
.build(),
SolrCLI.OPTION_ZKHOST,
+ SolrCLI.OPTION_CREDENTIALS,
SolrCLI.OPTION_VERBOSE);
}
@@ -92,7 +93,7 @@ public void runImpl(CommandLine cli) throws Exception {
SolrCLI.raiseLogLevelUnlessVerbose(cli);
String solrUrl = SolrCLI.normalizeSolrUrl(cli);
- try (var solrClient = SolrCLI.getSolrClient(solrUrl)) {
+ try (var solrClient = SolrCLI.getSolrClient(cli)) {
if (SolrCLI.isCloudMode(solrClient)) {
deleteCollection(cli);
} else {
@@ -102,13 +103,16 @@ public void runImpl(CommandLine cli) throws Exception {
}
protected void deleteCollection(CommandLine cli) throws Exception {
+ Http2SolrClient.Builder builder =
+ new Http2SolrClient.Builder()
+ .withIdleTimeout(30, TimeUnit.SECONDS)
+ .withConnectionTimeout(15, TimeUnit.SECONDS)
+ .withOptionalBasicAuthCredentials(cli.getOptionValue(("credentials")));
+
String zkHost = SolrCLI.getZkHost(cli);
try (CloudSolrClient cloudSolrClient =
new CloudHttp2SolrClient.Builder(Collections.singletonList(zkHost), Optional.empty())
- .withInternalClientBuilder(
- new Http2SolrClient.Builder()
- .withIdleTimeout(30, TimeUnit.SECONDS)
- .withConnectionTimeout(15, TimeUnit.SECONDS))
+ .withInternalClientBuilder(builder)
.build()) {
echoIfVerbose("Connecting to ZooKeeper at " + zkHost, cli);
cloudSolrClient.connect();
diff --git a/solr/core/src/java/org/apache/solr/cli/ExportTool.java b/solr/core/src/java/org/apache/solr/cli/ExportTool.java
index 9ea5435e071..e48d4ea5f91 100644
--- a/solr/core/src/java/org/apache/solr/cli/ExportTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/ExportTool.java
@@ -126,11 +126,13 @@ public List getOptions() {
.hasArg()
.required(false)
.desc("Comma separated list of fields to export. By default all fields are fetched.")
- .build());
+ .build(),
+ SolrCLI.OPTION_CREDENTIALS);
}
public abstract static class Info {
String baseurl;
+ String credentials;
String format;
boolean compress;
String query;
@@ -145,8 +147,9 @@ public abstract static class Info {
CloudSolrClient solrClient;
DocsSink sink;
- public Info(String url) {
+ public Info(String url, String credentials) {
setUrl(url);
+ setCredentials(credentials);
setOutFormat(null, "jsonl", false);
}
@@ -157,6 +160,10 @@ public void setUrl(String url) {
query = "*:*";
}
+ public void setCredentials(String credentials) {
+ this.credentials = credentials;
+ }
+
public void setLimit(String maxDocsStr) {
limit = Long.parseLong(maxDocsStr);
if (limit == -1) limit = Long.MAX_VALUE;
@@ -202,7 +209,13 @@ DocsSink getSink() {
abstract void exportDocs() throws Exception;
void fetchUniqueKey() throws SolrServerException, IOException {
- solrClient = new CloudHttp2SolrClient.Builder(Collections.singletonList(baseurl)).build();
+ Http2SolrClient.Builder builder =
+ new Http2SolrClient.Builder().withOptionalBasicAuthCredentials(credentials);
+
+ solrClient =
+ new CloudHttp2SolrClient.Builder(Collections.singletonList(baseurl))
+ .withInternalClientBuilder(builder)
+ .build();
NamedList response =
solrClient.request(
new GenericSolrRequest(
@@ -234,7 +247,8 @@ public void streamDocListInfo(long numFound, long start, Float maxScore) {}
@Override
public void runImpl(CommandLine cli) throws Exception {
String url = cli.getOptionValue("url");
- Info info = new MultiThreadedRunner(url);
+ String credentials = cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt());
+ Info info = new MultiThreadedRunner(url, credentials);
info.query = cli.getOptionValue("query", "*:*");
info.setOutFormat(
cli.getOptionValue("out"), cli.getOptionValue("format"), cli.hasOption("compress"));
@@ -491,8 +505,8 @@ static class MultiThreadedRunner extends Info {
private final long startTime;
@SuppressForbidden(reason = "Need to print out time")
- public MultiThreadedRunner(String url) {
- super(url);
+ public MultiThreadedRunner(String url, String credentials) {
+ super(url, credentials);
startTime = System.currentTimeMillis();
}
@@ -604,7 +618,7 @@ class CoreHandler {
boolean exportDocsFromCore() throws IOException, SolrServerException {
- try (SolrClient client = new Http2SolrClient.Builder(baseurl).build()) {
+ try (SolrClient client = SolrCLI.getSolrClient(baseurl, credentials)) {
expectedDocs = getDocCount(replica.getCoreName(), client, query);
GenericSolrRequest request;
ModifiableSolrParams params = new ModifiableSolrParams();
diff --git a/solr/core/src/java/org/apache/solr/cli/HealthcheckTool.java b/solr/core/src/java/org/apache/solr/cli/HealthcheckTool.java
index a657eca84bb..90b00239f48 100644
--- a/solr/core/src/java/org/apache/solr/cli/HealthcheckTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/HealthcheckTool.java
@@ -170,10 +170,15 @@ protected void runCloudTool(CloudSolrClient cloudSolrClient, CommandLine cli) th
q = new SolrQuery("*:*");
q.setRows(0);
q.set(DISTRIB, "false");
- try (var solrClientForCollection = SolrCLI.getSolrClient(coreUrl)) {
+ try (var solrClientForCollection =
+ SolrCLI.getSolrClient(
+ coreUrl, cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt()))) {
qr = solrClientForCollection.query(q);
numDocs = qr.getResults().getNumFound();
- try (var solrClient = SolrCLI.getSolrClient(replicaCoreProps.getBaseUrl())) {
+ try (var solrClient =
+ SolrCLI.getSolrClient(
+ replicaCoreProps.getBaseUrl(),
+ cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt()))) {
NamedList systemInfo =
solrClient.request(
new GenericSolrRequest(
diff --git a/solr/core/src/java/org/apache/solr/cli/PackageTool.java b/solr/core/src/java/org/apache/solr/cli/PackageTool.java
index 97ed80e7be3..a8bc4131ef4 100644
--- a/solr/core/src/java/org/apache/solr/cli/PackageTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/PackageTool.java
@@ -30,7 +30,6 @@
import org.apache.logging.log4j.core.config.Configurator;
import org.apache.lucene.util.SuppressForbidden;
import org.apache.solr.client.solrj.SolrClient;
-import org.apache.solr.client.solrj.impl.Http2SolrClient;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.util.Pair;
@@ -85,7 +84,7 @@ public void runImpl(CommandLine cli) throws Exception {
log.info("ZK: {}", zkHost);
- try (SolrClient solrClient = new Http2SolrClient.Builder(solrUrl).build()) {
+ try (SolrClient solrClient = SolrCLI.getSolrClient(cli, true)) {
packageManager = new PackageManager(solrClient, solrUrl, zkHost);
try {
repositoryManager = new RepositoryManager(solrClient, packageManager);
@@ -342,6 +341,14 @@ public List getOptions() {
.required(false)
.desc("Don't prompt for input; accept all default choices, defaults to false.")
.longOpt("noprompt")
+ .build(),
+ // u was taken, can we change that instead?
+ Option.builder("credentials")
+ .argName("credentials")
+ .hasArg()
+ .required(false)
+ .desc(
+ "Credentials in the format username:password. Example: --credentials solr:SolrRocks")
.build());
}
}
diff --git a/solr/core/src/java/org/apache/solr/cli/PostLogsTool.java b/solr/core/src/java/org/apache/solr/cli/PostLogsTool.java
index 91e1a4e6fbf..7a6c21649f2 100644
--- a/solr/core/src/java/org/apache/solr/cli/PostLogsTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/PostLogsTool.java
@@ -75,19 +75,22 @@ public List getOptions() {
.hasArg()
.required(true)
.desc("All files found at or below the root directory will be indexed.")
- .build());
+ .build(),
+ SolrCLI.OPTION_CREDENTIALS);
}
@Override
public void runImpl(CommandLine cli) throws Exception {
String url = cli.getOptionValue("url");
String rootDir = cli.getOptionValue("rootdir");
- runCommand(url, rootDir);
+ String credentials = cli.getOptionValue("credentials", null);
+ runCommand(url, rootDir, credentials);
}
- public void runCommand(String baseUrl, String root) throws IOException {
+ public void runCommand(String baseUrl, String root, String credentials) throws IOException {
- Http2SolrClient.Builder builder = new Http2SolrClient.Builder(baseUrl);
+ Http2SolrClient.Builder builder =
+ new Http2SolrClient.Builder(baseUrl).withOptionalBasicAuthCredentials(credentials);
try (SolrClient client = builder.build()) {
int rec = 0;
UpdateRequest request = new UpdateRequest();
diff --git a/solr/core/src/java/org/apache/solr/cli/PostTool.java b/solr/core/src/java/org/apache/solr/cli/PostTool.java
index b44bfe397a6..4edc2a8f3b8 100644
--- a/solr/core/src/java/org/apache/solr/cli/PostTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/PostTool.java
@@ -95,7 +95,8 @@ public List getOptions() {
.required(false)
.desc(
"sends application/json content as Solr commands to /update instead of /update/json/docs")
- .build());
+ .build(),
+ SolrCLI.OPTION_CREDENTIALS);
}
@Override
@@ -132,11 +133,24 @@ public void runImpl(CommandLine cli) throws Exception {
boolean commit = cli.hasOption("commit");
boolean optimize = cli.hasOption("optimize");
+ String credentials = cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt());
+
String[] args = cli.getArgs();
SimplePostTool spt =
new SimplePostTool(
- mode, solrUrl, auto, type, format, recursive, delay, fileTypes, out, commit, optimize,
+ mode,
+ solrUrl,
+ credentials,
+ auto,
+ type,
+ format,
+ recursive,
+ delay,
+ fileTypes,
+ out,
+ commit,
+ optimize,
args);
spt.execute();
diff --git a/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java b/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java
index 4a6ad5d5351..f77ae4cb202 100644
--- a/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java
@@ -267,7 +267,8 @@ protected void runExample(CommandLine cli, String exampleName) throws Exception
// safe check if core / collection already exists
boolean alreadyExists = false;
if (nodeStatus.get("cloud") != null) {
- if (SolrCLI.safeCheckCollectionExists(solrUrl, collectionName)) {
+ if (SolrCLI.safeCheckCollectionExists(
+ solrUrl, collectionName, cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt()))) {
alreadyExists = true;
echo(
"\nWARNING: Collection '"
@@ -276,7 +277,8 @@ protected void runExample(CommandLine cli, String exampleName) throws Exception
}
} else {
String coreName = collectionName;
- if (SolrCLI.safeCheckCoreExists(solrUrl, coreName)) {
+ if (SolrCLI.safeCheckCoreExists(
+ solrUrl, coreName, cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt()))) {
alreadyExists = true;
echo(
"\nWARNING: Core '"
@@ -536,7 +538,13 @@ protected void runCloudExample(CommandLine cli) throws Exception {
waitToSeeLiveNodes(zkHost, numNodes);
// create the collection
- String collectionName = createCloudExampleCollection(numNodes, readInput, prompt, solrUrl);
+ String collectionName =
+ createCloudExampleCollection(
+ numNodes,
+ readInput,
+ prompt,
+ solrUrl,
+ cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt()));
echo("\n\nSolrCloud example running, please visit: " + solrUrl + " \n");
}
@@ -640,7 +648,9 @@ protected Map startSolr(
String.format(
Locale.ROOT, "%s://%s:%d/solr", urlScheme, (host != null ? host : "localhost"), port);
- Map nodeStatus = checkPortConflict(solrUrl, solrHomeDir, port);
+ String credentials = null; // for now we don't need it for example tool. But we should.
+
+ Map nodeStatus = checkPortConflict(solrUrl, credentials, solrHomeDir, port);
if (nodeStatus != null)
return nodeStatus; // the server they are trying to start is already running
@@ -687,16 +697,18 @@ protected Map startSolr(
}
if (code != 0) throw new Exception("Failed to start Solr using command: " + startCmd);
- return getNodeStatus(solrUrl, maxWaitSecs);
+ return getNodeStatus(
+ solrUrl, cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt()), maxWaitSecs);
}
- protected Map checkPortConflict(String solrUrl, File solrHomeDir, int port) {
+ protected Map checkPortConflict(
+ String solrUrl, String credentials, File solrHomeDir, int port) {
// quickly check if the port is in use
if (isPortAvailable(port)) return null; // not in use ... try to start
Map nodeStatus = null;
try {
- nodeStatus = (new StatusTool()).getStatus(solrUrl);
+ nodeStatus = (new StatusTool()).getStatus(solrUrl, credentials);
} catch (Exception ignore) {
/* just trying to determine if this example is already running. */
}
@@ -745,7 +757,8 @@ protected String readExtraArgs(String[] extraArgsArr) {
}
protected String createCloudExampleCollection(
- int numNodes, Scanner readInput, boolean prompt, String solrUrl) throws Exception {
+ int numNodes, Scanner readInput, boolean prompt, String solrUrl, String credentials)
+ throws Exception {
// yay! numNodes SolrCloud nodes running
int numShards = 2;
int replicationFactor = 2;
@@ -769,7 +782,7 @@ protected String createCloudExampleCollection(
// Test for existence and then prompt to either create another collection or skip the
// creation step
- if (SolrCLI.safeCheckCollectionExists(solrUrl, collectionName)) {
+ if (SolrCLI.safeCheckCollectionExists(solrUrl, credentials, collectionName)) {
echo("\nCollection '" + collectionName + "' already exists!");
int oneOrTwo =
promptForInt(
@@ -825,7 +838,7 @@ protected String createCloudExampleCollection(
}
} else {
// must verify if default collection exists
- if (SolrCLI.safeCheckCollectionExists(solrUrl, collectionName)) {
+ if (SolrCLI.safeCheckCollectionExists(solrUrl, collectionName, credentials)) {
echo(
"\nCollection '"
+ collectionName
@@ -868,13 +881,14 @@ protected boolean isValidConfig(File configsetsDir, String config) {
return configDir.isDirectory();
}
- protected Map getNodeStatus(String solrUrl, int maxWaitSecs) throws Exception {
+ protected Map getNodeStatus(String solrUrl, String credentials, int maxWaitSecs)
+ throws Exception {
StatusTool statusTool = new StatusTool();
if (verbose) echo("\nChecking status of Solr at " + solrUrl + " ...");
URL solrURL = new URL(solrUrl);
Map nodeStatus =
- statusTool.waitToSeeSolrUp(solrUrl, maxWaitSecs, TimeUnit.SECONDS);
+ statusTool.waitToSeeSolrUp(solrUrl, credentials, maxWaitSecs, TimeUnit.SECONDS);
nodeStatus.put("baseUrl", solrUrl);
CharArr arr = new CharArr();
new JSONWriter(arr, 2).write(nodeStatus);
diff --git a/solr/core/src/java/org/apache/solr/cli/SimplePostTool.java b/solr/core/src/java/org/apache/solr/cli/SimplePostTool.java
index 1c4ceaba9e8..35842eb1c38 100644
--- a/solr/core/src/java/org/apache/solr/cli/SimplePostTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/SimplePostTool.java
@@ -112,6 +112,7 @@ public class SimplePostTool {
int delay = 0;
String fileTypes;
URL solrUrl;
+ String credentials;
OutputStream out = null;
String type;
String format;
@@ -256,10 +257,12 @@ protected static SimplePostTool parseArgsAndInit(String[] args) {
urlStr = SimplePostTool.appendParam(urlStr, params);
URL url = new URL(urlStr);
String user = null;
+ String credentials = null;
if (url.getUserInfo() != null && url.getUserInfo().trim().length() > 0) {
user = url.getUserInfo().split(":")[0];
} else if (System.getProperty(BASIC_AUTH) != null) {
user = System.getProperty(BASIC_AUTH).trim().split(":")[0];
+ credentials = System.getProperty(BASIC_AUTH).trim();
}
if (user != null) {
info("Basic Authentication enabled, user=" + user);
@@ -290,7 +293,19 @@ protected static SimplePostTool parseArgsAndInit(String[] args) {
boolean optimize = isOn(System.getProperty("optimize", DEFAULT_OPTIMIZE));
return new SimplePostTool(
- mode, url, auto, type, format, recursive, delay, fileTypes, out, commit, optimize, args);
+ mode,
+ url,
+ credentials,
+ auto,
+ type,
+ format,
+ recursive,
+ delay,
+ fileTypes,
+ out,
+ commit,
+ optimize,
+ args);
} catch (MalformedURLException e) {
fatal("System Property 'url' is not a valid URL: " + urlStr);
return null;
@@ -316,6 +331,7 @@ protected static SimplePostTool parseArgsAndInit(String[] args) {
public SimplePostTool(
String mode,
URL url,
+ String credentials,
boolean auto,
String type,
String format,
@@ -328,6 +344,7 @@ public SimplePostTool(
String[] args) {
this.mode = mode;
this.solrUrl = url;
+ this.credentials = credentials;
this.auto = auto;
this.type = type;
this.format = format;
@@ -1063,19 +1080,21 @@ public boolean postData(
return success;
}
- private static void basicAuth(HttpURLConnection urlc) throws Exception {
+ private void basicAuth(HttpURLConnection urlc) throws Exception {
if (urlc.getURL().getUserInfo() != null) {
String encoding =
Base64.getEncoder().encodeToString(urlc.getURL().getUserInfo().getBytes(US_ASCII));
urlc.setRequestProperty("Authorization", "Basic " + encoding);
- } else if (System.getProperty(BASIC_AUTH) != null) {
- String basicauth = System.getProperty(BASIC_AUTH).trim();
- if (!basicauth.contains(":")) {
- throw new Exception("System property '" + BASIC_AUTH + "' must be of format user:pass");
+ } else if (credentials != null) {
+ if (!credentials.contains(":")) {
+ throw new Exception("credentials '" + credentials + "' must be of format user:pass");
}
+ // urlc.setRequestProperty(
+ // "Authorization",
+ // "Basic " + Base64.getEncoder().encodeToString(credentials.getBytes(UTF_8)));
urlc.setRequestProperty(
"Authorization",
- "Basic " + Base64.getEncoder().encodeToString(basicauth.getBytes(UTF_8)));
+ "Basic " + Base64.getEncoder().encodeToString(credentials.getBytes(UTF_8)));
}
}
diff --git a/solr/core/src/java/org/apache/solr/cli/SolrCLI.java b/solr/core/src/java/org/apache/solr/cli/SolrCLI.java
index 3741672a952..14d9ab7f7c9 100755
--- a/solr/core/src/java/org/apache/solr/cli/SolrCLI.java
+++ b/solr/core/src/java/org/apache/solr/cli/SolrCLI.java
@@ -112,6 +112,16 @@ public class SolrCLI implements CLIO {
.desc("Recurse (true|false), default is false.")
.build();
+ public static final Option OPTION_CREDENTIALS =
+ Option.builder("u")
+ .longOpt("credentials")
+ .argName("credentials")
+ .hasArg()
+ .required(false)
+ .desc(
+ "Credentials in the format username:password. Example: --credentials solr:SolrRocks")
+ .build();
+
public static void exit(int exitStatus) {
try {
System.exit(exitStatus);
@@ -394,15 +404,44 @@ public static boolean exceptionIsAuthRelated(Exception exc) {
&& Arrays.asList(UNAUTHORIZED.code, FORBIDDEN.code).contains(((SolrException) exc).code()));
}
- public static SolrClient getSolrClient(String solrUrl) {
+ public static SolrClient getSolrClient(String solrUrl, String credentials, boolean barePath) {
// today we require all urls to end in /solr, however in the future we will need to support the
- // /api url end point instead.
+ // /api url end point instead. Eventually we want to have this method always
+ // return a bare url, and then individual calls decide if they are /solr or /api
// The /solr/ check is because sometimes a full url is passed in, like
// http://localhost:8983/solr/films_shard1_replica_n1/.
- if (!solrUrl.endsWith("/solr") && !solrUrl.contains("/solr/")) {
+ if (!barePath && !solrUrl.endsWith("/solr") && !solrUrl.contains("/solr/")) {
solrUrl = solrUrl + "/solr";
}
- return new Http2SolrClient.Builder(solrUrl).withMaxConnectionsPerHost(32).build();
+ Http2SolrClient.Builder builder =
+ new Http2SolrClient.Builder(solrUrl)
+ .withMaxConnectionsPerHost(32)
+ .withOptionalBasicAuthCredentials(credentials);
+
+ return builder.build();
+ }
+
+ /**
+ * Helper method for all the places where we assume a /solr on the url.
+ *
+ * @param solrUrl The solr url that you want the client for
+ * @param credentials The username:password for basic auth.
+ * @return The SolrClient
+ */
+ public static SolrClient getSolrClient(String solrUrl, String credentials) {
+ return getSolrClient(solrUrl, credentials, false);
+ }
+
+ public static SolrClient getSolrClient(CommandLine cli, boolean barePath) throws Exception {
+ String solrUrl = SolrCLI.normalizeSolrUrl(cli);
+ String credentials = cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt());
+ return getSolrClient(solrUrl, credentials, barePath);
+ }
+
+ public static SolrClient getSolrClient(CommandLine cli) throws Exception {
+ String solrUrl = SolrCLI.normalizeSolrUrl(cli);
+ String credentials = cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt());
+ return getSolrClient(solrUrl, credentials, false);
}
private static final String JSON_CONTENT_TYPE = "application/json";
@@ -474,7 +513,7 @@ private static void printHelp() {
*/
public static String normalizeSolrUrl(String solrUrl) {
if (solrUrl != null) {
- if (solrUrl.indexOf("/solr") > -1) { //
+ if (solrUrl.contains("/solr")) { //
String newSolrUrl = solrUrl.substring(0, solrUrl.indexOf("/solr"));
CLIO.out(
"WARNING: URLs provided to this tool needn't include Solr's context-root (e.g. \"/solr\"). Such URLs are deprecated and support for them will be removed in a future release. Correcting from ["
@@ -531,23 +570,13 @@ public static String normalizeSolrUrl(CommandLine cli) throws Exception {
* up from a running Solr instance based on the solrUrl option.
*/
public static String getZkHost(CommandLine cli) throws Exception {
+
String zkHost = cli.getOptionValue("zkHost");
if (zkHost != null && !zkHost.isBlank()) {
return zkHost;
}
- String solrUrl = cli.getOptionValue("solrUrl");
- if (solrUrl == null) {
- solrUrl = getDefaultSolrUrl();
- CLIO.getOutStream()
- .println(
- "Neither -zkHost or -solrUrl parameters provided so assuming solrUrl is "
- + solrUrl
- + ".");
- }
- solrUrl = normalizeSolrUrl(solrUrl);
-
- try (var solrClient = getSolrClient(solrUrl)) {
+ try (SolrClient solrClient = getSolrClient(cli)) {
// hit Solr to get system info
NamedList systemInfo =
solrClient.request(
@@ -570,9 +599,10 @@ public static String getZkHost(CommandLine cli) throws Exception {
return zkHost;
}
- public static boolean safeCheckCollectionExists(String solrUrl, String collection) {
+ public static boolean safeCheckCollectionExists(
+ String solrUrl, String collection, String credentials) {
boolean exists = false;
- try (var solrClient = getSolrClient(solrUrl)) {
+ try (var solrClient = getSolrClient(solrUrl, credentials)) {
NamedList existsCheckResult = solrClient.request(new CollectionAdminRequest.List());
@SuppressWarnings("unchecked")
List collections = (List) existsCheckResult.get("collections");
@@ -584,9 +614,9 @@ public static boolean safeCheckCollectionExists(String solrUrl, String collectio
}
@SuppressWarnings("unchecked")
- public static boolean safeCheckCoreExists(String solrUrl, String coreName) {
+ public static boolean safeCheckCoreExists(String solrUrl, String coreName, String credentials) {
boolean exists = false;
- try (var solrClient = getSolrClient(solrUrl)) {
+ try (var solrClient = getSolrClient(solrUrl, credentials)) {
boolean wait = false;
final long startWaitAt = System.nanoTime();
do {
diff --git a/solr/core/src/java/org/apache/solr/cli/SolrLogPostTool.java b/solr/core/src/java/org/apache/solr/cli/SolrLogPostTool.java
index cf4fee63b35..b0d6bee2de0 100644
--- a/solr/core/src/java/org/apache/solr/cli/SolrLogPostTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/SolrLogPostTool.java
@@ -45,6 +45,6 @@ public static void main(String[] args) throws Exception {
String baseUrl = args[0];
String root = args[1];
PostLogsTool postLogsTool = new PostLogsTool();
- postLogsTool.runCommand(baseUrl, root);
+ postLogsTool.runCommand(baseUrl, root, null);
}
}
diff --git a/solr/core/src/java/org/apache/solr/cli/StatusTool.java b/solr/core/src/java/org/apache/solr/cli/StatusTool.java
index 3758a60b3fe..a201fc42641 100644
--- a/solr/core/src/java/org/apache/solr/cli/StatusTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/StatusTool.java
@@ -97,7 +97,11 @@ public void runImpl(CommandLine cli) throws Exception {
int solrPort = (new URL(solrUrl)).getPort();
echo("Waiting up to " + maxWaitSecs + " seconds to see Solr running on port " + solrPort);
try {
- waitToSeeSolrUp(solrUrl, maxWaitSecs, TimeUnit.SECONDS);
+ waitToSeeSolrUp(
+ solrUrl,
+ cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt()),
+ maxWaitSecs,
+ TimeUnit.SECONDS);
echo("Started Solr server on port " + solrPort + ". Happy searching!");
} catch (TimeoutException timeout) {
throw new Exception(
@@ -106,7 +110,8 @@ public void runImpl(CommandLine cli) throws Exception {
} else {
try {
CharArr arr = new CharArr();
- new JSONWriter(arr, 2).write(getStatus(solrUrl));
+ new JSONWriter(arr, 2)
+ .write(getStatus(solrUrl, cli.getOptionValue(SolrCLI.OPTION_CREDENTIALS.getLongOpt())));
echo(arr.toString());
} catch (Exception exc) {
if (SolrCLI.exceptionIsAuthRelated(exc)) {
@@ -123,12 +128,13 @@ public void runImpl(CommandLine cli) throws Exception {
}
}
- public Map waitToSeeSolrUp(String solrUrl, long maxWait, TimeUnit unit)
- throws Exception {
+ public Map waitToSeeSolrUp(
+ String solrUrl, String credentials, long maxWait, TimeUnit unit) throws Exception {
long timeout = System.nanoTime() + TimeUnit.NANOSECONDS.convert(maxWait, unit);
while (System.nanoTime() < timeout) {
+
try {
- return getStatus(solrUrl);
+ return getStatus(solrUrl, credentials);
} catch (Exception exc) {
if (SolrCLI.exceptionIsAuthRelated(exc)) {
throw exc;
@@ -148,16 +154,20 @@ public Map waitToSeeSolrUp(String solrUrl, long maxWait, TimeUni
+ " seconds!");
}
- public Map getStatus(String solrUrl) throws Exception {
+ public Map getStatus(String solrUrl, String credentials) throws Exception {
+ try (var solrClient = SolrCLI.getSolrClient(solrUrl, credentials)) {
+ return getStatus(solrClient);
+ }
+ }
+
+ public Map getStatus(SolrClient solrClient) throws Exception {
Map status;
- try (var solrClient = SolrCLI.getSolrClient(solrUrl)) {
- NamedList systemInfo =
- solrClient.request(
- new GenericSolrRequest(SolrRequest.METHOD.GET, CommonParams.SYSTEM_INFO_PATH));
- // convert raw JSON into user-friendly output
- status = reportStatus(systemInfo, solrClient);
- }
+ NamedList systemInfo =
+ solrClient.request(
+ new GenericSolrRequest(SolrRequest.METHOD.GET, CommonParams.SYSTEM_INFO_PATH));
+ // convert raw JSON into user-friendly output
+ status = reportStatus(systemInfo, solrClient);
return status;
}
diff --git a/solr/core/src/java/org/apache/solr/cloud/CloudDescriptor.java b/solr/core/src/java/org/apache/solr/cloud/CloudDescriptor.java
index 7d013f875ec..31be35cc752 100644
--- a/solr/core/src/java/org/apache/solr/cloud/CloudDescriptor.java
+++ b/solr/core/src/java/org/apache/solr/cloud/CloudDescriptor.java
@@ -60,12 +60,7 @@ public CloudDescriptor(CoreDescriptor cd, String coreName, Properties props) {
this.nodeName = props.getProperty(CoreDescriptor.CORE_NODE_NAME);
if (StrUtils.isNullOrEmpty(nodeName)) this.nodeName = null;
this.numShards = PropertiesUtil.toInteger(props.getProperty(CloudDescriptor.NUM_SHARDS), null);
- String replicaTypeStr = props.getProperty(CloudDescriptor.REPLICA_TYPE);
- if (StrUtils.isNullOrEmpty(replicaTypeStr)) {
- this.replicaType = Replica.Type.NRT;
- } else {
- this.replicaType = Replica.Type.valueOf(replicaTypeStr);
- }
+ this.replicaType = Replica.Type.get(props.getProperty(CloudDescriptor.REPLICA_TYPE));
for (String propName : props.stringPropertyNames()) {
if (propName.startsWith(ZkController.COLLECTION_PARAM_PREFIX)) {
collectionParams.put(
diff --git a/solr/core/src/java/org/apache/solr/cloud/RecoveryStrategy.java b/solr/core/src/java/org/apache/solr/cloud/RecoveryStrategy.java
index 0a9a09968a8..ea3a3874439 100644
--- a/solr/core/src/java/org/apache/solr/cloud/RecoveryStrategy.java
+++ b/solr/core/src/java/org/apache/solr/cloud/RecoveryStrategy.java
@@ -224,7 +224,7 @@ private final void replicate(String nodeName, SolrCore core, ZkNodeProps leaderp
log.info("Attempting to replicate from [{}].", leaderUrl);
// send commit if replica could be a leader
- if (Replica.Type.isLeaderType(replicaType)) {
+ if (replicaType.leaderEligible) {
commitOnLeader(leaderUrl);
}
@@ -365,7 +365,7 @@ private final void doReplicateOnlyRecovery(SolrCore core) throws InterruptedExce
throw new SolrException(ErrorCode.SERVER_ERROR, "Cloud state still says we are leader.");
}
if (cloudDesc.isLeader()) {
- assert cloudDesc.getReplicaType() != Replica.Type.PULL;
+ assert cloudDesc.getReplicaType().leaderEligible;
// we are now the leader - no one else must have been suitable
log.warn("We have not yet recovered - but we are now the leader!");
log.info("Finished recovery process.");
diff --git a/solr/core/src/java/org/apache/solr/cloud/ShardLeaderElectionContext.java b/solr/core/src/java/org/apache/solr/cloud/ShardLeaderElectionContext.java
index c57a43980b1..6f42a82ad6d 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ShardLeaderElectionContext.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ShardLeaderElectionContext.java
@@ -17,9 +17,11 @@
package org.apache.solr.cloud;
import java.lang.invoke.MethodHandles;
+import java.util.Arrays;
import java.util.EnumSet;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.solr.cloud.overseer.OverseerAction;
import org.apache.solr.common.MapWriter;
@@ -50,6 +52,7 @@ final class ShardLeaderElectionContext extends ShardLeaderElectionContextBase {
private final CoreContainer cc;
private final SyncStrategy syncStrategy;
private final DistributedClusterStateUpdater distributedClusterStateUpdater;
+ private final EnumSet leaderEligibleReplicaTypes;
private volatile boolean isClosed = false;
@@ -65,6 +68,10 @@ public ShardLeaderElectionContext(
this.cc = cc;
this.syncStrategy = new SyncStrategy(cc);
this.distributedClusterStateUpdater = zkController.getDistributedClusterStateUpdater();
+ leaderEligibleReplicaTypes =
+ Arrays.stream(Replica.Type.values())
+ .filter(t -> t.leaderEligible)
+ .collect(Collectors.toCollection(() -> EnumSet.noneOf(Replica.Type.class)));
}
@Override
@@ -456,16 +463,16 @@ private boolean waitForReplicasToComeUp(int timeoutms) throws InterruptedExcepti
}
// on startup and after connection timeout, wait for all known shards
- if (found >= slices.getReplicas(EnumSet.of(Replica.Type.TLOG, Replica.Type.NRT)).size()) {
+ if (found >= slices.getReplicas(leaderEligibleReplicaTypes).size()) {
log.info("Enough replicas found to continue.");
return true;
} else {
if (cnt % 40 == 0) {
if (log.isInfoEnabled()) {
log.info(
- "Waiting until we see more replicas up for shard {}: total={} found={} timeoute in={}ms",
+ "Waiting until we see more replicas up for shard {}: total={} found={} timeout in={}ms",
shardId,
- slices.getReplicas(EnumSet.of(Replica.Type.TLOG, Replica.Type.NRT)).size(),
+ slices.getReplicas(leaderEligibleReplicaTypes).size(),
found,
TimeUnit.MILLISECONDS.convert(
timeoutAt - System.nanoTime(), TimeUnit.NANOSECONDS));
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 1770f2df748..0f1747173a1 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ZkController.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ZkController.java
@@ -804,7 +804,7 @@ public void giveupLeadership(CoreDescriptor cd) {
.getReplicas(
rep ->
rep.getState() == Replica.State.ACTIVE
- && rep.getType() != Type.PULL
+ && rep.getType().leaderEligible
&& liveNodes.contains(rep.getNodeName()))
.size();
@@ -1267,7 +1267,7 @@ public String register(
"Error registering SolrCore, replica is removed from clusterstate");
}
- if (replica.getType() != Type.PULL) {
+ if (replica.getType().leaderEligible) {
getCollectionTerms(collection).register(cloudDesc.getShardId(), coreZkNodeName);
}
@@ -1283,7 +1283,7 @@ public String register(
try {
// If we're a preferred leader, insert ourselves at the head of the queue
boolean joinAtHead = replica.getBool(SliceMutator.PREFERRED_LEADER_PROP, false);
- if (replica.getType() != Type.PULL) {
+ if (replica.getType().leaderEligible) {
joinElection(desc, afterExpiration, joinAtHead);
} else if (replica.getType() == Type.PULL) {
if (joinAtHead) {
@@ -1312,7 +1312,8 @@ public String register(
String ourUrl = ZkCoreNodeProps.getCoreUrl(baseUrl, coreName);
log.debug("We are {} and leader is {}", ourUrl, leaderUrl);
boolean isLeader = leaderUrl.equals(ourUrl);
- assert !(isLeader && replica.getType() == Type.PULL) : "Pull replica became leader!";
+ assert !isLeader || replica.getType().leaderEligible
+ : replica.getType().name() + " replica became leader!";
try (SolrCore core = cc.getCore(desc.getName())) {
@@ -1374,7 +1375,7 @@ public String register(
publish(desc, Replica.State.ACTIVE);
}
- if (replica.getType() != Type.PULL) {
+ if (replica.getType().leaderEligible) {
// the watcher is added to a set so multiple calls of this method will left only one
// watcher
shardTerms.addListener(
@@ -1712,13 +1713,14 @@ public void publish(
// pull replicas are excluded because their terms are not considered
if (state == Replica.State.RECOVERING
- && cd.getCloudDescriptor().getReplicaType() != Type.PULL) {
+ && cd.getCloudDescriptor().getReplicaType().leaderEligible) {
// state is used by client, state of replica can change from RECOVERING to DOWN without
// needed to finish recovery by calling this we will know that a replica actually finished
// recovery or not
getShardTerms(collection, shardId).startRecovering(coreNodeName);
}
- if (state == Replica.State.ACTIVE && cd.getCloudDescriptor().getReplicaType() != Type.PULL) {
+ if (state == Replica.State.ACTIVE
+ && cd.getCloudDescriptor().getReplicaType().leaderEligible) {
getShardTerms(collection, shardId).doneRecovering(coreNodeName);
}
@@ -1807,7 +1809,7 @@ public void unregister(String coreName, CoreDescriptor cd, boolean removeCoreFro
zkStateReader.getClusterState().getCollectionOrNull(collection);
Replica replica = (docCollection == null) ? null : docCollection.getReplica(coreNodeName);
- if (replica == null || replica.getType() != Type.PULL) {
+ if (replica == null || replica.getType().leaderEligible) {
ElectionContext context = electionContexts.remove(new ContextKey(collection, coreNodeName));
if (context != null) {
diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/AddReplicaCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/AddReplicaCmd.java
index f306fc3726c..e7c66689874 100644
--- a/solr/core/src/java/org/apache/solr/cloud/api/collections/AddReplicaCmd.java
+++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/AddReplicaCmd.java
@@ -37,7 +37,6 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.EnumMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -53,6 +52,7 @@
import org.apache.solr.common.cloud.ClusterState;
import org.apache.solr.common.cloud.DocCollection;
import org.apache.solr.common.cloud.Replica;
+import org.apache.solr.common.cloud.ReplicaCount;
import org.apache.solr.common.cloud.ReplicaPosition;
import org.apache.solr.common.cloud.Slice;
import org.apache.solr.common.cloud.ZkNodeProps;
@@ -135,23 +135,21 @@ List addReplica(
int timeout = message.getInt(TIMEOUT, 10 * 60); // 10 minutes
boolean parallel = message.getBool("parallel", false);
- Replica.Type replicaType =
- Replica.Type.valueOf(
- message
- .getStr(ZkStateReader.REPLICA_TYPE, Replica.Type.NRT.name())
- .toUpperCase(Locale.ROOT));
- EnumMap replicaTypesVsCount = new EnumMap<>(Replica.Type.class);
- replicaTypesVsCount.put(
- Replica.Type.NRT, message.getInt(NRT_REPLICAS, replicaType == Replica.Type.NRT ? 1 : 0));
- replicaTypesVsCount.put(
- Replica.Type.TLOG, message.getInt(TLOG_REPLICAS, replicaType == Replica.Type.TLOG ? 1 : 0));
- replicaTypesVsCount.put(
- Replica.Type.PULL, message.getInt(PULL_REPLICAS, replicaType == Replica.Type.PULL ? 1 : 0));
-
- int totalReplicas = 0;
- for (Map.Entry entry : replicaTypesVsCount.entrySet()) {
- totalReplicas += entry.getValue();
+ ReplicaCount numReplicas =
+ new ReplicaCount(
+ message.getInt(NRT_REPLICAS, 0),
+ message.getInt(TLOG_REPLICAS, 0),
+ message.getInt(PULL_REPLICAS, 0));
+ if (numReplicas.total() <= 0) {
+ Replica.Type replicaType =
+ Replica.Type.valueOf(
+ message
+ .getStr(ZkStateReader.REPLICA_TYPE, Replica.Type.NRT.name())
+ .toUpperCase(Locale.ROOT));
+ numReplicas.increment(replicaType);
}
+
+ int totalReplicas = numReplicas.total();
if (totalReplicas > 1) {
if (node != null) {
throw new SolrException(
@@ -173,7 +171,7 @@ List addReplica(
clusterState,
collectionName,
message,
- replicaTypesVsCount,
+ numReplicas,
ccc.getCoreContainer())
.stream()
.map(
@@ -255,10 +253,10 @@ private ModifiableSolrParams getReplicaParams(
CreateReplica createReplica)
throws InterruptedException, KeeperException {
if (!skipCreateReplicaInClusterState) {
- ZkNodeProps props =
- new ZkNodeProps(
+ Map replicaProps =
+ Utils.makeMap(
Overseer.QUEUE_OPERATION,
- ADDREPLICA.toLower(),
+ (Object) ADDREPLICA.toLower(),
ZkStateReader.COLLECTION_PROP,
collectionName,
ZkStateReader.SHARD_ID_PROP,
@@ -274,8 +272,11 @@ private ModifiableSolrParams getReplicaParams(
ZkStateReader.REPLICA_TYPE,
createReplica.replicaType.name());
if (createReplica.coreNodeName != null) {
- props = props.plus(ZkStateReader.CORE_NODE_NAME_PROP, createReplica.coreNodeName);
+ replicaProps.put(ZkStateReader.CORE_NODE_NAME_PROP, createReplica.coreNodeName);
}
+ CollectionHandlingUtils.addPropertyParams(message, replicaProps);
+
+ ZkNodeProps props = new ZkNodeProps(replicaProps);
if (ccc.getDistributedClusterStateUpdater().isDistributedStateUpdate()) {
ccc.getDistributedClusterStateUpdater()
.doSingleStateUpdate(
@@ -342,6 +343,9 @@ private ModifiableSolrParams getReplicaParams(
if (createReplica.coreNodeName != null) {
params.set(CoreAdminParams.CORE_NODE_NAME, createReplica.coreNodeName);
}
+ // Inherit user-defined properties from collection.
+ CollectionHandlingUtils.addPropertyParams(coll, params);
+ // Inherit user-defined properties from replica.
CollectionHandlingUtils.addPropertyParams(message, params);
return params;
@@ -401,7 +405,7 @@ public static List buildReplicaPositions(
ClusterState clusterState,
String collectionName,
ZkNodeProps message,
- EnumMap replicaTypeVsCount,
+ ReplicaCount numReplicas,
CoreContainer coreContainer)
throws IOException, InterruptedException {
boolean skipCreateReplicaInClusterState =
@@ -409,11 +413,7 @@ public static List buildReplicaPositions(
boolean skipNodeAssignment = message.getBool(CollectionAdminParams.SKIP_NODE_ASSIGNMENT, false);
String sliceName = message.getStr(SHARD_ID_PROP);
DocCollection collection = clusterState.getCollection(collectionName);
-
- int numNrtReplicas = replicaTypeVsCount.get(Replica.Type.NRT);
- int numPullReplicas = replicaTypeVsCount.get(Replica.Type.PULL);
- int numTlogReplicas = replicaTypeVsCount.get(Replica.Type.TLOG);
- int totalReplicas = numNrtReplicas + numPullReplicas + numTlogReplicas;
+ int totalReplicas = numReplicas.total();
String node = message.getStr(CoreAdminParams.NODE);
Object createNodeSetStr = message.get(CollectionHandlingUtils.CREATE_NODE_SET);
@@ -432,9 +432,7 @@ public static List buildReplicaPositions(
clusterState,
collection.getName(),
sliceName,
- numNrtReplicas,
- numTlogReplicas,
- numPullReplicas,
+ numReplicas,
createNodeSetStr,
cloudManager,
coreContainer);
@@ -452,9 +450,9 @@ public static List buildReplicaPositions(
// the same node, but we've got to accommodate.
positions = new ArrayList<>(totalReplicas);
int i = 0;
- for (Map.Entry entry : replicaTypeVsCount.entrySet()) {
- for (int j = 0; j < entry.getValue(); j++) {
- positions.add(new ReplicaPosition(collectionName, sliceName, i++, entry.getKey(), node));
+ for (Replica.Type type : Replica.Type.values()) {
+ for (int j = 0; j < numReplicas.get(type); j++) {
+ positions.add(new ReplicaPosition(collectionName, sliceName, i++, type, node));
}
}
}
diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/Assign.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/Assign.java
index 6304e522209..4f5f2482dcf 100644
--- a/solr/core/src/java/org/apache/solr/cloud/api/collections/Assign.java
+++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/Assign.java
@@ -49,6 +49,7 @@
import org.apache.solr.common.cloud.ClusterState;
import org.apache.solr.common.cloud.DocCollection;
import org.apache.solr.common.cloud.Replica;
+import org.apache.solr.common.cloud.ReplicaCount;
import org.apache.solr.common.cloud.ReplicaPosition;
import org.apache.solr.common.cloud.Slice;
import org.apache.solr.common.cloud.ZkNodeProps;
@@ -325,20 +326,18 @@ public static List getNodesForNewReplicas(
ClusterState clusterState,
String collectionName,
String shard,
- int nrtReplicas,
- int tlogReplicas,
- int pullReplicas,
+ ReplicaCount numReplicas,
Object createNodeSet,
SolrCloudManager cloudManager,
CoreContainer coreContainer)
throws IOException, InterruptedException, AssignmentException {
- log.debug(
- "getNodesForNewReplicas() shard: {} , nrtReplicas : {} , tlogReplicas: {} , pullReplicas: {} , createNodeSet {}",
- shard,
- nrtReplicas,
- tlogReplicas,
- pullReplicas,
- createNodeSet);
+ if (log.isDebugEnabled()) {
+ log.debug(
+ "getNodesForNewReplicas() shard={}, {} , createNodeSet={}",
+ shard,
+ numReplicas,
+ createNodeSet);
+ }
List createNodeList;
if (createNodeSet instanceof List) {
@@ -361,9 +360,7 @@ public static List getNodesForNewReplicas(
new AssignRequestBuilder()
.forCollection(collectionName)
.forShard(Collections.singletonList(shard))
- .assignNrtReplicas(nrtReplicas)
- .assignTlogReplicas(tlogReplicas)
- .assignPullReplicas(pullReplicas)
+ .assignReplicas(numReplicas)
.onNodes(createNodeList)
.build();
AssignStrategy assignStrategy = createAssignStrategy(coreContainer);
@@ -501,23 +498,17 @@ public static class AssignRequest {
public final String collectionName;
public final List shardNames;
public final List nodes;
- public final int numNrtReplicas;
- public final int numTlogReplicas;
- public final int numPullReplicas;
+ public final ReplicaCount numReplicas;
public AssignRequest(
String collectionName,
List shardNames,
List nodes,
- int numNrtReplicas,
- int numTlogReplicas,
- int numPullReplicas) {
+ ReplicaCount numReplicas) {
this.collectionName = collectionName;
this.shardNames = shardNames;
this.nodes = nodes;
- this.numNrtReplicas = numNrtReplicas;
- this.numTlogReplicas = numTlogReplicas;
- this.numPullReplicas = numPullReplicas;
+ this.numReplicas = numReplicas;
}
}
@@ -525,9 +516,11 @@ public static class AssignRequestBuilder {
private String collectionName;
private List shardNames;
private List nodes;
- private int numNrtReplicas;
- private int numTlogReplicas;
- private int numPullReplicas;
+ private ReplicaCount numReplicas;
+
+ public AssignRequestBuilder() {
+ this.numReplicas = ReplicaCount.empty();
+ }
public AssignRequestBuilder forCollection(String collectionName) {
this.collectionName = collectionName;
@@ -544,26 +537,15 @@ public AssignRequestBuilder onNodes(List nodes) {
return this;
}
- public AssignRequestBuilder assignNrtReplicas(int numNrtReplicas) {
- this.numNrtReplicas = numNrtReplicas;
- return this;
- }
-
- public AssignRequestBuilder assignTlogReplicas(int numTlogReplicas) {
- this.numTlogReplicas = numTlogReplicas;
- return this;
- }
-
- public AssignRequestBuilder assignPullReplicas(int numPullReplicas) {
- this.numPullReplicas = numPullReplicas;
+ public AssignRequestBuilder assignReplicas(ReplicaCount numReplicas) {
+ this.numReplicas = numReplicas;
return this;
}
public AssignRequest build() {
Objects.requireNonNull(collectionName, "The collectionName cannot be null");
Objects.requireNonNull(shardNames, "The shard names cannot be null");
- return new AssignRequest(
- collectionName, shardNames, nodes, numNrtReplicas, numTlogReplicas, numPullReplicas);
+ return new AssignRequest(collectionName, shardNames, nodes, numReplicas);
}
}
diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateCollectionCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateCollectionCmd.java
index 6a07970953e..a00b01b2370 100644
--- a/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateCollectionCmd.java
+++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateCollectionCmd.java
@@ -71,6 +71,7 @@
import org.apache.solr.common.cloud.PerReplicaStates;
import org.apache.solr.common.cloud.PerReplicaStatesOps;
import org.apache.solr.common.cloud.Replica;
+import org.apache.solr.common.cloud.ReplicaCount;
import org.apache.solr.common.cloud.ReplicaPosition;
import org.apache.solr.common.cloud.ZkNodeProps;
import org.apache.solr.common.cloud.ZkStateReader;
@@ -137,7 +138,9 @@ public void call(ClusterState clusterState, ZkNodeProps message, NamedList shardNames = populateShardNames(message, router);
- checkReplicaTypes(message);
+ ReplicaCount numReplicas = getNumReplicas(message);
+ numReplicas.validate();
+
DocCollection newColl = null;
final String collectionPath = DocCollection.getCollectionPath(collectionName);
@@ -239,7 +242,8 @@ public void call(ClusterState clusterState, ZkNodeProps message, NamedList buildReplicaPositions(
SolrCloudManager cloudManager,
ClusterState clusterState,
ZkNodeProps message,
- List shardNames)
+ List shardNames,
+ ReplicaCount numReplicas)
throws IOException, InterruptedException, Assign.AssignmentException {
final String collectionName = message.getStr(NAME);
// look at the replication factor and see if it matches reality
// if it does not, find best nodes to create more cores
- int numTlogReplicas = message.getInt(TLOG_REPLICAS, 0);
- int numNrtReplicas =
- message.getInt(
- NRT_REPLICAS, message.getInt(REPLICATION_FACTOR, numTlogReplicas > 0 ? 0 : 1));
- int numPullReplicas = message.getInt(PULL_REPLICAS, 0);
- int numSlices = shardNames.size();
cloudManager = wrapCloudManager(clusterState, cloudManager);
// we need to look at every node and see how many cores it serves
@@ -516,7 +515,7 @@ private static List buildReplicaPositions(
replicaPositions = new ArrayList<>();
} else {
- int totalNumReplicas = numNrtReplicas + numTlogReplicas + numPullReplicas;
+ int totalNumReplicas = numReplicas.total();
if (totalNumReplicas > nodeList.size()) {
log.warn(
"Specified number of replicas of {} on collection {} is higher than the number of Solr instances currently live or live and part of your {}({}). {}",
@@ -531,9 +530,7 @@ private static List buildReplicaPositions(
new Assign.AssignRequestBuilder()
.forCollection(collectionName)
.forShard(shardNames)
- .assignNrtReplicas(numNrtReplicas)
- .assignTlogReplicas(numTlogReplicas)
- .assignPullReplicas(numPullReplicas)
+ .assignReplicas(numReplicas)
.onNodes(nodeList)
.build();
Assign.AssignStrategy assignStrategy = Assign.createAssignStrategy(coreContainer);
@@ -571,18 +568,6 @@ public ClusterStateProvider getClusterStateProvider() {
};
}
- public static void checkReplicaTypes(ZkNodeProps message) {
- int numTlogReplicas = message.getInt(TLOG_REPLICAS, 0);
- int numNrtReplicas =
- message.getInt(
- NRT_REPLICAS, message.getInt(REPLICATION_FACTOR, numTlogReplicas > 0 ? 0 : 1));
-
- if (numNrtReplicas + numTlogReplicas <= 0) {
- throw new SolrException(
- ErrorCode.BAD_REQUEST, NRT_REPLICAS + " + " + TLOG_REPLICAS + " must be greater than 0");
- }
- }
-
public static List populateShardNames(ZkNodeProps message, String router) {
List shardNames = new ArrayList<>();
Integer numSlices = message.getInt(CollectionHandlingUtils.NUM_SLICES, null);
@@ -605,6 +590,14 @@ public static List populateShardNames(ZkNodeProps message, String router
return shardNames;
}
+ private static ReplicaCount getNumReplicas(ZkNodeProps message) {
+ int numTlogReplicas = message.getInt(TLOG_REPLICAS, 0);
+ int numNrtReplicas =
+ message.getInt(
+ NRT_REPLICAS, message.getInt(REPLICATION_FACTOR, numTlogReplicas > 0 ? 0 : 1));
+ return new ReplicaCount(numNrtReplicas, numTlogReplicas, message.getInt(PULL_REPLICAS, 0));
+ }
+
String getConfigName(String coll, ZkNodeProps message) throws IOException {
String configName = message.getStr(COLL_CONF);
diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateShardCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateShardCmd.java
index f0878e39df6..495f6856bc7 100644
--- a/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateShardCmd.java
+++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateShardCmd.java
@@ -32,6 +32,8 @@
import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.ClusterState;
import org.apache.solr.common.cloud.DocCollection;
+import org.apache.solr.common.cloud.Replica;
+import org.apache.solr.common.cloud.ReplicaCount;
import org.apache.solr.common.cloud.ZkNodeProps;
import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.common.params.CommonAdminParams;
@@ -70,20 +72,8 @@ public void call(ClusterState clusterState, ZkNodeProps message, NamedList verifyReplicaAvailability(List sourceReplicas, Clus
// can't delete the only replica in existence
res.add(coll + "/" + shard + "/" + replicaName + ", type=" + sourceReplica.getType());
} else { // check replica types
- int otherNonPullReplicas = 0;
+ int otherLeaderEligibleReplicas = 0;
for (Replica r : slice.getReplicas()) {
- if (!r.getName().equals(replicaName) && !r.getType().equals(Replica.Type.PULL)) {
- otherNonPullReplicas++;
+ if (!r.getName().equals(replicaName) && r.getType().leaderEligible) {
+ otherLeaderEligibleReplicas++;
}
}
- // can't delete - there are no other non-pull replicas
- if (otherNonPullReplicas == 0) {
+ // can't delete - there are no other replicas that can be leader
+ if (otherLeaderEligibleReplicas == 0) {
res.add(coll + "/" + shard + "/" + replicaName + ", type=" + sourceReplica.getType());
}
}
diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/LeaderRecoveryWatcher.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/LeaderRecoveryWatcher.java
index 9894d1aec23..d1fe62ec2b0 100644
--- a/solr/core/src/java/org/apache/solr/cloud/api/collections/LeaderRecoveryWatcher.java
+++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/LeaderRecoveryWatcher.java
@@ -73,7 +73,7 @@ public boolean onStateChanged(Set liveNodes, DocCollection collectionSta
// as long as it's active and can become a leader, in which case we don't have to wait
// for recovery of specifically the one that we've just added
if (!replica.getName().equals(replicaId)) {
- if (replica.getType().equals(Replica.Type.PULL)) { // not eligible for leader election
+ if (!replica.getType().leaderEligible) {
continue;
}
// check its state
diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/MigrateReplicasCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/MigrateReplicasCmd.java
index 29616737574..3912e096cb6 100644
--- a/solr/core/src/java/org/apache/solr/cloud/api/collections/MigrateReplicasCmd.java
+++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/MigrateReplicasCmd.java
@@ -30,6 +30,7 @@
import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.ClusterState;
import org.apache.solr.common.cloud.Replica;
+import org.apache.solr.common.cloud.ReplicaCount;
import org.apache.solr.common.cloud.ReplicaPosition;
import org.apache.solr.common.cloud.ZkNodeProps;
import org.apache.solr.common.cloud.ZkStateReader;
@@ -95,14 +96,11 @@ public void call(ClusterState state, ZkNodeProps message, NamedList resu
List assignRequests = new ArrayList<>(sourceReplicas.size());
List targetNodeList = new ArrayList<>(targetNodes);
for (Replica sourceReplica : sourceReplicas) {
- Replica.Type replicaType = sourceReplica.getType();
Assign.AssignRequest assignRequest =
new Assign.AssignRequestBuilder()
.forCollection(sourceReplica.getCollection())
.forShard(Collections.singletonList(sourceReplica.getShard()))
- .assignNrtReplicas(replicaType == Replica.Type.NRT ? 1 : 0)
- .assignTlogReplicas(replicaType == Replica.Type.TLOG ? 1 : 0)
- .assignPullReplicas(replicaType == Replica.Type.PULL ? 1 : 0)
+ .assignReplicas(ReplicaCount.of(sourceReplica.getType(), 1))
.onNodes(targetNodeList)
.build();
assignRequests.add(assignRequest);
diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/ReplaceNodeCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/ReplaceNodeCmd.java
index fe47f96cc6f..ee3324f628f 100644
--- a/solr/core/src/java/org/apache/solr/cloud/api/collections/ReplaceNodeCmd.java
+++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/ReplaceNodeCmd.java
@@ -27,6 +27,7 @@
import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.ClusterState;
import org.apache.solr.common.cloud.Replica;
+import org.apache.solr.common.cloud.ReplicaCount;
import org.apache.solr.common.cloud.ReplicaPosition;
import org.apache.solr.common.cloud.ZkNodeProps;
import org.apache.solr.common.cloud.ZkStateReader;
@@ -79,17 +80,11 @@ public void call(ClusterState state, ZkNodeProps message, NamedList resu
if (target == null || target.isEmpty()) {
List assignRequests = new ArrayList<>(sourceReplicas.size());
for (Replica sourceReplica : sourceReplicas) {
- Replica.Type replicaType = sourceReplica.getType();
- int numNrtReplicas = replicaType == Replica.Type.NRT ? 1 : 0;
- int numTlogReplicas = replicaType == Replica.Type.TLOG ? 1 : 0;
- int numPullReplicas = replicaType == Replica.Type.PULL ? 1 : 0;
Assign.AssignRequest assignRequest =
new Assign.AssignRequestBuilder()
.forCollection(sourceReplica.getCollection())
.forShard(Collections.singletonList(sourceReplica.getShard()))
- .assignNrtReplicas(numNrtReplicas)
- .assignTlogReplicas(numTlogReplicas)
- .assignPullReplicas(numPullReplicas)
+ .assignReplicas(ReplicaCount.of(sourceReplica.getType(), 1))
.onNodes(
ccc.getSolrCloudManager().getClusterStateProvider().getLiveNodes().stream()
.filter(node -> !node.equals(source))
diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/RestoreCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/RestoreCmd.java
index 7621750a5f5..c3bc1a19de0 100644
--- a/solr/core/src/java/org/apache/solr/cloud/api/collections/RestoreCmd.java
+++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/RestoreCmd.java
@@ -60,6 +60,7 @@
import org.apache.solr.common.cloud.DocCollection.CollectionStateProps;
import org.apache.solr.common.cloud.ImplicitDocRouter;
import org.apache.solr.common.cloud.Replica;
+import org.apache.solr.common.cloud.ReplicaCount;
import org.apache.solr.common.cloud.ReplicaPosition;
import org.apache.solr.common.cloud.Slice;
import org.apache.solr.common.cloud.ZkNodeProps;
@@ -103,8 +104,7 @@ public void call(ClusterState state, ZkNodeProps message, NamedList resu
} else {
RestoreOnANewCollection restoreOnANewCollection =
new RestoreOnANewCollection(message, restoreContext.backupCollectionState);
- restoreOnANewCollection.validate(
- restoreContext.backupCollectionState, restoreContext.nodeList.size());
+ restoreOnANewCollection.validate();
restoreOnANewCollection.process(results, restoreContext);
}
}
@@ -221,27 +221,27 @@ public void close() throws IOException {
* @see RestoreOnExistingCollection
*/
private class RestoreOnANewCollection {
- private int numNrtReplicas;
- private int numTlogReplicas;
- private int numPullReplicas;
- private ZkNodeProps message;
+ private final ReplicaCount numReplicas;
+ private final ZkNodeProps message;
private RestoreOnANewCollection(ZkNodeProps message, DocCollection backupCollectionState) {
this.message = message;
+ int numNrtReplicas;
if (message.get(REPLICATION_FACTOR) != null) {
- this.numNrtReplicas = message.getInt(REPLICATION_FACTOR, 0);
+ numNrtReplicas = message.getInt(REPLICATION_FACTOR, 0);
} else if (message.get(NRT_REPLICAS) != null) {
- this.numNrtReplicas = message.getInt(NRT_REPLICAS, 0);
+ numNrtReplicas = message.getInt(NRT_REPLICAS, 0);
} else {
// replicationFactor and nrtReplicas is always in sync after SOLR-11676
// pick from cluster state of the backed up collection
- this.numNrtReplicas = backupCollectionState.getReplicationFactor();
+ numNrtReplicas = backupCollectionState.getReplicationFactor();
}
- this.numTlogReplicas =
- getInt(message, TLOG_REPLICAS, backupCollectionState.getNumTlogReplicas(), 0);
- this.numPullReplicas =
- getInt(message, PULL_REPLICAS, backupCollectionState.getNumPullReplicas(), 0);
+ this.numReplicas =
+ new ReplicaCount(
+ numNrtReplicas,
+ getInt(message, TLOG_REPLICAS, backupCollectionState.getNumTlogReplicas(), 0),
+ getInt(message, PULL_REPLICAS, backupCollectionState.getNumPullReplicas(), 0));
}
public void process(NamedList results, RestoreContext rc) throws Exception {
@@ -307,10 +307,8 @@ public void process(NamedList results, RestoreContext rc) throws Excepti
log.info("Completed restoring collection={} backupName={}", restoreCollection, rc.backupName);
}
- private void validate(DocCollection backupCollectionState, int availableNodeCount) {
- int numShards = backupCollectionState.getActiveSlices().size();
- int totalReplicasPerShard = numNrtReplicas + numTlogReplicas + numPullReplicas;
- assert totalReplicasPerShard > 0;
+ private void validate() {
+ assert numReplicas.total() > 0;
}
private void uploadConfig(
@@ -343,10 +341,10 @@ private void createCoreLessCollection(
propMap.put(Overseer.QUEUE_OPERATION, CREATE.toString());
// mostly true. Prevents autoCreated=true in the collection state.
propMap.put("fromApi", "true");
- propMap.put(REPLICATION_FACTOR, numNrtReplicas);
- propMap.put(NRT_REPLICAS, numNrtReplicas);
- propMap.put(TLOG_REPLICAS, numTlogReplicas);
- propMap.put(PULL_REPLICAS, numPullReplicas);
+ propMap.put(REPLICATION_FACTOR, numReplicas.get(Replica.Type.NRT));
+ propMap.put(NRT_REPLICAS, numReplicas.get(Replica.Type.NRT));
+ propMap.put(TLOG_REPLICAS, numReplicas.get(Replica.Type.TLOG));
+ propMap.put(PULL_REPLICAS, numReplicas.get(Replica.Type.PULL));
// inherit settings from input API, defaulting to the backup's setting. Ex: replicationFactor
for (String collProp : CollectionHandlingUtils.COLLECTION_PROPS_AND_DEFAULTS.keySet()) {
@@ -427,9 +425,7 @@ private List getReplicaPositions(
new Assign.AssignRequestBuilder()
.forCollection(restoreCollection)
.forShard(sliceNames)
- .assignNrtReplicas(numNrtReplicas)
- .assignTlogReplicas(numTlogReplicas)
- .assignPullReplicas(numPullReplicas)
+ .assignReplicas(numReplicas)
.onNodes(nodeList)
.build();
Assign.AssignStrategy assignStrategy = Assign.createAssignStrategy(ccc.getCoreContainer());
@@ -453,20 +449,7 @@ private void createSingleReplicaPerShard(
propMap.put(Overseer.QUEUE_OPERATION, CREATESHARD);
propMap.put(COLLECTION_PROP, restoreCollection.getName());
propMap.put(SHARD_ID_PROP, sliceName);
-
- if (numNrtReplicas >= 1) {
- propMap.put(REPLICA_TYPE, Replica.Type.NRT.name());
- } else if (numTlogReplicas >= 1) {
- propMap.put(REPLICA_TYPE, Replica.Type.TLOG.name());
- } else {
- throw new SolrException(
- ErrorCode.BAD_REQUEST,
- "Unexpected number of replicas, replicationFactor, "
- + Replica.Type.NRT
- + " or "
- + Replica.Type.TLOG
- + " must be greater than 0");
- }
+ propMap.put(REPLICA_TYPE, numReplicas.getLeaderType().name());
// Get the first node matching the shard to restore in
String node;
@@ -554,7 +537,7 @@ private void addReplicasToShards(
List replicaPositions,
String asyncId)
throws Exception {
- int totalReplicasPerShard = numNrtReplicas + numTlogReplicas + numPullReplicas;
+ int totalReplicasPerShard = numReplicas.total();
if (totalReplicasPerShard > 1) {
if (log.isInfoEnabled()) {
log.info("Adding replicas to restored collection={}", restoreCollection.getName());
@@ -562,28 +545,19 @@ private void addReplicasToShards(
for (Slice slice : restoreCollection.getSlices()) {
// Add the remaining replicas for each shard, considering it's type
- int createdNrtReplicas = 0, createdTlogReplicas = 0, createdPullReplicas = 0;
-
- // We already created either a NRT or an TLOG replica as leader
- if (numNrtReplicas > 0) {
- createdNrtReplicas++;
- } else if (numTlogReplicas > 0) {
- createdTlogReplicas++;
- }
+ // We already created either a replica as leader.
+ ReplicaCount createdReplicas = ReplicaCount.of(numReplicas.getLeaderType(), 1);
for (int i = 1; i < totalReplicasPerShard; i++) {
- Replica.Type typeToCreate;
- if (createdNrtReplicas < numNrtReplicas) {
- createdNrtReplicas++;
- typeToCreate = Replica.Type.NRT;
- } else if (createdTlogReplicas < numTlogReplicas) {
- createdTlogReplicas++;
- typeToCreate = Replica.Type.TLOG;
- } else {
- createdPullReplicas++;
- typeToCreate = Replica.Type.PULL;
- assert createdPullReplicas <= numPullReplicas : "Unexpected number of replicas";
+ Replica.Type typeToCreate = null;
+ for (Replica.Type type : Replica.Type.values()) {
+ if (createdReplicas.get(type) < numReplicas.get(type)) {
+ createdReplicas.increment(type);
+ typeToCreate = type;
+ break;
+ }
}
+ assert null != typeToCreate : "Unexpected number of replicas";
if (log.isDebugEnabled()) {
log.debug(
diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java
index 0060eb676af..92c93e18b0e 100644
--- a/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java
+++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java
@@ -40,7 +40,6 @@
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.SolrResponse;
@@ -63,6 +62,7 @@
import org.apache.solr.common.cloud.DocRouter;
import org.apache.solr.common.cloud.PlainIdRouter;
import org.apache.solr.common.cloud.Replica;
+import org.apache.solr.common.cloud.ReplicaCount;
import org.apache.solr.common.cloud.ReplicaPosition;
import org.apache.solr.common.cloud.Slice;
import org.apache.solr.common.cloud.ZkNodeProps;
@@ -228,44 +228,24 @@ public boolean split(ClusterState clusterState, ZkNodeProps message, NamedList subShardNames = new ArrayList<>();
// reproduce the currently existing number of replicas per type
- AtomicInteger numNrt = new AtomicInteger();
- AtomicInteger numTlog = new AtomicInteger();
- AtomicInteger numPull = new AtomicInteger();
- parentSlice
- .getReplicas()
- .forEach(
- r -> {
- switch (r.getType()) {
- case NRT:
- numNrt.incrementAndGet();
- break;
- case TLOG:
- numTlog.incrementAndGet();
- break;
- case PULL:
- numPull.incrementAndGet();
- }
- });
- int repFactor = numNrt.get() + numTlog.get() + numPull.get();
+ ReplicaCount numReplicas = ReplicaCount.empty();
+ parentSlice.getReplicas().forEach(r -> numReplicas.increment(r.getType()));
+ int repFactor = numReplicas.total();
boolean success = false;
try {
// type of the first subreplica will be the same as leader
- boolean firstNrtReplica = parentShardLeader.getType() == Replica.Type.NRT;
+ Replica.Type leaderReplicaType = parentShardLeader.getType();
// verify that we indeed have the right number of correct replica types
- if ((firstNrtReplica && numNrt.get() < 1) || (!firstNrtReplica && numTlog.get() < 1)) {
+ if (numReplicas.get(leaderReplicaType) < 1) {
throw new SolrException(
SolrException.ErrorCode.SERVER_ERROR,
"aborting split - inconsistent replica types in collection "
+ collectionName
- + ": nrt="
- + numNrt.get()
- + ", tlog="
- + numTlog.get()
- + ", pull="
- + numPull.get()
+ + ": "
+ + numReplicas
+ ", shard leader type is "
- + parentShardLeader.getType());
+ + leaderReplicaType);
}
// check for the lock
@@ -340,7 +320,7 @@ public boolean split(ClusterState clusterState, ZkNodeProps message, NamedList subRanges,
List subSlices,
List subShardNames,
- boolean firstReplicaNrt) {
+ Replica.Type replicaType) {
String splitKey = message.getStr("split.key");
String rangesStr = message.getStr(CoreAdminParams.RANGES);
String fuzzStr = message.getStr(CommonAdminParams.SPLIT_FUZZ, "0");
@@ -1211,10 +1183,7 @@ public static String fillRanges(
subSlices.add(subSlice);
String subShardName =
Assign.buildSolrCoreName(
- cloudManager.getDistribStateManager(),
- collection,
- subSlice,
- firstReplicaNrt ? Replica.Type.NRT : Replica.Type.TLOG);
+ cloudManager.getDistribStateManager(), collection, subSlice, replicaType);
subShardNames.add(subShardName);
}
return rangesStr;
diff --git a/solr/core/src/java/org/apache/solr/cloud/overseer/ClusterStateMutator.java b/solr/core/src/java/org/apache/solr/cloud/overseer/ClusterStateMutator.java
index 2c625b2c5c4..11b3795745b 100644
--- a/solr/core/src/java/org/apache/solr/cloud/overseer/ClusterStateMutator.java
+++ b/solr/core/src/java/org/apache/solr/cloud/overseer/ClusterStateMutator.java
@@ -125,6 +125,13 @@ public ZkWriteCommand createCollection(ClusterState clusterState, ZkNodeProps me
collectionProps.put(ZkStateReader.CONFIGNAME_PROP, configName);
}
+ // add user-defined properties
+ for (String prop : message.keySet()) {
+ if (prop.startsWith(CollectionAdminParams.PROPERTY_PREFIX)) {
+ collectionProps.put(prop, message.get(prop));
+ }
+ }
+
assert !collectionProps.containsKey(CollectionAdminParams.COLL_CONF);
DocCollection newCollection =
DocCollection.create(
diff --git a/solr/core/src/java/org/apache/solr/cloud/overseer/SliceMutator.java b/solr/core/src/java/org/apache/solr/cloud/overseer/SliceMutator.java
index c83a965d5a1..c016fa5489b 100644
--- a/solr/core/src/java/org/apache/solr/cloud/overseer/SliceMutator.java
+++ b/solr/core/src/java/org/apache/solr/cloud/overseer/SliceMutator.java
@@ -94,25 +94,30 @@ public ZkWriteCommand addReplica(ClusterState clusterState, ZkNodeProps message)
cloudManager
.getClusterStateProvider()
.getClusterProperty(ZkStateReader.URL_SCHEME, "http"));
- Replica replica =
- new Replica(
- coreNodeName,
- Utils.makeMap(
- ZkStateReader.CORE_NAME_PROP,
- message.getStr(ZkStateReader.CORE_NAME_PROP),
- ZkStateReader.STATE_PROP,
- message.getStr(ZkStateReader.STATE_PROP),
- ZkStateReader.NODE_NAME_PROP,
- nodeName,
- ZkStateReader.BASE_URL_PROP,
- baseUrl,
- ZkStateReader.FORCE_SET_STATE_PROP,
- "false",
- ZkStateReader.REPLICA_TYPE,
- message.get(ZkStateReader.REPLICA_TYPE)),
- coll,
- slice);
+ Map replicaProps =
+ Utils.makeMap(
+ ZkStateReader.CORE_NAME_PROP,
+ message.getStr(ZkStateReader.CORE_NAME_PROP),
+ ZkStateReader.STATE_PROP,
+ message.getStr(ZkStateReader.STATE_PROP),
+ ZkStateReader.NODE_NAME_PROP,
+ nodeName,
+ ZkStateReader.BASE_URL_PROP,
+ baseUrl,
+ ZkStateReader.FORCE_SET_STATE_PROP,
+ "false",
+ ZkStateReader.REPLICA_TYPE,
+ message.get(ZkStateReader.REPLICA_TYPE));
+
+ // add user-defined properties
+ for (String prop : message.keySet()) {
+ if (prop.startsWith(CollectionAdminParams.PROPERTY_PREFIX)) {
+ replicaProps.put(prop, message.get(prop));
+ }
+ }
+
+ Replica replica = new Replica(coreNodeName, replicaProps, coll, slice);
return new ZkWriteCommand(coll, updateReplica(collection, sl, replica.getName(), replica));
}
diff --git a/solr/core/src/java/org/apache/solr/cluster/events/impl/CollectionsRepairEventListener.java b/solr/core/src/java/org/apache/solr/cluster/events/impl/CollectionsRepairEventListener.java
index 2c621f090ba..05a243f38ee 100644
--- a/solr/core/src/java/org/apache/solr/cluster/events/impl/CollectionsRepairEventListener.java
+++ b/solr/core/src/java/org/apache/solr/cluster/events/impl/CollectionsRepairEventListener.java
@@ -41,7 +41,7 @@
import org.apache.solr.cluster.events.ClusterEventListener;
import org.apache.solr.cluster.events.NodesDownEvent;
import org.apache.solr.common.cloud.ClusterState;
-import org.apache.solr.common.cloud.Replica;
+import org.apache.solr.common.cloud.ReplicaCount;
import org.apache.solr.common.cloud.ReplicaPosition;
import org.apache.solr.common.util.SolrNamedThreadFactory;
import org.apache.solr.core.CoreContainer;
@@ -171,39 +171,25 @@ private void runRepair() {
ClusterState clusterState = solrCloudManager.getClusterState();
clusterState.forEachCollection(
coll -> {
- // shard / type / count
- Map> lostReplicas = new HashMap<>();
+ // shard / number of replicas per type
+ Map lostReplicas = new HashMap<>();
coll.forEachReplica(
(shard, replica) -> {
if (reallyLostNodes.contains(replica.getNodeName())) {
lostReplicas
- .computeIfAbsent(shard, s -> new HashMap<>())
- .computeIfAbsent(replica.type, t -> new AtomicInteger())
- .incrementAndGet();
+ .computeIfAbsent(shard, s -> ReplicaCount.empty())
+ .increment(replica.type);
}
});
Assign.AssignStrategy assignStrategy = Assign.createAssignStrategy(cc);
lostReplicas.forEach(
(shard, types) -> {
- Assign.AssignRequestBuilder assignRequestBuilder =
+ Assign.AssignRequest assignRequest =
new Assign.AssignRequestBuilder()
.forCollection(coll.getName())
- .forShard(Collections.singletonList(shard));
- types.forEach(
- (type, count) -> {
- switch (type) {
- case NRT:
- assignRequestBuilder.assignNrtReplicas(count.get());
- break;
- case PULL:
- assignRequestBuilder.assignPullReplicas(count.get());
- break;
- case TLOG:
- assignRequestBuilder.assignTlogReplicas(count.get());
- break;
- }
- });
- Assign.AssignRequest assignRequest = assignRequestBuilder.build();
+ .forShard(Collections.singletonList(shard))
+ .assignReplicas(types)
+ .build();
try {
List positions =
assignStrategy.assign(solrCloudManager, assignRequest);
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/impl/PlacementPluginAssignStrategy.java b/solr/core/src/java/org/apache/solr/cluster/placement/impl/PlacementPluginAssignStrategy.java
index 5fab7b2fe9c..3b933400c65 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/impl/PlacementPluginAssignStrategy.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/impl/PlacementPluginAssignStrategy.java
@@ -193,9 +193,7 @@ private static List computeSystemCollectionPositions(
placementContext.getCluster().getCollection(assignRequest.collectionName),
new HashSet<>(assignRequest.shardNames),
nodes,
- assignRequest.numNrtReplicas,
- assignRequest.numTlogReplicas,
- assignRequest.numPullReplicas);
+ assignRequest.numReplicas);
final List replicaPositions = new ArrayList<>();
ArrayList nodeList = new ArrayList<>(request.getTargetNodes());
for (String shard : request.getShardNames()) {
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/impl/PlacementRequestImpl.java b/solr/core/src/java/org/apache/solr/cluster/placement/impl/PlacementRequestImpl.java
index bf1fa0dbccf..f101046803d 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/impl/PlacementRequestImpl.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/impl/PlacementRequestImpl.java
@@ -17,7 +17,6 @@
package org.apache.solr.cluster.placement.impl;
-import java.util.EnumMap;
import java.util.HashSet;
import java.util.Set;
import org.apache.solr.cloud.api.collections.Assign;
@@ -26,14 +25,15 @@
import org.apache.solr.cluster.Replica;
import org.apache.solr.cluster.SolrCollection;
import org.apache.solr.cluster.placement.PlacementRequest;
+import org.apache.solr.common.cloud.ReplicaCount;
public class PlacementRequestImpl implements PlacementRequest {
private final SolrCollection solrCollection;
private final Set shardNames;
private final Set targetNodes;
- private final EnumMap countReplicas =
- new EnumMap<>(Replica.ReplicaType.class);
+ private final ReplicaCount numReplicas;
+ @Deprecated
public PlacementRequestImpl(
SolrCollection solrCollection,
Set shardNames,
@@ -41,14 +41,22 @@ public PlacementRequestImpl(
int countNrtReplicas,
int countTlogReplicas,
int countPullReplicas) {
+ this(
+ solrCollection,
+ shardNames,
+ targetNodes,
+ new ReplicaCount(countNrtReplicas, countTlogReplicas, countPullReplicas));
+ }
+
+ public PlacementRequestImpl(
+ SolrCollection solrCollection,
+ Set shardNames,
+ Set targetNodes,
+ ReplicaCount numReplicas) {
this.solrCollection = solrCollection;
this.shardNames = shardNames;
this.targetNodes = targetNodes;
- // Initializing map for all values of enum, so unboxing always possible later without checking
- // for null
- countReplicas.put(Replica.ReplicaType.NRT, countNrtReplicas);
- countReplicas.put(Replica.ReplicaType.TLOG, countTlogReplicas);
- countReplicas.put(Replica.ReplicaType.PULL, countPullReplicas);
+ this.numReplicas = numReplicas;
}
@Override
@@ -68,7 +76,8 @@ public Set getTargetNodes() {
@Override
public int getCountReplicasToCreate(Replica.ReplicaType replicaType) {
- return countReplicas.get(replicaType);
+ return numReplicas.get(
+ SimpleClusterAbstractionsImpl.ReplicaImpl.toCloudReplicaType(replicaType));
}
/**
@@ -111,12 +120,6 @@ static PlacementRequestImpl toPlacementRequest(
}
}
- return new PlacementRequestImpl(
- solrCollection,
- shardNames,
- nodes,
- assignRequest.numNrtReplicas,
- assignRequest.numTlogReplicas,
- assignRequest.numPullReplicas);
+ return new PlacementRequestImpl(solrCollection, shardNames, nodes, assignRequest.numReplicas);
}
}
diff --git a/solr/core/src/java/org/apache/solr/core/TracerConfigurator.java b/solr/core/src/java/org/apache/solr/core/TracerConfigurator.java
index 47e5d32cb7b..54d718b9ca2 100644
--- a/solr/core/src/java/org/apache/solr/core/TracerConfigurator.java
+++ b/solr/core/src/java/org/apache/solr/core/TracerConfigurator.java
@@ -18,10 +18,14 @@
package org.apache.solr.core;
import io.opentelemetry.api.trace.Tracer;
+import io.opentelemetry.context.Context;
+import io.opentelemetry.context.Scope;
import java.lang.invoke.MethodHandles;
import java.util.Locale;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
import org.apache.solr.common.SolrException;
+import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.util.plugin.NamedListInitializedPlugin;
import org.apache.solr.util.tracing.SimplePropagator;
@@ -46,12 +50,14 @@ public static Tracer loadTracer(SolrResourceLoader loader, PluginInfo info) {
TracerConfigurator configurator =
loader.newInstance(info.className, TracerConfigurator.class);
configurator.init(info.initArgs);
+ ExecutorUtil.addThreadLocalProvider(new ContextThreadLocalProvider());
return configurator.getTracer();
}
if (shouldAutoConfigOTEL()) {
return autoConfigOTEL(loader);
}
if (TRACE_ID_GEN_ENABLED) {
+ ExecutorUtil.addThreadLocalProvider(new ContextThreadLocalProvider());
return SimplePropagator.load();
}
return TraceUtils.getGlobalTracer();
@@ -59,11 +65,34 @@ public static Tracer loadTracer(SolrResourceLoader loader, PluginInfo info) {
protected abstract Tracer getTracer();
+ private static class ContextThreadLocalProvider
+ implements ExecutorUtil.InheritableThreadLocalProvider {
+
+ @Override
+ public void store(AtomicReference ctx) {
+ ctx.set(Context.current());
+ }
+
+ @Override
+ public void set(AtomicReference ctx) {
+ var traceContext = (Context) ctx.get();
+ var scope = traceContext.makeCurrent();
+ ctx.set(scope);
+ }
+
+ @Override
+ public void clean(AtomicReference ctx) {
+ var scope = (Scope) ctx.get();
+ scope.close();
+ }
+ }
+
private static Tracer autoConfigOTEL(SolrResourceLoader loader) {
try {
TracerConfigurator configurator =
loader.newInstance(DEFAULT_CLASS_NAME, TracerConfigurator.class);
configurator.init(new NamedList<>());
+ ExecutorUtil.addThreadLocalProvider(new ContextThreadLocalProvider());
return configurator.getTracer();
} catch (SolrException e) {
log.error(
diff --git a/solr/core/src/java/org/apache/solr/handler/CatStream.java b/solr/core/src/java/org/apache/solr/handler/CatStream.java
index 9c7bda7bc24..70ee2b65242 100644
--- a/solr/core/src/java/org/apache/solr/handler/CatStream.java
+++ b/solr/core/src/java/org/apache/solr/handler/CatStream.java
@@ -196,7 +196,9 @@ private boolean advanceToNextFileWithData() throws IOException {
new GZIPInputStream(Files.newInputStream(currentFilePath.absolutePath)),
StandardCharsets.UTF_8));
} else {
- currentFileLines = FileUtils.lineIterator(currentFilePath.absolutePath.toFile(), "UTF-8");
+ currentFileLines =
+ FileUtils.lineIterator(
+ currentFilePath.absolutePath.toFile(), StandardCharsets.UTF_8.name());
}
if (currentFileLines.hasNext()) return true;
}
diff --git a/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java b/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java
index 17fb78a86c6..9ee84409290 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java
@@ -47,7 +47,6 @@
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrRequestInfo;
import org.apache.solr.security.AllowListUrlChecker;
-import org.apache.solr.util.tracing.TraceUtils;
@NotThreadSafe
public class HttpShardHandler extends ShardHandler {
@@ -166,7 +165,6 @@ public void submit(
@Override
public void onStart() {
- TraceUtils.injectContextIntoRequest(req);
SolrRequestInfo requestInfo = SolrRequestInfo.getRequestInfo();
if (requestInfo != null)
req.setUserPrincipal(requestInfo.getReq().getUserPrincipal());
diff --git a/solr/core/src/java/org/apache/solr/packagemanager/PackageUtils.java b/solr/core/src/java/org/apache/solr/packagemanager/PackageUtils.java
index 9d330b49bb8..c380764a678 100644
--- a/solr/core/src/java/org/apache/solr/packagemanager/PackageUtils.java
+++ b/solr/core/src/java/org/apache/solr/packagemanager/PackageUtils.java
@@ -179,7 +179,7 @@ public static Manifest fetchManifest(
NamedList response = solrClient.request(request);
String manifestJson = (String) response.get("response");
String calculatedSHA512 =
- BlobRepository.sha512Digest(ByteBuffer.wrap(manifestJson.getBytes("UTF-8")));
+ BlobRepository.sha512Digest(ByteBuffer.wrap(manifestJson.getBytes(StandardCharsets.UTF_8)));
if (expectedSHA512.equals(calculatedSHA512) == false) {
throw new SolrException(
ErrorCode.UNAUTHORIZED,
diff --git a/solr/core/src/java/org/apache/solr/packagemanager/RepositoryManager.java b/solr/core/src/java/org/apache/solr/packagemanager/RepositoryManager.java
index 8ef29ba5552..1899d8b4786 100644
--- a/solr/core/src/java/org/apache/solr/packagemanager/RepositoryManager.java
+++ b/solr/core/src/java/org/apache/solr/packagemanager/RepositoryManager.java
@@ -26,6 +26,7 @@
import java.lang.invoke.MethodHandles;
import java.net.URL;
import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -122,13 +123,13 @@ public void addRepository(String repoName, String uri) throws Exception {
if (packageManager.zkClient.exists(PackageUtils.REPOSITORIES_ZK_PATH, true) == false) {
packageManager.zkClient.create(
PackageUtils.REPOSITORIES_ZK_PATH,
- getMapper().writeValueAsString(repos).getBytes("UTF-8"),
+ getMapper().writeValueAsString(repos).getBytes(StandardCharsets.UTF_8),
CreateMode.PERSISTENT,
true);
} else {
packageManager.zkClient.setData(
PackageUtils.REPOSITORIES_ZK_PATH,
- getMapper().writeValueAsString(repos).getBytes("UTF-8"),
+ getMapper().writeValueAsString(repos).getBytes(StandardCharsets.UTF_8),
true);
}
@@ -155,7 +156,8 @@ private String getRepositoriesJson(SolrZkClient zkClient)
throws UnsupportedEncodingException, KeeperException, InterruptedException {
if (zkClient.exists(PackageUtils.REPOSITORIES_ZK_PATH, true)) {
return new String(
- zkClient.getData(PackageUtils.REPOSITORIES_ZK_PATH, null, null, true), "UTF-8");
+ zkClient.getData(PackageUtils.REPOSITORIES_ZK_PATH, null, null, true),
+ StandardCharsets.UTF_8);
}
return "[]";
}
@@ -191,10 +193,11 @@ private boolean installPackage(String packageName, String version) throws SolrEx
}
String manifestJson = getMapper().writeValueAsString(release.manifest);
String manifestSHA512 =
- BlobRepository.sha512Digest(ByteBuffer.wrap(manifestJson.getBytes("UTF-8")));
+ BlobRepository.sha512Digest(
+ ByteBuffer.wrap(manifestJson.getBytes(StandardCharsets.UTF_8)));
PackageUtils.postFile(
solrClient,
- ByteBuffer.wrap(manifestJson.getBytes("UTF-8")),
+ ByteBuffer.wrap(manifestJson.getBytes(StandardCharsets.UTF_8)),
String.format(Locale.ROOT, "/package/%s/%s/%s", packageName, version, "manifest.json"),
null);
diff --git a/solr/core/src/java/org/apache/solr/rest/BaseSolrResource.java b/solr/core/src/java/org/apache/solr/rest/BaseSolrResource.java
index cbfa72993b7..0ecb8b4f101 100644
--- a/solr/core/src/java/org/apache/solr/rest/BaseSolrResource.java
+++ b/solr/core/src/java/org/apache/solr/rest/BaseSolrResource.java
@@ -20,6 +20,7 @@
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.util.NamedList;
@@ -159,6 +160,6 @@ protected void handleException(Logger log) {
/** Decode URL-encoded strings as UTF-8, and avoid converting "+" to space */
protected static String urlDecode(String str) throws UnsupportedEncodingException {
- return URLDecoder.decode(str.replace("+", "%2B"), "UTF-8");
+ return URLDecoder.decode(str.replace("+", "%2B"), StandardCharsets.UTF_8);
}
}
diff --git a/solr/core/src/java/org/apache/solr/rest/RestManager.java b/solr/core/src/java/org/apache/solr/rest/RestManager.java
index d83f6bc7363..c7f6c053690 100644
--- a/solr/core/src/java/org/apache/solr/rest/RestManager.java
+++ b/solr/core/src/java/org/apache/solr/rest/RestManager.java
@@ -19,10 +19,10 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Reader;
-import java.io.UnsupportedEncodingException;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -253,11 +253,7 @@ public ManagedEndpoint(RestManager restManager) {
/** Determines the ManagedResource resourceId from the request path. */
public static String resolveResourceId(final String path) {
String resourceId;
- try {
- resourceId = URLDecoder.decode(path, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e); // shouldn't happen
- }
+ resourceId = URLDecoder.decode(path, StandardCharsets.UTF_8);
int at = resourceId.indexOf("/schema");
if (at == -1) {
@@ -288,27 +284,31 @@ public void doInit(SolrQueryRequest solrRequest, SolrQueryResponse solrResponse)
final String resourceId = resolveResourceId(solrRequest.getPath());
managedResource = restManager.getManagedResourceOrNull(resourceId);
if (managedResource == null) {
- // see if we have a registered endpoint one-level up ...
- int lastSlashAt = resourceId.lastIndexOf('/');
- if (lastSlashAt != -1) {
- String parentResourceId = resourceId.substring(0, lastSlashAt);
- log.info(
+ int lastSlashAt;
+ String parentResourceId;
+ String initialResourceId = resourceId;
+ // Check if we have a registered endpoint, going one level up each time...
+ do {
+ lastSlashAt = initialResourceId.lastIndexOf('/');
+ parentResourceId = resourceId.substring(0, lastSlashAt);
+ log.debug(
"Resource not found for {}, looking for parent: {}", resourceId, parentResourceId);
managedResource = restManager.getManagedResourceOrNull(parentResourceId);
- if (managedResource != null) {
- // verify this resource supports child resources
- if (!(managedResource instanceof ManagedResource.ChildResourceSupport)) {
- String errMsg =
- String.format(
- Locale.ROOT,
- "%s does not support child resources!",
- managedResource.getResourceId());
- throw new SolrException(ErrorCode.BAD_REQUEST, errMsg);
- }
-
- childId = resourceId.substring(lastSlashAt + 1);
- log.info("Found parent resource {} for child: {}", parentResourceId, childId);
+ initialResourceId = parentResourceId;
+ } while (managedResource == null && initialResourceId.lastIndexOf("/") != -1);
+ if (managedResource != null) {
+ // verify this resource supports child resources
+ if (!(managedResource instanceof ManagedResource.ChildResourceSupport)) {
+ String errMsg =
+ String.format(
+ Locale.ROOT,
+ "%s does not support child resources!",
+ managedResource.getResourceId());
+ throw new SolrException(ErrorCode.BAD_REQUEST, errMsg);
}
+
+ childId = resourceId.substring(lastSlashAt + 1);
+ log.debug("Found parent resource {} for child: {}", parentResourceId, childId);
}
}
diff --git a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
index ce9b1f8e6be..e93c412676e 100644
--- a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
+++ b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
@@ -37,8 +37,8 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
import java.lang.invoke.MethodHandles;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -49,6 +49,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -449,7 +450,7 @@ protected void extractHandlerFromURLPath(SolrRequestParsers parser) throws Excep
}
protected void extractRemotePath(String collectionName, String origCorename)
- throws UnsupportedEncodingException, KeeperException, InterruptedException, SolrException {
+ throws KeeperException, InterruptedException, SolrException {
assert core == null;
coreUrl = getRemoteCoreUrl(collectionName, origCorename);
// don't proxy for internal update requests
@@ -460,7 +461,7 @@ protected void extractRemotePath(String collectionName, String origCorename)
// it does not make sense to send the request to a remote node
throw new SolrException(
SolrException.ErrorCode.INVALID_STATE,
- new String(Utils.toJSON(invalidStates), org.apache.lucene.util.IOUtils.UTF_8));
+ new String(Utils.toJSON(invalidStates), StandardCharsets.UTF_8));
}
action = REMOTEQUERY;
} else {
@@ -1169,11 +1170,11 @@ private String getCoreUrl(
|| (liveNodes.contains(replica.getNodeName())
&& replica.getState() == Replica.State.ACTIVE)) {
- if (byCoreName && !origCorename.equals(replica.getStr(CORE_NAME_PROP))) {
+ if (byCoreName && !Objects.equals(origCorename, replica.getStr(CORE_NAME_PROP))) {
// if it's by core name, make sure they match
continue;
}
- if (replica.getBaseUrl().equals(cores.getZkController().getBaseUrl())) {
+ if (Objects.equals(replica.getBaseUrl(), cores.getZkController().getBaseUrl())) {
// don't count a local core
continue;
}
diff --git a/solr/core/src/java/org/apache/solr/update/SolrCmdDistributor.java b/solr/core/src/java/org/apache/solr/update/SolrCmdDistributor.java
index b40c79a166f..d31ddc9ca55 100644
--- a/solr/core/src/java/org/apache/solr/update/SolrCmdDistributor.java
+++ b/solr/core/src/java/org/apache/solr/update/SolrCmdDistributor.java
@@ -49,7 +49,6 @@
import org.apache.solr.update.processor.DistributedUpdateProcessor;
import org.apache.solr.update.processor.DistributedUpdateProcessor.LeaderRequestReplicationTracker;
import org.apache.solr.update.processor.DistributedUpdateProcessor.RollupRequestReplicationTracker;
-import org.apache.solr.util.tracing.TraceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -311,7 +310,6 @@ private void submit(final Req req, boolean isCommit) throws IOException {
if (SolrRequestInfo.getRequestInfo() != null) {
req.uReq.setUserPrincipal(SolrRequestInfo.getRequestInfo().getReq().getUserPrincipal());
}
- TraceUtils.injectContextIntoRequest(req.uReq);
if (req.synchronous) {
blockAndDoRetries();
diff --git a/solr/core/src/java/org/apache/solr/update/TransactionLog.java b/solr/core/src/java/org/apache/solr/update/TransactionLog.java
index 5c28297fa09..3174324f859 100644
--- a/solr/core/src/java/org/apache/solr/update/TransactionLog.java
+++ b/solr/core/src/java/org/apache/solr/update/TransactionLog.java
@@ -18,6 +18,7 @@
import java.io.Closeable;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
import java.lang.invoke.MethodHandles;
import java.nio.ByteBuffer;
@@ -63,17 +64,18 @@
*/
public class TransactionLog implements Closeable {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- private boolean debug = log.isDebugEnabled();
- private boolean trace = log.isTraceEnabled();
+ private static final boolean debug = log.isDebugEnabled();
+ private static final boolean trace = log.isTraceEnabled();
public static final String END_MESSAGE = "SOLR_TLOG_END";
long id;
- Path tlog;
- FileChannel channel;
- OutputStream os;
+ protected Path tlog;
+ protected FileChannel channel;
+ protected OutputStream os;
// all accesses to this stream should be synchronized on "this" (The TransactionLog)
protected FastOutputStream fos;
+ protected ChannelInputStreamOpener channelInputStreamOpener;
int numRecords;
public boolean isBuffer;
@@ -104,6 +106,12 @@ public Object resolve(Object o, JavaBinCodec codec) throws IOException {
}
};
+ protected static final OutputStreamOpener OUTPUT_STREAM_OPENER =
+ (channel, position) -> Channels.newOutputStream(channel);
+
+ protected static final ChannelInputStreamOpener CHANNEL_INPUT_STREAM_OPENER =
+ ChannelFastInputStream::new;
+
public class LogCodec extends JavaBinCodec {
public LogCodec(JavaBinCodec.ObjectResolver resolver) {
@@ -168,9 +176,19 @@ public boolean writePrimitive(Object val) throws IOException {
}
TransactionLog(Path tlogFile, Collection globalStrings, boolean openExisting) {
+ this(tlogFile, globalStrings, openExisting, OUTPUT_STREAM_OPENER, CHANNEL_INPUT_STREAM_OPENER);
+ }
+
+ protected TransactionLog(
+ Path tlogFile,
+ Collection globalStrings,
+ boolean openExisting,
+ OutputStreamOpener outputStreamOpener,
+ ChannelInputStreamOpener channelInputStreamOpener) {
boolean success = false;
try {
this.tlog = tlogFile;
+ this.channelInputStreamOpener = channelInputStreamOpener;
if (debug) {
log.debug(
@@ -190,14 +208,14 @@ public boolean writePrimitive(Object val) throws IOException {
long start = Files.size(tlog);
channel = FileChannel.open(tlog, StandardOpenOption.READ, StandardOpenOption.WRITE);
- os = Channels.newOutputStream(channel);
- fos = new FastOutputStream(os, new byte[65536], 0);
-
if (start > 0) {
readHeader(null);
+ }
+ os = outputStreamOpener.open(channel, start);
+ fos = new FastOutputStream(os, new byte[65536], 0);
+ if (start > 0) {
channel.position(start);
- fos.setWritten(start); // reflect that we aren't starting at the beginning
- assert fos.size() == channel.size();
+ setWrittenCount(start);
} else {
addGlobalStrings(globalStrings);
}
@@ -213,7 +231,7 @@ public boolean writePrimitive(Object val) throws IOException {
StandardOpenOption.READ,
StandardOpenOption.WRITE,
StandardOpenOption.CREATE_NEW);
- os = Channels.newOutputStream(channel);
+ os = outputStreamOpener.open(channel, 0);
fos = new FastOutputStream(os, new byte[65536], 0);
addGlobalStrings(globalStrings);
@@ -239,6 +257,20 @@ public boolean writePrimitive(Object val) throws IOException {
// for subclasses
protected TransactionLog() {}
+ /**
+ * Sets the counter of written data in the {@link FastOutputStream} view of the log file, to
+ * reflect that we aren't starting at the beginning.
+ */
+ protected void setWrittenCount(long fileStartOffset) throws IOException {
+ fos.setWritten(fileStartOffset);
+ assert fos.size() == getLogFileSize();
+ }
+
+ /** Gets the log file data size. */
+ protected long getLogFileSize() throws IOException {
+ return channel.size();
+ }
+
/**
* Returns the number of records in the log (currently includes the header and an optional
* commit). Note: currently returns 0 for reopened existing log files.
@@ -261,8 +293,11 @@ public boolean endsWithCommit() throws IOException {
long pos = size - END_MESSAGE.length() - 4;
if (pos < 0) return false;
@SuppressWarnings("resource")
- final ChannelFastInputStream is = new ChannelFastInputStream(channel, pos);
- is.read(buf);
+ final InputStream is = channelInputStreamOpener.open(channel, pos);
+ int n = is.read(buf);
+ if (n != buf.length) {
+ return false;
+ }
for (int i = 0; i < buf.length; i++) {
if (buf[i] != END_MESSAGE.charAt(i)) return false;
}
@@ -283,14 +318,14 @@ public long writeData(Object o) {
}
@SuppressWarnings({"unchecked"})
- private void readHeader(FastInputStream fis) throws IOException {
+ private void readHeader(DataInputInputStream is) throws IOException {
// read existing header
- fis = fis != null ? fis : new ChannelFastInputStream(channel, 0);
+ is = is != null ? is : channelInputStreamOpener.open(channel, 0);
@SuppressWarnings("resource")
final LogCodec codec = new LogCodec(resolver);
- Map, ?> header = (Map, ?>) codec.unmarshal(fis);
+ Map, ?> header = (Map, ?>) codec.unmarshal(is);
- fis.readInt(); // skip size
+ is.readInt(); // skip size
// needed to read other records
@@ -507,7 +542,7 @@ public long writeCommit(CommitUpdateCommand cmd) {
endRecord(pos);
fos.flush(); // flush since this will be the last record in a log fill
- assert fos.size() == channel.size();
+ assert fos.size() == getLogFileSize();
return pos;
} catch (IOException e) {
@@ -527,18 +562,18 @@ public Object lookup(long pos) {
// make sure any unflushed buffer has been flushed
synchronized (this) {
// TODO: optimize this by keeping track of what we have flushed up to
- fos.flushBuffer();
+ fos.flush();
/*
- System.out.println("###flushBuffer to " + fos.size() + " raf.length()=" + raf.length() + " pos="+pos);
+ System.out.println("###flush to " + fos.size() + " raf.length()=" + raf.length() + " pos="+pos);
if (fos.size() != raf.length() || pos >= fos.size() ) {
- throw new RuntimeException("ERROR" + "###flushBuffer to " + fos.size() + " raf.length()=" + raf.length() + " pos="+pos);
+ throw new RuntimeException("ERROR" + "###flush to " + fos.size() + " raf.length()=" + raf.length() + " pos="+pos);
}
*/
}
- ChannelFastInputStream fis = new ChannelFastInputStream(channel, pos);
+ DataInputInputStream is = channelInputStreamOpener.open(channel, pos);
try (LogCodec codec = new LogCodec(resolver)) {
- return codec.readVal(fis);
+ return codec.readVal(is);
}
} catch (IOException e) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
@@ -580,7 +615,7 @@ public void finish(UpdateLog.SyncLevel syncLevel) {
if (syncLevel == UpdateLog.SyncLevel.NONE) return;
try {
synchronized (this) {
- fos.flushBuffer();
+ fos.flush();
}
if (syncLevel == UpdateLog.SyncLevel.FSYNC) {
@@ -657,11 +692,11 @@ public synchronized long getLogSizeFromStream() {
* Returns a reader that can be used while a log is still in use. Currently only *one* LogReader
* may be outstanding, and that log may only be used from a single thread.
*/
- public LogReader getReader(long startingPos) {
+ public LogReader getReader(long startingPos) throws IOException {
return new LogReader(startingPos);
}
- public LogReader getSortedReader(long startingPos) {
+ public LogReader getSortedReader(long startingPos) throws IOException {
return new SortedLogReader(startingPos);
}
@@ -674,9 +709,9 @@ public class LogReader {
protected ChannelFastInputStream fis;
private LogCodec codec = new LogCodec(resolver);
- public LogReader(long startingPos) {
+ public LogReader(long startingPos) throws IOException {
incref();
- fis = new ChannelFastInputStream(channel, startingPos);
+ fis = channelInputStreamOpener.open(channel, startingPos);
}
// for classes that extend
@@ -700,7 +735,7 @@ public Object next() throws IOException, InterruptedException {
return null;
}
- fos.flushBuffer();
+ fos.flush();
}
if (pos == 0) {
@@ -752,7 +787,7 @@ public long currentPos() {
// returns best effort current size
// for info purposes
public long currentSize() throws IOException {
- return channel.size();
+ return getLogFileSize();
}
}
@@ -762,7 +797,7 @@ public class SortedLogReader extends LogReader {
private TreeMap versionToPos;
Iterator iterator;
- public SortedLogReader(long startingPos) {
+ public SortedLogReader(long startingPos) throws IOException {
super(startingPos);
this.startingPos = startingPos;
}
@@ -841,12 +876,12 @@ public FSReverseReader() throws IOException {
long sz;
synchronized (TransactionLog.this) {
- fos.flushBuffer();
+ fos.flush();
sz = fos.size();
- assert sz == channel.size();
+ assert sz == getLogFileSize();
}
- fis = new ChannelFastInputStream(channel, 0);
+ fis = channelInputStreamOpener.open(channel, 0);
if (sz >= 4) {
// readHeader(fis); // should not be needed
prevPos = sz - 4;
@@ -927,8 +962,8 @@ public String toString() {
}
}
- static class ChannelFastInputStream extends FastInputStream {
- private FileChannel ch;
+ public static class ChannelFastInputStream extends FastInputStream {
+ protected FileChannel ch;
public ChannelFastInputStream(FileChannel ch, long chPosition) {
// super(null, new byte[10],0,0); // a small buffer size for testing purposes
@@ -987,4 +1022,28 @@ public String toString() {
+ position();
}
}
+
+ /** Opens {@link OutputStream} from {@link FileChannel}. */
+ protected interface OutputStreamOpener {
+
+ /**
+ * Opens an {@link OutputStream} to write in a {@link FileChannel}.
+ *
+ * @param position The initial write position of the {@link OutputStream} view of the {@link
+ * FileChannel}.
+ */
+ OutputStream open(FileChannel channel, long position) throws IOException;
+ }
+
+ /** Opens {@link ChannelFastInputStream} from {@link FileChannel}. */
+ protected interface ChannelInputStreamOpener {
+
+ /**
+ * Opens a {@link ChannelFastInputStream} to read a {@link FileChannel}.
+ *
+ * @param position The initial read position of the {@link OutputStream} view of the {@link
+ * FileChannel}.
+ */
+ ChannelFastInputStream open(FileChannel channel, long position) throws IOException;
+ }
}
diff --git a/solr/core/src/java/org/apache/solr/update/UpdateLog.java b/solr/core/src/java/org/apache/solr/update/UpdateLog.java
index 1b29405f747..255f0489af4 100644
--- a/solr/core/src/java/org/apache/solr/update/UpdateLog.java
+++ b/solr/core/src/java/org/apache/solr/update/UpdateLog.java
@@ -25,8 +25,8 @@
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.UncheckedIOException;
import java.lang.invoke.MethodHandles;
-import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -998,7 +998,7 @@ public synchronized long applyPartialUpdates(
entry
+ " is not a partial doc"
+ ", while looking for id="
- + new String(id.bytes, Charset.forName("UTF-8")));
+ + new String(id.bytes, StandardCharsets.UTF_8));
}
// This update is an inplace update, get the partial doc. The input doc is always at last
// position.
@@ -1343,9 +1343,10 @@ public void copyOverOldUpdates(long commitVersion, TransactionLog oldTlog) {
copyOverOldUpdatesMeter.mark();
SolrQueryRequest req = new LocalSolrQueryRequest(uhandler.core, new ModifiableSolrParams());
- TransactionLog.LogReader logReader = oldTlog.getReader(0);
+ TransactionLog.LogReader logReader = null;
Object o = null;
try {
+ logReader = oldTlog.getReader(0);
while ((o = logReader.next()) != null) {
try {
List> entry = (List>) o;
@@ -1921,10 +1922,14 @@ public void doReplay(TransactionLog translog) {
recoveryInfo.positionOfStart,
inSortedOrder);
long lastStatusTime = System.nanoTime();
- if (inSortedOrder) {
- tlogReader = translog.getSortedReader(recoveryInfo.positionOfStart);
- } else {
- tlogReader = translog.getReader(recoveryInfo.positionOfStart);
+ try {
+ if (inSortedOrder) {
+ tlogReader = translog.getSortedReader(recoveryInfo.positionOfStart);
+ } else {
+ tlogReader = translog.getReader(recoveryInfo.positionOfStart);
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
}
// NOTE: we don't currently handle a core reload during recovery. This would cause the core
diff --git a/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpListenerFactory.java b/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpListenerFactory.java
index 0e90657f7d2..31523a5882f 100644
--- a/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpListenerFactory.java
+++ b/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpListenerFactory.java
@@ -20,18 +20,20 @@
import static org.apache.solr.metrics.SolrMetricManager.mkName;
import com.codahale.metrics.Timer;
+import io.opentelemetry.api.trace.Span;
import java.util.Locale;
import java.util.Map;
import org.apache.solr.client.solrj.impl.HttpListenerFactory;
import org.apache.solr.common.util.CollectionUtil;
import org.apache.solr.metrics.SolrMetricProducer;
import org.apache.solr.metrics.SolrMetricsContext;
+import org.apache.solr.util.tracing.TraceUtils;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Result;
/**
- * A HttpListenerFactory tracks metrics interesting to solr Inspired and partially copied from
- * dropwizard httpclient library
+ * A HttpListenerFactory tracking metrics and distributed tracing. The Metrics are inspired and
+ * partially copied from dropwizard httpclient library.
*/
public class InstrumentedHttpListenerFactory implements SolrMetricProducer, HttpListenerFactory {
@@ -86,12 +88,23 @@ private static String methodNameString(Request request) {
public RequestResponseListener get() {
return new RequestResponseListener() {
Timer.Context timerContext;
+ Span span = Span.getInvalid();
+
+ @Override
+ public void onQueued(Request request) {
+ // do tracing onQueued because it's called from Solr's thread
+ span = Span.current();
+ TraceUtils.injectTraceContext(request);
+ }
@Override
public void onBegin(Request request) {
if (solrMetricsContext != null) {
timerContext = timer(request).time();
}
+ if (span.isRecording()) {
+ span.addEvent("Client Send"); // perhaps delayed a bit after the span started in enqueue
+ }
}
@Override
@@ -99,6 +112,9 @@ public void onComplete(Result result) {
if (timerContext != null) {
timerContext.stop();
}
+ if (result.isFailed() && span.isRecording()) {
+ span.addEvent(result.toString()); // logs failure info and interesting stuff
+ }
}
};
}
diff --git a/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpRequestExecutor.java b/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpRequestExecutor.java
index c796fe8f57c..b50751a1ce0 100644
--- a/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpRequestExecutor.java
+++ b/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpRequestExecutor.java
@@ -36,6 +36,7 @@
import org.apache.solr.common.util.CollectionUtil;
import org.apache.solr.metrics.SolrMetricProducer;
import org.apache.solr.metrics.SolrMetricsContext;
+import org.apache.solr.util.tracing.TraceUtils;
/**
* Sub-class of HttpRequestExecutor which tracks metrics interesting to solr Inspired and partially
@@ -138,6 +139,7 @@ public HttpResponse execute(HttpRequest request, HttpClientConnection conn, Http
if (solrMetricsContext != null) {
timerContext = timer(request).time();
}
+ TraceUtils.injectTraceContext(request);
try {
return super.execute(request, conn, context);
} finally {
diff --git a/solr/core/src/java/org/apache/solr/util/tracing/SolrRequestSetter.java b/solr/core/src/java/org/apache/solr/util/tracing/SolrRequestSetter.java
deleted file mode 100644
index 0923d9db014..00000000000
--- a/solr/core/src/java/org/apache/solr/util/tracing/SolrRequestSetter.java
+++ /dev/null
@@ -1,32 +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.util.tracing;
-
-import io.opentelemetry.context.propagation.TextMapSetter;
-import org.apache.solr.client.solrj.SolrRequest;
-
-/**
- * {@code SolrRequest} aware {@code TextMapSetter} that allows header data to be added to a request
- */
-public class SolrRequestSetter implements TextMapSetter> {
-
- @Override
- public void set(SolrRequest> request, String key, String value) {
- request.addHeader(key, value);
- }
-}
diff --git a/solr/core/src/java/org/apache/solr/util/tracing/TraceUtils.java b/solr/core/src/java/org/apache/solr/util/tracing/TraceUtils.java
index 7edfe8fc55f..a153ae82bb6 100644
--- a/solr/core/src/java/org/apache/solr/util/tracing/TraceUtils.java
+++ b/solr/core/src/java/org/apache/solr/util/tracing/TraceUtils.java
@@ -25,12 +25,14 @@
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.propagation.TextMapPropagator;
+import io.opentelemetry.context.propagation.TextMapSetter;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
import javax.servlet.http.HttpServletRequest;
-import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.http.HttpRequest;
import org.apache.solr.request.SolrQueryRequest;
+import org.eclipse.jetty.client.api.Request;
/** Utilities for distributed tracing. */
public class TraceUtils {
@@ -144,9 +146,20 @@ public static Context extractContext(HttpServletRequest req) {
return textMapPropagator.extract(Context.current(), req, new HttpServletRequestGetter());
}
- public static void injectContextIntoRequest(SolrRequest> req) {
+ private static final TextMapSetter REQUEST_INJECTOR =
+ (req, k, v) -> req.headers(httpFields -> httpFields.put(k, v));
+
+ public static void injectTraceContext(Request req) {
+ TextMapPropagator textMapPropagator = getTextMapPropagator();
+ textMapPropagator.inject(Context.current(), req, REQUEST_INJECTOR);
+ }
+
+ private static final TextMapSetter HTTP_REQUEST_INJECTOR =
+ (req, k, v) -> req.setHeader(k, v);
+
+ public static void injectTraceContext(HttpRequest req) {
TextMapPropagator textMapPropagator = getTextMapPropagator();
- textMapPropagator.inject(Context.current(), req, new SolrRequestSetter());
+ textMapPropagator.inject(Context.current(), req, HTTP_REQUEST_INJECTOR);
}
public static Span startHttpRequestSpan(HttpServletRequest request, Context context) {
diff --git a/solr/core/src/test/org/apache/solr/CursorPagingTest.java b/solr/core/src/test/org/apache/solr/CursorPagingTest.java
index d47e1374847..45689e2cf21 100644
--- a/solr/core/src/test/org/apache/solr/CursorPagingTest.java
+++ b/solr/core/src/test/org/apache/solr/CursorPagingTest.java
@@ -1117,9 +1117,9 @@ public SentinelIntSet assertFullWalkNoDupsWithFacets(int maxSize, SolrParams par
if (null != previousFacets) {
assertEquals(
"Facets not the same as on previous page:\nprevious page facets: "
- + Arrays.toString(facets.toArray(new Object[facets.size()]))
+ + Arrays.toString(facets.toArray(new Object[0]))
+ "\ncurrent page facets: "
- + Arrays.toString(previousFacets.toArray(new Object[previousFacets.size()])),
+ + Arrays.toString(previousFacets.toArray(new Object[0])),
previousFacets,
facets);
}
diff --git a/solr/core/src/test/org/apache/solr/TestGroupingSearch.java b/solr/core/src/test/org/apache/solr/TestGroupingSearch.java
index 013bd2e5ff9..296b3517ff9 100644
--- a/solr/core/src/test/org/apache/solr/TestGroupingSearch.java
+++ b/solr/core/src/test/org/apache/solr/TestGroupingSearch.java
@@ -1991,7 +1991,7 @@ public static class Grp {
public Doc maxDoc; // the document highest according to the "sort" param
public void setMaxDoc(Comparator comparator) {
- Doc[] arr = docs.toArray(new Doc[docs.size()]);
+ Doc[] arr = docs.toArray(new Doc[0]);
Arrays.sort(arr, comparator);
maxDoc = arr.length > 0 ? arr[0] : null;
}
diff --git a/solr/core/src/test/org/apache/solr/cli/ApiToolTest.java b/solr/core/src/test/org/apache/solr/cli/ApiToolTest.java
index d817845854a..db04f60f0ef 100644
--- a/solr/core/src/test/org/apache/solr/cli/ApiToolTest.java
+++ b/solr/core/src/test/org/apache/solr/cli/ApiToolTest.java
@@ -16,7 +16,6 @@
*/
package org.apache.solr.cli;
-import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
@@ -66,9 +65,6 @@ public void testQueryResponse() throws Exception {
.process(cluster.getSolrClient());
cluster.waitForActiveCollection(COLLECTION_NAME, 2, 2);
- String tmpFileLoc =
- new File(cluster.getBaseDir().toFile().getAbsolutePath() + File.separator).getPath();
-
UpdateRequest ur = new UpdateRequest();
ur.setAction(AbstractUpdateRequest.ACTION.COMMIT, true, true);
@@ -90,7 +86,8 @@ public void testQueryResponse() throws Exception {
cluster.getJettySolrRunner(0).getBaseUrl()
+ "/"
+ COLLECTION_NAME
- + "/select?q=*:*&rows=1&fl=id&sort=id+asc");
+ + "/select?q=*:*&rows=1&fl=id&sort=id+asc",
+ null);
// Fields that could be missed because of serialization
assertFindInJson(response, "\"numFound\":1000,");
// Correct formatting
diff --git a/solr/core/src/test/org/apache/solr/cli/CreateToolTest.java b/solr/core/src/test/org/apache/solr/cli/CreateToolTest.java
new file mode 100644
index 00000000000..a4801c99fb0
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/cli/CreateToolTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.cli;
+
+import static java.util.Collections.singletonList;
+import static java.util.Collections.singletonMap;
+import static org.apache.solr.cli.SolrCLI.findTool;
+import static org.apache.solr.cli.SolrCLI.parseCmdLine;
+import static org.apache.solr.security.Sha256AuthenticationProvider.getSaltedHashedValue;
+
+import java.util.Map;
+import org.apache.commons.cli.CommandLine;
+import org.apache.solr.cloud.SolrCloudTestCase;
+import org.apache.solr.common.util.Utils;
+import org.apache.solr.security.BasicAuthPlugin;
+import org.apache.solr.security.RuleBasedAuthorizationPlugin;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class CreateToolTest extends SolrCloudTestCase {
+
+ private static final String USER = "solr";
+ private static final String PASS = "SolrRocksAgain";
+ private static final String collectionName = "testCreateCollectionWithBasicAuth";
+
+ @BeforeClass
+ public static void setupClusterWithSecurityEnabled() throws Exception {
+ final String SECURITY_JSON =
+ Utils.toJSONString(
+ Map.of(
+ "authorization",
+ Map.of(
+ "class",
+ RuleBasedAuthorizationPlugin.class.getName(),
+ "user-role",
+ singletonMap(USER, "admin"),
+ "permissions",
+ singletonList(Map.of("name", "all", "role", "admin"))),
+ "authentication",
+ Map.of(
+ "class",
+ BasicAuthPlugin.class.getName(),
+ "blockUnknown",
+ true,
+ "credentials",
+ singletonMap(USER, getSaltedHashedValue(PASS)))));
+
+ configureCluster(2)
+ .addConfig("conf", configset("cloud-minimal"))
+ .withSecurityJson(SECURITY_JSON)
+ .configure();
+ }
+
+ @Test
+ public void testCreateCollectionWithBasicAuth() throws Exception {
+
+ String[] args = {
+ "create",
+ "-c",
+ collectionName,
+ "-n",
+ "cloud-minimal",
+ "-zkHost",
+ cluster.getZkClient().getZkServerAddress(),
+ "-credentials",
+ USER + ":" + PASS,
+ "-verbose"
+ };
+
+ assertEquals(0, runTool(args));
+ }
+
+ private int runTool(String[] args) throws Exception {
+ Tool tool = findTool(args);
+ assertTrue(tool instanceof CreateTool);
+ CommandLine cli = parseCmdLine(tool.getName(), args, tool.getOptions());
+ return tool.runTool(cli);
+ }
+}
diff --git a/solr/core/src/test/org/apache/solr/cli/DeleteToolTest.java b/solr/core/src/test/org/apache/solr/cli/DeleteToolTest.java
new file mode 100644
index 00000000000..808f6171971
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/cli/DeleteToolTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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.cli;
+
+import static java.util.Collections.singletonList;
+import static java.util.Collections.singletonMap;
+import static org.apache.solr.cli.SolrCLI.findTool;
+import static org.apache.solr.cli.SolrCLI.parseCmdLine;
+import static org.apache.solr.security.Sha256AuthenticationProvider.getSaltedHashedValue;
+
+import java.util.Map;
+import org.apache.commons.cli.CommandLine;
+import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.SolrResponse;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.cloud.SolrCloudTestCase;
+import org.apache.solr.common.util.Utils;
+import org.apache.solr.security.BasicAuthPlugin;
+import org.apache.solr.security.RuleBasedAuthorizationPlugin;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class DeleteToolTest extends SolrCloudTestCase {
+
+ private static final String USER = "solr";
+ private static final String PASS = "SolrRocksAgain";
+
+ @BeforeClass
+ public static void setupClusterWithSecurityEnabled() throws Exception {
+ final String SECURITY_JSON =
+ Utils.toJSONString(
+ Map.of(
+ "authorization",
+ Map.of(
+ "class",
+ RuleBasedAuthorizationPlugin.class.getName(),
+ "user-role",
+ singletonMap(USER, "admin"),
+ "permissions",
+ singletonList(Map.of("name", "all", "role", "admin"))),
+ "authentication",
+ Map.of(
+ "class",
+ BasicAuthPlugin.class.getName(),
+ "blockUnknown",
+ true,
+ "credentials",
+ singletonMap(USER, getSaltedHashedValue(PASS)))));
+
+ configureCluster(2)
+ .addConfig("conf", configset("cloud-minimal"))
+ .withSecurityJson(SECURITY_JSON)
+ .configure();
+ }
+
+ private > T withBasicAuth(T req) {
+ req.setBasicAuthCredentials(USER, PASS);
+ return req;
+ }
+
+ @Test
+ public void testDeleteCollectionWithBasicAuth() throws Exception {
+
+ withBasicAuth(
+ CollectionAdminRequest.createCollection(
+ "testDeleteCollectionWithBasicAuth", "conf", 1, 1))
+ .processAndWait(cluster.getSolrClient(), 10);
+ waitForState(
+ "Expected collection to be created with 1 shard and 1 replicas",
+ "testDeleteCollectionWithBasicAuth",
+ clusterShape(1, 1));
+
+ String[] args = {
+ "delete",
+ "-c",
+ "testDeleteCollectionWithBasicAuth",
+ "-deleteConfig",
+ "false",
+ "-zkHost",
+ cluster.getZkClient().getZkServerAddress(),
+ "-credentials",
+ USER + ":" + PASS,
+ "-verbose"
+ };
+ assertEquals(0, runTool(args));
+ }
+
+ @Test
+ public void testFailsToDeleteProtectedCollection() throws Exception {
+
+ withBasicAuth(
+ CollectionAdminRequest.createCollection(
+ "testFailsToDeleteProtectedCollection", "conf", 1, 1))
+ .processAndWait(cluster.getSolrClient(), 10);
+ waitForState(
+ "Expected collection to be created with 1 shard and 1 replicas",
+ "testFailsToDeleteProtectedCollection",
+ clusterShape(1, 1));
+
+ String[] args = {
+ "delete",
+ "-c",
+ "testFailsToDeleteProtectedCollection",
+ "-zkHost",
+ cluster.getZkClient().getZkServerAddress(),
+ "-verbose"
+ };
+ assertEquals(1, runTool(args));
+ }
+
+ private int runTool(String[] args) throws Exception {
+ Tool tool = findTool(args);
+ assertTrue(tool instanceof DeleteTool);
+ CommandLine cli = parseCmdLine(tool.getName(), args, tool.getOptions());
+ return tool.runTool(cli);
+ }
+}
diff --git a/solr/core/src/test/org/apache/solr/cloud/PackageManagerCLITest.java b/solr/core/src/test/org/apache/solr/cli/PackageToolTest.java
similarity index 51%
rename from solr/core/src/test/org/apache/solr/cloud/PackageManagerCLITest.java
rename to solr/core/src/test/org/apache/solr/cli/PackageToolTest.java
index b1e11c45a3c..dea89655772 100644
--- a/solr/core/src/test/org/apache/solr/cloud/PackageManagerCLITest.java
+++ b/solr/core/src/test/org/apache/solr/cli/PackageToolTest.java
@@ -15,14 +15,27 @@
* limitations under the License.
*/
-package org.apache.solr.cloud;
+package org.apache.solr.cli;
+import static java.util.Collections.singletonList;
+import static java.util.Collections.singletonMap;
+import static org.apache.solr.security.Sha256AuthenticationProvider.getSaltedHashedValue;
+
+import java.io.StringReader;
import java.lang.invoke.MethodHandles;
import java.util.Arrays;
-import org.apache.solr.cli.PackageTool;
-import org.apache.solr.cli.SolrCLI;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.SolrResponse;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
-import org.apache.solr.core.TestSolrConfigHandler;
+import org.apache.solr.cloud.SolrCloudTestCase;
+import org.apache.solr.common.LinkedHashMapWriter;
+import org.apache.solr.common.util.StrUtils;
+import org.apache.solr.common.util.Utils;
+import org.apache.solr.security.BasicAuthPlugin;
+import org.apache.solr.security.RuleBasedAuthorizationPlugin;
import org.apache.solr.util.LogLevel;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
@@ -33,11 +46,14 @@
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.noggit.JSONParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@LogLevel("org.apache=INFO")
-public class PackageManagerCLITest extends SolrCloudTestCase {
+public class PackageToolTest extends SolrCloudTestCase {
+ private static final String USER = "solr";
+ private static final String PASS = "SolrRocksAgain";
// Note for those who want to modify the jar files used in the packages used in this test:
// You need to re-sign the jars for install step, as follows:
@@ -52,14 +68,35 @@ public class PackageManagerCLITest extends SolrCloudTestCase {
private static LocalWebServer repositoryServer;
@BeforeClass
- public static void setupCluster() throws Exception {
+ public static void setupClusterWithSecurityEnabled() throws Exception {
System.setProperty("enable.packages", "true");
- configureCluster(1)
+ final String SECURITY_JSON =
+ Utils.toJSONString(
+ Map.of(
+ "authorization",
+ Map.of(
+ "class",
+ RuleBasedAuthorizationPlugin.class.getName(),
+ "user-role",
+ singletonMap(USER, "admin"),
+ "permissions",
+ singletonList(Map.of("name", "all", "role", "admin"))),
+ "authentication",
+ Map.of(
+ "class",
+ BasicAuthPlugin.class.getName(),
+ "blockUnknown",
+ true,
+ "credentials",
+ singletonMap(USER, getSaltedHashedValue(PASS)))));
+
+ configureCluster(2)
.addConfig(
"conf1", TEST_PATH().resolve("configsets").resolve("cloud-minimal").resolve("conf"))
.addConfig(
"conf3", TEST_PATH().resolve("configsets").resolve("cloud-minimal").resolve("conf"))
+ .withSecurityJson(SECURITY_JSON)
.configure();
repositoryServer =
@@ -78,36 +115,61 @@ public static void teardown() throws Exception {
}
}
+ private > T withBasicAuth(T req) {
+ req.setBasicAuthCredentials(USER, PASS);
+ return req;
+ }
+
@Test
- public void testPackageManager() throws Exception {
+ public void testPackageTool() throws Exception {
PackageTool tool = new PackageTool();
String solrUrl = cluster.getJettySolrRunner(0).getBaseUrl().toString();
- run(tool, new String[] {"-solrUrl", solrUrl, "list-installed"});
+ run(
+ tool,
+ new String[] {"-solrUrl", solrUrl, "list-installed", "-credentials", USER + ":" + PASS});
run(
tool,
new String[] {
"-solrUrl",
solrUrl,
+ "-credentials",
+ USER + ":" + PASS,
"add-repo",
"fullstory",
- "http://localhost:" + repositoryServer.getPort()
+ "http://localhost:" + repositoryServer.getPort(),
+ "-credentials",
+ USER + ":" + PASS
});
- run(tool, new String[] {"-solrUrl", solrUrl, "list-available"});
+ run(
+ tool,
+ new String[] {"-solrUrl", solrUrl, "list-available", "-credentials", USER + ":" + PASS});
- run(tool, new String[] {"-solrUrl", solrUrl, "install", "question-answer:1.0.0"});
+ run(
+ tool,
+ new String[] {
+ "-solrUrl", solrUrl, "install", "question-answer:1.0.0", "-credentials", USER + ":" + PASS
+ });
- run(tool, new String[] {"-solrUrl", solrUrl, "list-installed"});
+ run(
+ tool,
+ new String[] {"-solrUrl", solrUrl, "list-installed", "-credentials", USER + ":" + PASS});
- CollectionAdminRequest.createCollection("abc", "conf1", 1, 1).process(cluster.getSolrClient());
- CollectionAdminRequest.createCollection("def", "conf3", 1, 1).process(cluster.getSolrClient());
+ withBasicAuth(CollectionAdminRequest.createCollection("abc", "conf1", 1, 1))
+ .processAndWait(cluster.getSolrClient(), 10);
+ withBasicAuth(CollectionAdminRequest.createCollection("def", "conf3", 1, 1))
+ .processAndWait(cluster.getSolrClient(), 10);
String rhPath = "/mypath2";
- run(tool, new String[] {"-solrUrl", solrUrl, "list-deployed", "question-answer"});
+ run(
+ tool,
+ new String[] {
+ "-solrUrl", solrUrl, "list-deployed", "question-answer", "-credentials", USER + ":" + PASS
+ });
run(
tool,
@@ -120,13 +182,23 @@ public void testPackageManager() throws Exception {
"-collections",
"abc",
"-p",
- "RH-HANDLER-PATH=" + rhPath
+ "RH-HANDLER-PATH=" + rhPath,
+ "-credentials",
+ USER + ":" + PASS
});
- assertPackageVersion("abc", "question-answer", "1.0.0", rhPath, "1.0.0");
+ assertPackageVersion("abc", "question-answer", "1.0.0", rhPath, "1.0.0", USER + ":" + PASS);
- run(tool, new String[] {"-solrUrl", solrUrl, "list-deployed", "question-answer"});
+ run(
+ tool,
+ new String[] {
+ "-solrUrl", solrUrl, "list-deployed", "question-answer", "-credentials", USER + ":" + PASS
+ });
- run(tool, new String[] {"-solrUrl", solrUrl, "list-deployed", "-c", "abc"});
+ run(
+ tool,
+ new String[] {
+ "-solrUrl", solrUrl, "list-deployed", "-c", "abc", "-credentials", USER + ":" + PASS
+ });
// Should we test the "auto-update to latest" functionality or the default explicit deploy
// functionality
@@ -139,17 +211,33 @@ public void testPackageManager() throws Exception {
run(
tool,
new String[] {
- "-solrUrl", solrUrl, "deploy", "question-answer:latest", "-y", "-collections", "abc"
+ "-solrUrl",
+ solrUrl,
+ "deploy",
+ "question-answer:latest",
+ "-y",
+ "-collections",
+ "abc",
+ "-credentials",
+ USER + ":" + PASS
});
- assertPackageVersion("abc", "question-answer", "$LATEST", rhPath, "1.0.0");
+ assertPackageVersion("abc", "question-answer", "$LATEST", rhPath, "1.0.0", USER + ":" + PASS);
- run(tool, new String[] {"-solrUrl", solrUrl, "install", "question-answer"});
- assertPackageVersion("abc", "question-answer", "$LATEST", rhPath, "1.1.0");
+ run(
+ tool,
+ new String[] {
+ "-solrUrl", solrUrl, "install", "question-answer", "-credentials", USER + ":" + PASS
+ });
+ assertPackageVersion("abc", "question-answer", "$LATEST", rhPath, "1.1.0", USER + ":" + PASS);
} else {
log.info("Testing explicit deployment to a different/newer version");
- run(tool, new String[] {"-solrUrl", solrUrl, "install", "question-answer"});
- assertPackageVersion("abc", "question-answer", "1.0.0", rhPath, "1.0.0");
+ run(
+ tool,
+ new String[] {
+ "-solrUrl", solrUrl, "install", "question-answer", "-credentials", USER + ":" + PASS
+ });
+ assertPackageVersion("abc", "question-answer", "1.0.0", rhPath, "1.0.0", USER + ":" + PASS);
// even if parameters are not passed in, they should be picked up from previous deployment
if (random().nextBoolean()) {
@@ -165,7 +253,9 @@ public void testPackageManager() throws Exception {
"-collections",
"abc",
"-p",
- "RH-HANDLER-PATH=" + rhPath
+ "RH-HANDLER-PATH=" + rhPath,
+ "-credentials",
+ USER + ":" + PASS
});
} else {
run(
@@ -178,40 +268,92 @@ public void testPackageManager() throws Exception {
"-y",
"question-answer",
"-collections",
- "abc"
+ "abc",
+ "-credentials",
+ USER + ":" + PASS
});
}
- assertPackageVersion("abc", "question-answer", "1.1.0", rhPath, "1.1.0");
+ assertPackageVersion("abc", "question-answer", "1.1.0", rhPath, "1.1.0", USER + ":" + PASS);
}
log.info("Running undeploy...");
run(
tool,
- new String[] {"-solrUrl", solrUrl, "undeploy", "question-answer", "-collections", "abc"});
+ new String[] {
+ "-solrUrl",
+ solrUrl,
+ "undeploy",
+ "question-answer",
+ "-collections",
+ "abc",
+ "-credentials",
+ USER + ":" + PASS
+ });
- run(tool, new String[] {"-solrUrl", solrUrl, "list-deployed", "question-answer"});
+ run(
+ tool,
+ new String[] {
+ "-solrUrl", solrUrl, "list-deployed", "question-answer", "-credentials", USER + ":" + PASS
+ });
}
void assertPackageVersion(
- String collection, String pkg, String version, String component, String componentVersion)
+ String collection,
+ String pkg,
+ String version,
+ String component,
+ String componentVersion,
+ String credentials)
throws Exception {
- TestSolrConfigHandler.testForResponseElement(
- null,
+
+ testForResponseElement(
cluster.getJettySolrRunner(0).getBaseUrl().toString() + "/" + collection,
"/config/params?meta=true",
- cluster.getSolrClient(),
+ credentials,
Arrays.asList("response", "params", "PKG_VERSIONS", pkg),
- version,
- 10);
+ version);
- TestSolrConfigHandler.testForResponseElement(
- null,
+ testForResponseElement(
cluster.getJettySolrRunner(0).getBaseUrl().toString() + "/" + collection,
"/config/requestHandler?componentName=" + component + "&meta=true",
- cluster.getSolrClient(),
+ credentials,
Arrays.asList("config", "requestHandler", component, "_packageinfo_", "version"),
- componentVersion,
- 10);
+ componentVersion);
+ }
+
+ @SuppressWarnings({"rawtypes"})
+ public static void testForResponseElement(
+ String testServerBaseUrl,
+ String uri,
+ String credentials,
+ List jsonPath,
+ Object expected)
+ throws Exception {
+
+ // Copied method from TestSolrConfigHandler.java
+ // and then tweaked it to handle basic auth. We need a nice pattern for doing
+ // http gets/puts to various end points that can be used across all tests.
+ // using the ApiTool makes me sad ;-)
+
+ boolean success = false;
+
+ ApiTool apiTool = new ApiTool();
+ String response = apiTool.callGet(testServerBaseUrl + uri, credentials);
+
+ LinkedHashMapWriter m =
+ (LinkedHashMapWriter)
+ Utils.MAPWRITEROBJBUILDER.apply(new JSONParser(new StringReader(response))).getVal();
+ Object actual = Utils.getObjectByPath(m, false, jsonPath);
+
+ if (Objects.equals(expected, actual)) {
+ success = true;
+ }
+
+ assertTrue(
+ StrUtils.formatString(
+ "Could not get expected value ''{0}'' for path ''{1}'' full output: {2}, from server: {3}",
+ expected, StrUtils.join(jsonPath, '/'), m.toString(), testServerBaseUrl),
+ success);
}
private void run(PackageTool tool, String[] args) throws Exception {
@@ -220,7 +362,7 @@ private void run(PackageTool tool, String[] args) throws Exception {
}
static class LocalWebServer {
- private int port = 0;
+ private final int port = 0;
private final String resourceDir;
Server server;
ServerConnector connector;
diff --git a/solr/core/src/test/org/apache/solr/cli/PostToolTest.java b/solr/core/src/test/org/apache/solr/cli/PostToolTest.java
index 681d788138c..c45bd7095f8 100644
--- a/solr/core/src/test/org/apache/solr/cli/PostToolTest.java
+++ b/solr/core/src/test/org/apache/solr/cli/PostToolTest.java
@@ -17,32 +17,87 @@
package org.apache.solr.cli;
+import static java.util.Collections.singletonList;
+import static java.util.Collections.singletonMap;
import static org.apache.solr.cli.SolrCLI.findTool;
import static org.apache.solr.cli.SolrCLI.parseCmdLine;
+import static org.apache.solr.security.Sha256AuthenticationProvider.getSaltedHashedValue;
+import java.io.File;
+import java.io.FileWriter;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
import org.apache.commons.cli.CommandLine;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.SolrResponse;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.cloud.SolrCloudTestCase;
+import org.apache.solr.common.util.Utils;
+import org.apache.solr.security.BasicAuthPlugin;
+import org.apache.solr.security.RuleBasedAuthorizationPlugin;
import org.junit.BeforeClass;
import org.junit.Test;
+@SolrTestCaseJ4.SuppressSSL
public class PostToolTest extends SolrCloudTestCase {
+ private static final String USER = "solr";
+ private static final String PASS = "SolrRocksAgain";
+
@BeforeClass
- public static void setupCluster() throws Exception {
- configureCluster(1)
- .addConfig(
- "config", TEST_PATH().resolve("configsets").resolve("cloud-minimal").resolve("conf"))
+ public static void setupClusterWithSecurityEnabled() throws Exception {
+ final String SECURITY_JSON =
+ Utils.toJSONString(
+ Map.of(
+ "authorization",
+ Map.of(
+ "class",
+ RuleBasedAuthorizationPlugin.class.getName(),
+ "user-role",
+ singletonMap(USER, "admin"),
+ "permissions",
+ singletonList(Map.of("name", "all", "role", "admin"))),
+ "authentication",
+ Map.of(
+ "class",
+ BasicAuthPlugin.class.getName(),
+ "blockUnknown",
+ true,
+ "credentials",
+ singletonMap(USER, getSaltedHashedValue(PASS)))));
+
+ configureCluster(2)
+ .addConfig("conf", configset("cloud-minimal"))
+ .withSecurityJson(SECURITY_JSON)
.configure();
}
+ private > T withBasicAuth(T req) {
+ req.setBasicAuthCredentials(USER, PASS);
+ return req;
+ }
+
@Test
public void testBasicRun() throws Exception {
final String collection = "aliasedCollection";
- CollectionAdminRequest.createCollection(collection, "config", 1, 1)
- .process(cluster.getSolrClient());
- String[] args = {"post", "-url", "http://localhost:8983/solr/aliasedCollection", "blah.json"};
+ withBasicAuth(CollectionAdminRequest.createCollection(collection, "config", 1, 1, 0, 0))
+ .processAndWait(cluster.getSolrClient(), 10);
+
+ File jsonDoc = File.createTempFile("temp", "json");
+
+ FileWriter fw = new FileWriter(jsonDoc, StandardCharsets.UTF_8);
+ Utils.writeJson(Utils.toJSONString(Map.of("id", "1", "title", "mytitle")), fw, true);
+
+ String[] args = {
+ "post",
+ "-url",
+ cluster.getJettySolrRunner(0).getBaseUrl() + "/" + collection,
+ "-credentials",
+ USER + ":" + PASS,
+ jsonDoc.getAbsolutePath()
+ };
assertEquals(0, runTool(args));
}
diff --git a/solr/core/src/test/org/apache/solr/cli/SolrCLITest.java b/solr/core/src/test/org/apache/solr/cli/SolrCLITest.java
index 03f35246211..091fb4daa3a 100644
--- a/solr/core/src/test/org/apache/solr/cli/SolrCLITest.java
+++ b/solr/core/src/test/org/apache/solr/cli/SolrCLITest.java
@@ -43,4 +43,7 @@ public void testUptime() {
assertEquals(
"106751991167 days, 7 hours, 12 minutes, 56 seconds", SolrCLI.uptime(Long.MAX_VALUE));
}
+
+ @Test
+ public void testGetCredentials() {}
}
diff --git a/solr/core/src/test/org/apache/solr/cli/TestExportTool.java b/solr/core/src/test/org/apache/solr/cli/TestExportTool.java
index a59dbafe7fb..0aa9bfb9b76 100644
--- a/solr/core/src/test/org/apache/solr/cli/TestExportTool.java
+++ b/solr/core/src/test/org/apache/solr/cli/TestExportTool.java
@@ -80,7 +80,7 @@ public void testBasic() throws Exception {
String url = cluster.getRandomJetty(random()).getBaseUrl() + "/" + COLLECTION_NAME;
- ExportTool.Info info = new ExportTool.MultiThreadedRunner(url);
+ ExportTool.Info info = new ExportTool.MultiThreadedRunner(url, null);
String absolutePath = tmpFileLoc + COLLECTION_NAME + random().nextInt(100000) + ".jsonl";
info.setOutFormat(absolutePath, "jsonl", false);
info.setLimit("200");
@@ -89,7 +89,7 @@ public void testBasic() throws Exception {
assertJsonDocsCount(info, 200, record -> "2019-09-30T05:58:03Z".equals(record.get("a_dt")));
- info = new ExportTool.MultiThreadedRunner(url);
+ info = new ExportTool.MultiThreadedRunner(url, null);
absolutePath = tmpFileLoc + COLLECTION_NAME + random().nextInt(100000) + ".jsonl";
info.setOutFormat(absolutePath, "jsonl", false);
info.setLimit("-1");
@@ -98,7 +98,7 @@ public void testBasic() throws Exception {
assertJsonDocsCount(info, 1000, null);
- info = new ExportTool.MultiThreadedRunner(url);
+ info = new ExportTool.MultiThreadedRunner(url, null);
absolutePath = tmpFileLoc + COLLECTION_NAME + random().nextInt(100000) + ".javabin";
info.setOutFormat(absolutePath, "javabin", false);
info.setLimit("200");
@@ -107,7 +107,7 @@ public void testBasic() throws Exception {
assertJavabinDocsCount(info, 200);
- info = new ExportTool.MultiThreadedRunner(url);
+ info = new ExportTool.MultiThreadedRunner(url, null);
absolutePath = tmpFileLoc + COLLECTION_NAME + random().nextInt(100000) + ".javabin";
info.setOutFormat(absolutePath, "javabin", false);
info.setLimit("-1");
@@ -115,7 +115,7 @@ public void testBasic() throws Exception {
info.exportDocs();
assertJavabinDocsCount(info, 1000);
- info = new ExportTool.MultiThreadedRunner(url);
+ info = new ExportTool.MultiThreadedRunner(url, null);
absolutePath = tmpFileLoc + COLLECTION_NAME + random().nextInt(100000) + ".json";
info.setOutFormat(absolutePath, "json", false);
info.setLimit("200");
@@ -124,7 +124,7 @@ public void testBasic() throws Exception {
assertJsonDocsCount2(info, 200);
- info = new ExportTool.MultiThreadedRunner(url);
+ info = new ExportTool.MultiThreadedRunner(url, null);
absolutePath = tmpFileLoc + COLLECTION_NAME + random().nextInt(100000) + ".json";
info.setOutFormat(absolutePath, "json", false);
info.setLimit("-1");
@@ -190,7 +190,7 @@ public void testVeryLargeCluster() throws Exception {
ExportTool.MultiThreadedRunner info;
String absolutePath;
- info = new ExportTool.MultiThreadedRunner(url);
+ info = new ExportTool.MultiThreadedRunner(url, null);
info.output = System.out;
absolutePath = tmpFileLoc + COLLECTION_NAME + random().nextInt(100000) + ".javabin";
info.setOutFormat(absolutePath, "javabin", false);
@@ -201,7 +201,7 @@ public void testVeryLargeCluster() throws Exception {
assertEquals(
e.getValue().longValue(), info.corehandlers.get(e.getKey()).receivedDocs.get());
}
- info = new ExportTool.MultiThreadedRunner(url);
+ info = new ExportTool.MultiThreadedRunner(url, null);
info.output = System.out;
absolutePath = tmpFileLoc + COLLECTION_NAME + random().nextInt(100000) + ".jsonl";
info.setOutFormat(absolutePath, "jsonl", false);
diff --git a/solr/core/src/test/org/apache/solr/cli/TestSolrCLIRunExample.java b/solr/core/src/test/org/apache/solr/cli/TestSolrCLIRunExample.java
index d6f7da99eee..47577082428 100644
--- a/solr/core/src/test/org/apache/solr/cli/TestSolrCLIRunExample.java
+++ b/solr/core/src/test/org/apache/solr/cli/TestSolrCLIRunExample.java
@@ -503,7 +503,7 @@ public void testInteractiveSolrCloudExample() throws Exception {
// verify Solr is running on the expected port and verify the collection exists
String solrUrl = "http://localhost:" + bindPort + "/solr";
- if (!SolrCLI.safeCheckCollectionExists(solrUrl, collectionName)) {
+ if (!SolrCLI.safeCheckCollectionExists(solrUrl, collectionName, null)) {
fail(
"After running Solr cloud example, test collection '"
+ collectionName
diff --git a/solr/core/src/test/org/apache/solr/cloud/AddReplicaTest.java b/solr/core/src/test/org/apache/solr/cloud/AddReplicaTest.java
index 7702012713d..fa2bdf84695 100644
--- a/solr/core/src/test/org/apache/solr/cloud/AddReplicaTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/AddReplicaTest.java
@@ -27,6 +27,7 @@
import org.apache.solr.common.cloud.ClusterState;
import org.apache.solr.common.cloud.DocCollection;
import org.apache.solr.common.cloud.Replica;
+import org.apache.solr.core.CoreDescriptor;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -187,4 +188,37 @@ public void test() throws Exception {
assertSame(coll + "\n" + replica, replica.getState(), Replica.State.ACTIVE);
}
}
+
+ @Test
+ public void testAddReplicaWithUserDefinedProperties() throws Exception {
+ // When creating a collection with user-defined properties
+ CloudSolrClient cloudClient = cluster.getSolrClient();
+ String collectionName = "testAddReplicaWithUserDefinedProperties";
+ CollectionAdminRequest.createCollection(collectionName, "conf1", 1, 1)
+ .withProperty("customProp1", "val1")
+ .withProperty("customProp2", "val2")
+ .process(cloudClient);
+ cluster.waitForActiveCollection(collectionName, 1, 1);
+
+ // When adding a replica to the collection with user-defined properties
+ CollectionAdminRequest.AddReplica addReplica =
+ CollectionAdminRequest.addReplicaToShard(collectionName, "shard1");
+ addReplica.withProperty("customProp2", "val2.1");
+ addReplica.withProperty("customProp3", "val3");
+ addReplica.setWaitForFinalState(true);
+ addReplica.process(cloudClient);
+
+ // Verify that the new core was created with user-defined properties coming from the request
+ // and inherited from the collection (the former taking precedence over the latter).
+ Replica replica =
+ cloudClient.getClusterState().getCollection(collectionName).getReplicas().get(1);
+ CoreDescriptor coreDescriptor =
+ cluster
+ .getReplicaJetty(replica)
+ .getCoreContainer()
+ .getCoreDescriptor(replica.getCoreName());
+ assertEquals("val1", coreDescriptor.getCoreProperty("customProp1", ""));
+ assertEquals("val2.1", coreDescriptor.getCoreProperty("customProp2", ""));
+ assertEquals("val3", coreDescriptor.getCoreProperty("customProp3", ""));
+ }
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/CollectionsAPISolrJTest.java b/solr/core/src/test/org/apache/solr/cloud/CollectionsAPISolrJTest.java
index 30d9339d50c..9eabee8a970 100644
--- a/solr/core/src/test/org/apache/solr/cloud/CollectionsAPISolrJTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/CollectionsAPISolrJTest.java
@@ -17,7 +17,6 @@
package org.apache.solr.cloud;
import static java.util.Arrays.asList;
-import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_DEF;
import static org.apache.solr.common.cloud.ZkStateReader.NRT_REPLICAS;
import static org.apache.solr.common.cloud.ZkStateReader.NUM_SHARDS_PROP;
import static org.apache.solr.common.params.CollectionAdminParams.COLLECTION;
@@ -25,6 +24,7 @@
import java.io.IOException;
import java.lang.invoke.MethodHandles;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
@@ -127,114 +127,6 @@ public void testCreateWithDefaultConfigSet() throws Exception {
(n, c) -> c == null);
}
- @Test
- public void testCreateCollWithDefaultClusterPropertiesOldFormat() throws Exception {
- String COLL_NAME = "CollWithDefaultClusterProperties";
- try {
- V2Response rsp =
- new V2Request.Builder("/cluster")
- .withMethod(SolrRequest.METHOD.POST)
- .withPayload(
- "{set-obj-property:{collectionDefaults:{numShards : 2 , nrtReplicas : 2}}}")
- .build()
- .process(cluster.getSolrClient());
-
- for (int i = 0; i < 300; i++) {
- Map, ?> m = cluster.getZkStateReader().getClusterProperty(COLLECTION_DEF, null);
- if (m != null) break;
- Thread.sleep(10);
- }
- Object clusterProperty =
- cluster
- .getZkStateReader()
- .getClusterProperty(List.of(DEFAULTS, COLLECTION, NUM_SHARDS_PROP), null);
- assertEquals("2", String.valueOf(clusterProperty));
- clusterProperty =
- cluster
- .getZkStateReader()
- .getClusterProperty(List.of(DEFAULTS, COLLECTION, NRT_REPLICAS), null);
- assertEquals("2", String.valueOf(clusterProperty));
- CollectionAdminResponse response =
- CollectionAdminRequest.createCollection(COLL_NAME, "conf", null, null, null, null)
- .process(cluster.getSolrClient());
- assertEquals(0, response.getStatus());
- assertTrue(response.isSuccess());
-
- cluster.waitForActiveCollection(COLL_NAME, 2, 4);
-
- DocCollection coll = cluster.getSolrClient().getClusterState().getCollection(COLL_NAME);
- Map slices = coll.getSlicesMap();
- assertEquals(2, slices.size());
- for (Slice slice : slices.values()) {
- assertEquals(2, slice.getReplicas().size());
- }
- CollectionAdminRequest.deleteCollection(COLL_NAME).process(cluster.getSolrClient());
-
- // unset only a single value using old format
- rsp =
- new V2Request.Builder("/cluster")
- .withMethod(SolrRequest.METHOD.POST)
- .withPayload(
- "{\n"
- + " \"set-obj-property\": {\n"
- + " \"collectionDefaults\": {\n"
- + " \"nrtReplicas\": null\n"
- + " }\n"
- + " }\n"
- + "}")
- .build()
- .process(cluster.getSolrClient());
- // assert that it is really gone in both old and new paths
- // we use a timeout so that the change made in ZK is reflected in the watched copy inside
- // ZkStateReader
- TimeOut timeOut = new TimeOut(5, TimeUnit.SECONDS, new TimeSource.NanoTimeSource());
- while (!timeOut.hasTimedOut()) {
- clusterProperty =
- cluster
- .getZkStateReader()
- .getClusterProperty(List.of(DEFAULTS, COLLECTION, NRT_REPLICAS), null);
- if (clusterProperty == null) break;
- }
- assertNull(clusterProperty);
- clusterProperty =
- cluster
- .getZkStateReader()
- .getClusterProperty(List.of(COLLECTION_DEF, NRT_REPLICAS), null);
- assertNull(clusterProperty);
-
- // delete all defaults the old way
- rsp =
- new V2Request.Builder("/cluster")
- .withMethod(SolrRequest.METHOD.POST)
- .withPayload("{set-obj-property:{collectionDefaults:null}}")
- .build()
- .process(cluster.getSolrClient());
- // assert that it is really gone in both old and new paths
- timeOut = new TimeOut(5, TimeUnit.SECONDS, new TimeSource.NanoTimeSource());
- while (!timeOut.hasTimedOut()) {
- clusterProperty =
- cluster
- .getZkStateReader()
- .getClusterProperty(List.of(DEFAULTS, COLLECTION, NUM_SHARDS_PROP), null);
- if (clusterProperty == null) break;
- }
- assertNull(clusterProperty);
- clusterProperty =
- cluster
- .getZkStateReader()
- .getClusterProperty(List.of(COLLECTION_DEF, NUM_SHARDS_PROP), null);
- assertNull(clusterProperty);
- } finally {
- // clean up in case there was an exception during the test
- V2Response rsp =
- new V2Request.Builder("/cluster")
- .withMethod(SolrRequest.METHOD.POST)
- .withPayload("{set-obj-property:{collectionDefaults: null}}")
- .build()
- .process(cluster.getSolrClient());
- }
- }
-
@Test
public void testCreateCollWithDefaultClusterPropertiesNewFormat() throws Exception {
String COLL_NAME = "CollWithDefaultClusterProperties";
@@ -248,7 +140,7 @@ public void testCreateCollWithDefaultClusterPropertiesNewFormat() throws Excepti
.process(cluster.getSolrClient());
for (int i = 0; i < 300; i++) {
- Map, ?> m = cluster.getZkStateReader().getClusterProperty(COLLECTION_DEF, null);
+ Map, ?> m = cluster.getZkStateReader().getClusterProperty(DEFAULTS, null);
if (m != null) break;
Thread.sleep(10);
}
@@ -322,11 +214,6 @@ public void testCreateCollWithDefaultClusterPropertiesNewFormat() throws Excepti
if (clusterProperty == null) break;
}
assertNull(clusterProperty);
- clusterProperty =
- cluster
- .getZkStateReader()
- .getClusterProperty(List.of(COLLECTION_DEF, NUM_SHARDS_PROP), null);
- assertNull(clusterProperty);
} finally {
V2Response rsp =
new V2Request.Builder("/cluster")
@@ -699,7 +586,7 @@ public void testColStatus() throws Exception {
cluster.waitForActiveCollection(collectionName, 2, 4);
SolrClient client = cluster.getSolrClient();
- byte[] binData = collectionName.getBytes("UTF-8");
+ byte[] binData = collectionName.getBytes(StandardCharsets.UTF_8);
// index some docs
for (int i = 0; i < 10; i++) {
SolrInputDocument doc = new SolrInputDocument();
diff --git a/solr/core/src/test/org/apache/solr/cloud/CreateCollectionWithPropertiesTest.java b/solr/core/src/test/org/apache/solr/cloud/CreateCollectionWithPropertiesTest.java
new file mode 100644
index 00000000000..c90e9d21190
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/cloud/CreateCollectionWithPropertiesTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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 org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.common.cloud.DocCollection;
+import org.apache.solr.common.cloud.Replica;
+import org.apache.solr.core.CoreDescriptor;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class CreateCollectionWithPropertiesTest extends SolrCloudTestCase {
+ @BeforeClass
+ public static void setupCluster() throws Exception {
+ configureCluster(3)
+ .addConfig(
+ "conf1", TEST_PATH().resolve("configsets").resolve("cloud-minimal").resolve("conf"))
+ .configure();
+ }
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ cluster.deleteAllCollections();
+ }
+
+ @Test
+ public void testCreateCollectionWithUserDefinedProperties() throws Exception {
+ // When creating a collection with user-defined properties
+ CloudSolrClient cloudClient = cluster.getSolrClient();
+ String collectionName = "testCreateCollectionWithUserDefinedProperties";
+ CollectionAdminRequest.createCollection(collectionName, "conf1", 1, 1)
+ .withProperty("customProp1", "val1")
+ .process(cloudClient);
+ cluster.waitForActiveCollection(collectionName, 1, 1);
+
+ // Verify that user-defined properties are stored in cluster state
+ DocCollection collection = cloudClient.getClusterState().getCollection(collectionName);
+ assertEquals("val1", collection.getProperties().get("property.customProp1"));
+
+ // Verify that the core was created with user-defined properties
+ Replica replica =
+ cloudClient.getClusterState().getCollection(collectionName).getReplicas().get(0);
+ CoreDescriptor coreDescriptor =
+ cluster
+ .getReplicaJetty(replica)
+ .getCoreContainer()
+ .getCoreDescriptor(replica.getCoreName());
+ assertEquals("val1", coreDescriptor.getCoreProperty("customProp1", ""));
+ }
+}
diff --git a/solr/core/src/test/org/apache/solr/cloud/ReplicationFactorTest.java b/solr/core/src/test/org/apache/solr/cloud/ReplicationFactorTest.java
index 9aed89fd306..5ebc71efa40 100644
--- a/solr/core/src/test/org/apache/solr/cloud/ReplicationFactorTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/ReplicationFactorTest.java
@@ -437,7 +437,7 @@ protected void testRf3() throws Exception {
protected void addDocs(String collection, Set docIds, int expectedRf, int retries)
throws Exception {
- Integer[] idList = docIds.toArray(new Integer[docIds.size()]);
+ Integer[] idList = docIds.toArray(new Integer[0]);
if (idList.length == 1) {
sendDoc(collection, idList[0]);
return;
diff --git a/solr/core/src/test/org/apache/solr/cloud/SolrCloudExampleTest.java b/solr/core/src/test/org/apache/solr/cloud/SolrCloudExampleTest.java
index 03ccf37751b..5ba4f287b88 100644
--- a/solr/core/src/test/org/apache/solr/cloud/SolrCloudExampleTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/SolrCloudExampleTest.java
@@ -196,6 +196,6 @@ protected void doTestDeleteAction(String testCollectionName, String solrUrl) thr
assertEquals("Delete action failed!", 0, tool.runTool(cli));
assertFalse(
SolrCLI.safeCheckCollectionExists(
- solrUrl, testCollectionName)); // it should not exist anymore
+ solrUrl, testCollectionName, null)); // it should not exist anymore
}
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestCloudPivotFacet.java b/solr/core/src/test/org/apache/solr/cloud/TestCloudPivotFacet.java
index 124da0b7913..3e55073a040 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestCloudPivotFacet.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestCloudPivotFacet.java
@@ -132,7 +132,7 @@ public void test() throws Exception {
fieldNameSet.remove("id");
assertTrue("WTF, bogus field exists?", fieldNameSet.add("bogus_not_in_any_doc_s"));
- final String[] fieldNames = fieldNameSet.toArray(new String[fieldNameSet.size()]);
+ final String[] fieldNames = fieldNameSet.toArray(new String[0]);
Arrays.sort(fieldNames); // need determinism when picking random fields
for (int i = 0; i < 5; i++) {
@@ -176,7 +176,7 @@ public void test() throws Exception {
if (random().nextBoolean()) {
pivotParamValues.add(buildPivotParamValue(buildRandomPivot(fieldNames)));
}
- pivotP.set(FACET_PIVOT, pivotParamValues.toArray(new String[pivotParamValues.size()]));
+ pivotP.set(FACET_PIVOT, pivotParamValues.toArray(new String[0]));
// keep limit low - lots of unique values, and lots of depth in pivots
pivotP.add(FACET_LIMIT, "" + TestUtil.nextInt(random(), 1, 17));
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorCloud.java b/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorCloud.java
index 612fdb1615e..9e710d94f57 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorCloud.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorCloud.java
@@ -787,7 +787,7 @@ protected static void testVariousAdds(SolrClient client) throws Exception {
update(
params("update.chain", "tolerant-chain-max-errors-10", "commit", "true"),
- docs.toArray(new SolrInputDocument[docs.size()]))
+ docs.toArray(new SolrInputDocument[0]))
.process(client);
});
@@ -895,7 +895,7 @@ protected static void testVariousAdds(SolrClient client) throws Exception {
update(
params("update.chain", "tolerant-chain-max-errors-10", "commit", "true"),
- docs.toArray(new SolrInputDocument[docs.size()]))
+ docs.toArray(new SolrInputDocument[0]))
.process(client);
});
@@ -964,12 +964,12 @@ protected static void testVariousAdds(SolrClient client) throws Exception {
"update.chain", "tolerant-chain-max-errors-10",
"maxErrors", "-1",
"commit", "true"),
- docs.toArray(new SolrInputDocument[docs.size()]))
+ docs.toArray(new SolrInputDocument[0]))
.process(client);
assertUpdateTolerantErrors(
"many docs from shard2 fail, but req should succeed",
rsp,
- expectedErrs.toArray(new ExpectedErr[expectedErrs.size()]));
+ expectedErrs.toArray(new ExpectedErr[0]));
assertQueryDocIds(
client,
true,
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorRandomCloud.java b/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorRandomCloud.java
index ef613df71a4..9689620b54d 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorRandomCloud.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorRandomCloud.java
@@ -277,7 +277,7 @@ public void testRandomUpdates() throws Exception {
assertUpdateTolerantErrors(
client.toString() + " => " + expectedErrors,
rsp,
- expectedErrors.toArray(new ExpectedErr[expectedErrors.size()]));
+ expectedErrors.toArray(new ExpectedErr[0]));
if (log.isInfoEnabled()) {
log.info("END ITER #{}, expecting #docs: {}", i, expectedDocIds.cardinality());
diff --git a/solr/core/src/test/org/apache/solr/cloud/api/collections/TestCollectionAPI.java b/solr/core/src/test/org/apache/solr/cloud/api/collections/TestCollectionAPI.java
index 29c103cb9a3..ddbe2e7b901 100644
--- a/solr/core/src/test/org/apache/solr/cloud/api/collections/TestCollectionAPI.java
+++ b/solr/core/src/test/org/apache/solr/cloud/api/collections/TestCollectionAPI.java
@@ -23,16 +23,12 @@
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
-import org.apache.solr.client.solrj.SolrRequest;
-import org.apache.solr.client.solrj.SolrResponse;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.BaseHttpSolrClient;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.QueryRequest;
-import org.apache.solr.client.solrj.request.V2Request;
import org.apache.solr.client.solrj.response.CollectionAdminResponse;
import org.apache.solr.cloud.MiniSolrCloudCluster;
import org.apache.solr.cloud.ZkConfigSetService;
@@ -539,23 +535,6 @@ private void clusterStatusZNodeVersion() throws Exception {
}
}
- private static long totalexpectedV2Calls;
-
- public static SolrRequest setV2(SolrRequest req) {
- if (V2Request.v2Calls.get() == null) V2Request.v2Calls.set(new AtomicLong());
- totalexpectedV2Calls = V2Request.v2Calls.get().get();
- if (random().nextBoolean()) {
- req.setUseV2(true);
- req.setUseBinaryV2(random().nextBoolean());
- totalexpectedV2Calls++;
- }
- return req;
- }
-
- public static void assertV2CallsCount() {
- assertEquals(totalexpectedV2Calls, V2Request.v2Calls.get().get());
- }
-
private void clusterStatusWithRouteKey() throws IOException, SolrServerException {
try (CloudSolrClient client = createCloudClient(DEFAULT_COLLECTION)) {
SolrInputDocument doc = new SolrInputDocument();
diff --git a/solr/core/src/test/org/apache/solr/cluster/placement/plugins/AffinityPlacementFactoryTest.java b/solr/core/src/test/org/apache/solr/cluster/placement/plugins/AffinityPlacementFactoryTest.java
index 424161dafa4..14113386b04 100644
--- a/solr/core/src/test/org/apache/solr/cluster/placement/plugins/AffinityPlacementFactoryTest.java
+++ b/solr/core/src/test/org/apache/solr/cluster/placement/plugins/AffinityPlacementFactoryTest.java
@@ -53,6 +53,7 @@
import org.apache.solr.cluster.placement.impl.ModificationRequestImpl;
import org.apache.solr.cluster.placement.impl.PlacementRequestImpl;
import org.apache.solr.common.SolrException;
+import org.apache.solr.common.cloud.ReplicaCount;
import org.apache.solr.common.util.Pair;
import org.apache.solr.common.util.StrUtils;
import org.junit.Before;
@@ -134,9 +135,7 @@ private void testBasicPlacementInternal(boolean hasExistingCollection) throws Ex
solrCollection,
Set.of(solrCollection.shards().iterator().next().getShardName()),
new HashSet<>(liveNodes),
- 1,
- 0,
- 0);
+ new ReplicaCount(1, 0, 0));
PlacementPlan pp = plugin.computePlacement(placementRequest, placementContext);
@@ -178,7 +177,10 @@ public void testLowSpaceNode() throws Exception {
// Place two replicas of each type for each shard
PlacementRequestImpl placementRequest =
new PlacementRequestImpl(
- solrCollection, solrCollection.getShardNames(), new HashSet<>(liveNodes), 2, 2, 2);
+ solrCollection,
+ solrCollection.getShardNames(),
+ new HashSet<>(liveNodes),
+ new ReplicaCount(2, 2, 2));
PlacementPlan pp =
plugin.computePlacement(placementRequest, clusterBuilder.buildPlacementContext());
@@ -202,7 +204,10 @@ public void testLowSpaceNode() throws Exception {
// Verify that if we ask for 7 replicas, the placement will use the low free space node
placementRequest =
new PlacementRequestImpl(
- solrCollection, solrCollection.getShardNames(), new HashSet<>(liveNodes), 7, 0, 0);
+ solrCollection,
+ solrCollection.getShardNames(),
+ new HashSet<>(liveNodes),
+ new ReplicaCount(7, 0, 0));
pp = plugin.computePlacement(placementRequest, clusterBuilder.buildPlacementContext());
assertEquals(21, pp.getReplicaPlacements().size()); // 3 shards, 7 replicas each
placements = new HashSet<>();
@@ -222,7 +227,10 @@ public void testLowSpaceNode() throws Exception {
try {
placementRequest =
new PlacementRequestImpl(
- solrCollection, solrCollection.getShardNames(), new HashSet<>(liveNodes), 8, 0, 0);
+ solrCollection,
+ solrCollection.getShardNames(),
+ new HashSet<>(liveNodes),
+ new ReplicaCount(8, 0, 0));
plugin.computePlacement(placementRequest, clusterBuilder.buildPlacementContext());
fail("Placing 8 replicas should not be possible given only 7 nodes have enough space");
} catch (PlacementException e) {
@@ -265,7 +273,10 @@ public void testPlacementWithExistingReplicas() throws Exception {
// Place an additional NRT and an additional TLOG replica for each shard
PlacementRequestImpl placementRequest =
new PlacementRequestImpl(
- solrCollection, solrCollection.getShardNames(), new HashSet<>(liveNodes), 1, 1, 0);
+ solrCollection,
+ solrCollection.getShardNames(),
+ new HashSet<>(liveNodes),
+ new ReplicaCount(1, 1, 0));
// The replicas must be placed on the most appropriate nodes, i.e. those that do not already
// have a replica for the shard and then on the node with the lowest number of cores. NRT are
@@ -374,7 +385,10 @@ public void testPlacementMultiCriteria() throws Exception {
// Add 2 NRT and one TLOG to each shard.
PlacementRequestImpl placementRequest =
new PlacementRequestImpl(
- solrCollection, solrCollection.getShardNames(), new HashSet<>(liveNodes), 2, 1, 0);
+ solrCollection,
+ solrCollection.getShardNames(),
+ new HashSet<>(liveNodes),
+ new ReplicaCount(2, 1, 0));
PlacementPlan pp =
plugin.computePlacement(placementRequest, clusterBuilder.buildPlacementContext());
// Shard 1: The NRT's should go to the med cores node on AZ2 and low core on az3 (even though a
@@ -397,7 +411,10 @@ public void testPlacementMultiCriteria() throws Exception {
// If we add instead 2 PULL replicas to each shard
placementRequest =
new PlacementRequestImpl(
- solrCollection, solrCollection.getShardNames(), new HashSet<>(liveNodes), 0, 0, 2);
+ solrCollection,
+ solrCollection.getShardNames(),
+ new HashSet<>(liveNodes),
+ new ReplicaCount(0, 0, 2));
pp = plugin.computePlacement(placementRequest, clusterBuilder.buildPlacementContext());
// Shard 1: Given node AZ3_TLOGPULL is taken by the TLOG replica, the PULL should go to
// AZ1_TLOGPULL_LOWFREEDISK and AZ2_TLOGPULL
@@ -462,9 +479,7 @@ public void testPlacementAzsCores() throws Exception {
solrCollection,
solrCollection.getShardNames(),
new HashSet<>(liveNodes),
- countNrtToPlace,
- 0,
- 0);
+ new ReplicaCount(countNrtToPlace, 0, 0));
PlacementPlan pp =
plugin.computePlacement(placementRequest, clusterBuilder.buildPlacementContext());
verifyPlacements(
@@ -509,9 +524,7 @@ public void testCollectionOnDeadNodes() throws Exception {
solrCollection,
Set.of(solrCollection.iterator().next().getShardName()),
new HashSet<>(liveNodes),
- 0,
- 0,
- 1);
+ new ReplicaCount(0, 0, 1));
PlacementPlan pp =
plugin.computePlacement(placementRequest, clusterBuilder.buildPlacementContext());
@@ -527,7 +540,10 @@ public void testCollectionOnDeadNodes() throws Exception {
it.next(); // skip first shard to do placement for the second one...
placementRequest =
new PlacementRequestImpl(
- solrCollection, Set.of(it.next().getShardName()), new HashSet<>(liveNodes), 0, 0, 1);
+ solrCollection,
+ Set.of(it.next().getShardName()),
+ new HashSet<>(liveNodes),
+ new ReplicaCount(0, 0, 1));
pp = plugin.computePlacement(placementRequest, clusterBuilder.buildPlacementContext());
expectedPlacements = Set.of("2 PULL 0");
verifyPlacements(expectedPlacements, pp, collectionBuilder.getShardBuilders(), liveNodes);
@@ -566,9 +582,7 @@ public void testAvailabilityZones() throws Exception {
.map(Shard::getShardName)
.collect(Collectors.toSet()),
cluster.getLiveNodes(),
- 2,
- 2,
- 2);
+ new ReplicaCount(2, 2, 2));
PlacementPlan pp = plugin.computePlacement(placementRequest, placementContext);
// 2 shards, 6 replicas
@@ -640,9 +654,7 @@ public void testReplicaType() throws Exception {
.map(Shard::getShardName)
.collect(Collectors.toSet()),
cluster.getLiveNodes(),
- 2,
- 2,
- 2);
+ new ReplicaCount(2, 2, 2));
PlacementPlan pp = plugin.computePlacement(placementRequest, placementContext);
// 2 shards, 6 replicas
@@ -721,9 +733,7 @@ public void testFreeDiskConstraints() throws Exception {
.map(Shard::getShardName)
.collect(Collectors.toSet()),
cluster.getLiveNodes(),
- 1,
- 0,
- 1);
+ new ReplicaCount(1, 0, 1));
PlacementPlan pp = plugin.computePlacement(placementRequest, placementContext);
assertEquals(4, pp.getReplicaPlacements().size());
@@ -772,9 +782,7 @@ public void testFreeDiskConstraintsWithNewReplicas() throws Exception {
.map(Set::of)
.orElseGet(Collections::emptySet),
cluster.getLiveNodes(),
- 0,
- 1,
- 1);
+ new ReplicaCount(0, 1, 1));
assertThrows(
PlacementException.class,
@@ -789,9 +797,7 @@ public void testFreeDiskConstraintsWithNewReplicas() throws Exception {
.map(Shard::getShardName)
.collect(Collectors.toSet()),
cluster.getLiveNodes(),
- 0,
- 1,
- 1);
+ new ReplicaCount(0, 1, 1));
assertThrows(
PlacementException.class,
@@ -845,7 +851,10 @@ public void testWithCollectionPlacement() throws Exception {
PlacementRequestImpl placementRequest =
new PlacementRequestImpl(
- primaryCollection, Set.of("shard1", "shard2"), cluster.getLiveNodes(), 1, 0, 0);
+ primaryCollection,
+ Set.of("shard1", "shard2"),
+ cluster.getLiveNodes(),
+ new ReplicaCount(1, 0, 0));
PlacementPlan pp = plugin.computePlacement(placementRequest, placementContext);
assertEquals(2, pp.getReplicaPlacements().size());
@@ -859,7 +868,7 @@ public void testWithCollectionPlacement() throws Exception {
placementRequest =
new PlacementRequestImpl(
- primaryCollection, Set.of("shard1"), cluster.getLiveNodes(), 3, 0, 0);
+ primaryCollection, Set.of("shard1"), cluster.getLiveNodes(), new ReplicaCount(3, 0, 0));
try {
pp = plugin.computePlacement(placementRequest, placementContext);
fail("should generate 'Not enough eligible nodes' failure here");
@@ -909,9 +918,7 @@ public void testWithCollectionShardsPlacement() throws Exception {
primaryCollection,
shuffle(Arrays.asList("shard2", "shard1")),
shuffle(cluster.getLiveNodes()),
- 1,
- 0,
- 0);
+ new ReplicaCount(1, 0, 0));
PlacementPlan pp = plugin.computePlacement(placementRequest, placementContext);
assertEquals(2, pp.getReplicaPlacements().size());
@@ -939,7 +946,7 @@ public void testWithCollectionShardsPlacement() throws Exception {
placementRequest =
new PlacementRequestImpl(
- primaryCollection, Set.of("shard3"), cluster.getLiveNodes(), 1, 0, 0);
+ primaryCollection, Set.of("shard3"), cluster.getLiveNodes(), new ReplicaCount(1, 0, 0));
try {
pp = plugin.computePlacement(placementRequest, placementContext);
fail("should generate 'has no replicas on eligible nodes' failure here");
@@ -1171,7 +1178,10 @@ public void testNodeType() throws Exception {
SolrCollection collection = placementContext.getCluster().getCollection(collectionName);
PlacementRequestImpl placementRequest =
new PlacementRequestImpl(
- collection, Set.of("shard1"), placementContext.getCluster().getLiveNodes(), 3, 0, 0);
+ collection,
+ Set.of("shard1"),
+ placementContext.getCluster().getLiveNodes(),
+ new ReplicaCount(3, 0, 0));
PlacementPlan pp = plugin.computePlacement(placementRequest, placementContext);
assertEquals("expected 3 placements: " + pp, 3, pp.getReplicaPlacements().size());
@@ -1196,7 +1206,10 @@ public void testNodeType() throws Exception {
collection = placementContext.getCluster().getCollection(collectionName);
placementRequest =
new PlacementRequestImpl(
- collection, Set.of("shard1"), placementContext.getCluster().getLiveNodes(), 6, 0, 0);
+ collection,
+ Set.of("shard1"),
+ placementContext.getCluster().getLiveNodes(),
+ new ReplicaCount(6, 0, 0));
pp = plugin.computePlacement(placementRequest, placementContext);
assertEquals("expected 6 placements: " + pp, 6, pp.getReplicaPlacements().size());
@@ -1220,7 +1233,10 @@ public void testNodeType() throws Exception {
collection = placementContext.getCluster().getCollection(collectionName);
placementRequest =
new PlacementRequestImpl(
- collection, Set.of("shard1"), placementContext.getCluster().getLiveNodes(), 6, 0, 0);
+ collection,
+ Set.of("shard1"),
+ placementContext.getCluster().getLiveNodes(),
+ new ReplicaCount(6, 0, 0));
pp = plugin.computePlacement(placementRequest, placementContext);
assertEquals("expected 6 placements: " + pp, 6, pp.getReplicaPlacements().size());
nodeNamesByType.clear();
@@ -1337,9 +1353,7 @@ private void runTestScalability(
solrCollection,
solrCollection.getShardNames(),
new HashSet<>(liveNodes),
- nrtReplicas,
- tlogReplicas,
- pullReplicas);
+ new ReplicaCount(nrtReplicas, tlogReplicas, pullReplicas));
long start = System.nanoTime();
PlacementPlan pp = plugin.computePlacement(placementRequest, placementContext);
@@ -1430,9 +1444,7 @@ public void testAntiAffinityIsSoft() throws Exception {
solrCollection,
Set.of(solrCollection.shards().iterator().next().getShardName()),
new HashSet<>(liveNodes),
- 1,
- 0,
- 0);
+ new ReplicaCount(1, 0, 0));
PlacementPlan pp = plugin.computePlacement(placementRequest, placementContext);
@@ -1447,9 +1459,7 @@ public void testAntiAffinityIsSoft() throws Exception {
solrCollection,
Set.of(solrCollection.shards().iterator().next().getShardName()),
new HashSet<>(liveNodes),
- 2,
- 0,
- 0);
+ new ReplicaCount(2, 0, 0));
PlacementPlan pp = plugin.computePlacement(placementRequest, placementContext);
@@ -1519,9 +1529,7 @@ private void testSpreadDomains(boolean hasExistingCollection) throws Exception {
solrCollection,
Set.of(solrCollection.shards().iterator().next().getShardName()),
new HashSet<>(liveNodes),
- 1,
- 0,
- 0);
+ new ReplicaCount(1, 0, 0));
PlacementPlan pp = plugin.computePlacement(placementRequest, placementContext);
@@ -1536,9 +1544,7 @@ private void testSpreadDomains(boolean hasExistingCollection) throws Exception {
solrCollection,
Set.of(solrCollection.shards().iterator().next().getShardName()),
new HashSet<>(liveNodes),
- 2,
- 0,
- 0);
+ new ReplicaCount(2, 0, 0));
PlacementPlan pp = plugin.computePlacement(placementRequest, placementContext);
@@ -1582,9 +1588,7 @@ public void testSpreadDomainsWithDownNode() throws Exception {
solrCollection,
Set.of(solrCollection.shards().iterator().next().getShardName()),
new HashSet<>(liveNodes),
- 1,
- 0,
- 0);
+ new ReplicaCount(1, 0, 0));
PlacementPlan pp = plugin.computePlacement(placementRequest, placementContext);
diff --git a/solr/core/src/test/org/apache/solr/cluster/placement/plugins/MinimizeCoresPlacementFactoryTest.java b/solr/core/src/test/org/apache/solr/cluster/placement/plugins/MinimizeCoresPlacementFactoryTest.java
index 6afd24fafd1..03a272110ac 100644
--- a/solr/core/src/test/org/apache/solr/cluster/placement/plugins/MinimizeCoresPlacementFactoryTest.java
+++ b/solr/core/src/test/org/apache/solr/cluster/placement/plugins/MinimizeCoresPlacementFactoryTest.java
@@ -33,6 +33,7 @@
import org.apache.solr.cluster.placement.ReplicaPlacement;
import org.apache.solr.cluster.placement.impl.BalanceRequestImpl;
import org.apache.solr.cluster.placement.impl.PlacementRequestImpl;
+import org.apache.solr.common.cloud.ReplicaCount;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
@@ -101,9 +102,7 @@ private void testBasicPlacementInternal(boolean hasExistingCollection) throws Ex
solrCollection,
Set.of(solrCollection.shards().iterator().next().getShardName()),
new HashSet<>(liveNodes),
- 1,
- 0,
- 0);
+ new ReplicaCount(1, 0, 0));
PlacementPlan pp = plugin.computePlacement(placementRequest, placementContext);
@@ -147,7 +146,10 @@ public void testPlacementWithExistingReplicas() throws Exception {
// Place an additional NRT and an additional TLOG replica for each shard
PlacementRequestImpl placementRequest =
new PlacementRequestImpl(
- solrCollection, solrCollection.getShardNames(), new HashSet<>(liveNodes), 1, 1, 0);
+ solrCollection,
+ solrCollection.getShardNames(),
+ new HashSet<>(liveNodes),
+ new ReplicaCount(1, 1, 0));
// The replicas must be placed on the most appropriate nodes, i.e. those that do not already
// have a replica for the shard and then on the node with the lowest number of cores. NRT are
@@ -198,9 +200,7 @@ public void testCollectionOnDeadNodes() throws Exception {
solrCollection,
Set.of(solrCollection.iterator().next().getShardName()),
new HashSet<>(liveNodes),
- 0,
- 0,
- 1);
+ new ReplicaCount(0, 0, 1));
PlacementPlan pp =
plugin.computePlacement(placementRequest, clusterBuilder.buildPlacementContext());
@@ -216,7 +216,10 @@ public void testCollectionOnDeadNodes() throws Exception {
it.next(); // skip first shard to do placement for the second one...
placementRequest =
new PlacementRequestImpl(
- solrCollection, Set.of(it.next().getShardName()), new HashSet<>(liveNodes), 0, 0, 1);
+ solrCollection,
+ Set.of(it.next().getShardName()),
+ new HashSet<>(liveNodes),
+ new ReplicaCount(0, 0, 1));
pp = plugin.computePlacement(placementRequest, clusterBuilder.buildPlacementContext());
expectedPlacements = Set.of("2 PULL 0");
verifyPlacements(expectedPlacements, pp, collectionBuilder.getShardBuilders(), liveNodes);
diff --git a/solr/core/src/test/org/apache/solr/handler/TestRestoreCore.java b/solr/core/src/test/org/apache/solr/handler/TestRestoreCore.java
index b46bbfb6ff6..593f0af7bd9 100644
--- a/solr/core/src/test/org/apache/solr/handler/TestRestoreCore.java
+++ b/solr/core/src/test/org/apache/solr/handler/TestRestoreCore.java
@@ -19,6 +19,7 @@
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -128,7 +129,7 @@ public void testSimpleRestore() throws Exception {
.getCoreContainer()
.getAllowPaths()
.add(Path.of(location)); // Allow core to be created outside SOLR_HOME
- params += "&location=" + URLEncoder.encode(location, "UTF-8");
+ params += "&location=" + URLEncoder.encode(location, StandardCharsets.UTF_8);
}
// named snapshot vs default snapshot name
@@ -188,7 +189,8 @@ public void testSimpleRestore() throws Exception {
public void testBackupFailsMissingAllowPaths() throws Exception {
final String params =
- "&location=" + URLEncoder.encode(createTempDir().toFile().getAbsolutePath(), "UTF-8");
+ "&location="
+ + URLEncoder.encode(createTempDir().toFile().getAbsolutePath(), StandardCharsets.UTF_8);
Throwable t =
expectThrows(
IOException.class,
@@ -207,7 +209,11 @@ public void testFailedRestore() throws Exception {
String location = createTempDir().toFile().getAbsolutePath();
leaderJetty.getCoreContainer().getAllowPaths().add(Path.of(location));
String snapshotName = TestUtil.randomSimpleString(random(), 1, 5);
- String params = "&name=" + snapshotName + "&location=" + URLEncoder.encode(location, "UTF-8");
+ String params =
+ "&name="
+ + snapshotName
+ + "&location="
+ + URLEncoder.encode(location, StandardCharsets.UTF_8);
String baseUrl = leaderJetty.getBaseUrl().toString();
TestReplicationHandlerBackup.runBackupCommand(
diff --git a/solr/core/src/test/org/apache/solr/handler/component/DistributedDebugComponentTest.java b/solr/core/src/test/org/apache/solr/handler/component/DistributedDebugComponentTest.java
index 92c73f969a6..f9b13f318ce 100644
--- a/solr/core/src/test/org/apache/solr/handler/component/DistributedDebugComponentTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/component/DistributedDebugComponentTest.java
@@ -226,7 +226,7 @@ public void testRandom() throws Exception {
debug.add("true");
all = true;
}
- q.set("debug", debug.toArray(new String[debug.size()]));
+ q.set("debug", debug.toArray(new String[0]));
QueryResponse r = client.query(q);
try {
diff --git a/solr/core/src/test/org/apache/solr/handler/component/DistributedQueryComponentOptimizationTest.java b/solr/core/src/test/org/apache/solr/handler/component/DistributedQueryComponentOptimizationTest.java
index 5f00e3f4264..8df32f40837 100644
--- a/solr/core/src/test/org/apache/solr/handler/component/DistributedQueryComponentOptimizationTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/component/DistributedQueryComponentOptimizationTest.java
@@ -654,14 +654,14 @@ private QueryResponse queryWithAsserts(String... q) throws Exception {
SHARD1,
CommonParams.FL,
ShardRequest.PURPOSE_GET_TOP_IDS,
- reqAndIdScoreFields.toArray(new String[reqAndIdScoreFields.size()]));
+ reqAndIdScoreFields.toArray(new String[0]));
assertParamsEquals(
trackingQueue,
COLLECTION,
SHARD2,
CommonParams.FL,
ShardRequest.PURPOSE_GET_TOP_IDS,
- reqAndIdScoreFields.toArray(new String[reqAndIdScoreFields.size()]));
+ reqAndIdScoreFields.toArray(new String[0]));
} else {
// we are assuming there are facet refinement or distributed idf requests here
assertTrue(
@@ -679,14 +679,14 @@ private QueryResponse queryWithAsserts(String... q) throws Exception {
SHARD1,
CommonParams.FL,
ShardRequest.PURPOSE_GET_TOP_IDS,
- idScoreFields.toArray(new String[idScoreFields.size()]));
+ idScoreFields.toArray(new String[0]));
assertParamsEquals(
trackingQueue,
COLLECTION,
SHARD2,
CommonParams.FL,
ShardRequest.PURPOSE_GET_TOP_IDS,
- idScoreFields.toArray(new String[idScoreFields.size()]));
+ idScoreFields.toArray(new String[0]));
// only originally requested fields must be requested in GET_FIELDS request
assertParamsEquals(
@@ -695,14 +695,14 @@ private QueryResponse queryWithAsserts(String... q) throws Exception {
SHARD1,
CommonParams.FL,
ShardRequest.PURPOSE_GET_FIELDS,
- fls.toArray(new String[fls.size()]));
+ fls.toArray(new String[0]));
assertParamsEquals(
trackingQueue,
COLLECTION,
SHARD2,
CommonParams.FL,
ShardRequest.PURPOSE_GET_FIELDS,
- fls.toArray(new String[fls.size()]));
+ fls.toArray(new String[0]));
}
return response;
diff --git a/solr/core/src/test/org/apache/solr/handler/component/DistributedSpellCheckComponentTest.java b/solr/core/src/test/org/apache/solr/handler/component/DistributedSpellCheckComponentTest.java
index 72fd63f1004..501a8863f0b 100644
--- a/solr/core/src/test/org/apache/solr/handler/component/DistributedSpellCheckComponentTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/component/DistributedSpellCheckComponentTest.java
@@ -431,6 +431,6 @@ private Object[] buildRequest(
if (addlParams != null) {
params.addAll(Arrays.asList(addlParams));
}
- return params.toArray(new Object[params.size()]);
+ return params.toArray(new Object[0]);
}
}
diff --git a/solr/core/src/test/org/apache/solr/handler/component/DistributedSuggestComponentTest.java b/solr/core/src/test/org/apache/solr/handler/component/DistributedSuggestComponentTest.java
index f916427d6ae..e1947ea85c1 100644
--- a/solr/core/src/test/org/apache/solr/handler/component/DistributedSuggestComponentTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/component/DistributedSuggestComponentTest.java
@@ -146,6 +146,6 @@ private Object[] buildRequest(
if (addlParams != null) {
params.addAll(Arrays.asList(addlParams));
}
- return params.toArray(new Object[params.size()]);
+ return params.toArray(new Object[0]);
}
}
diff --git a/solr/core/src/test/org/apache/solr/handler/component/DistributedTermsComponentTest.java b/solr/core/src/test/org/apache/solr/handler/component/DistributedTermsComponentTest.java
index 430b9074699..fbeda40717f 100644
--- a/solr/core/src/test/org/apache/solr/handler/component/DistributedTermsComponentTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/component/DistributedTermsComponentTest.java
@@ -196,7 +196,7 @@ protected QueryResponse query(Object... q) throws Exception {
params.add("terms.maxcount");
params.add(random().nextInt(4) - 1);
}
- q = params.toArray(new Object[params.size()]);
+ q = params.toArray(new Object[0]);
break;
}
}
diff --git a/solr/core/src/test/org/apache/solr/handler/component/StatsComponentTest.java b/solr/core/src/test/org/apache/solr/handler/component/StatsComponentTest.java
index 31c2ba8d91e..dfe5118a9a4 100644
--- a/solr/core/src/test/org/apache/solr/handler/component/StatsComponentTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/component/StatsComponentTest.java
@@ -1683,7 +1683,7 @@ public void testIndividualStatLocalParams() {
"true",
"stats.field",
"{!key=k " + exclude + stat + "=" + expect.input + "}a_i"),
- testXpaths.toArray(new String[testXpaths.size()]));
+ testXpaths.toArray(new String[0]));
}
// test all the possible combinations (of all possible sizes) of stats params
@@ -1714,7 +1714,7 @@ public void testIndividualStatLocalParams() {
assertQ(
"ask for and get only: " + combo,
req("q", "*:*", "stats", "true", "stats.field", paras.toString()),
- testXpaths.toArray(new String[testXpaths.size()]));
+ testXpaths.toArray(new String[0]));
}
}
}
@@ -2342,7 +2342,7 @@ public static final class StatSetCombinations implements Iterable>
public StatSetCombinations(int comboSize, EnumSet universe) {
// NOTE: should not need to sort, EnumSet uses natural ordering
- all = universe.toArray(new Stat[universe.size()]);
+ all = universe.toArray(new Stat[0]);
intCombos = new Combinations(all.length, comboSize);
}
diff --git a/solr/core/src/test/org/apache/solr/handler/tagger/RandomizedTaggerTest.java b/solr/core/src/test/org/apache/solr/handler/tagger/RandomizedTaggerTest.java
index e0d11111a7b..0d770412952 100644
--- a/solr/core/src/test/org/apache/solr/handler/tagger/RandomizedTaggerTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/tagger/RandomizedTaggerTest.java
@@ -81,7 +81,7 @@ public void test() throws Exception {
}
// BUILD NAMES
- buildNames(names.toArray(new String[names.size()]));
+ buildNames(names.toArray(new String[0]));
// QUERY LOOP
for (int tTries = 0; tTries < 10 * RANDOM_MULTIPLIER; tTries++) {
@@ -137,7 +137,7 @@ private void assertBruteForce(String input) throws Exception {
}
// assert
- assertTags(reqDoc(input), testTags.toArray(new TestTag[testTags.size()]));
+ assertTags(reqDoc(input), testTags.toArray(new TestTag[0]));
}
private String randomString() {
diff --git a/solr/core/src/test/org/apache/solr/metrics/reporters/SolrGraphiteReporterTest.java b/solr/core/src/test/org/apache/solr/metrics/reporters/SolrGraphiteReporterTest.java
index 49e0cef9824..24984623f1e 100644
--- a/solr/core/src/test/org/apache/solr/metrics/reporters/SolrGraphiteReporterTest.java
+++ b/solr/core/src/test/org/apache/solr/metrics/reporters/SolrGraphiteReporterTest.java
@@ -76,7 +76,7 @@ public void testReporter() throws Exception {
assertTrue(reporter instanceof SolrGraphiteReporter);
Thread.sleep(5000);
assertTrue(mock.lines.size() >= 3);
- String[] frozenLines = mock.lines.toArray(new String[mock.lines.size()]);
+ String[] frozenLines = mock.lines.toArray(new String[0]);
for (String line : frozenLines) {
assertTrue(line, line.startsWith("test.solr.node.CONTAINER.cores."));
}
diff --git a/solr/core/src/test/org/apache/solr/request/SimpleFacetsTest.java b/solr/core/src/test/org/apache/solr/request/SimpleFacetsTest.java
index 505fc793ec9..408b0c5c378 100644
--- a/solr/core/src/test/org/apache/solr/request/SimpleFacetsTest.java
+++ b/solr/core/src/test/org/apache/solr/request/SimpleFacetsTest.java
@@ -82,7 +82,7 @@ static void add_doc(String... fieldsAndValues) {
fieldsAndValuesList.add("bday_drf");
fieldsAndValuesList.add(fieldsAndValuesList.get(idx + 1)); // copy
}
- fieldsAndValues = fieldsAndValuesList.toArray(new String[fieldsAndValuesList.size()]);
+ fieldsAndValues = fieldsAndValuesList.toArray(new String[0]);
pendingDocs.add(fieldsAndValues);
} while (random().nextInt(100) <= random_dupe_percent);
diff --git a/solr/core/src/test/org/apache/solr/request/TestWriterPerf.java b/solr/core/src/test/org/apache/solr/request/TestWriterPerf.java
index 95ddfb1c459..f8d1942945e 100644
--- a/solr/core/src/test/org/apache/solr/request/TestWriterPerf.java
+++ b/solr/core/src/test/org/apache/solr/request/TestWriterPerf.java
@@ -73,7 +73,7 @@ public void tearDown() throws Exception {
void index(Object... olst) {
ArrayList lst = new ArrayList<>();
for (Object o : olst) lst.add(o.toString());
- assertU(adoc(lst.toArray(new String[lst.size()])));
+ assertU(adoc(lst.toArray(new String[0])));
}
void makeIndex() {
diff --git a/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedStopFilterFactory.java b/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedStopFilterFactory.java
index a1fff16edc0..d3aa476693c 100644
--- a/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedStopFilterFactory.java
+++ b/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedStopFilterFactory.java
@@ -191,6 +191,18 @@ public void testManagedStopwords() throws Exception {
// should fail with 404 as foo doesn't exist
assertJDelete(endpoint + "/foo", "/error/code==404");
+
+ // test for SOLR-6853 - should be able to delete stopwords with slash
+ assertJPut(
+ endpoint,
+ Utils.toJSONString(Arrays.asList("cheerful/joyful", "sleepy/tired")),
+ "/responseHeader/status==0");
+
+ // verify delete works
+ assertJDelete(endpoint + "/cheerful/joyful", "/responseHeader/status==0");
+
+ // should fail with 404 as some/thing doesn't exist
+ assertJDelete(endpoint + "/cheerful/joyful", "/error/code==404");
}
/** Can we add and remove stopwords with umlauts */
diff --git a/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedSynonymGraphFilterFactory.java b/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedSynonymGraphFilterFactory.java
index c5363c7f251..f27bdbc0d5d 100644
--- a/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedSynonymGraphFilterFactory.java
+++ b/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedSynonymGraphFilterFactory.java
@@ -249,6 +249,17 @@ public void testManagedSynonyms() throws Exception {
"/entertaining==['entertaining','funny','jocular','whimsical']");
assertJQ(endpoint + "/jocular", "/jocular==['entertaining','funny','jocular','whimsical']");
assertJQ(endpoint + "/whimsical", "/whimsical==['entertaining','funny','jocular','whimsical']");
+
+ // test for SOLR-6853 - should be able to delete synonyms with slash
+ Map> slashSyns = new HashMap<>();
+ slashSyns.put("cheerful/joyful", List.of("sleepy/tired"));
+ assertJPut(endpoint, toJSONString(slashSyns), "/responseHeader/status==0");
+
+ // verify delete works
+ assertJDelete(endpoint + "/cheerful/joyful", "/responseHeader/status==0");
+
+ // should fail with 404 as some/thing doesn't exist
+ assertJDelete(endpoint + "/cheerful/joyful", "/error/code==404");
}
/** Can we add and remove stopwords with umlauts */
diff --git a/solr/core/src/test/org/apache/solr/schema/TestPointFields.java b/solr/core/src/test/org/apache/solr/schema/TestPointFields.java
index e3a8f16a8b9..ffb6f69ee29 100644
--- a/solr/core/src/test/org/apache/solr/schema/TestPointFields.java
+++ b/solr/core/src/test/org/apache/solr/schema/TestPointFields.java
@@ -3108,12 +3108,11 @@ public void testMultiValuedDatePointFieldsAtomicUpdates() throws Exception {
if (!Boolean.getBoolean("enable.update.log")) {
return;
}
- List datesList =
+ String[] dates =
getRandomLongs(3, false, MAX_DATE_EPOCH_MILLIS).stream()
.map(Instant::ofEpochMilli)
.map(Object::toString)
- .collect(Collectors.toList());
- String[] dates = datesList.toArray(new String[datesList.size()]);
+ .toArray(String[]::new);
doTestMultiValuedPointFieldsAtomicUpdates("number_p_dt_mv", "date", dates);
doTestMultiValuedPointFieldsAtomicUpdates("number_p_dt_ni_mv_dv", "date", dates);
doTestMultiValuedPointFieldsAtomicUpdates("number_p_dt_dv_ns_mv", "date", dates);
diff --git a/solr/core/src/test/org/apache/solr/schema/TestSortableTextField.java b/solr/core/src/test/org/apache/solr/schema/TestSortableTextField.java
index 98fb2288d5d..2864ced67d9 100644
--- a/solr/core/src/test/org/apache/solr/schema/TestSortableTextField.java
+++ b/solr/core/src/test/org/apache/solr/schema/TestSortableTextField.java
@@ -532,7 +532,7 @@ public void testUseDocValuesAsStored() {
// check all our expected docs can be found (with the expected values)
assertU(commit());
xpaths.add("//*[@numFound='" + xpaths.size() + "']");
- assertQ(req("q", "*:*", "fl", "*"), xpaths.toArray(new String[xpaths.size()]));
+ assertQ(req("q", "*:*", "fl", "*"), xpaths.toArray(new String[0]));
}
/**
diff --git a/solr/core/src/test/org/apache/solr/search/RankQueryTestPlugin.java b/solr/core/src/test/org/apache/solr/search/RankQueryTestPlugin.java
index 791a26369af..7b3f77456cc 100644
--- a/solr/core/src/test/org/apache/solr/search/RankQueryTestPlugin.java
+++ b/solr/core/src/test/org/apache/solr/search/RankQueryTestPlugin.java
@@ -757,7 +757,7 @@ public int compare(ScoreDoc s1, ScoreDoc s2) {
}
}
});
- ScoreDoc[] scoreDocs = list.toArray(new ScoreDoc[list.size()]);
+ ScoreDoc[] scoreDocs = list.toArray(new ScoreDoc[0]);
return new TopDocs(new TotalHits(list.size(), TotalHits.Relation.EQUAL_TO), scoreDocs);
}
@@ -824,7 +824,7 @@ public int compare(ScoreDoc s1, ScoreDoc s2) {
}
}
});
- ScoreDoc[] scoreDocs = list.toArray(new ScoreDoc[list.size()]);
+ ScoreDoc[] scoreDocs = list.toArray(new ScoreDoc[0]);
return new TopDocs(new TotalHits(list.size(), TotalHits.Relation.EQUAL_TO), scoreDocs);
}
diff --git a/solr/core/src/test/org/apache/solr/search/TestFiltering.java b/solr/core/src/test/org/apache/solr/search/TestFiltering.java
index e6326508037..5d9ad6bb9da 100644
--- a/solr/core/src/test/org/apache/solr/search/TestFiltering.java
+++ b/solr/core/src/test/org/apache/solr/search/TestFiltering.java
@@ -539,7 +539,7 @@ public void testRandomFiltering() throws Exception {
}
}
- SolrQueryRequest sreq = req(params.toArray(new String[params.size()]));
+ SolrQueryRequest sreq = req(params.toArray(new String[0]));
long expected = model.answer.cardinality();
long expectedMultiSelect = model.multiSelect.cardinality();
long expectedFacetQuery = model.facetQuery.cardinality();
diff --git a/solr/core/src/test/org/apache/solr/search/TestFiltersQueryCaching.java b/solr/core/src/test/org/apache/solr/search/TestFiltersQueryCaching.java
index 72edc410184..0319b1be6d0 100644
--- a/solr/core/src/test/org/apache/solr/search/TestFiltersQueryCaching.java
+++ b/solr/core/src/test/org/apache/solr/search/TestFiltersQueryCaching.java
@@ -214,7 +214,6 @@ private static void doTestAbsentParams(Collection fqsArgs, int expectNum
List request = new ArrayList<>();
request.addAll(List.of("q", "*:*", "indent", "true", "fq", "{!filters param=$fqs}"));
request.addAll(fqsArgs);
- assertJQ(
- req(request.toArray(new String[request.size()])), "/response/numFound==" + expectNumFound);
+ assertJQ(req(request.toArray(new String[0])), "/response/numFound==" + expectNumFound);
}
}
diff --git a/solr/core/src/test/org/apache/solr/search/TestRangeQuery.java b/solr/core/src/test/org/apache/solr/search/TestRangeQuery.java
index b8e0380988f..b0642284740 100644
--- a/solr/core/src/test/org/apache/solr/search/TestRangeQuery.java
+++ b/solr/core/src/test/org/apache/solr/search/TestRangeQuery.java
@@ -170,7 +170,7 @@ public void testRangeQueries() {
fields.add(entry.getKey());
fields.add(entry.getValue()[j]);
}
- assertU(adoc(fields.toArray(new String[fields.size()])));
+ assertU(adoc(fields.toArray(new String[0])));
}
assertU(commit());
diff --git a/solr/core/src/test/org/apache/solr/search/TestSort.java b/solr/core/src/test/org/apache/solr/search/TestSort.java
index 7bb29329f23..a13b1b1081a 100644
--- a/solr/core/src/test/org/apache/solr/search/TestSort.java
+++ b/solr/core/src/test/org/apache/solr/search/TestSort.java
@@ -311,7 +311,7 @@ public int hashCode() {
}
if (r.nextBoolean()) sfields.add(new SortField(null, SortField.Type.SCORE));
- Sort sort = new Sort(sfields.toArray(new SortField[sfields.size()]));
+ Sort sort = new Sort(sfields.toArray(new SortField[0]));
final String nullRep =
luceneSort || (sortMissingFirst && !reverse) || (sortMissingLast && reverse)
diff --git a/solr/core/src/test/org/apache/solr/search/function/TestMinMaxOnMultiValuedField.java b/solr/core/src/test/org/apache/solr/search/function/TestMinMaxOnMultiValuedField.java
index 5e2f648add7..67768a12aea 100644
--- a/solr/core/src/test/org/apache/solr/search/function/TestMinMaxOnMultiValuedField.java
+++ b/solr/core/src/test/org/apache/solr/search/function/TestMinMaxOnMultiValuedField.java
@@ -1055,7 +1055,7 @@ private void testExpectedSortOrdering(
}
assertQ(
req("q", "*:*", "rows", "" + sortedDocs.size(), "sort", sort),
- xpaths.toArray(new String[xpaths.size()]));
+ xpaths.toArray(new String[0]));
}
/**
diff --git a/solr/core/src/test/org/apache/solr/servlet/DirectSolrConnectionTest.java b/solr/core/src/test/org/apache/solr/servlet/DirectSolrConnectionTest.java
index 33c04688009..8166578f8e2 100644
--- a/solr/core/src/test/org/apache/solr/servlet/DirectSolrConnectionTest.java
+++ b/solr/core/src/test/org/apache/solr/servlet/DirectSolrConnectionTest.java
@@ -17,6 +17,7 @@
package org.apache.solr.servlet;
import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.params.CommonParams;
import org.junit.BeforeClass;
@@ -65,7 +66,11 @@ public void testInsertThenSelect() throws Exception {
// Test using the Stream body parameter
for (String cmd : cmds) {
direct.request(
- "/update?" + CommonParams.STREAM_BODY + "=" + URLEncoder.encode(cmd, "UTF-8"), null);
+ "/update?"
+ + CommonParams.STREAM_BODY
+ + "="
+ + URLEncoder.encode(cmd, StandardCharsets.UTF_8),
+ null);
}
String got = direct.request(getIt, null);
assertTrue(got.indexOf(value) > 0);
diff --git a/solr/core/src/test/org/apache/solr/uninverting/TestDocTermOrds.java b/solr/core/src/test/org/apache/solr/uninverting/TestDocTermOrds.java
index f955196312a..21aa4f1576c 100644
--- a/solr/core/src/test/org/apache/solr/uninverting/TestDocTermOrds.java
+++ b/solr/core/src/test/org/apache/solr/uninverting/TestDocTermOrds.java
@@ -152,7 +152,7 @@ public void testRandom() throws Exception {
terms.add(new BytesRef(s));
}
}
- final BytesRef[] termsArray = terms.toArray(new BytesRef[terms.size()]);
+ final BytesRef[] termsArray = terms.toArray(new BytesRef[0]);
Arrays.sort(termsArray);
final int NUM_DOCS = atLeast(100);
@@ -240,7 +240,7 @@ public void testRandomWithPrefix() throws Exception {
prefixes.add(TestUtil.randomRealisticUnicodeString(random()));
// prefixes.add(_TestUtil.randomSimpleString(random));
}
- final String[] prefixesArray = prefixes.toArray(new String[prefixes.size()]);
+ final String[] prefixesArray = prefixes.toArray(new String[0]);
final int NUM_TERMS = atLeast(20);
final Set terms = new HashSet<>();
@@ -254,7 +254,7 @@ public void testRandomWithPrefix() throws Exception {
terms.add(new BytesRef(s));
}
}
- final BytesRef[] termsArray = terms.toArray(new BytesRef[terms.size()]);
+ final BytesRef[] termsArray = terms.toArray(new BytesRef[0]);
Arrays.sort(termsArray);
final int NUM_DOCS = atLeast(100);
diff --git a/solr/core/src/test/org/apache/solr/util/TestUtils.java b/solr/core/src/test/org/apache/solr/util/TestUtils.java
index 949c2dc15fe..e05f3130360 100644
--- a/solr/core/src/test/org/apache/solr/util/TestUtils.java
+++ b/solr/core/src/test/org/apache/solr/util/TestUtils.java
@@ -18,9 +18,10 @@
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Arrays.asList;
-import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_DEF;
+import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.NRT_REPLICAS;
import static org.apache.solr.common.cloud.ZkStateReader.NUM_SHARDS_PROP;
+import static org.apache.solr.common.params.CollectionAdminParams.DEFAULTS;
import static org.apache.solr.common.util.Utils.fromJSONString;
import java.io.ByteArrayOutputStream;
@@ -287,8 +288,10 @@ public void testMergeJson() {
Utils.mergeJson(
sink,
(Map)
- Utils.fromJSONString("collectionDefaults:{numShards:3 , nrtReplicas:2}")));
- assertEquals(3L, Utils.getObjectByPath(sink, true, List.of(COLLECTION_DEF, NUM_SHARDS_PROP)));
- assertEquals(2L, Utils.getObjectByPath(sink, true, List.of(COLLECTION_DEF, NRT_REPLICAS)));
+ Utils.fromJSONString("defaults: {collection: {numShards:3 , nrtReplicas:2}}")));
+ assertEquals(
+ 3L, Utils.getObjectByPath(sink, true, List.of(DEFAULTS, COLLECTION_PROP, NUM_SHARDS_PROP)));
+ assertEquals(
+ 2L, Utils.getObjectByPath(sink, true, List.of(DEFAULTS, COLLECTION_PROP, NRT_REPLICAS)));
}
}
diff --git a/solr/licenses/error_prone_annotations-2.22.0.jar.sha1 b/solr/licenses/error_prone_annotations-2.22.0.jar.sha1
deleted file mode 100644
index a0a78a421a9..00000000000
--- a/solr/licenses/error_prone_annotations-2.22.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-bfb9e4281a4cea34f0ec85b3acd47621cfab35b4
diff --git a/solr/licenses/error_prone_annotations-2.23.0.jar.sha1 b/solr/licenses/error_prone_annotations-2.23.0.jar.sha1
new file mode 100644
index 00000000000..4e95d96af0c
--- /dev/null
+++ b/solr/licenses/error_prone_annotations-2.23.0.jar.sha1
@@ -0,0 +1 @@
+43a27853b6c7d54893e0b1997c2c778c347179eb
diff --git a/solr/licenses/grpc-alts-1.58.0.jar.sha1 b/solr/licenses/grpc-alts-1.58.0.jar.sha1
deleted file mode 100644
index 6019d9701e6..00000000000
--- a/solr/licenses/grpc-alts-1.58.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-7e5ae496f9d7ae266abe30aa2848cbb3426b244e
diff --git a/solr/licenses/grpc-alts-1.59.0.jar.sha1 b/solr/licenses/grpc-alts-1.59.0.jar.sha1
new file mode 100644
index 00000000000..a920232bf9c
--- /dev/null
+++ b/solr/licenses/grpc-alts-1.59.0.jar.sha1
@@ -0,0 +1 @@
+bb4eda2c61102759e7c03ab12ff7c19547e20cbd
diff --git a/solr/licenses/grpc-api-1.58.0.jar.sha1 b/solr/licenses/grpc-api-1.58.0.jar.sha1
deleted file mode 100644
index e3782a67a1c..00000000000
--- a/solr/licenses/grpc-api-1.58.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-1f761949cdfd418a5f662e0d22d2c95f60099c0b
diff --git a/solr/licenses/grpc-api-1.59.0.jar.sha1 b/solr/licenses/grpc-api-1.59.0.jar.sha1
new file mode 100644
index 00000000000..25354bb147c
--- /dev/null
+++ b/solr/licenses/grpc-api-1.59.0.jar.sha1
@@ -0,0 +1 @@
+52da76c0c8190be88281aec828efd44df176ab34
diff --git a/solr/licenses/grpc-auth-1.58.0.jar.sha1 b/solr/licenses/grpc-auth-1.58.0.jar.sha1
deleted file mode 100644
index 15e05883800..00000000000
--- a/solr/licenses/grpc-auth-1.58.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-d7489cc1fc90658d43bf18307972db6b5305bb45
diff --git a/solr/licenses/grpc-auth-1.59.0.jar.sha1 b/solr/licenses/grpc-auth-1.59.0.jar.sha1
new file mode 100644
index 00000000000..ae48006db15
--- /dev/null
+++ b/solr/licenses/grpc-auth-1.59.0.jar.sha1
@@ -0,0 +1 @@
+878e2200222f5e11137d5bfde325a5db30687592
diff --git a/solr/licenses/grpc-context-1.58.0.jar.sha1 b/solr/licenses/grpc-context-1.58.0.jar.sha1
deleted file mode 100644
index 1a6b8003aa9..00000000000
--- a/solr/licenses/grpc-context-1.58.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-eae1e3ed15e40e3bd5c080a9bbb9a8eb1770afb7
diff --git a/solr/licenses/grpc-context-1.59.0.jar.sha1 b/solr/licenses/grpc-context-1.59.0.jar.sha1
new file mode 100644
index 00000000000..0084a08e353
--- /dev/null
+++ b/solr/licenses/grpc-context-1.59.0.jar.sha1
@@ -0,0 +1 @@
+44f8a2b2c0dfb15b4f112e22de76d837b89bd4d6
diff --git a/solr/licenses/grpc-core-1.58.0.jar.sha1 b/solr/licenses/grpc-core-1.58.0.jar.sha1
deleted file mode 100644
index 2c7016d5ee4..00000000000
--- a/solr/licenses/grpc-core-1.58.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-5a0fa4249397504443f7609754bf0acb50e0a0c5
diff --git a/solr/licenses/grpc-core-1.59.0.jar.sha1 b/solr/licenses/grpc-core-1.59.0.jar.sha1
new file mode 100644
index 00000000000..312e8809002
--- /dev/null
+++ b/solr/licenses/grpc-core-1.59.0.jar.sha1
@@ -0,0 +1 @@
+aaf681a518ce5c9a048328b86ba5b9c5123375aa
diff --git a/solr/licenses/grpc-googleapis-1.58.0.jar.sha1 b/solr/licenses/grpc-googleapis-1.58.0.jar.sha1
deleted file mode 100644
index 60cd4edc0cd..00000000000
--- a/solr/licenses/grpc-googleapis-1.58.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-2327b1875165d99a9b0fe2b52e257dfe0af29d6a
diff --git a/solr/licenses/grpc-googleapis-1.59.0.jar.sha1 b/solr/licenses/grpc-googleapis-1.59.0.jar.sha1
new file mode 100644
index 00000000000..ab3d3a80613
--- /dev/null
+++ b/solr/licenses/grpc-googleapis-1.59.0.jar.sha1
@@ -0,0 +1 @@
+532fd1449686690273222ebd5cb86c233ed19f58
diff --git a/solr/licenses/grpc-grpclb-1.58.0.jar.sha1 b/solr/licenses/grpc-grpclb-1.58.0.jar.sha1
deleted file mode 100644
index 1760630283e..00000000000
--- a/solr/licenses/grpc-grpclb-1.58.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-1d4e60a8053e583fd23b002c468df715ce7ffdab
diff --git a/solr/licenses/grpc-grpclb-1.59.0.jar.sha1 b/solr/licenses/grpc-grpclb-1.59.0.jar.sha1
new file mode 100644
index 00000000000..924c9dc5184
--- /dev/null
+++ b/solr/licenses/grpc-grpclb-1.59.0.jar.sha1
@@ -0,0 +1 @@
+60de19e6c8e44b1a78acb0dd73722b2feaa7ccfe
diff --git a/solr/licenses/grpc-netty-1.58.0.jar.sha1 b/solr/licenses/grpc-netty-1.58.0.jar.sha1
deleted file mode 100644
index 6f2a083cf72..00000000000
--- a/solr/licenses/grpc-netty-1.58.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-96ae48464ce0496e08c6a1c27a75e2135214fc7a
diff --git a/solr/licenses/grpc-netty-1.59.0.jar.sha1 b/solr/licenses/grpc-netty-1.59.0.jar.sha1
new file mode 100644
index 00000000000..e65dbdbcd36
--- /dev/null
+++ b/solr/licenses/grpc-netty-1.59.0.jar.sha1
@@ -0,0 +1 @@
+e8d15f9ec0c0a1f62478aeaa8c8c2770057ed4e1
diff --git a/solr/licenses/grpc-netty-shaded-1.58.0.jar.sha1 b/solr/licenses/grpc-netty-shaded-1.58.0.jar.sha1
deleted file mode 100644
index f37324555bc..00000000000
--- a/solr/licenses/grpc-netty-shaded-1.58.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-942622d5b4d908f9474ce5dbbdaa587e606cd9ed
diff --git a/solr/licenses/grpc-netty-shaded-1.59.0.jar.sha1 b/solr/licenses/grpc-netty-shaded-1.59.0.jar.sha1
new file mode 100644
index 00000000000..a3292aedddf
--- /dev/null
+++ b/solr/licenses/grpc-netty-shaded-1.59.0.jar.sha1
@@ -0,0 +1 @@
+71b610fca525744bc70eb96c9f9113cddbc38f4f
diff --git a/solr/licenses/grpc-protobuf-1.58.0.jar.sha1 b/solr/licenses/grpc-protobuf-1.58.0.jar.sha1
deleted file mode 100644
index a9934c4200b..00000000000
--- a/solr/licenses/grpc-protobuf-1.58.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-2e16536d0b9c27e7b28bf916a528aa92e9ea872d
diff --git a/solr/licenses/grpc-protobuf-1.59.0.jar.sha1 b/solr/licenses/grpc-protobuf-1.59.0.jar.sha1
new file mode 100644
index 00000000000..b261ea8e116
--- /dev/null
+++ b/solr/licenses/grpc-protobuf-1.59.0.jar.sha1
@@ -0,0 +1 @@
+2977cca2c82e3c5336805ebb6226c14137585b54
diff --git a/solr/licenses/grpc-protobuf-lite-1.58.0.jar.sha1 b/solr/licenses/grpc-protobuf-lite-1.58.0.jar.sha1
deleted file mode 100644
index 2f6c58b87af..00000000000
--- a/solr/licenses/grpc-protobuf-lite-1.58.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-60498c6688075a698ea3285587ed318aaf18d9db
diff --git a/solr/licenses/grpc-protobuf-lite-1.59.0.jar.sha1 b/solr/licenses/grpc-protobuf-lite-1.59.0.jar.sha1
new file mode 100644
index 00000000000..cddeca78cff
--- /dev/null
+++ b/solr/licenses/grpc-protobuf-lite-1.59.0.jar.sha1
@@ -0,0 +1 @@
+1d2d1a5ed9cfc58d0a7bdc1d9dda5ecb9987da9a
diff --git a/solr/licenses/grpc-rls-1.58.0.jar.sha1 b/solr/licenses/grpc-rls-1.58.0.jar.sha1
deleted file mode 100644
index dd79cc96487..00000000000
--- a/solr/licenses/grpc-rls-1.58.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-705efa0a05acc2df20e369817f091bba59235d9f
diff --git a/solr/licenses/grpc-rls-1.59.0.jar.sha1 b/solr/licenses/grpc-rls-1.59.0.jar.sha1
new file mode 100644
index 00000000000..0ca9a982165
--- /dev/null
+++ b/solr/licenses/grpc-rls-1.59.0.jar.sha1
@@ -0,0 +1 @@
+d339db49e637d2a8122a67ad846a294124f1a2f3
diff --git a/solr/licenses/grpc-services-1.58.0.jar.sha1 b/solr/licenses/grpc-services-1.58.0.jar.sha1
deleted file mode 100644
index 593048c5127..00000000000
--- a/solr/licenses/grpc-services-1.58.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-2dbe016ee80160b4dbb283ef8fc46a00294d952a
diff --git a/solr/licenses/netty-transport-native-epoll-4.1.99.Final-linux-x86_64.jar.sha1 b/solr/licenses/grpc-services-1.59.0.jar.sha1
similarity index 100%
rename from solr/licenses/netty-transport-native-epoll-4.1.99.Final-linux-x86_64.jar.sha1
rename to solr/licenses/grpc-services-1.59.0.jar.sha1
index 793b61695d9..0db4a3c3d49 100644
--- a/solr/licenses/netty-transport-native-epoll-4.1.99.Final-linux-x86_64.jar.sha1
+++ b/solr/licenses/grpc-services-1.59.0.jar.sha1
@@ -1 +1 @@
-49105fe39f6065dd3634d28fa755a708b237ce58
+02f16015ed9e2689e10f86f1b7c3522e541c0c75
diff --git a/solr/licenses/grpc-stub-1.58.0.jar.sha1 b/solr/licenses/grpc-stub-1.58.0.jar.sha1
deleted file mode 100644
index b40e8a44d5a..00000000000
--- a/solr/licenses/grpc-stub-1.58.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-6bba82c4e3298ffbc2faa182821c98f6e3903d77
diff --git a/solr/licenses/grpc-stub-1.59.0.jar.sha1 b/solr/licenses/grpc-stub-1.59.0.jar.sha1
new file mode 100644
index 00000000000..4eb63eb40eb
--- /dev/null
+++ b/solr/licenses/grpc-stub-1.59.0.jar.sha1
@@ -0,0 +1 @@
+0e7eab15d6b4184921b82fbca6f89dcb60ea972e
diff --git a/solr/licenses/grpc-util-1.58.0.jar.sha1 b/solr/licenses/grpc-util-1.58.0.jar.sha1
deleted file mode 100644
index 4b3ffa0ade4..00000000000
--- a/solr/licenses/grpc-util-1.58.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-1e95f31fe99adb642ec9d800ed950b438dfd0e50
diff --git a/solr/licenses/grpc-util-1.59.0.jar.sha1 b/solr/licenses/grpc-util-1.59.0.jar.sha1
new file mode 100644
index 00000000000..80eb8500d2e
--- /dev/null
+++ b/solr/licenses/grpc-util-1.59.0.jar.sha1
@@ -0,0 +1 @@
+362e2295d95b2e2797457760eef1f172d07d7417
diff --git a/solr/licenses/grpc-xds-1.58.0.jar.sha1 b/solr/licenses/grpc-xds-1.58.0.jar.sha1
deleted file mode 100644
index 3effe9ca8af..00000000000
--- a/solr/licenses/grpc-xds-1.58.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-2d60586187fb19850ee49e28b1664f7a539a6f66
diff --git a/solr/licenses/grpc-xds-1.59.0.jar.sha1 b/solr/licenses/grpc-xds-1.59.0.jar.sha1
new file mode 100644
index 00000000000..bbad81d5dd2
--- /dev/null
+++ b/solr/licenses/grpc-xds-1.59.0.jar.sha1
@@ -0,0 +1 @@
+c067143934cb76530adbb8fd4e2df1ab737a16e0
diff --git a/solr/licenses/guava-32.1.2-jre.jar.sha1 b/solr/licenses/guava-32.1.2-jre.jar.sha1
deleted file mode 100644
index 787d67061c2..00000000000
--- a/solr/licenses/guava-32.1.2-jre.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-5e64ec7e056456bef3a4bc4c6fdaef71e8ab6318
diff --git a/solr/licenses/guava-32.1.3-jre.jar.sha1 b/solr/licenses/guava-32.1.3-jre.jar.sha1
new file mode 100644
index 00000000000..69d6c745124
--- /dev/null
+++ b/solr/licenses/guava-32.1.3-jre.jar.sha1
@@ -0,0 +1 @@
+0f306708742ce2bf0fb0901216183bc14073feae
diff --git a/solr/licenses/jackson-annotations-2.15.2.jar.sha1 b/solr/licenses/jackson-annotations-2.15.2.jar.sha1
deleted file mode 100644
index 9f2de051b36..00000000000
--- a/solr/licenses/jackson-annotations-2.15.2.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-4724a65ac8e8d156a24898d50fd5dbd3642870b8
diff --git a/solr/licenses/jackson-annotations-2.15.3.jar.sha1 b/solr/licenses/jackson-annotations-2.15.3.jar.sha1
new file mode 100644
index 00000000000..e9e7e4e23f7
--- /dev/null
+++ b/solr/licenses/jackson-annotations-2.15.3.jar.sha1
@@ -0,0 +1 @@
+79baf4e605eb3bbb60b1c475d44a7aecceea1d60
diff --git a/solr/licenses/jackson-core-2.15.2.jar.sha1 b/solr/licenses/jackson-core-2.15.2.jar.sha1
deleted file mode 100644
index e94a74ef317..00000000000
--- a/solr/licenses/jackson-core-2.15.2.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-a6fe1836469a69b3ff66037c324d75fc66ef137c
diff --git a/solr/licenses/jackson-core-2.15.3.jar.sha1 b/solr/licenses/jackson-core-2.15.3.jar.sha1
new file mode 100644
index 00000000000..a0c13d95f67
--- /dev/null
+++ b/solr/licenses/jackson-core-2.15.3.jar.sha1
@@ -0,0 +1 @@
+60d600567c1862840397bf9ff5a92398edc5797b
diff --git a/solr/licenses/jackson-databind-2.15.2.jar.sha1 b/solr/licenses/jackson-databind-2.15.2.jar.sha1
deleted file mode 100644
index 292a15ec3aa..00000000000
--- a/solr/licenses/jackson-databind-2.15.2.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-9353b021f10c307c00328f52090de2bdb4b6ff9c
diff --git a/solr/licenses/jackson-databind-2.15.3.jar.sha1 b/solr/licenses/jackson-databind-2.15.3.jar.sha1
new file mode 100644
index 00000000000..5d31fd2ab96
--- /dev/null
+++ b/solr/licenses/jackson-databind-2.15.3.jar.sha1
@@ -0,0 +1 @@
+a734bc2c47a9453c4efa772461a3aeb273c010d9
diff --git a/solr/licenses/jackson-dataformat-cbor-2.15.2.jar.sha1 b/solr/licenses/jackson-dataformat-cbor-2.15.2.jar.sha1
deleted file mode 100644
index 99dad0d6f2d..00000000000
--- a/solr/licenses/jackson-dataformat-cbor-2.15.2.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-baafc85c70765594add14bd93f3efd68e1945b76
diff --git a/solr/licenses/jackson-dataformat-cbor-2.15.3.jar.sha1 b/solr/licenses/jackson-dataformat-cbor-2.15.3.jar.sha1
new file mode 100644
index 00000000000..6b5eefe89da
--- /dev/null
+++ b/solr/licenses/jackson-dataformat-cbor-2.15.3.jar.sha1
@@ -0,0 +1 @@
+c30a4e69e760401a98b9fa458a4f2db6fe392d7f
diff --git a/solr/licenses/jackson-dataformat-smile-2.15.2.jar.sha1 b/solr/licenses/jackson-dataformat-smile-2.15.2.jar.sha1
deleted file mode 100644
index cf03f49842e..00000000000
--- a/solr/licenses/jackson-dataformat-smile-2.15.2.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-16d1dd22f7d641459ed056399d4f7df0220f1176
diff --git a/solr/licenses/jackson-dataformat-smile-2.15.3.jar.sha1 b/solr/licenses/jackson-dataformat-smile-2.15.3.jar.sha1
new file mode 100644
index 00000000000..05f7218fa03
--- /dev/null
+++ b/solr/licenses/jackson-dataformat-smile-2.15.3.jar.sha1
@@ -0,0 +1 @@
+0b7688240ac7943b981cdf6592ee38101332bf5c
diff --git a/solr/licenses/jackson-dataformat-xml-2.15.2.jar.sha1 b/solr/licenses/jackson-dataformat-xml-2.15.2.jar.sha1
deleted file mode 100644
index 1a3fd34d037..00000000000
--- a/solr/licenses/jackson-dataformat-xml-2.15.2.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-e7e9038dee5c1adb1ebd07d3669e0e1182ac5b60
diff --git a/solr/licenses/jackson-dataformat-xml-2.15.3.jar.sha1 b/solr/licenses/jackson-dataformat-xml-2.15.3.jar.sha1
new file mode 100644
index 00000000000..a2b54986fbc
--- /dev/null
+++ b/solr/licenses/jackson-dataformat-xml-2.15.3.jar.sha1
@@ -0,0 +1 @@
+50f061b3ff15979ee0c784c657f5ea8ba7b920c5
diff --git a/solr/licenses/jackson-datatype-jdk8-2.15.2.jar.sha1 b/solr/licenses/jackson-datatype-jdk8-2.15.2.jar.sha1
deleted file mode 100644
index 5203e6d75df..00000000000
--- a/solr/licenses/jackson-datatype-jdk8-2.15.2.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-66a50e089cfd2f93896b9b6f7a734cea7bcf2f31
diff --git a/solr/licenses/jackson-datatype-jdk8-2.15.3.jar.sha1 b/solr/licenses/jackson-datatype-jdk8-2.15.3.jar.sha1
new file mode 100644
index 00000000000..42ec1c24029
--- /dev/null
+++ b/solr/licenses/jackson-datatype-jdk8-2.15.3.jar.sha1
@@ -0,0 +1 @@
+80158cb020c7bd4e4ba94d8d752a65729dc943b2
diff --git a/solr/licenses/jackson-datatype-jsr310-2.15.2.jar.sha1 b/solr/licenses/jackson-datatype-jsr310-2.15.2.jar.sha1
deleted file mode 100644
index 236746c6766..00000000000
--- a/solr/licenses/jackson-datatype-jsr310-2.15.2.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-30d16ec2aef6d8094c5e2dce1d95034ca8b6cb42
diff --git a/solr/licenses/jackson-datatype-jsr310-2.15.3.jar.sha1 b/solr/licenses/jackson-datatype-jsr310-2.15.3.jar.sha1
new file mode 100644
index 00000000000..4e2f50bfe68
--- /dev/null
+++ b/solr/licenses/jackson-datatype-jsr310-2.15.3.jar.sha1
@@ -0,0 +1 @@
+4a20a0e104931bfa72f24ef358c2eb63f1ef2aaf
diff --git a/solr/licenses/jackson-module-jaxb-annotations-2.15.2.jar.sha1 b/solr/licenses/jackson-module-jaxb-annotations-2.15.2.jar.sha1
deleted file mode 100644
index 62271773656..00000000000
--- a/solr/licenses/jackson-module-jaxb-annotations-2.15.2.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-6a22fd1c7b0f9788e81eea32c11dc8c1ba421f18
diff --git a/solr/licenses/jackson-module-jaxb-annotations-2.15.3.jar.sha1 b/solr/licenses/jackson-module-jaxb-annotations-2.15.3.jar.sha1
new file mode 100644
index 00000000000..d5c42a13c1c
--- /dev/null
+++ b/solr/licenses/jackson-module-jaxb-annotations-2.15.3.jar.sha1
@@ -0,0 +1 @@
+74e8ef60b65b42051258465f06c06195e61e92f2
diff --git a/solr/licenses/jackson-module-kotlin-2.15.2.jar.sha1 b/solr/licenses/jackson-module-kotlin-2.15.2.jar.sha1
deleted file mode 100644
index 0a109b33692..00000000000
--- a/solr/licenses/jackson-module-kotlin-2.15.2.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0475c9721f5a2a5b7bea57d504bd8b0586d1ba5e
diff --git a/solr/licenses/jackson-module-kotlin-2.15.3.jar.sha1 b/solr/licenses/jackson-module-kotlin-2.15.3.jar.sha1
new file mode 100644
index 00000000000..6398f822e34
--- /dev/null
+++ b/solr/licenses/jackson-module-kotlin-2.15.3.jar.sha1
@@ -0,0 +1 @@
+036ea7813ada694e67f562ff1dc6f3b47883e373
diff --git a/solr/licenses/jackson-module-parameter-names-2.15.2.jar.sha1 b/solr/licenses/jackson-module-parameter-names-2.15.2.jar.sha1
deleted file mode 100644
index d571d29d5e9..00000000000
--- a/solr/licenses/jackson-module-parameter-names-2.15.2.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-75f8d2788db20f6c587c7a19e94fb6248c314241
diff --git a/solr/licenses/jackson-module-parameter-names-2.15.3.jar.sha1 b/solr/licenses/jackson-module-parameter-names-2.15.3.jar.sha1
new file mode 100644
index 00000000000..04d6421d340
--- /dev/null
+++ b/solr/licenses/jackson-module-parameter-names-2.15.3.jar.sha1
@@ -0,0 +1 @@
+8d251b90c5358677e7d8161e0c2488e6f84f49da
diff --git a/solr/licenses/log4j-1.2-api-2.20.0.jar.sha1 b/solr/licenses/log4j-1.2-api-2.20.0.jar.sha1
deleted file mode 100644
index ac95ee746ec..00000000000
--- a/solr/licenses/log4j-1.2-api-2.20.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-689151374756cb809cb029f2501015bdc7733179
diff --git a/solr/licenses/log4j-1.2-api-2.21.0.jar.sha1 b/solr/licenses/log4j-1.2-api-2.21.0.jar.sha1
new file mode 100644
index 00000000000..41761161aba
--- /dev/null
+++ b/solr/licenses/log4j-1.2-api-2.21.0.jar.sha1
@@ -0,0 +1 @@
+12bad3819a9570807f3c97315930699584c12152
diff --git a/solr/licenses/log4j-api-2.20.0.jar.sha1 b/solr/licenses/log4j-api-2.20.0.jar.sha1
deleted file mode 100644
index 390ef64b01e..00000000000
--- a/solr/licenses/log4j-api-2.20.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-1fe6082e660daf07c689a89c94dc0f49c26b44bb
diff --git a/solr/licenses/log4j-api-2.21.0.jar.sha1 b/solr/licenses/log4j-api-2.21.0.jar.sha1
new file mode 100644
index 00000000000..6a05a4e5cb0
--- /dev/null
+++ b/solr/licenses/log4j-api-2.21.0.jar.sha1
@@ -0,0 +1 @@
+760192f2b69eacf4a4afc78e5a1d7a8de054fcbd
diff --git a/solr/licenses/log4j-core-2.20.0.jar.sha1 b/solr/licenses/log4j-core-2.20.0.jar.sha1
deleted file mode 100644
index 6272a4a0858..00000000000
--- a/solr/licenses/log4j-core-2.20.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-eb2a9a47b1396e00b5eee1264296729a70565cc0
diff --git a/solr/licenses/log4j-core-2.21.0.jar.sha1 b/solr/licenses/log4j-core-2.21.0.jar.sha1
new file mode 100644
index 00000000000..0a2615fc478
--- /dev/null
+++ b/solr/licenses/log4j-core-2.21.0.jar.sha1
@@ -0,0 +1 @@
+122e1a9e0603cc9eae07b0846a6ff01f2454bc49
diff --git a/solr/licenses/log4j-jul-2.20.0.jar.sha1 b/solr/licenses/log4j-jul-2.20.0.jar.sha1
deleted file mode 100644
index 980c951a714..00000000000
--- a/solr/licenses/log4j-jul-2.20.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-8170e6118eac1ab332046c179718a0f107f688e1
diff --git a/solr/licenses/log4j-jul-2.21.0.jar.sha1 b/solr/licenses/log4j-jul-2.21.0.jar.sha1
new file mode 100644
index 00000000000..89f7c940953
--- /dev/null
+++ b/solr/licenses/log4j-jul-2.21.0.jar.sha1
@@ -0,0 +1 @@
+f0da61113f4a47654677e6a98b1e13ca7de2483d
diff --git a/solr/licenses/log4j-layout-template-json-2.20.0.jar.sha1 b/solr/licenses/log4j-layout-template-json-2.20.0.jar.sha1
deleted file mode 100644
index ba0ad6db32b..00000000000
--- a/solr/licenses/log4j-layout-template-json-2.20.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-16f2e5669f4e4173fc446007e8b85aa2313df33b
diff --git a/solr/licenses/log4j-layout-template-json-2.21.0.jar.sha1 b/solr/licenses/log4j-layout-template-json-2.21.0.jar.sha1
new file mode 100644
index 00000000000..f7ee63037a5
--- /dev/null
+++ b/solr/licenses/log4j-layout-template-json-2.21.0.jar.sha1
@@ -0,0 +1 @@
+c90f410a98ddbbfe90b4ebe7f1e23526d72c0c96
diff --git a/solr/licenses/log4j-slf4j2-impl-2.20.0.jar.sha1 b/solr/licenses/log4j-slf4j2-impl-2.20.0.jar.sha1
deleted file mode 100644
index 5c2144b9c61..00000000000
--- a/solr/licenses/log4j-slf4j2-impl-2.20.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-155c8b9bbdac91d8461d9a403a646e6bd0d365d8
diff --git a/solr/licenses/log4j-slf4j2-impl-2.21.0.jar.sha1 b/solr/licenses/log4j-slf4j2-impl-2.21.0.jar.sha1
new file mode 100644
index 00000000000..f5d1f87d8f1
--- /dev/null
+++ b/solr/licenses/log4j-slf4j2-impl-2.21.0.jar.sha1
@@ -0,0 +1 @@
+070c38c479f4c495cab11da8396348eebffefcb2
diff --git a/solr/licenses/log4j-web-2.20.0.jar.sha1 b/solr/licenses/log4j-web-2.20.0.jar.sha1
deleted file mode 100644
index 586ef6986b9..00000000000
--- a/solr/licenses/log4j-web-2.20.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-3877f128ebc8655c4a48944ebf3e2c94de1bfbed
diff --git a/solr/licenses/log4j-web-2.21.0.jar.sha1 b/solr/licenses/log4j-web-2.21.0.jar.sha1
new file mode 100644
index 00000000000..f2ae414b1ed
--- /dev/null
+++ b/solr/licenses/log4j-web-2.21.0.jar.sha1
@@ -0,0 +1 @@
+5b6f3db6a2b00b033ec2c9ca8eabb08a00728df2
diff --git a/solr/licenses/metrics-annotation-4.2.20.jar.sha1 b/solr/licenses/metrics-annotation-4.2.20.jar.sha1
deleted file mode 100644
index f7fee757d07..00000000000
--- a/solr/licenses/metrics-annotation-4.2.20.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-356a49a3146af00df245c24d18860503a84a3b18
diff --git a/solr/licenses/metrics-annotation-4.2.21.jar.sha1 b/solr/licenses/metrics-annotation-4.2.21.jar.sha1
new file mode 100644
index 00000000000..52885f076ee
--- /dev/null
+++ b/solr/licenses/metrics-annotation-4.2.21.jar.sha1
@@ -0,0 +1 @@
+b2b639173cf1718e4ce839eb46e178e6348dc1d3
diff --git a/solr/licenses/metrics-core-4.2.20.jar.sha1 b/solr/licenses/metrics-core-4.2.20.jar.sha1
deleted file mode 100644
index 436e7cf8294..00000000000
--- a/solr/licenses/metrics-core-4.2.20.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-b3eb1b408021950fab1e22b2a851a109470064a9
diff --git a/solr/licenses/metrics-core-4.2.21.jar.sha1 b/solr/licenses/metrics-core-4.2.21.jar.sha1
new file mode 100644
index 00000000000..c79effe1a17
--- /dev/null
+++ b/solr/licenses/metrics-core-4.2.21.jar.sha1
@@ -0,0 +1 @@
+3361294b12e1bc6cab075c86cb1e2e02082dc86d
diff --git a/solr/licenses/metrics-graphite-4.2.20.jar.sha1 b/solr/licenses/metrics-graphite-4.2.20.jar.sha1
deleted file mode 100644
index 69f94d82ce3..00000000000
--- a/solr/licenses/metrics-graphite-4.2.20.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-e650d3670e1537b5ed99b8a83f7e13c95517c530
diff --git a/solr/licenses/metrics-graphite-4.2.21.jar.sha1 b/solr/licenses/metrics-graphite-4.2.21.jar.sha1
new file mode 100644
index 00000000000..e16682a91bf
--- /dev/null
+++ b/solr/licenses/metrics-graphite-4.2.21.jar.sha1
@@ -0,0 +1 @@
+b40e41964d6725fc2b20f890958a572b1b725769
diff --git a/solr/licenses/metrics-jetty10-4.2.20.jar.sha1 b/solr/licenses/metrics-jetty10-4.2.20.jar.sha1
deleted file mode 100644
index eaed525eb99..00000000000
--- a/solr/licenses/metrics-jetty10-4.2.20.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-d01cfde5cbf2231e13001f2b0c98f869246aa727
diff --git a/solr/licenses/metrics-jetty10-4.2.21.jar.sha1 b/solr/licenses/metrics-jetty10-4.2.21.jar.sha1
new file mode 100644
index 00000000000..eaac5b7dd3f
--- /dev/null
+++ b/solr/licenses/metrics-jetty10-4.2.21.jar.sha1
@@ -0,0 +1 @@
+5ae2c5adb46bd26554bd35a97bfcb5cb4effbcb8
diff --git a/solr/licenses/metrics-jmx-4.2.20.jar.sha1 b/solr/licenses/metrics-jmx-4.2.20.jar.sha1
deleted file mode 100644
index be81afcc3ca..00000000000
--- a/solr/licenses/metrics-jmx-4.2.20.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-6723adff28670f900e37fea60d9a6abc7537e78f
diff --git a/solr/licenses/metrics-jmx-4.2.21.jar.sha1 b/solr/licenses/metrics-jmx-4.2.21.jar.sha1
new file mode 100644
index 00000000000..e75023633ac
--- /dev/null
+++ b/solr/licenses/metrics-jmx-4.2.21.jar.sha1
@@ -0,0 +1 @@
+0651c1c0027b960d5c644aacd064eb84d9a08a12
diff --git a/solr/licenses/metrics-jvm-4.2.20.jar.sha1 b/solr/licenses/metrics-jvm-4.2.20.jar.sha1
deleted file mode 100644
index 32a1659499c..00000000000
--- a/solr/licenses/metrics-jvm-4.2.20.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-b6f1bdd9046a2e2c33f66a5865cf5c9187ddfc9e
diff --git a/solr/licenses/metrics-jvm-4.2.21.jar.sha1 b/solr/licenses/metrics-jvm-4.2.21.jar.sha1
new file mode 100644
index 00000000000..3a58ee8014e
--- /dev/null
+++ b/solr/licenses/metrics-jvm-4.2.21.jar.sha1
@@ -0,0 +1 @@
+99c1d2a846515bdee155358861d752ae7de465cf
diff --git a/solr/licenses/netty-buffer-4.1.100.Final.jar.sha1 b/solr/licenses/netty-buffer-4.1.100.Final.jar.sha1
new file mode 100644
index 00000000000..aaa2e6b18a8
--- /dev/null
+++ b/solr/licenses/netty-buffer-4.1.100.Final.jar.sha1
@@ -0,0 +1 @@
+39b05d2d4027971bf99111a9be1d7035a116bb55
diff --git a/solr/licenses/netty-buffer-4.1.99.Final.jar.sha1 b/solr/licenses/netty-buffer-4.1.99.Final.jar.sha1
deleted file mode 100644
index f14bb02dd1f..00000000000
--- a/solr/licenses/netty-buffer-4.1.99.Final.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-9f02dcb9b15a647a56af210dffdc294a57922fb0
diff --git a/solr/licenses/netty-codec-4.1.100.Final.jar.sha1 b/solr/licenses/netty-codec-4.1.100.Final.jar.sha1
new file mode 100644
index 00000000000..d093fc9eae4
--- /dev/null
+++ b/solr/licenses/netty-codec-4.1.100.Final.jar.sha1
@@ -0,0 +1 @@
+9c3c71e7cf3b8ce3bfc9fa52a524b9ca7ddf259c
diff --git a/solr/licenses/netty-codec-4.1.99.Final.jar.sha1 b/solr/licenses/netty-codec-4.1.99.Final.jar.sha1
deleted file mode 100644
index b170f6974ac..00000000000
--- a/solr/licenses/netty-codec-4.1.99.Final.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-9984cbd6e5d55c768f198e975d8aaf7fd42a4602
diff --git a/solr/licenses/netty-codec-http-4.1.100.Final.jar.sha1 b/solr/licenses/netty-codec-http-4.1.100.Final.jar.sha1
new file mode 100644
index 00000000000..f21057a5672
--- /dev/null
+++ b/solr/licenses/netty-codec-http-4.1.100.Final.jar.sha1
@@ -0,0 +1 @@
+992623e7d8f2d96e41faf1687bb963f5433e3517
diff --git a/solr/licenses/netty-codec-http-4.1.99.Final.jar.sha1 b/solr/licenses/netty-codec-http-4.1.99.Final.jar.sha1
deleted file mode 100644
index 752680c6c41..00000000000
--- a/solr/licenses/netty-codec-http-4.1.99.Final.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-7142095066eaebd5f29b88c41af7b383b6a953f6
diff --git a/solr/licenses/netty-codec-http2-4.1.100.Final.jar.sha1 b/solr/licenses/netty-codec-http2-4.1.100.Final.jar.sha1
new file mode 100644
index 00000000000..ae46145b95a
--- /dev/null
+++ b/solr/licenses/netty-codec-http2-4.1.100.Final.jar.sha1
@@ -0,0 +1 @@
+cbf1a430ea44dbdedbcde16b185cbb95f28d72c7
diff --git a/solr/licenses/netty-codec-http2-4.1.99.Final.jar.sha1 b/solr/licenses/netty-codec-http2-4.1.99.Final.jar.sha1
deleted file mode 100644
index a21d6a7d697..00000000000
--- a/solr/licenses/netty-codec-http2-4.1.99.Final.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-c5a3481c4bb9732a3a94fb63cf916141a1a14669
diff --git a/solr/licenses/netty-codec-socks-4.1.100.Final.jar.sha1 b/solr/licenses/netty-codec-socks-4.1.100.Final.jar.sha1
new file mode 100644
index 00000000000..e6a722d13c2
--- /dev/null
+++ b/solr/licenses/netty-codec-socks-4.1.100.Final.jar.sha1
@@ -0,0 +1 @@
+a9fbf4d64b08abed542eefd5f7aed4807edca56f
diff --git a/solr/licenses/netty-codec-socks-4.1.99.Final.jar.sha1 b/solr/licenses/netty-codec-socks-4.1.99.Final.jar.sha1
deleted file mode 100644
index dfbc3112d39..00000000000
--- a/solr/licenses/netty-codec-socks-4.1.99.Final.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-259bf1c5178c3e23bb89a2fab59b6d22846e3fa6
diff --git a/solr/licenses/netty-common-4.1.100.Final.jar.sha1 b/solr/licenses/netty-common-4.1.100.Final.jar.sha1
new file mode 100644
index 00000000000..9bbeb4b8200
--- /dev/null
+++ b/solr/licenses/netty-common-4.1.100.Final.jar.sha1
@@ -0,0 +1 @@
+847f942381145de23f21c836d05b0677474271d3
diff --git a/solr/licenses/netty-common-4.1.99.Final.jar.sha1 b/solr/licenses/netty-common-4.1.99.Final.jar.sha1
deleted file mode 100644
index 25f26d8d00c..00000000000
--- a/solr/licenses/netty-common-4.1.99.Final.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-278f6dfa49d6bd75c40ae1470eb165716f87dce0
diff --git a/solr/licenses/netty-handler-4.1.100.Final.jar.sha1 b/solr/licenses/netty-handler-4.1.100.Final.jar.sha1
new file mode 100644
index 00000000000..aed18d365b5
--- /dev/null
+++ b/solr/licenses/netty-handler-4.1.100.Final.jar.sha1
@@ -0,0 +1 @@
+4c0acdb8bb73647ebb3847ac2d503d53d72c02b4
diff --git a/solr/licenses/netty-handler-4.1.99.Final.jar.sha1 b/solr/licenses/netty-handler-4.1.99.Final.jar.sha1
deleted file mode 100644
index 1c796882bcc..00000000000
--- a/solr/licenses/netty-handler-4.1.99.Final.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-742693761d7ea4c038bccfda96bb38194720b80d
diff --git a/solr/licenses/netty-handler-proxy-4.1.100.Final.jar.sha1 b/solr/licenses/netty-handler-proxy-4.1.100.Final.jar.sha1
new file mode 100644
index 00000000000..399d711d28b
--- /dev/null
+++ b/solr/licenses/netty-handler-proxy-4.1.100.Final.jar.sha1
@@ -0,0 +1 @@
+af3cf676eed30184215426ecf0f0dde15555ea9c
diff --git a/solr/licenses/netty-handler-proxy-4.1.99.Final.jar.sha1 b/solr/licenses/netty-handler-proxy-4.1.99.Final.jar.sha1
deleted file mode 100644
index 0abb815a06a..00000000000
--- a/solr/licenses/netty-handler-proxy-4.1.99.Final.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-8c8a89ea89b06e120c57bdb3db14b9a47ca30bb3
diff --git a/solr/licenses/netty-resolver-4.1.100.Final.jar.sha1 b/solr/licenses/netty-resolver-4.1.100.Final.jar.sha1
new file mode 100644
index 00000000000..121e17de50c
--- /dev/null
+++ b/solr/licenses/netty-resolver-4.1.100.Final.jar.sha1
@@ -0,0 +1 @@
+fe62f9ccd41b8660d07639dbbab8ae1edd6f2720
diff --git a/solr/licenses/netty-resolver-4.1.99.Final.jar.sha1 b/solr/licenses/netty-resolver-4.1.99.Final.jar.sha1
deleted file mode 100644
index 28c9a8f0ca9..00000000000
--- a/solr/licenses/netty-resolver-4.1.99.Final.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-080e45397d9d5b134477de3ffd0f94283b908621
diff --git a/solr/licenses/netty-transport-4.1.100.Final.jar.sha1 b/solr/licenses/netty-transport-4.1.100.Final.jar.sha1
new file mode 100644
index 00000000000..cc4f4c89dec
--- /dev/null
+++ b/solr/licenses/netty-transport-4.1.100.Final.jar.sha1
@@ -0,0 +1 @@
+6620fbfb47667a5eb6050e35c7b4c88000bcd77f
diff --git a/solr/licenses/netty-transport-4.1.99.Final.jar.sha1 b/solr/licenses/netty-transport-4.1.99.Final.jar.sha1
deleted file mode 100644
index 39497e8367d..00000000000
--- a/solr/licenses/netty-transport-4.1.99.Final.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-9ca2e3ae19a6713b749df154622115f480b6716c
diff --git a/solr/licenses/netty-transport-classes-epoll-4.1.100.Final.jar.sha1 b/solr/licenses/netty-transport-classes-epoll-4.1.100.Final.jar.sha1
new file mode 100644
index 00000000000..f26e13ab47d
--- /dev/null
+++ b/solr/licenses/netty-transport-classes-epoll-4.1.100.Final.jar.sha1
@@ -0,0 +1 @@
+78489936ca1d91483e34a31d04a3b0812386eb39
diff --git a/solr/licenses/netty-transport-classes-epoll-4.1.99.Final.jar.sha1 b/solr/licenses/netty-transport-classes-epoll-4.1.99.Final.jar.sha1
deleted file mode 100644
index 3e46f9468f0..00000000000
--- a/solr/licenses/netty-transport-classes-epoll-4.1.99.Final.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-961bd5b8d97ea6a07168176462f398089a24b5c8
diff --git a/solr/licenses/netty-transport-native-epoll-4.1.100.Final-linux-x86_64.jar.sha1 b/solr/licenses/netty-transport-native-epoll-4.1.100.Final-linux-x86_64.jar.sha1
new file mode 100644
index 00000000000..9167d09e679
--- /dev/null
+++ b/solr/licenses/netty-transport-native-epoll-4.1.100.Final-linux-x86_64.jar.sha1
@@ -0,0 +1 @@
+d83003b8eac838e4bc3f7662a22f9f2d879c0fe4
diff --git a/solr/licenses/netty-transport-native-unix-common-4.1.100.Final.jar.sha1 b/solr/licenses/netty-transport-native-unix-common-4.1.100.Final.jar.sha1
new file mode 100644
index 00000000000..421d39abf8f
--- /dev/null
+++ b/solr/licenses/netty-transport-native-unix-common-4.1.100.Final.jar.sha1
@@ -0,0 +1 @@
+648ff5571022dbfa6789122e3872477bbf67fa7b
diff --git a/solr/licenses/netty-transport-native-unix-common-4.1.99.Final.jar.sha1 b/solr/licenses/netty-transport-native-unix-common-4.1.99.Final.jar.sha1
deleted file mode 100644
index 6429f60aea4..00000000000
--- a/solr/licenses/netty-transport-native-unix-common-4.1.99.Final.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-cb0fc6c31c387404212949c57950b5d72ce908b9
diff --git a/solr/licenses/opentelemetry-api-1.30.1.jar.sha1 b/solr/licenses/opentelemetry-api-1.30.1.jar.sha1
deleted file mode 100644
index b21be2984d1..00000000000
--- a/solr/licenses/opentelemetry-api-1.30.1.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-a32dfbd7f01de6711fd0e970f8d4b4c0405056d6
diff --git a/solr/licenses/opentelemetry-api-1.31.0.jar.sha1 b/solr/licenses/opentelemetry-api-1.31.0.jar.sha1
new file mode 100644
index 00000000000..826ced69764
--- /dev/null
+++ b/solr/licenses/opentelemetry-api-1.31.0.jar.sha1
@@ -0,0 +1 @@
+bb24a44d73484c681c236aed84fe6c28d17f30e2
diff --git a/solr/licenses/opentelemetry-api-events-1.30.1-alpha.jar.sha1 b/solr/licenses/opentelemetry-api-events-1.30.1-alpha.jar.sha1
deleted file mode 100644
index 1ec9a6f975e..00000000000
--- a/solr/licenses/opentelemetry-api-events-1.30.1-alpha.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-fb5fec3cdd62b98d61d1648f0027ea0b9767758b
diff --git a/solr/licenses/opentelemetry-api-events-1.31.0-alpha.jar.sha1 b/solr/licenses/opentelemetry-api-events-1.31.0-alpha.jar.sha1
new file mode 100644
index 00000000000..3d9689f4607
--- /dev/null
+++ b/solr/licenses/opentelemetry-api-events-1.31.0-alpha.jar.sha1
@@ -0,0 +1 @@
+537183c5cd8fa7ebf520c0887c4ffb8a450913fe
diff --git a/solr/licenses/opentelemetry-context-1.30.1.jar.sha1 b/solr/licenses/opentelemetry-context-1.30.1.jar.sha1
deleted file mode 100644
index 5009f902e27..00000000000
--- a/solr/licenses/opentelemetry-context-1.30.1.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-58f665ff01ce6b964cdf0b8cb5cd1c196dfe94ce
diff --git a/solr/licenses/opentelemetry-context-1.31.0.jar.sha1 b/solr/licenses/opentelemetry-context-1.31.0.jar.sha1
new file mode 100644
index 00000000000..f67b32c1f94
--- /dev/null
+++ b/solr/licenses/opentelemetry-context-1.31.0.jar.sha1
@@ -0,0 +1 @@
+b8004737f7a970124e36ac71fde8eb88423e8cee
diff --git a/solr/licenses/opentelemetry-exporter-common-1.30.1.jar.sha1 b/solr/licenses/opentelemetry-exporter-common-1.30.1.jar.sha1
deleted file mode 100644
index 4e601b99c00..00000000000
--- a/solr/licenses/opentelemetry-exporter-common-1.30.1.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-f299d336dba1039478497f37b273dfa764c6faef
diff --git a/solr/licenses/opentelemetry-exporter-common-1.31.0.jar.sha1 b/solr/licenses/opentelemetry-exporter-common-1.31.0.jar.sha1
new file mode 100644
index 00000000000..8510a13d3bd
--- /dev/null
+++ b/solr/licenses/opentelemetry-exporter-common-1.31.0.jar.sha1
@@ -0,0 +1 @@
+b7b4baf5f9af72d5eb8a231dfb114ae31c57150d
diff --git a/solr/licenses/opentelemetry-exporter-otlp-1.30.1.jar.sha1 b/solr/licenses/opentelemetry-exporter-otlp-1.30.1.jar.sha1
deleted file mode 100644
index 55848ca06a6..00000000000
--- a/solr/licenses/opentelemetry-exporter-otlp-1.30.1.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-15692246539571c41180aff2b55abe527b939a7b
diff --git a/solr/licenses/opentelemetry-exporter-otlp-1.31.0.jar.sha1 b/solr/licenses/opentelemetry-exporter-otlp-1.31.0.jar.sha1
new file mode 100644
index 00000000000..7f718e7a07a
--- /dev/null
+++ b/solr/licenses/opentelemetry-exporter-otlp-1.31.0.jar.sha1
@@ -0,0 +1 @@
+b6454464425dfd81519070caeca3824558a2f1ae
diff --git a/solr/licenses/opentelemetry-exporter-otlp-common-1.30.1.jar.sha1 b/solr/licenses/opentelemetry-exporter-otlp-common-1.30.1.jar.sha1
deleted file mode 100644
index 609f1e9ee85..00000000000
--- a/solr/licenses/opentelemetry-exporter-otlp-common-1.30.1.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-947cf43a6411c4a323e14594431040a476ad43e8
diff --git a/solr/licenses/opentelemetry-exporter-otlp-common-1.31.0.jar.sha1 b/solr/licenses/opentelemetry-exporter-otlp-common-1.31.0.jar.sha1
new file mode 100644
index 00000000000..e4079c3f874
--- /dev/null
+++ b/solr/licenses/opentelemetry-exporter-otlp-common-1.31.0.jar.sha1
@@ -0,0 +1 @@
+d8c22b6851bbc3dbf5d2387b9bde158ed5416ba4
diff --git a/solr/licenses/opentelemetry-exporter-sender-okhttp-1.30.1.jar.sha1 b/solr/licenses/opentelemetry-exporter-sender-okhttp-1.30.1.jar.sha1
deleted file mode 100644
index b7bad990390..00000000000
--- a/solr/licenses/opentelemetry-exporter-sender-okhttp-1.30.1.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-9f3a14515500e4df260ce7b10a668237a95ac791
diff --git a/solr/licenses/opentelemetry-exporter-sender-okhttp-1.31.0.jar.sha1 b/solr/licenses/opentelemetry-exporter-sender-okhttp-1.31.0.jar.sha1
new file mode 100644
index 00000000000..082be71904e
--- /dev/null
+++ b/solr/licenses/opentelemetry-exporter-sender-okhttp-1.31.0.jar.sha1
@@ -0,0 +1 @@
+dd209381d58cfe81a989e29c9ca26d97c8dabd7a
diff --git a/solr/licenses/opentelemetry-extension-incubator-1.30.1-alpha.jar.sha1 b/solr/licenses/opentelemetry-extension-incubator-1.30.1-alpha.jar.sha1
deleted file mode 100644
index d6483a14fe2..00000000000
--- a/solr/licenses/opentelemetry-extension-incubator-1.30.1-alpha.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-bfcea9bd71f97dd4e8a4f92c15ba5659fb07ff05
diff --git a/solr/licenses/opentelemetry-extension-incubator-1.31.0-alpha.jar.sha1 b/solr/licenses/opentelemetry-extension-incubator-1.31.0-alpha.jar.sha1
new file mode 100644
index 00000000000..2aa48c8e15f
--- /dev/null
+++ b/solr/licenses/opentelemetry-extension-incubator-1.31.0-alpha.jar.sha1
@@ -0,0 +1 @@
+6c9f5c063309d92b6dd28bff0667f54b63afd36f
diff --git a/solr/licenses/opentelemetry-sdk-1.30.1.jar.sha1 b/solr/licenses/opentelemetry-sdk-1.30.1.jar.sha1
deleted file mode 100644
index 918c08509ae..00000000000
--- a/solr/licenses/opentelemetry-sdk-1.30.1.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-4d15a9ea26e8e6ea93287a9f4ee02d91e5a74392
diff --git a/solr/licenses/opentelemetry-sdk-1.31.0.jar.sha1 b/solr/licenses/opentelemetry-sdk-1.31.0.jar.sha1
new file mode 100644
index 00000000000..92d071db230
--- /dev/null
+++ b/solr/licenses/opentelemetry-sdk-1.31.0.jar.sha1
@@ -0,0 +1 @@
+2b2093be08a09ac536292bf6cecf8129cc7fb191
diff --git a/solr/licenses/opentelemetry-sdk-common-1.30.1.jar.sha1 b/solr/licenses/opentelemetry-sdk-common-1.30.1.jar.sha1
deleted file mode 100644
index 5d133711ae5..00000000000
--- a/solr/licenses/opentelemetry-sdk-common-1.30.1.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-8e437ba87004bb63069d04fb06beae65b98dd13a
diff --git a/solr/licenses/opentelemetry-sdk-common-1.31.0.jar.sha1 b/solr/licenses/opentelemetry-sdk-common-1.31.0.jar.sha1
new file mode 100644
index 00000000000..27b691f58f9
--- /dev/null
+++ b/solr/licenses/opentelemetry-sdk-common-1.31.0.jar.sha1
@@ -0,0 +1 @@
+f492528288236e097e12fc1c45963dd82c70d33c
diff --git a/solr/licenses/opentelemetry-sdk-extension-autoconfigure-1.30.1.jar.sha1 b/solr/licenses/opentelemetry-sdk-extension-autoconfigure-1.30.1.jar.sha1
deleted file mode 100644
index 3a03d895bdb..00000000000
--- a/solr/licenses/opentelemetry-sdk-extension-autoconfigure-1.30.1.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-7f27a7b5d80efb75c39cead75dc7ba795e92d9ad
diff --git a/solr/licenses/opentelemetry-sdk-extension-autoconfigure-1.31.0.jar.sha1 b/solr/licenses/opentelemetry-sdk-extension-autoconfigure-1.31.0.jar.sha1
new file mode 100644
index 00000000000..bd0b75295b5
--- /dev/null
+++ b/solr/licenses/opentelemetry-sdk-extension-autoconfigure-1.31.0.jar.sha1
@@ -0,0 +1 @@
+178efb4a6102afa581307038f609324ed4418025
diff --git a/solr/licenses/opentelemetry-sdk-extension-autoconfigure-spi-1.30.1.jar.sha1 b/solr/licenses/opentelemetry-sdk-extension-autoconfigure-spi-1.30.1.jar.sha1
deleted file mode 100644
index 20078e803d9..00000000000
--- a/solr/licenses/opentelemetry-sdk-extension-autoconfigure-spi-1.30.1.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-05778b81d9d704217c749f4c9e2a580c23143f49
diff --git a/solr/licenses/opentelemetry-sdk-extension-autoconfigure-spi-1.31.0.jar.sha1 b/solr/licenses/opentelemetry-sdk-extension-autoconfigure-spi-1.31.0.jar.sha1
new file mode 100644
index 00000000000..5173561d82a
--- /dev/null
+++ b/solr/licenses/opentelemetry-sdk-extension-autoconfigure-spi-1.31.0.jar.sha1
@@ -0,0 +1 @@
+80acc40893fd00b56eee2acd145dbbd560173265
diff --git a/solr/licenses/opentelemetry-sdk-logs-1.30.1.jar.sha1 b/solr/licenses/opentelemetry-sdk-logs-1.30.1.jar.sha1
deleted file mode 100644
index 98a559361d3..00000000000
--- a/solr/licenses/opentelemetry-sdk-logs-1.30.1.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-5985d0950746ad12b49cc42c063f26ddfbcaaacb
diff --git a/solr/licenses/opentelemetry-sdk-logs-1.31.0.jar.sha1 b/solr/licenses/opentelemetry-sdk-logs-1.31.0.jar.sha1
new file mode 100644
index 00000000000..11dfa01bea9
--- /dev/null
+++ b/solr/licenses/opentelemetry-sdk-logs-1.31.0.jar.sha1
@@ -0,0 +1 @@
+a63a203d3dc6f8875f8c26b9e3b522dc9a3f6280
diff --git a/solr/licenses/opentelemetry-sdk-metrics-1.30.1.jar.sha1 b/solr/licenses/opentelemetry-sdk-metrics-1.30.1.jar.sha1
deleted file mode 100644
index 1d8b8f9ac96..00000000000
--- a/solr/licenses/opentelemetry-sdk-metrics-1.30.1.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-b12825541c5dae52a0fb35045c1b36df3ca8f632
diff --git a/solr/licenses/opentelemetry-sdk-metrics-1.31.0.jar.sha1 b/solr/licenses/opentelemetry-sdk-metrics-1.31.0.jar.sha1
new file mode 100644
index 00000000000..476dafe7fad
--- /dev/null
+++ b/solr/licenses/opentelemetry-sdk-metrics-1.31.0.jar.sha1
@@ -0,0 +1 @@
+47cc23762fae728d68e4fda1dfb71986ae0b8b3e
diff --git a/solr/licenses/opentelemetry-sdk-testing-1.30.1.jar.sha1 b/solr/licenses/opentelemetry-sdk-testing-1.30.1.jar.sha1
deleted file mode 100644
index ce2ac546fdd..00000000000
--- a/solr/licenses/opentelemetry-sdk-testing-1.30.1.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-99ca5001ea7afb4b3ef66436199c7726effef285
diff --git a/solr/licenses/opentelemetry-sdk-testing-1.31.0.jar.sha1 b/solr/licenses/opentelemetry-sdk-testing-1.31.0.jar.sha1
new file mode 100644
index 00000000000..54a8ae53723
--- /dev/null
+++ b/solr/licenses/opentelemetry-sdk-testing-1.31.0.jar.sha1
@@ -0,0 +1 @@
+bfa93429553b8933d969d1fc48c998c2db424242
diff --git a/solr/licenses/opentelemetry-sdk-trace-1.30.1.jar.sha1 b/solr/licenses/opentelemetry-sdk-trace-1.30.1.jar.sha1
deleted file mode 100644
index c3a51a19506..00000000000
--- a/solr/licenses/opentelemetry-sdk-trace-1.30.1.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-4c5531fbc44178a7bcfeb7021ae80e70a7c43458
diff --git a/solr/licenses/opentelemetry-sdk-trace-1.31.0.jar.sha1 b/solr/licenses/opentelemetry-sdk-trace-1.31.0.jar.sha1
new file mode 100644
index 00000000000..85f91cf59bf
--- /dev/null
+++ b/solr/licenses/opentelemetry-sdk-trace-1.31.0.jar.sha1
@@ -0,0 +1 @@
+a3941197cfb8ae9eb9e482073480c0c3918b746c
diff --git a/solr/licenses/semver4j-5.2.1.jar.sha1 b/solr/licenses/semver4j-5.2.1.jar.sha1
deleted file mode 100644
index dcd8c33033f..00000000000
--- a/solr/licenses/semver4j-5.2.1.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-e5942160167e4f9adfa49a59de1066442b980b5a
diff --git a/solr/licenses/semver4j-5.2.2.jar.sha1 b/solr/licenses/semver4j-5.2.2.jar.sha1
new file mode 100644
index 00000000000..29fdbd2eb71
--- /dev/null
+++ b/solr/licenses/semver4j-5.2.2.jar.sha1
@@ -0,0 +1 @@
+758cda82b388ce468c8d9880eaf6925155e5336c
diff --git a/solr/licenses/stax2-api-4.2.1.jar.sha1 b/solr/licenses/stax2-api-4.2.1.jar.sha1
deleted file mode 100644
index 4d3dd9c4294..00000000000
--- a/solr/licenses/stax2-api-4.2.1.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-a3f7325c52240418c2ba257b103c3c550e140c83
diff --git a/solr/licenses/stax2-api-4.2.2.jar.sha1 b/solr/licenses/stax2-api-4.2.2.jar.sha1
new file mode 100644
index 00000000000..e175b05f435
--- /dev/null
+++ b/solr/licenses/stax2-api-4.2.2.jar.sha1
@@ -0,0 +1 @@
+b0d746cadea928e5264f2ea294ea9a1bf815bbde
diff --git a/solr/licenses/swagger-annotations-2.2.16.jar.sha1 b/solr/licenses/swagger-annotations-2.2.16.jar.sha1
deleted file mode 100644
index e5990cfe995..00000000000
--- a/solr/licenses/swagger-annotations-2.2.16.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-baff53b8f5e2c6ee186a3913b3c1a06d92c79bb9
diff --git a/solr/licenses/swagger-annotations-2.2.17.jar.sha1 b/solr/licenses/swagger-annotations-2.2.17.jar.sha1
new file mode 100644
index 00000000000..4111ef52c0f
--- /dev/null
+++ b/solr/licenses/swagger-annotations-2.2.17.jar.sha1
@@ -0,0 +1 @@
+ee67ccee6a9d84831f0fdd635021e7e00439fecd
diff --git a/solr/licenses/value-annotations-2.10.0.jar.sha1 b/solr/licenses/value-annotations-2.10.0.jar.sha1
new file mode 100644
index 00000000000..ca0447202e2
--- /dev/null
+++ b/solr/licenses/value-annotations-2.10.0.jar.sha1
@@ -0,0 +1 @@
+7ef014a3ea9ce7dddb16c79dca00345387703b6b
diff --git a/solr/licenses/value-annotations-2.9.3.jar.sha1 b/solr/licenses/value-annotations-2.9.3.jar.sha1
deleted file mode 100644
index 1ae351c18ce..00000000000
--- a/solr/licenses/value-annotations-2.9.3.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0ceb905d89e453b578a2463274e2ec559977b6cd
diff --git a/solr/modules/analysis-extras/src/java/org/apache/solr/update/processor/OpenNLPExtractNamedEntitiesUpdateProcessorFactory.java b/solr/modules/analysis-extras/src/java/org/apache/solr/update/processor/OpenNLPExtractNamedEntitiesUpdateProcessorFactory.java
index 998d4fba78c..9df258cd303 100644
--- a/solr/modules/analysis-extras/src/java/org/apache/solr/update/processor/OpenNLPExtractNamedEntitiesUpdateProcessorFactory.java
+++ b/solr/modules/analysis-extras/src/java/org/apache/solr/update/processor/OpenNLPExtractNamedEntitiesUpdateProcessorFactory.java
@@ -666,7 +666,7 @@ private void extractEntitiesFromSentence(
List startOffsets,
List endOffsets,
List> entitiesWithType) {
- for (Span span : nerTaggerOp.getNames(terms.toArray(new String[terms.size()]))) {
+ for (Span span : nerTaggerOp.getNames(terms.toArray(new String[0]))) {
String text =
fullText.substring(
startOffsets.get(span.getStart()), endOffsets.get(span.getEnd() - 1));
diff --git a/solr/modules/hdfs/src/test/org/apache/hadoop/fs/FileUtil.java b/solr/modules/hdfs/src/test/org/apache/hadoop/fs/FileUtil.java
index f9a8717c1c7..29c08364fe3 100644
--- a/solr/modules/hdfs/src/test/org/apache/hadoop/fs/FileUtil.java
+++ b/solr/modules/hdfs/src/test/org/apache/hadoop/fs/FileUtil.java
@@ -736,7 +736,7 @@ private static void runCommandOnStream(
try (BufferedReader reader =
new BufferedReader(
new InputStreamReader(process.getInputStream(),
- Charset.forName("UTF-8")))) {
+ StandardCharsets.UTF_8))) {
String line;
while((line = reader.readLine()) != null) {
LOG.debug(line);
@@ -759,7 +759,7 @@ private static void runCommandOnStream(
try (BufferedReader reader =
new BufferedReader(
new InputStreamReader(process.getErrorStream(),
- Charset.forName("UTF-8")))) {
+ StandardCharsets.UTF_8))) {
String line;
while((line = reader.readLine()) != null) {
LOG.debug(line);
diff --git a/solr/modules/hdfs/src/test/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/BlockPoolSlice.java b/solr/modules/hdfs/src/test/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/BlockPoolSlice.java
index 3961fc29641..26536002d27 100644
--- a/solr/modules/hdfs/src/test/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/BlockPoolSlice.java
+++ b/solr/modules/hdfs/src/test/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/BlockPoolSlice.java
@@ -55,6 +55,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -497,7 +498,7 @@ private void addReplicaToReplicasMap(Block block, ReplicaMap volumeMap,
File.pathSeparator + "." + file.getName() + ".restart");
Scanner sc = null;
try {
- sc = new Scanner(restartMeta, "UTF-8");
+ sc = new Scanner(restartMeta, StandardCharsets.UTF_8);
// The restart meta file exists
if (sc.hasNextLong() && (sc.nextLong() > timer.now())) {
// It didn't expire. Load the replica as a RBW.
diff --git a/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/TestDistributedTracing.java b/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/TestDistributedTracing.java
index 23cf76f1cbf..ab362068e2e 100644
--- a/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/TestDistributedTracing.java
+++ b/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/TestDistributedTracing.java
@@ -18,7 +18,6 @@
package org.apache.solr.opentelemetry;
import io.opentelemetry.api.GlobalOpenTelemetry;
-import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.api.trace.TracerProvider;
import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter;
import io.opentelemetry.sdk.trace.data.SpanData;
@@ -26,7 +25,6 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.stream.Collectors;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.SolrServerException;
@@ -34,6 +32,7 @@
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.GenericSolrRequest;
import org.apache.solr.client.solrj.request.V2Request;
+import org.apache.solr.client.solrj.response.CollectionAdminResponse;
import org.apache.solr.client.solrj.response.V2Response;
import org.apache.solr.cloud.SolrCloudTestCase;
import org.apache.solr.common.SolrDocumentList;
@@ -108,14 +107,7 @@ public void test() throws IOException, SolrServerException {
|| !span.getAttributes().get(TraceUtils.TAG_HTTP_URL).endsWith("/select"));
// one from client to server, 2 for execute query, 2 for fetching documents
assertEquals(5, finishedSpans.size());
- assertEquals(1, finishedSpans.stream().filter(TestDistributedTracing::isRootSpan).count());
- var parentTraceId =
- finishedSpans.stream()
- .filter(TestDistributedTracing::isRootSpan)
- .collect(Collectors.toList())
- .get(0)
- .getSpanContext()
- .getTraceId();
+ var parentTraceId = getRootTraceId(finishedSpans);
for (var span : finishedSpans) {
if (isRootSpan(span)) {
continue;
@@ -177,8 +169,30 @@ public void testV2Api() throws Exception {
assertEquals(1, ((SolrDocumentList) v2Response.getResponse().get("response")).getNumFound());
}
+ /**
+ * Best effort test of the apache http client tracing. the test assumes the request uses the http
+ * client but there is no way to enforce it, so when the api will be rewritten this test will
+ * become obsolete
+ */
+ @Test
+ public void testApacheClient() throws Exception {
+ getAndClearSpans(); // reset
+ CollectionAdminRequest.ColStatus a1 = CollectionAdminRequest.collectionStatus(COLLECTION);
+ CollectionAdminResponse r1 = a1.process(cluster.getSolrClient());
+ assertEquals(0, r1.getStatus());
+ var finishedSpans = getAndClearSpans();
+ var parentTraceId = getRootTraceId(finishedSpans);
+ for (var span : finishedSpans) {
+ if (isRootSpan(span)) {
+ continue;
+ }
+ assertEquals(span.getParentSpanContext().getTraceId(), parentTraceId);
+ assertEquals(span.getTraceId(), parentTraceId);
+ }
+ }
+
private static boolean isRootSpan(SpanData span) {
- return span.getParentSpanContext() == SpanContext.getInvalid();
+ return !span.getParentSpanContext().isValid();
}
private static void assertCollectionName(SpanData span) {
@@ -208,4 +222,14 @@ static List getAndClearSpans() {
exporter.reset();
return result;
}
+
+ private String getRootTraceId(List finishedSpans) {
+ assertEquals(1, finishedSpans.stream().filter(TestDistributedTracing::isRootSpan).count());
+ return finishedSpans.stream()
+ .filter(TestDistributedTracing::isRootSpan)
+ .findFirst()
+ .get()
+ .getSpanContext()
+ .getTraceId();
+ }
}
diff --git a/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrTable.java b/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrTable.java
index 6b3cb67b96b..8bf82037e03 100644
--- a/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrTable.java
+++ b/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrTable.java
@@ -883,7 +883,7 @@ private StreamComparator[] adjustSorts(List> orders, Bucket
}
}
- return adjustedSorts.toArray(new FieldComparator[adjustedSorts.size()]);
+ return adjustedSorts.toArray(new FieldComparator[0]);
}
private TupleStream handleStats(
diff --git a/solr/packaging/test/test_basic_auth.bats b/solr/packaging/test/test_basic_auth.bats
new file mode 100644
index 00000000000..28a9efa0335
--- /dev/null
+++ b/solr/packaging/test/test_basic_auth.bats
@@ -0,0 +1,92 @@
+#!/usr/bin/env bats
+
+# 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.
+
+load bats_helper
+
+setup() {
+ common_clean_setup
+
+ echo "Starting Solr"
+ solr start -c -Denable.packages=true
+
+ # The auth command exports some system variables that are injected as basic auth username and password,
+ # however that defeats our test so fake that out via -solrIncludeFile param specifing a bogus path.
+ solr auth enable -type basicAuth -credentials name:password -solrIncludeFile /force/credentials/to/be/supplied
+
+ solr assert -credentials name:password --cloud http://localhost:${SOLR_PORT} --timeout 5000
+}
+
+teardown() {
+ # save a snapshot of SOLR_HOME for failed tests
+ save_home_on_failure
+
+ run solr auth disable -z localhost:${ZK_PORT}
+ solr stop -all >/dev/null 2>&1
+}
+
+# Remaining commands that should support basic auth:
+# package, export
+
+
+@test "create, config, api, and delete with basic auth" {
+
+ # Test create
+ run solr create -u name:password -c COLL_NAME
+ assert_output --partial "Created collection 'COLL_NAME'"
+
+ # Test config
+ run solr config -u name:password -c COLL_NAME -action set-property -property updateHandler.autoCommit.maxDocs -value 100 -solrUrl http://localhost:${SOLR_PORT}/solr
+ assert_output --partial "Successfully set-property updateHandler.autoCommit.maxDocs to 100"
+
+ # Test api
+ run solr api -u name:password -get "http://localhost:${SOLR_PORT}/solr/COLL_NAME/select?q=*:*" -verbose
+ assert_output --partial '"numFound":0'
+
+ # Test delete
+ run solr delete --credentials name:password -c COLL_NAME -zkHost localhost:${ZK_PORT} -verbose
+ assert_output --partial "Deleted collection 'COLL_NAME'"
+ refute collection_exists "COLL_NAME"
+
+}
+
+@test "post, postlogs and export with basic auth" {
+run solr create -c COLL_NAME
+ run solr create -u name:password -c COLL_NAME
+ assert_output --partial "Created collection 'COLL_NAME'"
+
+ # Test post
+ run solr post -u name:password -type application/xml -url http://localhost:${SOLR_PORT}/solr/monitors/update ${SOLR_TIP}/example/exampledocs/monitor.xml
+ assert_output --partial '1 files indexed.'
+
+ # Test postlogs
+ run solr postlogs -u name:password -url http://localhost:${SOLR_PORT}/solr/COLL_NAME -rootdir ${SOLR_LOGS_DIR}/solr.log
+ assert_output --partial 'Committed'
+
+ # Test export
+ #run solr export -u name:password -url "http://localhost:${SOLR_PORT}/solr/COLL_NAME" -query "*:*" -out "${BATS_TEST_TMPDIR}/output"
+ #assert_output --partial 'Export complete'
+
+}
+
+@test "package with basic auth" {
+
+ run solr package deploy PACKAGE_NAME -credentials name:password -collections foo-1.2
+ # verify that package tool is communicating with Solr via basic auth
+ assert_output --partial "Collection(s) doesn't exist: [foo-1.2]"
+ #assert_output --partial "Deployment successful"
+ #refute_output --partial "Invalid collection"
+}
diff --git a/solr/packaging/test/test_bats.bats b/solr/packaging/test/test_bats.bats
index 9d269a62d3f..7fbe19c74b4 100644
--- a/solr/packaging/test/test_bats.bats
+++ b/solr/packaging/test/test_bats.bats
@@ -33,7 +33,7 @@ teardown_file() {
sleep 3
# Conversely, on shutdown, we do need this to execute strictly
- # because using "run" will eat filing test exit codes
+ # because using "run" will eat failing test exit codes
solr stop -all
# DEBUG : (echo -n "# " ; solr stop -V -all) >&3
}
diff --git a/solr/solr-ref-guide/modules/configuration-guide/pages/package-manager.adoc b/solr/solr-ref-guide/modules/configuration-guide/pages/package-manager.adoc
index 2456ef7f244..4c09666a2ec 100644
--- a/solr/solr-ref-guide/modules/configuration-guide/pages/package-manager.adoc
+++ b/solr/solr-ref-guide/modules/configuration-guide/pages/package-manager.adoc
@@ -216,3 +216,5 @@ Also, it is critical to protect ZooKeeper from unauthorized write access.
Also, keep in mind, that it is possible to install *any* package from a repository once it has been added.
If you want to use some packages in production, a best practice is to setup your own repository and add that to Solr instead of adding a generic third-party repository that is beyond your administrative control.
You might want to re-sign packages from a third-party repository using your own private keys and host them at your own repository.
+
+To use the package tool with Basic Auth protected Solr installation pass in the credentials via `-credentials username:password`.
diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/cluster-node-management.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/cluster-node-management.adoc
index 117d066add4..4e5e02430ca 100644
--- a/solr/solr-ref-guide/modules/deployment-guide/pages/cluster-node-management.adoc
+++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cluster-node-management.adoc
@@ -335,12 +335,6 @@ curl -X POST -H 'Content-type:application/json' --data-binary '
}' http://localhost:8983/api/cluster
----
-NOTE: Until Solr 7.5, cluster properties supported a `collectionDefaults` key which is now deprecated and
-replaced with `defaults`.
-Using the `collectionDefaults` parameter in Solr 7.4 or 7.5 will continue to work
- but the format of the properties will automatically be converted to the new nested structure.
-Support for the "collectionDefaults" key will be removed in Solr 9.
-
=== Default Shard Preferences
Using the `defaultShardPreferences` parameter, you can implement rack or availability zone awareness.
diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/collection-management.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/collection-management.adoc
index 107b4849209..63da9c86e80 100644
--- a/solr/solr-ref-guide/modules/deployment-guide/pages/collection-management.adoc
+++ b/solr/solr-ref-guide/modules/deployment-guide/pages/collection-management.adoc
@@ -250,6 +250,7 @@ If `true` the states of individual replicas will be maintained as individual chi
+
Set core property _name_ to _value_.
See the section xref:configuration-guide:core-discovery.adoc[] for details on supported properties and values.
+Those properties are also applied to every new core that will be created when adding replicas to the collection later on.
+
[WARNING]
====
diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/solr-control-script-reference.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/solr-control-script-reference.adoc
index 54143627189..d292ed27e2c 100644
--- a/solr/solr-ref-guide/modules/deployment-guide/pages/solr-control-script-reference.adoc
+++ b/solr/solr-ref-guide/modules/deployment-guide/pages/solr-control-script-reference.adoc
@@ -51,7 +51,7 @@ If no nodes are already running, restart will skip the step to stop and proceed
The `bin/solr` script provides many options to allow you to customize the server in common ways, such as changing the listening port.
However, most of the defaults are adequate for most Solr installations, especially when just getting started.
-`-a ""`::
+`-a `::
+
[%autowidth,frame=none]
|===
@@ -69,7 +69,7 @@ If you are passing JVM parameters that begin with `-D`, you can omit the `-a` op
[source,bash]
bin/solr start -a "-Xdebug -Xrunjdwp:transport=dt_socket, server=y,suspend=n,address=1044"
-`-j ""`::
+`-j `::
+
[%autowidth,frame=none]
|===
@@ -484,7 +484,7 @@ Solr process 39827 running on port 8865
=== Assert
-The `assert` command sanity checks common issues with Solr installations.
+The `assert` command checks common issues with Solr installations.
These include checking the ownership/existence of particular directories, and ensuring Solr is available on the expected URL.
The command can either output a specified error message, or change its exit code to indicate errors.
@@ -530,6 +530,7 @@ usage: bin/solr assert [-m ] [-e] [-rR] [-s ] [-S ] [-c
-x,--exists Asserts that directory exists.
-X,--not-exists Asserts that directory does NOT
exist.
+ --credentials Username and password for Basic authentication.
----
=== Healthcheck
@@ -577,6 +578,16 @@ This parameter is unnecessary if `ZK_HOST` is defined in `solr.in.sh` or `solr.i
+
*Example*: `bin/solr healthcheck -z localhost:2181`
+`-u ` or `--credentials `::
++
+[%autowidth,frame=none]
+|===
+|Optional | Default: none
+|===
++
+Basic authentication username and password separated by a `:` character.
+This parameter is unnecessary if `SOLR_AUTH_TYPE` is defined in `solr.in.sh` or `solr.in.cmd`.
+
Below is an example healthcheck request and response using a non-standard ZooKeeper connect string, with 2 nodes running:
`$ bin/solr healthcheck -c gettingstarted -z localhost:9865`
@@ -734,6 +745,16 @@ Unnecessary if `ZK_HOST` is defined in `solr.in.sh` or `solr.in.cmd`.
+
Base Solr URL, which can be used in SolrCloud mode to determine the ZooKeeper connection string if that's not known.
+`-u ` or `--credentials `::
++
+[%autowidth,frame=none]
+|===
+|Optional | Default: none
+|===
++
+Basic authentication username and password separated by a `:` character.
+This parameter is unnecessary if `SOLR_AUTH_TYPE` is defined in `solr.in.sh` or `solr.in.cmd`.
+
==== Configuration Directories and SolrCloud
Before creating a collection in SolrCloud, the configuration directory used by the collection must be uploaded to ZooKeeper.
@@ -843,6 +864,16 @@ Unnecessary if `ZK_HOST` is defined in `solr.in.sh` or `solr.in.cmd`.
+
Base Solr URL, which can be used in SolrCloud mode to determine the ZooKeeper connection string if that's not known.
+`-u ` or `--credentials `::
++
+[%autowidth,frame=none]
+|===
+|Optional | Default: none
+|===
++
+Basic authentication username and password separated by a `:` character.
+This parameter is unnecessary if `SOLR_AUTH_TYPE` is defined in `solr.in.sh` or `solr.in.cmd`.
+
== Authentication
The `bin/solr` script allows enabling or disabling Authentication, allowing you to configure authentication from the command line.
@@ -880,7 +911,7 @@ Here are some example usages:
----
Usage: solr auth enable [-type basicAuth] -credentials user:pass [-blockUnknown ] [-updateIncludeFileOnly ] [-V]
solr auth enable [-type basicAuth] -prompt [-blockUnknown ] [-updateIncludeFileOnly ] [-V]
- solr auth enable -type kerberos -config "" [-updateIncludeFileOnly ] [-V]
+ solr auth enable -type kerberos -config [-updateIncludeFileOnly ] [-V]
solr auth disable [-updateIncludeFileOnly ] [-V]
----
@@ -888,7 +919,7 @@ Usage: solr auth enable [-type basicAuth] -credentials user:pass [-blockUnknown
The command takes the following parameters:
-`-credentials `::
+`-u ` or `--credentials `::
+
[%autowidth,frame=none]
|===
@@ -1088,6 +1119,16 @@ Base Solr URL, which can be used in SolrCloud mode to determine the ZooKeeper co
+
The scheme for accessing Solr. Accepted values: http or https. Default is 'http'
+`-u ` or `--credentials `::
++
+[%autowidth,frame=none]
+|===
+|Optional | Default: none
+|===
++
+Basic authentication username and password separated by a `:` character.
+This parameter is unnecessary if `SOLR_AUTH_TYPE` is defined in `solr.in.sh` or `solr.in.cmd`.
+
== ZooKeeper Operations
@@ -1614,6 +1655,16 @@ By default all fields are fetched.
Maximum number of docs to download.
The value `-1` will export all documents.
+`-u ` or `--credentials `::
++
+[%autowidth,frame=none]
+|===
+|Optional | Default: none
+|===
++
+Basic authentication username and password separated by a `:` character.
+This parameter is unnecessary if `SOLR_AUTH_TYPE` is defined in `solr.in.sh` or `solr.in.cmd`.
+
*Examples*
Export all documents from a collection `gettingstarted`:
@@ -1671,6 +1722,7 @@ $ curl -X POST --header "Content-Type: application/javabin" --data-binary @getti
== Interacting with API
The `api` command will allow you to send an arbitrary HTTP request to a Solr API endpoint.
+If you have configured basicAuth or TLS with your Solr you may find this easier than using a separate tool like `curl`.
`bin/solr api -get http://localhost:8983/solr/COLL_NAME/sql?stmt=select+id+from+COLL_NAME+limit+10`
@@ -1689,18 +1741,27 @@ Send a GET request to a Solr API endpoint.
+
*Example*: `bin/solr api -get http://localhost:8983/solr/COLL_NAME/sql?stmt=select+id+from+COLL_NAME+limit+10`
-=== API
+`-u ` or `--credentials `::
++
+[%autowidth,frame=none]
+|===
+|Optional | Default: none
+|===
++
+Basic authentication username and password separated by a `:` character.
+This parameter is unnecessary if `SOLR_AUTH_TYPE` is defined in `solr.in.sh` or `solr.in.cmd`.
+
+*Examples*
-The `api` command will allow you to send an arbitrary HTTP request to a Solr API endpoint.
-If you have configured basicAuth or TLS with your Solr you may find this easier than using a separate tool like `curl`.
+Simple search passing in Basic authentication credentials:
[source,bash]
-$ bin/solr api api -get http://localhost:8983/solr/techproducts/select?q=*:*
+$ bin/solr api -get http://localhost:8983/solr/techproducts/select?q=*:* -u user:password
-Here is an example of sending a SQL query to the techproducts /sql end point (assumes you started Solr in Cloud mode with the SQL module enabled):
+Here is an example of sending a SQL query to the techproducts `/sql` end point (assumes you started Solr in Cloud mode with the SQL module enabled):
[source,bash]
-$ bin/solr api api -get http://localhost:8983/solr/techproducts/sql?stmt=select+id+from+techproducts+limit+10
+$ bin/solr api -get http://localhost:8983/solr/techproducts/sql?stmt=select+id+from+techproducts+limit+10
Results are streamed to the terminal.
diff --git a/solr/solr-ref-guide/modules/indexing-guide/pages/post-tool.adoc b/solr/solr-ref-guide/modules/indexing-guide/pages/post-tool.adoc
index 28a47d28bbc..f285ac6486d 100644
--- a/solr/solr-ref-guide/modules/indexing-guide/pages/post-tool.adoc
+++ b/solr/solr-ref-guide/modules/indexing-guide/pages/post-tool.adoc
@@ -53,7 +53,7 @@ OPTIONS
Solr options:
-url
-commit issue a commit
- -u or -user (sets BasicAuth credentials)
+ -u or -credentials (sets BasicAuth credentials)
Web crawl options:
-recursive (default: 1)
diff --git a/solr/solr-ref-guide/modules/query-guide/pages/document-transformers.adoc b/solr/solr-ref-guide/modules/query-guide/pages/document-transformers.adoc
index 3821f772a94..addbefedb9d 100644
--- a/solr/solr-ref-guide/modules/query-guide/pages/document-transformers.adoc
+++ b/solr/solr-ref-guide/modules/query-guide/pages/document-transformers.adoc
@@ -187,7 +187,7 @@ It is likely to be removed in a future Solr release, so _if you find it has some
When a `\_nest_path_` field is defined, the `childFilter` option supports an experimental syntax to combine a "path syntax" restriction with a more traditional filtering query.
-*This syntax is triggered by including a `/` seperated path structure prior to a query that includes a `:` character.*
+*This syntax is triggered by including a `/` separated path structure prior to a query that includes a `:` character.*
When the "path" begins with a `/` character, it restricts matches to documents that have that exist "path" of nested pseudo-field documents, starting at the Root document of the block (even if the document being transformed is not a Root level document)
diff --git a/solr/solr-ref-guide/modules/query-guide/pages/logs.adoc b/solr/solr-ref-guide/modules/query-guide/pages/logs.adoc
index 7ac02556335..6246008ac7a 100644
--- a/solr/solr-ref-guide/modules/query-guide/pages/logs.adoc
+++ b/solr/solr-ref-guide/modules/query-guide/pages/logs.adoc
@@ -36,7 +36,7 @@ The `postlogs` command reads in Solr's log format and indexes it in a Solr colle
==== Healthcheck Parameters
-`-url `::
+`-url `::
+
[%autowidth,frame=none]
|===
@@ -46,7 +46,7 @@ The `postlogs` command reads in Solr's log format and indexes it in a Solr colle
Address of the collection, example http://localhost:8983/solr/collection1/.
+
-`-rootdir `::
+`-rootdir `::
+
[%autowidth,frame=none]
|===
@@ -56,6 +56,16 @@ Address of the collection, example http://localhost:8983/solr/collection1/.
File path to root of the logs directory: All files found under this directory (including sub-directories) will be indexed.
If the path points to a single log file only that log file will be loaded.
+`-u ` or `--credentials `::
++
+[%autowidth,frame=none]
+|===
+|Optional | Default: none
+|===
++
+Basic authentication username and password separated by a `:` character.
+This parameter is unnecessary if `SOLR_AUTH_TYPE` is defined in `solr.in.sh` or `solr.in.cmd`.
+
+
*Example*: `bin/solr postlogs --url http://localhost:8983/solr/logs --rootdir /var/logs/solrlogs`
diff --git a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/comp/MultipleFieldComparator.java b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/comp/MultipleFieldComparator.java
index 9790baddf20..065eabfd68c 100644
--- a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/comp/MultipleFieldComparator.java
+++ b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/comp/MultipleFieldComparator.java
@@ -145,6 +145,6 @@ public StreamComparator append(StreamComparator other) {
}
}
- return new MultipleFieldComparator(newComps.toArray(new StreamComparator[newComps.size()]));
+ return new MultipleFieldComparator(newComps.toArray(new StreamComparator[0]));
}
}
diff --git a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/graph/GatherNodesStream.java b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/graph/GatherNodesStream.java
index f62b8e57fa7..68a0e82e396 100644
--- a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/graph/GatherNodesStream.java
+++ b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/graph/GatherNodesStream.java
@@ -653,7 +653,7 @@ private String[] getDayWindow(int size, int lag, String start) {
}
List laggedWindow = windowList.subList(lag, windowList.size());
- return laggedWindow.toArray(new String[laggedWindow.size()]);
+ return laggedWindow.toArray(new String[0]);
} catch (ParseException e) {
log.warn("Unparseable date:{}", String.valueOf(start));
return new String[0];
@@ -684,7 +684,7 @@ private String[] getWeekDayWindow(int size, int lag, String start) {
}
List laggedWindow = windowList.subList(lag, windowList.size());
- return laggedWindow.toArray(new String[laggedWindow.size()]);
+ return laggedWindow.toArray(new String[0]);
} catch (ParseException e) {
log.warn("Unparseable date:{}", String.valueOf(start));
return new String[0];
diff --git a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/sql/DriverImpl.java b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/sql/DriverImpl.java
index 47366bb02dc..3509b54abd1 100644
--- a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/sql/DriverImpl.java
+++ b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/sql/DriverImpl.java
@@ -18,6 +18,7 @@
import java.net.URI;
import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
@@ -124,7 +125,7 @@ protected URI processUrl(String url) throws SQLException {
}
private void loadParams(URI uri, Properties props) throws SQLException {
- List parsedParams = URLEncodedUtils.parse(uri, "UTF-8");
+ List parsedParams = URLEncodedUtils.parse(uri, StandardCharsets.UTF_8);
for (NameValuePair pair : parsedParams) {
if (pair.getValue() != null) {
props.put(pair.getName(), pair.getValue());
diff --git a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/FacetStream.java b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/FacetStream.java
index 759c038d7a0..9e39198c287 100644
--- a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/FacetStream.java
+++ b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/FacetStream.java
@@ -480,7 +480,7 @@ private String[] parseSorts(String sortString) {
sorts.add(buff.toString());
}
- return sorts.toArray(new String[sorts.size()]);
+ return sorts.toArray(new String[0]);
}
private void init(
diff --git a/solr/solrj-zookeeper/src/java/org/apache/solr/client/solrj/impl/SolrClientCloudManager.java b/solr/solrj-zookeeper/src/java/org/apache/solr/client/solrj/impl/SolrClientCloudManager.java
index b7645a9a671..626a917e7ed 100644
--- a/solr/solrj-zookeeper/src/java/org/apache/solr/client/solrj/impl/SolrClientCloudManager.java
+++ b/solr/solrj-zookeeper/src/java/org/apache/solr/client/solrj/impl/SolrClientCloudManager.java
@@ -19,6 +19,7 @@
import java.io.IOException;
import java.lang.invoke.MethodHandles;
+import java.nio.charset.StandardCharsets;
import java.util.Map;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
@@ -139,7 +140,7 @@ public byte[] httpRequest(
final HttpRequestBase req;
HttpEntity entity = null;
if (payload != null) {
- entity = new StringEntity(payload, "UTF-8");
+ entity = new StringEntity(payload, StandardCharsets.UTF_8);
}
switch (method) {
case GET:
diff --git a/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/ClusterProperties.java b/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/ClusterProperties.java
index 84e5cf462e4..38e9e046266 100644
--- a/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/ClusterProperties.java
+++ b/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/ClusterProperties.java
@@ -17,8 +17,6 @@
package org.apache.solr.common.cloud;
-import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_DEF;
-
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.Arrays;
@@ -28,7 +26,6 @@
import java.util.Map;
import org.apache.solr.common.MapWriter;
import org.apache.solr.common.SolrException;
-import org.apache.solr.common.params.CollectionAdminParams;
import org.apache.solr.common.util.Utils;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
@@ -98,7 +95,7 @@ public Map getClusterProperties() throws IOException {
Map properties =
(Map)
Utils.fromJSON(client.getData(ZkStateReader.CLUSTER_PROPS, null, new Stat(), true));
- return convertCollectionDefaultsToNestedFormat(properties);
+ return properties;
} catch (KeeperException.NoNodeException e) {
return Collections.emptyMap();
} catch (KeeperException | InterruptedException e) {
@@ -111,13 +108,10 @@ public void setClusterProperties(Map properties)
client.atomicUpdate(
ZkStateReader.CLUSTER_PROPS,
zkData -> {
- if (zkData == null)
- return Utils.toJSON(convertCollectionDefaultsToNestedFormat(properties));
+ if (zkData == null) return Utils.toJSON(properties);
@SuppressWarnings({"unchecked"})
Map zkJson = (Map) Utils.fromJSON(zkData);
- zkJson = convertCollectionDefaultsToNestedFormat(zkJson);
- boolean modified =
- Utils.mergeJson(zkJson, convertCollectionDefaultsToNestedFormat(properties));
+ boolean modified = Utils.mergeJson(zkJson, properties);
return modified ? Utils.toJSON(zkJson) : null;
});
}
@@ -145,43 +139,6 @@ public void update(MapWriter obj, String... path) throws KeeperException, Interr
});
}
- /**
- * See SOLR-12827 for background. We auto convert any "collectionDefaults" keys to
- * "defaults/collection" format. This method will modify the given map and return the same object.
- * Remove this method in Solr 9.
- *
- * @param properties the properties to be converted
- * @return the converted map
- */
- @SuppressWarnings({"unchecked"})
- static Map convertCollectionDefaultsToNestedFormat(
- Map properties) {
- if (properties.containsKey(COLLECTION_DEF)) {
- Map values = (Map) properties.remove(COLLECTION_DEF);
- if (values != null) {
- properties.putIfAbsent(CollectionAdminParams.DEFAULTS, new LinkedHashMap<>());
- Map defaults =
- (Map) properties.get(CollectionAdminParams.DEFAULTS);
- defaults.compute(
- CollectionAdminParams.COLLECTION,
- (k, v) -> {
- if (v == null) return values;
- else {
- ((Map) v).putAll(values);
- return v;
- }
- });
- } else {
- // explicitly set to null, so set null in the nested format as well
- properties.putIfAbsent(CollectionAdminParams.DEFAULTS, new LinkedHashMap<>());
- Map defaults =
- (Map) properties.get(CollectionAdminParams.DEFAULTS);
- defaults.put(CollectionAdminParams.COLLECTION, null);
- }
- }
- return properties;
- }
-
/**
* This method sets a cluster property.
*
diff --git a/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/ZkStateReader.java b/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/ZkStateReader.java
index 0918ad48ef7..e85bac3173c 100644
--- a/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/ZkStateReader.java
+++ b/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/ZkStateReader.java
@@ -141,11 +141,6 @@ public class ZkStateReader implements SolrCloseable {
public static final String CONFIGS_ZKNODE = "/configs";
public static final String CONFIGNAME_PROP = "configName";
- /**
- * @deprecated use {@link org.apache.solr.common.params.CollectionAdminParams#DEFAULTS} instead.
- */
- @Deprecated public static final String COLLECTION_DEF = "collectionDefaults";
-
public static final String URL_SCHEME = "urlScheme";
public static final String HTTP = "http";
public static final String HTTPS = "https";
@@ -1141,6 +1136,7 @@ public Map getClusterProperties() {
loadClusterProperties();
};
+ @SuppressWarnings("unchecked")
private void loadClusterProperties() {
try {
while (true) {
@@ -1148,10 +1144,7 @@ private void loadClusterProperties() {
byte[] data =
zkClient.getData(
ZkStateReader.CLUSTER_PROPS, clusterPropertiesWatcher, new Stat(), true);
- @SuppressWarnings("unchecked")
- Map properties = (Map) Utils.fromJSON(data);
- this.clusterProperties =
- ClusterProperties.convertCollectionDefaultsToNestedFormat(properties);
+ this.clusterProperties = (Map) Utils.fromJSON(data);
log.debug("Loaded cluster properties: {}", this.clusterProperties);
for (ClusterPropertiesListener listener : clusterPropertiesListeners) {
diff --git a/solr/solrj/build.gradle b/solr/solrj/build.gradle
index e6bdf9caa0f..286022c728a 100644
--- a/solr/solrj/build.gradle
+++ b/solr/solrj/build.gradle
@@ -30,7 +30,7 @@ description = 'Solrj - Solr Java Client'
dependencies {
implementation 'com.fasterxml.jackson.core:jackson-databind'
implementation 'com.fasterxml.jackson.core:jackson-annotations'
- implementation project(":solr:api")
+ api project(":solr:api")
implementation 'org.slf4j:slf4j-api'
runtimeOnly 'org.slf4j:jcl-over-slf4j'
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/SolrRequest.java b/solr/solrj/src/java/org/apache/solr/client/solrj/SolrRequest.java
index f433b6c34d0..d3f813f8bcb 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/SolrRequest.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/SolrRequest.java
@@ -82,24 +82,6 @@ public enum SolrClientContext {
private StreamingResponseCallback callback;
private Set queryParams;
- protected boolean usev2;
- protected boolean useBinaryV2;
-
- /**
- * If set to true, every request that implements {@link V2RequestSupport} will be converted to a
- * V2 API call
- */
- public SolrRequest setUseV2(boolean flag) {
- this.usev2 = flag;
- return this;
- }
-
- /** If set to true use javabin instead of json (default) */
- public SolrRequest setUseBinaryV2(boolean flag) {
- this.useBinaryV2 = flag;
- return this;
- }
-
public SolrRequest setPreferredNodes(List nodes) {
this.preferredNodes = nodes;
return this;
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/V2RequestSupport.java b/solr/solrj/src/java/org/apache/solr/client/solrj/V2RequestSupport.java
deleted file mode 100644
index d65edd1606e..00000000000
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/V2RequestSupport.java
+++ /dev/null
@@ -1,25 +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.client.solrj;
-
-/** A a request object is able to convert itself to V2 Request it should implement this interface */
-public interface V2RequestSupport {
- /** If usev2 flag is set to true, return V2Request, if not, return V1 request object */
- @SuppressWarnings({"rawtypes"})
- SolrRequest getV2Request();
-}
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrClient.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrClient.java
index 7bed0138043..58f98c6bbc8 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrClient.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrClient.java
@@ -52,7 +52,6 @@
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.SolrServerException;
-import org.apache.solr.client.solrj.V2RequestSupport;
import org.apache.solr.client.solrj.request.AbstractUpdateRequest;
import org.apache.solr.client.solrj.request.IsUpdateRequest;
import org.apache.solr.client.solrj.request.RequestWriter;
@@ -785,9 +784,6 @@ protected NamedList requestWithRetryOnStaleState(
String stateVerParam = null;
List requestedCollections = null;
boolean isCollectionRequestOfV2 = false;
- if (request instanceof V2RequestSupport) {
- request = ((V2RequestSupport) request).getV2Request();
- }
if (request instanceof V2Request) {
isCollectionRequestOfV2 = ((V2Request) request).isPerCollectionRequest();
}
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Http2SolrClient.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Http2SolrClient.java
index f6d8a08df98..0f060000d30 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Http2SolrClient.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Http2SolrClient.java
@@ -53,7 +53,6 @@
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.SolrServerException;
-import org.apache.solr.client.solrj.V2RequestSupport;
import org.apache.solr.client.solrj.embedded.SSLConfig;
import org.apache.solr.client.solrj.impl.BaseHttpSolrClient.RemoteExecutionException;
import org.apache.solr.client.solrj.impl.BaseHttpSolrClient.RemoteSolrException;
@@ -462,9 +461,10 @@ public void send(OutStream outStream, SolrRequest> req, String collection) thr
private static final Cancellable FAILED_MAKING_REQUEST_CANCELLABLE = () -> {};
public Cancellable asyncRequest(
- SolrRequest> solrReq, String collection, AsyncListener> asyncListener) {
+ SolrRequest> solrRequest,
+ String collection,
+ AsyncListener> asyncListener) {
MDCCopyHelper mdcCopyHelper = new MDCCopyHelper();
- SolrRequest> solrRequest = unwrapV2Request(solrReq);
Request req;
try {
@@ -521,7 +521,6 @@ public void onFailure(Response response, Throwable failure) {
public NamedList request(SolrRequest> solrRequest, String collection)
throws SolrServerException, IOException {
- solrRequest = unwrapV2Request(solrRequest);
String url = getRequestPath(solrRequest, collection);
Throwable abortCause = null;
Request req = null;
@@ -634,17 +633,6 @@ private String changeV2RequestEndpoint(String basePath) throws MalformedURLExcep
return new URL(oldURL.getProtocol(), oldURL.getHost(), oldURL.getPort(), newPath).toString();
}
- private SolrRequest> unwrapV2Request(SolrRequest> solrRequest) {
- if (solrRequest.getBasePath() == null && serverBaseUrl == null)
- throw new IllegalArgumentException("Destination node is not provided!");
-
- if (solrRequest instanceof V2RequestSupport) {
- return ((V2RequestSupport) solrRequest).getV2Request();
- } else {
- return solrRequest;
- }
- }
-
private String getRequestPath(SolrRequest> solrRequest, String collection)
throws MalformedURLException {
String basePath = solrRequest.getBasePath() == null ? serverBaseUrl : solrRequest.getBasePath();
@@ -1313,6 +1301,26 @@ public Builder withProxyConfiguration(
this.proxyIsSecure = isSecure;
return this;
}
+
+ /**
+ * Setup basic authentication from a string formatted as username:password. If the string is
+ * Null then it doesn't do anything.
+ *
+ * @param credentials The username and password formatted as username:password
+ * @return this Builder
+ */
+ public Builder withOptionalBasicAuthCredentials(String credentials) {
+ if (credentials != null) {
+ if (credentials.indexOf(':') == -1) {
+ throw new IllegalStateException(
+ "Invalid Authentication credential formatting. Provide username and password in the 'username:password' format.");
+ }
+ String username = credentials.substring(0, credentials.indexOf(':'));
+ String password = credentials.substring(credentials.indexOf(':') + 1, credentials.length());
+ withBasicAuthCredentials(username, password);
+ }
+ return this;
+ }
}
public Set getUrlParamNames() {
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java
index c03fbc9f3f9..67f3162f1cb 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java
@@ -76,7 +76,6 @@
import org.apache.solr.client.solrj.ResponseParser;
import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.SolrServerException;
-import org.apache.solr.client.solrj.V2RequestSupport;
import org.apache.solr.client.solrj.request.RequestWriter;
import org.apache.solr.client.solrj.request.V2Request;
import org.apache.solr.common.SolrException;
@@ -339,9 +338,6 @@ static String changeV2RequestEndpoint(String basePath) throws MalformedURLExcept
protected HttpRequestBase createMethod(SolrRequest> request, String collection)
throws IOException, SolrServerException {
- if (request instanceof V2RequestSupport) {
- request = ((V2RequestSupport) request).getV2Request();
- }
SolrParams params = request.getParams();
RequestWriter.ContentWriter contentWriter = requestWriter.getContentWriter(request);
Collection streams =
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrClient.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrClient.java
index c6ca02f6753..1ba16f521f2 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrClient.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrClient.java
@@ -91,7 +91,7 @@ protected LBHttpSolrClient(Builder builder) {
this.httpSolrClientBuilder = builder.httpSolrClientBuilder;
this.httpClient =
builder.httpClient == null
- ? constructClient(builder.baseSolrUrls.toArray(new String[builder.baseSolrUrls.size()]))
+ ? constructClient(builder.baseSolrUrls.toArray(new String[0]))
: builder.httpClient;
this.connectionTimeoutMillis = builder.connectionTimeoutMillis;
this.soTimeoutMillis = builder.socketTimeoutMillis;
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java
index e619ae716c4..5f77eae75ee 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java
@@ -47,6 +47,7 @@
import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.ImplicitDocRouter;
import org.apache.solr.common.cloud.Replica;
+import org.apache.solr.common.cloud.ReplicaCount;
import org.apache.solr.common.params.CollectionAdminParams;
import org.apache.solr.common.params.CollectionParams;
import org.apache.solr.common.params.CollectionParams.CollectionAction;
@@ -127,6 +128,21 @@ public String getRequestType() {
return SolrRequestType.ADMIN.toString();
}
+ private static void writeNumReplicas(ReplicaCount numReplicas, ModifiableSolrParams params) {
+ if (numReplicas.contains(Replica.Type.NRT)) {
+ params.add(
+ CollectionAdminParams.NRT_REPLICAS, String.valueOf(numReplicas.get(Replica.Type.NRT)));
+ }
+ if (numReplicas.contains(Replica.Type.TLOG)) {
+ params.add(
+ CollectionAdminParams.TLOG_REPLICAS, String.valueOf(numReplicas.get(Replica.Type.TLOG)));
+ }
+ if (numReplicas.contains(Replica.Type.PULL)) {
+ params.add(
+ CollectionAdminParams.PULL_REPLICAS, String.valueOf(numReplicas.get(Replica.Type.PULL)));
+ }
+ }
+
/**
* Take the request specific basic auth creds on this admin request and propagate them to a
* related request if does not already have credentials set, such as a
@@ -445,9 +461,7 @@ public static Create createCollectionWithImplicitRouter(
ImplicitDocRouter.NAME,
null,
checkNotNull("shards", shards),
- numNrtReplicas,
- numTlogReplicas,
- numPullReplicas);
+ new ReplicaCount(numNrtReplicas, numTlogReplicas, numPullReplicas));
}
/**
@@ -470,9 +484,7 @@ public static class Create extends AsyncCollectionSpecificAdminRequest {
protected String shards;
protected String routerField;
protected Integer numShards;
- protected Integer nrtReplicas;
- protected Integer pullReplicas;
- protected Integer tlogReplicas;
+ protected ReplicaCount numReplicas;
protected Boolean perReplicaState;
protected Properties properties;
@@ -493,9 +505,7 @@ protected Create(
null,
numShards,
null,
- numNrtReplicas,
- numTlogReplicas,
- numPullReplicas);
+ new ReplicaCount(numNrtReplicas, numTlogReplicas, numPullReplicas));
}
/**
@@ -509,9 +519,7 @@ protected Create(String collection, String config, String shards, int numNrtRepl
ImplicitDocRouter.NAME,
null,
checkNotNull("shards", shards),
- numNrtReplicas,
- null,
- null);
+ ReplicaCount.of(Replica.Type.NRT, numNrtReplicas));
}
private Create(
@@ -520,9 +528,7 @@ private Create(
String routerName,
Integer numShards,
String shards,
- Integer numNrtReplicas,
- Integer numTlogReplicas,
- Integer numPullReplicas) {
+ ReplicaCount numReplicas) {
super(CollectionAction.CREATE, SolrIdentifierValidator.validateCollectionName(collection));
// NOTE: there's very little we can assert about the args because nothing but "collection" is
// required by the server
@@ -533,9 +539,7 @@ private Create(
this.routerName = routerName;
this.numShards = numShards;
this.setShards(shards);
- this.nrtReplicas = numNrtReplicas;
- this.tlogReplicas = numTlogReplicas;
- this.pullReplicas = numPullReplicas;
+ this.numReplicas = numReplicas;
}
public Create setCreateNodeSet(String nodeSet) {
@@ -554,23 +558,24 @@ public Create setRouterField(String routerField) {
}
public Create setNrtReplicas(Integer nrtReplicas) {
- this.nrtReplicas = nrtReplicas;
- return this;
+ return setNumReplicas(Replica.Type.NRT, nrtReplicas);
}
public Create setTlogReplicas(Integer tlogReplicas) {
- this.tlogReplicas = tlogReplicas;
- return this;
+ return setNumReplicas(Replica.Type.TLOG, tlogReplicas);
}
public Create setPullReplicas(Integer pullReplicas) {
- this.pullReplicas = pullReplicas;
+ return setNumReplicas(Replica.Type.PULL, pullReplicas);
+ }
+
+ public Create setNumReplicas(Replica.Type type, Integer count) {
+ this.numReplicas.put(type, count);
return this;
}
public Create setReplicationFactor(Integer repl) {
- this.nrtReplicas = repl;
- return this;
+ return setNrtReplicas(repl);
}
public Create setRule(String... s) {
@@ -614,19 +619,23 @@ public Integer getNumShards() {
}
public Integer getReplicationFactor() {
- return getNumNrtReplicas();
+ return getNumReplicas(Replica.Type.NRT);
}
public Integer getNumNrtReplicas() {
- return nrtReplicas;
+ return getNumReplicas(Replica.Type.NRT);
}
public Integer getNumTlogReplicas() {
- return tlogReplicas;
+ return getNumReplicas(Replica.Type.TLOG);
}
public Integer getNumPullReplicas() {
- return pullReplicas;
+ return getNumReplicas(Replica.Type.PULL);
+ }
+
+ public Integer getNumReplicas(Replica.Type type) {
+ return numReplicas.get(type);
}
public Boolean getPerReplicaState() {
@@ -686,18 +695,10 @@ public SolrParams getParams() {
if (routerField != null) {
params.set("router.field", routerField);
}
- if (nrtReplicas != null) {
- params.set(CollectionAdminParams.NRT_REPLICAS, nrtReplicas);
- }
if (properties != null) {
addProperties(params, properties);
}
- if (pullReplicas != null) {
- params.set(CollectionAdminParams.PULL_REPLICAS, pullReplicas);
- }
- if (tlogReplicas != null) {
- params.set(CollectionAdminParams.TLOG_REPLICAS, tlogReplicas);
- }
+ writeNumReplicas(numReplicas, params);
if (Boolean.TRUE.equals(perReplicaState)) {
params.set(CollectionAdminParams.PER_REPLICA_STATE, perReplicaState);
}
@@ -1251,9 +1252,7 @@ public static class Restore extends AsyncCollectionSpecificAdminRequest {
// in common with collection creation:
protected String configName;
protected Integer replicationFactor;
- protected Integer nrtReplicas;
- protected Integer tlogReplicas;
- protected Integer pullReplicas;
+ protected ReplicaCount numReplicas;
protected Optional createNodeSet = Optional.empty();
protected Optional createNodeSetShuffle = Optional.empty();
protected Properties properties;
@@ -1262,6 +1261,7 @@ public static class Restore extends AsyncCollectionSpecificAdminRequest {
public Restore(String collection, String backupName) {
super(CollectionAction.RESTORE, collection);
this.backupName = backupName;
+ this.numReplicas = ReplicaCount.empty();
}
public String getLocation() {
@@ -1318,30 +1318,35 @@ public Restore setReplicationFactor(Integer replicationFactor) {
}
public Integer getNrtReplicas() {
- return nrtReplicas;
+ return getNumReplicas(Replica.Type.NRT);
}
public Restore setNrtReplicas(Integer nrtReplicas) {
- this.nrtReplicas = nrtReplicas;
- return this;
+ return setNumReplicas(Replica.Type.NRT, nrtReplicas);
}
- ;
public Integer getTlogReplicas() {
- return tlogReplicas;
+ return getNumReplicas(Replica.Type.TLOG);
}
public Restore setTlogReplicas(Integer tlogReplicas) {
- this.tlogReplicas = tlogReplicas;
- return this;
+ return setNumReplicas(Replica.Type.TLOG, tlogReplicas);
}
public Integer getPullReplicas() {
- return pullReplicas;
+ return getNumReplicas(Replica.Type.PULL);
}
public Restore setPullReplicas(Integer pullReplicas) {
- this.pullReplicas = pullReplicas;
+ return setNumReplicas(Replica.Type.PULL, pullReplicas);
+ }
+
+ public int getNumReplicas(Replica.Type type) {
+ return this.numReplicas.get(type);
+ }
+
+ public Restore setNumReplicas(Replica.Type type, Integer count) {
+ this.numReplicas.put(type, count);
return this;
}
@@ -1377,7 +1382,7 @@ public SolrParams getParams() {
params.set(CoreAdminParams.NAME, backupName);
params.set(CoreAdminParams.BACKUP_LOCATION, location); // note: optional
params.set("collection.configName", configName); // note: optional
- if (replicationFactor != null && nrtReplicas != null) {
+ if (replicationFactor != null && numReplicas.contains(Replica.Type.NRT)) {
throw new SolrException(
SolrException.ErrorCode.BAD_REQUEST,
"Cannot set both replicationFactor and nrtReplicas as they mean the same thing");
@@ -1385,15 +1390,7 @@ public SolrParams getParams() {
if (replicationFactor != null) {
params.set(CollectionAdminParams.REPLICATION_FACTOR, replicationFactor);
}
- if (nrtReplicas != null) {
- params.set(CollectionAdminParams.NRT_REPLICAS, nrtReplicas);
- }
- if (pullReplicas != null) {
- params.set(CollectionAdminParams.PULL_REPLICAS, pullReplicas);
- }
- if (tlogReplicas != null) {
- params.set(CollectionAdminParams.TLOG_REPLICAS, tlogReplicas);
- }
+ writeNumReplicas(numReplicas, params);
if (properties != null) {
addProperties(params, properties);
}
@@ -2441,7 +2438,7 @@ public static class AddReplica extends AsyncCollectionAdminRequest {
protected String ulogDir;
protected Properties properties;
protected Replica.Type type;
- protected Integer nrtReplicas, tlogReplicas, pullReplicas;
+ protected ReplicaCount numReplicas;
protected Boolean skipNodeAssignment;
protected String createNodeSet;
@@ -2451,6 +2448,7 @@ private AddReplica(String collection, String shard, String routeKey, Replica.Typ
this.shard = shard;
this.routeKey = routeKey;
this.type = type;
+ this.numReplicas = ReplicaCount.empty();
}
public Properties getProperties() {
@@ -2528,29 +2526,35 @@ public String getShard() {
}
public Integer getNrtReplicas() {
- return nrtReplicas;
+ return getNumReplicas(Replica.Type.NRT);
}
public AddReplica setNrtReplicas(Integer nrtReplicas) {
- this.nrtReplicas = nrtReplicas;
- return this;
+ return setNumReplicas(Replica.Type.NRT, nrtReplicas);
}
public Integer getTlogReplicas() {
- return tlogReplicas;
+ return getNumReplicas(Replica.Type.TLOG);
}
public AddReplica setTlogReplicas(Integer tlogReplicas) {
- this.tlogReplicas = tlogReplicas;
- return this;
+ return setNumReplicas(Replica.Type.TLOG, tlogReplicas);
}
public Integer getPullReplicas() {
- return pullReplicas;
+ return getNumReplicas(Replica.Type.PULL);
}
public AddReplica setPullReplicas(Integer pullReplicas) {
- this.pullReplicas = pullReplicas;
+ return setNumReplicas(Replica.Type.PULL, pullReplicas);
+ }
+
+ public int getNumReplicas(Replica.Type type) {
+ return this.numReplicas.get(type);
+ }
+
+ public AddReplica setNumReplicas(Replica.Type type, Integer count) {
+ this.numReplicas.put(type, count);
return this;
}
@@ -2598,15 +2602,7 @@ public SolrParams getParams() {
if (properties != null) {
addProperties(params, properties);
}
- if (nrtReplicas != null) {
- params.add(CollectionAdminParams.NRT_REPLICAS, String.valueOf(nrtReplicas));
- }
- if (tlogReplicas != null) {
- params.add(CollectionAdminParams.TLOG_REPLICAS, String.valueOf(tlogReplicas));
- }
- if (pullReplicas != null) {
- params.add(CollectionAdminParams.PULL_REPLICAS, String.valueOf(pullReplicas));
- }
+ writeNumReplicas(numReplicas, params);
if (createNodeSet != null) {
params.add(CREATE_NODE_SET_PARAM, createNodeSet);
}
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/request/LukeRequest.java b/solr/solrj/src/java/org/apache/solr/client/solrj/request/LukeRequest.java
index 261437ce43f..3e28a258faa 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/request/LukeRequest.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/LukeRequest.java
@@ -111,7 +111,7 @@ protected LukeResponse createResponse(SolrClient client) {
public SolrParams getParams() {
ModifiableSolrParams params = new ModifiableSolrParams();
if (fields != null && fields.size() > 0) {
- params.add(CommonParams.FL, fields.toArray(new String[fields.size()]));
+ params.add(CommonParams.FL, fields.toArray(new String[0]));
}
if (numTerms >= 0) {
params.add("numTerms", numTerms + "");
diff --git a/solr/solrj/src/java/org/apache/solr/common/cloud/DocCollection.java b/solr/solrj/src/java/org/apache/solr/common/cloud/DocCollection.java
index 0d23ca58ab0..f49087967e3 100644
--- a/solr/solrj/src/java/org/apache/solr/common/cloud/DocCollection.java
+++ b/solr/solrj/src/java/org/apache/solr/common/cloud/DocCollection.java
@@ -58,9 +58,7 @@ public class DocCollection extends ZkNodeProps implements Iterable {
private final String znode;
private final Integer replicationFactor;
- private final Integer numNrtReplicas;
- private final Integer numTlogReplicas;
- private final Integer numPullReplicas;
+ private final ReplicaCount numReplicas;
private final Boolean readOnly;
private final Boolean perReplicaState;
private final Map replicaMap = new HashMap<>();
@@ -115,9 +113,11 @@ private DocCollection(
this.nodeNameLeaderReplicas = new HashMap<>();
this.nodeNameReplicas = new HashMap<>();
this.replicationFactor = (Integer) verifyProp(props, CollectionStateProps.REPLICATION_FACTOR);
- this.numNrtReplicas = (Integer) verifyProp(props, CollectionStateProps.NRT_REPLICAS, 0);
- this.numTlogReplicas = (Integer) verifyProp(props, CollectionStateProps.TLOG_REPLICAS, 0);
- this.numPullReplicas = (Integer) verifyProp(props, CollectionStateProps.PULL_REPLICAS, 0);
+ this.numReplicas =
+ new ReplicaCount(
+ (Integer) verifyProp(props, CollectionStateProps.NRT_REPLICAS, 0),
+ (Integer) verifyProp(props, CollectionStateProps.TLOG_REPLICAS, 0),
+ (Integer) verifyProp(props, CollectionStateProps.PULL_REPLICAS, 0));
this.perReplicaState =
(Boolean) verifyProp(props, CollectionStateProps.PER_REPLICA_STATE, Boolean.FALSE);
if (this.perReplicaState) {
@@ -148,7 +148,7 @@ private DocCollection(
}
}
}
- this.activeSlicesArr = activeSlices.values().toArray(new Slice[activeSlices.size()]);
+ this.activeSlicesArr = activeSlices.values().toArray(new Slice[0]);
this.router = router;
this.znode = getCollectionPath(name);
assert name != null && slices != null;
@@ -513,7 +513,7 @@ public int hashCode() {
* this collection was created with
*/
public Integer getNumNrtReplicas() {
- return numNrtReplicas;
+ return getNumReplicas(Replica.Type.NRT);
}
/**
@@ -521,7 +521,7 @@ public Integer getNumNrtReplicas() {
* this collection was created with
*/
public Integer getNumTlogReplicas() {
- return numTlogReplicas;
+ return getNumReplicas(Replica.Type.TLOG);
}
/**
@@ -529,7 +529,14 @@ public Integer getNumTlogReplicas() {
* this collection was created with
*/
public Integer getNumPullReplicas() {
- return numPullReplicas;
+ return getNumReplicas(Replica.Type.PULL);
+ }
+
+ /**
+ * @return the number of replicas of a given type this collection was created with
+ */
+ public Integer getNumReplicas(Replica.Type type) {
+ return numReplicas.get(type);
}
public boolean isPerReplicaState() {
@@ -540,12 +547,14 @@ public PerReplicaStates getPerReplicaStates() {
return perReplicaStatesRef != null ? perReplicaStatesRef.get() : null;
}
+ @Deprecated
public int getExpectedReplicaCount(Replica.Type type, int def) {
- Integer result = null;
- if (type == Replica.Type.NRT) result = numNrtReplicas;
- if (type == Replica.Type.PULL) result = numPullReplicas;
- if (type == Replica.Type.TLOG) result = numTlogReplicas;
- return result == null ? def : result;
+ // def is kept for backwards compatibility.
+ return numReplicas.get(type);
+ }
+
+ public int getExpectedReplicaCount(Replica.Type type) {
+ return numReplicas.get(type);
}
/** JSON properties related to a collection's state. */
diff --git a/solr/solrj/src/java/org/apache/solr/common/cloud/Replica.java b/solr/solrj/src/java/org/apache/solr/common/cloud/Replica.java
index 72bb2879662..854b20fa815 100644
--- a/solr/solrj/src/java/org/apache/solr/common/cloud/Replica.java
+++ b/solr/solrj/src/java/org/apache/solr/common/cloud/Replica.java
@@ -26,6 +26,7 @@
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.solr.common.MapWriter;
+import org.apache.solr.common.util.StrUtils;
import org.apache.solr.common.util.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -125,17 +126,7 @@ public enum Type {
}
public static Type get(String name) {
- return name == null ? Type.NRT : Type.valueOf(name.toUpperCase(Locale.ROOT));
- }
-
- /**
- * Only certain replica types can become leaders
- *
- * @param type the type of a replica
- * @return true if that type is able to be leader, false otherwise
- */
- public static boolean isLeaderType(Type type) {
- return type == null || type == NRT || type == TLOG;
+ return StrUtils.isNullOrEmpty(name) ? NRT : Type.valueOf(name.toUpperCase(Locale.ROOT));
}
}
diff --git a/solr/solrj/src/java/org/apache/solr/common/cloud/ReplicaCount.java b/solr/solrj/src/java/org/apache/solr/common/cloud/ReplicaCount.java
new file mode 100644
index 00000000000..35c35c3ba76
--- /dev/null
+++ b/solr/solrj/src/java/org/apache/solr/common/cloud/ReplicaCount.java
@@ -0,0 +1,133 @@
+/*
+ * 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.util.Arrays;
+import java.util.EnumMap;
+import java.util.Locale;
+import java.util.stream.Collectors;
+import org.apache.solr.common.SolrException;
+
+/** Tracks the number of replicas per replica type. This class is mutable. */
+public final class ReplicaCount {
+ private final EnumMap countByType;
+
+ public ReplicaCount(Integer nrtReplicas, Integer tlogReplicas, Integer pullReplicas) {
+ this.countByType = new EnumMap<>(Replica.Type.class);
+ put(Replica.Type.NRT, nrtReplicas);
+ put(Replica.Type.TLOG, tlogReplicas);
+ put(Replica.Type.PULL, pullReplicas);
+ }
+
+ public static ReplicaCount empty() {
+ return new ReplicaCount(null, null, null);
+ }
+
+ public static ReplicaCount of(Replica.Type type, Integer count) {
+ ReplicaCount replicaCount = empty();
+ replicaCount.put(type, count);
+ return replicaCount;
+ }
+
+ /**
+ * Returns the number of replicas for a given type.
+ *
+ * @param type a replica type
+ */
+ public int get(Replica.Type type) {
+ return countByType.getOrDefault(type, 0);
+ }
+
+ /**
+ * Returns whether the number of replicas for a given type was explicitly defined.
+ *
+ * @param type a replica type
+ */
+ public boolean contains(Replica.Type type) {
+ return countByType.containsKey(type);
+ }
+
+ /**
+ * Defines the number of replicas for a given type.
+ *
+ * @param type a replica type
+ * @param count a number of replicas (if null, mark the value as missing)
+ */
+ public void put(Replica.Type type, Integer count) {
+ if (null != count && count >= 0) {
+ // If it considered as an error to put a negative value. In this case,
+ // we choose to fail gracefully by not changing anything.
+ countByType.put(type, count);
+ } else if (null == count) {
+ countByType.remove(type);
+ }
+ }
+
+ /**
+ * Increment the number of replicas for a given type.
+ *
+ * @param type a replica type
+ */
+ public void increment(Replica.Type type) {
+ put(type, get(type) + 1);
+ }
+
+ /**
+ * Decrement the number of replicas for a given type.
+ *
+ * @param type a replica type
+ */
+ public void decrement(Replica.Type type) {
+ put(type, get(type) - 1);
+ }
+
+ /** Returns the total number of replicas. */
+ public int total() {
+ return countByType.values().stream().reduce(Integer::sum).orElse(0);
+ }
+
+ /**
+ * Returns the first non-zero replica type that can be a leader.
+ *
+ * @throws SolrException if no such replica exists
+ */
+ public Replica.Type getLeaderType() {
+ for (Replica.Type type : Replica.Type.values()) {
+ if (type.leaderEligible && get(type) >= 1) {
+ return type;
+ }
+ }
+ throw new SolrException(
+ SolrException.ErrorCode.BAD_REQUEST,
+ "Unexpected number of replicas ("
+ + this
+ + "), there must be at least one leader-eligible replica");
+ }
+
+ /** Validate that there is at least one replica that can be a leader. */
+ public void validate() {
+ getLeaderType();
+ }
+
+ /** Returns a representation of this class which can be used for debugging. */
+ @Override
+ public String toString() {
+ return Arrays.stream(Replica.Type.values())
+ .map(t -> t.name().toLowerCase(Locale.ROOT) + "=" + get(t))
+ .collect(Collectors.joining(", "));
+ }
+}
diff --git a/solr/solrj/src/java/org/apache/solr/common/cloud/Slice.java b/solr/solrj/src/java/org/apache/solr/common/cloud/Slice.java
index 9a570646661..f1998b4264e 100644
--- a/solr/solrj/src/java/org/apache/solr/common/cloud/Slice.java
+++ b/solr/solrj/src/java/org/apache/solr/common/cloud/Slice.java
@@ -32,7 +32,6 @@
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;
import java.util.stream.Collectors;
-import org.apache.solr.common.cloud.Replica.Type;
import org.apache.solr.common.util.CollectionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -242,8 +241,8 @@ private Map makeReplicas(
private Replica findLeader() {
for (Replica replica : replicas.values()) {
if (replica.isLeader()) {
- assert replica.getType() == Type.TLOG || replica.getType() == Type.NRT
- : "Pull replica should not become leader!";
+ assert replica.getType().leaderEligible
+ : replica.getType().toString() + " replica should not become leader!";
return replica;
}
}
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/Http2SolrClientTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/Http2SolrClientTest.java
index dd9bf0ea927..20b96a782e7 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/Http2SolrClientTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/Http2SolrClientTest.java
@@ -929,6 +929,71 @@ public void testNoCredentials() {
}
}
+ @Test
+ public void testUseOptionalCredentials() {
+ // username foo, password with embedded colon separator is "expli:cit".
+ try (Http2SolrClient client =
+ new Http2SolrClient.Builder(getBaseUrl() + "/debug/foo")
+ .withOptionalBasicAuthCredentials("foo:expli:cit")
+ .build(); ) {
+ QueryRequest r = new QueryRequest(new SolrQuery("quick brown fox"));
+ try {
+ ignoreException("Error from server");
+ client.request(r);
+ } catch (Exception e) {
+ // expected
+ }
+ unIgnoreException("Error from server");
+ assertTrue(DebugServlet.headers.size() > 0);
+ String authorizationHeader = DebugServlet.headers.get("authorization");
+ assertNotNull(
+ "No authorization information in headers found. Headers: " + DebugServlet.headers,
+ authorizationHeader);
+ assertEquals(
+ "Basic "
+ + Base64.getEncoder()
+ .encodeToString("foo:expli:cit".getBytes(StandardCharsets.UTF_8)),
+ authorizationHeader);
+ }
+ }
+
+ @Test
+ public void testUseOptionalCredentialsWithNull() {
+ // username foo, password with embedded colon separator is "expli:cit".
+ try (Http2SolrClient client =
+ new Http2SolrClient.Builder(getBaseUrl() + "/debug/foo")
+ .withOptionalBasicAuthCredentials(null)
+ .build(); ) {
+ QueryRequest r = new QueryRequest(new SolrQuery("quick brown fox"));
+ try {
+ ignoreException("Error from server");
+ client.request(r);
+ } catch (Exception e) {
+ // expected
+ }
+ unIgnoreException("Error from server");
+ assertTrue(DebugServlet.headers.size() > 0);
+ String authorizationHeader = DebugServlet.headers.get("authorization");
+ assertNull(
+ "No authorization headers expected. Headers: " + DebugServlet.headers,
+ authorizationHeader);
+ }
+ }
+
+ @Test
+ public void testMalformedOptionalCredentials() {
+
+ expectThrowsAndMessage(
+ IllegalStateException.class,
+ () -> new Http2SolrClient.Builder().withOptionalBasicAuthCredentials("usernamepassword"),
+ "Invalid Authentication credential formatting. Provide username and password in the 'username:password' format.");
+
+ expectThrowsAndMessage(
+ IllegalStateException.class,
+ () -> new Http2SolrClient.Builder().withOptionalBasicAuthCredentials("username password"),
+ "Invalid Authentication credential formatting. Provide username and password in the 'username:password' format.");
+ }
+
@Test
public void testBadHttpFactory() {
System.setProperty(HttpClientUtil.SYS_PROP_HTTP_CLIENT_BUILDER_FACTORY, "FakeClassName");
diff --git a/solr/solrj/src/test/org/apache/solr/common/cloud/ReplicaCountTest.java b/solr/solrj/src/test/org/apache/solr/common/cloud/ReplicaCountTest.java
new file mode 100644
index 00000000000..44c371debad
--- /dev/null
+++ b/solr/solrj/src/test/org/apache/solr/common/cloud/ReplicaCountTest.java
@@ -0,0 +1,147 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.solr.common.SolrException;
+import org.junit.Test;
+
+/** Unit tests for {@link ReplicaCount}. */
+public class ReplicaCountTest {
+
+ @Test
+ public void testPutAndGet() {
+ ReplicaCount replicaCount = ReplicaCount.empty();
+ replicaCount.put(Replica.Type.NRT, 1);
+ replicaCount.put(Replica.Type.TLOG, 2);
+
+ assertTrue(replicaCount.contains(Replica.Type.NRT));
+ assertTrue(replicaCount.contains(Replica.Type.TLOG));
+ assertFalse(replicaCount.contains(Replica.Type.PULL));
+
+ assertEquals(1, replicaCount.get(Replica.Type.NRT));
+ assertEquals(2, replicaCount.get(Replica.Type.TLOG));
+ assertEquals(0, replicaCount.get(Replica.Type.PULL));
+ }
+
+ @Test
+ public void testPutNullValue() {
+ ReplicaCount replicaCount = ReplicaCount.of(Replica.Type.NRT, 1);
+ replicaCount.put(Replica.Type.NRT, null);
+
+ assertFalse(replicaCount.contains(Replica.Type.NRT));
+ assertEquals(0, replicaCount.get(Replica.Type.NRT));
+ }
+
+ @Test
+ public void testPutNegativeValue() {
+ ReplicaCount replicaCount = ReplicaCount.of(Replica.Type.NRT, -1);
+
+ assertFalse(replicaCount.contains(Replica.Type.NRT));
+ assertEquals(0, replicaCount.get(Replica.Type.NRT));
+ }
+
+ @Test
+ public void testIncrement() {
+ ReplicaCount replicaCount = ReplicaCount.empty();
+ replicaCount.put(Replica.Type.NRT, 1);
+ replicaCount.increment(Replica.Type.NRT);
+ replicaCount.increment(Replica.Type.TLOG);
+
+ assertTrue(replicaCount.contains(Replica.Type.NRT));
+ assertTrue(replicaCount.contains(Replica.Type.TLOG));
+ assertFalse(replicaCount.contains(Replica.Type.PULL));
+
+ assertEquals(2, replicaCount.get(Replica.Type.NRT));
+ assertEquals(1, replicaCount.get(Replica.Type.TLOG));
+ }
+
+ @Test
+ public void testDecrement() {
+ ReplicaCount replicaCount = ReplicaCount.empty();
+ replicaCount.put(Replica.Type.NRT, 1);
+ replicaCount.put(Replica.Type.PULL, 2);
+ replicaCount.decrement(Replica.Type.NRT);
+ replicaCount.decrement(Replica.Type.PULL);
+
+ assertTrue(replicaCount.contains(Replica.Type.NRT));
+ assertTrue(replicaCount.contains(Replica.Type.PULL));
+
+ assertEquals(0, replicaCount.get(Replica.Type.NRT));
+ assertEquals(1, replicaCount.get(Replica.Type.PULL));
+ }
+
+ @Test
+ public void testDecrementZero() {
+ ReplicaCount replicaCount = ReplicaCount.empty();
+ replicaCount.decrement(Replica.Type.NRT);
+
+ assertFalse(replicaCount.contains(Replica.Type.NRT));
+ assertEquals(0, replicaCount.get(Replica.Type.NRT));
+ }
+
+ @Test
+ public void testTotal() {
+ ReplicaCount replicaCount = ReplicaCount.empty();
+ replicaCount.put(Replica.Type.NRT, 1);
+ replicaCount.put(Replica.Type.TLOG, 2);
+
+ assertEquals(3, replicaCount.total());
+ }
+
+ @Test
+ public void testToString() {
+ ReplicaCount replicaCount = ReplicaCount.empty();
+ replicaCount.put(Replica.Type.NRT, 1);
+ replicaCount.put(Replica.Type.TLOG, 2);
+
+ assertEquals("nrt=1, tlog=2, pull=0", replicaCount.toString());
+ }
+
+ @Test
+ public void testValidate() {
+ ReplicaCount replicaCountNrtOnly = ReplicaCount.of(Replica.Type.NRT, 1);
+ replicaCountNrtOnly.validate(); // Should not throw
+
+ ReplicaCount replicaCountPullOnly = ReplicaCount.of(Replica.Type.PULL, 1);
+ Throwable t = assertThrows(SolrException.class, replicaCountPullOnly::validate);
+ assertEquals(
+ "Unexpected number of replicas (nrt=0, tlog=0, pull=1), there must "
+ + "be at least one leader-eligible replica",
+ t.getMessage());
+ }
+
+ @Test
+ public void testGetLeaderType() {
+ // With only 1 NRT, NRT should be returned.
+ ReplicaCount replicaCount = ReplicaCount.of(Replica.Type.NRT, 1);
+ assertEquals(Replica.Type.NRT, replicaCount.getLeaderType());
+
+ // With 1 NRT and 1 TLOG, NRT is still returned as the leader type, as it comes
+ // first in the order of preference.
+ replicaCount.increment(Replica.Type.TLOG);
+ assertEquals(Replica.Type.NRT, replicaCount.getLeaderType());
+
+ // With only 1 TLOG, TLOG should now be returned.
+ replicaCount.decrement(Replica.Type.NRT);
+ assertEquals(Replica.Type.TLOG, replicaCount.getLeaderType());
+ }
+}
diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/IpTables.java b/solr/test-framework/src/java/org/apache/solr/cloud/IpTables.java
index 33678bd09aa..901813ae913 100644
--- a/solr/test-framework/src/java/org/apache/solr/cloud/IpTables.java
+++ b/solr/test-framework/src/java/org/apache/solr/cloud/IpTables.java
@@ -54,7 +54,7 @@ public static void unblockPort(int port) throws IOException, InterruptedExceptio
public static void unblockAllPorts() throws IOException, InterruptedException {
if (ENABLED) {
log.info("Unblocking any ports previously blocked with iptables...");
- final Integer[] ports = BLOCK_PORTS.toArray(new Integer[BLOCK_PORTS.size()]);
+ final Integer[] ports = BLOCK_PORTS.toArray(new Integer[0]);
for (Integer port : ports) {
IpTables.unblockPort(port);
}
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 a5ab7c6471c..ac837002815 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
@@ -344,7 +344,7 @@ public MiniSolrCloudCluster(
}
private void waitForAllNodes(int numServers, int timeoutSeconds)
- throws IOException, InterruptedException, TimeoutException {
+ throws InterruptedException, TimeoutException {
log.info("waitForAllNodes: numServers={}", numServers);
int numRunning;
@@ -668,7 +668,7 @@ public void shutdown() throws Exception {
IOUtils.closeQuietly(c);
});
solrClientByCollection.clear();
- ;
+
List> shutdowns = new ArrayList<>(jettys.size());
for (final JettySolrRunner jetty : jettys) {
shutdowns.add(() -> stopJettySolrRunner(jetty));
@@ -768,13 +768,6 @@ public CloudLegacySolrClient.Builder basicSolrClientBuilder() {
.withConnectionTimeout(15000);
}
- private static String getHostContextSuitableForServletContext(String ctx) {
- if (ctx == null || ctx.isEmpty()) ctx = "/solr";
- if (ctx.endsWith("/")) ctx = ctx.substring(0, ctx.length() - 1);
- if (!ctx.startsWith("/")) ctx = "/" + ctx;
- return ctx;
- }
-
private Exception checkForExceptions(String message, Collection> futures)
throws InterruptedException {
Exception parsed = new Exception(message);
@@ -822,6 +815,7 @@ public void expireZkSession(JettySolrRunner jetty) {
}
}
+ // Currently not used ;-(
public synchronized void injectChaos(Random random) throws Exception {
// sometimes we restart one of the jetty nodes
@@ -951,11 +945,7 @@ public static CollectionStatePredicate expectedShardsAndActiveReplicas(
}
}
}
- if (activeReplicas == expectedReplicas) {
- return true;
- }
-
- return false;
+ return activeReplicas == expectedReplicas;
};
}
diff --git a/versions.lock b/versions.lock
index dd3afc7b6fe..919453ac3b5 100644
--- a/versions.lock
+++ b/versions.lock
@@ -6,19 +6,19 @@ com.carrotsearch:hppc:0.9.1 (2 constraints: ad0fc9a6)
com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.1 (2 constraints: cf1501e2)
com.cybozu.labs:langdetect:1.1-20120112 (1 constraints: 5c066d5e)
com.epam:parso:2.0.14 (1 constraints: 8e0c750e)
-com.fasterxml.jackson:jackson-bom:2.15.2 (12 constraints: 4ef8ad55)
-com.fasterxml.jackson.core:jackson-annotations:2.15.2 (10 constraints: 9cbe6d17)
-com.fasterxml.jackson.core:jackson-core:2.15.2 (13 constraints: 4302e328)
-com.fasterxml.jackson.core:jackson-databind:2.15.2 (18 constraints: 8d63878e)
-com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.15.2 (2 constraints: 631c9af1)
-com.fasterxml.jackson.dataformat:jackson-dataformat-smile:2.15.2 (1 constraints: ba0eab66)
-com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.15.2 (2 constraints: a724cae0)
+com.fasterxml.jackson:jackson-bom:2.15.3 (12 constraints: 5af84666)
+com.fasterxml.jackson.core:jackson-annotations:2.15.3 (10 constraints: a2bea21f)
+com.fasterxml.jackson.core:jackson-core:2.15.3 (13 constraints: 4c026138)
+com.fasterxml.jackson.core:jackson-databind:2.15.3 (18 constraints: 96637da4)
+com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.15.3 (2 constraints: 641c9bf1)
+com.fasterxml.jackson.dataformat:jackson-dataformat-smile:2.15.3 (1 constraints: bb0eac66)
+com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.15.3 (2 constraints: a82409e1)
com.fasterxml.woodstox:woodstox-core:6.5.1 (2 constraints: a0239c84)
com.github.ben-manes.caffeine:caffeine:3.1.8 (1 constraints: 0e050536)
com.github.jai-imageio:jai-imageio-core:1.4.0 (1 constraints: 5c0ced01)
com.github.junrar:junrar:7.5.3 (1 constraints: 660c1102)
com.github.openjson:openjson:1.0.12 (1 constraints: 8b0c6d0e)
-com.github.spotbugs:spotbugs-annotations:4.7.3 (1 constraints: 10051736)
+com.github.spotbugs:spotbugs-annotations:4.8.0 (1 constraints: 0e051736)
com.github.stephenc.jcip:jcip-annotations:1.0-1 (3 constraints: c71d2c87)
com.github.virtuald:curvesapi:1.07 (1 constraints: 9e0ac7c0)
com.google.android:annotations:4.1.1.4 (2 constraints: b918820a)
@@ -42,17 +42,16 @@ com.google.cloud:google-cloud-core-grpc:2.23.0 (1 constraints: 1b1002a6)
com.google.cloud:google-cloud-core-http:2.23.0 (1 constraints: 1b1002a6)
com.google.cloud:google-cloud-storage:2.27.0 (2 constraints: d71c8a27)
com.google.code.gson:gson:2.10.1 (7 constraints: 005f69b0)
-com.google.errorprone:error_prone_annotations:2.22.0 (11 constraints: 6e891f5a)
+com.google.errorprone:error_prone_annotations:2.23.0 (11 constraints: b286c424)
com.google.guava:failureaccess:1.0.1 (2 constraints: f9199e37)
-com.google.guava:guava:32.1.2-jre (27 constraints: 498a9992)
-com.google.guava:guava-parent:32.1.2-jre (1 constraints: b80ba5eb)
+com.google.guava:guava:32.1.3-jre (27 constraints: 4a8a1197)
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava (2 constraints: 4b35b0a0)
com.google.http-client:google-http-client:1.43.3 (11 constraints: 3fbf96b4)
com.google.http-client:google-http-client-apache-v2:1.43.3 (2 constraints: b820e775)
com.google.http-client:google-http-client-appengine:1.43.3 (2 constraints: de20d381)
com.google.http-client:google-http-client-gson:1.43.3 (7 constraints: 6270684c)
com.google.http-client:google-http-client-jackson2:1.43.3 (1 constraints: 1f1007a6)
-com.google.j2objc:j2objc-annotations:2.8 (4 constraints: 87367e23)
+com.google.j2objc:j2objc-annotations:2.8 (3 constraints: 132a2f47)
com.google.oauth-client:google-oauth-client:1.34.1 (2 constraints: b520b575)
com.google.protobuf:protobuf-java:3.24.0 (11 constraints: d6952db6)
com.google.protobuf:protobuf-java-util:3.23.2 (3 constraints: 332b702b)
@@ -88,68 +87,68 @@ edu.ucar:httpservices:4.5.5 (2 constraints: 8f122834)
edu.ucar:netcdf4:4.5.5 (1 constraints: 650c0402)
edu.ucar:udunits:4.5.5 (1 constraints: 2b06034e)
edu.usc.ir:sentiment-analysis-parser:0.1 (1 constraints: fa0b50e9)
-io.dropwizard.metrics:metrics-annotation:4.2.20 (1 constraints: 30106db0)
-io.dropwizard.metrics:metrics-core:4.2.20 (6 constraints: 015254da)
-io.dropwizard.metrics:metrics-graphite:4.2.20 (1 constraints: 3a05413b)
-io.dropwizard.metrics:metrics-jetty10:4.2.20 (1 constraints: 3a05413b)
-io.dropwizard.metrics:metrics-jmx:4.2.20 (1 constraints: 3a05413b)
-io.dropwizard.metrics:metrics-jvm:4.2.20 (1 constraints: 3a05413b)
-io.grpc:grpc-alts:1.58.0 (1 constraints: 211012a6)
-io.grpc:grpc-api:1.58.0 (6 constraints: 4c40f8d0)
-io.grpc:grpc-auth:1.58.0 (1 constraints: 211012a6)
-io.grpc:grpc-context:1.58.0 (4 constraints: a32a5d1e)
-io.grpc:grpc-core:1.58.0 (3 constraints: 4721ad1f)
-io.grpc:grpc-googleapis:1.58.0 (1 constraints: 211012a6)
-io.grpc:grpc-grpclb:1.58.0 (1 constraints: 211012a6)
-io.grpc:grpc-netty:1.58.0 (1 constraints: 4005513b)
-io.grpc:grpc-netty-shaded:1.58.0 (1 constraints: 211012a6)
-io.grpc:grpc-protobuf:1.58.0 (2 constraints: 601503d8)
-io.grpc:grpc-protobuf-lite:1.58.0 (2 constraints: 2c1a134e)
-io.grpc:grpc-rls:1.58.0 (1 constraints: 211012a6)
-io.grpc:grpc-services:1.58.0 (1 constraints: 211012a6)
-io.grpc:grpc-stub:1.58.0 (2 constraints: 601503d8)
-io.grpc:grpc-util:1.58.0 (3 constraints: 2d1a087d)
-io.grpc:grpc-xds:1.58.0 (1 constraints: 211012a6)
-io.netty:netty-buffer:4.1.99.Final (10 constraints: de999d1c)
-io.netty:netty-codec:4.1.99.Final (5 constraints: 79452589)
-io.netty:netty-codec-http:4.1.99.Final (3 constraints: 6124fbef)
-io.netty:netty-codec-http2:4.1.99.Final (1 constraints: ea0a80cb)
-io.netty:netty-codec-socks:4.1.99.Final (1 constraints: 190fce6c)
-io.netty:netty-common:4.1.99.Final (12 constraints: 60b319a3)
-io.netty:netty-handler:4.1.99.Final (3 constraints: 782b0b3f)
-io.netty:netty-handler-proxy:4.1.99.Final (1 constraints: ea0a80cb)
-io.netty:netty-resolver:4.1.99.Final (2 constraints: 621a2533)
+io.dropwizard.metrics:metrics-annotation:4.2.21 (1 constraints: 31106eb0)
+io.dropwizard.metrics:metrics-core:4.2.21 (6 constraints: 0652dcdc)
+io.dropwizard.metrics:metrics-graphite:4.2.21 (1 constraints: 3b05423b)
+io.dropwizard.metrics:metrics-jetty10:4.2.21 (1 constraints: 3b05423b)
+io.dropwizard.metrics:metrics-jmx:4.2.21 (1 constraints: 3b05423b)
+io.dropwizard.metrics:metrics-jvm:4.2.21 (1 constraints: 3b05423b)
+io.grpc:grpc-alts:1.59.0 (1 constraints: 211012a6)
+io.grpc:grpc-api:1.59.0 (6 constraints: 514038d2)
+io.grpc:grpc-auth:1.59.0 (1 constraints: 211012a6)
+io.grpc:grpc-context:1.59.0 (4 constraints: a52af91e)
+io.grpc:grpc-core:1.59.0 (3 constraints: 4921ce1f)
+io.grpc:grpc-googleapis:1.59.0 (1 constraints: 211012a6)
+io.grpc:grpc-grpclb:1.59.0 (1 constraints: 211012a6)
+io.grpc:grpc-netty:1.59.0 (1 constraints: 4105543b)
+io.grpc:grpc-netty-shaded:1.59.0 (1 constraints: 211012a6)
+io.grpc:grpc-protobuf:1.59.0 (2 constraints: 611535d8)
+io.grpc:grpc-protobuf-lite:1.59.0 (2 constraints: 2d1a164e)
+io.grpc:grpc-rls:1.59.0 (1 constraints: 211012a6)
+io.grpc:grpc-services:1.59.0 (1 constraints: 211012a6)
+io.grpc:grpc-stub:1.59.0 (2 constraints: 611535d8)
+io.grpc:grpc-util:1.59.0 (3 constraints: 301a697d)
+io.grpc:grpc-xds:1.59.0 (1 constraints: 211012a6)
+io.netty:netty-buffer:4.1.100.Final (10 constraints: 149b2024)
+io.netty:netty-codec:4.1.100.Final (5 constraints: 1446fa84)
+io.netty:netty-codec-http:4.1.100.Final (3 constraints: be24283d)
+io.netty:netty-codec-http2:4.1.100.Final (1 constraints: ee0a9ccb)
+io.netty:netty-codec-socks:4.1.100.Final (1 constraints: 380f8f7a)
+io.netty:netty-common:4.1.100.Final (12 constraints: d4b4a541)
+io.netty:netty-handler:4.1.100.Final (3 constraints: b62b0a76)
+io.netty:netty-handler-proxy:4.1.100.Final (1 constraints: ee0a9ccb)
+io.netty:netty-resolver:4.1.100.Final (2 constraints: a01a785c)
io.netty:netty-tcnative-boringssl-static:2.0.61.Final (1 constraints: d10fc38e)
io.netty:netty-tcnative-classes:2.0.61.Final (1 constraints: d113ea5d)
-io.netty:netty-transport:4.1.99.Final (9 constraints: 268c2655)
-io.netty:netty-transport-classes-epoll:4.1.99.Final (1 constraints: b6121b1f)
-io.netty:netty-transport-native-epoll:4.1.99.Final (1 constraints: da0f128f)
-io.netty:netty-transport-native-unix-common:4.1.99.Final (4 constraints: 643d7197)
+io.netty:netty-transport:4.1.100.Final (9 constraints: 3d8d8fa3)
+io.netty:netty-transport-classes-epoll:4.1.100.Final (1 constraints: d5127930)
+io.netty:netty-transport-native-epoll:4.1.100.Final (1 constraints: da0f128f)
+io.netty:netty-transport-native-unix-common:4.1.100.Final (4 constraints: c53d4729)
io.opencensus:opencensus-api:0.31.1 (5 constraints: 924d4692)
io.opencensus:opencensus-contrib-http-util:0.31.1 (3 constraints: 7232a9fc)
io.opencensus:opencensus-proto:0.2.0 (1 constraints: e60fd595)
-io.opentelemetry:opentelemetry-api:1.30.1 (10 constraints: 28b70389)
-io.opentelemetry:opentelemetry-api-events:1.30.1-alpha (2 constraints: 252f227e)
-io.opentelemetry:opentelemetry-bom:1.30.1 (1 constraints: 3705323b)
-io.opentelemetry:opentelemetry-context:1.30.1 (2 constraints: 1f1f02b4)
-io.opentelemetry:opentelemetry-exporter-common:1.30.1 (3 constraints: 413df2a8)
-io.opentelemetry:opentelemetry-exporter-otlp:1.30.1 (1 constraints: 920fe383)
-io.opentelemetry:opentelemetry-exporter-otlp-common:1.30.1 (2 constraints: 4a23451b)
-io.opentelemetry:opentelemetry-exporter-sender-okhttp:1.30.1 (2 constraints: 4a23451b)
-io.opentelemetry:opentelemetry-extension-incubator:1.30.1-alpha (1 constraints: ed14ae96)
-io.opentelemetry:opentelemetry-sdk:1.30.1 (4 constraints: 5956ccbc)
-io.opentelemetry:opentelemetry-sdk-common:1.30.1 (6 constraints: 696c0959)
-io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.30.1 (1 constraints: 920fe383)
-io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.30.1 (3 constraints: 913ce021)
-io.opentelemetry:opentelemetry-sdk-logs:1.30.1 (3 constraints: df3251b0)
-io.opentelemetry:opentelemetry-sdk-metrics:1.30.1 (3 constraints: df3251b0)
-io.opentelemetry:opentelemetry-sdk-trace:1.30.1 (3 constraints: df3251b0)
+io.opentelemetry:opentelemetry-api:1.31.0 (10 constraints: 28b71789)
+io.opentelemetry:opentelemetry-api-events:1.31.0-alpha (2 constraints: 252f267e)
+io.opentelemetry:opentelemetry-bom:1.31.0 (1 constraints: 3705343b)
+io.opentelemetry:opentelemetry-context:1.31.0 (2 constraints: 1f1f06b4)
+io.opentelemetry:opentelemetry-exporter-common:1.31.0 (3 constraints: 413df8a8)
+io.opentelemetry:opentelemetry-exporter-otlp:1.31.0 (1 constraints: 920fe583)
+io.opentelemetry:opentelemetry-exporter-otlp-common:1.31.0 (2 constraints: 4a23491b)
+io.opentelemetry:opentelemetry-exporter-sender-okhttp:1.31.0 (2 constraints: 4a23491b)
+io.opentelemetry:opentelemetry-extension-incubator:1.31.0-alpha (1 constraints: ed14b096)
+io.opentelemetry:opentelemetry-sdk:1.31.0 (4 constraints: 5956d4bc)
+io.opentelemetry:opentelemetry-sdk-common:1.31.0 (6 constraints: 696c1559)
+io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.31.0 (1 constraints: 920fe583)
+io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.31.0 (3 constraints: 913ce621)
+io.opentelemetry:opentelemetry-sdk-logs:1.31.0 (3 constraints: df3257b0)
+io.opentelemetry:opentelemetry-sdk-metrics:1.31.0 (3 constraints: df3257b0)
+io.opentelemetry:opentelemetry-sdk-trace:1.31.0 (3 constraints: df3257b0)
io.perfmark:perfmark-api:0.26.0 (3 constraints: 21212b16)
io.prometheus:simpleclient:0.16.0 (3 constraints: 9d257513)
io.prometheus:simpleclient_common:0.16.0 (1 constraints: 1a1139c0)
io.prometheus:simpleclient_httpserver:0.16.0 (1 constraints: 3905353b)
io.sgr:s2-geometry-library-java:1.0.0 (1 constraints: b0107fb9)
-io.swagger.core.v3:swagger-annotations:2.2.16 (1 constraints: 3d05393b)
+io.swagger.core.v3:swagger-annotations:2.2.17 (1 constraints: 3e053a3b)
jakarta.activation:jakarta.activation-api:1.2.2 (1 constraints: 8e0f4791)
jakarta.annotation:jakarta.annotation-api:1.3.5 (4 constraints: d740f9a9)
jakarta.validation:jakarta.validation-api:2.0.2 (1 constraints: fd10b6c3)
@@ -202,13 +201,13 @@ org.apache.kerby:kerby-asn1:1.0.1 (1 constraints: fd0be9f4)
org.apache.kerby:kerby-config:1.0.1 (4 constraints: 4d3182b9)
org.apache.kerby:kerby-pkix:1.0.1 (1 constraints: 710bfce4)
org.apache.kerby:kerby-util:1.0.1 (2 constraints: 6518bdb6)
-org.apache.logging.log4j:log4j-1.2-api:2.20.0 (1 constraints: 3605333b)
-org.apache.logging.log4j:log4j-api:2.20.0 (10 constraints: ea7d264d)
-org.apache.logging.log4j:log4j-core:2.20.0 (5 constraints: 82556aef)
-org.apache.logging.log4j:log4j-jul:2.20.0 (1 constraints: 3605333b)
-org.apache.logging.log4j:log4j-layout-template-json:2.20.0 (1 constraints: 3605333b)
-org.apache.logging.log4j:log4j-slf4j2-impl:2.20.0 (1 constraints: 3605333b)
-org.apache.logging.log4j:log4j-web:2.20.0 (1 constraints: 3605333b)
+org.apache.logging.log4j:log4j-1.2-api:2.21.0 (1 constraints: 3705363b)
+org.apache.logging.log4j:log4j-api:2.21.0 (10 constraints: f07d3453)
+org.apache.logging.log4j:log4j-core:2.21.0 (5 constraints: 5f510091)
+org.apache.logging.log4j:log4j-jul:2.21.0 (1 constraints: 3705363b)
+org.apache.logging.log4j:log4j-layout-template-json:2.21.0 (1 constraints: 3705363b)
+org.apache.logging.log4j:log4j-slf4j2-impl:2.21.0 (1 constraints: 3705363b)
+org.apache.logging.log4j:log4j-web:2.21.0 (1 constraints: 3705363b)
org.apache.lucene:lucene-analysis-common:9.8.0 (10 constraints: fc9e4474)
org.apache.lucene:lucene-analysis-icu:9.8.0 (1 constraints: 13053036)
org.apache.lucene:lucene-analysis-kuromoji:9.8.0 (1 constraints: 13053036)
@@ -271,10 +270,10 @@ org.carrot2:morfologik-fsa:2.1.9 (1 constraints: db0d9c36)
org.carrot2:morfologik-polish:2.1.9 (1 constraints: d312541e)
org.carrot2:morfologik-stemming:2.1.9 (2 constraints: d81fb300)
org.ccil.cowan.tagsoup:tagsoup:1.2.1 (1 constraints: 5b0ce801)
-org.checkerframework:checker-qual:3.37.0 (5 constraints: 0f491d14)
+org.checkerframework:checker-qual:3.37.0 (5 constraints: 5c4694ee)
org.codehaus.janino:commons-compiler:3.1.9 (2 constraints: 3119a8ec)
org.codehaus.janino:janino:3.1.9 (1 constraints: 650dbd2c)
-org.codehaus.woodstox:stax2-api:4.2.1 (2 constraints: 36152eaf)
+org.codehaus.woodstox:stax2-api:4.2.2 (2 constraints: 37155caf)
org.codelibs:jhighlight:1.1.0 (1 constraints: 590ce401)
org.conscrypt:conscrypt-openjdk-uber:2.5.2 (1 constraints: ed0fea95)
org.eclipse.jetty:jetty-alpn-client:10.0.17 (3 constraints: f72e2e61)
@@ -283,15 +282,15 @@ org.eclipse.jetty:jetty-alpn-java-server:10.0.17 (1 constraints: 6b059340)
org.eclipse.jetty:jetty-alpn-server:10.0.17 (2 constraints: f9167949)
org.eclipse.jetty:jetty-client:10.0.17 (2 constraints: 231b136f)
org.eclipse.jetty:jetty-deploy:10.0.17 (1 constraints: 6b059340)
-org.eclipse.jetty:jetty-http:10.0.17 (6 constraints: 814f3f91)
-org.eclipse.jetty:jetty-io:10.0.17 (9 constraints: c67d94ee)
+org.eclipse.jetty:jetty-http:10.0.17 (6 constraints: 824feb91)
+org.eclipse.jetty:jetty-io:10.0.17 (9 constraints: c77dc8ef)
org.eclipse.jetty:jetty-jmx:10.0.17 (1 constraints: 6b059340)
org.eclipse.jetty:jetty-rewrite:10.0.17 (1 constraints: 6b059340)
org.eclipse.jetty:jetty-security:10.0.17 (2 constraints: c0137379)
-org.eclipse.jetty:jetty-server:10.0.17 (7 constraints: e96d982b)
+org.eclipse.jetty:jetty-server:10.0.17 (7 constraints: ea6d9a2c)
org.eclipse.jetty:jetty-servlet:10.0.17 (2 constraints: 3a139d61)
org.eclipse.jetty:jetty-servlets:10.0.17 (1 constraints: 6b059340)
-org.eclipse.jetty:jetty-util:10.0.17 (9 constraints: c081b69e)
+org.eclipse.jetty:jetty-util:10.0.17 (9 constraints: c181f79f)
org.eclipse.jetty:jetty-webapp:10.0.17 (2 constraints: 48132562)
org.eclipse.jetty:jetty-xml:10.0.17 (3 constraints: 1721b2bb)
org.eclipse.jetty.http2:http2-client:10.0.17 (2 constraints: 231b136f)
@@ -319,7 +318,7 @@ org.glassfish.jersey.inject:jersey-hk2:2.39.1 (1 constraints: 4105533b)
org.glassfish.jersey.media:jersey-media-json-jackson:2.39.1 (1 constraints: 4105533b)
org.hamcrest:hamcrest:2.2 (5 constraints: 125db3af)
org.hamcrest:hamcrest-core:2.2 (1 constraints: cc05fe3f)
-org.immutables:value-annotations:2.9.3 (1 constraints: 10051336)
+org.immutables:value-annotations:2.10.0 (1 constraints: 35052f3b)
org.itadaki:bzip2:0.9.1 (2 constraints: bd0c4b2c)
org.javassist:javassist:3.29.0-GA (1 constraints: 2e1126f1)
org.jctools:jctools-core:4.0.1 (1 constraints: 07050036)
@@ -329,7 +328,7 @@ org.jetbrains.kotlin:kotlin-stdlib:1.8.22 (5 constraints: 7a4c42d2)
org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 (3 constraints: 3a2cc871)
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0 (1 constraints: b01019c2)
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0 (4 constraints: dd389ae5)
-org.junit:junit-bom:5.9.1 (7 constraints: 1974131b)
+org.junit:junit-bom:5.9.1 (6 constraints: 526217ff)
org.junit.jupiter:junit-jupiter-api:5.9.1 (5 constraints: 5c467228)
org.junit.platform:junit-platform-commons:1.9.1 (3 constraints: ee29f32b)
org.locationtech.jts:jts-core:1.19.0 (2 constraints: a31de760)
@@ -348,7 +347,7 @@ org.ow2.asm:asm-commons:7.2 (1 constraints: 6b0f7267)
org.ow2.asm:asm-tree:7.2 (2 constraints: 2f14468c)
org.quicktheories:quicktheories:0.26 (1 constraints: dc04f530)
org.reactivestreams:reactive-streams:1.0.4 (3 constraints: 3f2b77fd)
-org.semver4j:semver4j:5.2.1 (1 constraints: 0a050b36)
+org.semver4j:semver4j:5.2.2 (1 constraints: 0b050c36)
org.slf4j:jcl-over-slf4j:2.0.9 (3 constraints: cf17cfa6)
org.slf4j:jul-to-slf4j:2.0.9 (3 constraints: 29286349)
org.slf4j:slf4j-api:2.0.9 (59 constraints: dd104075)
@@ -392,11 +391,11 @@ com.amazonaws:aws-java-sdk-core:1.12.501 (2 constraints: b01a32b3)
com.amazonaws:aws-java-sdk-kms:1.12.501 (1 constraints: 060dbd37)
com.amazonaws:aws-java-sdk-s3:1.12.501 (1 constraints: 10136f43)
com.amazonaws:jmespath-java:1.12.501 (2 constraints: b01a32b3)
-com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.2 (2 constraints: aa195413)
-com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.15.2 (3 constraints: fc2e56b4)
-com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2 (4 constraints: 6d485635)
-com.fasterxml.jackson.module:jackson-module-kotlin:2.15.2 (2 constraints: a91d3a60)
-com.fasterxml.jackson.module:jackson-module-parameter-names:2.15.2 (2 constraints: 0c243f82)
+com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.3 (2 constraints: ab195513)
+com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.15.3 (3 constraints: fd2e92b4)
+com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.3 (4 constraints: 6e48d735)
+com.fasterxml.jackson.module:jackson-module-kotlin:2.15.3 (2 constraints: aa1d6760)
+com.fasterxml.jackson.module:jackson-module-parameter-names:2.15.3 (2 constraints: 0d247b82)
com.google.cloud:google-cloud-nio:0.127.3 (1 constraints: 9a0e5e6c)
com.nimbusds:content-type:2.2 (1 constraints: d80b68eb)
com.nimbusds:lang-tag:1.7 (1 constraints: dc0b6aeb)
@@ -406,7 +405,7 @@ com.squareup.okhttp3:mockwebserver:4.11.0 (1 constraints: ec0e9471)
io.github.microutils:kotlin-logging:3.0.5 (1 constraints: be0ea162)
io.github.microutils:kotlin-logging-jvm:3.0.5 (1 constraints: 810f8b7c)
io.micrometer:micrometer-core:1.9.12 (1 constraints: fe162919)
-io.opentelemetry:opentelemetry-sdk-testing:1.30.1 (1 constraints: 920fe383)
+io.opentelemetry:opentelemetry-sdk-testing:1.31.0 (1 constraints: 920fe583)
jakarta.servlet:jakarta.servlet-api:4.0.4 (4 constraints: 5b6ed66b)
jakarta.websocket:jakarta.websocket-api:1.1.2 (1 constraints: 92155ab9)
javax.inject:javax.inject:1 (1 constraints: 7a0df617)
diff --git a/versions.props b/versions.props
index 3fa56598e34..775683e91e3 100644
--- a/versions.props
+++ b/versions.props
@@ -5,13 +5,13 @@ com.adobe.testing:s3mock-junit4=2.17.0
com.carrotsearch.randomizedtesting:*=2.8.1
com.carrotsearch:hppc=0.9.1
com.cybozu.labs:langdetect=1.1-20120112
-com.fasterxml.jackson:jackson-bom=2.15.2
+com.fasterxml.jackson:jackson-bom=2.15.3
com.github.ben-manes.caffeine:caffeine=3.1.8
-com.github.spotbugs:*=4.7.3
+com.github.spotbugs:*=4.8.0
com.github.stephenc.jcip:jcip-annotations=1.0-1
com.google.cloud:google-cloud-bom=0.204.0
-com.google.errorprone:*=2.22.0
-com.google.guava:guava=32.1.2-jre
+com.google.errorprone:*=2.23.0
+com.google.guava:guava=32.1.3-jre
com.google.re2j:re2j=1.7
com.jayway.jsonpath:json-path=2.8.0
com.lmax:disruptor=3.4.4
@@ -20,12 +20,12 @@ commons-cli:commons-cli=1.5.0
commons-codec:commons-codec=1.16.0
commons-collections:commons-collections=3.2.2
commons-io:commons-io=2.14.0
-io.dropwizard.metrics:*=4.2.20
-io.grpc:grpc-*=1.58.0
-io.netty:*=4.1.99.Final
-io.opentelemetry:opentelemetry-bom=1.30.1
+io.dropwizard.metrics:*=4.2.21
+io.grpc:grpc-*=1.59.0
+io.netty:*=4.1.100.Final
+io.opentelemetry:opentelemetry-bom=1.31.0
io.prometheus:*=0.16.0
-io.swagger.core.v3:*=2.2.16
+io.swagger.core.v3:*=2.2.17
jakarta.ws.rs:jakarta.ws.rs-api=2.1.6
junit:junit=4.13.2
net.sourceforge.argparse4j:argparse4j=0.9.0
@@ -46,27 +46,27 @@ org.apache.httpcomponents:httpclient=4.5.14
org.apache.httpcomponents:httpcore=4.4.16
org.apache.httpcomponents:httpmime=4.5.14
org.apache.kerby:*=1.0.1
-org.apache.logging.log4j:*=2.20.0
+org.apache.logging.log4j:*=2.21.0
org.apache.lucene:*=9.8.0
org.apache.tika:*=1.28.5
org.apache.tomcat:annotations-api=6.0.53
org.apache.zookeeper:*=3.9.1
org.bitbucket.b_c:jose4j=0.9.3
org.carrot2:carrot2-core=4.5.1
-org.codehaus.woodstox:stax2-api=4.2.1
+org.codehaus.woodstox:stax2-api=4.2.2
org.eclipse.jetty*:*=10.0.17
org.eclipse.jetty.toolchain:jetty-servlet-api=4.0.6
org.glassfish.hk2*:*=2.6.1
org.glassfish.jersey*:*=2.39.1
org.hamcrest:*=2.2
org.hsqldb:hsqldb=2.7.2
-org.immutables:value-annotations=2.9.3
+org.immutables:value-annotations=2.10.0
org.jctools:jctools-core=4.0.1
org.mockito:mockito*=5.5.0
org.openjdk.jmh:*=1.37
org.osgi:osgi.annotation=8.1.0
org.quicktheories:quicktheories=0.26
-org.semver4j:semver4j=5.2.1
+org.semver4j:semver4j=5.2.2
org.slf4j:*=2.0.9
org.xerial.snappy:snappy-java=1.1.10.5
software.amazon.awssdk:*=2.20.155