You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by ds...@apache.org on 2026/09/09 14:14:54 UTC
(solr) branch branch_10x updated (883e98b01db -> 7eb62d0ab67)
This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a change to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
from 883e98b01db SOLR-18420: Improve ZookeeperRead path normalization
new dc954d8e947 Tracing & audit: HttpSolrCall.getQueryParams (#4870)
new 1031b8ee439 SOLR-18406: Restart replication after index generation expires (#4820)
new f66fd9307a9 prevent warning in gradle console output about plugin name (#4885)
new f650e7e3d7b Review and tidy solr/modules/language-models code (#4836)
new 21e8d021e78 DistributedUpdateProcessor: expose isLeader, setupRequest (#4878)
new 5aca7607cbd SOLR-18411: CrossDC: Configure security properties in KafkaMirroringSink initConsumer. (#4883)
new 07c253a4d04 SOLR-18418: Fix complement()/intersect() with asymmetric on= (#4873)
new 6482df91420 SOLR-18335 : SPLITSHARD now supports router.field with docValues (#4717)
new 1079929502d SOLR-18390: test-framework SolrClient accessor improvements (#4778)
new 5c3ae79fbde HttpSolrClient add withTheseParamNamesInTheUrl defaults (#4871)
new dad6ee50e2b SOLR-18364: Remove deprecated SolrCore.isWriterLocked(Directory) (#4784)
new a8bc5486572 SOLR-504: a missing or blank "pf" must not add an empty/no-op boolean clause to the query (#4891)
new a11fc98e1b2 SOLR-18394: Simplify JettyConfig construction (#4786)
new ca957478839 SOLR-18412: CrossDC - ZooKeeper /crossdc.properties no longer overrides solr.crossdc.kafka.* sysprops or env vars (#4884)
new 93dbb63f971 SOLR-18423: CrossDC Consumer: off-by-one error in ThreadDump handler. (#4889)
new ee5120a6c9d Fix misleading deprecation warning for SOLR_HOST_ADVERTISE (#4715)
new 7eb62d0ab67 Update Error Prone to v2.50.0 (#4847)
The 17 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../PR#4847-update-error-prone-to-v2-50-0.yml | 7 +
.../PR#4870-httpSolrCallGetQueryParams.yml | 10 +
.../PR#4871-httpSolrClientDefaultUrlParams.yml | 9 +
...R-18335-splitshard-router-field-point-field.yml | 10 +
.../SOLR-18406-replication-stale-generation.yml | 10 +
changelog/unreleased/SOLR-18412.yml | 8 +
...8418-fix-complement-intersect-asymmetric-on.yml | 9 +
.../SOLR-504-dismax-blank-pf-empty-clause.yml | 9 +
changelog/unreleased/fix-solr-18337.yml | 8 +
changelog/unreleased/solr-18411.yml | 8 +
changelog/unreleased/solr-18423.yml | 8 +
gradle/libs.versions.toml | 4 +-
gradle/validation/error-prone.gradle | 17 +-
solr/api/gradle.lockfile | 8 +-
.../api/model/GetClusterCommandStatusResponse.java | 10 +-
solr/benchmark/gradle.lockfile | 8 +-
.../apache/solr/bench/lifecycle/SolrStartup.java | 7 +-
solr/core/gradle.lockfile | 8 +-
.../src/java/org/apache/solr/cli/ExportTool.java | 2 +
.../solr/cloud/DistributedClusterStateUpdater.java | 4 +
.../src/java/org/apache/solr/cloud/LockTree.java | 2 +
.../src/java/org/apache/solr/cloud/Overseer.java | 3 -
.../org/apache/solr/cloud/ReplicateFromLeader.java | 3 +
.../cloud/api/collections/CategoryRoutedAlias.java | 2 +
.../api/collections/DimensionalRoutedAlias.java | 2 +
.../cloud/api/collections/TimeRoutedAlias.java | 2 +
.../apache/solr/cloud/overseer/ZkStateWriter.java | 6 +
.../apache/solr/cloud/overseer/ZkWriteCommand.java | 2 +
.../apache/solr/core/CachingDirectoryFactory.java | 4 +
.../java/org/apache/solr/core/CoreContainer.java | 1 +
.../src/java/org/apache/solr/core/PluginBag.java | 5 +-
.../src/java/org/apache/solr/core/SolrCore.java | 62 +-
.../src/java/org/apache/solr/core/SolrPaths.java | 2 +
.../org/apache/solr/core/SolrResourceLoader.java | 9 +
.../java/org/apache/solr/handler/IndexFetcher.java | 65 +-
.../apache/solr/handler/ReplicationHandler.java | 4 +
.../solr/handler/admin/CoreAdminHandler.java | 2 +
.../solr/handler/admin/IndexSizeEstimator.java | 2 +
.../solr/handler/admin/SecurityConfHandler.java | 4 +
.../solr/handler/admin/SystemInfoProvider.java | 2 +
.../solr/handler/admin/api/ClusterCommands.java | 2 +-
.../solr/handler/admin/api/ReplicationAPIBase.java | 11 +-
.../handler/component/RealTimeGetComponent.java | 4 +
.../solr/handler/component/ResponseBuilder.java | 2 +
.../solr/handler/component/SearchHandler.java | 3 +
.../solr/handler/component/TermsComponent.java | 2 +
.../apache/solr/handler/loader/JavabinLoader.java | 2 +
.../java/org/apache/solr/handler/tagger/TagLL.java | 4 +
.../java/org/apache/solr/legacy/BBoxStrategy.java | 3 +
.../org/apache/solr/logging/jul/JulWatcher.java | 3 +
.../apache/solr/logging/log4j2/Log4j2Watcher.java | 2 +
.../DualRegistryAttributedLongCounter.java | 2 +
.../DualRegistryAttributedLongTimer.java | 2 +
.../DualRegistryAttributedLongUpDownCounter.java | 2 +
.../java/org/apache/solr/pkg/PackageListeners.java | 2 +
.../org/apache/solr/pkg/PackagePluginHolder.java | 2 +
.../apache/solr/response/TextResponseWriter.java | 1 +
.../transform/RawValueTransformerFactory.java | 2 +
.../response/transform/ValueSourceAugmenter.java | 2 +
.../src/java/org/apache/solr/schema/BBoxField.java | 1 +
.../java/org/apache/solr/schema/IndexSchema.java | 1 +
.../solr/schema/LatLonPointSpatialField.java | 3 +
.../java/org/apache/solr/schema/SchemaManager.java | 2 +
.../java/org/apache/solr/search/CaffeineCache.java | 1 +
.../solr/search/CollapsingQParserPlugin.java | 12 +-
.../java/org/apache/solr/search/DisMaxQParser.java | 7 +-
.../apache/solr/search/DocValuesIteratorCache.java | 1 +
.../apache/solr/search/ExtendedDismaxQParser.java | 1 +
.../solr/search/GraphTermsQParserPlugin.java | 5 +
.../src/java/org/apache/solr/search/JoinQuery.java | 3 +
.../org/apache/solr/search/QueryResultKey.java | 1 +
.../org/apache/solr/search/SolrIndexSearcher.java | 2 +
.../solr/search/facet/FacetFieldProcessor.java | 3 +
.../apache/solr/search/facet/RelatednessAgg.java | 2 +
.../java/org/apache/solr/search/facet/SlotAcc.java | 3 +
.../apache/solr/search/facet/UnInvertedField.java | 2 +
.../apache/solr/security/AllowListUrlChecker.java | 2 +
.../solr/security/PKIAuthenticationPlugin.java | 2 +
.../java/org/apache/solr/servlet/HttpSolrCall.java | 8 +-
.../apache/solr/servlet/RequestRateLimiter.java | 4 +
.../apache/solr/servlet/SolrRequestParsers.java | 6 +-
.../solr/spelling/ConjunctionSolrSpellChecker.java | 1 +
.../apache/solr/update/DirectUpdateHandler2.java | 1 +
.../org/apache/solr/update/MemOutputStream.java | 3 +
.../src/java/org/apache/solr/update/PeerSync.java | 6 +
.../org/apache/solr/update/PeerSyncWithLeader.java | 9 +
.../org/apache/solr/update/SolrIndexConfig.java | 3 +
.../org/apache/solr/update/SolrIndexSplitter.java | 154 ++++-
.../org/apache/solr/update/SolrIndexWriter.java | 12 +
.../src/java/org/apache/solr/update/UpdateLog.java | 9 +-
...llValuesOrNoneFieldMutatingUpdateProcessor.java | 3 +
.../processor/AtomicUpdateDocumentMerger.java | 3 +
.../processor/DistributedUpdateProcessor.java | 11 +-
.../processor/DistributedZkUpdateProcessor.java | 2 +-
.../DocBasedVersionConstraintsProcessor.java | 2 +
.../processor/FieldMutatingUpdateProcessor.java | 3 +
.../FieldValueMutatingUpdateProcessor.java | 3 +
.../SkipExistingDocumentsProcessorFactory.java | 2 +
.../apache/solr/util/tracing/SimplePropagator.java | 6 +-
.../test/org/apache/solr/TestCpuTimeSearch.java | 5 +-
.../test/org/apache/solr/TestGroupingSearch.java | 3 +
.../org/apache/solr/cli/TestSolrCLIRunExample.java | 5 +-
.../apache/solr/cloud/AliasIntegrationTest.java | 7 +-
.../apache/solr/cloud/BasicDistributedZk2Test.java | 47 +-
.../apache/solr/cloud/BasicDistributedZkTest.java | 180 +++---
.../cloud/CloudExitableDirectoryReaderTest.java | 2 +-
.../apache/solr/cloud/CollectionsAPISolrJTest.java | 19 +-
.../cloud/ConcurrentCreateRoutedAliasTest.java | 6 +-
.../solr/cloud/DeleteInactiveReplicaTest.java | 29 +-
.../DistribDocExpirationUpdateProcessorTest.java | 61 +-
.../solr/cloud/DistributedVersionInfoTest.java | 127 ++--
.../solr/cloud/FullSolrCloudDistribCmdsTest.java | 416 ++++++-------
.../solr/cloud/HttpPartitionOnCommitTest.java | 35 +-
.../org/apache/solr/cloud/HttpPartitionTest.java | 39 +-
.../solr/cloud/LeaderElectionIntegrationTest.java | 2 +
.../cloud/LeaderFailoverAfterPartitionTest.java | 10 +-
.../org/apache/solr/cloud/MigrateReplicasTest.java | 30 +-
.../org/apache/solr/cloud/MigrateRouteKeyTest.java | 101 ++--
.../org/apache/solr/cloud/MoveReplicaTest.java | 49 +-
.../solr/cloud/NestedShardedAtomicUpdateTest.java | 9 +-
.../apache/solr/cloud/RemoteQueryErrorTest.java | 19 +-
.../org/apache/solr/cloud/ReplaceNodeTest.java | 24 +-
.../apache/solr/cloud/ReplicationFactorTest.java | 31 +-
.../test/org/apache/solr/cloud/SplitShardTest.java | 16 +-
.../apache/solr/cloud/TestBaseStatsCacheCloud.java | 79 ++-
.../apache/solr/cloud/TestCloudConsistency.java | 25 +-
.../apache/solr/cloud/TestCloudDeleteByQuery.java | 46 +-
.../TestCloudPhrasesIdentificationComponent.java | 2 +-
.../solr/cloud/TestCloudPseudoReturnFields.java | 2 +-
.../org/apache/solr/cloud/TestCloudRecovery2.java | 33 +-
.../org/apache/solr/cloud/TestConfigSetsAPI.java | 114 ++--
.../solr/cloud/TestConfigSetsAPIExclusivity.java | 8 +-
.../solr/cloud/TestConfigSetsAPIZkFailure.java | 5 +-
.../solr/cloud/TestGracefulJettyShutdown.java | 4 +-
.../solr/cloud/TestMiniSolrCloudClusterSSL.java | 2 +-
.../org/apache/solr/cloud/TestPullReplica.java | 111 ++--
.../solr/cloud/TestPullReplicaErrorHandling.java | 37 +-
.../apache/solr/cloud/TestPullReplicaWithAuth.java | 10 +-
.../solr/cloud/TestQueryingOnDownCollection.java | 59 +-
.../cloud/TestStressCloudBlindAtomicUpdates.java | 13 +-
.../solr/cloud/TestTlogReplayVsRecovery.java | 22 +-
.../org/apache/solr/cloud/TestTlogReplica.java | 138 +++--
.../cloud/TestTolerantUpdateProcessorCloud.java | 26 +-
.../TestTolerantUpdateProcessorRandomCloud.java | 11 +-
.../apache/solr/cloud/UnloadDistributedZkTest.java | 132 ++---
.../solr/cloud/ZkShardTermsRecoveryTest.java | 11 +-
.../ConcurrentDeleteAndCreateCollectionTest.java | 6 +-
.../solr/cloud/api/collections/ShardSplitTest.java | 332 ++++++-----
.../org/apache/solr/core/TestCustomStream.java | 17 +-
.../core/snapshots/TestSolrCloudSnapshots.java | 32 +-
.../solr/core/snapshots/TestSolrCoreSnapshots.java | 265 ++++-----
.../solr/filestore/TestDistribFileStore.java | 23 +-
.../solr/handler/TestReplicationHandler.java | 118 +++-
.../solr/handler/TestStressIncrementalBackup.java | 11 +-
.../solr/handler/TestStressThreadBackup.java | 11 +-
.../org/apache/solr/handler/V2StandaloneTest.java | 17 +-
.../solr/handler/admin/CoreAdminHandlerTest.java | 11 +-
.../solr/handler/admin/HealthCheckHandlerTest.java | 34 +-
.../solr/handler/admin/LukeHandlerCloudTest.java | 29 +-
.../solr/handler/admin/TestApiFramework.java | 2 +
.../handler/admin/api/ClusterCommandsTest.java | 22 +-
.../solr/handler/component/UpdateLogCloudTest.java | 6 +-
.../solr/metrics/SolrMetricsIntegrationTest.java | 43 +-
.../src/test/org/apache/solr/pkg/TestPackages.java | 1 +
.../response/TestPrometheusResponseWriter.java | 154 +++--
.../apache/solr/response/TestRawTransformer.java | 4 +-
.../schema/ManagedSchemaRoundRobinCloudTest.java | 27 +-
.../solr/schema/TestManagedSchemaThreadSafety.java | 2 +
.../apache/solr/search/TestCoordinatorRole.java | 464 ++++++++-------
.../solr/search/TestExtendedDismaxParser.java | 29 +
.../search/facet/TestCloudJSONFacetJoinDomain.java | 2 +-
.../solr/search/facet/TestCloudJSONFacetSKG.java | 2 +-
.../search/facet/TestCloudJSONFacetSKGEquiv.java | 2 +-
.../apache/solr/search/facet/TestJsonFacets.java | 2 +
.../solr/search/function/AggValueSourceTest.java | 2 +
.../apache/solr/search/stats/TestDistribIDF.java | 105 ++--
.../solr/security/BasicAuthIntegrationTest.java | 15 +-
.../solr/security/BasicAuthStandaloneTest.java | 99 ++--
.../apache/solr/security/MultiAuthPluginTest.java | 658 ++++++++++-----------
.../solr/uninverting/TestFieldCacheSortRandom.java | 2 +
.../solr/update/DeleteByIdWithRouterFieldTest.java | 28 +-
.../apache/solr/update/SolrIndexSplitterTest.java | 91 +++
.../solr/update/TestInPlaceUpdatesStandalone.java | 2 +-
.../update/processor/TestCloudDeduplication.java | 2 +-
solr/cross-dc-manager/gradle.lockfile | 8 +-
.../solr/crossdc/manager/consumer/ThreadDump.java | 2 +-
.../crossdc/manager/consumer/ThreadDumpTest.java | 126 ++++
solr/modules/analysis-extras/gradle.lockfile | 8 +-
solr/modules/clustering/gradle.lockfile | 8 +-
solr/modules/cross-dc/gradle.lockfile | 8 +-
.../solr/crossdc/common/KafkaCrossDcConf.java | 13 +-
.../solr/crossdc/common/KafkaMirroringSink.java | 3 +
.../apache/solr/crossdc/common/ConfUtilTest.java | 81 +++
.../crossdc/common/KafkaMirroringSinkTest.java | 101 ++++
solr/modules/cuvs/gradle.lockfile | 8 +-
solr/modules/extraction/gradle.lockfile | 8 +-
solr/modules/gcs-repository/gradle.lockfile | 8 +-
solr/modules/jwt-auth/gradle.lockfile | 8 +-
solr/modules/langid/gradle.lockfile | 8 +-
solr/modules/language-models/gradle.lockfile | 8 +-
.../processor/TextToVectorUpdateProcessor.java | 2 +-
.../solr/languagemodels/TestLanguageModelBase.java | 2 +-
.../store/rest/TestLargeLanguageModelManager.java | 2 +-
.../store/rest/TestTextToVectorModelManager.java | 2 +-
...cumentEnrichmentUpdateProcessorFactoryTest.java | 3 +-
solr/modules/ltr/gradle.lockfile | 8 +-
.../org/apache/solr/ltr/feature/SolrFeature.java | 3 +
.../org/apache/solr/ltr/model/LTRScoringModel.java | 2 +
solr/modules/opentelemetry/gradle.lockfile | 8 +-
.../solr/opentelemetry/OtelTracerConfigurator.java | 4 +-
.../solr/tracing/TestDistributedTracing/test.json | 12 +-
.../tracing/TestDistributedTracing/testV2Api.json | 29 +-
.../CustomTestOtelTracerConfigurator.java | 4 +-
.../opentelemetry/OtelTracerConfiguratorTest.java | 2 +-
.../solr/opentelemetry/TestDistributedTracing.java | 14 +-
solr/modules/s3-repository/gradle.lockfile | 8 +-
solr/modules/scripting/gradle.lockfile | 8 +-
solr/modules/sql/gradle.lockfile | 8 +-
.../org/apache/solr/handler/sql/SolrAggregate.java | 2 +
.../org/apache/solr/handler/sql/SolrFilter.java | 2 +
.../org/apache/solr/handler/sql/SolrProject.java | 2 +
.../java/org/apache/solr/handler/sql/SolrSort.java | 2 +
.../org/apache/solr/handler/sql/SolrTableScan.java | 2 +
solr/server/gradle.lockfile | 8 +-
solr/solr-ref-guide/gradle.lockfile | 8 +-
.../pages/collection-management.adoc | 5 +-
.../pages/stream-decorator-reference.adoc | 16 +-
solr/solrj-jetty/gradle.lockfile | 8 +-
solr/solrj-streaming/gradle.lockfile | 8 +-
.../solr/client/solrj/io/comp/FieldComparator.java | 2 +-
.../solr/client/solrj/io/eq/FieldEqualitor.java | 48 +-
.../client/solrj/io/eq/MultipleFieldEqualitor.java | 49 ++
.../solr/client/solrj/io/eq/StreamEqualitor.java | 78 +++
.../solr/client/solrj/io/stream/BiJoinStream.java | 55 +-
.../client/solrj/io/stream/ComplementStream.java | 22 +-
.../client/solrj/io/stream/IntersectStream.java | 28 +-
.../solrj/io/stream/JavabinTupleStreamParser.java | 7 +-
.../solrj/io/stream/StreamDecoratorTest.java | 116 ++++
solr/solrj-zookeeper/gradle.lockfile | 8 +-
.../apache/solr/common/cloud/ZkStateReader.java | 4 +
solr/solrj/gradle.lockfile | 8 +-
.../solrj/impl/ConcurrentUpdateBaseSolrClient.java | 2 +
.../solr/client/solrj/impl/HttpSolrClient.java | 27 +-
.../solrj/request/JavaBinUpdateRequestCodec.java | 2 +
.../solr/client/solrj/response/ResponseParser.java | 1 +
.../RequestReplicaListTransformerGenerator.java | 2 +-
.../apache/solr/common/util/CommandOperation.java | 2 +-
.../org/apache/solr/common/util/JavaBinCodec.java | 6 +
.../src/resources/EnvToSyspropMappings.properties | 29 +-
.../apache/solr/client/solrj/SolrExampleTests.java | 12 +-
.../solr/client/solrj/SolrExampleTestsBase.java | 6 +-
.../solrj/impl/CloudHttp2SolrClientTest.java | 104 ++--
.../solrj/impl/HttpSolrClientBadInputTest.java | 80 +--
.../solr/client/solrj/impl/LB2SolrClientTest.java | 4 +-
.../org/apache/solr/common/util/EnvUtilsTest.java | 130 +++-
.../apache/solr/common/util/TestFastWriter.java | 2 +
solr/test-framework/gradle.lockfile | 8 +-
.../apache/solr/BaseDistributedSearchTestCase.java | 6 +-
.../src/java/org/apache/solr/JSONTestUtil.java | 1 +
.../src/java/org/apache/solr/SolrTestCaseHS.java | 4 +-
.../src/java/org/apache/solr/SolrTestCaseJ4.java | 56 +-
.../solr/cloud/AbstractFullDistribZkTestBase.java | 28 +-
.../apache/solr/cloud/MiniSolrCloudCluster.java | 38 +-
...bstractCollectionsAPIDistributedZkTestBase.java | 15 +-
.../apache/solr/cluster/placement/Builders.java | 2 +
.../java/org/apache/solr/embedded/JettyConfig.java | 84 ++-
.../org/apache/solr/embedded/JettySolrRunner.java | 19 +-
.../solr/util/RevertDefaultThreadHandlerRule.java | 2 +
.../org/apache/solr/util/SolrJMetricTestUtils.java | 6 +-
.../apache/solr/embedded/TestJettySolrRunner.java | 11 +-
solr/webapp/gradle.lockfile | 8 +-
.../webapp/AdminUiCoreAdminStandaloneTest.java | 19 +-
.../apache/solr/webapp/AdminUiQueryScreenTest.java | 4 +-
.../webapp/AdminUiReplicationStandaloneTest.java | 23 +-
.../solr/webapp/AdminUiSecurityAuthTest.java | 9 +-
.../org/apache/solr/webapp/AdminUiTestBase.java | 7 +-
276 files changed, 4212 insertions(+), 3102 deletions(-)
create mode 100644 changelog/unreleased/PR#4847-update-error-prone-to-v2-50-0.yml
create mode 100644 changelog/unreleased/PR#4870-httpSolrCallGetQueryParams.yml
create mode 100644 changelog/unreleased/PR#4871-httpSolrClientDefaultUrlParams.yml
create mode 100644 changelog/unreleased/SOLR-18335-splitshard-router-field-point-field.yml
create mode 100644 changelog/unreleased/SOLR-18406-replication-stale-generation.yml
create mode 100644 changelog/unreleased/SOLR-18412.yml
create mode 100644 changelog/unreleased/SOLR-18418-fix-complement-intersect-asymmetric-on.yml
create mode 100644 changelog/unreleased/SOLR-504-dismax-blank-pf-empty-clause.yml
create mode 100644 changelog/unreleased/fix-solr-18337.yml
create mode 100644 changelog/unreleased/solr-18411.yml
create mode 100644 changelog/unreleased/solr-18423.yml
create mode 100644 solr/cross-dc-manager/src/test/org/apache/solr/crossdc/manager/consumer/ThreadDumpTest.java
create mode 100644 solr/modules/cross-dc/src/test/org/apache/solr/crossdc/common/KafkaMirroringSinkTest.java
(solr) 12/17: SOLR-504: a missing or blank "pf" must not add an empty/no-op boolean clause to the query (#4891)
Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
commit a8bc5486572d6bb18a30a2501d222532f95d07ca
Author: Eric Pugh <ep...@opensourceconnections.com>
AuthorDate: Wed Sep 9 06:43:08 2026 -0400
SOLR-504: a missing or blank "pf" must not add an empty/no-op boolean clause to the query (#4891)
(cherry picked from commit a0714c8d01d070d1bf8fea2efb1d3bdece82c280)
---
.../SOLR-504-dismax-blank-pf-empty-clause.yml | 9 +++++++
.../java/org/apache/solr/search/DisMaxQParser.java | 7 +++++-
.../solr/search/TestExtendedDismaxParser.java | 29 ++++++++++++++++++++++
3 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/changelog/unreleased/SOLR-504-dismax-blank-pf-empty-clause.yml b/changelog/unreleased/SOLR-504-dismax-blank-pf-empty-clause.yml
new file mode 100644
index 00000000000..ebab4b53904
--- /dev/null
+++ b/changelog/unreleased/SOLR-504-dismax-blank-pf-empty-clause.yml
@@ -0,0 +1,9 @@
+title: >
+ The DisMax query parser no longer adds an empty, no-op boolean clause to the query when the
+ pf parameter is blank or missing.
+type: fixed
+authors:
+ - name: Eric Pugh
+links:
+ - name: SOLR-504
+ url: https://issues.apache.org/jira/browse/SOLR-504
diff --git a/solr/core/src/java/org/apache/solr/search/DisMaxQParser.java b/solr/core/src/java/org/apache/solr/search/DisMaxQParser.java
index 25e93592d35..91eec6acabd 100644
--- a/solr/core/src/java/org/apache/solr/search/DisMaxQParser.java
+++ b/solr/core/src/java/org/apache/solr/search/DisMaxQParser.java
@@ -227,7 +227,12 @@ public class DisMaxQParser extends QParser {
* matched those phrases but do match looser phrases.
*/
String userPhraseQuery = userQuery.replace("\"", "");
- return pp.parse("\"" + userPhraseQuery + "\"");
+ Query phrase = pp.parse("\"" + userPhraseQuery + "\"");
+ // blank/missing pf yields an empty BooleanQuery, not null; normalize it
+ if (ExtendedDismaxQParser.isEmpty(phrase)) {
+ return null;
+ }
+ return phrase;
}
protected Query getUserQuery(
diff --git a/solr/core/src/test/org/apache/solr/search/TestExtendedDismaxParser.java b/solr/core/src/test/org/apache/solr/search/TestExtendedDismaxParser.java
index cf80ef4eb24..f1568b25795 100644
--- a/solr/core/src/test/org/apache/solr/search/TestExtendedDismaxParser.java
+++ b/solr/core/src/test/org/apache/solr/search/TestExtendedDismaxParser.java
@@ -3377,4 +3377,33 @@ public class TestExtendedDismaxParser extends SolrTestCaseJ4 {
"org.apache.solr.search.SyntaxError: Query Field 'nosuchfield' is not a valid field name",
exception.getMessage());
}
+
+ /** SOLR-504: a missing or blank "pf" must not add an empty/no-op boolean clause to the query */
+ @Test
+ public void testPfMissingOrBlankAddsNoEmptyClause() throws Exception {
+ final String expectedNoPf = "+((subject:hello | title:hello) (subject:world | title:world))";
+ final String expectedRealPf = expectedNoPf + " (subject:\"hello world\")";
+
+ for (String defType : List.of("dismax", "edismax")) {
+ try (SolrQueryRequest req = req("qf", "subject title", "defType", defType)) {
+ assertEquals(
+ defType,
+ expectedNoPf,
+ QParser.getParser("hello world", defType, req).getQuery().toString());
+ }
+ try (SolrQueryRequest req = req("qf", "subject title", "pf", "", "defType", defType)) {
+ assertEquals(
+ defType,
+ expectedNoPf,
+ QParser.getParser("hello world", defType, req).getQuery().toString());
+ }
+ // sanity check: a real pf *does* add a (non-empty) phrase clause
+ try (SolrQueryRequest req = req("qf", "subject title", "pf", "subject", "defType", defType)) {
+ assertEquals(
+ defType,
+ expectedRealPf,
+ QParser.getParser("hello world", defType, req).getQuery().toString());
+ }
+ }
+ }
}
(solr) 02/17: SOLR-18406: Restart replication after index generation expires (#4820)
Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
commit 1031b8ee4394df89aa7122e5be0b343099d12c79
Author: Zhenyu Li <48...@users.noreply.github.com>
AuthorDate: Mon Sep 7 23:04:40 2026 -0400
SOLR-18406: Restart replication after index generation expires (#4820)
Leader/follower replication now restarts with the latest index generation when the selected generation expires during download, avoiding retries against an unavailable generation.
(cherry picked from commit 0cc72b8e326d9702958e9603b420af4c60d24c19)
---
.../SOLR-18406-replication-stale-generation.yml | 10 ++++
.../java/org/apache/solr/handler/IndexFetcher.java | 65 +++++++++++++++++-----
.../solr/handler/admin/api/ReplicationAPIBase.java | 11 +++-
.../solr/handler/TestReplicationHandler.java | 62 +++++++++++++++++++++
4 files changed, 133 insertions(+), 15 deletions(-)
diff --git a/changelog/unreleased/SOLR-18406-replication-stale-generation.yml b/changelog/unreleased/SOLR-18406-replication-stale-generation.yml
new file mode 100644
index 00000000000..694dd5c4b08
--- /dev/null
+++ b/changelog/unreleased/SOLR-18406-replication-stale-generation.yml
@@ -0,0 +1,10 @@
+title: >
+ Leader/follower replication now restarts with the latest index generation when the selected
+ generation expires during download, avoiding retries against an unavailable generation.
+type: changed
+authors:
+ - name: ZhenyuLi
+ nick: JHSUYU
+links:
+ - name: SOLR-18406
+ url: https://issues.apache.org/jira/browse/SOLR-18406
diff --git a/solr/core/src/java/org/apache/solr/handler/IndexFetcher.java b/solr/core/src/java/org/apache/solr/handler/IndexFetcher.java
index 4a9f14834cd..b6fa1146959 100644
--- a/solr/core/src/java/org/apache/solr/handler/IndexFetcher.java
+++ b/solr/core/src/java/org/apache/solr/handler/IndexFetcher.java
@@ -405,6 +405,18 @@ public class IndexFetcher {
*/
IndexFetchResult fetchLatestIndex(boolean forceReplication, boolean forceCoreReload)
throws IOException, InterruptedException {
+ try {
+ return fetchLatestIndexOnce(forceReplication, forceCoreReload);
+ } catch (InvalidIndexGenerationException e) {
+ log.info(
+ "Leader no longer has index generation {}; restarting replication from its latest generation",
+ e.generation);
+ return fetchLatestIndexOnce(forceReplication, forceCoreReload);
+ }
+ }
+
+ private IndexFetchResult fetchLatestIndexOnce(boolean forceReplication, boolean forceCoreReload)
+ throws IOException, InterruptedException {
boolean cleanupDone = false;
boolean successfulInstall = false;
@@ -556,6 +568,7 @@ public class IndexFetcher {
log.info("Starting replication process");
// get the list of files first
fetchFileList(latestGeneration);
+ assert testWait.getAsBoolean();
// this can happen if the commit point is deleted before we fetch the file list.
if (filesToDownload.isEmpty()) {
return IndexFetchResult.PEER_INDEX_COMMIT_DELETED;
@@ -761,6 +774,8 @@ public class IndexFetcher {
} catch (ReplicationHandlerException e) {
log.error("User aborted Replication", e);
return new IndexFetchResult(IndexFetchResult.FAILED_BY_EXCEPTION_MESSAGE, false, e);
+ } catch (InvalidIndexGenerationException e) {
+ throw e;
} catch (SolrException e) {
throw e;
} catch (InterruptedException e) {
@@ -1593,6 +1608,8 @@ public class IndexFetcher {
bytesDownloaded = 0;
try {
fetch();
+ } catch (InvalidIndexGenerationException e) {
+ throw e;
} catch (Exception e) {
if (!aborted) {
IndexFetcher.log.error("Error fetching file, doing one retry...", e);
@@ -1605,6 +1622,7 @@ public class IndexFetcher {
}
private void fetch() throws Exception {
+ boolean invalidIndexGeneration = false;
try {
while (true) {
try (FastInputStream fis = getStream()) {
@@ -1617,17 +1635,22 @@ public class IndexFetcher {
// if there is an error continue. But continue from the point where it got broken
}
}
+ } catch (InvalidIndexGenerationException e) {
+ invalidIndexGeneration = true;
+ throw e;
} finally {
- cleanup();
- // if cleanup succeeds, and the file is downloaded fully, then do a fsync.
- fsyncService.execute(
- () -> {
- try {
- file.sync();
- } catch (IOException | AlreadyClosedException e) {
- fsyncException = e;
- }
- });
+ cleanup(invalidIndexGeneration);
+ if (!invalidIndexGeneration) {
+ // if cleanup succeeds, and the file is downloaded fully, then do a fsync.
+ fsyncService.execute(
+ () -> {
+ try {
+ file.sync();
+ } catch (IOException | AlreadyClosedException e) {
+ fsyncException = e;
+ }
+ });
+ }
}
}
@@ -1744,7 +1767,7 @@ public class IndexFetcher {
}
/** cleanup everything */
- private void cleanup() {
+ private void cleanup(boolean invalidIndexGeneration) {
try {
file.close();
} catch (Exception e) {
@@ -1760,7 +1783,7 @@ public class IndexFetcher {
log.error("Error deleting file: {}", this.saveAs, e);
}
// if the failure is due to a user abort it is returned normally else an exception is thrown
- if (!aborted)
+ if (!aborted && !invalidIndexGeneration)
throw new SolrException(
SolrException.ErrorCode.SERVER_ERROR,
"Unable to download "
@@ -1806,6 +1829,10 @@ public class IndexFetcher {
final var responseStatus = (Integer) response.get("responseStatus");
is = (InputStream) response.get("stream");
+ if (responseStatus == ErrorCode.CONFLICT.code) {
+ throw new InvalidIndexGenerationException(indexGen);
+ }
+
if (responseStatus != 200) {
final var errorMsg =
String.format(
@@ -1813,13 +1840,16 @@ public class IndexFetcher {
"Unexpected status code [%d] when downloading file [%s].",
responseStatus,
fileName);
- closeStreamAndBuildIOE(is, errorMsg, null);
+ throw closeStreamAndBuildIOE(is, errorMsg, null);
}
if (useInternalCompression) {
is = new InflaterInputStream(is);
}
return new FastInputStream(is);
+ } catch (InvalidIndexGenerationException e) {
+ IOUtils.closeQuietly(is);
+ throw e;
} catch (Exception e) {
final var ioe = closeStreamAndBuildIOE(is, "Could not download file '" + fileName + "'", e);
throw ioe;
@@ -1836,6 +1866,15 @@ public class IndexFetcher {
}
}
+ private static class InvalidIndexGenerationException extends IOException {
+ private final long generation;
+
+ InvalidIndexGenerationException(long generation) {
+ super("Leader no longer has index generation " + generation);
+ this.generation = generation;
+ }
+ }
+
private static class DirectoryFile implements FileInterface {
private final String saveAs;
private Directory copy2Dir;
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/ReplicationAPIBase.java b/solr/core/src/java/org/apache/solr/handler/admin/api/ReplicationAPIBase.java
index 3b7170494c5..8dbf4afa911 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/ReplicationAPIBase.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/ReplicationAPIBase.java
@@ -254,6 +254,7 @@ public abstract class ReplicationAPIBase extends JerseyResource {
protected Long indexGen;
protected IndexDeletionPolicyWrapper delPolicy;
+ private boolean commitPointSaved;
protected String fileName;
protected String cfileName;
@@ -342,7 +343,13 @@ public abstract class ReplicationAPIBase extends JerseyResource {
// reserve commit point till write is complete
if (indexGen != null) {
- delPolicy.saveCommitPoint(indexGen);
+ try {
+ delPolicy.saveCommitPoint(indexGen);
+ commitPointSaved = true;
+ } catch (IllegalStateException e) {
+ throw new SolrException(
+ SolrException.ErrorCode.CONFLICT, "invalid index generation: " + indexGen, e);
+ }
}
}
@@ -360,7 +367,7 @@ public abstract class ReplicationAPIBase extends JerseyResource {
ReplicationHandler replicationHandler =
(ReplicationHandler) solrCore.getRequestHandler(ReplicationHandler.PATH);
- if (indexGen != null) {
+ if (commitPointSaved) {
// Reserve the commit point for another 10s for the next file to be to fetched.
// We need to keep extending the commit reservation between requests so that the replica can
// fetch all the files correctly.
diff --git a/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java b/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java
index 326e0ac5059..cc719d054c4 100644
--- a/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java
+++ b/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java
@@ -34,6 +34,9 @@ import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import org.apache.lucene.index.DirectoryReader;
@@ -65,7 +68,9 @@ import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.common.util.NamedList;
+import org.apache.solr.common.util.SolrNamedThreadFactory;
import org.apache.solr.common.util.TimeSource;
import org.apache.solr.core.CachingDirectoryFactory;
import org.apache.solr.core.CoreContainer;
@@ -1493,6 +1498,63 @@ public class TestReplicationHandler extends SolrTestCaseJ4 {
assertEquals("invalid index generation", resp.get("message"));
}
+ @Test
+ public void testFollowerRestartsWhenCommitExpiresBeforeFileDownload() throws Exception {
+ invokeReplicationCommand(
+ buildUrl(followerJetty.getLocalPort()) + "/" + DEFAULT_TEST_CORENAME, "disablepoll");
+
+ index(leaderClient, "id", "1", "name", "generation-g");
+ leaderClient.commit();
+ index(leaderClient, "id", "1", "name", "generation-g-plus-one");
+
+ CountDownLatch fileListFetched = new CountDownLatch(1);
+ CountDownLatch continueDownload = new CountDownLatch(1);
+ IndexFetcher.testWait =
+ () -> {
+ fileListFetched.countDown();
+ try {
+ continueDownload.await();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new RuntimeException(e);
+ }
+ return true;
+ };
+
+ ExecutorService workload =
+ ExecutorUtil.newMDCAwareSingleThreadExecutor(
+ new SolrNamedThreadFactory("staleGenerationWorkload"));
+ try {
+ Future<?> followerFetch =
+ workload.submit(
+ () -> {
+ pullFromTo(leaderJetty, followerJetty);
+ return null;
+ });
+
+ assertTrue(fileListFetched.await(TIMEOUT, TimeUnit.MILLISECONDS));
+
+ long reserveDuration;
+ try (SolrCore core = leaderJetty.getCoreContainer().getCore(DEFAULT_TEST_CORENAME)) {
+ ReplicationHandler handler =
+ (ReplicationHandler) core.getRequestHandler(ReplicationHandler.PATH);
+ reserveDuration = handler.getReserveCommitDuration();
+ }
+ Thread.sleep(reserveDuration + 1000);
+ leaderClient.commit();
+
+ IndexFetcher.testWait = () -> true;
+ continueDownload.countDown();
+ followerFetch.get(TIMEOUT, TimeUnit.MILLISECONDS);
+
+ assertEquals(1, numFound(rQuery(1, "name:generation-g-plus-one", followerClient)));
+ } finally {
+ IndexFetcher.testWait = () -> true;
+ continueDownload.countDown();
+ workload.shutdownNow();
+ }
+ }
+
@Test
public void testFetchIndexShouldReportErrorsWhenTheyOccur() throws Exception {
int leaderPort = leaderJetty.getLocalPort();
(solr) 07/17: SOLR-18418: Fix complement()/intersect() with asymmetric on= (#4873)
Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
commit 07c253a4d04a9c28f4b5128754d9d06947be69c9
Author: David Smiley <ds...@apache.org>
AuthorDate: Tue Sep 8 20:27:07 2026 -0400
SOLR-18418: Fix complement()/intersect() with asymmetric on= (#4873)
Fix complement() and intersect() streaming expressions silently returning wrong results when on= maps two differently-named fields
Co-authored-by: Claude Opus 5 (1M context) <no...@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <17...@users.noreply.github.com>
(cherry picked from commit ba6f29cbf8bdfc6f0087c2f92adecc44ce350552)
---
...8418-fix-complement-intersect-asymmetric-on.yml | 9 ++
.../pages/stream-decorator-reference.adoc | 16 ++-
.../solr/client/solrj/io/eq/FieldEqualitor.java | 46 ++++++++
.../client/solrj/io/eq/MultipleFieldEqualitor.java | 49 +++++++++
.../solr/client/solrj/io/eq/StreamEqualitor.java | 78 ++++++++++++++
.../solr/client/solrj/io/stream/BiJoinStream.java | 55 +---------
.../client/solrj/io/stream/ComplementStream.java | 22 +++-
.../client/solrj/io/stream/IntersectStream.java | 28 +++--
.../solrj/io/stream/StreamDecoratorTest.java | 116 +++++++++++++++++++++
9 files changed, 349 insertions(+), 70 deletions(-)
diff --git a/changelog/unreleased/SOLR-18418-fix-complement-intersect-asymmetric-on.yml b/changelog/unreleased/SOLR-18418-fix-complement-intersect-asymmetric-on.yml
new file mode 100644
index 00000000000..951b51a3954
--- /dev/null
+++ b/changelog/unreleased/SOLR-18418-fix-complement-intersect-asymmetric-on.yml
@@ -0,0 +1,9 @@
+title: Fix complement() and intersect() streaming expressions silently returning wrong
+ results when on= maps two differently-named fields
+type: fixed
+authors:
+ - name: David Smiley
+ url: https://home.apache.org/phonebook.html?uid=dsmiley
+links:
+ - name: SOLR-18418
+ url: https://issues.apache.org/jira/browse/SOLR-18418
diff --git a/solr/solr-ref-guide/modules/query-guide/pages/stream-decorator-reference.adoc b/solr/solr-ref-guide/modules/query-guide/pages/stream-decorator-reference.adoc
index ca52627a712..120f871f5f6 100644
--- a/solr/solr-ref-guide/modules/query-guide/pages/stream-decorator-reference.adoc
+++ b/solr/solr-ref-guide/modules/query-guide/pages/stream-decorator-reference.adoc
@@ -467,7 +467,13 @@ commit(
The `complement` function wraps two streams (A and B) and emits tuples from A which do not exist in B.
The tuples are emitted in the order in which they appear in stream A.
-Both streams must be sorted by the fields being used to determine equality (using the `on` parameter).
+Both streams must be sorted ascending by the field(s) named on their own side of the `on` parameter
+(e.g. for `on="fieldNameInLeft=fieldNameInRight"`, A must be sorted by `fieldNameInLeft` and B by
+`fieldNameInRight`) - this holds whether or not the two sides name the same field.
+
+As a sanity check, `complement` and `intersect` (below) partition A: for the same two input streams
+and the same `on`, the number of tuples emitted by `complement` plus the number emitted by
+`intersect` always equals the number of tuples in A.
=== complement Parameters
@@ -1025,9 +1031,15 @@ innerJoin(
The `intersect` function wraps two streams, A and B, and emits tuples from A which *DO* exist in B.
The tuples are emitted in the order in which they appear in stream A.
-Both streams must be sorted by the fields being used to determine equality (the `on` parameter).
+Both streams must be sorted ascending by the field(s) named on their own side of the `on` parameter
+(e.g. for `on="fieldNameInLeft=fieldNameInRight"`, A must be sorted by `fieldNameInLeft` and B by
+`fieldNameInRight`) - this holds whether or not the two sides name the same field.
Only tuples from A are emitted.
+As a sanity check, `intersect` and `complement` (above) partition A: for the same two input streams
+and the same `on`, the number of tuples emitted by `complement` plus the number emitted by
+`intersect` always equals the number of tuples in A.
+
=== intersect Parameters
* `StreamExpression for StreamA`
diff --git a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/eq/FieldEqualitor.java b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/eq/FieldEqualitor.java
index f17b62afc9a..78ca78a9fdc 100644
--- a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/eq/FieldEqualitor.java
+++ b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/eq/FieldEqualitor.java
@@ -137,4 +137,50 @@ public class FieldEqualitor implements StreamEqualitor {
return false;
}
+
+ @Override
+ public boolean isDerivedFromLeft(StreamComparator base) {
+ if (null == base) {
+ return false;
+ }
+ if (base instanceof FieldComparator baseComp) {
+ return leftFieldName.equals(baseComp.getLeftFieldName());
+ } else if (base instanceof MultipleFieldComparator baseComps) {
+ // must equal the first one
+ if (baseComps.getComps().length > 0) {
+ return isDerivedFromLeft(baseComps.getComps()[0]);
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean isDerivedFromRight(StreamComparator base) {
+ if (null == base) {
+ return false;
+ }
+ if (base instanceof FieldComparator baseComp) {
+ return rightFieldName.equals(baseComp.getRightFieldName());
+ } else if (base instanceof MultipleFieldComparator baseComps) {
+ // must equal the first one
+ if (baseComps.getComps().length > 0) {
+ return isDerivedFromRight(baseComps.getComps()[0]);
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public void assertFieldsPresent(Tuple left, Tuple right) throws IOException {
+ if (!left.getFields().containsKey(leftFieldName)) {
+ throw new IOException(
+ "Field '" + leftFieldName + "' is missing (not just null) from tuple: " + left);
+ }
+ if (!right.getFields().containsKey(rightFieldName)) {
+ throw new IOException(
+ "Field '" + rightFieldName + "' is missing (not just null) from tuple: " + right);
+ }
+ }
}
diff --git a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/eq/MultipleFieldEqualitor.java b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/eq/MultipleFieldEqualitor.java
index 1889ce2fd8a..7384402aafa 100644
--- a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/eq/MultipleFieldEqualitor.java
+++ b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/eq/MultipleFieldEqualitor.java
@@ -119,4 +119,53 @@ public class MultipleFieldEqualitor implements StreamEqualitor {
return true;
}
+
+ @Override
+ public boolean isDerivedFromLeft(StreamComparator base) {
+ if (null == base) {
+ return false;
+ }
+ if (!(base instanceof MultipleFieldComparator baseComps)) {
+ return false;
+ }
+
+ if (baseComps.getComps().length >= eqs.length) {
+ for (int idx = 0; idx < eqs.length; ++idx) {
+ if (!eqs[idx].isDerivedFromLeft(baseComps.getComps()[idx])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean isDerivedFromRight(StreamComparator base) {
+ if (null == base) {
+ return false;
+ }
+ if (!(base instanceof MultipleFieldComparator baseComps)) {
+ return false;
+ }
+
+ if (baseComps.getComps().length >= eqs.length) {
+ for (int idx = 0; idx < eqs.length; ++idx) {
+ if (!eqs[idx].isDerivedFromRight(baseComps.getComps()[idx])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public void assertFieldsPresent(Tuple left, Tuple right) throws IOException {
+ for (StreamEqualitor eq : eqs) {
+ eq.assertFieldsPresent(left, right);
+ }
+ }
}
diff --git a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/eq/StreamEqualitor.java b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/eq/StreamEqualitor.java
index 9eaeb4973e1..122f367ebf5 100644
--- a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/eq/StreamEqualitor.java
+++ b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/eq/StreamEqualitor.java
@@ -16,8 +16,11 @@
*/
package org.apache.solr.client.solrj.io.eq;
+import java.io.IOException;
import java.io.Serializable;
import org.apache.solr.client.solrj.io.Tuple;
+import org.apache.solr.client.solrj.io.comp.FieldComparator;
+import org.apache.solr.client.solrj.io.comp.MultipleFieldComparator;
import org.apache.solr.client.solrj.io.comp.StreamComparator;
import org.apache.solr.client.solrj.io.stream.expr.Expressible;
@@ -26,4 +29,79 @@ public interface StreamEqualitor extends Equalitor<Tuple>, Expressible, Serializ
public boolean isDerivedFrom(StreamEqualitor base);
public boolean isDerivedFrom(StreamComparator base);
+
+ /**
+ * Whether this equalitor's left-hand field(s) are exactly the field(s) that {@code base} - a
+ * single stream's own sort comparator, whose left/right field names are necessarily identical -
+ * sorts on. Used to validate the stream feeding the left side of a two-stream equality (e.g.
+ * streamA in complement/intersect), as opposed to {@link #isDerivedFrom(StreamComparator)} which
+ * matches either side and so cannot validate an asymmetric {@code on=} clause correctly.
+ */
+ default boolean isDerivedFromLeft(StreamComparator base) {
+ return isDerivedFrom(base);
+ }
+
+ /** Right-hand counterpart of {@link #isDerivedFromLeft(StreamComparator)}. */
+ default boolean isDerivedFromRight(StreamComparator base) {
+ return isDerivedFrom(base);
+ }
+
+ /**
+ * Verifies that this equalitor's field(s) are actually present in the given tuples, as opposed to
+ * merely holding a null value, throwing if not. A missing field compares as null just like a
+ * present-but-null field, which would otherwise silently mask a stream wiring bug (e.g. an {@code
+ * on=} clause naming a field that one side's search/select never returns).
+ */
+ default void assertFieldsPresent(Tuple left, Tuple right) throws IOException {
+ // no-op by default; overridden by equalitors that know their own field names
+ }
+
+ /**
+ * Builds a {@link StreamComparator} that orders tuples the way this equalitor pairs fields across
+ * two streams, taking the sort order(s) from {@code comp} (typically one of the two streams' own
+ * sort). Unlike {@code comp} itself - whose left and right field names are identical, since it's
+ * a single stream's own sort - the returned comparator carries this equalitor's (possibly
+ * different) left/right field names, so it can correctly order a tuple from one stream against a
+ * tuple from the other even when {@code on=} maps differently-named fields.
+ */
+ static StreamComparator deriveComparator(StreamEqualitor eq, StreamComparator comp)
+ throws IOException {
+ if (eq instanceof MultipleFieldEqualitor multiEq
+ && comp instanceof MultipleFieldComparator multiComp) {
+ // comp is at least as long as eq because tuple order has already been validated
+ StreamComparator[] compoundComps = new StreamComparator[multiEq.getEqs().length];
+ for (int idx = 0; idx < compoundComps.length; ++idx) {
+ compoundComps[idx] = deriveComparator(multiEq.getEqs()[idx], multiComp.getComps()[idx]);
+ }
+ return new MultipleFieldComparator(compoundComps);
+ } else if (comp instanceof MultipleFieldComparator multiComp) {
+ return deriveComparator(eq, multiComp.getComps()[0]);
+ } else if (eq instanceof FieldEqualitor fieldEq && comp instanceof FieldComparator fieldComp) {
+ return new FieldComparator(
+ fieldEq.getLeftFieldName(), fieldEq.getRightFieldName(), fieldComp.getOrder());
+ } else {
+ throw new IOException(
+ "Failed to derive a comparator from equalitor " + eq + " and comparator " + comp);
+ }
+ }
+
+ /**
+ * Derives an equalitor referencing only this equalitor's right-hand field(s), for comparing two
+ * tuples that both come from the "right" stream (e.g. de-duplicating streamB against itself in
+ * complement/intersect, where using the original, possibly asymmetric equalitor would compare the
+ * wrong field on one side).
+ */
+ static StreamEqualitor deriveRightEqualitor(StreamEqualitor eq) throws IOException {
+ if (eq instanceof MultipleFieldEqualitor multiEq) {
+ StreamEqualitor[] rightEqs = new StreamEqualitor[multiEq.getEqs().length];
+ for (int idx = 0; idx < rightEqs.length; ++idx) {
+ rightEqs[idx] = deriveRightEqualitor(multiEq.getEqs()[idx]);
+ }
+ return new MultipleFieldEqualitor(rightEqs);
+ } else if (eq instanceof FieldEqualitor fieldEq) {
+ return new FieldEqualitor(fieldEq.getRightFieldName());
+ } else {
+ throw new IOException("Failed to derive a right-side equalitor from " + eq);
+ }
+ }
}
diff --git a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/BiJoinStream.java b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/BiJoinStream.java
index 566ed39f720..86d17614b49 100644
--- a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/BiJoinStream.java
+++ b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/BiJoinStream.java
@@ -20,7 +20,6 @@ import java.io.IOException;
import org.apache.solr.client.solrj.io.comp.FieldComparator;
import org.apache.solr.client.solrj.io.comp.MultipleFieldComparator;
import org.apache.solr.client.solrj.io.comp.StreamComparator;
-import org.apache.solr.client.solrj.io.eq.FieldEqualitor;
import org.apache.solr.client.solrj.io.eq.MultipleFieldEqualitor;
import org.apache.solr.client.solrj.io.eq.StreamEqualitor;
import org.apache.solr.client.solrj.io.stream.expr.Expressible;
@@ -67,7 +66,7 @@ public abstract class BiJoinStream extends JoinStream implements Expressible {
// easily be done by grabbing the first N parts of each comp where N is the number of parts in
// the equalitor. Because we've already validated tuple order (the comps) then we know this can
// be done.
- iterationComparator = createIterationComparator(eq, leftStream.getStreamSort());
+ iterationComparator = StreamEqualitor.deriveComparator(eq, leftStream.getStreamSort());
leftStreamComparator = createSideComparator(eq, leftStream.getStreamSort());
rightStreamComparator = createSideComparator(eq, rightStream.getStreamSort());
}
@@ -80,58 +79,6 @@ public abstract class BiJoinStream extends JoinStream implements Expressible {
}
}
- private StreamComparator createIterationComparator(StreamEqualitor eq, StreamComparator comp)
- throws IOException {
- if (eq instanceof MultipleFieldEqualitor && comp instanceof MultipleFieldComparator) {
- // we know the comp is at least as long as the eq because we've already validated the tuple
- // order
- StreamComparator[] compoundComps =
- new StreamComparator[((MultipleFieldEqualitor) eq).getEqs().length];
- for (int idx = 0; idx < compoundComps.length; ++idx) {
- StreamEqualitor sourceEqualitor = ((MultipleFieldEqualitor) eq).getEqs()[idx];
- StreamComparator sourceComparator = ((MultipleFieldComparator) comp).getComps()[idx];
-
- if (sourceEqualitor instanceof FieldEqualitor fieldEqualitor
- && sourceComparator instanceof FieldComparator fieldComparator) {
- compoundComps[idx] =
- new FieldComparator(
- fieldEqualitor.getLeftFieldName(),
- fieldEqualitor.getRightFieldName(),
- fieldComparator.getOrder());
- } else {
- throw new IOException("Failed to create an iteration comparator");
- }
- }
- return new MultipleFieldComparator(compoundComps);
- } else if (comp instanceof MultipleFieldComparator) {
- StreamEqualitor sourceEqualitor = eq;
- StreamComparator sourceComparator = ((MultipleFieldComparator) comp).getComps()[0];
-
- if (sourceEqualitor instanceof FieldEqualitor fieldEqualitor
- && sourceComparator instanceof FieldComparator fieldComparator) {
- return new FieldComparator(
- fieldEqualitor.getLeftFieldName(),
- fieldEqualitor.getRightFieldName(),
- fieldComparator.getOrder());
- } else {
- throw new IOException("Failed to create an iteration comparator");
- }
- } else {
- StreamEqualitor sourceEqualitor = eq;
- StreamComparator sourceComparator = comp;
-
- if (sourceEqualitor instanceof FieldEqualitor fieldEqualitor
- && sourceComparator instanceof FieldComparator fieldComparator) {
- return new FieldComparator(
- fieldEqualitor.getLeftFieldName(),
- fieldEqualitor.getRightFieldName(),
- fieldComparator.getOrder());
- } else {
- throw new IOException("Failed to create an iteration comparator");
- }
- }
- }
-
private StreamComparator createSideComparator(StreamEqualitor eq, StreamComparator comp)
throws IOException {
if (eq instanceof MultipleFieldEqualitor && comp instanceof MultipleFieldComparator) {
diff --git a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/ComplementStream.java b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/ComplementStream.java
index 8698099d71b..5d503d1f997 100644
--- a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/ComplementStream.java
+++ b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/ComplementStream.java
@@ -47,6 +47,7 @@ public class ComplementStream extends TupleStream implements Expressible {
private PushBackStream streamB;
private TupleStream originalStreamB;
private StreamEqualitor eq;
+ private StreamComparator crossStreamComparator;
public ComplementStream(TupleStream streamA, TupleStream streamB, StreamEqualitor eq)
throws IOException {
@@ -94,15 +95,23 @@ public class ComplementStream extends TupleStream implements Expressible {
private void init(TupleStream streamA, TupleStream streamB, StreamEqualitor eq)
throws IOException {
this.streamA = new PushBackStream(streamA);
- this.streamB = new PushBackStream(new UniqueStream(streamB, eq));
+ // dedup streamB using only its own (right-side) field(s); using the full, possibly
+ // asymmetric eq here would compare streamB's field against a field it doesn't have.
+ this.streamB =
+ new PushBackStream(new UniqueStream(streamB, StreamEqualitor.deriveRightEqualitor(eq)));
this.originalStreamB = streamB; // hold onto this for toExpression
this.eq = eq;
// streamA and streamB must both be sorted so that comp can be derived from
- if (!eq.isDerivedFrom(streamA.getStreamSort()) || !eq.isDerivedFrom(streamB.getStreamSort())) {
+ if (!eq.isDerivedFromLeft(this.streamA.getStreamSort())
+ || !eq.isDerivedFromRight(this.streamB.getStreamSort())) {
throw new IOException(
"Invalid ComplementStream - both substream comparators (sort) must be a superset of this stream's equalitor.");
}
+
+ // comparator used to order a streamA tuple against a streamB tuple; unlike either stream's own
+ // sort, it carries eq's (possibly different) left/right field names.
+ crossStreamComparator = StreamEqualitor.deriveComparator(eq, this.streamA.getStreamSort());
}
@Override
@@ -201,9 +210,12 @@ public class ComplementStream extends TupleStream implements Expressible {
}
// if a != b && a < b then we know there is no b which a might equal so return a
- if (!eq.test(a, b) && streamA.getStreamSort().compare(a, b) < 0) {
- streamB.pushBack(b);
- return a;
+ if (!eq.test(a, b)) {
+ eq.assertFieldsPresent(a, b);
+ if (crossStreamComparator.compare(a, b) < 0) {
+ streamB.pushBack(b);
+ return a;
+ }
}
// if a == b then ignore a cause it exists in b
diff --git a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/IntersectStream.java b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/IntersectStream.java
index e0fed5a49f9..f9e6680ef7f 100644
--- a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/IntersectStream.java
+++ b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/IntersectStream.java
@@ -47,6 +47,7 @@ public class IntersectStream extends TupleStream implements Expressible {
private PushBackStream streamB;
private TupleStream originalStreamB;
private StreamEqualitor eq;
+ private StreamComparator crossStreamComparator;
public IntersectStream(TupleStream streamA, TupleStream streamB, StreamEqualitor eq)
throws IOException {
@@ -94,15 +95,23 @@ public class IntersectStream extends TupleStream implements Expressible {
private void init(TupleStream streamA, TupleStream streamB, StreamEqualitor eq)
throws IOException {
this.streamA = new PushBackStream(streamA);
- this.streamB = new PushBackStream(new UniqueStream(streamB, eq));
+ // dedup streamB using only its own (right-side) field(s); using the full, possibly
+ // asymmetric eq here would compare streamB's field against a field it doesn't have.
+ this.streamB =
+ new PushBackStream(new UniqueStream(streamB, StreamEqualitor.deriveRightEqualitor(eq)));
this.originalStreamB = streamB; // hold onto this for toExpression
this.eq = eq;
// streamA and streamB must both be sorted so that comp can be derived from
- if (!eq.isDerivedFrom(streamA.getStreamSort()) || !eq.isDerivedFrom(streamB.getStreamSort())) {
+ if (!eq.isDerivedFromLeft(this.streamA.getStreamSort())
+ || !eq.isDerivedFromRight(this.streamB.getStreamSort())) {
throw new IOException(
"Invalid IntersectStream - both substream comparators (sort) must be a superset of this stream's equalitor.");
}
+
+ // comparator used to order a streamA tuple against a streamB tuple; unlike either stream's own
+ // sort, it carries eq's (possibly different) left/right field names.
+ crossStreamComparator = StreamEqualitor.deriveComparator(eq, this.streamA.getStreamSort());
}
@Override
@@ -203,13 +212,14 @@ public class IntersectStream extends TupleStream implements Expressible {
}
// We're not at the end, and they're not equal. We now need to decide which we can
- // throw away. This is accomplished by checking which is less than the other. The
- // one that is less (determined by the sort) can be tossed. The other should
- // be pushed back and the loop continued. We don't have to worry about an == 0
- // result because we already know tuples a and b are not equal. And because eq
- // is derived from the sorts of both streamA and streamB we can rest assured that
- // equality is not a possibility.
- int aComp = streamA.getStreamSort().compare(a, b);
+ // throw away. This is accomplished by checking which is less than the other, using
+ // crossStreamComparator - a comparator built from eq's (possibly different) left/right
+ // field names, since streamA's own sort comparator only knows streamA's field and would
+ // read null off of b. The one that is less can be tossed. The other should be pushed back
+ // and the loop continued. We don't have to worry about an == 0 result because we already
+ // know tuples a and b are not equal.
+ eq.assertFieldsPresent(a, b);
+ int aComp = crossStreamComparator.compare(a, b);
if (aComp < 0) {
streamB.pushBack(b);
} else {
diff --git a/solr/solrj-streaming/src/test/org/apache/solr/client/solrj/io/stream/StreamDecoratorTest.java b/solr/solrj-streaming/src/test/org/apache/solr/client/solrj/io/stream/StreamDecoratorTest.java
index 4b1acf26959..6337f626189 100644
--- a/solr/solrj-streaming/src/test/org/apache/solr/client/solrj/io/stream/StreamDecoratorTest.java
+++ b/solr/solrj-streaming/src/test/org/apache/solr/client/solrj/io/stream/StreamDecoratorTest.java
@@ -33,6 +33,8 @@ import org.apache.solr.client.solrj.io.SolrClientCache;
import org.apache.solr.client.solrj.io.Tuple;
import org.apache.solr.client.solrj.io.comp.ComparatorOrder;
import org.apache.solr.client.solrj.io.comp.FieldComparator;
+import org.apache.solr.client.solrj.io.eq.FieldEqualitor;
+import org.apache.solr.client.solrj.io.eq.StreamEqualitor;
import org.apache.solr.client.solrj.io.eval.AddEvaluator;
import org.apache.solr.client.solrj.io.eval.AndEvaluator;
import org.apache.solr.client.solrj.io.eval.EqualToEvaluator;
@@ -4895,6 +4897,120 @@ public class StreamDecoratorTest extends SolrCloudTestCase {
}
}
+ @Test
+ public void testIntersectComplementAsymmetricOn() throws Exception {
+ // Regression test: complement()/intersect() must order tuples across streamA/streamB using
+ // a comparator derived from the (possibly asymmetric) on= equalitor, not streamA's own sort
+ // comparator (whose left/right field names are both streamA's field, so comparing it against
+ // a streamB tuple always reads a missing field as null and returns a constant, non-negative
+ // result). That bug caused streamB to be fully drained the first time a streamA value that
+ // isn't present in streamB was compared, silently making complement() return all of streamA
+ // and intersect() return nothing.
+ //
+ // streamA's first value (x_i=1) is deliberately absent from streamB's y_i values, which is
+ // exactly what drained streamB under the bug. fl restricts each side's tuples so that the
+ // other side's field is genuinely absent (not merely null).
+ new UpdateRequest()
+ .add(id, "10", "a_s", "setA", "x_i", "1") // no match in streamB
+ .add(id, "11", "a_s", "setA", "x_i", "2") // matches streamB y_i=2
+ .add(id, "12", "a_s", "setA", "x_i", "4") // matches streamB y_i=4
+ .add(id, "13", "a_s", "setB", "y_i", "2")
+ .add(id, "14", "a_s", "setB", "y_i", "3")
+ .add(id, "15", "a_s", "setB", "y_i", "4")
+ .commit(cluster.getSolrClient(), COLLECTIONORALIAS);
+
+ StreamContext streamContext = new StreamContext();
+ SolrClientCache solrClientCache = new SolrClientCache();
+ streamContext.setSolrClientCache(solrClientCache);
+
+ StreamFactory factory =
+ new StreamFactory()
+ .withCollectionUseThisConnection("collection1", getSolrConnection())
+ .withFunctionName("search", CloudSolrStream.class)
+ .withFunctionName("intersect", IntersectStream.class)
+ .withFunctionName("complement", ComplementStream.class);
+
+ try {
+ StreamExpression intersectExpr =
+ StreamExpressionParser.parse(
+ "intersect("
+ + "search(collection1, q=a_s:setA, fl=\"id,x_i\", sort=\"x_i asc\"),"
+ + "search(collection1, q=a_s:setB, fl=\"id,y_i\", sort=\"y_i asc\"),"
+ + "on=\"x_i=y_i\")");
+ TupleStream intersectStream = new IntersectStream(intersectExpr, factory);
+ intersectStream.setStreamContext(streamContext);
+ List<Tuple> intersectTuples = getTuples(intersectStream);
+
+ assertEquals(2, intersectTuples.size());
+ assertOrder(intersectTuples, 11, 12);
+
+ StreamExpression complementExpr =
+ StreamExpressionParser.parse(
+ "complement("
+ + "search(collection1, q=a_s:setA, fl=\"id,x_i\", sort=\"x_i asc\"),"
+ + "search(collection1, q=a_s:setB, fl=\"id,y_i\", sort=\"y_i asc\"),"
+ + "on=\"x_i=y_i\")");
+ TupleStream complementStream = new ComplementStream(complementExpr, factory);
+ complementStream.setStreamContext(streamContext);
+ List<Tuple> complementTuples = getTuples(complementStream);
+
+ assertEquals(1, complementTuples.size());
+ assertOrder(complementTuples, 10);
+
+ // sanity check invariant: complement and intersect partition streamA
+ assertEquals(3, complementTuples.size() + intersectTuples.size());
+ } finally {
+ solrClientCache.close();
+ }
+ }
+
+ @Test
+ public void testUniqueStreamRightSideEqualitorDedup() throws Exception {
+ // Regression test: complement()/intersect() dedup streamB using an equalitor derived from
+ // only the right-hand side of the (possibly asymmetric) on= equalitor. Using the full,
+ // asymmetric equalitor directly (the pre-fix behavior) compares tuple.get(leftFieldName) - a
+ // field streamB doesn't have - against tuple.get(rightFieldName), so two equal streamB tuples
+ // never test as equal and dedup silently never fires.
+ new UpdateRequest()
+ .add(id, "20", "a_s", "setB", "y_i", "7")
+ .add(id, "21", "a_s", "setB", "y_i", "7")
+ .add(id, "22", "a_s", "setB", "y_i", "9")
+ .commit(cluster.getSolrClient(), COLLECTIONORALIAS);
+
+ StreamContext streamContext = new StreamContext();
+ SolrClientCache solrClientCache = new SolrClientCache();
+ streamContext.setSolrClientCache(solrClientCache);
+
+ StreamFactory factory =
+ new StreamFactory()
+ .withCollectionUseThisConnection("collection1", getSolrConnection())
+ .withFunctionName("search", CloudSolrStream.class);
+
+ try {
+ StreamEqualitor asymmetricEq = new FieldEqualitor("x_i", "y_i");
+ // sort includes "id asc" as a tiebreaker so which of the two y_i=7 tuples survives dedup is
+ // deterministic
+ String searchExpr =
+ "search(collection1, q=a_s:setB, fl=\"id,y_i\", sort=\"y_i asc, id asc\")";
+
+ TupleStream undeduped = new UniqueStream(factory.constructStream(searchExpr), asymmetricEq);
+ undeduped.setStreamContext(streamContext);
+ // dedup never fires against the asymmetric equalitor: the duplicate y_i=7 isn't collapsed
+ assertEquals(3, getTuples(undeduped).size());
+
+ TupleStream deduped =
+ new UniqueStream(
+ factory.constructStream(searchExpr),
+ StreamEqualitor.deriveRightEqualitor(asymmetricEq));
+ deduped.setStreamContext(streamContext);
+ List<Tuple> dedupedTuples = getTuples(deduped);
+ assertEquals(2, dedupedTuples.size());
+ assertOrder(dedupedTuples, 20, 22);
+ } finally {
+ solrClientCache.close();
+ }
+ }
+
@Test
public void testCartesianProductStream() throws Exception {
(solr) 13/17: SOLR-18394: Simplify JettyConfig construction (#4786)
Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
commit a11fc98e1b2bdd15f3119261fb1465872f4ddfc4
Author: Jan HĂžydahl <ja...@apache.org>
AuthorDate: Wed Sep 9 08:48:45 2026 +0200
SOLR-18394: Simplify JettyConfig construction (#4786)
(cherry picked from commit 6e8604569fac49cd64f50a1c89f6f222d0ef7f14)
---
.../java/org/apache/solr/embedded/JettyConfig.java | 84 +++++++++-------------
1 file changed, 34 insertions(+), 50 deletions(-)
diff --git a/solr/test-framework/src/java/org/apache/solr/embedded/JettyConfig.java b/solr/test-framework/src/java/org/apache/solr/embedded/JettyConfig.java
index 20516d7c007..258657bedbc 100644
--- a/solr/test-framework/src/java/org/apache/solr/embedded/JettyConfig.java
+++ b/solr/test-framework/src/java/org/apache/solr/embedded/JettyConfig.java
@@ -17,6 +17,7 @@
package org.apache.solr.embedded;
import jakarta.servlet.Filter;
+import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
@@ -40,29 +41,22 @@ public class JettyConfig {
/** If true, serve the Admin UI static files and index.html like the production web.xml does. */
public final boolean enableAdminUi;
- private JettyConfig(
- boolean onlyHttp1,
- int port,
- int portRetryTime,
- boolean stopAtShutdown,
- Long waitForLoadingCoresToFinishMs,
- Map<ServletHolder, String> extraServlets,
- Map<Class<? extends Filter>, String> extraFilters,
- SSLConfig sslConfig,
- boolean enableV2,
- boolean enableGracefulShutdown,
- boolean enableAdminUi) {
- this.onlyHttp1 = onlyHttp1;
- this.port = port;
- this.portRetryTime = portRetryTime;
- this.stopAtShutdown = stopAtShutdown;
- this.waitForLoadingCoresToFinishMs = waitForLoadingCoresToFinishMs;
- this.extraServlets = extraServlets;
- this.extraFilters = extraFilters;
- this.sslConfig = sslConfig;
- this.enableV2 = enableV2;
- this.enableGracefulShutdown = enableGracefulShutdown;
- this.enableAdminUi = enableAdminUi;
+ /** Snapshot of the builder that built this config; enables {@link #builder(JettyConfig)}. */
+ private final Builder builder;
+
+ private JettyConfig(Builder builder) {
+ this.builder = builder;
+ this.onlyHttp1 = builder.onlyHttp1;
+ this.port = builder.port;
+ this.portRetryTime = builder.portRetryTime;
+ this.stopAtShutdown = builder.stopAtShutdown;
+ this.waitForLoadingCoresToFinishMs = builder.waitForLoadingCoresToFinishMs;
+ this.extraServlets = Collections.unmodifiableMap(builder.extraServlets);
+ this.extraFilters = Collections.unmodifiableMap(builder.extraFilters);
+ this.sslConfig = builder.sslConfig;
+ this.enableV2 = builder.enableV2;
+ this.enableGracefulShutdown = builder.enableGracefulShutdown;
+ this.enableAdminUi = builder.enableAdminUi;
}
public static Builder builder() {
@@ -70,23 +64,10 @@ public class JettyConfig {
}
public static Builder builder(JettyConfig other) {
- Builder builder = new Builder();
-
- builder.onlyHttp1 = other.onlyHttp1;
- builder.port = other.port;
- builder.portRetryTime = other.portRetryTime;
- builder.stopAtShutdown = other.stopAtShutdown;
- builder.waitForLoadingCoresToFinishMs = other.waitForLoadingCoresToFinishMs;
- builder.extraServlets = other.extraServlets;
- builder.extraFilters = other.extraFilters;
- builder.sslConfig = other.sslConfig;
- builder.enableV2 = other.enableV2;
- builder.enableGracefulShutdown = other.enableGracefulShutdown;
- builder.enableAdminUi = other.enableAdminUi;
- return builder;
+ return other.builder.clone();
}
- public static class Builder {
+ public static class Builder implements Cloneable {
boolean onlyHttp1 = false;
int port = 0;
@@ -166,19 +147,22 @@ public class JettyConfig {
return this;
}
+ /** Copies the maps too, so the clone is fully independent; the SSLConfig is shared. */
+ @Override
+ public Builder clone() {
+ try {
+ Builder clone = (Builder) super.clone();
+ clone.extraServlets = new TreeMap<>(extraServlets);
+ clone.extraFilters = new LinkedHashMap<>(extraFilters);
+ return clone;
+ } catch (CloneNotSupportedException e) {
+ throw new AssertionError(e);
+ }
+ }
+
public JettyConfig build() {
- return new JettyConfig(
- onlyHttp1,
- port,
- portRetryTime,
- stopAtShutdown,
- waitForLoadingCoresToFinishMs,
- extraServlets,
- extraFilters,
- sslConfig,
- enableV2,
- enableGracefulShutdown,
- enableAdminUi);
+ // clone so later mutations of this builder don't leak into the built config's snapshot
+ return new JettyConfig(clone());
}
}
}
(solr) 01/17: Tracing & audit: HttpSolrCall.getQueryParams (#4870)
Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
commit dc954d8e9478779f0b6fb32a953828a7eaf868c1
Author: David Smiley <ds...@apache.org>
AuthorDate: Mon Sep 7 22:32:07 2026 -0400
Tracing & audit: HttpSolrCall.getQueryParams (#4870)
Distributed tracing and audit logging now see request parameters sent in a url-encoded POST body, not only those in the URL query string.
(cherry picked from commit b7ccc9a7af78592ada152ecd41778868b17dffd5)
---
changelog/unreleased/PR#4870-httpSolrCallGetQueryParams.yml | 10 ++++++++++
solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java | 6 +++++-
.../solr/tracing/TestDistributedTracing/testV2Api.json | 8 ++++----
.../apache/solr/opentelemetry/TestDistributedTracing.java | 12 ++++++------
4 files changed, 25 insertions(+), 11 deletions(-)
diff --git a/changelog/unreleased/PR#4870-httpSolrCallGetQueryParams.yml b/changelog/unreleased/PR#4870-httpSolrCallGetQueryParams.yml
new file mode 100644
index 00000000000..d4f29e24bf0
--- /dev/null
+++ b/changelog/unreleased/PR#4870-httpSolrCallGetQueryParams.yml
@@ -0,0 +1,10 @@
+title: >
+ Distributed tracing and audit logging now see request parameters sent in a url-encoded POST body,
+ not only those in the URL query string.
+type: changed
+authors:
+ - name: David Smiley
+ - name: Xinyao Zhang
+links:
+ - name: PR#4870
+ url: https://github.com/apache/solr/pull/4870
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 3d80367921f..cec6cf3346b 100644
--- a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
+++ b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
@@ -201,8 +201,12 @@ public class HttpSolrCall {
return core;
}
+ /**
+ * If the request has been created, return its parameters (merges URL and body if applicable);
+ * otherwise, return only the URL query parameters.
+ */
public SolrParams getQueryParams() {
- return queryParams;
+ return solrReq != null ? solrReq.getParams() : queryParams;
}
/** The collection(s) referenced in this request. Populated in {@link #init()}. Not null. */
diff --git a/solr/modules/opentelemetry/src/test-files/solr/tracing/TestDistributedTracing/testV2Api.json b/solr/modules/opentelemetry/src/test-files/solr/tracing/TestDistributedTracing/testV2Api.json
index 975aac13532..20ef31ae8ab 100644
--- a/solr/modules/opentelemetry/src/test-files/solr/tracing/TestDistributedTracing/testV2Api.json
+++ b/solr/modules/opentelemetry/src/test-files/solr/tracing/TestDistributedTracing/testV2Api.json
@@ -8,7 +8,7 @@
"db.instance":"collection1",
"children":[
{
- "name":"post:/admin/cores",
+ "name":"reload:/admin/cores",
"kind":"SERVER",
"db.instance":"collection1_shard1_replica_nN",
"db.type":"solr",
@@ -16,7 +16,7 @@
"http.response.status_code":200,
"http.url":"http://NORMALIZED/solr/admin/cores"},
{
- "name":"post:/admin/cores",
+ "name":"reload:/admin/cores",
"kind":"SERVER",
"db.instance":"collection1_shard1_replica_nN",
"db.type":"solr",
@@ -24,7 +24,7 @@
"http.response.status_code":200,
"http.url":"http://NORMALIZED/solr/admin/cores"},
{
- "name":"post:/admin/cores",
+ "name":"reload:/admin/cores",
"kind":"SERVER",
"db.instance":"collection1_shard2_replica_nN",
"db.type":"solr",
@@ -32,7 +32,7 @@
"http.response.status_code":200,
"http.url":"http://NORMALIZED/solr/admin/cores"},
{
- "name":"post:/admin/cores",
+ "name":"reload:/admin/cores",
"kind":"SERVER",
"db.instance":"collection1_shard2_replica_nN",
"db.type":"solr",
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 72f478590d2..f667729eb60 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
@@ -222,7 +222,7 @@ public class TestDistributedTracing extends SolrCloudTestCase {
var finishedSpans = getAndClearSpans(1);
var s0 = finishedSpans.remove(0);
assertCollectionName(s0, collection);
- assertEquals("post:/admin/collections", s0.getName());
+ assertEquals("create:/admin/collections", s0.getName());
Map<String, Integer> ops = new HashMap<>();
assertEquals(11, finishedSpans.size());
@@ -238,7 +238,7 @@ public class TestDistributedTracing extends SolrCloudTestCase {
ops.put(span.getName(), ops.getOrDefault(span.getName(), 0) + 1);
}
var expectedOps =
- Map.of("CreateCollectionCmd", 1, "post:/admin/cores", 4, "post:/{core}/get", 6);
+ Map.of("CreateCollectionCmd", 1, "create:/admin/cores", 4, "post:/{core}/get", 6);
assertEquals(expectedOps, ops);
}
@@ -248,13 +248,13 @@ public class TestDistributedTracing extends SolrCloudTestCase {
assertEquals(0, r1.getStatus());
// Expecting 6 spans:
- // 1. api call "name=post:/admin/collections". db.instance=testInternalCollectionApiCommands
+ // 1. api call "name=delete:/admin/collections". db.instance=testInternalCollectionApiCommands
// - unique traceId unrelated to the internal trace id generated for the operation
// 2. internal CollectionApiCommand "name=DeleteCollectionCmd"
// db.instance=testInternalCollectionApiCommands
// - this will be the parent span, all following spans will have the same traceId
//
- // 3..6 (4 times) name=post:/admin/cores
+ // 3..6 (4 times) name=unload:/admin/cores
// db.instance=testInternalCollectionApiCommands_shard2_replica_n1
// db.instance=testInternalCollectionApiCommands_shard1_replica_n2
// db.instance=testInternalCollectionApiCommands_shard2_replica_n4
@@ -263,7 +263,7 @@ public class TestDistributedTracing extends SolrCloudTestCase {
var finishedSpans = getAndClearSpans(1);
var s0 = finishedSpans.remove(0);
assertCollectionName(s0, collection);
- assertEquals("post:/admin/collections", s0.getName());
+ assertEquals("delete:/admin/collections", s0.getName());
Map<String, Integer> ops = new HashMap<>();
assertEquals(5, finishedSpans.size());
@@ -278,7 +278,7 @@ public class TestDistributedTracing extends SolrCloudTestCase {
assertEquals(span.getTraceId(), parentTraceId);
ops.put(span.getName(), ops.getOrDefault(span.getName(), 0) + 1);
}
- var expectedOps = Map.of("DeleteCollectionCmd", 1, "post:/admin/cores", 4);
+ var expectedOps = Map.of("DeleteCollectionCmd", 1, "unload:/admin/cores", 4);
assertEquals(expectedOps, ops);
}
(solr) 09/17: SOLR-18390: test-framework SolrClient accessor improvements (#4778)
Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
commit 1079929502d627fff6d9907685583a3503d57fa4
Author: Serhiy Bzhezytskyy <me...@serhiy-bzhezytskyy.com>
AuthorDate: Wed Sep 9 02:01:48 2026 +0300
SOLR-18390: test-framework SolrClient accessor improvements (#4778)
Converted many tests to use them -- any test that was using one we want to remove.
Co-authored-by: David Smiley <ds...@apache.org>
Co-authored-by: Claude Sonnet 5 <no...@anthropic.com>
(cherry picked from commit cc2d450f935c7d61621cadc3f40606d672b649de)
---
.../apache/solr/bench/lifecycle/SolrStartup.java | 7 +-
.../test/org/apache/solr/TestCpuTimeSearch.java | 5 +-
.../org/apache/solr/cli/TestSolrCLIRunExample.java | 5 +-
.../apache/solr/cloud/AliasIntegrationTest.java | 7 +-
.../apache/solr/cloud/BasicDistributedZk2Test.java | 47 +-
.../apache/solr/cloud/BasicDistributedZkTest.java | 180 +++---
.../cloud/CloudExitableDirectoryReaderTest.java | 2 +-
.../apache/solr/cloud/CollectionsAPISolrJTest.java | 19 +-
.../cloud/ConcurrentCreateRoutedAliasTest.java | 6 +-
.../solr/cloud/DeleteInactiveReplicaTest.java | 29 +-
.../DistribDocExpirationUpdateProcessorTest.java | 61 +-
.../solr/cloud/DistributedVersionInfoTest.java | 127 ++--
.../solr/cloud/FullSolrCloudDistribCmdsTest.java | 416 ++++++-------
.../solr/cloud/HttpPartitionOnCommitTest.java | 35 +-
.../org/apache/solr/cloud/HttpPartitionTest.java | 39 +-
.../cloud/LeaderFailoverAfterPartitionTest.java | 10 +-
.../org/apache/solr/cloud/MigrateReplicasTest.java | 30 +-
.../org/apache/solr/cloud/MigrateRouteKeyTest.java | 101 ++--
.../org/apache/solr/cloud/MoveReplicaTest.java | 49 +-
.../solr/cloud/NestedShardedAtomicUpdateTest.java | 9 +-
.../apache/solr/cloud/RemoteQueryErrorTest.java | 19 +-
.../org/apache/solr/cloud/ReplaceNodeTest.java | 24 +-
.../apache/solr/cloud/ReplicationFactorTest.java | 31 +-
.../test/org/apache/solr/cloud/SplitShardTest.java | 16 +-
.../apache/solr/cloud/TestBaseStatsCacheCloud.java | 79 ++-
.../apache/solr/cloud/TestCloudConsistency.java | 25 +-
.../apache/solr/cloud/TestCloudDeleteByQuery.java | 46 +-
.../TestCloudPhrasesIdentificationComponent.java | 2 +-
.../solr/cloud/TestCloudPseudoReturnFields.java | 2 +-
.../org/apache/solr/cloud/TestCloudRecovery2.java | 33 +-
.../org/apache/solr/cloud/TestConfigSetsAPI.java | 114 ++--
.../solr/cloud/TestConfigSetsAPIExclusivity.java | 8 +-
.../solr/cloud/TestConfigSetsAPIZkFailure.java | 5 +-
.../solr/cloud/TestGracefulJettyShutdown.java | 4 +-
.../solr/cloud/TestMiniSolrCloudClusterSSL.java | 2 +-
.../org/apache/solr/cloud/TestPullReplica.java | 111 ++--
.../solr/cloud/TestPullReplicaErrorHandling.java | 37 +-
.../apache/solr/cloud/TestPullReplicaWithAuth.java | 10 +-
.../solr/cloud/TestQueryingOnDownCollection.java | 59 +-
.../cloud/TestStressCloudBlindAtomicUpdates.java | 13 +-
.../solr/cloud/TestTlogReplayVsRecovery.java | 22 +-
.../org/apache/solr/cloud/TestTlogReplica.java | 138 +++--
.../cloud/TestTolerantUpdateProcessorCloud.java | 26 +-
.../TestTolerantUpdateProcessorRandomCloud.java | 11 +-
.../apache/solr/cloud/UnloadDistributedZkTest.java | 132 ++---
.../solr/cloud/ZkShardTermsRecoveryTest.java | 11 +-
.../ConcurrentDeleteAndCreateCollectionTest.java | 6 +-
.../solr/cloud/api/collections/ShardSplitTest.java | 330 +++++------
.../org/apache/solr/core/TestCustomStream.java | 17 +-
.../core/snapshots/TestSolrCloudSnapshots.java | 32 +-
.../solr/core/snapshots/TestSolrCoreSnapshots.java | 265 ++++-----
.../solr/filestore/TestDistribFileStore.java | 23 +-
.../solr/handler/TestReplicationHandler.java | 56 +-
.../solr/handler/TestStressIncrementalBackup.java | 11 +-
.../solr/handler/TestStressThreadBackup.java | 11 +-
.../org/apache/solr/handler/V2StandaloneTest.java | 17 +-
.../solr/handler/admin/CoreAdminHandlerTest.java | 11 +-
.../solr/handler/admin/HealthCheckHandlerTest.java | 34 +-
.../solr/handler/admin/LukeHandlerCloudTest.java | 29 +-
.../solr/handler/component/UpdateLogCloudTest.java | 6 +-
.../solr/metrics/SolrMetricsIntegrationTest.java | 43 +-
.../response/TestPrometheusResponseWriter.java | 154 +++--
.../apache/solr/response/TestRawTransformer.java | 4 +-
.../schema/ManagedSchemaRoundRobinCloudTest.java | 27 +-
.../apache/solr/search/TestCoordinatorRole.java | 464 ++++++++-------
.../search/facet/TestCloudJSONFacetJoinDomain.java | 2 +-
.../solr/search/facet/TestCloudJSONFacetSKG.java | 2 +-
.../search/facet/TestCloudJSONFacetSKGEquiv.java | 2 +-
.../apache/solr/search/stats/TestDistribIDF.java | 105 ++--
.../solr/security/BasicAuthIntegrationTest.java | 15 +-
.../solr/security/BasicAuthStandaloneTest.java | 99 ++--
.../apache/solr/security/MultiAuthPluginTest.java | 658 ++++++++++-----------
.../solr/update/DeleteByIdWithRouterFieldTest.java | 28 +-
.../update/processor/TestCloudDeduplication.java | 2 +-
.../apache/solr/client/solrj/SolrExampleTests.java | 12 +-
.../solr/client/solrj/SolrExampleTestsBase.java | 6 +-
.../solrj/impl/CloudHttp2SolrClientTest.java | 104 ++--
.../solrj/impl/HttpSolrClientBadInputTest.java | 80 +--
.../solr/client/solrj/impl/LB2SolrClientTest.java | 4 +-
.../apache/solr/BaseDistributedSearchTestCase.java | 5 +-
.../src/java/org/apache/solr/SolrTestCaseHS.java | 4 +-
.../src/java/org/apache/solr/SolrTestCaseJ4.java | 48 --
.../solr/cloud/AbstractFullDistribZkTestBase.java | 28 +-
.../apache/solr/cloud/MiniSolrCloudCluster.java | 38 +-
...bstractCollectionsAPIDistributedZkTestBase.java | 15 +-
.../org/apache/solr/embedded/JettySolrRunner.java | 17 +-
.../org/apache/solr/util/SolrJMetricTestUtils.java | 6 +-
.../apache/solr/embedded/TestJettySolrRunner.java | 11 +-
.../webapp/AdminUiCoreAdminStandaloneTest.java | 19 +-
.../apache/solr/webapp/AdminUiQueryScreenTest.java | 4 +-
.../webapp/AdminUiReplicationStandaloneTest.java | 23 +-
.../solr/webapp/AdminUiSecurityAuthTest.java | 9 +-
.../org/apache/solr/webapp/AdminUiTestBase.java | 7 +-
93 files changed, 2356 insertions(+), 2701 deletions(-)
diff --git a/solr/benchmark/src/java/org/apache/solr/bench/lifecycle/SolrStartup.java b/solr/benchmark/src/java/org/apache/solr/bench/lifecycle/SolrStartup.java
index d0bd64d56ba..359be6e2e68 100644
--- a/solr/benchmark/src/java/org/apache/solr/bench/lifecycle/SolrStartup.java
+++ b/solr/benchmark/src/java/org/apache/solr/bench/lifecycle/SolrStartup.java
@@ -78,10 +78,9 @@ public class SolrStartup {
solrRunner = new JettySolrRunner(tmpSolrHome.toString(), buildJettyConfig());
solrRunner.start(false);
- try (SolrClient client = solrRunner.newClient()) {
- for (int i = 0; i < NUM_CORES; i++) {
- createCore(client, "core-prefix-" + i);
- }
+ SolrClient client = solrRunner.getSolrClient();
+ for (int i = 0; i < NUM_CORES; i++) {
+ createCore(client, "core-prefix-" + i);
}
solrRunner.stop();
}
diff --git a/solr/core/src/test/org/apache/solr/TestCpuTimeSearch.java b/solr/core/src/test/org/apache/solr/TestCpuTimeSearch.java
index 427205d300c..fec884f0afa 100644
--- a/solr/core/src/test/org/apache/solr/TestCpuTimeSearch.java
+++ b/solr/core/src/test/org/apache/solr/TestCpuTimeSearch.java
@@ -18,7 +18,6 @@ package org.apache.solr;
import java.io.IOException;
import java.util.List;
-import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.SolrQuery;
@@ -100,9 +99,7 @@ public class TestCpuTimeSearch extends SolrCloudTestCase {
coll.getSlices().stream()
.flatMap(s -> s.getReplicas().stream())
.toArray(Replica[]::new));
- try (SolrClient client = getHttpSolrClient(randomReplica.getCoreUrl())) {
- response = client.query(query);
- }
+ response = cluster.getSolrClient(randomReplica).query(query);
SolrDocumentList results = response.getResults();
int size = results.size();
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 7a7f105c084..2e2157878ae 100644
--- a/solr/core/src/test/org/apache/solr/cli/TestSolrCLIRunExample.java
+++ b/solr/core/src/test/org/apache/solr/cli/TestSolrCLIRunExample.java
@@ -39,6 +39,7 @@ import org.apache.lucene.tests.util.LuceneTestCase;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.jetty.HttpJettySolrClient;
import org.apache.solr.client.solrj.request.SolrQuery;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.cloud.MiniSolrCloudCluster;
@@ -376,7 +377,9 @@ public class TestSolrCLIRunExample extends SolrTestCaseJ4 {
if ("techproducts".equals(exampleName)) {
try (SolrClient solrClient =
- getHttpSolrClient("http://localhost:" + bindPort + "/solr", exampleName)) {
+ new HttpJettySolrClient.Builder("http://localhost:" + bindPort + "/solr")
+ .withDefaultCollection(exampleName)
+ .build()) {
SolrQuery query = new SolrQuery("*:*");
QueryResponse qr = solrClient.query(query);
long numFound = qr.getResults().getNumFound();
diff --git a/solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java b/solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java
index 7f2fa3b1de1..ceb0bdb7184 100644
--- a/solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java
@@ -960,13 +960,12 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
// HttpSolrClient
JettySolrRunner jetty = cluster.getRandomJetty(random());
if (random().nextBoolean()) {
- try (SolrClient client = getHttpSolrClient(jetty.getBaseUrl().toString(), collectionList)) {
+ try (SolrClient client = jetty.newSolrClient(collectionList)) {
responseConsumer.accept(client.query(null, solrQuery));
}
} else {
- try (SolrClient client = getHttpSolrClient(jetty.getBaseUrl().toString())) {
- responseConsumer.accept(client.query(collectionList, solrQuery));
- }
+ SolrClient client = jetty.getSolrClient();
+ responseConsumer.accept(client.query(collectionList, solrQuery));
}
// Recursively do again; this time with the &collection= param
diff --git a/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZk2Test.java b/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZk2Test.java
index 61edcfa0f1f..d4c1ad631ed 100644
--- a/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZk2Test.java
+++ b/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZk2Test.java
@@ -210,18 +210,17 @@ public class BasicDistributedZk2Test extends AbstractFullDistribZkTestBase {
int docs = 2;
for (JettySolrRunner jetty : jettys) {
- final String clientUrl = getBaseUrl(jetty);
- addAndQueryDocs(clientUrl, docs);
+ addAndQueryDocs(jetty, docs);
docs += 2;
}
}
// 2 docs added every call
- private void addAndQueryDocs(final String baseUrl, int docs) throws Exception {
+ private void addAndQueryDocs(final JettySolrRunner jetty, int docs) throws Exception {
SolrQuery query = new SolrQuery("*:*");
- try (SolrClient client = getHttpSolrClient(baseUrl, "onenodecollection")) {
+ try (SolrClient client = jetty.newSolrClient("onenodecollection")) {
// add a doc
client.add(sdoc("id", docs));
client.commit();
@@ -441,27 +440,25 @@ public class BasicDistributedZk2Test extends AbstractFullDistribZkTestBase {
checkShardConsistency(true, false);
// try a backup command
- try (final SolrClient client =
- getHttpSolrClient((String) shardToJetty.get(SHARD2).get(0).info.get("base_url"))) {
- final String backupName = "the_backup";
- ModifiableSolrParams params = new ModifiableSolrParams();
- params.set("command", "backup");
- params.set("name", backupName);
- final Path location = FilterPath.unwrap(createTempDir()).toRealPath();
- // Allow non-standard location outside SOLR_HOME
- jettys.forEach(j -> j.getCoreContainer().getAllowPaths().add(location));
- params.set("location", location.toString());
-
- QueryRequest request = new QueryRequest(ReplicationHandler.PATH, params);
- client.request(request, DEFAULT_TEST_COLLECTION_NAME);
-
- final BackupStatusChecker backupStatus =
- new BackupStatusChecker(client, "/" + DEFAULT_TEST_COLLECTION_NAME + "/replication");
- final String backupDirName = backupStatus.waitForBackupSuccess(backupName, 30);
- assertTrue(
- "Backup dir does not exist: " + backupDirName,
- Files.exists(location.resolve(backupDirName)));
- }
+ final SolrClient client = shardToJetty.get(SHARD2).get(0).jetty.getSolrClient();
+ final String backupName = "the_backup";
+ ModifiableSolrParams params = new ModifiableSolrParams();
+ params.set("command", "backup");
+ params.set("name", backupName);
+ final Path location = FilterPath.unwrap(createTempDir()).toRealPath();
+ // Allow non-standard location outside SOLR_HOME
+ jettys.forEach(j -> j.getCoreContainer().getAllowPaths().add(location));
+ params.set("location", location.toString());
+
+ QueryRequest request = new QueryRequest(ReplicationHandler.PATH, params);
+ client.request(request, DEFAULT_TEST_COLLECTION_NAME);
+
+ final BackupStatusChecker backupStatus =
+ new BackupStatusChecker(client, "/" + DEFAULT_TEST_COLLECTION_NAME + "/replication");
+ final String backupDirName = backupStatus.waitForBackupSuccess(backupName, 30);
+ assertTrue(
+ "Backup dir does not exist: " + backupDirName,
+ Files.exists(location.resolve(backupDirName)));
}
private void addNewReplica() throws Exception {
diff --git a/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java b/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java
index a21f4938228..f392491ca4d 100644
--- a/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java
@@ -36,7 +36,6 @@ import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.lucene.util.IOUtils;
@@ -49,7 +48,6 @@ import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.request.AbstractUpdateRequest;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
-import org.apache.solr.client.solrj.request.CoreAdminRequest.Create;
import org.apache.solr.client.solrj.request.CoreAdminRequest.Unload;
import org.apache.solr.client.solrj.request.GenericSolrRequest;
import org.apache.solr.client.solrj.request.MetricsRequest;
@@ -111,8 +109,6 @@ public class BasicDistributedZkTest extends AbstractFullDistribZkTestBase {
private String oneInstanceCollection = "oneInstanceCollection";
private String oneInstanceCollection2 = "oneInstanceCollection2";
- private AtomicInteger nodeCounter = new AtomicInteger();
-
CompletionService<Object> completionService;
Set<Future<Object>> pending;
@@ -914,18 +910,17 @@ public class BasicDistributedZkTest extends AbstractFullDistribZkTestBase {
for (Slice slice : dColl.getActiveSlices()) {
long sliceDocCount = -1;
for (Replica rep : slice.getReplicas()) {
- try (SolrClient one = getHttpSolrClient(rep)) {
- SolrQuery query = new SolrQuery("*:*");
- query.setDistrib(false);
- QueryResponse resp = one.query(query);
- long hits = resp.getResults().getNumFound();
- if (sliceDocCount == -1) {
- sliceDocCount = hits;
- docTotal += hits;
- } else {
- if (hits != sliceDocCount) {
- return -1;
- }
+ SolrClient one = getSolrClient(rep);
+ SolrQuery query = new SolrQuery("*:*");
+ query.setDistrib(false);
+ QueryResponse resp = one.query(query);
+ long hits = resp.getResults().getNumFound();
+ if (sliceDocCount == -1) {
+ sliceDocCount = hits;
+ docTotal += hits;
+ } else {
+ if (hits != sliceDocCount) {
+ return -1;
}
}
}
@@ -1043,26 +1038,25 @@ public class BasicDistributedZkTest extends AbstractFullDistribZkTestBase {
private void testStopAndStartCoresInOneInstance() throws Exception {
JettySolrRunner jetty = jettys.get(0);
- try (final var httpSolrClient = jetty.newClient(15000, 60000)) {
- ThreadPoolExecutor executor = null;
- try {
- executor =
- new ExecutorUtil.MDCAwareThreadPoolExecutor(
- 0,
- Integer.MAX_VALUE,
- 5,
- TimeUnit.SECONDS,
- new SynchronousQueue<Runnable>(),
- new SolrNamedThreadFactory("testExecutor"));
- int cnt = 3;
-
- // create the cores
- createCollectionInOneInstance(
- httpSolrClient, jetty.getNodeName(), executor, "multiunload2", 1, cnt);
- } finally {
- if (executor != null) {
- ExecutorUtil.shutdownAndAwaitTermination(executor);
- }
+ var httpSolrClient = jetty.getSolrClient();
+ ThreadPoolExecutor executor = null;
+ try {
+ executor =
+ new ExecutorUtil.MDCAwareThreadPoolExecutor(
+ 0,
+ Integer.MAX_VALUE,
+ 5,
+ TimeUnit.SECONDS,
+ new SynchronousQueue<Runnable>(),
+ new SolrNamedThreadFactory("testExecutor"));
+ int cnt = 3;
+
+ // create the cores
+ createCollectionInOneInstance(
+ httpSolrClient, jetty.getNodeName(), executor, "multiunload2", 1, cnt);
+ } finally {
+ if (executor != null) {
+ ExecutorUtil.shutdownAndAwaitTermination(executor);
}
}
@@ -1379,47 +1373,46 @@ public class BasicDistributedZkTest extends AbstractFullDistribZkTestBase {
.getLeader("shard1");
// now test that unloading a core gets us a new leader
- try (SolrClient unloadClient = jettys.getFirst().newClient(15000, 60000)) {
- Unload unloadCmd = new Unload(true);
- unloadCmd.setCoreName(leader.getCoreName());
-
- String leaderUrl = leader.getCoreUrl();
-
- testExecutor.execute(
- new Runnable() {
-
- @Override
- public void run() {
- try {
- unloadClient.request(unloadCmd);
- } catch (SolrServerException e) {
- throw new RuntimeException(e);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ SolrClient unloadClient = jettys.getFirst().getSolrClient();
+ Unload unloadCmd = new Unload(true);
+ unloadCmd.setCoreName(leader.getCoreName());
+
+ String leaderUrl = leader.getCoreUrl();
+
+ testExecutor.execute(
+ new Runnable() {
+
+ @Override
+ public void run() {
+ try {
+ unloadClient.request(unloadCmd);
+ } catch (SolrServerException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
}
- });
+ }
+ });
- try {
- ZkStateReader.from(getCommonCloudSolrClient())
- .waitForState(
- oneInstanceCollection2,
- 20000,
- TimeUnit.MILLISECONDS,
- (n, c) -> {
- try {
- if (leaderUrl.equals(
- zkStateReader.getLeaderUrl(oneInstanceCollection2, "shard1", 10000))) {
- return false;
- }
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
+ try {
+ ZkStateReader.from(getCommonCloudSolrClient())
+ .waitForState(
+ oneInstanceCollection2,
+ 20000,
+ TimeUnit.MILLISECONDS,
+ (n, c) -> {
+ try {
+ if (leaderUrl.equals(
+ zkStateReader.getLeaderUrl(oneInstanceCollection2, "shard1", 10000))) {
+ return false;
}
- return true;
- });
- } catch (TimeoutException | InterruptedException e) {
- fail("Leader never changed");
- }
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ return true;
+ });
+ } catch (TimeoutException | InterruptedException e) {
+ fail("Leader never changed");
}
IOUtils.close(collectionClients);
@@ -1497,45 +1490,6 @@ public class BasicDistributedZkTest extends AbstractFullDistribZkTestBase {
IOUtils.close(collectionClients);
}
- private void createSolrCore(
- final String collection,
- List<SolrClient> collectionClients,
- final String baseUrl,
- final int num,
- final String shardId) {
- Callable<Object> call =
- () -> {
- try (SolrClient client = getHttpSolrClient(baseUrl)) {
- // client.setConnectionTimeout(15000);
- Create createCmd = new Create();
- createCmd.setCoreName(collection + num);
- createCmd.setCollection(collection);
-
- if (random().nextBoolean()) {
- // sometimes we use an explicit core node name
- createCmd.setCoreNodeName("anode" + nodeCounter.incrementAndGet());
- }
-
- if (shardId == null) {
- createCmd.setNumShards(2);
- }
- createCmd.setDataDir(getDataDir(createTempDir(collection).toString()));
- if (shardId != null) {
- createCmd.setShardId(shardId);
- }
- client.request(createCmd);
- } catch (Exception e) {
- log.error("error creating core", e);
- // fail
- }
- return null;
- };
-
- pending.add(completionService.submit(call));
-
- collectionClients.add(createNewSolrClient(baseUrl, collection + num));
- }
-
private void testMultipleCollections() throws Exception {
log.info("### STARTING testMultipleCollections");
// create another 2 collections and search across them
diff --git a/solr/core/src/test/org/apache/solr/cloud/CloudExitableDirectoryReaderTest.java b/solr/core/src/test/org/apache/solr/cloud/CloudExitableDirectoryReaderTest.java
index 24d02a389cf..28bd7dc9d4b 100644
--- a/solr/core/src/test/org/apache/solr/cloud/CloudExitableDirectoryReaderTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/CloudExitableDirectoryReaderTest.java
@@ -81,7 +81,7 @@ public class CloudExitableDirectoryReaderTest extends SolrCloudTestCase {
clusterBuilder.configure();
// pick an arbitrary node to use for our requests
- client = cluster.getRandomJetty(random()).newClient();
+ client = cluster.getRandomJetty(random()).newSolrClient(null);
CollectionAdminRequest.createCollection(COLLECTION, "conf", 2, 1)
.processAndWait(cluster.getSolrClient(), DEFAULT_TIMEOUT);
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 44c24de9b10..077d4a6f557 100644
--- a/solr/core/src/test/org/apache/solr/cloud/CollectionsAPISolrJTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/CollectionsAPISolrJTest.java
@@ -296,17 +296,16 @@ public class CollectionsAPISolrJTest extends SolrCloudTestCase {
cluster.waitForActiveCollection(collectionName, 2, 4);
- String nodeName = response._getStr("success[0]/key");
- String corename = response._getStr(asList("success", nodeName, "core"), null);
+ String successKey = response._getStr("success[0]/key"); // "nodeName/coreNodeName"
+ String corename = response._getStr(asList("success", successKey, "core"), null);
+ String nodeName = successKey.substring(0, successKey.indexOf('/'));
- try (SolrClient coreClient =
- getHttpSolrClient(cluster.getZkStateReader().getBaseUrlForNodeName(nodeName))) {
- CoreAdminResponse status = CoreAdminRequest.getStatus(corename, coreClient);
- assertEquals(
- collectionName, status._get(asList("status", corename, "cloud", "collection"), null));
- assertNotNull(status._get(asList("status", corename, "cloud", "shard"), null));
- assertNotNull(status._get(asList("status", corename, "cloud", "replica"), null));
- }
+ SolrClient coreClient = cluster.getJetty(nodeName).getSolrClient();
+ CoreAdminResponse status = CoreAdminRequest.getStatus(corename, coreClient);
+ assertEquals(
+ collectionName, status._get(asList("status", corename, "cloud", "collection"), null));
+ assertNotNull(status._get(asList("status", corename, "cloud", "shard"), null));
+ assertNotNull(status._get(asList("status", corename, "cloud", "replica"), null));
}
@Test
diff --git a/solr/core/src/test/org/apache/solr/cloud/ConcurrentCreateRoutedAliasTest.java b/solr/core/src/test/org/apache/solr/cloud/ConcurrentCreateRoutedAliasTest.java
index 504bfd94fac..50a177d5eff 100644
--- a/solr/core/src/test/org/apache/solr/cloud/ConcurrentCreateRoutedAliasTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/ConcurrentCreateRoutedAliasTest.java
@@ -95,8 +95,7 @@ public class ConcurrentCreateRoutedAliasTest extends SolrTestCaseJ4 {
int numStart = num;
for (; num < threads.length + numStart; num++) {
final String aliasName = "testAlias" + num;
- final String baseUrl = solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString();
- final SolrClient solrClient = getHttpSolrClient(baseUrl);
+ final SolrClient solrClient = solrCluster.getJettySolrRunners().get(0).newSolrClient(null);
int i = num - numStart;
threads[i] =
@@ -119,8 +118,7 @@ public class ConcurrentCreateRoutedAliasTest extends SolrTestCaseJ4 {
System.out.println("NUM ==> " + num);
for (; num < threads.length + numStart; num++) {
final String aliasName = "testAliasCplx" + num;
- final String baseUrl = solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString();
- final SolrClient solrClient = getHttpSolrClient(baseUrl);
+ final SolrClient solrClient = solrCluster.getJettySolrRunners().get(0).newSolrClient(null);
int i = num - numStart;
threads[i] =
diff --git a/solr/core/src/test/org/apache/solr/cloud/DeleteInactiveReplicaTest.java b/solr/core/src/test/org/apache/solr/cloud/DeleteInactiveReplicaTest.java
index e84e9e436dc..35b017aef12 100644
--- a/solr/core/src/test/org/apache/solr/cloud/DeleteInactiveReplicaTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/DeleteInactiveReplicaTest.java
@@ -108,20 +108,19 @@ public class DeleteInactiveReplicaTest extends SolrCloudTestCase {
&& !FileUtils.fileExists(replicaCd.getDataDir()));
// Check that we can't create a core with no coreNodeName
- try (SolrClient queryClient = getHttpSolrClient(jetty.getBaseUrl().toString())) {
- Exception e =
- expectThrows(
- Exception.class,
- () -> {
- CoreAdminRequest.Create createRequest = new CoreAdminRequest.Create();
- createRequest.setCoreName("testcore");
- createRequest.setCollection(collectionName);
- createRequest.setShardId("shard2");
- queryClient.request(createRequest);
- });
- assertTrue(
- "Unexpected error message: " + e.getMessage(),
- e.getMessage().contains("coreNodeName missing"));
- }
+ SolrClient queryClient = jetty.getSolrClient();
+ Exception e =
+ expectThrows(
+ Exception.class,
+ () -> {
+ CoreAdminRequest.Create createRequest = new CoreAdminRequest.Create();
+ createRequest.setCoreName("testcore");
+ createRequest.setCollection(collectionName);
+ createRequest.setShardId("shard2");
+ queryClient.request(createRequest);
+ });
+ assertTrue(
+ "Unexpected error message: " + e.getMessage(),
+ e.getMessage().contains("coreNodeName missing"));
}
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/DistribDocExpirationUpdateProcessorTest.java b/solr/core/src/test/org/apache/solr/cloud/DistribDocExpirationUpdateProcessorTest.java
index 821548e1238..ef5d87ae29b 100644
--- a/solr/core/src/test/org/apache/solr/cloud/DistribDocExpirationUpdateProcessorTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/DistribDocExpirationUpdateProcessorTest.java
@@ -289,37 +289,36 @@ public class DistribDocExpirationUpdateProcessorTest extends SolrCloudTestCase {
for (Replica replica : slice.getReplicas()) {
String coreName = replica.getCoreName();
- try (SolrClient client = getHttpSolrClient(replica)) {
-
- ModifiableSolrParams params = new ModifiableSolrParams();
- params.set("command", "indexversion");
- params.set("_trace", "getIndexVersion");
- QueryRequest req = setAuthIfNeeded(new QueryRequest(ReplicationHandler.PATH, params));
-
- NamedList<Object> res = client.request(req);
- assertNotNull("null response from server: " + coreName, res);
-
- Object version = res.get("indexversion");
- assertNotNull("null version from server: " + coreName, version);
- assertTrue("version isn't a long: " + coreName, version instanceof Long);
-
- long numDocs =
- setAuthIfNeeded(
- new QueryRequest(
- params(
- "q", "*:*",
- "distrib", "false",
- "rows", "0",
- "_trace", "counting_docs")))
- .process(client)
- .getResults()
- .getNumFound();
-
- final ReplicaData data =
- new ReplicaData(replica.getShard(), coreName, (Long) version, numDocs);
- log.info("{}", data);
- results.put(coreName, data);
- }
+ SolrClient client = cluster.getSolrClient(replica);
+
+ ModifiableSolrParams params = new ModifiableSolrParams();
+ params.set("command", "indexversion");
+ params.set("_trace", "getIndexVersion");
+ QueryRequest req = setAuthIfNeeded(new QueryRequest(ReplicationHandler.PATH, params));
+
+ NamedList<Object> res = client.request(req);
+ assertNotNull("null response from server: " + coreName, res);
+
+ Object version = res.get("indexversion");
+ assertNotNull("null version from server: " + coreName, version);
+ assertTrue("version isn't a long: " + coreName, version instanceof Long);
+
+ long numDocs =
+ setAuthIfNeeded(
+ new QueryRequest(
+ params(
+ "q", "*:*",
+ "distrib", "false",
+ "rows", "0",
+ "_trace", "counting_docs")))
+ .process(client)
+ .getResults()
+ .getNumFound();
+
+ final ReplicaData data =
+ new ReplicaData(replica.getShard(), coreName, (Long) version, numDocs);
+ log.info("{}", data);
+ results.put(coreName, data);
}
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/DistributedVersionInfoTest.java b/solr/core/src/test/org/apache/solr/cloud/DistributedVersionInfoTest.java
index a67f0c0495e..7c557eb5166 100644
--- a/solr/core/src/test/org/apache/solr/cloud/DistributedVersionInfoTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/DistributedVersionInfoTest.java
@@ -110,32 +110,29 @@ public class DistributedVersionInfoTest extends SolrCloudTestCase {
maxOnReplica);
// send the same doc but with a lower version than the max in the index
- try (SolrClient client = getHttpSolrClient(replica)) {
- String docId = String.valueOf(1);
- SolrInputDocument doc = new SolrInputDocument();
- doc.setField("id", docId);
- doc.setField("_version_", maxOnReplica - 1); // bad version!!!
-
- // simulate what the leader does when sending a doc to a replica
- ModifiableSolrParams params = new ModifiableSolrParams();
- params.set(
- DISTRIB_UPDATE_PARAM, DistributedUpdateProcessor.DistribPhase.FROMLEADER.toString());
- params.set(DISTRIB_FROM, leader.getCoreUrl());
-
- UpdateRequest req = new UpdateRequest();
- req.setParams(params);
- req.add(doc);
-
- log.info(
- "Sending doc with out-of-date version ({}) document directly to replica",
- maxOnReplica - 1);
-
- client.request(req);
- client.commit();
-
- Long docVersion = getVersionFromIndex(replica, docId);
- assertEquals("older version should have been thrown away", maxOnReplica, docVersion);
- }
+ SolrClient client = cluster.getSolrClient(replica);
+ String docId = String.valueOf(1);
+ SolrInputDocument doc = new SolrInputDocument();
+ doc.setField("id", docId);
+ doc.setField("_version_", maxOnReplica - 1); // bad version!!!
+
+ // simulate what the leader does when sending a doc to a replica
+ ModifiableSolrParams params = new ModifiableSolrParams();
+ params.set(DISTRIB_UPDATE_PARAM, DistributedUpdateProcessor.DistribPhase.FROMLEADER.toString());
+ params.set(DISTRIB_FROM, leader.getCoreUrl());
+
+ UpdateRequest req = new UpdateRequest();
+ req.setParams(params);
+ req.add(doc);
+
+ log.info(
+ "Sending doc with out-of-date version ({}) document directly to replica", maxOnReplica - 1);
+
+ client.request(req);
+ client.commit();
+
+ Long docVersion = getVersionFromIndex(replica, docId);
+ assertEquals("older version should have been thrown away", maxOnReplica, docVersion);
reloadCollection(leader, COLLECTION);
@@ -301,13 +298,12 @@ public class DistributedVersionInfoTest extends SolrCloudTestCase {
query.addSort(new SolrQuery.SortClause("_version_", SolrQuery.ORDER.desc));
query.setParam("distrib", false);
- try (SolrClient client = getHttpSolrClient(replica)) {
- QueryResponse qr = client.query(query);
- SolrDocumentList hits = qr.getResults();
- if (hits.isEmpty()) fail("No results returned from query: " + query);
+ SolrClient client = cluster.getSolrClient(replica);
+ QueryResponse qr = client.query(query);
+ SolrDocumentList hits = qr.getResults();
+ if (hits.isEmpty()) fail("No results returned from query: " + query);
- vers = (Long) hits.get(0).getFirstValue("_version_");
- }
+ vers = (Long) hits.get(0).getFirstValue("_version_");
if (vers == null)
fail("Failed to get version using query " + query + " from " + replica.getCoreUrl());
@@ -323,27 +319,18 @@ public class DistributedVersionInfoTest extends SolrCloudTestCase {
int lastDocId,
Set<Integer> deletedDocs)
throws Exception {
- SolrClient leaderSolr = getHttpSolrClient(leader);
+ SolrClient leaderSolr = cluster.getSolrClient(leader);
List<SolrClient> replicas = new ArrayList<SolrClient>(notLeaders.size());
- for (Replica r : notLeaders) replicas.add(getHttpSolrClient(r));
+ for (Replica r : notLeaders) replicas.add(cluster.getSolrClient(r));
- try {
- for (int d = firstDocId; d <= lastDocId; d++) {
+ for (int d = firstDocId; d <= lastDocId; d++) {
- if (deletedDocs != null && deletedDocs.contains(d)) continue;
+ if (deletedDocs != null && deletedDocs.contains(d)) continue;
- String docId = String.valueOf(d);
- Long leaderVers = assertDocExists(leaderSolr, docId, null);
- for (SolrClient replicaSolr : replicas) {
- assertDocExists(replicaSolr, docId, leaderVers);
- }
- }
- } finally {
- if (leaderSolr != null) {
- leaderSolr.close();
- }
+ String docId = String.valueOf(d);
+ Long leaderVers = assertDocExists(leaderSolr, docId, null);
for (SolrClient replicaSolr : replicas) {
- replicaSolr.close();
+ assertDocExists(replicaSolr, docId, leaderVers);
}
}
}
@@ -379,30 +366,30 @@ public class DistributedVersionInfoTest extends SolrCloudTestCase {
protected boolean reloadCollection(Replica replica, String testCollectionName) throws Exception {
String coreName = replica.getCoreName();
boolean reloadedOk = false;
- try (SolrClient client = getHttpSolrClient(replica.getBaseUrl())) {
- CoreAdminResponse statusResp = CoreAdminRequest.getStatus(coreName, client);
- long leaderCoreStartTime = statusResp.getStartTime(coreName).getTime();
-
- Thread.sleep(1000);
-
- // send reload command for the collection
- log.info("Sending RELOAD command for {}", testCollectionName);
- CollectionAdminRequest.reloadCollection(testCollectionName).process(client);
- Thread.sleep(2000); // reload can take a short while
-
- // verify reload is done, waiting up to 30 seconds for slow test environments
- long timeout = System.nanoTime() + TimeUnit.NANOSECONDS.convert(30, TimeUnit.SECONDS);
- while (System.nanoTime() < timeout) {
- statusResp = CoreAdminRequest.getStatus(coreName, client);
- long startTimeAfterReload = statusResp.getStartTime(coreName).getTime();
- if (startTimeAfterReload > leaderCoreStartTime) {
- reloadedOk = true;
- break;
- }
- // else ... still waiting to see the reloaded core report a later start time
- Thread.sleep(1000);
+ SolrClient client = cluster.getSolrClient(replica);
+ CoreAdminResponse statusResp = CoreAdminRequest.getStatus(coreName, client);
+ long leaderCoreStartTime = statusResp.getStartTime(coreName).getTime();
+
+ Thread.sleep(1000);
+
+ // send reload command for the collection
+ log.info("Sending RELOAD command for {}", testCollectionName);
+ CollectionAdminRequest.reloadCollection(testCollectionName).process(client);
+ Thread.sleep(2000); // reload can take a short while
+
+ // verify reload is done, waiting up to 30 seconds for slow test environments
+ long timeout = System.nanoTime() + TimeUnit.NANOSECONDS.convert(30, TimeUnit.SECONDS);
+ while (System.nanoTime() < timeout) {
+ statusResp = CoreAdminRequest.getStatus(coreName, client);
+ long startTimeAfterReload = statusResp.getStartTime(coreName).getTime();
+ if (startTimeAfterReload > leaderCoreStartTime) {
+ reloadedOk = true;
+ break;
}
+ // else ... still waiting to see the reloaded core report a later start time
+ Thread.sleep(1000);
}
+
return reloadedOk;
}
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java b/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java
index cb5bee46878..84de1bb043c 100644
--- a/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java
@@ -31,6 +31,7 @@ import org.apache.lucene.tests.util.TestUtil;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.apache.solr.client.solrj.jetty.ConcurrentUpdateJettySolrClient;
+import org.apache.solr.client.solrj.jetty.HttpJettySolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.SolrQuery;
import org.apache.solr.client.solrj.request.UpdateRequest;
@@ -170,106 +171,105 @@ public class FullSolrCloudDistribCmdsTest extends SolrCloudTestCase {
(n, c1) -> SolrCloudTestCase.replicasForCollectionAreFullyActive(n, c1, 2, 2));
final DocCollection docCol = cloudClient.getClusterState().getCollection(testCollectionName);
- try (SolrClient shard1 = getHttpSolrClient(docCol.getSlice("shard1").getLeader());
- SolrClient shard2 = getHttpSolrClient(docCol.getSlice("shard2").getLeader())) {
-
- // Add three documents to shard1
- shard1.add(sdoc("id", "1", "title", "s1 one"));
- shard1.add(sdoc("id", "2", "title", "s1 two"));
- shard1.add(sdoc("id", "3", "title", "s1 three"));
- shard1.commit();
- final AtomicInteger docCounts1 = new AtomicInteger(3);
-
- // Add two documents to shard2
- shard2.add(sdoc("id", "4", "title", "s2 four"));
- shard2.add(sdoc("id", "5", "title", "s2 five"));
- shard2.commit();
- final AtomicInteger docCounts2 = new AtomicInteger(2);
-
- // A re-usable helper to verify that the expected number of documents can be found on each
- // shard...
- Runnable checkShardCounts =
- () -> {
- try {
- // including cloudClient helps us test view from other nodes that aren't the
- // leaders...
- for (SolrClient c : Arrays.asList(cloudClient, shard1, shard2)) {
-
- ModifiableSolrParams params = params("q", "*:*");
- if (c instanceof CloudSolrClient) {
- params.add("collection", testCollectionName);
- }
- assertEquals(
- docCounts1.get() + docCounts2.get(),
- c.query(params).getResults().getNumFound());
-
- assertEquals(
- docCounts1.get(),
- c.query(params.set("shards", "shard1")).getResults().getNumFound());
- assertEquals(
- docCounts2.get(),
- c.query(params.set("shards", "shard2")).getResults().getNumFound());
-
- assertEquals(
- docCounts1.get() + docCounts2.get(),
- c.query(params.set("shards", "shard2,shard1")).getResults().getNumFound());
+ Replica shard1Leader = docCol.getSlice("shard1").getLeader();
+ Replica shard2Leader = docCol.getSlice("shard2").getLeader();
+ SolrClient shard1 = cluster.getSolrClient(shard1Leader);
+ SolrClient shard2 = cluster.getSolrClient(shard2Leader);
+ // Add three documents to shard1
+ shard1.add(sdoc("id", "1", "title", "s1 one"));
+ shard1.add(sdoc("id", "2", "title", "s1 two"));
+ shard1.add(sdoc("id", "3", "title", "s1 three"));
+ shard1.commit();
+ final AtomicInteger docCounts1 = new AtomicInteger(3);
+
+ // Add two documents to shard2
+ shard2.add(sdoc("id", "4", "title", "s2 four"));
+ shard2.add(sdoc("id", "5", "title", "s2 five"));
+ shard2.commit();
+ final AtomicInteger docCounts2 = new AtomicInteger(2);
+
+ // A re-usable helper to verify that the expected number of documents can be found on each
+ // shard...
+ Runnable checkShardCounts =
+ () -> {
+ try {
+ // including cloudClient helps us test view from other nodes that aren't the
+ // leaders...
+ for (SolrClient c : Arrays.asList(cloudClient, shard1, shard2)) {
+
+ ModifiableSolrParams params = params("q", "*:*");
+ if (c instanceof CloudSolrClient) {
+ params.add("collection", testCollectionName);
}
+ assertEquals(
+ docCounts1.get() + docCounts2.get(), c.query(params).getResults().getNumFound());
assertEquals(
docCounts1.get(),
- shard1.query(params("q", "*:*", "distrib", "false")).getResults().getNumFound());
+ c.query(params.set("shards", "shard1")).getResults().getNumFound());
assertEquals(
docCounts2.get(),
- shard2.query(params("q", "*:*", "distrib", "false")).getResults().getNumFound());
+ c.query(params.set("shards", "shard2")).getResults().getNumFound());
- } catch (Exception sse) {
- throw new RuntimeException(sse);
+ assertEquals(
+ docCounts1.get() + docCounts2.get(),
+ c.query(params.set("shards", "shard2,shard1")).getResults().getNumFound());
}
- };
- checkShardCounts.run();
-
- { // Send a delete request for a doc on shard1 to core hosting shard1 with NO routing info
- // Should delete (implicitly) since doc is (implicitly) located on this shard
- final UpdateRequest deleteRequest = new UpdateRequest();
- deleteRequest.deleteById("1");
- shard1.request(deleteRequest);
- shard1.commit();
- docCounts1.decrementAndGet();
- }
- checkShardCounts.run();
-
- { // Send a delete request to core hosting shard1 with a route param for a document that is
- // actually in shard2 should delete.
- final UpdateRequest deleteRequest = new UpdateRequest();
- deleteRequest.deleteById("4").withRoute("shard2");
- shard1.request(deleteRequest);
- shard1.commit();
- docCounts2.decrementAndGet();
- }
- checkShardCounts.run();
-
- { // Send a delete request to core hosting shard1 with NO route param for a document that is
- // actually in shard2. Shouldn't delete, since deleteById requests are not broadcast to all
- // shard leaders. (This is effectively a request to delete "5" if and only if it is on
- // shard1)
- final UpdateRequest deleteRequest = new UpdateRequest();
- deleteRequest.deleteById("5");
- shard1.request(deleteRequest);
- shard1.commit();
- }
- checkShardCounts.run();
-
- { // Multiple deleteById commands for different shards in a single request
- final UpdateRequest deleteRequest = new UpdateRequest();
- deleteRequest.deleteById("2", "shard1");
- deleteRequest.deleteById("5", "shard2");
- shard1.request(deleteRequest);
- shard1.commit();
- docCounts1.decrementAndGet();
- docCounts2.decrementAndGet();
- }
- checkShardCounts.run();
+
+ assertEquals(
+ docCounts1.get(),
+ shard1.query(params("q", "*:*", "distrib", "false")).getResults().getNumFound());
+ assertEquals(
+ docCounts2.get(),
+ shard2.query(params("q", "*:*", "distrib", "false")).getResults().getNumFound());
+
+ } catch (Exception sse) {
+ throw new RuntimeException(sse);
+ }
+ };
+ checkShardCounts.run();
+
+ { // Send a delete request for a doc on shard1 to core hosting shard1 with NO routing info
+ // Should delete (implicitly) since doc is (implicitly) located on this shard
+ final UpdateRequest deleteRequest = new UpdateRequest();
+ deleteRequest.deleteById("1");
+ shard1.request(deleteRequest);
+ shard1.commit();
+ docCounts1.decrementAndGet();
+ }
+ checkShardCounts.run();
+
+ { // Send a delete request to core hosting shard1 with a route param for a document that is
+ // actually in shard2 should delete.
+ final UpdateRequest deleteRequest = new UpdateRequest();
+ deleteRequest.deleteById("4").withRoute("shard2");
+ shard1.request(deleteRequest);
+ shard1.commit();
+ docCounts2.decrementAndGet();
}
+ checkShardCounts.run();
+
+ { // Send a delete request to core hosting shard1 with NO route param for a document that is
+ // actually in shard2. Shouldn't delete, since deleteById requests are not broadcast to all
+ // shard leaders. (This is effectively a request to delete "5" if and only if it is on
+ // shard1)
+ final UpdateRequest deleteRequest = new UpdateRequest();
+ deleteRequest.deleteById("5");
+ shard1.request(deleteRequest);
+ shard1.commit();
+ }
+ checkShardCounts.run();
+
+ { // Multiple deleteById commands for different shards in a single request
+ final UpdateRequest deleteRequest = new UpdateRequest();
+ deleteRequest.deleteById("2", "shard1");
+ deleteRequest.deleteById("5", "shard2");
+ shard1.request(deleteRequest);
+ shard1.commit();
+ docCounts1.decrementAndGet();
+ docCounts2.decrementAndGet();
+ }
+ checkShardCounts.run();
}
public void testRTGCompositeRouterWithRouterField() throws Exception {
@@ -325,102 +325,102 @@ public class FullSolrCloudDistribCmdsTest extends SolrCloudTestCase {
(n, c1) -> SolrCloudTestCase.replicasForCollectionAreFullyActive(n, c1, 2, 2));
final DocCollection docCol = cloudClient.getClusterState().getCollection(testCollectionName);
- try (SolrClient shard1 = getHttpSolrClient(docCol.getSlice("shard1").getLeader());
- SolrClient shard2 = getHttpSolrClient(docCol.getSlice("shard2").getLeader())) {
-
- // Add six documents w/diff routes (all sent to shard1 leader's core)
- shard1.add(sdoc("id", "1", "routefield_s", "europe"));
- shard1.add(sdoc("id", "3", "routefield_s", "europe"));
- shard1.add(sdoc("id", "5", "routefield_s", "africa"));
- shard1.add(sdoc("id", "7", "routefield_s", "europe"));
- shard1.add(sdoc("id", "9", "routefield_s", "europe"));
- shard1.add(sdoc("id", "11", "routefield_s", "africa"));
- shard1.commit();
-
- // Add four documents w/diff routes (all sent to shard2 leader's core)
- shard2.add(sdoc("id", "8", "routefield_s", "africa"));
- shard2.add(sdoc("id", "6", "routefield_s", "europe"));
- shard2.add(sdoc("id", "4", "routefield_s", "africa"));
- shard2.add(sdoc("id", "2", "routefield_s", "europe"));
- shard2.commit();
-
- final AtomicInteger docCountsEurope = new AtomicInteger(6);
- final AtomicInteger docCountsAfrica = new AtomicInteger(4);
-
- // A re-usable helper to verify that the expected number of documents can be found based on
- // _route_ key...
- Runnable checkShardCounts =
- () -> {
- try {
- // including cloudClient helps us test view from other nodes that aren't the
- // leaders...
- for (SolrClient c : Arrays.asList(cloudClient, shard1, shard2)) {
-
- ModifiableSolrParams params = params("q", "*:*");
- if (c instanceof CloudSolrClient) {
- params.add("collection", testCollectionName);
- }
- assertEquals(
- docCountsEurope.get() + docCountsAfrica.get(),
- c.query(params).getResults().getNumFound());
-
- assertEquals(
- docCountsEurope.get(),
- c.query(params.set("_route_", "europe")).getResults().getNumFound());
- assertEquals(
- docCountsAfrica.get(),
- c.query(params.set("_route_", "africa")).getResults().getNumFound());
+ Replica shard1Leader = docCol.getSlice("shard1").getLeader();
+ Replica shard2Leader = docCol.getSlice("shard2").getLeader();
+ SolrClient shard1 = cluster.getSolrClient(shard1Leader);
+ SolrClient shard2 = cluster.getSolrClient(shard2Leader);
+ // Add six documents w/diff routes (all sent to shard1 leader's core)
+ shard1.add(sdoc("id", "1", "routefield_s", "europe"));
+ shard1.add(sdoc("id", "3", "routefield_s", "europe"));
+ shard1.add(sdoc("id", "5", "routefield_s", "africa"));
+ shard1.add(sdoc("id", "7", "routefield_s", "europe"));
+ shard1.add(sdoc("id", "9", "routefield_s", "europe"));
+ shard1.add(sdoc("id", "11", "routefield_s", "africa"));
+ shard1.commit();
+
+ // Add four documents w/diff routes (all sent to shard2 leader's core)
+ shard2.add(sdoc("id", "8", "routefield_s", "africa"));
+ shard2.add(sdoc("id", "6", "routefield_s", "europe"));
+ shard2.add(sdoc("id", "4", "routefield_s", "africa"));
+ shard2.add(sdoc("id", "2", "routefield_s", "europe"));
+ shard2.commit();
+
+ final AtomicInteger docCountsEurope = new AtomicInteger(6);
+ final AtomicInteger docCountsAfrica = new AtomicInteger(4);
+
+ // A re-usable helper to verify that the expected number of documents can be found based on
+ // _route_ key...
+ Runnable checkShardCounts =
+ () -> {
+ try {
+ // including cloudClient helps us test view from other nodes that aren't the
+ // leaders...
+ for (SolrClient c : Arrays.asList(cloudClient, shard1, shard2)) {
+
+ ModifiableSolrParams params = params("q", "*:*");
+ if (c instanceof CloudSolrClient) {
+ params.add("collection", testCollectionName);
}
- } catch (Exception sse) {
- throw new RuntimeException(sse);
+ assertEquals(
+ docCountsEurope.get() + docCountsAfrica.get(),
+ c.query(params).getResults().getNumFound());
+
+ assertEquals(
+ docCountsEurope.get(),
+ c.query(params.set("_route_", "europe")).getResults().getNumFound());
+ assertEquals(
+ docCountsAfrica.get(),
+ c.query(params.set("_route_", "africa")).getResults().getNumFound());
}
- };
- checkShardCounts.run();
-
- { // Send a delete request to core hosting shard1 with a route param for a document that was
- // originally added via core on shard2
- final UpdateRequest deleteRequest = new UpdateRequest();
- deleteRequest.deleteById("4", "africa");
- shard1.request(deleteRequest);
- shard1.commit();
- docCountsAfrica.decrementAndGet();
- }
- checkShardCounts.run();
-
- { // Multiple deleteById commands with different routes in a single request
- final UpdateRequest deleteRequest = new UpdateRequest();
- deleteRequest.deleteById("2", "europe");
- deleteRequest.deleteById("5", "africa");
- shard1.request(deleteRequest);
- shard1.commit();
- docCountsEurope.decrementAndGet();
- docCountsAfrica.decrementAndGet();
- }
- checkShardCounts.run();
-
- // Tests for distributing delete by id when route is missing from the request
- { // Send a delete request with no route to shard1 for document on shard2, should be
- // distributed
- final UpdateRequest deleteRequest = new UpdateRequest();
- deleteRequest.deleteById("8");
- shard1.request(deleteRequest);
- shard1.commit();
- docCountsAfrica.decrementAndGet();
- }
- checkShardCounts.run();
-
- { // Multiple deleteById commands with missing route in a single request, should be
- // distributed
- final UpdateRequest deleteRequest = new UpdateRequest();
- deleteRequest.deleteById("6");
- deleteRequest.deleteById("11");
- shard1.request(deleteRequest);
- shard1.commit();
- docCountsEurope.decrementAndGet();
- docCountsAfrica.decrementAndGet();
- }
- checkShardCounts.run();
+ } catch (Exception sse) {
+ throw new RuntimeException(sse);
+ }
+ };
+ checkShardCounts.run();
+
+ { // Send a delete request to core hosting shard1 with a route param for a document that was
+ // originally added via core on shard2
+ final UpdateRequest deleteRequest = new UpdateRequest();
+ deleteRequest.deleteById("4", "africa");
+ shard1.request(deleteRequest);
+ shard1.commit();
+ docCountsAfrica.decrementAndGet();
}
+ checkShardCounts.run();
+
+ { // Multiple deleteById commands with different routes in a single request
+ final UpdateRequest deleteRequest = new UpdateRequest();
+ deleteRequest.deleteById("2", "europe");
+ deleteRequest.deleteById("5", "africa");
+ shard1.request(deleteRequest);
+ shard1.commit();
+ docCountsEurope.decrementAndGet();
+ docCountsAfrica.decrementAndGet();
+ }
+ checkShardCounts.run();
+
+ // Tests for distributing delete by id when route is missing from the request
+ { // Send a delete request with no route to shard1 for document on shard2, should be
+ // distributed
+ final UpdateRequest deleteRequest = new UpdateRequest();
+ deleteRequest.deleteById("8");
+ shard1.request(deleteRequest);
+ shard1.commit();
+ docCountsAfrica.decrementAndGet();
+ }
+ checkShardCounts.run();
+
+ { // Multiple deleteById commands with missing route in a single request, should be
+ // distributed
+ final UpdateRequest deleteRequest = new UpdateRequest();
+ deleteRequest.deleteById("6");
+ deleteRequest.deleteById("11");
+ shard1.request(deleteRequest);
+ shard1.commit();
+ docCountsEurope.decrementAndGet();
+ docCountsAfrica.decrementAndGet();
+ }
+ checkShardCounts.run();
}
public void testThatCantForwardToLeaderFails() throws Exception {
@@ -488,7 +488,10 @@ public class FullSolrCloudDistribCmdsTest extends SolrCloudTestCase {
}
// create client to send our updates to...
- try (SolrClient indexClient = getHttpSolrClient(indexingBaseUrl, collectionName)) {
+ try (SolrClient indexClient =
+ new HttpJettySolrClient.Builder(indexingBaseUrl)
+ .withDefaultCollection(collectionName)
+ .build()) {
// Sanity check: we should be able to send a bunch of updates that work right now...
for (int i = 0; i < 100; i++) {
@@ -862,30 +865,27 @@ public class FullSolrCloudDistribCmdsTest extends SolrCloudTestCase {
final Slice slice = entry.getValue();
log.info("Checking: {} -> {}", shardName, slice);
final Replica leader = entry.getValue().getLeader();
- try (SolrClient leaderClient = getHttpSolrClient(leader)) {
- final SolrDocumentList leaderResults = leaderClient.query(perReplicaParams).getResults();
- log.debug("Shard {}: Leader results: {}", shardName, leaderResults);
- for (Replica replica : slice) {
- try (SolrClient replicaClient = getHttpSolrClient(replica)) {
- final SolrDocumentList replicaResults =
- replicaClient.query(perReplicaParams).getResults();
- if (log.isDebugEnabled()) {
- log.debug(
- "Shard {}: Replica ({}) results: {}",
- shardName,
- replica.getCoreName(),
- replicaResults);
- }
- assertEquals(
- "inconsistency w/leader: shard=" + shardName + "core=" + replica.getCoreName(),
- Set.of(),
- CloudInspectUtil.showDiff(
- leaderResults,
- replicaResults,
- shardName + " leader: " + leader.getCoreUrl(),
- shardName + ": " + replica.getCoreUrl()));
- }
+ SolrClient leaderClient = cluster.getSolrClient(leader);
+ final SolrDocumentList leaderResults = leaderClient.query(perReplicaParams).getResults();
+ log.debug("Shard {}: Leader results: {}", shardName, leaderResults);
+ for (Replica replica : slice) {
+ SolrClient replicaClient = cluster.getSolrClient(replica);
+ final SolrDocumentList replicaResults = replicaClient.query(perReplicaParams).getResults();
+ if (log.isDebugEnabled()) {
+ log.debug(
+ "Shard {}: Replica ({}) results: {}",
+ shardName,
+ replica.getCoreName(),
+ replicaResults);
}
+ assertEquals(
+ "inconsistency w/leader: shard=" + shardName + "core=" + replica.getCoreName(),
+ Set.of(),
+ CloudInspectUtil.showDiff(
+ leaderResults,
+ replicaResults,
+ shardName + " leader: " + leader.getCoreUrl(),
+ shardName + ": " + replica.getCoreUrl()));
}
}
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/HttpPartitionOnCommitTest.java b/solr/core/src/test/org/apache/solr/cloud/HttpPartitionOnCommitTest.java
index c271c88adb7..a41b5e2b061 100644
--- a/solr/core/src/test/org/apache/solr/cloud/HttpPartitionOnCommitTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/HttpPartitionOnCommitTest.java
@@ -190,25 +190,24 @@ public class HttpPartitionOnCommitTest extends BasicDistributedZkTest {
String replicaCoreUrl = replica.getCoreUrl();
log.info("Sending commit request to: {}", replicaCoreUrl);
final RTimer timer = new RTimer();
- try (SolrClient client = getHttpSolrClient(replica)) {
- try {
- client.commit();
+ SolrClient client = getSolrClient(replica);
+ try {
+ client.commit();
- if (log.isInfoEnabled()) {
- log.info("Sent commit request to {} OK, took {}ms", replicaCoreUrl, timer.getTime());
- }
- } catch (Exception exc) {
- Throwable rootCause = SolrException.getRootCause(exc);
- if (rootCause instanceof IOException) {
- log.warn(
- "No HTTP response from sending commit request to {}; will re-try after waiting 3 seconds",
- replicaCoreUrl);
- Thread.sleep(3000);
- client.commit();
- log.info("Second attempt at sending commit to {} succeeded", replicaCoreUrl);
- } else {
- throw exc;
- }
+ if (log.isInfoEnabled()) {
+ log.info("Sent commit request to {} OK, took {}ms", replicaCoreUrl, timer.getTime());
+ }
+ } catch (Exception exc) {
+ Throwable rootCause = SolrException.getRootCause(exc);
+ if (rootCause instanceof IOException) {
+ log.warn(
+ "No HTTP response from sending commit request to {}; will re-try after waiting 3 seconds",
+ replicaCoreUrl);
+ Thread.sleep(3000);
+ client.commit();
+ log.info("Second attempt at sending commit to {} succeeded", replicaCoreUrl);
+ } else {
+ throw exc;
}
}
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/HttpPartitionTest.java b/solr/core/src/test/org/apache/solr/cloud/HttpPartitionTest.java
index ee536f12ae1..b3008764c21 100644
--- a/solr/core/src/test/org/apache/solr/cloud/HttpPartitionTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/HttpPartitionTest.java
@@ -430,21 +430,15 @@ public class HttpPartitionTest extends AbstractFullDistribZkTestBase {
if (log.isInfoEnabled()) {
log.info("Sending doc 2 to old leader {}", leader.getName());
}
- try (SolrClient leaderSolr = getHttpSolrClient(leader, testCollectionName)) {
-
- leaderSolr.add(doc);
- leaderSolr.close();
+ try {
+ getSolrClient(leader).add(doc);
// if the add worked, then the doc must exist on the new leader
- try (SolrClient newLeaderSolr = getHttpSolrClient(currentLeader, testCollectionName)) {
- assertDocExists(newLeaderSolr, "2");
- }
+ assertDocExists(getSolrClient(currentLeader), "2");
} catch (SolrException exc) {
// this is ok provided the doc doesn't exist on the current leader
- try (SolrClient client = getHttpSolrClient(currentLeader, testCollectionName)) {
- client.add(doc); // this should work
- }
+ getSolrClient(currentLeader).add(doc); // this should work
}
List<Replica> participatingReplicas =
@@ -491,34 +485,21 @@ public class HttpPartitionTest extends AbstractFullDistribZkTestBase {
throws Exception {
Replica leader =
ZkStateReader.from(cloudClient).getLeaderRetry(testCollectionName, "shard1", 10000);
- SolrClient leaderSolr = getHttpSolrClient(leader, testCollectionName);
+ SolrClient leaderSolr = getSolrClient(leader);
List<SolrClient> replicas = new ArrayList<SolrClient>(notLeaders.size());
for (Replica r : notLeaders) {
- replicas.add(getHttpSolrClient(r, testCollectionName));
+ replicas.add(getSolrClient(r));
}
- try {
- for (int d = firstDocId; d <= lastDocId; d++) {
- String docId = String.valueOf(d);
- assertDocExists(leaderSolr, docId);
- for (SolrClient replicaSolr : replicas) {
- assertDocExists(replicaSolr, docId);
- }
- }
- } finally {
- if (leaderSolr != null) {
- leaderSolr.close();
- }
+ for (int d = firstDocId; d <= lastDocId; d++) {
+ String docId = String.valueOf(d);
+ assertDocExists(leaderSolr, docId);
for (SolrClient replicaSolr : replicas) {
- replicaSolr.close();
+ assertDocExists(replicaSolr, docId);
}
}
}
- protected SolrClient getHttpSolrClient(Replica replica, String collection) {
- return getHttpSolrClient(replica.getBaseUrl(), collection);
- }
-
// Send doc directly to a server (without going through proxy)
protected int sendDoc(String collectionName, int docId, JettySolrRunner leaderJetty)
throws IOException, SolrServerException {
diff --git a/solr/core/src/test/org/apache/solr/cloud/LeaderFailoverAfterPartitionTest.java b/solr/core/src/test/org/apache/solr/cloud/LeaderFailoverAfterPartitionTest.java
index 18e3d792cbe..9a8ff0fef95 100644
--- a/solr/core/src/test/org/apache/solr/cloud/LeaderFailoverAfterPartitionTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/LeaderFailoverAfterPartitionTest.java
@@ -22,7 +22,6 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.apache.solr.SolrTestCaseJ4.SuppressSSL;
-import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.cloud.Replica;
import org.apache.solr.common.cloud.ZkStateReader;
@@ -124,13 +123,8 @@ public class LeaderFailoverAfterPartitionTest extends HttpPartitionTest {
// doc should be on leader and 1 replica
sendDoc(testCollectionName, 5);
- try (SolrClient server = getHttpSolrClient(leader, testCollectionName)) {
- assertDocExists(server, "5");
- }
-
- try (SolrClient server = getHttpSolrClient(notLeaders.get(1), testCollectionName)) {
- assertDocExists(server, "5");
- }
+ assertDocExists(getSolrClient(leader), "5");
+ assertDocExists(getSolrClient(notLeaders.get(1)), "5");
Thread.sleep(sleepMsBeforeHealPartition);
diff --git a/solr/core/src/test/org/apache/solr/cloud/MigrateReplicasTest.java b/solr/core/src/test/org/apache/solr/cloud/MigrateReplicasTest.java
index 1d4d431d6df..a72e991690f 100644
--- a/solr/core/src/test/org/apache/solr/cloud/MigrateReplicasTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/MigrateReplicasTest.java
@@ -35,7 +35,6 @@ import org.apache.solr.client.solrj.response.CoreAdminResponse;
import org.apache.solr.common.cloud.DocCollection;
import org.apache.solr.common.cloud.Replica;
import org.apache.solr.common.cloud.Slice;
-import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.common.util.StrUtils;
import org.apache.solr.common.util.Utils;
import org.apache.solr.core.CoreContainer;
@@ -122,15 +121,12 @@ public class MigrateReplicasTest extends SolrCloudTestCase {
"MigrateReplicas request was unsuccessful",
0L,
((Map<?, ?>) response.get("responseHeader")).get("status"));
- ZkStateReader zkStateReader = ZkStateReader.from(cloudClient);
- try (SolrClient coreClient =
- getHttpSolrClient(zkStateReader.getBaseUrlForNodeName(nodeToBeDecommissioned))) {
- CoreAdminResponse status = CoreAdminRequest.getStatus(null, coreClient);
- assertEquals(
- "There should not be any cores left on decommissioned node",
- 0,
- status.getCoreStatus().size());
- }
+ SolrClient coreClient = cluster.getJetty(nodeToBeDecommissioned).getSolrClient();
+ CoreAdminResponse status = CoreAdminRequest.getStatus(null, coreClient);
+ assertEquals(
+ "There should not be any cores left on decommissioned node",
+ 0,
+ status.getCoreStatus().size());
Thread.sleep(5000);
collection = cloudClient.getClusterState().getCollectionOrNull(coll, false);
@@ -150,14 +146,12 @@ public class MigrateReplicasTest extends SolrCloudTestCase {
0L,
((Map<?, ?>) response.get("responseHeader")).get("status"));
- try (SolrClient coreClient =
- getHttpSolrClient(zkStateReader.getBaseUrlForNodeName(emptyNode))) {
- CoreAdminResponse status = CoreAdminRequest.getStatus(null, coreClient);
- assertEquals(
- "Expecting no cores but found some: " + status.getCoreStatus(),
- 0,
- status.getCoreStatus().size());
- }
+ SolrClient emptyNodeClient = cluster.getJetty(emptyNode).getSolrClient();
+ CoreAdminResponse emptyNodeStatus = CoreAdminRequest.getStatus(null, emptyNodeClient);
+ assertEquals(
+ "Expecting no cores but found some: " + emptyNodeStatus.getCoreStatus(),
+ 0,
+ emptyNodeStatus.getCoreStatus().size());
collection = cluster.getSolrClient().getClusterState().getCollection(coll);
assertEquals(create.getNumShards().intValue(), collection.getSlices().size());
diff --git a/solr/core/src/test/org/apache/solr/cloud/MigrateRouteKeyTest.java b/solr/core/src/test/org/apache/solr/cloud/MigrateRouteKeyTest.java
index 09114574f2a..c0b1ce96d67 100644
--- a/solr/core/src/test/org/apache/solr/cloud/MigrateRouteKeyTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/MigrateRouteKeyTest.java
@@ -133,14 +133,13 @@ public class MigrateRouteKeyTest extends SolrCloudTestCase {
DocCollection sourceState = getCollectionState(sourceCollection);
assertEquals(2, sourceState.getSlice("shard1").getReplicas().size());
for (Replica replica : sourceState.getSlice("shard1")) {
- try (SolrClient replicaClient = getHttpSolrClient(replica)) {
- SolrQuery query = new SolrQuery("id:\"a!2\"");
- query.set("distrib", false);
- assertEquals(
- "Document missing from replica " + replica.getName(),
- 1,
- replicaClient.query(query).getResults().getNumFound());
- }
+ var replicaClient = cluster.getSolrClient(replica);
+ SolrQuery query = new SolrQuery("id:\"a!2\"");
+ query.set("distrib", false);
+ assertEquals(
+ "Document missing from replica " + replica.getName(),
+ 1,
+ replicaClient.query(query).getResults().getNumFound());
}
waitForState(
@@ -187,56 +186,54 @@ public class MigrateRouteKeyTest extends SolrCloudTestCase {
DocCollection state = getCollectionState(targetCollection);
Replica replica = state.replicaStream().findFirst().orElseThrow();
- try (SolrClient collectionClient = getHttpSolrClient(replica)) {
+ SolrClient collectionClient = cluster.getSolrClient(replica);
+ SolrQuery solrQuery = new SolrQuery("*:*");
+ assertEquals(
+ "DocCount on target collection does not match",
+ 0,
+ collectionClient.query(solrQuery).getResults().getNumFound());
- SolrQuery solrQuery = new SolrQuery("*:*");
- assertEquals(
- "DocCount on target collection does not match",
- 0,
- collectionClient.query(solrQuery).getResults().getNumFound());
+ invokeCollectionMigration(
+ CollectionAdminRequest.migrateData(
+ sourceCollection, targetCollection, splitKey + "/" + BIT_SEP + "!")
+ .setForwardTimeout(45));
- invokeCollectionMigration(
- CollectionAdminRequest.migrateData(
- sourceCollection, targetCollection, splitKey + "/" + BIT_SEP + "!")
- .setForwardTimeout(45));
+ long finishTime = System.nanoTime();
- long finishTime = System.nanoTime();
+ indexer.join();
+ splitKeyCount += indexer.getSplitKeyCount();
- indexer.join();
- splitKeyCount += indexer.getSplitKeyCount();
+ try {
+ cluster.getSolrClient().deleteById(sourceCollection, "a/" + BIT_SEP + "!104");
+ splitKeyCount--;
+ } catch (Exception e) {
+ log.warn("Error deleting document a/{}!104", BIT_SEP, e);
+ }
+ cluster.getSolrClient().commit(sourceCollection);
+ collectionClient.commit();
- try {
- cluster.getSolrClient().deleteById(sourceCollection, "a/" + BIT_SEP + "!104");
- splitKeyCount--;
- } catch (Exception e) {
- log.warn("Error deleting document a/{}!104", BIT_SEP, e);
- }
- cluster.getSolrClient().commit(sourceCollection);
- collectionClient.commit();
+ solrQuery = new SolrQuery("*:*").setRows(1000);
+ QueryResponse response = collectionClient.query(solrQuery);
+ log.info("Response from target collection: {}", response);
+ assertEquals(
+ "DocCount on target collection does not match",
+ splitKeyCount,
+ response.getResults().getNumFound());
- solrQuery = new SolrQuery("*:*").setRows(1000);
- QueryResponse response = collectionClient.query(solrQuery);
- log.info("Response from target collection: {}", response);
- assertEquals(
- "DocCount on target collection does not match",
- splitKeyCount,
- response.getResults().getNumFound());
-
- waitForState(
- "Expected to find routing rule for split key " + splitKey,
- sourceCollection,
- c -> {
- if (c == null) return false;
- Slice shard = c.getSlice("shard2");
- if (shard == null) return false;
- if (shard.getRoutingRules() == null || shard.getRoutingRules().isEmpty()) return false;
- if (shard.getRoutingRules().get(splitKey + "!") == null) return false;
- return true;
- });
-
- boolean ruleRemoved = waitForRuleToExpire(sourceCollection, "shard2", splitKey, finishTime);
- assertTrue("Routing rule was not expired", ruleRemoved);
- }
+ waitForState(
+ "Expected to find routing rule for split key " + splitKey,
+ sourceCollection,
+ c -> {
+ if (c == null) return false;
+ Slice shard = c.getSlice("shard2");
+ if (shard == null) return false;
+ if (shard.getRoutingRules() == null || shard.getRoutingRules().isEmpty()) return false;
+ if (shard.getRoutingRules().get(splitKey + "!") == null) return false;
+ return true;
+ });
+
+ boolean ruleRemoved = waitForRuleToExpire(sourceCollection, "shard2", splitKey, finishTime);
+ assertTrue("Routing rule was not expired", ruleRemoved);
}
static class Indexer extends Thread {
diff --git a/solr/core/src/test/org/apache/solr/cloud/MoveReplicaTest.java b/solr/core/src/test/org/apache/solr/cloud/MoveReplicaTest.java
index 68524274e02..7e9706f9410 100644
--- a/solr/core/src/test/org/apache/solr/cloud/MoveReplicaTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/MoveReplicaTest.java
@@ -38,7 +38,6 @@ import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.cloud.DocCollection;
import org.apache.solr.common.cloud.Replica;
import org.apache.solr.common.cloud.Slice;
-import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.embedded.JettySolrRunner;
import org.apache.solr.util.IdUtils;
@@ -364,35 +363,33 @@ public class MoveReplicaTest extends SolrCloudTestCase {
private int getNumOfCores(
CloudSolrClient cloudClient, String nodeName, String collectionName, String replicaType)
throws IOException, SolrServerException {
- try (SolrClient coreclient =
- getHttpSolrClient(ZkStateReader.from(cloudClient).getBaseUrlForNodeName(nodeName))) {
- CoreAdminResponse status = CoreAdminRequest.getStatus(null, coreclient);
- if (status.getCoreStatus().size() == 0) {
- return 0;
- }
- if (collectionName == null && replicaType == null) {
- return status.getCoreStatus().size();
- }
- // filter size by collection name
- int size = 0;
- for (Map.Entry<String, CoreStatusResponse.SingleCoreData> coreStatusEntry :
- status.getCoreStatus().entrySet()) {
- if (collectionName != null) {
- String coll = coreStatusEntry.getValue().cloud.collection;
- if (!collectionName.equals(coll)) {
- continue;
- }
+ SolrClient coreclient = cluster.getJetty(nodeName).getSolrClient();
+ CoreAdminResponse status = CoreAdminRequest.getStatus(null, coreclient);
+ if (status.getCoreStatus().size() == 0) {
+ return 0;
+ }
+ if (collectionName == null && replicaType == null) {
+ return status.getCoreStatus().size();
+ }
+ // filter size by collection name
+ int size = 0;
+ for (Map.Entry<String, CoreStatusResponse.SingleCoreData> coreStatusEntry :
+ status.getCoreStatus().entrySet()) {
+ if (collectionName != null) {
+ String coll = coreStatusEntry.getValue().cloud.collection;
+ if (!collectionName.equals(coll)) {
+ continue;
}
- if (replicaType != null) {
- String type = coreStatusEntry.getValue().cloud.replicaType;
- if (!replicaType.equals(type)) {
- continue;
- }
+ }
+ if (replicaType != null) {
+ String type = coreStatusEntry.getValue().cloud.replicaType;
+ if (!replicaType.equals(type)) {
+ continue;
}
- size++;
}
- return size;
+ size++;
}
+ return size;
}
protected void addDocs(String collection, int numDocs) throws Exception {
diff --git a/solr/core/src/test/org/apache/solr/cloud/NestedShardedAtomicUpdateTest.java b/solr/core/src/test/org/apache/solr/cloud/NestedShardedAtomicUpdateTest.java
index c284d581cd8..c3569fc7865 100644
--- a/solr/core/src/test/org/apache/solr/cloud/NestedShardedAtomicUpdateTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/NestedShardedAtomicUpdateTest.java
@@ -22,7 +22,6 @@ import java.lang.invoke.MethodHandles;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
-import org.apache.lucene.util.IOUtils;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
@@ -36,7 +35,6 @@ import org.apache.solr.common.cloud.ClusterState;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.util.RandomNoReverseMergePolicyFactory;
-import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
@@ -73,12 +71,7 @@ public class NestedShardedAtomicUpdateTest extends SolrCloudTestCase {
clusterState
.getCollection(DEFAULT_COLLECTION)
.replicaStream()
- .forEach(replica -> clients.add(getHttpSolrClient(replica)));
- }
-
- @AfterClass
- public static void afterClass() throws Exception {
- IOUtils.close(clients);
+ .forEach(replica -> clients.add(cluster.getSolrClient(replica)));
}
@Test
diff --git a/solr/core/src/test/org/apache/solr/cloud/RemoteQueryErrorTest.java b/solr/core/src/test/org/apache/solr/cloud/RemoteQueryErrorTest.java
index 9da524dfc9b..a1465260522 100644
--- a/solr/core/src/test/org/apache/solr/cloud/RemoteQueryErrorTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/RemoteQueryErrorTest.java
@@ -43,16 +43,15 @@ public class RemoteQueryErrorTest extends SolrCloudTestCase {
.process(cluster.getSolrClient());
for (JettySolrRunner jetty : cluster.getJettySolrRunners()) {
- try (SolrClient client = jetty.newClient()) {
- SolrException e =
- expectThrows(
- SolrException.class,
- () -> {
- client.add("collection", new SolrInputDocument());
- });
- assertThat(
- e.getMessage(), containsString("Document is missing mandatory uniqueKey field: id"));
- }
+ SolrClient client = jetty.getSolrClient();
+ SolrException e =
+ expectThrows(
+ SolrException.class,
+ () -> {
+ client.add("collection", new SolrInputDocument());
+ });
+ assertThat(
+ e.getMessage(), containsString("Document is missing mandatory uniqueKey field: id"));
}
}
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/ReplaceNodeTest.java b/solr/core/src/test/org/apache/solr/cloud/ReplaceNodeTest.java
index bc64635d2d8..fac7fe5928e 100644
--- a/solr/core/src/test/org/apache/solr/cloud/ReplaceNodeTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/ReplaceNodeTest.java
@@ -36,7 +36,6 @@ import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.DocCollection;
import org.apache.solr.common.cloud.Replica;
import org.apache.solr.common.cloud.Slice;
-import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.common.params.CollectionParams;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.SolrParams;
@@ -116,12 +115,9 @@ public class ReplaceNodeTest extends SolrCloudTestCase {
log.info("excluded_node : {} ", emptyNode);
createReplaceNodeRequest(nodeToBeDecommissioned, emptyNode, null)
.processAndWait("000", cloudClient, 15);
- ZkStateReader zkStateReader = ZkStateReader.from(cloudClient);
- try (SolrClient coreClient =
- getHttpSolrClient(zkStateReader.getBaseUrlForNodeName(nodeToBeDecommissioned))) {
- CoreAdminResponse status = CoreAdminRequest.getStatus(null, coreClient);
- assertEquals(0, status.getCoreStatus().size());
- }
+ SolrClient coreClient = cluster.getJetty(nodeToBeDecommissioned).getSolrClient();
+ CoreAdminResponse status = CoreAdminRequest.getStatus(null, coreClient);
+ assertEquals(0, status.getCoreStatus().size());
Thread.sleep(5000);
collection = cloudClient.getClusterState().getCollection(coll);
@@ -136,14 +132,12 @@ public class ReplaceNodeTest extends SolrCloudTestCase {
replaceNodeRequest.setWaitForFinalState(true);
replaceNodeRequest.processAndWait("001", cloudClient, 10);
- try (SolrClient coreClient =
- getHttpSolrClient(zkStateReader.getBaseUrlForNodeName(emptyNode))) {
- CoreAdminResponse status = CoreAdminRequest.getStatus(null, coreClient);
- assertEquals(
- "Expecting no cores but found some: " + status.getCoreStatus(),
- 0,
- status.getCoreStatus().size());
- }
+ SolrClient emptyNodeClient = cluster.getJetty(emptyNode).getSolrClient();
+ CoreAdminResponse emptyNodeStatus = CoreAdminRequest.getStatus(null, emptyNodeClient);
+ assertEquals(
+ "Expecting no cores but found some: " + emptyNodeStatus.getCoreStatus(),
+ 0,
+ emptyNodeStatus.getCoreStatus().size());
collection = cluster.getSolrClient().getClusterState().getCollection(coll);
assertEquals(create.getNumShards().intValue(), collection.getSlices().size());
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 eb63af4a5ac..1d967a55c25 100644
--- a/solr/core/src/test/org/apache/solr/cloud/ReplicationFactorTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/ReplicationFactorTest.java
@@ -29,7 +29,6 @@ import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
import org.apache.lucene.tests.util.LuceneTestCase.AwaitsFix;
import org.apache.solr.SolrTestCaseJ4.SuppressSSL;
-import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.UpdateRequest;
@@ -268,22 +267,20 @@ public class ReplicationFactorTest extends AbstractFullDistribZkTestBase {
protected void sendNonDirectUpdateRequestReplica(
Replica replica, UpdateRequest up, int expectedRf, String collection) throws Exception {
- try (SolrClient solrServer = getHttpSolrClient(replica.getBaseUrl(), collection)) {
- NamedList<?> resp = solrServer.request(up);
- NamedList<?> hdr = (NamedList<?>) resp.get("responseHeader");
- Integer batchRf = (Integer) hdr.get(UpdateRequest.REPFACT);
- // Note that this also tests if we're wonky and return an achieved rf greater than the number
- // of live replicas.
- assertEquals(
- "Expected rf="
- + expectedRf
- + " for batch but got "
- + batchRf
- + "; clusterState: "
- + printClusterStateInfo(),
- (int) batchRf,
- expectedRf);
- }
+ NamedList<?> resp = getSolrClient(replica).request(up);
+ NamedList<?> hdr = (NamedList<?>) resp.get("responseHeader");
+ Integer batchRf = (Integer) hdr.get(UpdateRequest.REPFACT);
+ // Note that this also tests if we're wonky and return an achieved rf greater than the number
+ // of live replicas.
+ assertEquals(
+ "Expected rf="
+ + expectedRf
+ + " for batch but got "
+ + batchRf
+ + "; clusterState: "
+ + printClusterStateInfo(),
+ (int) batchRf,
+ expectedRf);
}
protected void testRf3() throws Exception {
diff --git a/solr/core/src/test/org/apache/solr/cloud/SplitShardTest.java b/solr/core/src/test/org/apache/solr/cloud/SplitShardTest.java
index 0b539bd39d0..a7405273e26 100644
--- a/solr/core/src/test/org/apache/solr/cloud/SplitShardTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/SplitShardTest.java
@@ -229,18 +229,10 @@ public class SplitShardTest extends SolrCloudTestCase {
if (!slice.getState().equals(Slice.State.ACTIVE)) continue;
long lastReplicaCount = -1;
for (Replica replica : slice.getReplicas()) {
- SolrClient replicaClient = getHttpSolrClient(replica);
- long numFound;
- try {
- numFound =
- replicaClient
- .query(params("q", "*:*", "distrib", "false"))
- .getResults()
- .getNumFound();
- log.info("Replica count={} for {}", numFound, replica);
- } finally {
- replicaClient.close();
- }
+ SolrClient replicaClient = cluster.getSolrClient(replica);
+ long numFound =
+ replicaClient.query(params("q", "*:*", "distrib", "false")).getResults().getNumFound();
+ log.info("Replica count={} for {}", numFound, replica);
if (lastReplicaCount >= 0) {
assertEquals("Replica doc count for " + replica, lastReplicaCount, numFound);
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestBaseStatsCacheCloud.java b/solr/core/src/test/org/apache/solr/cloud/TestBaseStatsCacheCloud.java
index a7dc3f8d12f..f73c4447059 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestBaseStatsCacheCloud.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestBaseStatsCacheCloud.java
@@ -131,46 +131,45 @@ public abstract class TestBaseStatsCacheCloud extends SolrCloudTestCase {
// check cache metrics
StatsCache.StatsCacheMetrics statsCacheMetrics = new StatsCache.StatsCacheMetrics();
for (JettySolrRunner jettySolrRunner : cluster.getJettySolrRunners()) {
- try (SolrClient client = getHttpSolrClient(jettySolrRunner.getBaseUrl().toString())) {
- var req = new MetricsRequest(SolrParams.of("wt", "prometheus"));
-
- NamedList<Object> resp = client.request(req);
- try (InputStream in = (InputStream) resp.get("stream")) {
- String output = new String(in.readAllBytes(), StandardCharsets.UTF_8);
-
- for (String line : output.lines().toList()) {
- if (line.startsWith("solr_core_indexsearcher_termstats_cache")) {
- String type = extractTypeAttribute(line);
- long value = extractMetricValue(line);
- switch (type) {
- case "lookups":
- statsCacheMetrics.lookups.add(value);
- break;
- case "return_local":
- statsCacheMetrics.returnLocalStats.add(value);
- break;
- case "merge_to_global":
- statsCacheMetrics.mergeToGlobalStats.add(value);
- break;
- case "missing_global_field":
- statsCacheMetrics.missingGlobalFieldStats.add(value);
- break;
- case "missing_global_term":
- statsCacheMetrics.missingGlobalTermStats.add(value);
- break;
- case "receive_global":
- statsCacheMetrics.receiveGlobalStats.add(value);
- break;
- case "retrieve":
- statsCacheMetrics.retrieveStats.add(value);
- break;
- case "send_global":
- statsCacheMetrics.sendGlobalStats.add(value);
- break;
- case "use_cached_global":
- statsCacheMetrics.useCachedGlobalStats.add(value);
- break;
- }
+ SolrClient client = jettySolrRunner.getSolrClient();
+ var req = new MetricsRequest(SolrParams.of("wt", "prometheus"));
+
+ NamedList<Object> resp = client.request(req);
+ try (InputStream in = (InputStream) resp.get("stream")) {
+ String output = new String(in.readAllBytes(), StandardCharsets.UTF_8);
+
+ for (String line : output.lines().toList()) {
+ if (line.startsWith("solr_core_indexsearcher_termstats_cache")) {
+ String type = extractTypeAttribute(line);
+ long value = extractMetricValue(line);
+ switch (type) {
+ case "lookups":
+ statsCacheMetrics.lookups.add(value);
+ break;
+ case "return_local":
+ statsCacheMetrics.returnLocalStats.add(value);
+ break;
+ case "merge_to_global":
+ statsCacheMetrics.mergeToGlobalStats.add(value);
+ break;
+ case "missing_global_field":
+ statsCacheMetrics.missingGlobalFieldStats.add(value);
+ break;
+ case "missing_global_term":
+ statsCacheMetrics.missingGlobalTermStats.add(value);
+ break;
+ case "receive_global":
+ statsCacheMetrics.receiveGlobalStats.add(value);
+ break;
+ case "retrieve":
+ statsCacheMetrics.retrieveStats.add(value);
+ break;
+ case "send_global":
+ statsCacheMetrics.sendGlobalStats.add(value);
+ break;
+ case "use_cached_global":
+ statsCacheMetrics.useCachedGlobalStats.add(value);
+ break;
}
}
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestCloudConsistency.java b/solr/core/src/test/org/apache/solr/cloud/TestCloudConsistency.java
index b3c7c4142ae..39f9661bd40 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestCloudConsistency.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestCloudConsistency.java
@@ -309,26 +309,17 @@ public class TestCloudConsistency extends SolrCloudTestCase {
List<Replica> notLeaders, String testCollectionName, int firstDocId, int lastDocId)
throws Exception {
Replica leader = cluster.getZkStateReader().getLeaderRetry(testCollectionName, "shard1", 10000);
- SolrClient leaderSolr = getHttpSolrClient(leader, testCollectionName);
+ SolrClient leaderSolr = cluster.getSolrClient(leader);
List<SolrClient> replicas = new ArrayList<>(notLeaders.size());
for (Replica r : notLeaders) {
- replicas.add(getHttpSolrClient(r, testCollectionName));
+ replicas.add(cluster.getSolrClient(r));
}
- try {
- for (int d = firstDocId; d <= lastDocId; d++) {
- String docId = String.valueOf(d);
- assertDocExists(leaderSolr, docId);
- for (SolrClient replicaSolr : replicas) {
- assertDocExists(replicaSolr, docId);
- }
- }
- } finally {
- if (leaderSolr != null) {
- leaderSolr.close();
- }
+ for (int d = firstDocId; d <= lastDocId; d++) {
+ String docId = String.valueOf(d);
+ assertDocExists(leaderSolr, docId);
for (SolrClient replicaSolr : replicas) {
- replicaSolr.close();
+ assertDocExists(replicaSolr, docId);
}
}
}
@@ -349,8 +340,4 @@ public class TestCloudConsistency extends SolrCloudTestCase {
params("id", docId, "distrib", "false"))
.setRequiresCollection(true));
}
-
- protected SolrClient getHttpSolrClient(Replica replica, String coll) {
- return getHttpSolrClient(replica.getBaseUrl(), coll);
- }
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestCloudDeleteByQuery.java b/solr/core/src/test/org/apache/solr/cloud/TestCloudDeleteByQuery.java
index 451ef12dab6..c5fe0b43e98 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestCloudDeleteByQuery.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestCloudDeleteByQuery.java
@@ -27,6 +27,7 @@ import java.util.Map;
import java.util.UUID;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.CollectionScopedSolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.UpdateRequest;
import org.apache.solr.common.SolrDocument;
@@ -88,26 +89,11 @@ public class TestCloudDeleteByQuery extends SolrCloudTestCase {
COLLECTION_CLIENT.close();
COLLECTION_CLIENT = null;
}
- if (null != S_ONE_LEADER_CLIENT) {
- S_ONE_LEADER_CLIENT.close();
- S_ONE_LEADER_CLIENT = null;
- }
- if (null != S_TWO_LEADER_CLIENT) {
- S_TWO_LEADER_CLIENT.close();
- S_TWO_LEADER_CLIENT = null;
- }
- if (null != S_ONE_NON_LEADER_CLIENT) {
- S_ONE_NON_LEADER_CLIENT.close();
- S_ONE_NON_LEADER_CLIENT = null;
- }
- if (null != S_TWO_NON_LEADER_CLIENT) {
- S_TWO_NON_LEADER_CLIENT.close();
- S_TWO_NON_LEADER_CLIENT = null;
- }
- if (null != NO_COLLECTION_CLIENT) {
- NO_COLLECTION_CLIENT.close();
- NO_COLLECTION_CLIENT = null;
- }
+ S_ONE_LEADER_CLIENT = null;
+ S_TWO_LEADER_CLIENT = null;
+ S_ONE_NON_LEADER_CLIENT = null;
+ S_TWO_NON_LEADER_CLIENT = null;
+ NO_COLLECTION_CLIENT = null;
}
@BeforeClass
@@ -166,17 +152,27 @@ public class TestCloudDeleteByQuery extends SolrCloudTestCase {
assertNotNull("could not find URL for " + shardName + " replica", passiveUrl);
if (shardName.equals("shard1")) {
- S_ONE_LEADER_CLIENT = getHttpSolrClient(leaderUrl, COLLECTION_NAME);
- S_ONE_NON_LEADER_CLIENT = getHttpSolrClient(passiveUrl, COLLECTION_NAME);
+ S_ONE_LEADER_CLIENT =
+ new CollectionScopedSolrClient(
+ cluster.getJetty(leaderUrl).getSolrClient(), COLLECTION_NAME);
+ S_ONE_NON_LEADER_CLIENT =
+ new CollectionScopedSolrClient(
+ cluster.getJetty(passiveUrl).getSolrClient(), COLLECTION_NAME);
} else if (shardName.equals("shard2")) {
- S_TWO_LEADER_CLIENT = getHttpSolrClient(leaderUrl, COLLECTION_NAME);
- S_TWO_NON_LEADER_CLIENT = getHttpSolrClient(passiveUrl, COLLECTION_NAME);
+ S_TWO_LEADER_CLIENT =
+ new CollectionScopedSolrClient(
+ cluster.getJetty(leaderUrl).getSolrClient(), COLLECTION_NAME);
+ S_TWO_NON_LEADER_CLIENT =
+ new CollectionScopedSolrClient(
+ cluster.getJetty(passiveUrl).getSolrClient(), COLLECTION_NAME);
} else {
fail("unexpected shard: " + shardName);
}
}
assertEquals("Should be exactly one server left (not hosting either shard)", 1, urlMap.size());
- NO_COLLECTION_CLIENT = getHttpSolrClient(urlMap.values().iterator().next(), COLLECTION_NAME);
+ NO_COLLECTION_CLIENT =
+ new CollectionScopedSolrClient(
+ cluster.getJetty(urlMap.values().iterator().next()).getSolrClient(), COLLECTION_NAME);
assertNotNull(S_ONE_LEADER_CLIENT);
assertNotNull(S_TWO_LEADER_CLIENT);
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestCloudPhrasesIdentificationComponent.java b/solr/core/src/test/org/apache/solr/cloud/TestCloudPhrasesIdentificationComponent.java
index 2a979299698..cedc2927c73 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestCloudPhrasesIdentificationComponent.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestCloudPhrasesIdentificationComponent.java
@@ -80,7 +80,7 @@ public class TestCloudPhrasesIdentificationComponent extends SolrCloudTestCase {
waitForRecoveriesToFinish(COLLECTION_CLIENT);
for (JettySolrRunner jetty : cluster.getJettySolrRunners()) {
- CLIENTS.add(getHttpSolrClient(jetty.getBaseUrl().toString(), COLLECTION_NAME));
+ CLIENTS.add(jetty.newSolrClient(COLLECTION_NAME));
}
// index some docs...
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestCloudPseudoReturnFields.java b/solr/core/src/test/org/apache/solr/cloud/TestCloudPseudoReturnFields.java
index 81969dae345..848d88fc2b6 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestCloudPseudoReturnFields.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestCloudPseudoReturnFields.java
@@ -97,7 +97,7 @@ public class TestCloudPseudoReturnFields extends SolrCloudTestCase {
waitForRecoveriesToFinish(COLLECTION_CLIENT);
for (JettySolrRunner jetty : cluster.getJettySolrRunners()) {
- CLIENTS.add(getHttpSolrClient(jetty.getBaseUrl().toString(), COLLECTION_NAME));
+ CLIENTS.add(jetty.newSolrClient(COLLECTION_NAME));
}
assertEquals(
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestCloudRecovery2.java b/solr/core/src/test/org/apache/solr/cloud/TestCloudRecovery2.java
index d4af2692573..b1962539f18 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestCloudRecovery2.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestCloudRecovery2.java
@@ -49,7 +49,8 @@ public class TestCloudRecovery2 extends SolrCloudTestCase {
public void test() throws Exception {
JettySolrRunner node1 = cluster.getJettySolrRunner(0);
JettySolrRunner node2 = cluster.getJettySolrRunner(1);
- try (SolrClient client1 = getHttpSolrClient(node1.getBaseUrl().toString())) {
+ {
+ SolrClient client1 = node1.getSolrClient();
node2.stop();
waitForState("", COLLECTION, (liveNodes, collectionState) -> liveNodes.size() == 1);
@@ -63,9 +64,10 @@ public class TestCloudRecovery2 extends SolrCloudTestCase {
node2.start();
waitForState("", COLLECTION, clusterShape(1, 2));
- try (SolrClient client = getHttpSolrClient(node2.getBaseUrl().toString())) {
+ {
long numFound =
- client
+ node2
+ .getSolrClient()
.query(COLLECTION, new SolrQuery("q", "*:*", "distrib", "false"))
.getResults()
.getNumFound();
@@ -80,9 +82,10 @@ public class TestCloudRecovery2 extends SolrCloudTestCase {
new UpdateRequest().add("id", "1", "num", "10").commit(client1, COLLECTION);
- try (SolrClient client = getHttpSolrClient(node2.getBaseUrl().toString())) {
+ {
Object v =
- client
+ node2
+ .getSolrClient()
.query(COLLECTION, new SolrQuery("q", "id:1", "distrib", "false"))
.getResults()
.get(0)
@@ -112,9 +115,10 @@ public class TestCloudRecovery2 extends SolrCloudTestCase {
node2.start();
waitForState("", COLLECTION, clusterShape(1, 2));
- try (SolrClient client = getHttpSolrClient(node2.getBaseUrl().toString())) {
+ {
v =
- client
+ node2
+ .getSolrClient()
.query(COLLECTION, new SolrQuery("q", "id:1", "distrib", "false"))
.getResults()
.get(0)
@@ -137,9 +141,10 @@ public class TestCloudRecovery2 extends SolrCloudTestCase {
node2.start();
waitForState("", COLLECTION, clusterShape(1, 2));
- try (SolrClient client = getHttpSolrClient(node2.getBaseUrl().toString())) {
+ {
v =
- client
+ node2
+ .getSolrClient()
.query(COLLECTION, new SolrQuery("q", "id:1", "distrib", "false"))
.getResults()
.get(0)
@@ -166,18 +171,20 @@ public class TestCloudRecovery2 extends SolrCloudTestCase {
node1.start();
waitForState("", COLLECTION, clusterShape(1, 2));
- try (SolrClient client = getHttpSolrClient(node1.getBaseUrl().toString())) {
+ {
Object v =
- client
+ node1
+ .getSolrClient()
.query(COLLECTION, new SolrQuery("q", "id:1", "distrib", "false"))
.getResults()
.get(0)
.get("num");
assertEquals("30", v.toString());
}
- try (SolrClient client = getHttpSolrClient(node2.getBaseUrl().toString())) {
+ {
Object v =
- client
+ node2
+ .getSolrClient()
.query(COLLECTION, new SolrQuery("q", "id:1", "distrib", "false"))
.getResults()
.get(0)
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java
index c7ece98ae62..f2f80ed019e 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java
@@ -136,39 +136,37 @@ public class TestConfigSetsAPI extends SolrCloudTestCase {
@Test
public void testCreateErrors() throws Exception {
- final String baseUrl = cluster.getJettySolrRunners().get(0).getBaseUrl().toString();
- try (final SolrClient solrClient = getHttpSolrClient(baseUrl)) {
- getConfigSetService().uploadConfig("configSet", configset("configset-2"));
-
- // no action
- CreateNoErrorChecking createNoAction = new CreateNoErrorChecking();
- createNoAction.setAction(null);
- verifyException(solrClient, createNoAction, "action");
-
- // no ConfigSet name
- CreateNoErrorChecking create = new CreateNoErrorChecking();
- verifyException(solrClient, create, NAME);
-
- // set ConfigSet
- create.setConfigSetName("configSetName");
-
- // ConfigSet already exists
- Create alreadyExists = new Create();
- alreadyExists.setConfigSetName("configSet").setBaseConfigSetName("baseConfigSet");
- verifyException(solrClient, alreadyExists, "ConfigSet already exists");
-
- // Base ConfigSet does not exist
- Create baseConfigNoExists = new Create();
- baseConfigNoExists.setConfigSetName("newConfigSet").setBaseConfigSetName("baseConfigSet");
- verifyException(solrClient, baseConfigNoExists, "Base ConfigSet does not exist");
-
- // Invalid configset names
- for (String invalidName :
- new String[] {"configset!", "configset\"", "-configset", "configset name"}) {
- Create invalidNameCreate = new Create();
- invalidNameCreate.setConfigSetName(invalidName).setBaseConfigSetName("_default");
- verifyException(solrClient, invalidNameCreate, "Invalid configset");
- }
+ final SolrClient solrClient = cluster.getJettySolrRunners().get(0).getSolrClient();
+ getConfigSetService().uploadConfig("configSet", configset("configset-2"));
+
+ // no action
+ CreateNoErrorChecking createNoAction = new CreateNoErrorChecking();
+ createNoAction.setAction(null);
+ verifyException(solrClient, createNoAction, "action");
+
+ // no ConfigSet name
+ CreateNoErrorChecking create = new CreateNoErrorChecking();
+ verifyException(solrClient, create, NAME);
+
+ // set ConfigSet
+ create.setConfigSetName("configSetName");
+
+ // ConfigSet already exists
+ Create alreadyExists = new Create();
+ alreadyExists.setConfigSetName("configSet").setBaseConfigSetName("baseConfigSet");
+ verifyException(solrClient, alreadyExists, "ConfigSet already exists");
+
+ // Base ConfigSet does not exist
+ Create baseConfigNoExists = new Create();
+ baseConfigNoExists.setConfigSetName("newConfigSet").setBaseConfigSetName("baseConfigSet");
+ verifyException(solrClient, baseConfigNoExists, "Base ConfigSet does not exist");
+
+ // Invalid configset names
+ for (String invalidName :
+ new String[] {"configset!", "configset\"", "-configset", "configset name"}) {
+ Create invalidNameCreate = new Create();
+ invalidNameCreate.setConfigSetName(invalidName).setBaseConfigSetName("_default");
+ verifyException(solrClient, invalidNameCreate, "Invalid configset");
}
}
@@ -223,25 +221,23 @@ public class TestConfigSetsAPI extends SolrCloudTestCase {
Map<String, String> newProps,
String username)
throws Exception {
- final String baseUrl = cluster.getJettySolrRunners().get(0).getBaseUrl().toString();
- try (final SolrClient solrClient = getHttpSolrClient(baseUrl)) {
- setupBaseConfigSet(baseConfigSetName, oldProps);
-
- try (SolrZkClient zkClient =
- new SolrZkClient.Builder()
- .withUrl(cluster.getZkServer().getZkAddress())
- .withTimeout(AbstractZkTestCase.TIMEOUT, TimeUnit.MILLISECONDS)
- .withConnTimeOut(AbstractZkTestCase.TIMEOUT, TimeUnit.MILLISECONDS)
- .build()) {
- assertFalse(getConfigSetService().checkConfigExists(configSetName));
-
- ConfigSetAdminResponse response =
- createConfigSet(baseConfigSetName, configSetName, newProps, solrClient, username);
- assertNotNull(response.getResponse());
- assertTrue(getConfigSetService().checkConfigExists(configSetName));
-
- verifyProperties(configSetName, oldProps, newProps, zkClient);
- }
+ final SolrClient solrClient = cluster.getJettySolrRunners().get(0).getSolrClient();
+ setupBaseConfigSet(baseConfigSetName, oldProps);
+
+ try (SolrZkClient zkClient =
+ new SolrZkClient.Builder()
+ .withUrl(cluster.getZkServer().getZkAddress())
+ .withTimeout(AbstractZkTestCase.TIMEOUT, TimeUnit.MILLISECONDS)
+ .withConnTimeOut(AbstractZkTestCase.TIMEOUT, TimeUnit.MILLISECONDS)
+ .build()) {
+ assertFalse(getConfigSetService().checkConfigExists(configSetName));
+
+ ConfigSetAdminResponse response =
+ createConfigSet(baseConfigSetName, configSetName, newProps, solrClient, username);
+ assertNotNull(response.getResponse());
+ assertTrue(getConfigSetService().checkConfigExists(configSetName));
+
+ verifyProperties(configSetName, oldProps, newProps, zkClient);
}
}
@@ -1639,8 +1635,7 @@ public class TestConfigSetsAPI extends SolrCloudTestCase {
@Test
public void testDeleteErrors() throws Exception {
- final String baseUrl = cluster.getJettySolrRunners().get(0).getBaseUrl().toString();
- final SolrClient solrClient = getHttpSolrClient(baseUrl);
+ final SolrClient solrClient = cluster.getJettySolrRunners().get(0).getSolrClient();
final Path configDir = getFile("solr").resolve("configsets/configset-2/conf");
final Path tmpConfigDir = createTempDir();
// Ensure ConfigSet is immutable
@@ -1658,8 +1653,6 @@ public class TestConfigSetsAPI extends SolrCloudTestCase {
// ConfigSet is immutable
delete.setConfigSetName("configSet");
verifyException(solrClient, delete, "Requested delete of immutable ConfigSet");
-
- solrClient.close();
}
@SuppressWarnings("try")
@@ -1675,13 +1668,11 @@ public class TestConfigSetsAPI extends SolrCloudTestCase {
@Test
public void testDelete() throws Exception {
- final String baseUrl = cluster.getJettySolrRunners().get(0).getBaseUrl().toString();
- final SolrClient solrClient = getHttpSolrClient(baseUrl);
+ final SolrClient solrClient = cluster.getJettySolrRunners().get(0).getSolrClient();
final String configSet = "testDelete";
getConfigSetService().uploadConfig(configSet, configset("configset-2"));
assertDelete(solrClient, configSet, true);
assertDelete(solrClient, "configSetBogus", false);
- solrClient.close();
}
private void assertDelete(SolrClient solrClient, String configSet, boolean assertExists)
@@ -1707,8 +1698,7 @@ public class TestConfigSetsAPI extends SolrCloudTestCase {
@Test
public void testList() throws Exception {
- final String baseUrl = cluster.getJettySolrRunners().get(0).getBaseUrl().toString();
- final SolrClient solrClient = getHttpSolrClient(baseUrl);
+ final SolrClient solrClient = cluster.getJettySolrRunners().get(0).getSolrClient();
SolrZkClient zkClient =
new SolrZkClient.Builder()
@@ -1737,8 +1727,6 @@ public class TestConfigSetsAPI extends SolrCloudTestCase {
} finally {
zkClient.close();
}
-
- solrClient.close();
}
/**
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPIExclusivity.java b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPIExclusivity.java
index 722ed01c1fa..4f4c715f742 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPIExclusivity.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPIExclusivity.java
@@ -118,8 +118,7 @@ public class TestConfigSetsAPIExclusivity extends SolrTestCaseJ4 {
@Override
public void run() {
- final String baseUrl = solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString();
- final SolrClient solrClient = getHttpSolrClient(baseUrl);
+ final SolrClient solrClient = solrCluster.getJettySolrRunners().get(0).getSolrClient();
ConfigSetAdminRequest<?, ?> request = createRequest();
for (int i = 0; i < trials; ++i) {
@@ -129,11 +128,6 @@ public class TestConfigSetsAPIExclusivity extends SolrTestCaseJ4 {
verifyException(e);
}
}
- try {
- solrClient.close();
- } catch (Exception e) {
- log.error("Error closing client", e);
- }
}
private void verifyException(Exception e) {
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPIZkFailure.java b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPIZkFailure.java
index 0cce6aef96f..2ce4b74190e 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPIZkFailure.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPIZkFailure.java
@@ -108,8 +108,7 @@ public class TestConfigSetsAPIZkFailure extends SolrTestCaseJ4 {
@Test
public void testCreateZkFailure() throws Exception {
- final String baseUrl = solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString();
- final SolrClient solrClient = getHttpSolrClient(baseUrl);
+ final SolrClient solrClient = solrCluster.getJettySolrRunners().get(0).getSolrClient();
final ConfigSetService configSetService =
solrCluster.getOpenOverseer().getCoreContainer().getConfigSetService();
@@ -136,8 +135,6 @@ public class TestConfigSetsAPIZkFailure extends SolrTestCaseJ4 {
} finally {
zkClient.close();
}
-
- solrClient.close();
}
private void setupBaseConfigSet(String baseConfigSetName, Map<String, String> oldProps)
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestGracefulJettyShutdown.java b/solr/core/src/test/org/apache/solr/cloud/TestGracefulJettyShutdown.java
index c0cc72fb206..a0c6fdbec99 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestGracefulJettyShutdown.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestGracefulJettyShutdown.java
@@ -28,6 +28,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.jetty.HttpJettySolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.QueryRequest;
import org.apache.solr.client.solrj.response.QueryResponse;
@@ -84,7 +85,8 @@ public class TestGracefulJettyShutdown extends SolrTestCaseJ4 {
final List<Future<QueryResponse>> results = new ArrayList<>(13);
- try (SolrClient jettyClient = nodeToStop.newClient()) {
+ try (SolrClient jettyClient =
+ new HttpJettySolrClient.Builder(nodeToStop.getBaseUrl().toString()).build()) {
final QueryRequest req = new QueryRequest(handler, params("q", "foo_s:aaa"));
// check inflight requests using both clients...
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java b/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java
index 39d6561381c..e49441cdd4e 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java
@@ -412,6 +412,6 @@ public class TestMiniSolrCloudClusterSSL extends SolrTestCaseJ4 {
if (random().nextBoolean()) {
return HttpSolrClient.builder(url).build();
} // else...
- return getHttpSolrClient(url);
+ return new HttpJettySolrClient.Builder(url).build();
}
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestPullReplica.java b/solr/core/src/test/org/apache/solr/cloud/TestPullReplica.java
index c6f30385972..d3e4c120b13 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestPullReplica.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestPullReplica.java
@@ -36,6 +36,7 @@ import java.util.stream.Collectors;
import org.apache.lucene.tests.util.LuceneTestCase.Nightly;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.jetty.HttpJettySolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.QueryRequest;
import org.apache.solr.client.solrj.request.SolrQuery;
@@ -297,9 +298,10 @@ public class TestPullReplica extends SolrCloudTestCase {
log.info("Committed doc {} to leader", numDocs);
Slice s = docCollection.getSlices().iterator().next();
- try (SolrClient leaderClient = getHttpSolrClient(s.getLeader())) {
- assertEquals(numDocs, leaderClient.query(new SolrQuery("*:*")).getResults().getNumFound());
- }
+ Replica sliceLeader = s.getLeader();
+ SolrClient leaderClient = cluster.getSolrClient(sliceLeader);
+ assertEquals(numDocs, leaderClient.query(new SolrQuery("*:*")).getResults().getNumFound());
+
log.info(
"Found {} docs in leader, verifying updates make it to {} pull replicas",
numDocs,
@@ -532,33 +534,32 @@ public class TestPullReplica extends SolrCloudTestCase {
Slice slice = docCollection.getSlice("shard1");
List<String> ids = new ArrayList<>(slice.getReplicas().size());
for (Replica rAdd : slice.getReplicas()) {
- try (SolrClient client = getHttpSolrClient(rAdd.getBaseUrl(), rAdd.getCoreName())) {
- client.add(new SolrInputDocument("id", String.valueOf(id), "foo_s", "bar"));
- }
+ SolrClient client = cluster.getSolrClient(rAdd);
+ client.add(new SolrInputDocument("id", String.valueOf(id), "foo_s", "bar"));
+
SolrDocument docCloudClient =
cluster.getSolrClient().getById(collectionName, String.valueOf(id));
assertEquals("bar", docCloudClient.getFieldValue("foo_s"));
for (Replica rGet : slice.getReplicas()) {
- try (SolrClient client = getHttpSolrClient(rGet.getBaseUrl(), rGet.getCoreName())) {
- SolrDocument doc = client.getById(String.valueOf(id));
- assertEquals("bar", doc.getFieldValue("foo_s"));
- }
+ SolrClient getClient = cluster.getSolrClient(rGet);
+ SolrDocument doc = getClient.getById(String.valueOf(id));
+ assertEquals("bar", doc.getFieldValue("foo_s"));
}
ids.add(String.valueOf(id));
id++;
}
SolrDocumentList previousAllIdsResult = null;
for (Replica rAdd : slice.getReplicas()) {
- try (SolrClient client = getHttpSolrClient(rAdd.getBaseUrl(), rAdd.getCoreName())) {
- SolrDocumentList allIdsResult = client.getById(ids);
- if (previousAllIdsResult != null) {
- assertTrue(compareSolrDocumentList(previousAllIdsResult, allIdsResult));
- } else {
- // set the first response here
- previousAllIdsResult = allIdsResult;
- assertEquals("Unexpected number of documents", ids.size(), allIdsResult.getNumFound());
- }
+ SolrClient client = cluster.getSolrClient(rAdd);
+ SolrDocumentList allIdsResult = client.getById(ids);
+ if (previousAllIdsResult != null) {
+ assertTrue(compareSolrDocumentList(previousAllIdsResult, allIdsResult));
+ } else {
+ // set the first response here
+ previousAllIdsResult = allIdsResult;
+ assertEquals("Unexpected number of documents", ids.size(), allIdsResult.getNumFound());
}
+
id++;
}
}
@@ -580,9 +581,9 @@ public class TestPullReplica extends SolrCloudTestCase {
cluster.getSolrClient().add(collectionName, new SolrInputDocument("id", "1", "foo", "bar"));
cluster.getSolrClient().commit(collectionName);
Slice s = docCollection.getSlices().iterator().next();
- try (SolrClient leaderClient = getHttpSolrClient(s.getLeader())) {
- assertEquals(1, leaderClient.query(new SolrQuery("*:*")).getResults().getNumFound());
- }
+ Replica sliceLeader = s.getLeader();
+ SolrClient leaderClient = cluster.getSolrClient(sliceLeader);
+ assertEquals(1, leaderClient.query(new SolrQuery("*:*")).getResults().getNumFound());
waitForNumDocsInAllReplicas(1, getReplicas(docCollection, EnumSet.of(Replica.Type.PULL)));
@@ -637,7 +638,11 @@ public class TestPullReplica extends SolrCloudTestCase {
// Also fails if I send the update to the pull replica explicitly
try (SolrClient pullReplicaClient =
- getHttpSolrClient(getReplicas(docCollection, EnumSet.of(Replica.Type.PULL)).get(0))) {
+ new HttpJettySolrClient.Builder(
+ getReplicas(docCollection, EnumSet.of(Replica.Type.PULL)).get(0).getBaseUrl())
+ .withDefaultCollection(
+ getReplicas(docCollection, EnumSet.of(Replica.Type.PULL)).get(0).getCoreName())
+ .build()) {
expectThrows(
SolrException.class,
() ->
@@ -685,10 +690,11 @@ public class TestPullReplica extends SolrCloudTestCase {
// add docs agin
cluster.getSolrClient().add(collectionName, new SolrInputDocument("id", "2", "foo", "zoo"));
s = docCollection.getSlices().iterator().next();
- try (SolrClient leaderClient = getHttpSolrClient(s.getLeader())) {
- leaderClient.commit();
- assertEquals(1, leaderClient.query(new SolrQuery("*:*")).getResults().getNumFound());
- }
+ sliceLeader = s.getLeader();
+ leaderClient = cluster.getSolrClient(sliceLeader);
+ leaderClient.commit();
+ assertEquals(1, leaderClient.query(new SolrQuery("*:*")).getResults().getNumFound());
+
waitForNumDocsInAllReplicas(
1, getReplicas(docCollection, EnumSet.of(Replica.Type.PULL)), "id:2", null, null);
waitForNumDocsInAllReplicas(1, getReplicas(docCollection, EnumSet.of(Replica.Type.PULL)));
@@ -889,32 +895,31 @@ public class TestPullReplica extends SolrCloudTestCase {
TimeOut t = new TimeOut(REPLICATION_TIMEOUT_SECS, TimeUnit.SECONDS, TimeSource.NANO_TIME);
for (Replica r : replicas) {
String replicaUrl = r.getCoreUrl();
- try (SolrClient replicaClient = getHttpSolrClient(r)) {
- while (true) {
- QueryRequest req = new QueryRequest(new SolrQuery(query));
- if (user != null && pass != null) {
- req.setBasicAuthCredentials(user, pass);
- }
- try {
- long numFound = req.process(replicaClient).getResults().getNumFound();
- assertEquals(
- "Replica "
- + r.getName()
- + " ("
- + replicaUrl
- + ") not up to date after "
- + REPLICATION_TIMEOUT_SECS
- + " seconds",
- numDocs,
- numFound);
- log.info("Replica {} ({}) has all {} docs", r.name, replicaUrl, numDocs);
- break;
- } catch (AssertionError e) {
- if (t.hasTimedOut()) {
- throw e;
- } else {
- Thread.sleep(200);
- }
+ SolrClient replicaClient = cluster.getSolrClient(r);
+ while (true) {
+ QueryRequest req = new QueryRequest(new SolrQuery(query));
+ if (user != null && pass != null) {
+ req.setBasicAuthCredentials(user, pass);
+ }
+ try {
+ long numFound = req.process(replicaClient).getResults().getNumFound();
+ assertEquals(
+ "Replica "
+ + r.getName()
+ + " ("
+ + replicaUrl
+ + ") not up to date after "
+ + REPLICATION_TIMEOUT_SECS
+ + " seconds",
+ numDocs,
+ numFound);
+ log.info("Replica {} ({}) has all {} docs", r.name, replicaUrl, numDocs);
+ break;
+ } catch (AssertionError e) {
+ if (t.hasTimedOut()) {
+ throw e;
+ } else {
+ Thread.sleep(200);
}
}
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestPullReplicaErrorHandling.java b/solr/core/src/test/org/apache/solr/cloud/TestPullReplicaErrorHandling.java
index c4c4047487c..5797e0d3020 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestPullReplicaErrorHandling.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestPullReplicaErrorHandling.java
@@ -29,6 +29,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.solr.SolrTestCaseJ4.SuppressSSL;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.jetty.HttpJettySolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.SolrQuery;
import org.apache.solr.common.SolrException;
@@ -140,9 +141,8 @@ public class TestPullReplicaErrorHandling extends SolrCloudTestCase {
proxy.close();
for (int i = 1; i <= 10; i++) {
addDocs(10 + i);
- try (SolrClient leaderClient = getHttpSolrClient(s.getLeader())) {
- assertNumDocs(10 + i, leaderClient);
- }
+ Replica leader = s.getLeader();
+ assertNumDocs(10 + i, cluster.getSolrClient(leader));
}
SolrServerException e =
@@ -150,7 +150,11 @@ public class TestPullReplicaErrorHandling extends SolrCloudTestCase {
SolrServerException.class,
() -> {
try (SolrClient pullReplicaClient =
- getHttpSolrClient(s.getReplicas(EnumSet.of(Replica.Type.PULL)).get(0))) {
+ new HttpJettySolrClient.Builder(
+ s.getReplicas(EnumSet.of(Replica.Type.PULL)).get(0).getBaseUrl())
+ .withDefaultCollection(
+ s.getReplicas(EnumSet.of(Replica.Type.PULL)).get(0).getCoreName())
+ .build()) {
pullReplicaClient.query(new SolrQuery("*:*")).getResults().getNumFound();
}
});
@@ -174,10 +178,7 @@ public class TestPullReplicaErrorHandling extends SolrCloudTestCase {
proxy.reopen();
}
- try (SolrClient pullReplicaClient =
- getHttpSolrClient(s.getReplicas(EnumSet.of(Replica.Type.PULL)).get(0))) {
- assertNumDocs(20, pullReplicaClient);
- }
+ assertNumDocs(20, cluster.getSolrClient(s.getReplicas(EnumSet.of(Replica.Type.PULL)).get(0)));
}
public void testCantConnectToLeader() throws Exception {
@@ -191,16 +192,10 @@ public class TestPullReplicaErrorHandling extends SolrCloudTestCase {
SocketProxy proxy = getProxyForReplica(s.getLeader());
try {
// wait for replication
- try (SolrClient pullReplicaClient =
- getHttpSolrClient(s.getReplicas(EnumSet.of(Replica.Type.PULL)).get(0))) {
- assertNumDocs(10, pullReplicaClient);
- }
+ assertNumDocs(10, cluster.getSolrClient(s.getReplicas(EnumSet.of(Replica.Type.PULL)).get(0)));
proxy.close();
expectThrows(SolrException.class, () -> addDocs(1));
- try (SolrClient pullReplicaClient =
- getHttpSolrClient(s.getReplicas(EnumSet.of(Replica.Type.PULL)).get(0))) {
- assertNumDocs(10, pullReplicaClient);
- }
+ assertNumDocs(10, cluster.getSolrClient(s.getReplicas(EnumSet.of(Replica.Type.PULL)).get(0)));
assertNumDocs(10, cluster.getSolrClient(collectionName));
} finally {
log.info("Opening leader node");
@@ -227,10 +222,7 @@ public class TestPullReplicaErrorHandling extends SolrCloudTestCase {
addDocs(10);
DocCollection docCollection = assertNumberOfReplicas(numShards, 0, numShards, false, true);
Slice s = docCollection.getSlices().iterator().next();
- try (SolrClient pullReplicaClient =
- getHttpSolrClient(s.getReplicas(EnumSet.of(Replica.Type.PULL)).get(0))) {
- assertNumDocs(10, pullReplicaClient);
- }
+ assertNumDocs(10, cluster.getSolrClient(s.getReplicas(EnumSet.of(Replica.Type.PULL)).get(0)));
addDocs(20);
JettySolrRunner jetty = getJettyForReplica(s.getReplicas(EnumSet.of(Replica.Type.PULL)).get(0));
cluster.expireZkSession(jetty);
@@ -238,10 +230,7 @@ public class TestPullReplicaErrorHandling extends SolrCloudTestCase {
waitForState("Expecting node to be disconnected", collectionName, activeReplicaCount(1, 0, 0));
addDocs(40);
waitForState("Expecting node to be reconnected", collectionName, activeReplicaCount(1, 0, 1));
- try (SolrClient pullReplicaClient =
- getHttpSolrClient(s.getReplicas(EnumSet.of(Replica.Type.PULL)).get(0))) {
- assertNumDocs(40, pullReplicaClient);
- }
+ assertNumDocs(40, cluster.getSolrClient(s.getReplicas(EnumSet.of(Replica.Type.PULL)).get(0)));
}
public void testCloseHooksDeletedOnReconnect() throws Exception {
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestPullReplicaWithAuth.java b/solr/core/src/test/org/apache/solr/cloud/TestPullReplicaWithAuth.java
index 4439f8fbf35..8d3fea023d3 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestPullReplicaWithAuth.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestPullReplicaWithAuth.java
@@ -93,11 +93,11 @@ public class TestPullReplicaWithAuth extends SolrCloudTestCase {
ureq.commit(solrClient, collectionName);
Slice s = docCollection.getSlices().iterator().next();
- try (SolrClient leaderClient = getHttpSolrClient(s.getLeader())) {
- assertEquals(
- numDocs,
- queryWithBasicAuth(leaderClient, new SolrQuery("*:*")).getResults().getNumFound());
- }
+ Replica leader = s.getLeader();
+ SolrClient leaderClient = cluster.getSolrClient(leader);
+ assertEquals(
+ numDocs,
+ queryWithBasicAuth(leaderClient, new SolrQuery("*:*")).getResults().getNumFound());
List<Replica> pullReplicas = s.getReplicas(EnumSet.of(Replica.Type.PULL));
waitForNumDocsInAllReplicas(
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestQueryingOnDownCollection.java b/solr/core/src/test/org/apache/solr/cloud/TestQueryingOnDownCollection.java
index 2d9d9749221..0fa50874d0d 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestQueryingOnDownCollection.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestQueryingOnDownCollection.java
@@ -19,7 +19,6 @@ package org.apache.solr.cloud;
import java.util.Map;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrRequest;
-import org.apache.solr.client.solrj.jetty.HttpJettySolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.QueryRequest;
import org.apache.solr.client.solrj.request.SolrQuery;
@@ -82,41 +81,33 @@ public class TestQueryingOnDownCollection extends SolrCloudTestCase {
new QueryRequest(new SolrQuery("*:*").setRows(0))
.setBasicAuthCredentials(USERNAME, PASSWORD);
- try (SolrClient client = cluster.getJettySolrRunner(0).newClient()) {
- // Without the SOLR-13793 fix, this causes requests to "down collection" to pile up (until the
- // nodes run out of serviceable threads, and they crash, even for other collections hosted on
- // the
- // nodes).
- SolrException error =
- expectThrows(
- SolrException.class,
- "Request should fail after trying all replica nodes once",
- () -> client.request(req, COLLECTION_NAME));
-
- assertEquals(error.code(), SolrException.ErrorCode.INVALID_STATE.code);
- assertTrue(
- error
- .getMessage()
- .contains("No active replicas found for collection: " + COLLECTION_NAME));
- }
+ SolrClient client = cluster.getJettySolrRunner(0).getSolrClient();
+ // Without the SOLR-13793 fix, this causes requests to "down collection" to pile up (until the
+ // nodes run out of serviceable threads, and they crash, even for other collections hosted on
+ // the
+ // nodes).
+ SolrException error =
+ expectThrows(
+ SolrException.class,
+ "Request should fail after trying all replica nodes once",
+ () -> client.request(req, COLLECTION_NAME));
+
+ assertEquals(error.code(), SolrException.ErrorCode.INVALID_STATE.code);
+ assertTrue(
+ error.getMessage().contains("No active replicas found for collection: " + COLLECTION_NAME));
// run same set of tests on v2 client which uses V2HttpCall
- try (SolrClient v2Client =
- new HttpJettySolrClient.Builder(cluster.getJettySolrRunner(0).getBaseUrl().toString())
- .build()) {
-
- SolrException error =
- expectThrows(
- SolrException.class,
- "Request should fail after trying all replica nodes once",
- () -> v2Client.request(req, COLLECTION_NAME));
-
- assertEquals(error.code(), SolrException.ErrorCode.INVALID_STATE.code);
- assertTrue(
- error
- .getMessage()
- .contains("No active replicas found for collection: " + COLLECTION_NAME));
- }
+ SolrClient v2Client = cluster.getJettySolrRunner(0).getSolrClient();
+
+ error =
+ expectThrows(
+ SolrException.class,
+ "Request should fail after trying all replica nodes once",
+ () -> v2Client.request(req, COLLECTION_NAME));
+
+ assertEquals(error.code(), SolrException.ErrorCode.INVALID_STATE.code);
+ assertTrue(
+ error.getMessage().contains("No active replicas found for collection: " + COLLECTION_NAME));
}
@SuppressWarnings({"unchecked"})
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestStressCloudBlindAtomicUpdates.java b/solr/core/src/test/org/apache/solr/cloud/TestStressCloudBlindAtomicUpdates.java
index 8abccaf7fbd..d9297f2d206 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestStressCloudBlindAtomicUpdates.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestStressCloudBlindAtomicUpdates.java
@@ -17,7 +17,6 @@
package org.apache.solr.cloud;
import java.lang.invoke.MethodHandles;
-import java.net.URL;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
@@ -33,6 +32,7 @@ import org.apache.lucene.tests.util.TestUtil;
import org.apache.solr.SolrTestCaseJ4.SuppressSSL;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.CollectionScopedSolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.UpdateRequest;
import org.apache.solr.client.solrj.request.schema.SchemaRequest.Field;
@@ -139,9 +139,7 @@ public class TestStressCloudBlindAtomicUpdates extends SolrCloudTestCase {
CLIENTS.clear();
for (JettySolrRunner jetty : cluster.getJettySolrRunners()) {
assertNotNull("Cluster contains null jetty?", jetty);
- final URL baseUrl = jetty.getBaseUrl();
- assertNotNull("Jetty has null baseUrl: " + jetty, baseUrl);
- CLIENTS.add(getHttpSolrClient(baseUrl.toString(), COLLECTION_NAME));
+ CLIENTS.add(new CollectionScopedSolrClient(jetty.getSolrClient(), COLLECTION_NAME));
}
// sanity check no one broke the assumptions we make about our schema
@@ -166,12 +164,7 @@ public class TestStressCloudBlindAtomicUpdates extends SolrCloudTestCase {
IOUtils.closeQuietly(COLLECTION_CLIENT);
COLLECTION_CLIENT = null;
}
- for (SolrClient client : CLIENTS) {
- if (null == client) {
- log.error("CLIENTS contains a null SolrClient???");
- }
- IOUtils.closeQuietly(client);
- }
+ // the jettys own these clients
CLIENTS.clear();
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestTlogReplayVsRecovery.java b/solr/core/src/test/org/apache/solr/cloud/TestTlogReplayVsRecovery.java
index af90ea36ee3..b181eaa7cb3 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestTlogReplayVsRecovery.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestTlogReplayVsRecovery.java
@@ -243,11 +243,10 @@ public class TestTlogReplayVsRecovery extends SolrCloudTestCase {
}
// For simplicity, we always add out docs directly to NODE0
// (where the leader should be) and bypass the proxy...
- try (SolrClient client = getHttpSolrClient(NODE0.getBaseUrl().toString())) {
- assertEquals(0, client.add(COLLECTION, docs).getStatus());
- if (commit) {
- assertEquals(0, client.commit(COLLECTION).getStatus());
- }
+ SolrClient client = NODE0.getSolrClient();
+ assertEquals(0, client.add(COLLECTION, docs).getStatus());
+ if (commit) {
+ assertEquals(0, client.commit(COLLECTION).getStatus());
}
}
@@ -256,13 +255,12 @@ public class TestTlogReplayVsRecovery extends SolrCloudTestCase {
* (inclusive) can be found on both the leader and the replica
*/
private void assertDocsExistInBothReplicas(int firstDocId, int lastDocId) throws Exception {
- try (SolrClient leaderSolr = getHttpSolrClient(NODE0.getBaseUrl().toString());
- SolrClient replicaSolr = getHttpSolrClient(NODE1.getBaseUrl().toString())) {
- for (int d = firstDocId; d <= lastDocId; d++) {
- String docId = String.valueOf(d);
- assertDocExists("leader", leaderSolr, docId);
- assertDocExists("replica", replicaSolr, docId);
- }
+ SolrClient leaderSolr = NODE0.getSolrClient();
+ SolrClient replicaSolr = NODE1.getSolrClient();
+ for (int d = firstDocId; d <= lastDocId; d++) {
+ String docId = String.valueOf(d);
+ assertDocExists("leader", leaderSolr, docId);
+ assertDocExists("replica", replicaSolr, docId);
}
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestTlogReplica.java b/solr/core/src/test/org/apache/solr/cloud/TestTlogReplica.java
index 855a6562ce4..9a1e9f7524c 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestTlogReplica.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestTlogReplica.java
@@ -257,50 +257,49 @@ public class TestTlogReplica extends SolrCloudTestCase {
cluster.getSolrClient().commit(collectionName);
Slice s = docCollection.getSlices().iterator().next();
- try (SolrClient leaderClient = getHttpSolrClient(s.getLeader())) {
- assertEquals(1, leaderClient.query(new SolrQuery("*:*")).getResults().getNumFound());
- }
+ Replica sliceLeader = s.getLeader();
+ SolrClient leaderClient = cluster.getSolrClient(sliceLeader);
+ assertEquals(1, leaderClient.query(new SolrQuery("*:*")).getResults().getNumFound());
TimeOut t = new TimeOut(REPLICATION_TIMEOUT_SECS, TimeUnit.SECONDS, TimeSource.NANO_TIME);
for (Replica r : s.getReplicas(EnumSet.of(Replica.Type.TLOG))) {
// TODO: assert replication < REPLICATION_TIMEOUT_SECS
- try (SolrClient tlogReplicaClient = getHttpSolrClient(r)) {
- while (true) {
- try {
+ SolrClient tlogReplicaClient = cluster.getSolrClient(r);
+ while (true) {
+ try {
+ assertEquals(
+ "Replica " + r.getName() + " not up to date after 10 seconds",
+ 1,
+ tlogReplicaClient.query(new SolrQuery("*:*")).getResults().getNumFound());
+ JettySolrRunner jetty =
+ cluster.getJettySolrRunners().stream()
+ .filter(j -> j.getBaseUrl().toString().equals(r.getBaseUrl()))
+ .findFirst()
+ .orElse(null);
+ assertNotNull("Could not find jetty for replica " + r, jetty);
+
+ try (SolrCore core = jetty.getCoreContainer().getCore(r.getCoreName())) {
+ var cumulativeAddsDatapoint =
+ SolrMetricTestUtils.getGaugeDatapoint(
+ core,
+ "solr_core_update_cumulative_ops",
+ SolrMetricTestUtils.newCloudLabelsBuilder(core)
+ .label("category", "UPDATE")
+ .label("ops", "adds")
+ .build());
+ assertNotNull("Could not find cumulative adds metric", cumulativeAddsDatapoint);
assertEquals(
- "Replica " + r.getName() + " not up to date after 10 seconds",
- 1,
- tlogReplicaClient.query(new SolrQuery("*:*")).getResults().getNumFound());
- JettySolrRunner jetty =
- cluster.getJettySolrRunners().stream()
- .filter(j -> j.getBaseUrl().toString().equals(r.getBaseUrl()))
- .findFirst()
- .orElse(null);
- assertNotNull("Could not find jetty for replica " + r, jetty);
-
- try (SolrCore core = jetty.getCoreContainer().getCore(r.getCoreName())) {
- var cumulativeAddsDatapoint =
- SolrMetricTestUtils.getGaugeDatapoint(
- core,
- "solr_core_update_cumulative_ops",
- SolrMetricTestUtils.newCloudLabelsBuilder(core)
- .label("category", "UPDATE")
- .label("ops", "adds")
- .build());
- assertNotNull("Could not find cumulative adds metric", cumulativeAddsDatapoint);
- assertEquals(
- "Append replicas should receive all updates. Replica: " + r,
- 1.0,
- cumulativeAddsDatapoint.getValue(),
- 0.0);
- }
- break;
- } catch (AssertionError e) {
- if (t.hasTimedOut()) {
- throw e;
- } else {
- Thread.sleep(100);
- }
+ "Append replicas should receive all updates. Replica: " + r,
+ 1.0,
+ cumulativeAddsDatapoint.getValue(),
+ 0.0);
+ }
+ break;
+ } catch (AssertionError e) {
+ if (t.hasTimedOut()) {
+ throw e;
+ } else {
+ Thread.sleep(100);
}
}
}
@@ -443,9 +442,9 @@ public class TestTlogReplica extends SolrCloudTestCase {
cluster.getSolrClient().add(collectionName, new SolrInputDocument("id", "1", "foo", "bar"));
cluster.getSolrClient().commit(collectionName);
Slice s = docCollection.getSlices().iterator().next();
- try (SolrClient leaderClient = getHttpSolrClient(s.getLeader())) {
- assertEquals(1, leaderClient.query(new SolrQuery("*:*")).getResults().getNumFound());
- }
+ Replica sliceLeader = s.getLeader();
+ SolrClient leaderClient = cluster.getSolrClient(sliceLeader);
+ assertEquals(1, leaderClient.query(new SolrQuery("*:*")).getResults().getNumFound());
waitForNumDocsInAllReplicas(
1, getReplicas(docCollection, EnumSet.of(Replica.Type.TLOG)), REPLICATION_TIMEOUT_SECS);
@@ -895,10 +894,9 @@ public class TestTlogReplica extends SolrCloudTestCase {
updates.add(simulatedDBQ("inplace_updatable_int:5", 3L));
updates.add(simulatedUpdateRequest(1L, "id", 1, "inplace_updatable_int", 6, "_version_", 2L));
for (JettySolrRunner solrRunner : getSolrRunner(false)) {
- try (SolrClient client = solrRunner.newClient()) {
- for (UpdateRequest up : updates) {
- up.process(client, collectionName);
- }
+ SolrClient client = solrRunner.getSolrClient();
+ for (UpdateRequest up : updates) {
+ up.process(client, collectionName);
}
}
JettySolrRunner oldLeaderJetty = getSolrRunner(true).get(0);
@@ -1000,20 +998,19 @@ public class TestTlogReplica extends SolrCloudTestCase {
if (!r.isActive(cluster.getSolrClient().getClusterState().getLiveNodes())) {
continue;
}
- try (SolrClient replicaClient = getHttpSolrClient(r)) {
- while (true) {
- try {
- assertEquals(
- "Replica " + r.getName() + " not up to date after " + timeout + " seconds",
- numDocs,
- replicaClient.query(new SolrQuery(query)).getResults().getNumFound());
- break;
- } catch (AssertionError e) {
- if (t.hasTimedOut()) {
- throw e;
- } else {
- Thread.sleep(100);
- }
+ SolrClient replicaClient = cluster.getSolrClient(r);
+ while (true) {
+ try {
+ assertEquals(
+ "Replica " + r.getName() + " not up to date after " + timeout + " seconds",
+ numDocs,
+ replicaClient.query(new SolrQuery(query)).getResults().getNumFound());
+ break;
+ } catch (AssertionError e) {
+ if (t.hasTimedOut()) {
+ throw e;
+ } else {
+ Thread.sleep(100);
}
}
}
@@ -1150,17 +1147,16 @@ public class TestTlogReplica extends SolrCloudTestCase {
private void checkRTG(int from, int to, List<JettySolrRunner> solrRunners) throws Exception {
for (JettySolrRunner solrRunner : solrRunners) {
- try (SolrClient client = solrRunner.newClient()) {
- for (int i = from; i <= to; i++) {
- SolrQuery query = new SolrQuery();
- query.set("distrib", false);
- query.setRequestHandler("/get");
- query.set("id", i);
- QueryResponse res = client.query(collectionName, query);
- assertNotNull(
- "Can not find doc " + i + " in " + solrRunner.getBaseUrl(),
- res.getResponse().get("doc"));
- }
+ SolrClient client = solrRunner.getSolrClient();
+ for (int i = from; i <= to; i++) {
+ SolrQuery query = new SolrQuery();
+ query.set("distrib", false);
+ query.setRequestHandler("/get");
+ query.set("id", i);
+ QueryResponse res = client.query(collectionName, query);
+ assertNotNull(
+ "Can not find doc " + i + " in " + solrRunner.getBaseUrl(),
+ res.getResponse().get("doc"));
}
}
}
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 dc0a4435949..107f7b273b3 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorCloud.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorCloud.java
@@ -27,6 +27,7 @@ import java.util.List;
import java.util.Set;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.CollectionScopedSolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.UpdateRequest;
import org.apache.solr.client.solrj.response.UpdateResponse;
@@ -145,17 +146,27 @@ public class TestTolerantUpdateProcessorCloud extends SolrCloudTestCase {
assertNotNull("could not find URL for " + shardName + " replica", passiveUrl);
if (shardName.equals("shard1")) {
- S_ONE_LEADER_CLIENT = getHttpSolrClient(leaderUrl, COLLECTION_NAME);
- S_ONE_NON_LEADER_CLIENT = getHttpSolrClient(passiveUrl, COLLECTION_NAME);
+ S_ONE_LEADER_CLIENT =
+ new CollectionScopedSolrClient(
+ cluster.getJetty(leaderUrl).getSolrClient(), COLLECTION_NAME);
+ S_ONE_NON_LEADER_CLIENT =
+ new CollectionScopedSolrClient(
+ cluster.getJetty(passiveUrl).getSolrClient(), COLLECTION_NAME);
} else if (shardName.equals("shard2")) {
- S_TWO_LEADER_CLIENT = getHttpSolrClient(leaderUrl, COLLECTION_NAME);
- S_TWO_NON_LEADER_CLIENT = getHttpSolrClient(passiveUrl, COLLECTION_NAME);
+ S_TWO_LEADER_CLIENT =
+ new CollectionScopedSolrClient(
+ cluster.getJetty(leaderUrl).getSolrClient(), COLLECTION_NAME);
+ S_TWO_NON_LEADER_CLIENT =
+ new CollectionScopedSolrClient(
+ cluster.getJetty(passiveUrl).getSolrClient(), COLLECTION_NAME);
} else {
fail("unexpected shard: " + shardName);
}
}
assertEquals("Should be exactly one server left (not hosting either shard)", 1, urlMap.size());
- NO_COLLECTION_CLIENT = getHttpSolrClient(urlMap.values().iterator().next(), COLLECTION_NAME);
+ NO_COLLECTION_CLIENT =
+ new CollectionScopedSolrClient(
+ cluster.getJetty(urlMap.values().iterator().next()).getSolrClient(), COLLECTION_NAME);
assertNotNull(S_ONE_LEADER_CLIENT);
assertNotNull(S_TWO_LEADER_CLIENT);
@@ -204,15 +215,10 @@ public class TestTolerantUpdateProcessorCloud extends SolrCloudTestCase {
@AfterClass
public static void afterClass() throws IOException {
- close(S_ONE_LEADER_CLIENT);
S_ONE_LEADER_CLIENT = null;
- close(S_TWO_LEADER_CLIENT);
S_TWO_LEADER_CLIENT = null;
- close(S_ONE_NON_LEADER_CLIENT);
S_ONE_NON_LEADER_CLIENT = null;
- close(S_TWO_NON_LEADER_CLIENT);
S_TWO_NON_LEADER_CLIENT = null;
- close(NO_COLLECTION_CLIENT);
NO_COLLECTION_CLIENT = null;
close(COLLECTION_CLIENT);
COLLECTION_CLIENT = null;
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 a39197320cf..c96a633577b 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorRandomCloud.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorRandomCloud.java
@@ -27,7 +27,6 @@ import static org.apache.solr.common.params.CursorMarkParams.CURSOR_MARK_START;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
-import java.net.URL;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.BitSet;
@@ -39,6 +38,7 @@ import org.apache.lucene.tests.util.TestUtil;
import org.apache.solr.SolrTestCaseJ4.SuppressSSL;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.CollectionScopedSolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.UpdateRequest;
import org.apache.solr.client.solrj.response.QueryResponse;
@@ -114,8 +114,7 @@ public class TestTolerantUpdateProcessorRandomCloud extends SolrCloudTestCase {
NODE_CLIENTS = new ArrayList<SolrClient>(numServers);
for (JettySolrRunner jetty : cluster.getJettySolrRunners()) {
- URL jettyURL = jetty.getBaseUrl();
- NODE_CLIENTS.add(getHttpSolrClient(jettyURL.toString(), COLLECTION_NAME));
+ NODE_CLIENTS.add(new CollectionScopedSolrClient(jetty.getSolrClient(), COLLECTION_NAME));
}
assertEquals(numServers, NODE_CLIENTS.size());
}
@@ -133,11 +132,7 @@ public class TestTolerantUpdateProcessorRandomCloud extends SolrCloudTestCase {
@AfterClass
public static void afterClass() throws IOException {
- if (NODE_CLIENTS != null) {
- for (SolrClient client : NODE_CLIENTS) {
- client.close();
- }
- }
+ // the jettys own these clients
NODE_CLIENTS = null;
if (COLLECTION_CLIENT != null) {
COLLECTION_CLIENT.close();
diff --git a/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java b/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java
index 93781dbbd1e..c79fa27b77a 100644
--- a/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java
@@ -155,29 +155,22 @@ public class UnloadDistributedZkTest extends AbstractFullDistribZkTestBase {
final String unloadCmdCoreName1 = (unloadInOrder ? coreName1 : coreName2);
final String unloadCmdCoreName2 = (unloadInOrder ? coreName2 : coreName1);
- try (SolrClient adminClient = getHttpSolrClient(buildUrl(jettys.get(0).getLocalPort()))) {
- // now unload one of the two
- Unload unloadCmd = new Unload(false);
- unloadCmd.setCoreName(unloadCmdCoreName1);
- adminClient.request(unloadCmd);
-
- // there should still be two shards (as of SOLR-5209)
- checkCoreNamePresenceAndSliceCount(
- collection,
- unloadCmdCoreName1,
- false /* shouldBePresent */,
- numShards /* expectedSliceCount */);
-
- // now unload one of the other
- unloadCmd = new Unload(false);
- unloadCmd.setCoreName(unloadCmdCoreName2);
- adminClient.request(unloadCmd);
- checkCoreNamePresenceAndSliceCount(
- collection,
- unloadCmdCoreName2,
- false /* shouldBePresent */,
- numShards /* expectedSliceCount */);
- }
+ SolrClient adminClient = jettys.get(0).getSolrClient();
+ // now unload one of the two
+ Unload unloadCmd = new Unload(false);
+ unloadCmd.setCoreName(unloadCmdCoreName1);
+ adminClient.request(unloadCmd);
+
+ // there should still be two shards (as of SOLR-5209)
+ checkCoreNamePresenceAndSliceCount(
+ collection, unloadCmdCoreName1, false /* shouldBePresent */, numShards);
+
+ // now unload one of the other
+ unloadCmd = new Unload(false);
+ unloadCmd.setCoreName(unloadCmdCoreName2);
+ adminClient.request(unloadCmd);
+ checkCoreNamePresenceAndSliceCount(
+ collection, unloadCmdCoreName2, false /* shouldBePresent */, numShards);
// printLayout();
// the collection should still be present (as of SOLR-5209 replica removal does not cascade to
@@ -391,56 +384,55 @@ public class UnloadDistributedZkTest extends AbstractFullDistribZkTestBase {
private void testUnloadLotsOfCores() throws Exception {
JettySolrRunner jetty = jettys.get(0);
int shards = TEST_NIGHTLY ? 2 : 1;
- try (final SolrClient adminClient = jetty.newClient(15000, 60000)) {
- int numReplicas = atLeast(3);
- ThreadPoolExecutor executor =
- new ExecutorUtil.MDCAwareThreadPoolExecutor(
- 0,
- Integer.MAX_VALUE,
- 5,
- TimeUnit.SECONDS,
- new SynchronousQueue<>(),
- new SolrNamedThreadFactory("testExecutor"));
- try {
- // create the cores
- BasicDistributedZkTest.createCollectionInOneInstance(
- adminClient, jetty.getNodeName(), executor, "multiunload", shards, numReplicas);
- } finally {
- ExecutorUtil.shutdownAndAwaitTermination(executor);
- }
+ final SolrClient adminClient = jetty.getSolrClient();
+ int numReplicas = atLeast(3);
+ ThreadPoolExecutor executor =
+ new ExecutorUtil.MDCAwareThreadPoolExecutor(
+ 0,
+ Integer.MAX_VALUE,
+ 5,
+ TimeUnit.SECONDS,
+ new SynchronousQueue<>(),
+ new SolrNamedThreadFactory("testExecutor"));
+ try {
+ // create the cores
+ BasicDistributedZkTest.createCollectionInOneInstance(
+ adminClient, jetty.getNodeName(), executor, "multiunload", shards, numReplicas);
+ } finally {
+ ExecutorUtil.shutdownAndAwaitTermination(executor);
+ }
- if (TEST_NIGHTLY == false) {
- // with nightly tests, we can try doing the unloads before the creates are done
- // it still works, but takes much longer since we end up waiting for a timeout
- waitForRecoveriesToFinish("multiunload", false);
- }
+ if (TEST_NIGHTLY == false) {
+ // with nightly tests, we can try doing the unloads before the creates are done
+ // it still works, but takes much longer since we end up waiting for a timeout
+ waitForRecoveriesToFinish("multiunload", false);
+ }
- executor =
- new ExecutorUtil.MDCAwareThreadPoolExecutor(
- 0,
- Integer.MAX_VALUE,
- 5,
- TimeUnit.SECONDS,
- new SynchronousQueue<>(),
- new SolrNamedThreadFactory("testExecutor"));
- try {
- for (int j = 0; j < numReplicas; j++) {
- final int freezeJ = j;
- executor.execute(
- () -> {
- Unload unloadCmd = new Unload(true);
- unloadCmd.setCoreName("multiunload" + freezeJ);
- try {
- adminClient.request(unloadCmd);
- } catch (SolrServerException | IOException e) {
- throw new RuntimeException(e);
- }
- });
- Thread.sleep(random().nextInt(50));
- }
- } finally {
- ExecutorUtil.shutdownAndAwaitTermination(executor);
+ executor =
+ new ExecutorUtil.MDCAwareThreadPoolExecutor(
+ 0,
+ Integer.MAX_VALUE,
+ 5,
+ TimeUnit.SECONDS,
+ new SynchronousQueue<>(),
+ new SolrNamedThreadFactory("testExecutor"));
+ try {
+ for (int j = 0; j < numReplicas; j++) {
+ final int freezeJ = j;
+ executor.execute(
+ () -> {
+ Unload unloadCmd = new Unload(true);
+ unloadCmd.setCoreName("multiunload" + freezeJ);
+ try {
+ adminClient.request(unloadCmd);
+ } catch (SolrServerException | IOException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ Thread.sleep(random().nextInt(50));
}
+ } finally {
+ ExecutorUtil.shutdownAndAwaitTermination(executor);
}
}
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/ZkShardTermsRecoveryTest.java b/solr/core/src/test/org/apache/solr/cloud/ZkShardTermsRecoveryTest.java
index 10385f2c54c..cc0f5ca7e6c 100644
--- a/solr/core/src/test/org/apache/solr/cloud/ZkShardTermsRecoveryTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/ZkShardTermsRecoveryTest.java
@@ -190,12 +190,11 @@ public class ZkShardTermsRecoveryTest extends SolrCloudTestCase {
if (!r.isActive(cluster.getSolrClient().getClusterState().getLiveNodes())) {
continue;
}
- try (SolrClient replicaClient = getHttpSolrClient(r)) {
- assertEquals(
- "Replica " + r.getName() + " not up to date",
- numDocs,
- replicaClient.query(new SolrQuery(query)).getResults().getNumFound());
- }
+ SolrClient replicaClient = cluster.getSolrClient(r);
+ assertEquals(
+ "Replica " + r.getName() + " not up to date",
+ numDocs,
+ replicaClient.query(new SolrQuery(query)).getResults().getNumFound());
}
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/api/collections/ConcurrentDeleteAndCreateCollectionTest.java b/solr/core/src/test/org/apache/solr/cloud/api/collections/ConcurrentDeleteAndCreateCollectionTest.java
index c89f46ccf39..44edb664e3c 100644
--- a/solr/core/src/test/org/apache/solr/cloud/api/collections/ConcurrentDeleteAndCreateCollectionTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/api/collections/ConcurrentDeleteAndCreateCollectionTest.java
@@ -67,8 +67,7 @@ public class ConcurrentDeleteAndCreateCollectionTest extends SolrTestCaseJ4 {
for (int i = 0; i < threads.length; i++) {
final String collectionName = "collection" + i;
solrCluster.uploadConfigSet(configset("configset-2"), collectionName);
- final String baseUrl = solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString();
- final SolrClient solrClient = getHttpSolrClient(baseUrl);
+ final SolrClient solrClient = solrCluster.getJettySolrRunners().get(0).newSolrClient(null);
threads[i] =
new CreateDeleteSearchCollectionThread(
"create-delete-search-" + i,
@@ -89,13 +88,12 @@ public class ConcurrentDeleteAndCreateCollectionTest extends SolrTestCaseJ4 {
final String configName = "testconfig";
// upload config once, to be used by all collections
solrCluster.uploadConfigSet(configset("configset-2"), configName);
- final String baseUrl = solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString();
final AtomicReference<Exception> failure = new AtomicReference<>();
final int timeToRunSec = 30;
final CreateDeleteCollectionThread[] threads = new CreateDeleteCollectionThread[2];
for (int i = 0; i < threads.length; i++) {
final String collectionName = "collection" + i;
- final SolrClient solrClient = getHttpSolrClient(baseUrl);
+ final SolrClient solrClient = solrCluster.getJettySolrRunners().get(0).newSolrClient(null);
threads[i] =
new CreateDeleteCollectionThread(
"create-delete-" + i, collectionName, configName, timeToRunSec, solrClient, failure);
diff --git a/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java b/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java
index 074d0431342..a366a849a42 100644
--- a/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java
@@ -43,6 +43,7 @@ import org.apache.solr.client.solrj.SolrRequest.METHOD;
import org.apache.solr.client.solrj.SolrRequest.SolrRequestType;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.CollectionScopedSolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.GenericSolrRequest;
import org.apache.solr.client.solrj.request.SolrQuery;
@@ -966,52 +967,52 @@ public class ShardSplitTest extends BasicDistributedZkTest {
getCommonCloudSolrClient();
String baseUrl = getBaseUrlFromZk(cloudClient.getClusterState(), collectionName);
- try (SolrClient collectionClient = getHttpSolrClient(baseUrl, collectionName)) {
+ SolrClient collectionClient =
+ new CollectionScopedSolrClient(getJetty(baseUrl).getSolrClient(), collectionName);
- ClusterState clusterState = cloudClient.getClusterState();
- final DocRouter router = clusterState.getCollection(collectionName).getRouter();
- Slice shard1 = clusterState.getCollection(collectionName).getSlice(SHARD1);
- DocRouter.Range shard1Range =
- shard1.getRange() != null ? shard1.getRange() : router.fullRange();
- final List<DocRouter.Range> ranges = router.partitionRange(2, shard1Range);
- final int[] docCounts = new int[ranges.size()];
+ ClusterState clusterState = cloudClient.getClusterState();
+ final DocRouter router = clusterState.getCollection(collectionName).getRouter();
+ Slice shard1 = clusterState.getCollection(collectionName).getSlice(SHARD1);
+ DocRouter.Range shard1Range =
+ shard1.getRange() != null ? shard1.getRange() : router.fullRange();
+ final List<DocRouter.Range> ranges = router.partitionRange(2, shard1Range);
+ final int[] docCounts = new int[ranges.size()];
- for (int i = 100; i <= 200; i++) {
- // See comment in ShardRoutingTest for hash distribution
- String shardKey = "" + (char) ('a' + (i % 26));
+ for (int i = 100; i <= 200; i++) {
+ // See comment in ShardRoutingTest for hash distribution
+ String shardKey = "" + (char) ('a' + (i % 26));
- collectionClient.add(getDoc(id, i, "n_ti", i, shard_fld, shardKey));
- int idx = getHashRangeIdx(router, ranges, shardKey);
- if (idx != -1) {
- docCounts[idx]++;
- }
+ collectionClient.add(getDoc(id, i, "n_ti", i, shard_fld, shardKey));
+ int idx = getHashRangeIdx(router, ranges, shardKey);
+ if (idx != -1) {
+ docCounts[idx]++;
}
+ }
- for (int i = 0; i < docCounts.length; i++) {
- int docCount = docCounts[i];
- log.info("Shard shard1_{} docCount = {}", i, docCount);
- }
+ for (int i = 0; i < docCounts.length; i++) {
+ int docCount = docCounts[i];
+ log.info("Shard shard1_{} docCount = {}", i, docCount);
+ }
- collectionClient.commit();
+ collectionClient.commit();
- trySplit(collectionName, null, SHARD1, 3);
+ trySplit(collectionName, null, SHARD1, 3);
- waitForRecoveriesToFinish(collectionName, false);
+ waitForRecoveriesToFinish(collectionName, false);
- assertEquals(
- docCounts[0],
- collectionClient
- .query(new SolrQuery("*:*").setParam("shards", "shard1_0"))
- .getResults()
- .getNumFound());
- assertEquals(
- docCounts[1],
- collectionClient
- .query(new SolrQuery("*:*").setParam("shards", "shard1_1"))
- .getResults()
- .getNumFound());
- assertEquals(101, collectionClient.query(new SolrQuery("*:*")).getResults().getNumFound());
- }
+ assertEquals(
+ docCounts[0],
+ collectionClient
+ .query(new SolrQuery("*:*").setParam("shards", "shard1_0"))
+ .getResults()
+ .getNumFound());
+ assertEquals(
+ docCounts[1],
+ collectionClient
+ .query(new SolrQuery("*:*").setParam("shards", "shard1_1"))
+ .getResults()
+ .getNumFound());
+ assertEquals(101, collectionClient.query(new SolrQuery("*:*")).getResults().getNumFound());
}
public void splitByNumericRouteFieldTest() throws Exception {
@@ -1043,43 +1044,44 @@ public class ShardSplitTest extends BasicDistributedZkTest {
getCommonCloudSolrClient();
String baseUrl = getBaseUrlFromZk(cloudClient.getClusterState(), collectionName);
- try (SolrClient collectionClient = getHttpSolrClient(baseUrl, collectionName)) {
- ClusterState clusterState = cloudClient.getClusterState();
- final DocRouter router = clusterState.getCollection(collectionName).getRouter();
- Slice shard1 = clusterState.getCollection(collectionName).getSlice(SHARD1);
- DocRouter.Range shard1Range =
- shard1.getRange() != null ? shard1.getRange() : router.fullRange();
- final List<DocRouter.Range> ranges = router.partitionRange(2, shard1Range);
- final int[] docCounts = new int[ranges.size()];
-
- for (int i = 100; i <= 200; i++) {
- collectionClient.add(getDoc(id, i, "n_ti", i, shardField, i));
- int idx = getHashRangeIdx(router, ranges, Integer.toString(i));
- if (idx != -1) {
- docCounts[idx]++;
- }
+ SolrClient collectionClient =
+ new CollectionScopedSolrClient(getJetty(baseUrl).getSolrClient(), collectionName);
+
+ ClusterState clusterState = cloudClient.getClusterState();
+ final DocRouter router = clusterState.getCollection(collectionName).getRouter();
+ Slice shard1 = clusterState.getCollection(collectionName).getSlice(SHARD1);
+ DocRouter.Range shard1Range =
+ shard1.getRange() != null ? shard1.getRange() : router.fullRange();
+ final List<DocRouter.Range> ranges = router.partitionRange(2, shard1Range);
+ final int[] docCounts = new int[ranges.size()];
+
+ for (int i = 100; i <= 200; i++) {
+ collectionClient.add(getDoc(id, i, "n_ti", i, shardField, i));
+ int idx = getHashRangeIdx(router, ranges, Integer.toString(i));
+ if (idx != -1) {
+ docCounts[idx]++;
}
+ }
- collectionClient.commit();
+ collectionClient.commit();
- trySplit(collectionName, null, SHARD1, 3);
+ trySplit(collectionName, null, SHARD1, 3);
- waitForRecoveriesToFinish(collectionName, false);
+ waitForRecoveriesToFinish(collectionName, false);
- assertEquals(
- docCounts[0],
- collectionClient
- .query(new SolrQuery("*:*").setParam("shards", "shard1_0"))
- .getResults()
- .getNumFound());
- assertEquals(
- docCounts[1],
- collectionClient
- .query(new SolrQuery("*:*").setParam("shards", "shard1_1"))
- .getResults()
- .getNumFound());
- assertEquals(101, collectionClient.query(new SolrQuery("*:*")).getResults().getNumFound());
- }
+ assertEquals(
+ docCounts[0],
+ collectionClient
+ .query(new SolrQuery("*:*").setParam("shards", "shard1_0"))
+ .getResults()
+ .getNumFound());
+ assertEquals(
+ docCounts[1],
+ collectionClient
+ .query(new SolrQuery("*:*").setParam("shards", "shard1_1"))
+ .getResults()
+ .getNumFound());
+ assertEquals(101, collectionClient.query(new SolrQuery("*:*")).getResults().getNumFound());
}
private void splitByRouteKeyTest() throws Exception {
@@ -1106,92 +1108,92 @@ public class ShardSplitTest extends BasicDistributedZkTest {
getCommonCloudSolrClient();
String baseUrl = getBaseUrlFromZk(cloudClient.getClusterState(), collectionName);
- try (SolrClient collectionClient = getHttpSolrClient(baseUrl, collectionName)) {
-
- String splitKey = "b!";
-
- ClusterState clusterState = cloudClient.getClusterState();
- final DocRouter router = clusterState.getCollection(collectionName).getRouter();
- Slice shard1 = clusterState.getCollection(collectionName).getSlice(SHARD1);
- DocRouter.Range shard1Range =
- shard1.getRange() != null ? shard1.getRange() : router.fullRange();
- final List<DocRouter.Range> ranges =
- ((CompositeIdRouter) router).partitionRangeByKey(splitKey, shard1Range);
- final int[] docCounts = new int[ranges.size()];
-
- int uniqIdentifier = (1 << 12);
- int splitKeyDocCount = 0;
- for (int i = 100; i <= 200; i++) {
- // See comment in ShardRoutingTest for hash distribution
- String shardKey = "" + (char) ('a' + (i % 26));
-
- String idStr = shardKey + "!" + i;
- collectionClient.add(
- getDoc(id, idStr, "n_ti", (shardKey + "!").equals(splitKey) ? uniqIdentifier : i));
- int idx = getHashRangeIdx(router, ranges, idStr);
- if (idx != -1) {
- docCounts[idx]++;
- }
- if (splitKey.equals(shardKey + "!")) splitKeyDocCount++;
- }
+ SolrClient collectionClient =
+ new CollectionScopedSolrClient(getJetty(baseUrl).getSolrClient(), collectionName);
- for (int i = 0; i < docCounts.length; i++) {
- int docCount = docCounts[i];
- log.info("Shard shard1_{} docCount = {}", i, docCount);
- }
- log.info("Route key doc count = {}", splitKeyDocCount);
+ String splitKey = "b!";
- collectionClient.commit();
+ ClusterState clusterState = cloudClient.getClusterState();
+ final DocRouter router = clusterState.getCollection(collectionName).getRouter();
+ Slice shard1 = clusterState.getCollection(collectionName).getSlice(SHARD1);
+ DocRouter.Range shard1Range =
+ shard1.getRange() != null ? shard1.getRange() : router.fullRange();
+ final List<DocRouter.Range> ranges =
+ ((CompositeIdRouter) router).partitionRangeByKey(splitKey, shard1Range);
+ final int[] docCounts = new int[ranges.size()];
- trySplit(collectionName, splitKey, null, 3);
+ int uniqIdentifier = (1 << 12);
+ int splitKeyDocCount = 0;
+ for (int i = 100; i <= 200; i++) {
+ // See comment in ShardRoutingTest for hash distribution
+ String shardKey = "" + (char) ('a' + (i % 26));
+
+ String idStr = shardKey + "!" + i;
+ collectionClient.add(
+ getDoc(id, idStr, "n_ti", (shardKey + "!").equals(splitKey) ? uniqIdentifier : i));
+ int idx = getHashRangeIdx(router, ranges, idStr);
+ if (idx != -1) {
+ docCounts[idx]++;
+ }
+ if (splitKey.equals(shardKey + "!")) splitKeyDocCount++;
+ }
- waitForRecoveriesToFinish(collectionName, false);
- SolrQuery solrQuery = new SolrQuery("*:*");
- assertEquals(
- "DocCount on shard1_0 does not match",
- docCounts[0],
- collectionClient
- .query(solrQuery.setParam("shards", "shard1_0"))
- .getResults()
- .getNumFound());
- assertEquals(
- "DocCount on shard1_1 does not match",
- docCounts[1],
- collectionClient
- .query(solrQuery.setParam("shards", "shard1_1"))
- .getResults()
- .getNumFound());
- assertEquals(
- "DocCount on shard1_2 does not match",
- docCounts[2],
- collectionClient
- .query(solrQuery.setParam("shards", "shard1_2"))
- .getResults()
- .getNumFound());
-
- solrQuery = new SolrQuery("n_ti:" + uniqIdentifier);
- assertEquals(
- "shard1_0 must have 0 docs for route key: " + splitKey,
- 0,
- collectionClient
- .query(solrQuery.setParam("shards", "shard1_0"))
- .getResults()
- .getNumFound());
- assertEquals(
- "Wrong number of docs on shard1_1 for route key: " + splitKey,
- splitKeyDocCount,
- collectionClient
- .query(solrQuery.setParam("shards", "shard1_1"))
- .getResults()
- .getNumFound());
- assertEquals(
- "shard1_2 must have 0 docs for route key: " + splitKey,
- 0,
- collectionClient
- .query(solrQuery.setParam("shards", "shard1_2"))
- .getResults()
- .getNumFound());
+ for (int i = 0; i < docCounts.length; i++) {
+ int docCount = docCounts[i];
+ log.info("Shard shard1_{} docCount = {}", i, docCount);
}
+ log.info("Route key doc count = {}", splitKeyDocCount);
+
+ collectionClient.commit();
+
+ trySplit(collectionName, splitKey, null, 3);
+
+ waitForRecoveriesToFinish(collectionName, false);
+ SolrQuery solrQuery = new SolrQuery("*:*");
+ assertEquals(
+ "DocCount on shard1_0 does not match",
+ docCounts[0],
+ collectionClient
+ .query(solrQuery.setParam("shards", "shard1_0"))
+ .getResults()
+ .getNumFound());
+ assertEquals(
+ "DocCount on shard1_1 does not match",
+ docCounts[1],
+ collectionClient
+ .query(solrQuery.setParam("shards", "shard1_1"))
+ .getResults()
+ .getNumFound());
+ assertEquals(
+ "DocCount on shard1_2 does not match",
+ docCounts[2],
+ collectionClient
+ .query(solrQuery.setParam("shards", "shard1_2"))
+ .getResults()
+ .getNumFound());
+
+ solrQuery = new SolrQuery("n_ti:" + uniqIdentifier);
+ assertEquals(
+ "shard1_0 must have 0 docs for route key: " + splitKey,
+ 0,
+ collectionClient
+ .query(solrQuery.setParam("shards", "shard1_0"))
+ .getResults()
+ .getNumFound());
+ assertEquals(
+ "Wrong number of docs on shard1_1 for route key: " + splitKey,
+ splitKeyDocCount,
+ collectionClient
+ .query(solrQuery.setParam("shards", "shard1_1"))
+ .getResults()
+ .getNumFound());
+ assertEquals(
+ "shard1_2 must have 0 docs for route key: " + splitKey,
+ 0,
+ collectionClient
+ .query(solrQuery.setParam("shards", "shard1_2"))
+ .getResults()
+ .getNumFound());
}
private void trySplit(String collectionName, String splitKey, String shardId, int maxTries)
@@ -1260,18 +1262,16 @@ public class ShardSplitTest extends BasicDistributedZkTest {
Replica shard1_0 = getLeaderFromZk(AbstractFullDistribZkTestBase.DEFAULT_COLLECTION, SHARD1_0);
QueryResponse response;
- try (SolrClient shard1_0Client =
- getHttpSolrClient(shard1_0.getBaseUrl(), shard1_0.getCoreName())) {
- response = shard1_0Client.query(query);
- }
+ SolrClient shard1_0Client = getSolrClient(shard1_0);
+ response = shard1_0Client.query(query);
+
long shard10Count = response.getResults().getNumFound();
Replica shard1_1 = getLeaderFromZk(AbstractFullDistribZkTestBase.DEFAULT_COLLECTION, SHARD1_1);
QueryResponse response2;
- try (SolrClient shard1_1Client =
- getHttpSolrClient(shard1_1.getBaseUrl(), shard1_1.getCoreName())) {
- response2 = shard1_1Client.query(query);
- }
+ SolrClient shard1_1Client = getSolrClient(shard1_1);
+ response2 = shard1_1Client.query(query);
+
long shard11Count = response2.getResults().getNumFound();
logDebugHelp(docCounts, response, shard10Count, response2, shard11Count, documentIds);
@@ -1294,9 +1294,9 @@ public class ShardSplitTest extends BasicDistributedZkTest {
for (Replica replica : slice.getReplicas()) {
String coreUrl = replica.getCoreUrl();
QueryResponse response;
- try (SolrClient client = getHttpSolrClient(replica)) {
- response = client.query(query);
- }
+ SolrClient client = getSolrClient(replica);
+ response = client.query(query);
+
numFound[c++] = response.getResults().getNumFound();
if (log.isInfoEnabled()) {
log.info(
@@ -1345,11 +1345,9 @@ public class ShardSplitTest extends BasicDistributedZkTest {
new GenericSolrRequest(METHOD.POST, "/admin/collections", SolrRequestType.ADMIN, params);
JettySolrRunner jetty = shardToJetty.get(SHARD1).getFirst().jetty;
- try (SolrClient baseServer = jetty.newClient(30_000, 300_000)) {
- NamedList<Object> rsp = baseServer.request(request);
- if (log.isInfoEnabled()) {
- log.info("Shard split response: {}", Utils.toJSONString(rsp));
- }
+ NamedList<Object> rsp = jetty.getSolrClient().request(request);
+ if (log.isInfoEnabled()) {
+ log.info("Shard split response: {}", Utils.toJSONString(rsp));
}
}
diff --git a/solr/core/src/test/org/apache/solr/core/TestCustomStream.java b/solr/core/src/test/org/apache/solr/core/TestCustomStream.java
index 73c8afc93de..e167c798aad 100644
--- a/solr/core/src/test/org/apache/solr/core/TestCustomStream.java
+++ b/solr/core/src/test/org/apache/solr/core/TestCustomStream.java
@@ -18,21 +18,30 @@
package org.apache.solr.core;
import java.util.Arrays;
-import org.apache.solr.cloud.AbstractFullDistribZkTestBase;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.cloud.SolrCloudTestCase;
import org.apache.solr.util.RestTestHarness;
+import org.junit.BeforeClass;
import org.junit.Test;
-public class TestCustomStream extends AbstractFullDistribZkTestBase {
+public class TestCustomStream extends SolrCloudTestCase {
+
+ @BeforeClass
+ public static void setupCluster() throws Exception {
+ configureCluster(2).addConfig("conf1", configset("cloud-minimal")).configure();
+ CollectionAdminRequest.createCollection("collection1", "conf1", 1, 2)
+ .process(cluster.getSolrClient());
+ cluster.waitForActiveCollection("collection1", 1, 2);
+ }
@Test
public void testDynamicLoadingCustomStream() throws Exception {
- setupRestTestHarnesses();
String payload =
"{\n"
+ "'create-expressible' : { 'name' : 'hello', 'class': 'org.apache.solr.core.HelloStream' }\n"
+ "}";
- RestTestHarness client = randomRestTestHarness();
+ RestTestHarness client = cluster.getRandomJetty(random()).getRestClient("collection1");
TestSolrConfigHandler.runConfigCommand(client, "/config", payload);
TestSolrConfigHandler.testForResponseElement(
client,
diff --git a/solr/core/src/test/org/apache/solr/core/snapshots/TestSolrCloudSnapshots.java b/solr/core/src/test/org/apache/solr/core/snapshots/TestSolrCloudSnapshots.java
index 6fa70f020e6..6ead68205f9 100644
--- a/solr/core/src/test/org/apache/solr/core/snapshots/TestSolrCloudSnapshots.java
+++ b/solr/core/src/test/org/apache/solr/core/snapshots/TestSolrCloudSnapshots.java
@@ -151,20 +151,18 @@ public class TestSolrCloudSnapshots extends SolrCloudTestCase {
continue; // We know that the snapshot is not created for this replica.
}
- String replicaBaseUrl = replica.getBaseUrl();
String coreName = replica.getCoreName();
assertTrue(snapshotByCoreName.containsKey(coreName));
CoreSnapshotMetaData coreSnapshot = snapshotByCoreName.get(coreName);
- try (SolrClient adminClient = getHttpSolrClient(replicaBaseUrl)) {
- Collection<SnapshotMetaData> snapshots = listCoreSnapshots(adminClient, coreName);
- Optional<SnapshotMetaData> metaData =
- snapshots.stream().filter(x -> commitName.equals(x.getName())).findFirst();
- assertTrue("Snapshot not created for core " + coreName, metaData.isPresent());
- assertEquals(coreSnapshot.getIndexDirPath(), metaData.get().getIndexDirPath());
- assertEquals(coreSnapshot.getGenerationNumber(), metaData.get().getGenerationNumber());
- }
+ SolrClient adminClient = cluster.getSolrClient(replica);
+ Collection<SnapshotMetaData> snapshots = listCoreSnapshots(adminClient, coreName);
+ Optional<SnapshotMetaData> metaData =
+ snapshots.stream().filter(x -> commitName.equals(x.getName())).findFirst();
+ assertTrue("Snapshot not created for core " + coreName, metaData.isPresent());
+ assertEquals(coreSnapshot.getIndexDirPath(), metaData.get().getIndexDirPath());
+ assertEquals(coreSnapshot.getGenerationNumber(), metaData.get().getGenerationNumber());
}
}
@@ -273,17 +271,15 @@ public class TestSolrCloudSnapshots extends SolrCloudTestCase {
continue; // We know that the snapshot was not created for this replica.
}
- String replicaBaseUrl = replica.getBaseUrl();
String coreName = replica.getCoreName();
- try (SolrClient adminClient = getHttpSolrClient(replicaBaseUrl)) {
- Collection<SnapshotMetaData> snapshots = listCoreSnapshots(adminClient, coreName);
- Optional<SnapshotMetaData> metaData =
- snapshots.stream().filter(x -> commitName.equals(x.getName())).findFirst();
- assertFalse("Snapshot not deleted for core " + coreName, metaData.isPresent());
- // Remove the entry for core if the snapshot is deleted successfully.
- snapshotByCoreName.remove(coreName);
- }
+ SolrClient adminClient = cluster.getSolrClient(replica);
+ Collection<SnapshotMetaData> snapshots = listCoreSnapshots(adminClient, coreName);
+ Optional<SnapshotMetaData> metaData =
+ snapshots.stream().filter(x -> commitName.equals(x.getName())).findFirst();
+ assertFalse("Snapshot not deleted for core " + coreName, metaData.isPresent());
+ // Remove the entry for core if the snapshot is deleted successfully.
+ snapshotByCoreName.remove(coreName);
}
}
diff --git a/solr/core/src/test/org/apache/solr/core/snapshots/TestSolrCoreSnapshots.java b/solr/core/src/test/org/apache/solr/core/snapshots/TestSolrCoreSnapshots.java
index 431a43a2fb7..b251c5b3dcd 100644
--- a/solr/core/src/test/org/apache/solr/core/snapshots/TestSolrCoreSnapshots.java
+++ b/solr/core/src/test/org/apache/solr/core/snapshots/TestSolrCoreSnapshots.java
@@ -33,7 +33,6 @@ import org.apache.lucene.tests.util.TestUtil;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
-import org.apache.solr.client.solrj.jetty.HttpJettySolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.CoreAdminRequest.CreateSnapshot;
import org.apache.solr.client.solrj.request.CoreAdminRequest.DeleteSnapshot;
@@ -98,79 +97,73 @@ public class TestSolrCoreSnapshots extends SolrCloudTestCase {
String commitName = TestUtil.randomSimpleString(random(), 1, 5);
String duplicateName = commitName.concat("_duplicate");
- try (SolrClient adminClient =
- getHttpSolrClient(cluster.getJettySolrRunners().get(0).getBaseUrl().toString());
- SolrClient leaderClient =
- new HttpJettySolrClient.Builder(replica.getBaseUrl())
- .withDefaultCollection(replica.getCoreName())
- .build()) {
-
- SnapshotMetaData metaData = createSnapshot(adminClient, coreName, commitName);
- // Create another snapshot referring to the same index commit to verify the
- // reference counting implementation during snapshot deletion.
- SnapshotMetaData duplicateCommit = createSnapshot(adminClient, coreName, duplicateName);
-
- assertEquals(metaData.getIndexDirPath(), duplicateCommit.getIndexDirPath());
- assertEquals(metaData.getGenerationNumber(), duplicateCommit.getGenerationNumber());
-
- // Delete all documents
- leaderClient.deleteByQuery("*:*");
- leaderClient.commit();
- BackupRestoreUtils.verifyDocs(0, cluster.getSolrClient(), collectionName);
-
- // Verify that the index directory contains at least 2 index commits - one referred by the
- // snapshots and the other containing document deletions.
- {
- List<IndexCommit> commits = listCommits(metaData.getIndexDirPath());
- assertTrue(commits.size() >= 2);
- }
+ SolrClient adminClient = cluster.getJettySolrRunners().get(0).getSolrClient();
+ SolrClient leaderClient = cluster.getSolrClient(replica);
+ SnapshotMetaData metaData = createSnapshot(adminClient, coreName, commitName);
+ // Create another snapshot referring to the same index commit to verify the
+ // reference counting implementation during snapshot deletion.
+ SnapshotMetaData duplicateCommit = createSnapshot(adminClient, coreName, duplicateName);
+
+ assertEquals(metaData.getIndexDirPath(), duplicateCommit.getIndexDirPath());
+ assertEquals(metaData.getGenerationNumber(), duplicateCommit.getGenerationNumber());
+
+ // Delete all documents
+ leaderClient.deleteByQuery("*:*");
+ leaderClient.commit();
+ BackupRestoreUtils.verifyDocs(0, cluster.getSolrClient(), collectionName);
+
+ // Verify that the index directory contains at least 2 index commits - one referred by the
+ // snapshots and the other containing document deletions.
+ {
+ List<IndexCommit> commits = listCommits(metaData.getIndexDirPath());
+ assertTrue(commits.size() >= 2);
+ }
- // Backup the earlier created snapshot.
- {
- Map<String, String> params = new HashMap<>();
- params.put("name", backupName);
- params.put("commitName", commitName);
- params.put("location", location);
- params.put("incremental", "false");
- BackupRestoreUtils.runCoreAdminCommand(
- replicaBaseUrl, coreName, CoreAdminAction.BACKUPCORE.toString(), params);
- }
+ // Backup the earlier created snapshot.
+ {
+ Map<String, String> params = new HashMap<>();
+ params.put("name", backupName);
+ params.put("commitName", commitName);
+ params.put("location", location);
+ params.put("incremental", "false");
+ BackupRestoreUtils.runCoreAdminCommand(
+ replicaBaseUrl, coreName, CoreAdminAction.BACKUPCORE.toString(), params);
+ }
- // Restore the backup
- {
- Map<String, String> params = new HashMap<>();
- params.put("name", "snapshot." + backupName);
- params.put("location", location);
- BackupRestoreUtils.runCoreAdminCommand(
- replicaBaseUrl, coreName, CoreAdminAction.RESTORECORE.toString(), params);
- BackupRestoreUtils.verifyDocs(nDocs, cluster.getSolrClient(), collectionName);
- }
+ // Restore the backup
+ {
+ Map<String, String> params = new HashMap<>();
+ params.put("name", "snapshot." + backupName);
+ params.put("location", location);
+ BackupRestoreUtils.runCoreAdminCommand(
+ replicaBaseUrl, coreName, CoreAdminAction.RESTORECORE.toString(), params);
+ BackupRestoreUtils.verifyDocs(nDocs, cluster.getSolrClient(), collectionName);
+ }
- // Verify that the old index directory (before restore) contains only those index commits
- // referred by snapshots. The IndexWriter (used to clean up index files) creates an additional
- // commit during closing. Hence, we expect 2 commits (instead of 1).
- {
- List<IndexCommit> commits = listCommits(metaData.getIndexDirPath());
- assertEquals(2, commits.size());
- assertEquals(metaData.getGenerationNumber(), commits.get(0).getGeneration());
- }
+ // Verify that the old index directory (before restore) contains only those index commits
+ // referred by snapshots. The IndexWriter (used to clean up index files) creates an additional
+ // commit during closing. Hence, we expect 2 commits (instead of 1).
+ {
+ List<IndexCommit> commits = listCommits(metaData.getIndexDirPath());
+ assertEquals(2, commits.size());
+ assertEquals(metaData.getGenerationNumber(), commits.get(0).getGeneration());
+ }
- // Delete first snapshot
- deleteSnapshot(adminClient, coreName, commitName);
+ // Delete first snapshot
+ deleteSnapshot(adminClient, coreName, commitName);
- // Verify that corresponding index files have NOT been deleted (due to reference counting).
- assertFalse(listCommits(metaData.getIndexDirPath()).isEmpty());
+ // Verify that corresponding index files have NOT been deleted (due to reference counting).
+ assertFalse(listCommits(metaData.getIndexDirPath()).isEmpty());
- // Delete second snapshot
- deleteSnapshot(adminClient, coreName, duplicateCommit.getName());
+ // Delete second snapshot
+ deleteSnapshot(adminClient, coreName, duplicateCommit.getName());
- // Verify that corresponding index files have been deleted. Ideally this directory should
- // be removed immediately. But the current DirectoryFactory impl waits until the
- // closing the core (or the directoryFactory) for actual removal. Since the IndexWriter
- // (used to clean up index files) creates an additional commit during closing, we expect a
- // single commit (instead of 0).
- assertEquals(1, listCommits(duplicateCommit.getIndexDirPath()).size());
- }
+ // Verify that corresponding index files have been deleted. Ideally this directory should
+ // be removed immediately. But the current DirectoryFactory impl waits until the
+ // closing the core (or the directoryFactory) for actual removal. Since the IndexWriter
+ // (used to clean up index files) creates an additional commit during closing, we expect a
+ // single commit (instead of 0).
+ assertEquals(1, listCommits(duplicateCommit.getIndexDirPath()).size());
}
@Test
@@ -192,72 +185,20 @@ public class TestSolrCoreSnapshots extends SolrCloudTestCase {
String coreName = replica.getStr(ZkStateReader.CORE_NAME_PROP);
String commitName = TestUtil.randomSimpleString(random(), 1, 5);
- try (SolrClient adminClient =
- getHttpSolrClient(cluster.getJettySolrRunners().get(0).getBaseUrl().toString());
- SolrClient leaderClient =
- new HttpJettySolrClient.Builder(replica.getBaseUrl())
- .withDefaultCollection(replica.getCoreName())
- .build()) {
-
- SnapshotMetaData metaData = createSnapshot(adminClient, coreName, commitName);
-
- int numTests = nDocs > 0 ? TestUtil.nextInt(random(), 1, 5) : 1;
- for (int attempt = 0; attempt < numTests; attempt++) {
- // Modify existing index before we call optimize.
- if (nDocs > 0) {
- // Delete a few docs
- int numDeletes = TestUtil.nextInt(random(), 1, nDocs);
- for (int i = 0; i < numDeletes; i++) {
- leaderClient.deleteByQuery("id:" + i);
- }
- // Add a few more
- int moreAdds = TestUtil.nextInt(random(), 1, 100);
- for (int i = 0; i < moreAdds; i++) {
- SolrInputDocument doc = new SolrInputDocument();
- doc.addField("id", i + nDocs);
- doc.addField("name", "name = " + (i + nDocs));
- leaderClient.add(doc);
- }
- leaderClient.commit();
+ SolrClient adminClient = cluster.getJettySolrRunners().get(0).getSolrClient();
+ SolrClient leaderClient = cluster.getSolrClient(replica);
+ SnapshotMetaData metaData = createSnapshot(adminClient, coreName, commitName);
+
+ int numTests = nDocs > 0 ? TestUtil.nextInt(random(), 1, 5) : 1;
+ for (int attempt = 0; attempt < numTests; attempt++) {
+ // Modify existing index before we call optimize.
+ if (nDocs > 0) {
+ // Delete a few docs
+ int numDeletes = TestUtil.nextInt(random(), 1, nDocs);
+ for (int i = 0; i < numDeletes; i++) {
+ leaderClient.deleteByQuery("id:" + i);
}
- }
-
- // Before invoking optimize command, verify that the index directory contains multiple commits
- // (including the one we snapshotted earlier).
- {
- Collection<IndexCommit> commits = listCommits(metaData.getIndexDirPath());
- // Verify that multiple index commits are stored in this directory.
- assertTrue(commits.size() > 0);
- // Verify that the snapshot commit is present in this directory.
- assertTrue(
- commits.stream()
- .filter(x -> x.getGeneration() == metaData.getGenerationNumber())
- .findFirst()
- .isPresent());
- }
-
- // Optimize the index.
- leaderClient.optimize(true, true, 1);
-
- // After invoking optimize command, verify that the index directory contains multiple commits
- // (including the one we snapshotted earlier).
- {
- List<IndexCommit> commits = listCommits(metaData.getIndexDirPath());
- // Verify that multiple index commits are stored in this directory.
- assertTrue(commits.size() > 1);
- // Verify that the snapshot commit is present in this directory.
- assertTrue(
- commits.stream()
- .filter(x -> x.getGeneration() == metaData.getGenerationNumber())
- .findFirst()
- .isPresent());
- }
-
- // Delete the snapshot
- deleteSnapshot(adminClient, coreName, metaData.getName());
-
- // Add few documents. Without this the optimize command below does not take effect.
- {
+ // Add a few more
int moreAdds = TestUtil.nextInt(random(), 1, 100);
for (int i = 0; i < moreAdds; i++) {
SolrInputDocument doc = new SolrInputDocument();
@@ -267,20 +208,66 @@ public class TestSolrCoreSnapshots extends SolrCloudTestCase {
}
leaderClient.commit();
}
+ }
- // Optimize the index.
- leaderClient.optimize(true, true, 1);
-
- // Verify that the index directory contains only 1 index commit (which is not the same as the
- // snapshotted commit).
+ // Before invoking optimize command, verify that the index directory contains multiple commits
+ // (including the one we snapshotted earlier).
+ {
Collection<IndexCommit> commits = listCommits(metaData.getIndexDirPath());
- assertEquals(1, commits.size());
- assertFalse(
+ // Verify that multiple index commits are stored in this directory.
+ assertTrue(commits.size() > 0);
+ // Verify that the snapshot commit is present in this directory.
+ assertTrue(
+ commits.stream()
+ .filter(x -> x.getGeneration() == metaData.getGenerationNumber())
+ .findFirst()
+ .isPresent());
+ }
+
+ // Optimize the index.
+ leaderClient.optimize(true, true, 1);
+
+ // After invoking optimize command, verify that the index directory contains multiple commits
+ // (including the one we snapshotted earlier).
+ {
+ List<IndexCommit> commits = listCommits(metaData.getIndexDirPath());
+ // Verify that multiple index commits are stored in this directory.
+ assertTrue(commits.size() > 1);
+ // Verify that the snapshot commit is present in this directory.
+ assertTrue(
commits.stream()
.filter(x -> x.getGeneration() == metaData.getGenerationNumber())
.findFirst()
.isPresent());
}
+
+ // Delete the snapshot
+ deleteSnapshot(adminClient, coreName, metaData.getName());
+
+ // Add few documents. Without this the optimize command below does not take effect.
+ {
+ int moreAdds = TestUtil.nextInt(random(), 1, 100);
+ for (int i = 0; i < moreAdds; i++) {
+ SolrInputDocument doc = new SolrInputDocument();
+ doc.addField("id", i + nDocs);
+ doc.addField("name", "name = " + (i + nDocs));
+ leaderClient.add(doc);
+ }
+ leaderClient.commit();
+ }
+
+ // Optimize the index.
+ leaderClient.optimize(true, true, 1);
+
+ // Verify that the index directory contains only 1 index commit (which is not the same as the
+ // snapshotted commit).
+ Collection<IndexCommit> commits = listCommits(metaData.getIndexDirPath());
+ assertEquals(1, commits.size());
+ assertFalse(
+ commits.stream()
+ .filter(x -> x.getGeneration() == metaData.getGenerationNumber())
+ .findFirst()
+ .isPresent());
}
private SnapshotMetaData createSnapshot(
diff --git a/solr/core/src/test/org/apache/solr/filestore/TestDistribFileStore.java b/solr/core/src/test/org/apache/solr/filestore/TestDistribFileStore.java
index 8e7b5ab80ed..133116e6908 100644
--- a/solr/core/src/test/org/apache/solr/filestore/TestDistribFileStore.java
+++ b/solr/core/src/test/org/apache/solr/filestore/TestDistribFileStore.java
@@ -173,18 +173,17 @@ public class TestDistribFileStore extends SolrCloudTestCase {
for (JettySolrRunner jettySolrRunner : cluster.getJettySolrRunners()) {
final var fetchReq = new FileStoreApi.FetchFile("/package/mypkg/v1.0/runtimelibs.jar2");
fetchReq.setGetFrom("someFakeSolrNode:8983_solr");
- try (final var solrClient = jettySolrRunner.newClient()) {
- final var expectedExc =
- expectThrows(
- RemoteSolrException.class,
- () -> {
- fetchReq.process(solrClient);
- });
- assertEquals(400, expectedExc.code());
- assertThat(
- expectedExc.getMessage(), containsString("File store cannot fetch from source node"));
- assertThat(expectedExc.getMessage(), containsString("does not appear in live-nodes"));
- }
+ final var solrClient = jettySolrRunner.getSolrClient();
+ final var expectedExc =
+ expectThrows(
+ RemoteSolrException.class,
+ () -> {
+ fetchReq.process(solrClient);
+ });
+ assertEquals(400, expectedExc.code());
+ assertThat(
+ expectedExc.getMessage(), containsString("File store cannot fetch from source node"));
+ assertThat(expectedExc.getMessage(), containsString("does not appear in live-nodes"));
}
// Delete Jars
diff --git a/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java b/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java
index cc719d054c4..b531dc113f0 100644
--- a/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java
+++ b/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java
@@ -239,14 +239,13 @@ public class TestReplicationHandler extends SolrTestCaseJ4 {
new GenericSolrRequest(
SolrRequest.METHOD.POST, "/admin/cores", SolrRequestType.ADMIN, params);
- try (SolrClient adminClient = adminClient(jettySolrRunner)) {
- NamedList<Object> res = adminClient.request(req);
- assertNotNull("null response from server", res);
- }
+ SolrClient adminClient = adminClient(jettySolrRunner);
+ NamedList<Object> res = adminClient.request(req);
+ assertNotNull("null response from server", res);
}
private SolrClient adminClient(JettySolrRunner client) {
- return getHttpSolrClient(client.getBaseUrl().toString());
+ return client.getSolrClient();
}
@Test
@@ -1721,33 +1720,32 @@ public class TestReplicationHandler extends SolrTestCaseJ4 {
final long sleepInterval = 200;
long timeSlept = 0;
- try (SolrClient adminClient = adminClient(jettySolrRunner)) {
- final var statusRequest = new CoresApi.GetCoreStatus("collection1");
- while (timeSlept < TIMEOUT) {
- try {
- final var statusResponse = statusRequest.process(adminClient);
- assertNotNull(statusResponse.status);
- assertTrue(statusResponse.status.containsKey("collection1"));
- final var coreStatus = statusResponse.status.get("collection1");
- Date startTime = coreStatus.startTime;
-
- assertNotNull("core has null startTime", startTime);
- if (null == min || startTime.after(min)) {
- return startTime;
- }
- } catch (SolrException e) {
- // workaround for SOLR-4668
- if (500 != e.code()) {
- throw e;
- } // else server possibly from the core reload in progress...
+ SolrClient adminClient = adminClient(jettySolrRunner);
+ final var statusRequest = new CoresApi.GetCoreStatus("collection1");
+ while (timeSlept < TIMEOUT) {
+ try {
+ final var statusResponse = statusRequest.process(adminClient);
+ assertNotNull(statusResponse.status);
+ assertTrue(statusResponse.status.containsKey("collection1"));
+ final var coreStatus = statusResponse.status.get("collection1");
+ Date startTime = coreStatus.startTime;
+
+ assertNotNull("core has null startTime", startTime);
+ if (null == min || startTime.after(min)) {
+ return startTime;
}
-
- timeSlept += sleepInterval;
- Thread.sleep(sleepInterval);
+ } catch (SolrException e) {
+ // workaround for SOLR-4668
+ if (500 != e.code()) {
+ throw e;
+ } // else server possibly from the core reload in progress...
}
- fail("timed out waiting for collection1 startAt time to exceed: " + min);
- return min; // compilation necessity
+
+ timeSlept += sleepInterval;
+ Thread.sleep(sleepInterval);
}
+ fail("timed out waiting for collection1 startAt time to exceed: " + min);
+ return min; // compilation necessity
}
@Test
diff --git a/solr/core/src/test/org/apache/solr/handler/TestStressIncrementalBackup.java b/solr/core/src/test/org/apache/solr/handler/TestStressIncrementalBackup.java
index 6305473b94e..54856313195 100644
--- a/solr/core/src/test/org/apache/solr/handler/TestStressIncrementalBackup.java
+++ b/solr/core/src/test/org/apache/solr/handler/TestStressIncrementalBackup.java
@@ -62,7 +62,7 @@ public class TestStressIncrementalBackup extends SolrCloudTestCase {
(CollectionAdminRequest.createCollection(DEFAULT_TEST_COLLECTION_NAME, "conf1", 1, 1)
.process(cluster.getSolrClient())
.getStatus()));
- adminClient = getHttpSolrClient(cluster.getJettySolrRunners().get(0).getBaseUrl().toString());
+ adminClient = cluster.getJettySolrRunners().get(0).getSolrClient();
initCoreNameAndSolrCoreClient();
}
@@ -80,20 +80,13 @@ public class TestStressIncrementalBackup extends SolrCloudTestCase {
.iterator()
.next();
coreName = r.getCoreName();
- coreClient = getHttpSolrClient(r);
+ coreClient = cluster.getSolrClient(r);
}
@After
public void afterTest() throws Exception {
// we use a clean cluster instance for every test, so we need to clean it up
shutdownCluster();
-
- if (null != adminClient) {
- adminClient.close();
- }
- if (null != coreClient) {
- coreClient.close();
- }
}
@SuppressWarnings("AssertionFailureIgnored") // failure happens inside a thread
diff --git a/solr/core/src/test/org/apache/solr/handler/TestStressThreadBackup.java b/solr/core/src/test/org/apache/solr/handler/TestStressThreadBackup.java
index 70db545fced..ea4d54c5c22 100644
--- a/solr/core/src/test/org/apache/solr/handler/TestStressThreadBackup.java
+++ b/solr/core/src/test/org/apache/solr/handler/TestStressThreadBackup.java
@@ -96,7 +96,7 @@ public class TestStressThreadBackup extends SolrCloudTestCase {
(CollectionAdminRequest.createCollection(DEFAULT_TEST_COLLECTION_NAME, "conf1", 1, 1)
.process(cluster.getSolrClient())
.getStatus()));
- adminClient = getHttpSolrClient(cluster.getJettySolrRunners().get(0).getBaseUrl().toString());
+ adminClient = cluster.getJettySolrRunners().get(0).getSolrClient();
initCoreNameAndSolrCoreClient();
}
@@ -104,13 +104,6 @@ public class TestStressThreadBackup extends SolrCloudTestCase {
public void afterTest() throws Exception {
// we use a clean cluster instance for every test, so we need to clean it up
shutdownCluster();
-
- if (null != adminClient) {
- adminClient.close();
- }
- if (null != coreClient) {
- coreClient.close();
- }
}
@Test
@@ -371,7 +364,7 @@ public class TestStressThreadBackup extends SolrCloudTestCase {
.iterator()
.next();
coreName = r.getCoreName();
- coreClient = getHttpSolrClient(r);
+ coreClient = cluster.getSolrClient(r);
}
/**
diff --git a/solr/core/src/test/org/apache/solr/handler/V2StandaloneTest.java b/solr/core/src/test/org/apache/solr/handler/V2StandaloneTest.java
index aa76092cf5d..5d6184ce0f0 100644
--- a/solr/core/src/test/org/apache/solr/handler/V2StandaloneTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/V2StandaloneTest.java
@@ -39,15 +39,14 @@ public class V2StandaloneTest extends SolrTestCaseJ4 {
new JettySolrRunner(solrHomeTmp.toString(), JettyConfig.builder().build());
jetty.start();
- try (SolrClient client = getHttpSolrClient(buildUrl(jetty.getLocalPort()))) {
- NamedList<?> res = client.request(new V2Request.Builder("/").build());
- NamedList<?> header = (NamedList<?>) res.get("responseHeader");
- assertEquals(0, header.get("status"));
-
- res = client.request(new V2Request.Builder("/_introspect").build());
- header = (NamedList<?>) res.get("responseHeader");
- assertEquals(0, header.get("status"));
- }
+ SolrClient client = jetty.getSolrClient();
+ NamedList<?> res = client.request(new V2Request.Builder("/").build());
+ NamedList<?> header = (NamedList<?>) res.get("responseHeader");
+ assertEquals(0, header.get("status"));
+
+ res = client.request(new V2Request.Builder("/_introspect").build());
+ header = (NamedList<?>) res.get("responseHeader");
+ assertEquals(0, header.get("status"));
jetty.stop();
}
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/CoreAdminHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/CoreAdminHandlerTest.java
index 0c85bbee765..e3b3a1084f0 100644
--- a/solr/core/src/test/org/apache/solr/handler/admin/CoreAdminHandlerTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/admin/CoreAdminHandlerTest.java
@@ -419,12 +419,11 @@ public class CoreAdminHandlerTest extends SolrTestCaseJ4 {
runner.getSolrClient().commit("corex");
Path dataDir = null;
- try (SolrClient client = getHttpSolrClient(runner.getBaseUrl().toString())) {
- final var status = CoreAdminRequest.getCoreStatus("corex", true, client);
- String dataDirectory = status.dataDir;
- dataDir = Path.of(dataDirectory);
- assertTrue(Files.exists(dataDir));
- }
+ SolrClient client = runner.getSolrClient();
+ final var status = CoreAdminRequest.getCoreStatus("corex", true, client);
+ String dataDirectory = status.dataDir;
+ dataDir = Path.of(dataDirectory);
+ assertTrue(Files.exists(dataDir));
Path subHome = solrHomeDirectory.resolve("corex").resolve("conf");
Path top = SolrTestCaseJ4.TEST_HOME().resolve("collection1").resolve("conf");
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/HealthCheckHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/HealthCheckHandlerTest.java
index 96cb2f4c425..4fadec44fef 100644
--- a/solr/core/src/test/org/apache/solr/handler/admin/HealthCheckHandlerTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/admin/HealthCheckHandlerTest.java
@@ -74,14 +74,13 @@ public class HealthCheckHandlerTest extends SolrCloudTestCase {
genericHealthcheck.process(cluster.getSolrClient()).getResponse().get(CommonParams.STATUS));
// positive check that our exiting "healthy" node works with direct http client
- try (SolrClient solrClient =
- getHttpSolrClient(cluster.getJettySolrRunner(0).getBaseUrl().toString())) {
- assertEquals(CommonParams.OK, runHealthcheckWithClient(solrClient).getNodeStatus());
- }
+ assertEquals(
+ CommonParams.OK,
+ runHealthcheckWithClient(cluster.getJettySolrRunner(0).getSolrClient()).getNodeStatus());
// successfully create a dummy collection
- try (SolrClient solrClient =
- getHttpSolrClient(cluster.getJettySolrRunner(0).getBaseUrl().toString())) {
+ try {
+ SolrClient solrClient = cluster.getJettySolrRunner(0).getSolrClient();
CollectionAdminResponse collectionAdminResponse =
CollectionAdminRequest.createCollection("test", "_default", 1, 1)
.withProperty("solr.directoryFactory", "solr.StandardDirectoryFactory")
@@ -95,7 +94,8 @@ public class HealthCheckHandlerTest extends SolrCloudTestCase {
// add a new node for the purpose of negative testing
JettySolrRunner newJetty = cluster.startJettySolrRunner();
- try (SolrClient solrClient = getHttpSolrClient(newJetty.getBaseUrl().toString())) {
+ try {
+ SolrClient solrClient = newJetty.getSolrClient();
// positive check that our (new) "healthy" node works with direct http client
final var response = runHealthcheckWithClient(solrClient);
@@ -115,22 +115,17 @@ public class HealthCheckHandlerTest extends SolrCloudTestCase {
// (redundant) positive check that our (previously) exiting "healthy" node (still) works
// after getting negative results from our broken node and failed core container
- try (SolrClient solrClient =
- getHttpSolrClient(cluster.getJettySolrRunner(0).getBaseUrl().toString())) {
-
- assertEquals(CommonParams.OK, runHealthcheckWithClient(solrClient).getNodeStatus());
- }
+ assertEquals(
+ CommonParams.OK,
+ runHealthcheckWithClient(cluster.getJettySolrRunner(0).getSolrClient()).getNodeStatus());
}
@Test
public void testHealthCheckHandlerSolrJ() throws IOException, SolrServerException {
// positive check of a HealthCheckRequest using http client
HealthCheckRequest req = new HealthCheckRequest();
- try (SolrClient solrClient =
- getHttpSolrClient(cluster.getJettySolrRunner(0).getBaseUrl().toString())) {
- HealthCheckResponse rsp = req.process(solrClient);
- assertEquals(CommonParams.OK, rsp.getNodeStatus());
- }
+ HealthCheckResponse rsp = req.process(cluster.getJettySolrRunner(0).getSolrClient());
+ assertEquals(CommonParams.OK, rsp.getNodeStatus());
}
/**
@@ -148,9 +143,10 @@ public class HealthCheckHandlerTest extends SolrCloudTestCase {
@Test
public void testV1FailureResponseIncludesStatusField() throws Exception {
JettySolrRunner newJetty = cluster.startJettySolrRunner();
- try (SolrClient solrClient = getHttpSolrClient(newJetty.getBaseUrl().toString())) {
+ try {
// Sanity check: the new node is initially healthy.
- assertEquals(CommonParams.OK, runHealthcheckWithClient(solrClient).getNodeStatus());
+ assertEquals(
+ CommonParams.OK, runHealthcheckWithClient(newJetty.getSolrClient()).getNodeStatus());
String nodeName = newJetty.getCoreContainer().getZkController().getNodeName();
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/LukeHandlerCloudTest.java b/solr/core/src/test/org/apache/solr/handler/admin/LukeHandlerCloudTest.java
index c9ddbabe2bb..ed418d1621e 100644
--- a/solr/core/src/test/org/apache/solr/handler/admin/LukeHandlerCloudTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/admin/LukeHandlerCloudTest.java
@@ -137,13 +137,12 @@ public class LukeHandlerCloudTest extends SolrCloudTestCase {
String targetSliceName = null;
for (Slice slice : docColl.getSlices()) {
Replica leader = slice.getLeader();
- try (SolrClient client = getHttpSolrClient(leader)) {
- SolrQuery q = new SolrQuery("id:target");
- q.set(DISTRIB, "false");
- QueryResponse qr = client.query(q);
- if (qr.getResults().getNumFound() > 0) {
- targetSliceName = slice.getName();
- }
+ SolrClient client = cluster.getSolrClient(leader);
+ SolrQuery q = new SolrQuery("id:target");
+ q.set(DISTRIB, "false");
+ QueryResponse qr = client.query(q);
+ if (qr.getResults().getNumFound() > 0) {
+ targetSliceName = slice.getName();
}
}
assertNotNull("target doc should exist on a shard", targetSliceName);
@@ -153,14 +152,14 @@ public class LukeHandlerCloudTest extends SolrCloudTestCase {
for (Slice slice : docColl.getSlices()) {
if (!slice.getName().equals(targetSliceName)) {
Replica leader = slice.getLeader();
- try (SolrClient client = getHttpSolrClient(leader)) {
- SolrQuery q = new SolrQuery("*:*");
- q.setRows(1);
- q.set(DISTRIB, "false");
- QueryResponse qr = client.query(q);
- assertTrue("other shard should have seed docs", qr.getResults().getNumFound() > 0);
- otherDocId = (String) qr.getResults().getFirst().getFieldValue("id");
- }
+ SolrClient client = cluster.getSolrClient(leader);
+ SolrQuery q = new SolrQuery("*:*");
+ q.setRows(1);
+ q.set(DISTRIB, "false");
+ QueryResponse qr = client.query(q);
+ assertTrue("other shard should have seed docs", qr.getResults().getNumFound() > 0);
+ otherDocId = (String) qr.getResults().getFirst().getFieldValue("id");
+
break;
}
}
diff --git a/solr/core/src/test/org/apache/solr/handler/component/UpdateLogCloudTest.java b/solr/core/src/test/org/apache/solr/handler/component/UpdateLogCloudTest.java
index fcc0efde3ba..cf44fc09300 100644
--- a/solr/core/src/test/org/apache/solr/handler/component/UpdateLogCloudTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/component/UpdateLogCloudTest.java
@@ -22,6 +22,7 @@ import java.util.Deque;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.solr.client.solrj.SolrClient;
+import org.apache.solr.client.solrj.jetty.HttpJettySolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.QueryRequest;
import org.apache.solr.client.solrj.request.UpdateRequest;
@@ -90,7 +91,10 @@ public class UpdateLogCloudTest extends SolrCloudTestCase {
.equals(getCollectionState(COLLECTION).getLeader("shard1").getBaseUrl())) {
specialIdx = solrClients.size();
}
- solrClients.add(jettySolrRunner.newClient());
+ // own clients on purpose: this test stops and restarts a node, which the runner's
+ // cached client does not survive
+ solrClients.add(
+ new HttpJettySolrClient.Builder(jettySolrRunner.getBaseUrl().toString()).build());
}
new UpdateRequest()
diff --git a/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java b/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java
index ad9bcf5a479..78120c4ed55 100644
--- a/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java
+++ b/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java
@@ -123,31 +123,30 @@ public class SolrMetricsIntegrationTest extends SolrTestCaseJ4 {
reader, "solr_zk_ops", baseLabels.merge(Labels.of("ops", type))));
}
- try (SolrClient solrClient = j.newClient()) {
- assertNotNull(solrClient);
- HttpClient httpClient = j.getSolrClient().getHttpClient();
- var initialChildFetches =
- SolrMetricTestUtils.getCounterDatapoint(reader, "solr_zk_get_children_ops", baseLabels)
- .getValue();
- var initialExistsOp =
- SolrMetricTestUtils.getCounterDatapoint(
- reader, "solr_zk_ops", baseLabels.merge(Labels.of("ops", "exists")))
- .getValue();
+ SolrClient solrClient = j.getSolrClient();
+ assertNotNull(solrClient);
+ HttpClient httpClient = j.getSolrClient().getHttpClient();
+ var initialChildFetches =
+ SolrMetricTestUtils.getCounterDatapoint(reader, "solr_zk_get_children_ops", baseLabels)
+ .getValue();
+ var initialExistsOp =
+ SolrMetricTestUtils.getCounterDatapoint(
+ reader, "solr_zk_ops", baseLabels.merge(Labels.of("ops", "exists")))
+ .getValue();
- // Send GET request to trigger some metrics
- httpClient.GET(j.getBaseURLV2() + "/cluster/zookeeper/children/live_nodes");
+ // Send GET request to trigger some metrics
+ httpClient.GET(j.getBaseURLV2() + "/cluster/zookeeper/children/live_nodes");
- var childFetches =
- SolrMetricTestUtils.getCounterDatapoint(reader, "solr_zk_get_children_ops", baseLabels)
- .getValue();
- var existsOp =
- SolrMetricTestUtils.getCounterDatapoint(
- reader, "solr_zk_ops", builder.label("ops", "exists").build())
- .getValue();
+ var childFetches =
+ SolrMetricTestUtils.getCounterDatapoint(reader, "solr_zk_get_children_ops", baseLabels)
+ .getValue();
+ var existsOp =
+ SolrMetricTestUtils.getCounterDatapoint(
+ reader, "solr_zk_ops", builder.label("ops", "exists").build())
+ .getValue();
- assertTrue(childFetches - initialChildFetches >= 1.0);
- assertTrue(existsOp - initialExistsOp >= 4.0);
- }
+ assertTrue(childFetches - initialChildFetches >= 1.0);
+ assertTrue(existsOp - initialExistsOp >= 4.0);
cluster.shutdown();
}
diff --git a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java
index 610b7267cbe..3c6032df129 100644
--- a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java
+++ b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java
@@ -68,47 +68,46 @@ public class TestPrometheusResponseWriter extends SolrTestCaseJ4 {
params.set("wt", "prometheus");
var req = new MetricsRequest(params); // response parser set in MetricsRequest constructor
- try (SolrClient adminClient = getHttpSolrClient(solrTestRule.getBaseUrl())) {
- NamedList<Object> res = adminClient.request(req);
- String output = InputStreamResponseParser.consumeResponseToString(res);
-
- Set<String> seenTypeInfo = new HashSet<>();
-
- List<String> filteredResponse =
- output
- .lines()
- .filter(
- line -> {
- if (!line.startsWith("#")) {
- return true;
- }
- assertTrue(
- "Prometheus exposition format cannot have duplicate TYPE information",
- seenTypeInfo.add(line));
- return false;
- })
- .toList();
- filteredResponse.forEach(
- (actualMetric) -> {
- String actualValue;
- if (actualMetric.contains("}")) {
- actualValue = actualMetric.substring(actualMetric.lastIndexOf("} ") + 1);
- } else {
- actualValue = actualMetric.split(" ")[1];
- }
- if (actualMetric.startsWith("target_info")) {
- // Skip standard OTEL metric
- return;
- }
- assertTrue("All metrics should start with 'solr_'", actualMetric.startsWith("solr_"));
- try {
- Float.parseFloat(actualValue);
- } catch (NumberFormatException e) {
- log.warn("Prometheus value not a parsable float");
- assertTrue(VALID_PROMETHEUS_VALUES.contains(actualValue));
- }
- });
- }
+ SolrClient adminClient = solrTestRule.getAdminClient();
+ NamedList<Object> res = adminClient.request(req);
+ String output = InputStreamResponseParser.consumeResponseToString(res);
+
+ Set<String> seenTypeInfo = new HashSet<>();
+
+ List<String> filteredResponse =
+ output
+ .lines()
+ .filter(
+ line -> {
+ if (!line.startsWith("#")) {
+ return true;
+ }
+ assertTrue(
+ "Prometheus exposition format cannot have duplicate TYPE information",
+ seenTypeInfo.add(line));
+ return false;
+ })
+ .toList();
+ filteredResponse.forEach(
+ (actualMetric) -> {
+ String actualValue;
+ if (actualMetric.contains("}")) {
+ actualValue = actualMetric.substring(actualMetric.lastIndexOf("} ") + 1);
+ } else {
+ actualValue = actualMetric.split(" ")[1];
+ }
+ if (actualMetric.startsWith("target_info")) {
+ // Skip standard OTEL metric
+ return;
+ }
+ assertTrue("All metrics should start with 'solr_'", actualMetric.startsWith("solr_"));
+ try {
+ Float.parseFloat(actualValue);
+ } catch (NumberFormatException e) {
+ log.warn("Prometheus value not a parsable float");
+ assertTrue(VALID_PROMETHEUS_VALUES.contains(actualValue));
+ }
+ });
}
@Test
@@ -119,15 +118,14 @@ public class TestPrometheusResponseWriter extends SolrTestCaseJ4 {
req.addHeader("Accept", "application/openmetrics-text;version=1.0.0");
- try (SolrClient adminClient = getHttpSolrClient(solrTestRule.getBaseUrl())) {
- NamedList<Object> res = adminClient.request(req);
+ SolrClient adminClient = solrTestRule.getAdminClient();
+ NamedList<Object> res = adminClient.request(req);
- try (InputStream in = (InputStream) res.get(STREAM_KEY)) {
- String output = new String(in.readAllBytes(), StandardCharsets.UTF_8);
- assertTrue(
- "Should use OpenMetrics format when Accept header is set",
- output.trim().endsWith("# EOF"));
- }
+ try (InputStream in = (InputStream) res.get(STREAM_KEY)) {
+ String output = new String(in.readAllBytes(), StandardCharsets.UTF_8);
+ assertTrue(
+ "Should use OpenMetrics format when Accept header is set",
+ output.trim().endsWith("# EOF"));
}
}
@@ -137,15 +135,14 @@ public class TestPrometheusResponseWriter extends SolrTestCaseJ4 {
req.setResponseParser(new InputStreamResponseParser("openmetrics"));
- try (SolrClient adminClient = getHttpSolrClient(solrTestRule.getBaseUrl())) {
- NamedList<Object> res = adminClient.request(req);
+ SolrClient adminClient = solrTestRule.getAdminClient();
+ NamedList<Object> res = adminClient.request(req);
- try (InputStream in = (InputStream) res.get(STREAM_KEY)) {
- String output = new String(in.readAllBytes(), StandardCharsets.UTF_8);
- assertTrue(
- "Should use OpenMetrics format when wt=openmetrics is set",
- output.trim().endsWith("# EOF"));
- }
+ try (InputStream in = (InputStream) res.get(STREAM_KEY)) {
+ String output = new String(in.readAllBytes(), StandardCharsets.UTF_8);
+ assertTrue(
+ "Should use OpenMetrics format when wt=openmetrics is set",
+ output.trim().endsWith("# EOF"));
}
}
@@ -155,15 +152,14 @@ public class TestPrometheusResponseWriter extends SolrTestCaseJ4 {
req.setResponseParser(new InputStreamResponseParser("prometheus"));
- try (SolrClient adminClient = getHttpSolrClient(solrTestRule.getBaseUrl())) {
- NamedList<Object> res = adminClient.request(req);
+ SolrClient adminClient = solrTestRule.getAdminClient();
+ NamedList<Object> res = adminClient.request(req);
- try (InputStream in = (InputStream) res.get(STREAM_KEY)) {
- String output = new String(in.readAllBytes(), StandardCharsets.UTF_8);
- assertFalse(
- "Should use Prometheus format when wt=prometheus is set",
- output.trim().endsWith("# EOF"));
- }
+ try (InputStream in = (InputStream) res.get(STREAM_KEY)) {
+ String output = new String(in.readAllBytes(), StandardCharsets.UTF_8);
+ assertFalse(
+ "Should use Prometheus format when wt=prometheus is set",
+ output.trim().endsWith("# EOF"));
}
}
@@ -173,15 +169,14 @@ public class TestPrometheusResponseWriter extends SolrTestCaseJ4 {
req.setResponseParser(new InputStreamResponseParser(null));
- try (SolrClient adminClient = getHttpSolrClient(solrTestRule.getBaseUrl())) {
- NamedList<Object> res = adminClient.request(req);
+ SolrClient adminClient = solrTestRule.getAdminClient();
+ NamedList<Object> res = adminClient.request(req);
- try (InputStream in = (InputStream) res.get(STREAM_KEY)) {
- String output = new String(in.readAllBytes(), StandardCharsets.UTF_8);
- assertFalse(
- "Should default to Prometheus format when no wt parameter is set",
- output.trim().endsWith("# EOF"));
- }
+ try (InputStream in = (InputStream) res.get(STREAM_KEY)) {
+ String output = new String(in.readAllBytes(), StandardCharsets.UTF_8);
+ assertFalse(
+ "Should default to Prometheus format when no wt parameter is set",
+ output.trim().endsWith("# EOF"));
}
}
@@ -191,12 +186,11 @@ public class TestPrometheusResponseWriter extends SolrTestCaseJ4 {
req.setResponseParser(new InputStreamResponseParser("unknownFormat"));
- try (SolrClient adminClient = getHttpSolrClient(solrTestRule.getBaseUrl())) {
- NamedList<Object> res = adminClient.request(req);
- InputStream stream = (InputStream) res.get("stream");
- if (stream != null) stream.close();
- // Unknown wt parameter should return a 400 error
- assertEquals(400, res.get("responseStatus"));
- }
+ SolrClient adminClient = solrTestRule.getAdminClient();
+ NamedList<Object> res = adminClient.request(req);
+ InputStream stream = (InputStream) res.get("stream");
+ if (stream != null) stream.close();
+ // Unknown wt parameter should return a 400 error
+ assertEquals(400, res.get("responseStatus"));
}
}
diff --git a/solr/core/src/test/org/apache/solr/response/TestRawTransformer.java b/solr/core/src/test/org/apache/solr/response/TestRawTransformer.java
index 0190653249b..1fff683d95a 100644
--- a/solr/core/src/test/org/apache/solr/response/TestRawTransformer.java
+++ b/solr/core/src/test/org/apache/solr/response/TestRawTransformer.java
@@ -62,13 +62,13 @@ public class TestRawTransformer extends SolrCloudTestCase {
initStandalone();
JSR.start();
if (random().nextBoolean()) {
- CLIENT = JSR.newClient();
+ CLIENT = JSR.getSolrClient();
} else {
CLIENT = new EmbeddedSolrServer(JSR.getCoreContainer(), null);
}
} else {
initCloud();
- CLIENT = JSR.newClient();
+ CLIENT = JSR.getSolrClient();
JSR = null;
}
initIndex();
diff --git a/solr/core/src/test/org/apache/solr/schema/ManagedSchemaRoundRobinCloudTest.java b/solr/core/src/test/org/apache/solr/schema/ManagedSchemaRoundRobinCloudTest.java
index 2b770f7f23c..bd75970eca2 100644
--- a/solr/core/src/test/org/apache/solr/schema/ManagedSchemaRoundRobinCloudTest.java
+++ b/solr/core/src/test/org/apache/solr/schema/ManagedSchemaRoundRobinCloudTest.java
@@ -55,23 +55,16 @@ public class ManagedSchemaRoundRobinCloudTest extends SolrCloudTestCase {
@Test
public void testAddFieldsRoundRobin() throws Exception {
List<SolrClient> clients = new ArrayList<>(NUM_SHARDS);
- try {
- for (int shardNum = 0; shardNum < NUM_SHARDS; ++shardNum) {
- clients.add(
- getHttpSolrClient(cluster.getJettySolrRunners().get(shardNum).getBaseUrl().toString()));
- }
- int shardNum = 0;
- for (int fieldNum = 0; fieldNum < NUM_FIELDS_TO_ADD; ++fieldNum) {
- addField(
- clients.get(shardNum),
- keyValueArrayToMap("name", FIELD_PREFIX + fieldNum, "type", "string"));
- if (++shardNum == NUM_SHARDS) {
- shardNum = 0;
- }
- }
- } finally {
- for (int shardNum = 0; shardNum < NUM_SHARDS; ++shardNum) {
- clients.get(shardNum).close();
+ for (int shardNum = 0; shardNum < NUM_SHARDS; ++shardNum) {
+ clients.add(cluster.getJettySolrRunners().get(shardNum).getSolrClient());
+ }
+ int shardNum = 0;
+ for (int fieldNum = 0; fieldNum < NUM_FIELDS_TO_ADD; ++fieldNum) {
+ addField(
+ clients.get(shardNum),
+ keyValueArrayToMap("name", FIELD_PREFIX + fieldNum, "type", "string"));
+ if (++shardNum == NUM_SHARDS) {
+ shardNum = 0;
}
}
}
diff --git a/solr/core/src/test/org/apache/solr/search/TestCoordinatorRole.java b/solr/core/src/test/org/apache/solr/search/TestCoordinatorRole.java
index 053fb9e4d7c..3019cf48fd6 100644
--- a/solr/core/src/test/org/apache/solr/search/TestCoordinatorRole.java
+++ b/solr/core/src/test/org/apache/solr/search/TestCoordinatorRole.java
@@ -35,7 +35,6 @@ import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
-import org.apache.solr.client.solrj.jetty.HttpJettySolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.QueryRequest;
import org.apache.solr.client.solrj.request.SolrQuery;
@@ -219,225 +218,224 @@ public class TestCoordinatorRole extends SolrCloudTestCase {
}
assertNotNull(nrtJetty);
assertNotNull(pullJetty);
- try (SolrClient client = pullJetty.newClient()) {
- client.add(COLL, sid);
- client.commit(COLL);
- assertEquals(
- nrtCore,
- getHostCoreName(
- COLL, qaJettyBase, p -> p.add(ShardParams.SHARDS_PREFERENCE, "replica.type:NRT")));
- assertEquals(
- pullCore,
- getHostCoreName(
- COLL, qaJettyBase, p -> p.add(ShardParams.SHARDS_PREFERENCE, "replica.type:PULL")));
- // Now , kill NRT jetty
- JettySolrRunner nrtJettyF = nrtJetty;
- JettySolrRunner pullJettyF = pullJetty;
- Random r = random();
- final long establishBaselineMs = r.nextInt(1000);
- final long nrtDowntimeMs = r.nextInt(10000);
- // NOTE: for `pullServiceTimeMs`, it can't be super-short. This is just to simplify our
- // indexing code,
- // based on the fact that our indexing is based on a PULL-node client.
- final long pullServiceTimeMs = 1000 + (long) r.nextInt(9000);
- Future<?> jettyManipulationFuture =
- executor.submit(
- () -> {
- // we manipulate the jetty instances in a separate thread to more closely mimic
- // the behavior we'd see irl.
+ SolrClient client = pullJetty.getSolrClient();
+ client.add(COLL, sid);
+ client.commit(COLL);
+ assertEquals(
+ nrtCore,
+ getHostCoreName(
+ COLL, qaJettyBase, p -> p.add(ShardParams.SHARDS_PREFERENCE, "replica.type:NRT")));
+ assertEquals(
+ pullCore,
+ getHostCoreName(
+ COLL, qaJettyBase, p -> p.add(ShardParams.SHARDS_PREFERENCE, "replica.type:PULL")));
+ // Now , kill NRT jetty
+ JettySolrRunner nrtJettyF = nrtJetty;
+ JettySolrRunner pullJettyF = pullJetty;
+ Random r = random();
+ final long establishBaselineMs = r.nextInt(1000);
+ final long nrtDowntimeMs = r.nextInt(10000);
+ // NOTE: for `pullServiceTimeMs`, it can't be super-short. This is just to simplify our
+ // indexing code,
+ // based on the fact that our indexing is based on a PULL-node client.
+ final long pullServiceTimeMs = 1000 + (long) r.nextInt(9000);
+ Future<?> jettyManipulationFuture =
+ executor.submit(
+ () -> {
+ // we manipulate the jetty instances in a separate thread to more closely mimic
+ // the behavior we'd see irl.
+ try {
+ Thread.sleep(establishBaselineMs);
+ log.info("stopping NRT jetty ...");
+ nrtJettyF.stop();
+ log.info("NRT jetty stopped.");
+ Thread.sleep(nrtDowntimeMs); // let NRT be down for a while
+ log.info("restarting NRT jetty ...");
+ nrtJettyF.start(true);
+ log.info("NRT jetty restarted.");
+ // once NRT is back up, we expect PULL to continue serving until the TTL on ZK
+ // state used for query request routing has expired (60s). But here we force a
+ // return to NRT by stopping the PULL replica after a brief delay ...
+ Thread.sleep(pullServiceTimeMs);
+ log.info("stopping PULL jetty ...");
+ pullJettyF.stop();
+ log.info("PULL jetty stopped.");
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ });
+ String hostCore;
+ long start = new Date().getTime();
+ long individualRequestStart = start;
+ int count = 0;
+ while (nrtCore.equals(
+ hostCore =
+ getHostCoreName(
+ COLL,
+ qaJettyBase,
+ p -> p.add(ShardParams.SHARDS_PREFERENCE, "replica.type:NRT")))) {
+ count++;
+ Thread.sleep(100);
+ individualRequestStart = new Date().getTime();
+ }
+ long now = new Date().getTime();
+ log.info(
+ "phase1 NRT queries count={}, overall_duration={}, baseline_expected_overall_duration={}, switch-to-pull_duration={}",
+ count,
+ now - start,
+ establishBaselineMs,
+ now - individualRequestStart);
+ // default tolerance of 500ms below should suffice. Failover to PULL for this case should be
+ // very fast, because our QA-based client already knows both replicas are active, the index
+ // is stable, so the moment the client finds NRT is down it should be able to failover
+ // immediately and transparently to PULL.
+ assertEquals(
+ "when we break out of the NRT query loop, should be b/c routed to PULL",
+ pullCore,
+ hostCore);
+ SolrInputDocument d = new SolrInputDocument();
+ d.addField("id", "345");
+ d.addField("desc_s", "Another Document");
+ // attempts to add another doc while NRT is down should fail, then eventually succeed when
+ // NRT comes back up
+ count = 0;
+ start = new Date().getTime();
+ individualRequestStart = start;
+ for (; ; ) {
+ try {
+ client.add(COLL, d);
+ client.commit(COLL);
+ break;
+ } catch (SolrException ex) {
+ // we expect these until nrtJetty is back up.
+ count++;
+ Thread.sleep(100);
+ }
+ individualRequestStart = new Date().getTime();
+ }
+ now = new Date().getTime();
+ log.info(
+ "successfully added another doc; duration: {}, overall_duration={}, baseline_expected_overall_duration={}, exception_count={}",
+ now - individualRequestStart,
+ now - start,
+ nrtDowntimeMs,
+ count);
+ // NRT replica is back up, registered as available with Zk, and availability info has been
+ // pulled down by our PULL-replica-based `client`, forwarded indexing command to NRT,
+ // index/commit completed. All of this accounts for the 3000ms tolerance allowed for below.
+ // This is not a strict value, and if it causes failures regularly we should feel free to
+ // increase the tolerance; but it's meant to provide a stable baseline from which to detect
+ // regressions.
+ count = 0;
+ start = new Date().getTime();
+ individualRequestStart = start;
+ while (pullCore.equals(
+ hostCore =
+ getHostCoreName(
+ COLL,
+ qaJettyBase,
+ p -> {
+ p.set(CommonParams.Q, "id:345");
+ p.add(ShardParams.SHARDS_PREFERENCE, "replica.type:NRT");
+ }))) {
+ count++;
+ Thread.sleep(100);
+ individualRequestStart = new Date().getTime();
+ }
+ now = new Date().getTime();
+ log.info(
+ "query retries between NRT index-ready and query-ready: {}; overall_duration={}; baseline_expected_overall_duration={}; failover-request_duration={}",
+ count,
+ now - start,
+ pullServiceTimeMs,
+ now - individualRequestStart);
+ assertEquals(nrtCore, hostCore);
+ // allow any exceptions to propagate
+ jettyManipulationFuture.get();
+
+ // next phase: just toggle a bunch
+ // TODO: could separate this out into a different test method, but this should suffice for
+ // now
+ pullJetty.start(true);
+ waitForState(
+ "Pull jetty replicas didn't become active in time",
+ COLL,
+ ((liveNodes, collectionState) ->
+ collectionState.getReplicasOnNode(pullJettyF.getNodeName()).stream()
+ .allMatch(rep -> rep.getState() == Replica.State.ACTIVE)));
+ AtomicBoolean done = new AtomicBoolean();
+ long runMinutes = 1;
+ long finishTimeMs =
+ new Date().getTime() + TimeUnit.MILLISECONDS.convert(runMinutes, TimeUnit.MINUTES);
+ JettySolrRunner[] jettys = new JettySolrRunner[] {pullJettyF, nrtJettyF};
+ Random threadRandom = new Random(r.nextInt());
+ Future<Integer> f =
+ executor.submit(
+ () -> {
+ int iteration = 0;
+ while (new Date().getTime() < finishTimeMs && !done.get()) {
+ int idx = iteration++ % jettys.length;
+ JettySolrRunner toManipulate = jettys[idx];
try {
- Thread.sleep(establishBaselineMs);
- log.info("stopping NRT jetty ...");
- nrtJettyF.stop();
- log.info("NRT jetty stopped.");
- Thread.sleep(nrtDowntimeMs); // let NRT be down for a while
- log.info("restarting NRT jetty ...");
- nrtJettyF.start(true);
- log.info("NRT jetty restarted.");
- // once NRT is back up, we expect PULL to continue serving until the TTL on ZK
- // state used for query request routing has expired (60s). But here we force a
- // return to NRT by stopping the PULL replica after a brief delay ...
- Thread.sleep(pullServiceTimeMs);
- log.info("stopping PULL jetty ...");
- pullJettyF.stop();
- log.info("PULL jetty stopped.");
+ int serveTogetherTime = threadRandom.nextInt(7000);
+ int downTime = threadRandom.nextInt(7000);
+ log.info("serving together for {}ms", serveTogetherTime);
+ Thread.sleep(serveTogetherTime);
+ log.info("stopping {} ...", idx);
+ toManipulate.stop();
+ log.info("stopped {}.", idx);
+ Thread.sleep(downTime);
+ log.info("restarting {} ...", idx);
+ toManipulate.start(true);
+ log.info("restarted {}.", idx);
+ waitForState(
+ toManipulate.getNodeName() + " replicas didn't become active in time",
+ COLL,
+ ((liveNodes, collectionState) ->
+ collectionState.getReplicasOnNode(toManipulate.getNodeName()).stream()
+ .allMatch(rep -> rep.getState() == Replica.State.ACTIVE)));
} catch (Exception e) {
throw new RuntimeException(e);
}
- });
- String hostCore;
- long start = new Date().getTime();
- long individualRequestStart = start;
- int count = 0;
- while (nrtCore.equals(
- hostCore =
- getHostCoreName(
- COLL,
- qaJettyBase,
- p -> p.add(ShardParams.SHARDS_PREFERENCE, "replica.type:NRT")))) {
- count++;
- Thread.sleep(100);
- individualRequestStart = new Date().getTime();
- }
- long now = new Date().getTime();
- log.info(
- "phase1 NRT queries count={}, overall_duration={}, baseline_expected_overall_duration={}, switch-to-pull_duration={}",
- count,
- now - start,
- establishBaselineMs,
- now - individualRequestStart);
- // default tolerance of 500ms below should suffice. Failover to PULL for this case should be
- // very fast, because our QA-based client already knows both replicas are active, the index
- // is stable, so the moment the client finds NRT is down it should be able to failover
- // immediately and transparently to PULL.
- assertEquals(
- "when we break out of the NRT query loop, should be b/c routed to PULL",
- pullCore,
- hostCore);
- SolrInputDocument d = new SolrInputDocument();
- d.addField("id", "345");
- d.addField("desc_s", "Another Document");
- // attempts to add another doc while NRT is down should fail, then eventually succeed when
- // NRT comes back up
- count = 0;
- start = new Date().getTime();
- individualRequestStart = start;
- for (; ; ) {
- try {
- client.add(COLL, d);
- client.commit(COLL);
- break;
- } catch (SolrException ex) {
- // we expect these until nrtJetty is back up.
- count++;
- Thread.sleep(100);
+ }
+ done.set(true);
+ return iteration;
+ });
+ count = 0;
+ start = new Date().getTime();
+ try {
+ do {
+ if (pullCore.equals(
+ getHostCoreName(
+ COLL,
+ qaJettyBase,
+ p -> {
+ p.set(CommonParams.Q, "id:345");
+ p.add(ShardParams.SHARDS_PREFERENCE, "replica.type:NRT");
+ }))) {
+ done.set(true);
}
- individualRequestStart = new Date().getTime();
- }
- now = new Date().getTime();
- log.info(
- "successfully added another doc; duration: {}, overall_duration={}, baseline_expected_overall_duration={}, exception_count={}",
- now - individualRequestStart,
- now - start,
- nrtDowntimeMs,
- count);
- // NRT replica is back up, registered as available with Zk, and availability info has been
- // pulled down by our PULL-replica-based `client`, forwarded indexing command to NRT,
- // index/commit completed. All of this accounts for the 3000ms tolerance allowed for below.
- // This is not a strict value, and if it causes failures regularly we should feel free to
- // increase the tolerance; but it's meant to provide a stable baseline from which to detect
- // regressions.
- count = 0;
- start = new Date().getTime();
- individualRequestStart = start;
- while (pullCore.equals(
- hostCore =
- getHostCoreName(
- COLL,
- qaJettyBase,
- p -> {
- p.set(CommonParams.Q, "id:345");
- p.add(ShardParams.SHARDS_PREFERENCE, "replica.type:NRT");
- }))) {
count++;
Thread.sleep(100);
- individualRequestStart = new Date().getTime();
+ } while (!done.get());
+ } finally {
+ final String result;
+ if (done.getAndSet(true)) {
+ result = "Success";
+ } else {
+ // not yet set to done, completed abnormally (exception will be thrown beyond `finally`
+ // block)
+ result = "Failure";
}
- now = new Date().getTime();
+ Integer toggleCount = f.get();
+ long secondsDuration =
+ TimeUnit.SECONDS.convert(new Date().getTime() - start, TimeUnit.MILLISECONDS);
log.info(
- "query retries between NRT index-ready and query-ready: {}; overall_duration={}; baseline_expected_overall_duration={}; failover-request_duration={}",
- count,
- now - start,
- pullServiceTimeMs,
- now - individualRequestStart);
- assertEquals(nrtCore, hostCore);
- // allow any exceptions to propagate
- jettyManipulationFuture.get();
-
- // next phase: just toggle a bunch
- // TODO: could separate this out into a different test method, but this should suffice for
- // now
- pullJetty.start(true);
- waitForState(
- "Pull jetty replicas didn't become active in time",
- COLL,
- ((liveNodes, collectionState) ->
- collectionState.getReplicasOnNode(pullJettyF.getNodeName()).stream()
- .allMatch(rep -> rep.getState() == Replica.State.ACTIVE)));
- AtomicBoolean done = new AtomicBoolean();
- long runMinutes = 1;
- long finishTimeMs =
- new Date().getTime() + TimeUnit.MILLISECONDS.convert(runMinutes, TimeUnit.MINUTES);
- JettySolrRunner[] jettys = new JettySolrRunner[] {pullJettyF, nrtJettyF};
- Random threadRandom = new Random(r.nextInt());
- Future<Integer> f =
- executor.submit(
- () -> {
- int iteration = 0;
- while (new Date().getTime() < finishTimeMs && !done.get()) {
- int idx = iteration++ % jettys.length;
- JettySolrRunner toManipulate = jettys[idx];
- try {
- int serveTogetherTime = threadRandom.nextInt(7000);
- int downTime = threadRandom.nextInt(7000);
- log.info("serving together for {}ms", serveTogetherTime);
- Thread.sleep(serveTogetherTime);
- log.info("stopping {} ...", idx);
- toManipulate.stop();
- log.info("stopped {}.", idx);
- Thread.sleep(downTime);
- log.info("restarting {} ...", idx);
- toManipulate.start(true);
- log.info("restarted {}.", idx);
- waitForState(
- toManipulate.getNodeName() + " replicas didn't become active in time",
- COLL,
- ((liveNodes, collectionState) ->
- collectionState.getReplicasOnNode(toManipulate.getNodeName()).stream()
- .allMatch(rep -> rep.getState() == Replica.State.ACTIVE)));
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- done.set(true);
- return iteration;
- });
- count = 0;
- start = new Date().getTime();
- try {
- do {
- if (pullCore.equals(
- getHostCoreName(
- COLL,
- qaJettyBase,
- p -> {
- p.set(CommonParams.Q, "id:345");
- p.add(ShardParams.SHARDS_PREFERENCE, "replica.type:NRT");
- }))) {
- done.set(true);
- }
- count++;
- Thread.sleep(100);
- } while (!done.get());
- } finally {
- final String result;
- if (done.getAndSet(true)) {
- result = "Success";
- } else {
- // not yet set to done, completed abnormally (exception will be thrown beyond `finally`
- // block)
- result = "Failure";
- }
- Integer toggleCount = f.get();
- long secondsDuration =
- TimeUnit.SECONDS.convert(new Date().getTime() - start, TimeUnit.MILLISECONDS);
- log.info(
- "{}! {} seconds, {} toggles, {} requests served",
- result,
- secondsDuration,
- toggleCount,
- count);
- }
+ "{}! {} seconds, {} toggles, {} requests served",
+ result,
+ secondsDuration,
+ toggleCount,
+ count);
}
} finally {
try {
@@ -463,31 +461,31 @@ public class TestCoordinatorRole extends SolrCloudTestCase {
CommonParams.JAVABIN);
p.accept(q);
SolrDocumentList docs = null;
- try (SolrClient solrClient = new HttpJettySolrClient.Builder(qaNode).build()) {
- for (int i = 0; i < 100; i++) {
- try {
- QueryResponse queryResponse = solrClient.query(COLL, q);
- docs = queryResponse.getResults();
- assertNotNull("Docs should not be null. Query response was: " + queryResponse, docs);
- if (docs.size() > 0) {
- found = true;
- break;
- }
- } catch (SolrException ex) {
- // we know we're doing tricky things that might cause transient errors
- // TODO: all these query requests go to the QA node -- should QA propagate internal
- // request errors to the external client (and the external client retry?) or should QA
- // attempt to failover transparently in the event of an error?
- if (i < 5) {
- log.info("swallowing transient error", ex);
- } else {
- log.error("only expect actual _errors_ within a small window (e.g. 500ms)", ex);
- fail("initial error time threshold exceeded");
- }
+ SolrClient solrClient = cluster.getJetty(qaNode).getSolrClient();
+ for (int i = 0; i < 100; i++) {
+ try {
+ QueryResponse queryResponse = solrClient.query(COLL, q);
+ docs = queryResponse.getResults();
+ assertNotNull("Docs should not be null. Query response was: " + queryResponse, docs);
+ if (docs.size() > 0) {
+ found = true;
+ break;
+ }
+ } catch (SolrException ex) {
+ // we know we're doing tricky things that might cause transient errors
+ // TODO: all these query requests go to the QA node -- should QA propagate internal
+ // request errors to the external client (and the external client retry?) or should QA
+ // attempt to failover transparently in the event of an error?
+ if (i < 5) {
+ log.info("swallowing transient error", ex);
+ } else {
+ log.error("only expect actual _errors_ within a small window (e.g. 500ms)", ex);
+ fail("initial error time threshold exceeded");
}
- Thread.sleep(100);
}
+ Thread.sleep(100);
}
+
assertTrue(found);
return (String) docs.get(0).getFieldValue("_core_");
}
diff --git a/solr/core/src/test/org/apache/solr/search/facet/TestCloudJSONFacetJoinDomain.java b/solr/core/src/test/org/apache/solr/search/facet/TestCloudJSONFacetJoinDomain.java
index 1d0c4aaccf1..42534ae8b72 100644
--- a/solr/core/src/test/org/apache/solr/search/facet/TestCloudJSONFacetJoinDomain.java
+++ b/solr/core/src/test/org/apache/solr/search/facet/TestCloudJSONFacetJoinDomain.java
@@ -124,7 +124,7 @@ public class TestCloudJSONFacetJoinDomain extends SolrCloudTestCase {
waitForRecoveriesToFinish(CLOUD_CLIENT);
for (JettySolrRunner jetty : cluster.getJettySolrRunners())
- CLIENTS.add(getHttpSolrClient(jetty.getBaseUrl().toString(), COLLECTION_NAME));
+ CLIENTS.add(jetty.newSolrClient(COLLECTION_NAME));
final int numDocs = atLeast(100);
for (int id = 0; id < numDocs; id++) {
diff --git a/solr/core/src/test/org/apache/solr/search/facet/TestCloudJSONFacetSKG.java b/solr/core/src/test/org/apache/solr/search/facet/TestCloudJSONFacetSKG.java
index 3695c732e50..1b21d8d7d24 100644
--- a/solr/core/src/test/org/apache/solr/search/facet/TestCloudJSONFacetSKG.java
+++ b/solr/core/src/test/org/apache/solr/search/facet/TestCloudJSONFacetSKG.java
@@ -151,7 +151,7 @@ public class TestCloudJSONFacetSKG extends SolrCloudTestCase {
waitForRecoveriesToFinish(CLOUD_CLIENT);
for (JettySolrRunner jetty : cluster.getJettySolrRunners()) {
- CLIENTS.add(getHttpSolrClient(jetty.getBaseUrl().toString(), COLLECTION_NAME));
+ CLIENTS.add(jetty.newSolrClient(COLLECTION_NAME));
}
final int numDocs = atLeast(100);
diff --git a/solr/core/src/test/org/apache/solr/search/facet/TestCloudJSONFacetSKGEquiv.java b/solr/core/src/test/org/apache/solr/search/facet/TestCloudJSONFacetSKGEquiv.java
index deec286fd21..5446cea0945 100644
--- a/solr/core/src/test/org/apache/solr/search/facet/TestCloudJSONFacetSKGEquiv.java
+++ b/solr/core/src/test/org/apache/solr/search/facet/TestCloudJSONFacetSKGEquiv.java
@@ -142,7 +142,7 @@ public class TestCloudJSONFacetSKGEquiv extends SolrCloudTestCase {
waitForRecoveriesToFinish(CLOUD_CLIENT);
for (JettySolrRunner jetty : cluster.getJettySolrRunners()) {
- CLIENTS.add(getHttpSolrClient(jetty.getBaseUrl().toString(), COLLECTION_NAME));
+ CLIENTS.add(jetty.newSolrClient(COLLECTION_NAME));
}
final int numDocs = atLeast(100);
diff --git a/solr/core/src/test/org/apache/solr/search/stats/TestDistribIDF.java b/solr/core/src/test/org/apache/solr/search/stats/TestDistribIDF.java
index 4f63b16f52f..0522942543c 100644
--- a/solr/core/src/test/org/apache/solr/search/stats/TestDistribIDF.java
+++ b/solr/core/src/test/org/apache/solr/search/stats/TestDistribIDF.java
@@ -108,34 +108,31 @@ public class TestDistribIDF extends SolrTestCaseJ4 {
// Test against all nodes
for (JettySolrRunner jettySolrRunner : solrCluster.getJettySolrRunners()) {
- try (SolrClient solrClient = getHttpSolrClient(jettySolrRunner.getBaseUrl().toString())) {
- try (SolrClient solrClient_local =
- getHttpSolrClient(jettySolrRunner.getBaseUrl().toString())) {
-
- SolrQuery query = new SolrQuery("cat:football");
- query.setFields("*,score");
- QueryResponse queryResponse = solrClient.query("onecollection", query);
- assertEquals(2, queryResponse.getResults().getNumFound());
- float score1 = (float) queryResponse.getResults().get(0).get("score");
- float score2 = (float) queryResponse.getResults().get(1).get("score");
- assertEquals(
- "Doc1 score=" + score1 + " Doc2 score=" + score2, 0, Float.compare(score1, score2));
-
- query = new SolrQuery("cat:football");
- query.setShowDebugInfo(true);
- query.setFields("*,score");
- queryResponse = solrClient_local.query("onecollection_local", query);
- assertEquals(2, queryResponse.getResults().getNumFound());
- assertEquals("2", queryResponse.getResults().get(0).get("id"));
- assertEquals("1", queryResponse.getResults().get(1).get("id"));
- float score1_local = (float) queryResponse.getResults().get(0).get("score");
- float score2_local = (float) queryResponse.getResults().get(1).get("score");
- assertEquals(
- "Doc1 score=" + score1_local + " Doc2 score=" + score2_local,
- 1,
- Float.compare(score1_local, score2_local));
- }
- }
+ SolrClient solrClient = jettySolrRunner.getSolrClient();
+ SolrClient solrClient_local = jettySolrRunner.getSolrClient();
+
+ SolrQuery query = new SolrQuery("cat:football");
+ query.setFields("*,score");
+ QueryResponse queryResponse = solrClient.query("onecollection", query);
+ assertEquals(2, queryResponse.getResults().getNumFound());
+ float score1 = (float) queryResponse.getResults().get(0).get("score");
+ float score2 = (float) queryResponse.getResults().get(1).get("score");
+ assertEquals(
+ "Doc1 score=" + score1 + " Doc2 score=" + score2, 0, Float.compare(score1, score2));
+
+ query = new SolrQuery("cat:football");
+ query.setShowDebugInfo(true);
+ query.setFields("*,score");
+ queryResponse = solrClient_local.query("onecollection_local", query);
+ assertEquals(2, queryResponse.getResults().getNumFound());
+ assertEquals("2", queryResponse.getResults().get(0).get("id"));
+ assertEquals("1", queryResponse.getResults().get(1).get("id"));
+ float score1_local = (float) queryResponse.getResults().get(0).get("score");
+ float score2_local = (float) queryResponse.getResults().get(1).get("score");
+ assertEquals(
+ "Doc1 score=" + score1_local + " Doc2 score=" + score2_local,
+ 1,
+ Float.compare(score1_local, score2_local));
}
}
@@ -159,34 +156,30 @@ public class TestDistribIDF extends SolrTestCaseJ4 {
// Test against all nodes
for (JettySolrRunner jettySolrRunner : solrCluster.getJettySolrRunners()) {
-
- try (SolrClient solrClient = getHttpSolrClient(jettySolrRunner.getBaseUrl().toString())) {
-
- try (SolrClient solrClient_local =
- getHttpSolrClient(jettySolrRunner.getBaseUrl().toString())) {
- SolrQuery query = new SolrQuery("cat:football");
- query.setFields("*,score").add("collection", "collection1,collection2");
- QueryResponse queryResponse = solrClient.query("collection1", query);
- assertEquals(2, queryResponse.getResults().getNumFound());
- float score1 = (float) queryResponse.getResults().get(0).get("score");
- float score2 = (float) queryResponse.getResults().get(1).get("score");
- assertEquals(
- "Doc1 score=" + score1 + " Doc2 score=" + score2, 0, Float.compare(score1, score2));
-
- query = new SolrQuery("cat:football");
- query.setFields("*,score").add("collection", "collection1_local,collection2_local");
- queryResponse = solrClient_local.query("collection1_local", query);
- assertEquals(2, queryResponse.getResults().getNumFound());
- assertEquals("2", queryResponse.getResults().get(0).get("id"));
- assertEquals("1", queryResponse.getResults().get(1).get("id"));
- float score1_local = (float) queryResponse.getResults().get(0).get("score");
- float score2_local = (float) queryResponse.getResults().get(1).get("score");
- assertEquals(
- "Doc1 score=" + score1_local + " Doc2 score=" + score2_local,
- 1,
- Float.compare(score1_local, score2_local));
- }
- }
+ SolrClient solrClient = jettySolrRunner.getSolrClient();
+ SolrClient solrClient_local = jettySolrRunner.getSolrClient();
+
+ SolrQuery query = new SolrQuery("cat:football");
+ query.setFields("*,score").add("collection", "collection1,collection2");
+ QueryResponse queryResponse = solrClient.query("collection1", query);
+ assertEquals(2, queryResponse.getResults().getNumFound());
+ float score1 = (float) queryResponse.getResults().get(0).get("score");
+ float score2 = (float) queryResponse.getResults().get(1).get("score");
+ assertEquals(
+ "Doc1 score=" + score1 + " Doc2 score=" + score2, 0, Float.compare(score1, score2));
+
+ query = new SolrQuery("cat:football");
+ query.setFields("*,score").add("collection", "collection1_local,collection2_local");
+ queryResponse = solrClient_local.query("collection1_local", query);
+ assertEquals(2, queryResponse.getResults().getNumFound());
+ assertEquals("2", queryResponse.getResults().get(0).get("id"));
+ assertEquals("1", queryResponse.getResults().get(1).get("id"));
+ float score1_local = (float) queryResponse.getResults().get(0).get("score");
+ float score2_local = (float) queryResponse.getResults().get(1).get("score");
+ assertEquals(
+ "Doc1 score=" + score1_local + " Doc2 score=" + score2_local,
+ 1,
+ Float.compare(score1_local, score2_local));
}
}
diff --git a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java
index 9684d5447cf..71c1da0c463 100644
--- a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java
+++ b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java
@@ -176,7 +176,8 @@ public class BasicAuthIntegrationTest extends SolrCloudAuthTestCase {
executeCommand(httpClient, baseUrl + authzPrefix, command, "solr", "SolrRocks");
assertAuthMetricsMinimums(5, 2, 3, 0, 0, 0);
- baseUrl = cluster.getBaseUrl(random());
+ final JettySolrRunner secondRandomJetty = cluster.getRandomJetty(random());
+ baseUrl = secondRandomJetty.getBaseUrl().toString();
verifySecurityStatus(
httpClient, baseUrl + authzPrefix, "authorization/user-role/harry", NOT_NULL_PREDICATE, 20);
@@ -210,11 +211,10 @@ public class BasicAuthIntegrationTest extends SolrCloudAuthTestCase {
CollectionAdminRequest.Reload reload = CollectionAdminRequest.reloadCollection(COLLECTION);
- try (var solrClient2 = getHttpSolrClient(baseUrl)) {
- expectThrows(RemoteSolrException.class, () -> solrClient2.request(reload));
- reload.setMethod(SolrRequest.METHOD.POST);
- expectThrows(RemoteSolrException.class, () -> solrClient2.request(reload));
- }
+ var solrClient2 = secondRandomJetty.getSolrClient();
+ expectThrows(RemoteSolrException.class, () -> solrClient2.request(reload));
+ reload.setMethod(SolrRequest.METHOD.POST);
+ expectThrows(RemoteSolrException.class, () -> solrClient2.request(reload));
cluster
.getSolrClient()
.request(
@@ -247,7 +247,7 @@ public class BasicAuthIntegrationTest extends SolrCloudAuthTestCase {
// Test for SOLR-12514. Create a new jetty . This jetty does not have the collection.
// Make a request to that jetty and it should fail
JettySolrRunner aNewJetty = cluster.startJettySolrRunner();
- SolrClient aNewClient = aNewJetty.newClient();
+ SolrClient aNewClient = aNewJetty.getSolrClient();
UpdateRequest delQuery = null;
delQuery = new UpdateRequest().deleteByQuery("*:*");
delQuery.setBasicAuthCredentials("harry", "HarryIsUberCool");
@@ -261,7 +261,6 @@ public class BasicAuthIntegrationTest extends SolrCloudAuthTestCase {
});
assertEquals(401, e.code()); // Authentication failed
} finally {
- aNewClient.close();
cluster.stopJettySolrRunner(aNewJetty);
}
diff --git a/solr/core/src/test/org/apache/solr/security/BasicAuthStandaloneTest.java b/solr/core/src/test/org/apache/solr/security/BasicAuthStandaloneTest.java
index 63c83c13579..bdd26321183 100644
--- a/solr/core/src/test/org/apache/solr/security/BasicAuthStandaloneTest.java
+++ b/solr/core/src/test/org/apache/solr/security/BasicAuthStandaloneTest.java
@@ -26,7 +26,6 @@ import java.nio.file.Path;
import java.util.Base64;
import java.util.Map;
import org.apache.solr.SolrTestCaseJ4;
-import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.common.params.MapSolrParams;
import org.apache.solr.common.util.Utils;
import org.apache.solr.embedded.JettySolrRunner;
@@ -70,66 +69,58 @@ public class BasicAuthStandaloneTest extends SolrTestCaseJ4 {
String authcPrefix = "/admin/authentication";
String authzPrefix = "/admin/authorization";
- HttpClient httpClient;
- SolrClient solrClient = null;
- try {
- httpClient = jetty.getSolrClient().getHttpClient();
- String baseUrl = buildUrl(jetty.getLocalPort());
- solrClient = getHttpSolrClient(baseUrl);
+ var solrClient = jetty.getSolrClient();
+ HttpClient httpClient = solrClient.getHttpClient();
+ String baseUrl = buildUrl(jetty.getLocalPort());
- verifySecurityStatus(httpClient, baseUrl + authcPrefix, "/errorMessages", null, 20);
+ verifySecurityStatus(httpClient, baseUrl + authcPrefix, "/errorMessages", null, 20);
- // Write security.json locally. Should cause security to be initialized
- securityConfHandler.persistConf(
- new SecurityConfHandler.SecurityConfig()
- .setData(Utils.fromJSONString(STD_CONF.replace("'", "\""))));
- securityConfHandler.securityConfEdited();
- verifySecurityStatus(
- httpClient, baseUrl + authcPrefix, "authentication/class", "solr.BasicAuthPlugin", 20);
+ // Write security.json locally. Should cause security to be initialized
+ securityConfHandler.persistConf(
+ new SecurityConfHandler.SecurityConfig()
+ .setData(Utils.fromJSONString(STD_CONF.replace("'", "\""))));
+ securityConfHandler.securityConfEdited();
+ verifySecurityStatus(
+ httpClient, baseUrl + authcPrefix, "authentication/class", "solr.BasicAuthPlugin", 20);
- String command = "{\n" + "'set-user': {'harry':'HarryIsCool'}\n" + "}";
+ String command = "{\n" + "'set-user': {'harry':'HarryIsCool'}\n" + "}";
- doHttpPost(httpClient, baseUrl + authcPrefix, command, null, null, 401);
- verifySecurityStatus(httpClient, baseUrl + authcPrefix, "authentication.enabled", "true", 20);
+ doHttpPost(httpClient, baseUrl + authcPrefix, command, null, null, 401);
+ verifySecurityStatus(httpClient, baseUrl + authcPrefix, "authentication.enabled", "true", 20);
- command = "{\n" + "'set-user': {'harry':'HarryIsUberCool'}\n" + "}";
+ command = "{\n" + "'set-user': {'harry':'HarryIsUberCool'}\n" + "}";
- doHttpPost(httpClient, baseUrl + authcPrefix, command, "solr", "SolrRocks");
- verifySecurityStatus(
- httpClient,
- baseUrl + authcPrefix,
- "authentication/credentials/harry",
- NOT_NULL_PREDICATE,
- 20);
-
- // Read file from SOLR_HOME and verify that it contains our new user
- assertTrue(
- new String(Utils.toJSON(securityConfHandler.getSecurityConfig(false).getData()), UTF_8)
- .contains("harry"));
-
- // Edit authorization
+ doHttpPost(httpClient, baseUrl + authcPrefix, command, "solr", "SolrRocks");
+ verifySecurityStatus(
+ httpClient,
+ baseUrl + authcPrefix,
+ "authentication/credentials/harry",
+ NOT_NULL_PREDICATE,
+ 20);
+
+ // Read file from SOLR_HOME and verify that it contains our new user
+ assertTrue(
+ new String(Utils.toJSON(securityConfHandler.getSecurityConfig(false).getData()), UTF_8)
+ .contains("harry"));
+
+ // Edit authorization
+ verifySecurityStatus(
+ httpClient, baseUrl + authzPrefix, "authorization/permissions[1]/role", null, 20);
+ doHttpPost(
+ httpClient,
+ baseUrl + authzPrefix,
+ "{'set-permission': {'name': 'update', 'role':'updaterole'}}",
+ "solr",
+ "SolrRocks");
+ command = "{\n" + "'set-permission': {'name': 'read', 'role':'solr'}\n" + "}";
+ doHttpPost(httpClient, baseUrl + authzPrefix, command, "solr", "SolrRocks");
+ try {
+ solrClient.query("collection1", new MapSolrParams(Map.of("q", "foo")));
+ fail("Should return a 401 response");
+ } catch (Exception e) {
+ // Test that the second doPost request to /security/authorization went through
verifySecurityStatus(
- httpClient, baseUrl + authzPrefix, "authorization/permissions[1]/role", null, 20);
- doHttpPost(
- httpClient,
- baseUrl + authzPrefix,
- "{'set-permission': {'name': 'update', 'role':'updaterole'}}",
- "solr",
- "SolrRocks");
- command = "{\n" + "'set-permission': {'name': 'read', 'role':'solr'}\n" + "}";
- doHttpPost(httpClient, baseUrl + authzPrefix, command, "solr", "SolrRocks");
- try {
- solrClient.query("collection1", new MapSolrParams(Map.of("q", "foo")));
- fail("Should return a 401 response");
- } catch (Exception e) {
- // Test that the second doPost request to /security/authorization went through
- verifySecurityStatus(
- httpClient, baseUrl + authzPrefix, "authorization/permissions[2]/role", "solr", 20);
- }
- } finally {
- if (solrClient != null) {
- solrClient.close();
- }
+ httpClient, baseUrl + authzPrefix, "authorization/permissions[2]/role", "solr", 20);
}
}
diff --git a/solr/core/src/test/org/apache/solr/security/MultiAuthPluginTest.java b/solr/core/src/test/org/apache/solr/security/MultiAuthPluginTest.java
index 9cb8d774989..3076b0f3277 100644
--- a/solr/core/src/test/org/apache/solr/security/MultiAuthPluginTest.java
+++ b/solr/core/src/test/org/apache/solr/security/MultiAuthPluginTest.java
@@ -38,7 +38,6 @@ import java.util.Objects;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.apache.solr.SolrTestCaseJ4;
-import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.util.CommandOperation;
@@ -85,175 +84,166 @@ public class MultiAuthPluginTest extends SolrTestCaseJ4 {
final String user = "admin";
final String pass = "SolrRocks";
- HttpClient httpClient = null;
- SolrClient solrClient = null;
- try {
- httpClient = jetty.getSolrClient().getHttpClient();
- String baseUrl = buildUrl(jetty.getLocalPort());
- solrClient = getHttpSolrClient(baseUrl);
-
- verifySecurityStatus(httpClient, baseUrl + authcPrefix, "/errorMessages", null, 5);
-
- // Initialize security.json with multiple auth plugins configured
- String multiAuthPluginSecurityJson =
- Files.readString(
- TEST_PATH().resolve("security").resolve("multi_auth_plugin_security.json"),
- StandardCharsets.UTF_8);
- securityConfHandler.persistConf(
- new SecurityConfHandler.SecurityConfig()
- .setData(Utils.fromJSONString(multiAuthPluginSecurityJson)));
- securityConfHandler.securityConfEdited();
-
- // verify "WWW-Authenticate" headers are returned
- verifyWWWAuthenticateHeaders(httpClient, baseUrl);
-
- verifySecurityStatus(
- httpClient,
- baseUrl + authcPrefix,
- "authentication/class",
- "solr.MultiAuthPlugin",
- 5,
- user,
- pass);
- verifySecurityStatus(
- httpClient,
- baseUrl + authzPrefix,
- "authorization/class",
- "solr.MultiAuthRuleBasedAuthorizationPlugin",
- 5,
- user,
- pass);
-
- // anonymous requests are blocked by all plugins
- int statusCode = doHttpGetAnonymous(httpClient, baseUrl + CommonParams.SYSTEM_INFO_PATH);
- assertEquals("anonymous get succeeded but should not have", 401, statusCode);
- // update blockUnknown to allow anonymous for the basic plugin
- String command = "{\n" + "'set-property': { 'basic': {'blockUnknown':false} }\n" + "}";
- doHttpPost(httpClient, baseUrl + authcPrefix, command, user, pass, 200);
- statusCode = doHttpGetAnonymous(httpClient, baseUrl + CommonParams.SYSTEM_INFO_PATH);
- assertEquals("anonymous get failed but should have succeeded", 200, statusCode);
-
- // For the multi-auth plugin, every command is wrapped with an object that identifies the
- // "scheme"
- command = "{\n" + "'set-user': {'harry':'HarryIsCool'}\n" + "}";
- // no scheme identified!
- doHttpPost(httpClient, baseUrl + authcPrefix, command, user, pass, 400);
-
- command = "{\n" + "'set-user': { 'foo': {'harry':'HarryIsCool'} }\n" + "}";
- // no "foo" scheme configured
- doHttpPost(httpClient, baseUrl + authcPrefix, command, user, pass, 400);
-
- command = "{\n" + "'set-user': { 'basic': {'harry':'HarryIsCool'} }\n" + "}";
-
- // no creds, should fail ...
- doHttpPost(httpClient, baseUrl + authcPrefix, command, null, null, 401);
- // with basic creds, should pass ...
- doHttpPost(httpClient, baseUrl + authcPrefix, command, user, pass, 200);
- verifySecurityStatus(
- httpClient,
- baseUrl + authcPrefix,
- "authentication/schemes[0]/credentials/harry",
- NOT_NULL_PREDICATE,
- 5,
- user,
- pass);
-
- // authz command but missing the "scheme" wrapper
- command = "{\n" + "'set-user-role': {'harry':['users']}\n" + "}";
- doHttpPost(httpClient, baseUrl + authzPrefix, command, user, pass, 400);
-
- // add "harry" to the "users" role ...
- command = "{\n" + "'set-user-role': { 'basic': {'harry':['users']} }\n" + "}";
- doHttpPost(httpClient, baseUrl + authzPrefix, command, user, pass, 200);
- verifySecurityStatus(
- httpClient,
- baseUrl + authzPrefix,
- "authorization/schemes[0]/user-role/harry",
- NOT_NULL_PREDICATE,
- 5,
- user,
- pass);
-
- // give the users role a custom permission
- verifySecurityStatus(
- httpClient,
- baseUrl + authzPrefix,
- "authorization/permissions[6]",
- NULL_PREDICATE,
- 5,
- user,
- pass);
- command =
- "{\n"
- + "'set-permission': { 'name':'k8s-zk', 'role':'users', 'collection':null, 'path':'/admin/zookeeper/status' }\n"
- + "}";
- doHttpPost(httpClient, baseUrl + authzPrefix, command, user, pass, 200);
- verifySecurityStatus(
- httpClient,
- baseUrl + authzPrefix,
- "authorization/permissions[6]/path",
- new ExpectedValuePredicate("/admin/zookeeper/status"),
- 5,
- user,
- pass);
-
- command =
- "{\n"
- + "'update-permission': { 'index':'7', 'name':'k8s-zk', 'role':'users', 'collection':null, 'path':'/admin/zookeeper/status2' }\n"
- + "}";
- doHttpPost(httpClient, baseUrl + authzPrefix, command, user, pass, 200);
- verifySecurityStatus(
- httpClient,
- baseUrl + authzPrefix,
- "authorization/permissions[6]/path",
- new ExpectedValuePredicate("/admin/zookeeper/status2"),
- 5,
- user,
- pass);
-
- // delete the permission
- command = "{\n" + "'delete-permission': 7\n" + "}";
- doHttpPost(httpClient, baseUrl + authzPrefix, command, user, pass, 200);
- verifySecurityStatus(
- httpClient,
- baseUrl + authzPrefix,
- "authorization/permissions[6]",
- NULL_PREDICATE,
- 5,
- user,
- pass);
-
- // delete the user
- command = "{\n" + "'delete-user': { 'basic': 'harry' }\n" + "}";
-
- doHttpPost(httpClient, baseUrl + authcPrefix, command, user, pass, 200);
- verifySecurityStatus(
- httpClient,
- baseUrl + authcPrefix,
- "authentication/schemes[0]/credentials/harry",
- NULL_PREDICATE,
- 5,
- user,
- pass);
-
- // update the property on the mock (just to test routing to the mock plugin)
- command = "{\n" + "'set-property': { 'mock': { 'blockUnknown':false } }\n" + "}";
-
- doHttpPostWithHeader(
- httpClient, baseUrl + authcPrefix, command, "Authorization", "mock foo", 200);
- verifySecurityStatus(
- httpClient,
- baseUrl + authcPrefix,
- "authentication/schemes[1]/blockUnknown",
- new ExpectedValuePredicate(Boolean.FALSE),
- 5,
- user,
- pass);
- } finally {
- if (solrClient != null) {
- solrClient.close();
- }
- }
+ HttpClient httpClient = jetty.getSolrClient().getHttpClient();
+ String baseUrl = buildUrl(jetty.getLocalPort());
+
+ verifySecurityStatus(httpClient, baseUrl + authcPrefix, "/errorMessages", null, 5);
+
+ // Initialize security.json with multiple auth plugins configured
+ String multiAuthPluginSecurityJson =
+ Files.readString(
+ TEST_PATH().resolve("security").resolve("multi_auth_plugin_security.json"),
+ StandardCharsets.UTF_8);
+ securityConfHandler.persistConf(
+ new SecurityConfHandler.SecurityConfig()
+ .setData(Utils.fromJSONString(multiAuthPluginSecurityJson)));
+ securityConfHandler.securityConfEdited();
+
+ // verify "WWW-Authenticate" headers are returned
+ verifyWWWAuthenticateHeaders(httpClient, baseUrl);
+
+ verifySecurityStatus(
+ httpClient,
+ baseUrl + authcPrefix,
+ "authentication/class",
+ "solr.MultiAuthPlugin",
+ 5,
+ user,
+ pass);
+ verifySecurityStatus(
+ httpClient,
+ baseUrl + authzPrefix,
+ "authorization/class",
+ "solr.MultiAuthRuleBasedAuthorizationPlugin",
+ 5,
+ user,
+ pass);
+
+ // anonymous requests are blocked by all plugins
+ int statusCode = doHttpGetAnonymous(httpClient, baseUrl + CommonParams.SYSTEM_INFO_PATH);
+ assertEquals("anonymous get succeeded but should not have", 401, statusCode);
+ // update blockUnknown to allow anonymous for the basic plugin
+ String command = "{\n" + "'set-property': { 'basic': {'blockUnknown':false} }\n" + "}";
+ doHttpPost(httpClient, baseUrl + authcPrefix, command, user, pass, 200);
+ statusCode = doHttpGetAnonymous(httpClient, baseUrl + CommonParams.SYSTEM_INFO_PATH);
+ assertEquals("anonymous get failed but should have succeeded", 200, statusCode);
+
+ // For the multi-auth plugin, every command is wrapped with an object that identifies the
+ // "scheme"
+ command = "{\n" + "'set-user': {'harry':'HarryIsCool'}\n" + "}";
+ // no scheme identified!
+ doHttpPost(httpClient, baseUrl + authcPrefix, command, user, pass, 400);
+
+ command = "{\n" + "'set-user': { 'foo': {'harry':'HarryIsCool'} }\n" + "}";
+ // no "foo" scheme configured
+ doHttpPost(httpClient, baseUrl + authcPrefix, command, user, pass, 400);
+
+ command = "{\n" + "'set-user': { 'basic': {'harry':'HarryIsCool'} }\n" + "}";
+
+ // no creds, should fail ...
+ doHttpPost(httpClient, baseUrl + authcPrefix, command, null, null, 401);
+ // with basic creds, should pass ...
+ doHttpPost(httpClient, baseUrl + authcPrefix, command, user, pass, 200);
+ verifySecurityStatus(
+ httpClient,
+ baseUrl + authcPrefix,
+ "authentication/schemes[0]/credentials/harry",
+ NOT_NULL_PREDICATE,
+ 5,
+ user,
+ pass);
+
+ // authz command but missing the "scheme" wrapper
+ command = "{\n" + "'set-user-role': {'harry':['users']}\n" + "}";
+ doHttpPost(httpClient, baseUrl + authzPrefix, command, user, pass, 400);
+
+ // add "harry" to the "users" role ...
+ command = "{\n" + "'set-user-role': { 'basic': {'harry':['users']} }\n" + "}";
+ doHttpPost(httpClient, baseUrl + authzPrefix, command, user, pass, 200);
+ verifySecurityStatus(
+ httpClient,
+ baseUrl + authzPrefix,
+ "authorization/schemes[0]/user-role/harry",
+ NOT_NULL_PREDICATE,
+ 5,
+ user,
+ pass);
+
+ // give the users role a custom permission
+ verifySecurityStatus(
+ httpClient,
+ baseUrl + authzPrefix,
+ "authorization/permissions[6]",
+ NULL_PREDICATE,
+ 5,
+ user,
+ pass);
+ command =
+ "{\n"
+ + "'set-permission': { 'name':'k8s-zk', 'role':'users', 'collection':null, 'path':'/admin/zookeeper/status' }\n"
+ + "}";
+ doHttpPost(httpClient, baseUrl + authzPrefix, command, user, pass, 200);
+ verifySecurityStatus(
+ httpClient,
+ baseUrl + authzPrefix,
+ "authorization/permissions[6]/path",
+ new ExpectedValuePredicate("/admin/zookeeper/status"),
+ 5,
+ user,
+ pass);
+
+ command =
+ "{\n"
+ + "'update-permission': { 'index':'7', 'name':'k8s-zk', 'role':'users', 'collection':null, 'path':'/admin/zookeeper/status2' }\n"
+ + "}";
+ doHttpPost(httpClient, baseUrl + authzPrefix, command, user, pass, 200);
+ verifySecurityStatus(
+ httpClient,
+ baseUrl + authzPrefix,
+ "authorization/permissions[6]/path",
+ new ExpectedValuePredicate("/admin/zookeeper/status2"),
+ 5,
+ user,
+ pass);
+
+ // delete the permission
+ command = "{\n" + "'delete-permission': 7\n" + "}";
+ doHttpPost(httpClient, baseUrl + authzPrefix, command, user, pass, 200);
+ verifySecurityStatus(
+ httpClient,
+ baseUrl + authzPrefix,
+ "authorization/permissions[6]",
+ NULL_PREDICATE,
+ 5,
+ user,
+ pass);
+
+ // delete the user
+ command = "{\n" + "'delete-user': { 'basic': 'harry' }\n" + "}";
+
+ doHttpPost(httpClient, baseUrl + authcPrefix, command, user, pass, 200);
+ verifySecurityStatus(
+ httpClient,
+ baseUrl + authcPrefix,
+ "authentication/schemes[0]/credentials/harry",
+ NULL_PREDICATE,
+ 5,
+ user,
+ pass);
+
+ // update the property on the mock (just to test routing to the mock plugin)
+ command = "{\n" + "'set-property': { 'mock': { 'blockUnknown':false } }\n" + "}";
+
+ doHttpPostWithHeader(
+ httpClient, baseUrl + authcPrefix, command, "Authorization", "mock foo", 200);
+ verifySecurityStatus(
+ httpClient,
+ baseUrl + authcPrefix,
+ "authentication/schemes[1]/blockUnknown",
+ new ExpectedValuePredicate(Boolean.FALSE),
+ 5,
+ user,
+ pass);
}
@Test
@@ -261,40 +251,29 @@ public class MultiAuthPluginTest extends SolrTestCaseJ4 {
final String user = "admin";
final String pass = "SolrRocks";
- HttpClient httpClient = null;
- SolrClient solrClient = null;
- try {
- httpClient = jetty.getSolrClient().getHttpClient();
- String baseUrl = buildUrl(jetty.getLocalPort());
- solrClient = getHttpSolrClient(baseUrl);
-
- verifySecurityStatus(httpClient, baseUrl + authcPrefix, "/errorMessages", null, 5);
-
- // Initialize security.json with multiple xbasic auth and other configured
- String multiAuthPluginSecurityJson =
- Files.readString(
- TEST_PATH()
- .resolve("security")
- .resolve("multi_auth_plugin_with_xbasic_security.json"),
- StandardCharsets.UTF_8);
- securityConfHandler.persistConf(
- new SecurityConfHandler.SecurityConfig()
- .setData(Utils.fromJSONString(multiAuthPluginSecurityJson)));
- securityConfHandler.securityConfEdited();
-
- // verify "WWW-Authenticate" headers are returned
- verifyWWWAuthenticateHeaders(httpClient, baseUrl);
-
- // Command that does not update anything in the current config
- String command = "{ 'set-property': { 'xbasic': { 'blockUnknown': true } } }";
-
- // verify that clients can still use "Basic" scheme with xBasic scheme configured in MultiAuth
- doHttpPost(httpClient, baseUrl + authcPrefix, command, user, pass, 200);
- } finally {
- if (solrClient != null) {
- solrClient.close();
- }
- }
+ HttpClient httpClient = jetty.getSolrClient().getHttpClient();
+ String baseUrl = buildUrl(jetty.getLocalPort());
+
+ verifySecurityStatus(httpClient, baseUrl + authcPrefix, "/errorMessages", null, 5);
+
+ // Initialize security.json with multiple xbasic auth and other configured
+ String multiAuthPluginSecurityJson =
+ Files.readString(
+ TEST_PATH().resolve("security").resolve("multi_auth_plugin_with_xbasic_security.json"),
+ StandardCharsets.UTF_8);
+ securityConfHandler.persistConf(
+ new SecurityConfHandler.SecurityConfig()
+ .setData(Utils.fromJSONString(multiAuthPluginSecurityJson)));
+ securityConfHandler.securityConfEdited();
+
+ // verify "WWW-Authenticate" headers are returned
+ verifyWWWAuthenticateHeaders(httpClient, baseUrl);
+
+ // Command that does not update anything in the current config
+ String command = "{ 'set-property': { 'xbasic': { 'blockUnknown': true } } }";
+
+ // verify that clients can still use "Basic" scheme with xBasic scheme configured in MultiAuth
+ doHttpPost(httpClient, baseUrl + authcPrefix, command, user, pass, 200);
}
@Test
@@ -303,45 +282,36 @@ public class MultiAuthPluginTest extends SolrTestCaseJ4 {
final String xUser = "xadmin";
final String pass = "SolrRocks";
- HttpClient httpClient = null;
- SolrClient solrClient = null;
- try {
- httpClient = jetty.getSolrClient().getHttpClient();
- String baseUrl = buildUrl(jetty.getLocalPort());
- solrClient = getHttpSolrClient(baseUrl);
-
- verifySecurityStatus(httpClient, baseUrl + authcPrefix, "/errorMessages", null, 5);
-
- // Initialize security.json with basic and xbasic scheme
- String multiAuthPluginSecurityJson =
- Files.readString(
- TEST_PATH()
- .resolve("security")
- .resolve("multi_auth_plugin_with_basic_and_xbasic_security.json"),
- StandardCharsets.UTF_8);
- securityConfHandler.persistConf(
- new SecurityConfHandler.SecurityConfig()
- .setData(Utils.fromJSONString(multiAuthPluginSecurityJson)));
- securityConfHandler.securityConfEdited();
-
- // verify "WWW-Authenticate" headers are returned
- verifyWWWAuthenticateHeaders(httpClient, baseUrl);
-
- // Command that does not update anything in the current config
- String command = "{ 'set-property': { 'basic': { 'blockUnknown': true } } }";
-
- // verify that basic takes precedence over xbasic when both present
- doHttpPost(httpClient, baseUrl + authcPrefix, command, user, pass, 200);
-
- // Since both are present, xbasic will never be looked up if client does not send XBasic
- // as auth scheme, and using xBasic won't work with BasicAuthPlugin, so this security
- // configuration should return 401 as it resolves with the plugin that uses "basic" as scheme
- doHttpPost(httpClient, baseUrl + authcPrefix, command, xUser, pass, 401);
- } finally {
- if (solrClient != null) {
- solrClient.close();
- }
- }
+ HttpClient httpClient = jetty.getSolrClient().getHttpClient();
+ String baseUrl = buildUrl(jetty.getLocalPort());
+
+ verifySecurityStatus(httpClient, baseUrl + authcPrefix, "/errorMessages", null, 5);
+
+ // Initialize security.json with basic and xbasic scheme
+ String multiAuthPluginSecurityJson =
+ Files.readString(
+ TEST_PATH()
+ .resolve("security")
+ .resolve("multi_auth_plugin_with_basic_and_xbasic_security.json"),
+ StandardCharsets.UTF_8);
+ securityConfHandler.persistConf(
+ new SecurityConfHandler.SecurityConfig()
+ .setData(Utils.fromJSONString(multiAuthPluginSecurityJson)));
+ securityConfHandler.securityConfEdited();
+
+ // verify "WWW-Authenticate" headers are returned
+ verifyWWWAuthenticateHeaders(httpClient, baseUrl);
+
+ // Command that does not update anything in the current config
+ String command = "{ 'set-property': { 'basic': { 'blockUnknown': true } } }";
+
+ // verify that basic takes precedence over xbasic when both present
+ doHttpPost(httpClient, baseUrl + authcPrefix, command, user, pass, 200);
+
+ // Since both are present, xbasic will never be looked up if client does not send XBasic
+ // as auth scheme, and using xBasic won't work with BasicAuthPlugin, so this security
+ // configuration should return 401 as it resolves with the plugin that uses "basic" as scheme
+ doHttpPost(httpClient, baseUrl + authcPrefix, command, xUser, pass, 401);
}
@Test
@@ -349,40 +319,31 @@ public class MultiAuthPluginTest extends SolrTestCaseJ4 {
final String user = "admin";
final String pass = "SolrRocks";
- HttpClient httpClient = null;
- SolrClient solrClient = null;
- try {
- httpClient = jetty.getSolrClient().getHttpClient();
- String baseUrl = buildUrl(jetty.getLocalPort());
- solrClient = getHttpSolrClient(baseUrl);
-
- verifySecurityStatus(httpClient, baseUrl + authcPrefix, "/errorMessages", null, 5);
-
- // Initialize security.json with a single plugin configured
- String multiAuthPluginSecurityJson =
- Files.readString(
- TEST_PATH()
- .resolve("security")
- .resolve("multi_auth_plugin_with_basic_only_security.json"),
- StandardCharsets.UTF_8);
- securityConfHandler.persistConf(
- new SecurityConfHandler.SecurityConfig()
- .setData(Utils.fromJSONString(multiAuthPluginSecurityJson)));
- securityConfHandler.securityConfEdited();
-
- // verify "WWW-Authenticate" headers are returned
- verifyWWWAuthenticateHeaders(httpClient, baseUrl);
-
- // Command that does not update anything in the current config
- String command = "{ 'set-property': { 'basic': { 'blockUnknown': true } } }";
-
- // verify that a single plugin configuration is allowed and works
- doHttpPost(httpClient, baseUrl + authcPrefix, command, user, pass, 200);
- } finally {
- if (solrClient != null) {
- solrClient.close();
- }
- }
+ HttpClient httpClient = jetty.getSolrClient().getHttpClient();
+ String baseUrl = buildUrl(jetty.getLocalPort());
+
+ verifySecurityStatus(httpClient, baseUrl + authcPrefix, "/errorMessages", null, 5);
+
+ // Initialize security.json with a single plugin configured
+ String multiAuthPluginSecurityJson =
+ Files.readString(
+ TEST_PATH()
+ .resolve("security")
+ .resolve("multi_auth_plugin_with_basic_only_security.json"),
+ StandardCharsets.UTF_8);
+ securityConfHandler.persistConf(
+ new SecurityConfHandler.SecurityConfig()
+ .setData(Utils.fromJSONString(multiAuthPluginSecurityJson)));
+ securityConfHandler.securityConfEdited();
+
+ // verify "WWW-Authenticate" headers are returned
+ verifyWWWAuthenticateHeaders(httpClient, baseUrl);
+
+ // Command that does not update anything in the current config
+ String command = "{ 'set-property': { 'basic': { 'blockUnknown': true } } }";
+
+ // verify that a single plugin configuration is allowed and works
+ doHttpPost(httpClient, baseUrl + authcPrefix, command, user, pass, 200);
}
@Test
@@ -390,91 +351,74 @@ public class MultiAuthPluginTest extends SolrTestCaseJ4 {
final String user = "admin";
final String pass = "SolrRocks";
- HttpClient httpClient = null;
- SolrClient solrClient = null;
- try {
- httpClient = jetty.getSolrClient().getHttpClient();
- String baseUrl = buildUrl(jetty.getLocalPort());
- solrClient = getHttpSolrClient(baseUrl);
-
- verifySecurityStatus(httpClient, baseUrl + authcPrefix, "/errorMessages", null, 5);
-
- // Initialize security.json with a single plugin configured
- String multiAuthPluginSecurityJson =
- Files.readString(
- TEST_PATH()
- .resolve("security")
- .resolve("multi_auth_plugin_with_mock_and_basic_security.json"),
- StandardCharsets.UTF_8);
- securityConfHandler.persistConf(
- new SecurityConfHandler.SecurityConfig()
- .setData(Utils.fromJSONString(multiAuthPluginSecurityJson)));
- securityConfHandler.securityConfEdited();
-
- // verify "WWW-Authenticate" headers are returned
- verifyWWWAuthenticateHeaders(httpClient, baseUrl);
-
- // Command that does not update anything in the current config
- String command = "{ 'set-property': { 'basic': { 'blockUnknown': true } } }";
-
- // verify that the basic auth plugin works and is looked up as expected
- doHttpPost(httpClient, baseUrl + authcPrefix, command, user, pass, 200);
- } finally {
- if (solrClient != null) {
- solrClient.close();
- }
- }
+ HttpClient httpClient = jetty.getSolrClient().getHttpClient();
+ String baseUrl = buildUrl(jetty.getLocalPort());
+
+ verifySecurityStatus(httpClient, baseUrl + authcPrefix, "/errorMessages", null, 5);
+
+ // Initialize security.json with a single plugin configured
+ String multiAuthPluginSecurityJson =
+ Files.readString(
+ TEST_PATH()
+ .resolve("security")
+ .resolve("multi_auth_plugin_with_mock_and_basic_security.json"),
+ StandardCharsets.UTF_8);
+ securityConfHandler.persistConf(
+ new SecurityConfHandler.SecurityConfig()
+ .setData(Utils.fromJSONString(multiAuthPluginSecurityJson)));
+ securityConfHandler.securityConfEdited();
+
+ // verify "WWW-Authenticate" headers are returned
+ verifyWWWAuthenticateHeaders(httpClient, baseUrl);
+
+ // Command that does not update anything in the current config
+ String command = "{ 'set-property': { 'basic': { 'blockUnknown': true } } }";
+
+ // verify that the basic auth plugin works and is looked up as expected
+ doHttpPost(httpClient, baseUrl + authcPrefix, command, user, pass, 200);
}
@Test
public void testMultiAuthWithBasicPluginAndAjax() throws Exception {
- SolrClient solrClient = null;
+ var httpClient = jetty.getSolrClient().getHttpClient();
+ String baseUrl = buildUrl(jetty.getLocalPort());
+
+ verifySecurityStatus(httpClient, baseUrl + authcPrefix, "/errorMessages", null, 5);
+
+ // Initialize security.json with a single plugin configured
+ String multiAuthPluginSecurityJson =
+ Files.readString(
+ TEST_PATH().resolve("security").resolve("multi_auth_plugin_security.json"),
+ StandardCharsets.UTF_8);
+ securityConfHandler.persistConf(
+ new SecurityConfHandler.SecurityConfig()
+ .setData(Utils.fromJSONString(multiAuthPluginSecurityJson)));
+ securityConfHandler.securityConfEdited();
+
+ // Pretend to send unauthorized AJAX request
try {
- var httpClient = jetty.getSolrClient().getHttpClient();
- String baseUrl = buildUrl(jetty.getLocalPort());
- solrClient = getHttpSolrClient(baseUrl);
-
- verifySecurityStatus(httpClient, baseUrl + authcPrefix, "/errorMessages", null, 5);
-
- // Initialize security.json with a single plugin configured
- String multiAuthPluginSecurityJson =
- Files.readString(
- TEST_PATH().resolve("security").resolve("multi_auth_plugin_security.json"),
- StandardCharsets.UTF_8);
- securityConfHandler.persistConf(
- new SecurityConfHandler.SecurityConfig()
- .setData(Utils.fromJSONString(multiAuthPluginSecurityJson)));
- securityConfHandler.securityConfEdited();
-
- // Pretend to send unauthorized AJAX request
- try {
- var response =
- httpClient
- .newRequest(baseUrl + CommonParams.SYSTEM_INFO_PATH)
- .headers(h -> h.add("X-Requested-With", "XMLHttpRequest"))
- .send();
- assertEquals("Unauthorized response was expected", 401, response.getStatus());
-
- // Only first plugin is expected as response, which is also xBasic if BasicAuthPlugin
- List<String> actualSchemes = response.getHeaders().getValuesList("WWW-Authenticate");
-
- // Only the first scheme is expected for AJAX-Requests
- assertEquals("Only one scheme was expected", 1, actualSchemes.size());
-
- // In case of BasicAuthPlugin, xBasic should be returned if AJAX request sent and handled by
- // BasicAuthPlugin
- String expectedScheme = "xBasic realm=\"solr\"";
- assertEquals(
- "Mapped xBasic challenge expected from first plugin which is BasicAuthPlugin",
- expectedScheme,
- actualSchemes.getFirst());
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- } finally {
- if (solrClient != null) {
- solrClient.close();
- }
+ var response =
+ httpClient
+ .newRequest(baseUrl + CommonParams.SYSTEM_INFO_PATH)
+ .headers(h -> h.add("X-Requested-With", "XMLHttpRequest"))
+ .send();
+ assertEquals("Unauthorized response was expected", 401, response.getStatus());
+
+ // Only first plugin is expected as response, which is also xBasic if BasicAuthPlugin
+ List<String> actualSchemes = response.getHeaders().getValuesList("WWW-Authenticate");
+
+ // Only the first scheme is expected for AJAX-Requests
+ assertEquals("Only one scheme was expected", 1, actualSchemes.size());
+
+ // In case of BasicAuthPlugin, xBasic should be returned if AJAX request sent and handled by
+ // BasicAuthPlugin
+ String expectedScheme = "xBasic realm=\"solr\"";
+ assertEquals(
+ "Mapped xBasic challenge expected from first plugin which is BasicAuthPlugin",
+ expectedScheme,
+ actualSchemes.getFirst());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
}
}
diff --git a/solr/core/src/test/org/apache/solr/update/DeleteByIdWithRouterFieldTest.java b/solr/core/src/test/org/apache/solr/update/DeleteByIdWithRouterFieldTest.java
index e879b3281bd..0d5e86ffd54 100644
--- a/solr/core/src/test/org/apache/solr/update/DeleteByIdWithRouterFieldTest.java
+++ b/solr/core/src/test/org/apache/solr/update/DeleteByIdWithRouterFieldTest.java
@@ -117,21 +117,19 @@ public class DeleteByIdWithRouterFieldTest extends SolrCloudTestCase {
final String shardName = entry.getKey();
final Slice slice = entry.getValue();
final Replica leader = entry.getValue().getLeader();
- try (SolrClient leaderClient = getHttpSolrClient(leader)) {
- final SolrDocumentList leaderResults = leaderClient.query(params).getResults();
- for (Replica replica : slice) {
- try (SolrClient replicaClient = getHttpSolrClient(replica)) {
- final SolrDocumentList replicaResults = replicaClient.query(params).getResults();
- assertEquals(
- "inconsistency w/leader: shard=" + shardName + "core=" + replica.getCoreName(),
- Set.of(),
- CloudInspectUtil.showDiff(
- leaderResults,
- replicaResults,
- shardName + " leader: " + leader.getCoreUrl(),
- shardName + ": " + replica.getCoreUrl()));
- }
- }
+ SolrClient leaderClient = cluster.getSolrClient(leader);
+ final SolrDocumentList leaderResults = leaderClient.query(params).getResults();
+ for (Replica replica : slice) {
+ SolrClient replicaClient = cluster.getSolrClient(replica);
+ final SolrDocumentList replicaResults = replicaClient.query(params).getResults();
+ assertEquals(
+ "inconsistency w/leader: shard=" + shardName + "core=" + replica.getCoreName(),
+ Set.of(),
+ CloudInspectUtil.showDiff(
+ leaderResults,
+ replicaResults,
+ shardName + " leader: " + leader.getCoreUrl(),
+ shardName + ": " + replica.getCoreUrl()));
}
}
}
diff --git a/solr/core/src/test/org/apache/solr/update/processor/TestCloudDeduplication.java b/solr/core/src/test/org/apache/solr/update/processor/TestCloudDeduplication.java
index 6c1dcc0fa8b..5c8b2f14043 100644
--- a/solr/core/src/test/org/apache/solr/update/processor/TestCloudDeduplication.java
+++ b/solr/core/src/test/org/apache/solr/update/processor/TestCloudDeduplication.java
@@ -59,7 +59,7 @@ public class TestCloudDeduplication extends SolrCloudTestCase {
CLIENTS.add(cluster.getSolrClient());
for (JettySolrRunner jetty : cluster.getJettySolrRunners()) {
- final SolrClient c = getHttpSolrClient(jetty.getBaseUrl().toString());
+ final SolrClient c = jetty.getSolrClient();
NODE_CLIENTS.add(c);
CLIENTS.add(c);
}
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTests.java b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTests.java
index f1314c29b92..7b2ae5e6a29 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTests.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTests.java
@@ -439,14 +439,12 @@ public abstract class SolrExampleTests extends SolrExampleTestsBase {
if (solrTestRule.getJetty() != null) {
// check system wide system handler + "/admin/info/system"
- String url = solrTestRule.getBaseUrl();
- try (SolrClient adminClient = getHttpSolrClient(url)) {
- SolrQuery q = new SolrQuery();
+ SolrClient adminClient = solrTestRule.getAdminClient();
+ SolrQuery q = new SolrQuery();
- final var rsp = new SystemInfoRequest().process(adminClient);
- assertNotNull(rsp.getResponse().get("mode"));
- assertNotNull(rsp.getResponse().get("lucene"));
- }
+ final var rsp = new SystemInfoRequest().process(adminClient);
+ assertNotNull(rsp.getResponse().get("mode"));
+ assertNotNull(rsp.getResponse().get("lucene"));
}
}
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTestsBase.java b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTestsBase.java
index 8d41ab9ce22..f4716ee0de1 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTestsBase.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTestsBase.java
@@ -22,6 +22,7 @@ import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.client.solrj.jetty.HttpJettySolrClient;
import org.apache.solr.client.solrj.request.AbstractUpdateRequest.ACTION;
import org.apache.solr.client.solrj.request.SolrQuery;
import org.apache.solr.client.solrj.request.UpdateRequest;
@@ -78,8 +79,9 @@ public abstract class SolrExampleTestsBase extends SolrTestCaseJ4 {
* options.
*/
public SolrClient createNewSolrClient() {
- return SolrTestCaseJ4.getHttpSolrClient(
- solrTestRule.getBaseUrl(), DEFAULT_TEST_COLLECTION_NAME);
+ return new HttpJettySolrClient.Builder(solrTestRule.getBaseUrl())
+ .withDefaultCollection(DEFAULT_TEST_COLLECTION_NAME)
+ .build();
}
/** query the example */
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientTest.java
index 94ca36f2b15..ee80cbb85b9 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientTest.java
@@ -395,11 +395,11 @@ public class CloudHttp2SolrClientTest extends SolrCloudTestCase {
params.add("distrib", "false");
QueryRequest queryRequest = new QueryRequest(params);
- try (SolrClient solrClient = getHttpSolrClient(baseUrl, coreName)) {
- QueryResponse queryResponse = queryRequest.process(solrClient);
- SolrDocumentList docList = queryResponse.getResults();
- assertEquals(1, docList.getNumFound());
- }
+ SolrClient solrClient =
+ new CollectionScopedSolrClient(cluster.getJetty(baseUrl).getSolrClient(), coreName);
+ QueryResponse queryResponse = queryRequest.process(solrClient);
+ SolrDocumentList docList = queryResponse.getResults();
+ assertEquals(1, docList.getNumFound());
}
// Test the deleteById routing for UpdateRequest
@@ -444,11 +444,11 @@ public class CloudHttp2SolrClientTest extends SolrCloudTestCase {
params.add("q", "id:" + id);
params.add("distrib", "false");
QueryRequest queryRequest = new QueryRequest(params);
- try (SolrClient solrClient = getHttpSolrClient(baseUrl, coreName)) {
- QueryResponse queryResponse = queryRequest.process(solrClient);
- SolrDocumentList docList = queryResponse.getResults();
- assertEquals(1, docList.getNumFound());
- }
+ SolrClient solrClient =
+ new CollectionScopedSolrClient(cluster.getJetty(baseUrl).getSolrClient(), coreName);
+ QueryResponse queryResponse = queryRequest.process(solrClient);
+ SolrDocumentList docList = queryResponse.getResults();
+ assertEquals(1, docList.getNumFound());
}
}
@@ -728,9 +728,7 @@ public class CloudHttp2SolrClientTest extends SolrCloudTestCase {
for (JettySolrRunner runner : cluster.getJettySolrRunners()) {
Double numRequests =
SolrJMetricTestUtils.getNumNodeRequestErrors(
- runner.getBaseUrl().toString(),
- SolrRequest.SolrRequestType.ADMIN.name(),
- adminPath);
+ runner, SolrRequest.SolrRequestType.ADMIN.name(), adminPath);
errorsBefore += numRequests.longValue();
if (log.isInfoEnabled()) {
log.info(
@@ -754,9 +752,7 @@ public class CloudHttp2SolrClientTest extends SolrCloudTestCase {
for (JettySolrRunner runner : cluster.getJettySolrRunners()) {
Double numRequests =
SolrJMetricTestUtils.getNumNodeRequestErrors(
- runner.getBaseUrl().toString(),
- SolrRequest.SolrRequestType.ADMIN.name(),
- adminPath);
+ runner, SolrRequest.SolrRequestType.ADMIN.name(), adminPath);
errorsAfter += numRequests.longValue();
if (log.isInfoEnabled()) {
log.info(
@@ -836,33 +832,33 @@ public class CloudHttp2SolrClientTest extends SolrCloudTestCase {
SolrQuery q = new SolrQuery().setQuery("*:*");
RemoteSolrException sse = null;
- try (SolrClient solrClient = getHttpSolrClient(r.getBaseUrl(), COLLECTION)) {
+ // addressed by collection (not core) on purpose: that is what exercises _stateVer_
+ SolrClient solrClient =
+ new CollectionScopedSolrClient(cluster.getReplicaJetty(r).getSolrClient(), COLLECTION);
- if (log.isInfoEnabled()) {
- log.info("should work query, result {}", solrClient.query(q));
- }
- // no problem
- q.setParam(CloudSolrClient.STATE_VERSION, COLLECTION + ":" + coll.getZNodeVersion());
- if (log.isInfoEnabled()) {
- log.info("2nd query , result {}", solrClient.query(q));
- }
- // no error yet good
-
- q.setParam(
- CloudSolrClient.STATE_VERSION,
- COLLECTION + ":" + (coll.getZNodeVersion() - 1)); // an older version expect error
-
- QueryResponse rsp = solrClient.query(q);
- final NamedList<Object> response = rsp.getResponse();
- final int stateVersionIdx =
- response.indexOf(CloudSolrClient.STATE_VERSION, response.size() - 1);
- @SuppressWarnings({"rawtypes"})
- Map m = stateVersionIdx == -1 ? null : (Map) response.getVal(stateVersionIdx);
- assertNotNull(
- "Expected an extra information from server with the list of invalid collection states",
- m);
- assertNotNull(m.get(COLLECTION));
+ if (log.isInfoEnabled()) {
+ log.info("should work query, result {}", solrClient.query(q));
+ }
+ // no problem
+ q.setParam(CloudSolrClient.STATE_VERSION, COLLECTION + ":" + coll.getZNodeVersion());
+ if (log.isInfoEnabled()) {
+ log.info("2nd query , result {}", solrClient.query(q));
}
+ // no error yet good
+
+ q.setParam(
+ CloudSolrClient.STATE_VERSION,
+ COLLECTION + ":" + (coll.getZNodeVersion() - 1)); // an older version expect error
+
+ QueryResponse rsp = solrClient.query(q);
+ final NamedList<Object> response = rsp.getResponse();
+ final int stateVersionIdx =
+ response.indexOf(CloudSolrClient.STATE_VERSION, response.size() - 1);
+ @SuppressWarnings({"rawtypes"})
+ Map m = stateVersionIdx == -1 ? null : (Map) response.getVal(stateVersionIdx);
+ assertNotNull(
+ "Expected an extra information from server with the list of invalid collection states", m);
+ assertNotNull(m.get(COLLECTION));
// now send the request to another node that does not serve the collection
@@ -884,19 +880,20 @@ public class CloudHttp2SolrClientTest extends SolrCloudTestCase {
log.info("the node which does not serve this collection{} ", theNode);
assertNotNull(theNode);
- try (SolrClient solrClient = getHttpSolrClient(theNode, COLLECTION)) {
+ // this node has no replica of the collection, so it is addressed by node rather than replica
+ SolrClient otherNodeClient =
+ new CollectionScopedSolrClient(cluster.getJetty(theNode).getSolrClient(), COLLECTION);
- q.setParam(CloudSolrClient.STATE_VERSION, COLLECTION + ":" + (coll.getZNodeVersion() - 1));
- try {
- QueryResponse rsp = solrClient.query(q);
- log.info("error was expected");
- } catch (RemoteSolrException e) {
- sse = e;
- }
- assertNotNull(sse);
- assertEquals(
- " Error code should be 510", SolrException.ErrorCode.INVALID_STATE.code, sse.code());
+ q.setParam(CloudSolrClient.STATE_VERSION, COLLECTION + ":" + (coll.getZNodeVersion() - 1));
+ try {
+ otherNodeClient.query(q);
+ log.info("error was expected");
+ } catch (RemoteSolrException e) {
+ sse = e;
}
+ assertNotNull(sse);
+ assertEquals(
+ " Error code should be 510", SolrException.ErrorCode.INVALID_STATE.code, sse.code());
}
@Test
@@ -937,7 +934,8 @@ public class CloudHttp2SolrClientTest extends SolrCloudTestCase {
@Test
public void customHttpClientTest() throws Exception {
String baseUrl = cluster.getJettySolrRunners().get(0).getBaseUrl().toString();
- try (HttpJettySolrClient httpClient = new HttpJettySolrClient.Builder(baseUrl).build()) {
+ try (HttpJettySolrClient httpClient =
+ cluster.getJettySolrRunners().get(0).newSolrClient(null)) {
try (CloudSolrClient cloudClient =
new CloudJettySolrClient.Builder(List.of(baseUrl)).withHttpClient(httpClient).build()) {
// Verify the CloudJettySolrClient uses the provided HttpJettySolrClient
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpSolrClientBadInputTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpSolrClientBadInputTest.java
index e9c4e9e093a..e9781b67d86 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpSolrClientBadInputTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpSolrClientBadInputTest.java
@@ -49,59 +49,31 @@ public class HttpSolrClientBadInputTest extends SolrTestCaseJ4 {
}
@Test
- public void testDeleteByIdReportsInvalidIdLists() throws Exception {
- try (SolrClient client = getHttpSolrClient(solrTestRule.getBaseUrl(), ANY_COLLECTION)) {
- assertExceptionThrownWithMessageContaining(
- IllegalArgumentException.class,
- List.of("ids", "null"),
- () -> {
- client.deleteById(NULL_STR_LIST);
- });
- assertExceptionThrownWithMessageContaining(
- IllegalArgumentException.class,
- List.of("ids", "empty"),
- () -> {
- client.deleteById(EMPTY_STR_LIST);
- });
- assertExceptionThrownWithMessageContaining(
- IllegalArgumentException.class,
- List.of("ids", "null"),
- () -> {
- client.deleteById(NULL_STR_LIST, ANY_COMMIT_WITHIN_TIME);
- });
- assertExceptionThrownWithMessageContaining(
- IllegalArgumentException.class,
- List.of("ids", "empty"),
- () -> {
- client.deleteById(EMPTY_STR_LIST, ANY_COMMIT_WITHIN_TIME);
- });
- }
-
- try (SolrClient client = getHttpSolrClient(solrTestRule.getBaseUrl())) {
- assertExceptionThrownWithMessageContaining(
- IllegalArgumentException.class,
- List.of("ids", "null"),
- () -> {
- client.deleteById(ANY_COLLECTION, NULL_STR_LIST);
- });
- assertExceptionThrownWithMessageContaining(
- IllegalArgumentException.class,
- List.of("ids", "empty"),
- () -> {
- client.deleteById(ANY_COLLECTION, EMPTY_STR_LIST);
- });
- assertExceptionThrownWithMessageContaining(
- IllegalArgumentException.class,
- List.of("ids", "null"),
- () -> {
- client.deleteById(ANY_COLLECTION, NULL_STR_LIST, ANY_COMMIT_WITHIN_TIME);
- });
- assertExceptionThrownWithMessageContaining(
- IllegalArgumentException.class,
- List.of("ids", "empty"),
- () -> {
- client.deleteById(ANY_COLLECTION, EMPTY_STR_LIST, ANY_COMMIT_WITHIN_TIME);
- });
- }
+ public void testDeleteByIdReportsInvalidIdLists() {
+ SolrClient client = solrTestRule.getSolrClient(ANY_COLLECTION);
+ assertExceptionThrownWithMessageContaining(
+ IllegalArgumentException.class,
+ List.of("ids", "null"),
+ () -> {
+ client.deleteById(NULL_STR_LIST);
+ });
+ assertExceptionThrownWithMessageContaining(
+ IllegalArgumentException.class,
+ List.of("ids", "empty"),
+ () -> {
+ client.deleteById(EMPTY_STR_LIST);
+ });
+ assertExceptionThrownWithMessageContaining(
+ IllegalArgumentException.class,
+ List.of("ids", "null"),
+ () -> {
+ client.deleteById(NULL_STR_LIST, ANY_COMMIT_WITHIN_TIME);
+ });
+ assertExceptionThrownWithMessageContaining(
+ IllegalArgumentException.class,
+ List.of("ids", "empty"),
+ () -> {
+ client.deleteById(EMPTY_STR_LIST, ANY_COMMIT_WITHIN_TIME);
+ });
}
}
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/LB2SolrClientTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/LB2SolrClientTest.java
index 849d8953c0f..5fca5e8f789 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/LB2SolrClientTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/LB2SolrClientTest.java
@@ -91,7 +91,9 @@ public class LB2SolrClientTest extends SolrTestCaseJ4 {
}
SolrResponseBase resp;
try (SolrClient client =
- getHttpSolrClient(solrInstance.getBaseUrl(), solrInstance.getDefaultCollection())) {
+ new HttpJettySolrClient.Builder(solrInstance.getBaseUrl())
+ .withDefaultCollection(solrInstance.getDefaultCollection())
+ .build()) {
resp = client.add(docs);
assertEquals(0, resp.getStatus());
resp = client.commit();
diff --git a/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java b/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
index 11aa4fb83a0..219f5e19a03 100644
--- a/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
+++ b/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
@@ -51,6 +51,7 @@ import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrResponse;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
+import org.apache.solr.client.solrj.jetty.HttpJettySolrClient;
import org.apache.solr.client.solrj.request.QueryRequest;
import org.apache.solr.client.solrj.request.UpdateRequest;
import org.apache.solr.client.solrj.response.QueryResponse;
@@ -447,7 +448,9 @@ public abstract class BaseDistributedSearchTestCase extends SolrTestCaseJ4 {
}
protected HttpSolrClient createNewSolrClient(int port) {
- return getHttpSolrClient(buildUrl(port), DEFAULT_TEST_CORENAME);
+ return new HttpJettySolrClient.Builder(buildUrl(port))
+ .withDefaultCollection(DEFAULT_TEST_CORENAME)
+ .build();
}
protected static void addFields(SolrInputDocument doc, Object... fields) {
diff --git a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseHS.java b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseHS.java
index fa5dd6e6d83..be382bcbbb7 100644
--- a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseHS.java
+++ b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseHS.java
@@ -35,6 +35,7 @@ import org.apache.lucene.util.IOUtils;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
+import org.apache.solr.client.solrj.jetty.HttpJettySolrClient;
import org.apache.solr.client.solrj.request.QueryRequest;
import org.apache.solr.client.solrj.request.UpdateRequest;
import org.apache.solr.client.solrj.response.InputStreamResponseParser;
@@ -405,7 +406,8 @@ public class SolrTestCaseHS extends SolrTestCaseJ4 {
public SolrClient getSolrJ() {
if (solrj == null) {
- solrj = getHttpSolrClient(getBaseURL(), collection);
+ solrj =
+ new HttpJettySolrClient.Builder(getBaseURL()).withDefaultCollection(collection).build();
}
return solrj;
}
diff --git a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
index 295f595bf1c..141b6db0a7f 100644
--- a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
+++ b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
@@ -88,7 +88,6 @@ import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.SolrInputField;
-import org.apache.solr.common.cloud.Replica;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.MultiMapSolrParams;
@@ -2524,53 +2523,6 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
}
}
- /**
- * This method creates a basic HttpSolrClient. Tests that want to control the creation process
- * should use the {@link org.apache.solr.client.solrj.jetty.HttpJettySolrClient.Builder} class
- * directly
- *
- * @param url the base URL for a Solr node. Should not contain a core or collection name.
- */
- /**
- * @deprecated Prefer an existing client, e.g. from a {@link
- * org.apache.solr.util.SolrClientTestRule} or {@link
- * org.apache.solr.embedded.JettySolrRunner#getSolrClient()}.
- */
- @Deprecated(since = "10.1") // probably use an existing client like on a testRule/jettyRunner
- public static HttpJettySolrClient getHttpSolrClient(String url) {
- return new HttpJettySolrClient.Builder(url).build();
- }
-
- /** Create a basic HttpSolrClient pointed at the specified replica */
- /**
- * @deprecated Prefer an existing client, e.g. from a {@link
- * org.apache.solr.util.SolrClientTestRule} or {@link
- * org.apache.solr.embedded.JettySolrRunner#getSolrClient()}.
- */
- @Deprecated(since = "10.1") // probably use an existing client like on a testRule/jettyRunner
- public static HttpJettySolrClient getHttpSolrClient(Replica replica) {
- return getHttpSolrClient(replica.getBaseUrl(), replica.getCoreName());
- }
-
- /**
- * This method creates a basic HttpSolrClient. Tests that want to control the creation process
- * should use the {@link org.apache.solr.client.solrj.jetty.HttpJettySolrClient.Builder} class
- * directly
- *
- * @param url the base URL of a Solr node. Should <em>not</em> include a collection or core name.
- * @param defaultCoreName the name of a core that the created client should default to when making
- * core-aware requests
- */
- /**
- * @deprecated Prefer an existing client, e.g. from a {@link
- * org.apache.solr.util.SolrClientTestRule} or {@link
- * org.apache.solr.embedded.JettySolrRunner#getSolrClient()}.
- */
- @Deprecated(since = "10.1") // probably use an existing client like on a testRule/jettyRunner
- public static HttpJettySolrClient getHttpSolrClient(String url, String defaultCoreName) {
- return new HttpJettySolrClient.Builder(url).withDefaultCollection(defaultCoreName).build();
- }
-
/**
* Returns a randomly generated Date in the appropriate Solr external (input) format
*
diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java
index 7a62af77d0e..0b8e194abc7 100644
--- a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java
+++ b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java
@@ -59,6 +59,7 @@ import org.apache.solr.client.solrj.SolrRequest.METHOD;
import org.apache.solr.client.solrj.SolrRequest.SolrRequestType;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.CollectionScopedSolrClient;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.jetty.HttpJettySolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
@@ -2556,6 +2557,31 @@ public abstract class AbstractFullDistribZkTestBase extends BaseDistributedSearc
return commonCloudSolrClient;
}
+ /** Returns the jetty identified by node name or base URL. */
+ protected JettySolrRunner getJetty(String nodeNameOrUrl) {
+ return MiniSolrCloudCluster.findJetty(allRunners(), nodeNameOrUrl);
+ }
+
+ /**
+ * Returns the jetty-owned client for the node hosting {@code replica}, scoped to that replica's
+ * core. The caller must not close it -- the jetty owns it.
+ */
+ protected SolrClient getSolrClient(Replica replica) {
+ return new CollectionScopedSolrClient(
+ MiniSolrCloudCluster.findReplicaJetty(allRunners(), replica).getSolrClient(),
+ replica.getCoreName());
+ }
+
+ /** All runners of this cluster; the control jetty is kept outside {@link #jettys}. */
+ private List<JettySolrRunner> allRunners() {
+ if (controlJetty == null) {
+ return jettys;
+ }
+ List<JettySolrRunner> all = new ArrayList<>(jettys);
+ all.add(controlJetty);
+ return all;
+ }
+
protected CloudSolrClient getSolrClient(String collectionName) {
return solrClientByCollection.computeIfAbsent(
collectionName,
@@ -2816,7 +2842,7 @@ public abstract class AbstractFullDistribZkTestBase extends BaseDistributedSearc
protected boolean reloadCollection(Replica replica, String testCollectionName) throws Exception {
String coreName = replica.getCoreName();
boolean reloadedOk = false;
- try (SolrClient client = getHttpSolrClient(replica.getBaseUrl())) {
+ try (SolrClient client = new HttpJettySolrClient.Builder(replica.getBaseUrl()).build()) {
CoreAdminResponse statusResp = CoreAdminRequest.getStatus(coreName, client);
long leaderCoreStartTime = statusResp.getStartTime(coreName).getTime();
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 161760e3e70..7aba36a9188 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
@@ -53,8 +53,10 @@ import java.util.function.Consumer;
import org.apache.lucene.tests.util.LuceneTestCase;
import org.apache.solr.SolrBackend;
import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.CollectionScopedSolrClient;
import org.apache.solr.client.solrj.impl.ZkClientClusterStateProvider;
import org.apache.solr.client.solrj.jetty.CloudJettySolrClient;
import org.apache.solr.client.solrj.jetty.HttpJettySolrClient;
@@ -738,14 +740,48 @@ public class MiniSolrCloudCluster implements SolrBackend {
/** Return the jetty that a particular replica resides on */
public JettySolrRunner getReplicaJetty(Replica replica) {
- for (JettySolrRunner jetty : jettys) {
+ return findReplicaJetty(jettys, replica);
+ }
+
+ /** Returns the runner among {@code runners} that hosts {@code replica}. */
+ static JettySolrRunner findReplicaJetty(Collection<JettySolrRunner> runners, Replica replica) {
+ for (JettySolrRunner jetty : runners) {
if (jetty.isStopped()) continue;
if (replica.getCoreUrl().startsWith(jetty.getBaseUrl().toString())) return jetty;
+ // a proxied jetty registers its replicas under the proxy's port
+ if (replica.getCoreUrl().startsWith(jetty.getProxyBaseUrl().toString())) return jetty;
}
throw new IllegalArgumentException(
"Cannot find Jetty for a replica with core url " + replica.getCoreUrl());
}
+ /** Return the jetty for a node, identified by either its node name or its base URL. */
+ public JettySolrRunner getJetty(String nodeNameOrUrl) {
+ return findJetty(jettys, nodeNameOrUrl);
+ }
+
+ /** Returns the runner among {@code runners} identified by node name or base URL. */
+ static JettySolrRunner findJetty(Collection<JettySolrRunner> runners, String nodeNameOrUrl) {
+ for (JettySolrRunner jetty : runners) {
+ if (jetty.isStopped()) continue;
+ if (nodeNameOrUrl.equals(jetty.getNodeName())
+ || nodeNameOrUrl.equals(jetty.getBaseUrl().toString())) {
+ return jetty;
+ }
+ }
+ throw new IllegalArgumentException("Cannot find Jetty for node " + nodeNameOrUrl);
+ }
+
+ /**
+ * Returns the jetty-owned client for the node hosting {@code replica}, scoped to that replica's
+ * core. The caller must not close the returned client -- it delegates to the jetty's own shared
+ * client, which the jetty itself owns.
+ */
+ public SolrClient getSolrClient(Replica replica) {
+ return new CollectionScopedSolrClient(
+ getReplicaJetty(replica).getSolrClient(), replica.getCoreName());
+ }
+
/** Make the zookeeper session on a particular jetty lose connection and expire */
public void expireZkSession(JettySolrRunner jetty) {
ChaosMonkey.expireSession(jetty, zkServer);
diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/api/collections/AbstractCollectionsAPIDistributedZkTestBase.java b/solr/test-framework/src/java/org/apache/solr/cloud/api/collections/AbstractCollectionsAPIDistributedZkTestBase.java
index 59a66bec4b2..febda3ee265 100644
--- a/solr/test-framework/src/java/org/apache/solr/cloud/api/collections/AbstractCollectionsAPIDistributedZkTestBase.java
+++ b/solr/test-framework/src/java/org/apache/solr/cloud/api/collections/AbstractCollectionsAPIDistributedZkTestBase.java
@@ -560,9 +560,8 @@ public abstract class AbstractCollectionsAPIDistributedZkTestBase extends SolrCl
for (Slice shard : collectionState) {
for (Replica replica : shard) {
CoreStatusResponse.SingleCoreData coreStatus;
- try (SolrClient server = getHttpSolrClient(replica.getBaseUrl())) {
- coreStatus = CoreAdminRequest.getCoreStatus(replica.getCoreName(), false, server);
- }
+ SolrClient server = cluster.getSolrClient(replica);
+ coreStatus = CoreAdminRequest.getCoreStatus(replica.getCoreName(), false, server);
long before = coreStatus.startTime.getTime();
urlToTime.put(replica.getCoreUrl(), before);
}
@@ -640,12 +639,10 @@ public abstract class AbstractCollectionsAPIDistributedZkTestBase extends SolrCl
assertNotNull(newReplica);
cluster.waitForActiveCollection(collectionName, 2, 6);
- try (SolrClient coreclient = getHttpSolrClient(newReplica.getBaseUrl())) {
- CoreAdminResponse status = CoreAdminRequest.getStatus(newReplica.getStr("core"), coreclient);
- final var coreStatus = status.getCoreStatus(newReplica.getStr("core"));
- String instanceDirStr = coreStatus.instanceDir;
- assertEquals(instanceDirStr, instancePath.toString());
- }
+ SolrClient coreclient = cluster.getSolrClient(newReplica);
+ CoreAdminResponse status = CoreAdminRequest.getStatus(newReplica.getStr("core"), coreclient);
+ final var coreStatus = status.getCoreStatus(newReplica.getStr("core"));
+ assertEquals(coreStatus.instanceDir, instancePath.toString());
// Test to make sure we can't create another replica with an existing core_name of that
// collection
diff --git a/solr/test-framework/src/java/org/apache/solr/embedded/JettySolrRunner.java b/solr/test-framework/src/java/org/apache/solr/embedded/JettySolrRunner.java
index bd97bf8c690..aea83190d9f 100644
--- a/solr/test-framework/src/java/org/apache/solr/embedded/JettySolrRunner.java
+++ b/solr/test-framework/src/java/org/apache/solr/embedded/JettySolrRunner.java
@@ -690,7 +690,7 @@ public class JettySolrRunner implements SolrBackend {
if (getCoreContainer() != null) {
final var coreStatusReq = new CoresApi.GetAllCoreStatus();
coreStatusReq.setIndexInfo(true);
- try (final var client = newClient()) {
+ try (final var client = new HttpJettySolrClient.Builder(getBaseUrl().toString()).build()) {
final var coreStatusRsp = coreStatusReq.process(client);
Utils.writeJson(coreStatusRsp, pw, true);
} catch (SolrServerException | IOException e) {
@@ -785,21 +785,6 @@ public class JettySolrRunner implements SolrBackend {
}
}
- /**
- * @deprecated Use {@link #getSolrClient()} or {@link #newClient(int, int)} instead.
- */
- @Deprecated(since = "10.1")
- public HttpJettySolrClient newClient() {
- return new HttpJettySolrClient.Builder(getBaseUrl().toString()).build();
- }
-
- public HttpJettySolrClient newClient(int connectionTimeoutMillis, int socketTimeoutMillis) {
- return new HttpJettySolrClient.Builder(getBaseUrl().toString())
- .withConnectionTimeout(connectionTimeoutMillis, TimeUnit.MILLISECONDS)
- .withIdleTimeout(socketTimeoutMillis, TimeUnit.MILLISECONDS)
- .build();
- }
-
// --------------------------------------------------------------
// --------------------------------------------------------------
diff --git a/solr/test-framework/src/java/org/apache/solr/util/SolrJMetricTestUtils.java b/solr/test-framework/src/java/org/apache/solr/util/SolrJMetricTestUtils.java
index 7669c3755cf..f589887b49e 100644
--- a/solr/test-framework/src/java/org/apache/solr/util/SolrJMetricTestUtils.java
+++ b/solr/test-framework/src/java/org/apache/solr/util/SolrJMetricTestUtils.java
@@ -26,6 +26,7 @@ import org.apache.solr.client.solrj.jetty.HttpJettySolrClient;
import org.apache.solr.client.solrj.request.MetricsRequest;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
+import org.apache.solr.embedded.JettySolrRunner;
public final class SolrJMetricTestUtils {
@@ -72,10 +73,11 @@ public final class SolrJMetricTestUtils {
}
}
- public static Double getNumNodeRequestErrors(String baseUrl, String category, String handler)
+ public static Double getNumNodeRequestErrors(
+ JettySolrRunner runner, String category, String handler)
throws SolrServerException, IOException {
- try (var client = new HttpJettySolrClient.Builder(baseUrl).build()) {
+ try (var client = runner.newSolrClient(null)) {
var req = new MetricsRequest(SolrParams.of("wt", "prometheus"));
NamedList<Object> resp = client.request(req);
diff --git a/solr/test-framework/src/test/org/apache/solr/embedded/TestJettySolrRunner.java b/solr/test-framework/src/test/org/apache/solr/embedded/TestJettySolrRunner.java
index 230a279864d..a874787c0ea 100644
--- a/solr/test-framework/src/test/org/apache/solr/embedded/TestJettySolrRunner.java
+++ b/solr/test-framework/src/test/org/apache/solr/embedded/TestJettySolrRunner.java
@@ -55,13 +55,12 @@ public class TestJettySolrRunner extends SolrTestCaseJ4 {
try {
runner.start();
- try (SolrClient client = getHttpSolrClient(runner.getBaseUrl().toString())) {
- CoreAdminRequest.Create createReq = new CoreAdminRequest.Create();
- createReq.setCoreName("newcore");
- createReq.setConfigSet("minimal");
+ SolrClient client = runner.getSolrClient();
+ CoreAdminRequest.Create createReq = new CoreAdminRequest.Create();
+ createReq.setCoreName("newcore");
+ createReq.setConfigSet("minimal");
- client.request(createReq);
- }
+ client.request(createReq);
assertTrue(Files.exists(coresDir.resolve("newcore").resolve("core.properties")));
diff --git a/solr/webapp/src/test/org/apache/solr/webapp/AdminUiCoreAdminStandaloneTest.java b/solr/webapp/src/test/org/apache/solr/webapp/AdminUiCoreAdminStandaloneTest.java
index 0508fd636e7..1707bc9f2a3 100644
--- a/solr/webapp/src/test/org/apache/solr/webapp/AdminUiCoreAdminStandaloneTest.java
+++ b/solr/webapp/src/test/org/apache/solr/webapp/AdminUiCoreAdminStandaloneTest.java
@@ -95,12 +95,11 @@ public class AdminUiCoreAdminStandaloneTest extends AdminUiStandaloneTestBase {
@Test
public void testSwapCoresViaUi() throws Exception {
// make the cores distinguishable: swapa gets one document, swapb stays empty
- try (var client = standaloneJetty.newClient()) {
- var doc = new SolrInputDocument();
- doc.addField("id", "swap-doc");
- client.add("swapa", doc);
- client.commit("swapa");
- }
+ var client = standaloneJetty.getSolrClient();
+ var doc = new SolrInputDocument();
+ doc.addField("id", "swap-doc");
+ client.add("swapa", doc);
+ client.commit("swapa");
assertEquals(1, numDocs("swapa"));
assertEquals(0, numDocs("swapb"));
@@ -136,8 +135,12 @@ public class AdminUiCoreAdminStandaloneTest extends AdminUiStandaloneTestBase {
}
private long numDocs(String coreName) {
- try (var client = standaloneJetty.newClient()) {
- return client.query(coreName, new SolrQuery("*:*")).getResults().getNumFound();
+ try {
+ return standaloneJetty
+ .getSolrClient()
+ .query(coreName, new SolrQuery("*:*"))
+ .getResults()
+ .getNumFound();
} catch (Exception e) {
throw new RuntimeException(e);
}
diff --git a/solr/webapp/src/test/org/apache/solr/webapp/AdminUiQueryScreenTest.java b/solr/webapp/src/test/org/apache/solr/webapp/AdminUiQueryScreenTest.java
index 86ee2ba1fe0..08b9d18e6f1 100644
--- a/solr/webapp/src/test/org/apache/solr/webapp/AdminUiQueryScreenTest.java
+++ b/solr/webapp/src/test/org/apache/solr/webapp/AdminUiQueryScreenTest.java
@@ -93,9 +93,7 @@ public class AdminUiQueryScreenTest extends AdminUiTestBase {
setParams.setContentWriter(
new RequestWriter.StringPayloadContentWriter(
"{\"set\":{\"" + paramset + "\":{\"rows\":\"2\"}}}", CommonParams.JSON_MIME));
- try (SolrClient client = cluster.getJettySolrRunner(0).newClient()) {
- client.request(setParams);
- }
+ cluster.getJettySolrRunner(0).getSolrClient().request(setParams);
openPage(COLLECTION + "/query", By.id("query"));
chosenSelect("useParams", paramset);
diff --git a/solr/webapp/src/test/org/apache/solr/webapp/AdminUiReplicationStandaloneTest.java b/solr/webapp/src/test/org/apache/solr/webapp/AdminUiReplicationStandaloneTest.java
index d7e78d7f0d0..3434feebb0e 100644
--- a/solr/webapp/src/test/org/apache/solr/webapp/AdminUiReplicationStandaloneTest.java
+++ b/solr/webapp/src/test/org/apache/solr/webapp/AdminUiReplicationStandaloneTest.java
@@ -91,15 +91,14 @@ public class AdminUiReplicationStandaloneTest extends AdminUiStandaloneTestBase
"polling should be disabled", () -> "true".equals(followerDetail("isPollingDisabled")));
// index documents on the leader; the follower does not poll them
- try (var client = leaderJetty.newClient()) {
- for (int i = 1; i <= 2; i++) {
- SolrInputDocument doc = new SolrInputDocument();
- doc.addField("id", "repl-doc-" + i);
- doc.addField("name", "replicated");
- client.add(CORE, doc);
- }
- client.commit(CORE);
+ var client = leaderJetty.getSolrClient();
+ for (int i = 1; i <= 2; i++) {
+ SolrInputDocument doc = new SolrInputDocument();
+ doc.addField("id", "repl-doc-" + i);
+ doc.addField("name", "replicated");
+ client.add(CORE, doc);
}
+ client.commit(CORE);
// replicate on demand and watch the docs arrive on the follower
click(By.cssSelector("#replication button.replicate-now"));
@@ -151,8 +150,12 @@ public class AdminUiReplicationStandaloneTest extends AdminUiStandaloneTestBase
}
private long followerNumDocs() {
- try (var client = standaloneJetty.newClient()) {
- return client.query(CORE, new SolrQuery("*:*")).getResults().getNumFound();
+ try {
+ return standaloneJetty
+ .getSolrClient()
+ .query(CORE, new SolrQuery("*:*"))
+ .getResults()
+ .getNumFound();
} catch (Exception e) {
throw new RuntimeException(e);
}
diff --git a/solr/webapp/src/test/org/apache/solr/webapp/AdminUiSecurityAuthTest.java b/solr/webapp/src/test/org/apache/solr/webapp/AdminUiSecurityAuthTest.java
index 8ac87a18af5..a3269ccfc3f 100644
--- a/solr/webapp/src/test/org/apache/solr/webapp/AdminUiSecurityAuthTest.java
+++ b/solr/webapp/src/test/org/apache/solr/webapp/AdminUiSecurityAuthTest.java
@@ -18,7 +18,6 @@ package org.apache.solr.webapp;
import java.util.List;
import java.util.Map;
-import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.request.GenericSolrRequest;
import org.apache.solr.common.util.NamedList;
@@ -134,11 +133,11 @@ public class AdminUiSecurityAuthTest extends AdminUiTestBase {
/** Returns the authorization config as fetched with credentials. */
private NamedList<Object> authorizationApi() {
- try (SolrClient client = cluster.getJettySolrRunner(0).newClient()) {
+ try {
GenericSolrRequest req =
new GenericSolrRequest(SolrRequest.METHOD.GET, "/admin/authorization", params());
req.setBasicAuthCredentials(USER, PASS);
- return client.request(req);
+ return cluster.getJettySolrRunner(0).getSolrClient().request(req);
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -158,11 +157,11 @@ public class AdminUiSecurityAuthTest extends AdminUiTestBase {
/** Checks via the authentication API (with credentials) whether the user exists. */
private boolean userExists(String user) {
- try (SolrClient client = cluster.getJettySolrRunner(0).newClient()) {
+ try {
GenericSolrRequest req =
new GenericSolrRequest(SolrRequest.METHOD.GET, "/admin/authentication", params());
req.setBasicAuthCredentials(USER, PASS);
- NamedList<Object> response = client.request(req);
+ NamedList<Object> response = cluster.getJettySolrRunner(0).getSolrClient().request(req);
Map<?, ?> authentication = (Map<?, ?>) response.get("authentication");
Map<?, ?> credentials = (Map<?, ?>) authentication.get("credentials");
return credentials.containsKey(user);
diff --git a/solr/webapp/src/test/org/apache/solr/webapp/AdminUiTestBase.java b/solr/webapp/src/test/org/apache/solr/webapp/AdminUiTestBase.java
index 54e1a79d424..a0f6469aa17 100644
--- a/solr/webapp/src/test/org/apache/solr/webapp/AdminUiTestBase.java
+++ b/solr/webapp/src/test/org/apache/solr/webapp/AdminUiTestBase.java
@@ -38,7 +38,6 @@ import org.apache.lucene.tests.util.QuickPatchThreadsFilter;
import org.apache.lucene.util.SuppressForbidden;
import org.apache.solr.SolrIgnoredThreadsFilter;
import org.apache.solr.SolrTestCaseJ4;
-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.request.CollectionAdminRequest;
@@ -382,9 +381,9 @@ public abstract class AdminUiTestBase extends SolrCloudTestCase {
throws IOException, SolrServerException {
ensureCloudCluster();
JettySolrRunner jetty = standaloneMode ? standaloneJetty : cluster.getJettySolrRunner(0);
- try (SolrClient client = jetty.newClient()) {
- return client.request(new GenericSolrRequest(SolrRequest.METHOD.GET, path, params));
- }
+ return jetty
+ .getSolrClient()
+ .request(new GenericSolrRequest(SolrRequest.METHOD.GET, path, params));
}
/**
(solr) 16/17: Fix misleading deprecation warning for SOLR_HOST_ADVERTISE (#4715)
Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
commit ee5120a6c9ddad2922c98e86416603c8c1477701
Author: msternermxy <81...@users.noreply.github.com>
AuthorDate: Wed Sep 9 13:29:28 2026 +0200
Fix misleading deprecation warning for SOLR_HOST_ADVERTISE (#4715)
Co-authored-by: Eric Pugh <ep...@opensourceconnections.com>
(cherry picked from commit e8463623f9dc16a7486bfab29c351a8bb9a24001)
---
changelog/unreleased/fix-solr-18337.yml | 8 ++
.../apache/solr/util/tracing/SimplePropagator.java | 6 +-
.../solr/opentelemetry/OtelTracerConfigurator.java | 4 +-
.../CustomTestOtelTracerConfigurator.java | 4 +-
.../opentelemetry/OtelTracerConfiguratorTest.java | 2 +-
.../src/resources/EnvToSyspropMappings.properties | 29 ++---
.../org/apache/solr/common/util/EnvUtilsTest.java | 130 ++++++++++++++++++---
7 files changed, 142 insertions(+), 41 deletions(-)
diff --git a/changelog/unreleased/fix-solr-18337.yml b/changelog/unreleased/fix-solr-18337.yml
new file mode 100644
index 00000000000..155a9cb1154
--- /dev/null
+++ b/changelog/unreleased/fix-solr-18337.yml
@@ -0,0 +1,8 @@
+title: Fix misleading deprecation warning for SOLR_HOST_ADVERTISE
+type: fixed
+authors:
+ - name: Eric Pugh
+ - name: Mikael Sterner
+links:
+ - name: SOLR-18337
+ url: https://issues.apache.org/jira/browse/SOLR-18337
diff --git a/solr/core/src/java/org/apache/solr/util/tracing/SimplePropagator.java b/solr/core/src/java/org/apache/solr/util/tracing/SimplePropagator.java
index a626e55f707..6e0fc91179c 100644
--- a/solr/core/src/java/org/apache/solr/util/tracing/SimplePropagator.java
+++ b/solr/core/src/java/org/apache/solr/util/tracing/SimplePropagator.java
@@ -21,14 +21,11 @@ import io.opentelemetry.context.ContextKey;
import io.opentelemetry.context.propagation.TextMapGetter;
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.context.propagation.TextMapSetter;
-import java.lang.invoke.MethodHandles;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.solr.common.util.EnvUtils;
import org.apache.solr.logging.MDCLoggingContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* Simple Http Header Propagator. When enabled, this will only propagate the trace id from the
@@ -39,10 +36,9 @@ import org.slf4j.LoggerFactory;
* replacing/upgrading once that becomes generally available
*/
public class SimplePropagator implements TextMapPropagator {
- private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private static final String TRACE_HOST_NAME =
- EnvUtils.getProperty("solr.traceHostName", EnvUtils.getProperty("host"));
+ EnvUtils.getProperty("solr.traceHostName", EnvUtils.getProperty("solr.host.advertise"));
private static final TextMapPropagator INSTANCE = new SimplePropagator();
private static final ContextKey<String> TRACE_ID_KEY = ContextKey.named("trace_id");
diff --git a/solr/modules/opentelemetry/src/java/org/apache/solr/opentelemetry/OtelTracerConfigurator.java b/solr/modules/opentelemetry/src/java/org/apache/solr/opentelemetry/OtelTracerConfigurator.java
index ae1aa625991..d3cb53f5f74 100644
--- a/solr/modules/opentelemetry/src/java/org/apache/solr/opentelemetry/OtelTracerConfigurator.java
+++ b/solr/modules/opentelemetry/src/java/org/apache/solr/opentelemetry/OtelTracerConfigurator.java
@@ -74,8 +74,8 @@ public class OtelTracerConfigurator extends OpenTelemetryConfigurator {
setDefaultIfNotConfigured("OTEL_EXPORTER_OTLP_PROTOCOL", "http/protobuf");
setDefaultIfNotConfigured("OTEL_TRACES_SAMPLER", "parentbased_always_on");
setDefaultIfNotConfigured("OTEL_PROPAGATORS", "tracecontext,baggage");
- if (EnvUtils.getProperty("host") != null) {
- addOtelResourceAttributes(Map.of("host.name", EnvUtils.getProperty("host")));
+ if (EnvUtils.getProperty("solr.host.advertise") != null) {
+ addOtelResourceAttributes(Map.of("host.name", EnvUtils.getProperty("solr.host.advertise")));
}
final String currentConfig = getCurrentOtelConfigAsString();
diff --git a/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/CustomTestOtelTracerConfigurator.java b/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/CustomTestOtelTracerConfigurator.java
index c9501edd810..3790bc7c61b 100644
--- a/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/CustomTestOtelTracerConfigurator.java
+++ b/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/CustomTestOtelTracerConfigurator.java
@@ -32,8 +32,8 @@ public class CustomTestOtelTracerConfigurator extends OtelTracerConfigurator {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
static {
- if (EnvUtils.getProperty("host") == null) {
- System.setProperty("host", "localhost");
+ if (EnvUtils.getProperty("solr.host.advertise") == null) {
+ System.setProperty("solr.host.advertise", "localhost");
}
}
diff --git a/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/OtelTracerConfiguratorTest.java b/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/OtelTracerConfiguratorTest.java
index a1cfc7bf10d..0818e9961a5 100644
--- a/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/OtelTracerConfiguratorTest.java
+++ b/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/OtelTracerConfiguratorTest.java
@@ -39,7 +39,7 @@ public class OtelTracerConfiguratorTest extends SolrTestCaseJ4 {
System.setProperty("otelnothere", "bar");
System.setProperty("otel.k1", "prop-k1");
System.setProperty("otel.k3", "prop-k3");
- System.setProperty("host", "my.solr.host");
+ System.setProperty("solr.host.advertise", "my.solr.host");
instance = new OtelTracerConfigurator(currentEnv);
}
diff --git a/solr/solrj/src/resources/EnvToSyspropMappings.properties b/solr/solrj/src/resources/EnvToSyspropMappings.properties
index 176bccf7a13..61fabd7ea8f 100644
--- a/solr/solrj/src/resources/EnvToSyspropMappings.properties
+++ b/solr/solrj/src/resources/EnvToSyspropMappings.properties
@@ -1,17 +1,18 @@
# Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements; and to You under the Apache License, Version 2.0.
#
-# Mapping from Environment variable to system property
-# This file only contains non-standard mappings that do not follow the standard naming convention
-# Map to nothing to avoid setting any system property for the env.variable
-# CamelCase properties are mapped to dot separated lowercase
-# This way, env SOLR_FOO_BAR will also match property 'solr.foo.bar' without a mapping in this file
-# TODO: Deprecate non-standard sysprops and standardize on solr.foo.bar in Solr 10
+# Mapping from Environment variable to system property.
+# This file only contains non-standard mappings that do not follow the standard naming convention.
+# Map to nothing to avoid setting any system property for the env.variable.
+# Env var names are mapped to sys props by lowercasing and replacing '_' with '.', so
+# SOLR_FOO_BAR will match property 'solr.foo.bar' without needing a mapping in this file.
+# Separately, sysprop lookups (EnvUtils.getProperty) also fall back from camelCase to
+# dot-separated form (e.g. 'solr.logLevel' <-> 'solr.log.level'), independent of this file.
+# TODO: Deprecate non-standard sysprops and standardize on solr.foo.bar.
AWS_PROFILE=aws.profile
-SOLR_ALWAYS_ON_TRACE_ID=solr.alwaysOnTraceId
-SOLR_AUTH_JWT_ALLOW_OUTBOUND_HTTP=solr.auth.jwt.allowOutboundHttp
-SOLR_HIDDEN_SYS_PROPS=solr.hiddenSysProps
+SOLR_ALWAYS_ON_TRACE_ID=solr.tracing.always.on.enabled
+SOLR_AUTH_JWT_ALLOW_OUTBOUND_HTTP=solr.auth.jwt.outbound.http.enabled
+SOLR_HIDDEN_SYS_PROPS=solr.responses.hidden.sys.props
SOLR_HOME=solr.solr.home
-SOLR_HOST_ADVERTISE=host
SOLR_HTTP_DISABLE_COOKIES=solr.http.disableCookies
# Couldn't we just use solr.ip.allowlist everywhere instead of solr.jetty.inetaccess.includes?
SOLR_IP_ALLOWLIST=solr.jetty.inetaccess.includes
@@ -20,8 +21,8 @@ SOLR_OTEL_DEFAULT_CONFIGURATOR=solr.otelDefaultConfigurator
SOLR_TIMEZONE=user.timezone
SOLR_TIP=solr.install.dir
SOLR_TIP_SYM=solr.install.symDir
-ZK_CLIENT_TIMEOUT=zkClientTimeout
-ZK_CREATE_CHROOT=createZkChroot
+ZK_CLIENT_TIMEOUT=solr.zookeeper.client.timeout
+ZK_CREATE_CHROOT=solr.zookeeper.chroot.create
ZK_CREDENTIALS_INJECTOR=zkCredentialsInjector
ZK_CREDENTIALS_PROVIDER=zkCredentialsProvider
ZK_DIGEST=PASSWORD=zkDigestPassword
@@ -32,8 +33,8 @@ ZK_DIGEST_USERNAME=zkDigestUsername
ZK_HOST=zkHost
# Commonly used in solr.xml
-SOLR_ALLOW_PATHS=solr.allowPaths
-SOLR_ALLOW_URLS=solr.allowUrls
+SOLR_ALLOW_PATHS=solr.security.allow.paths
+SOLR_ALLOW_URLS=solr.security.allow.urls
SOLR_MAX_BOOLEAN_CLAUSES=solr.max.booleanClauses
SOLR_METRICS_ENABLED=metricsEnabled
SOLR_SHARED_LIB=solr.sharedLib
diff --git a/solr/solrj/src/test/org/apache/solr/common/util/EnvUtilsTest.java b/solr/solrj/src/test/org/apache/solr/common/util/EnvUtilsTest.java
index 346aee08b42..2d425c5fe18 100644
--- a/solr/solrj/src/test/org/apache/solr/common/util/EnvUtilsTest.java
+++ b/solr/solrj/src/test/org/apache/solr/common/util/EnvUtilsTest.java
@@ -17,27 +17,35 @@
package org.apache.solr.common.util;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Properties;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
import org.apache.solr.SolrTestCase;
+import org.apache.solr.util.LogListener;
import org.junit.BeforeClass;
import org.junit.Test;
public class EnvUtilsTest extends SolrTestCase {
private static final Map<String, String> ENV =
- Map.of(
- "SOLR_HOME", "/home/solr",
- "SOLR_PORT_LISTEN", "8983",
- "SOLR_HOST_ADVERTISE", "localhost",
- "SOLR_LOG_LEVEL", "INFO",
- "SOLR_BOOLEAN", "true",
- "SOLR_LONG", "1234567890",
- "SOLR_COMMASEP", "one,two, three",
- "SOLR_JSON_LIST", "[\"one\", \"two\", \"three\"]",
- "SOLR_ALWAYS_ON_TRACE_ID", "true",
- "SOLR_STR_WITH_NEWLINE", "foo\nbar,baz");
+ Map.ofEntries(
+ Map.entry("SOLR_HOME", "/home/solr"),
+ Map.entry("SOLR_PORT_LISTEN", "8983"),
+ Map.entry("SOLR_HOST_ADVERTISE", "localhost"),
+ Map.entry("SOLR_LOG_LEVEL", "INFO"),
+ Map.entry("SOLR_BOOLEAN", "true"),
+ Map.entry("SOLR_LONG", "1234567890"),
+ Map.entry("SOLR_COMMASEP", "one,two, three"),
+ Map.entry("SOLR_JSON_LIST", "[\"one\", \"two\", \"three\"]"),
+ Map.entry("SOLR_ALWAYS_ON_TRACE_ID", "true"),
+ Map.entry("SOLR_STR_WITH_NEWLINE", "foo\nbar,baz"),
+ Map.entry("SOLR_TIP", "/opt/solr"),
+ Map.entry("SOLR_TIP_SYM", "/opt/solr-9.9.9"));
@BeforeClass
public static void beforeClass() throws Exception {
@@ -71,16 +79,17 @@ public class EnvUtilsTest extends SolrTestCase {
assertEquals("INFO", EnvUtils.getProperty("solr.logLevel"));
assertEquals("INFO", EnvUtils.getProperty("solr.LogLevel"));
assertEquals(Long.valueOf(1234567890L), EnvUtils.getPropertyAsLong("solrLong"));
- assertEquals(Boolean.TRUE, EnvUtils.getPropertyAsBool("solr.alwaysOnTraceId"));
- assertEquals(Boolean.TRUE, EnvUtils.getPropertyAsBool("solr.always.on.trace.id"));
+ assertEquals(Boolean.TRUE, EnvUtils.getPropertyAsBool("solr.tracing.always.on.enabled"));
}
@Test
public void testEnvsWithCustomKeyNameMappings() {
- // These have different names than the environment variables
- assertEquals(ENV.get("SOLR_HOME"), EnvUtils.getProperty("solr.solr.home"));
- assertEquals(ENV.get("SOLR_HOST_ADVERTISE"), EnvUtils.getProperty("host"));
- assertEquals(ENV.get("SOLR_LOGS_DIR"), EnvUtils.getProperty("solr.logs.dir"));
+ // These map to a sysprop name that doesn't follow the standard SOLR_FOO_BAR -> solr.foo.bar
+ // convention (see EnvToSyspropMappings.properties). Assert against literal expected values,
+ // not ENV.get(...), so a broken/missing mapping would actually be caught here.
+ assertEquals("/home/solr", EnvUtils.getProperty("solr.solr.home"));
+ assertEquals("/opt/solr", EnvUtils.getProperty("solr.install.dir"));
+ assertEquals("/opt/solr-9.9.9", EnvUtils.getProperty("solr.install.symDir"));
}
@Test
@@ -143,4 +152,91 @@ public class EnvUtilsTest extends SolrTestCase {
EnvUtils.init(false, env, defaultProps);
assertEquals(false, EnvUtils.getPropertyAsBool("solr.ui.enabled"));
}
+
+ /**
+ * These env vars must map directly to their current sysprop name, not to a legacy/intermediate
+ * name that DeprecatedSystemPropertyMappings.properties also treats as deprecated -- otherwise
+ * EnvUtils' own deprecation-forwarding logic trips on itself and logs a confusing warning, even
+ * though the value still resolves correctly via that indirection. A value-only assertion wouldn't
+ * catch a regression here, since the value resolves fine either way -- the warning is the actual
+ * symptom, so this asserts on both.
+ *
+ * <p>SOLR_ALWAYS_ON_TRACE_ID is the same pattern (see {@link #getPropWithCamelCase}) but is
+ * deliberately excluded here: it shares a target sysprop with that other test, and this test
+ * would clobber it with a non-boolean value depending on random test execution order.
+ *
+ * <p>The LogListener is scoped to only these six properties' names (rather than listening for
+ * *any* WARN from EnvUtils) because {@code init()} is called here with the real, live {@code
+ * System.getProperties()} -- its deprecated-property-forwarding loop rescans *all* current system
+ * properties every time, so leftover deprecated markers set by unrelated tests earlier in this
+ * same suite/JVM (e.g. {@link #testFlippingDisabledToEnabledPropertyName}) would otherwise be
+ * re-detected and re-warned-about here too, causing flaky, unrelated failures.
+ */
+ @Test
+ public void envToSyspropMappingsDoNotTriggerDeprecationWarnings() {
+ var envVarToExpectedSysprop =
+ Map.of(
+ "ZK_CLIENT_TIMEOUT", "solr.zookeeper.client.timeout",
+ "ZK_CREATE_CHROOT", "solr.zookeeper.chroot.create",
+ "SOLR_AUTH_JWT_ALLOW_OUTBOUND_HTTP", "solr.auth.jwt.outbound.http.enabled",
+ "SOLR_HIDDEN_SYS_PROPS", "solr.responses.hidden.sys.props",
+ "SOLR_ALLOW_PATHS", "solr.security.allow.paths",
+ "SOLR_ALLOW_URLS", "solr.security.allow.urls");
+ var onlyOurTargets =
+ Pattern.compile(
+ envVarToExpectedSysprop.values().stream()
+ .map(Pattern::quote)
+ .collect(Collectors.joining("|")));
+
+ try (LogListener warnLog = LogListener.warn(EnvUtils.class).regex(onlyOurTargets)) {
+ for (var entry : envVarToExpectedSysprop.entrySet()) {
+ EnvUtils.init(true, Map.of(entry.getKey(), entry.getKey()), System.getProperties());
+ assertEquals(
+ "env var " + entry.getKey() + " should map to " + entry.getValue(),
+ entry.getKey(),
+ EnvUtils.getProperty(entry.getValue()));
+ }
+ assertEquals(
+ "No deprecated-property warnings should be logged for these mappings",
+ 0,
+ warnLog.getCount());
+ }
+ }
+
+ @Test
+ public void envToSyspropMappingsDoNotMapToDeprecatedSystemProperties() throws IOException {
+ Properties envMappings = loadProperties("EnvToSyspropMappings.properties");
+ Properties deprecatedMappings = loadProperties("DeprecatedSystemPropertyMappings.properties");
+ Map<String, String> reverseDeprecatedMappings =
+ deprecatedMappings.entrySet().stream()
+ .collect(Collectors.toMap(e -> (String) e.getValue(), e -> (String) e.getKey()));
+
+ for (String envVar : envMappings.stringPropertyNames()) {
+ String sysProp = envMappings.getProperty(envVar);
+ String newSysProp = reverseDeprecatedMappings.get(sysProp);
+ if (newSysProp != null) {
+ fail(
+ "expected <"
+ + sysProp
+ + "> "
+ + "mapped from <"
+ + envVar
+ + "> to not be deprecated, "
+ + "but it was replaced by <"
+ + newSysProp
+ + ">");
+ }
+ }
+ }
+
+ private static Properties loadProperties(String resourceName) throws IOException {
+ Properties properties = new Properties();
+ try (var resource =
+ new InputStreamReader(
+ EnvUtils.class.getClassLoader().getResourceAsStream(resourceName),
+ StandardCharsets.UTF_8)) {
+ properties.load(resource);
+ }
+ return properties;
+ }
}
(solr) 11/17: SOLR-18364: Remove deprecated SolrCore.isWriterLocked(Directory) (#4784)
Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
commit dad6ee50e2b5bf3fc77363e9f8a47edd0b43c001
Author: Serhiy Bzhezytskyy <me...@serhiy-bzhezytskyy.com>
AuthorDate: Wed Sep 9 04:16:52 2026 +0300
SOLR-18364: Remove deprecated SolrCore.isWriterLocked(Directory) (#4784)
(cherry picked from commit bc9d070c666be4fc536b10da881664be96b1afb4)
---
.../src/java/org/apache/solr/core/SolrCore.java | 56 +++-------------------
.../org/apache/solr/update/SolrIndexWriter.java | 12 +++++
2 files changed, 18 insertions(+), 50 deletions(-)
diff --git a/solr/core/src/java/org/apache/solr/core/SolrCore.java b/solr/core/src/java/org/apache/solr/core/SolrCore.java
index 2fae19650a7..fe3bf4c9fe8 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrCore.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java
@@ -80,7 +80,6 @@ import org.apache.lucene.store.Directory;
import org.apache.lucene.store.IOContext;
import org.apache.lucene.store.IndexInput;
import org.apache.lucene.store.IndexOutput;
-import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.util.ResourceLoader;
import org.apache.solr.client.solrj.response.JavaBinResponseParser;
import org.apache.solr.cloud.CloudDescriptor;
@@ -854,59 +853,16 @@ public class SolrCore implements SolrInfoBean, Closeable {
this.indexReaderFactory = indexReaderFactory;
}
- // protect via synchronized(SolrCore.class)
- private static Set<String> dirs = new HashSet<>();
-
- /**
- * Returns <code>true</code> iff the index in the named directory is currently locked.
- *
- * @param directory the directory to check for a lock
- * @throws IOException if there is a low-level IO error
- * @deprecated Use of this method can only lead to race conditions. Try to actually obtain a lock
- * instead.
- */
- @Deprecated(since = "7.0")
- private static boolean isWriterLocked(Directory directory) throws IOException {
- try {
- directory.obtainLock(IndexWriter.WRITE_LOCK_NAME).close();
- return false;
- } catch (LockObtainFailedException failed) {
- return true;
- }
- }
-
- void initIndex(boolean passOnPreviousState, boolean reload) throws IOException {
+ /** Also fails fast (LockObtainFailedException) if an existing index directory is locked. */
+ void initIndex(boolean reload) throws IOException {
String indexDir = getNewIndexDir();
boolean indexExists = getDirectoryFactory().exists(indexDir);
- boolean firstTime;
- synchronized (SolrCore.class) {
- firstTime = dirs.add(getDirectoryFactory().normalize(indexDir));
- }
initIndexReaderFactory();
- if (indexExists && firstTime && !passOnPreviousState) {
- final String lockType = getSolrConfig().indexConfig.lockType;
- Directory dir = directoryFactory.get(indexDir, DirContext.DEFAULT, lockType);
- try {
- if (isWriterLocked(dir)) {
- log.error(
- "Solr index directory '{}' is locked (lockType={}). Throwing exception.",
- indexDir,
- lockType);
- throw new LockObtainFailedException(
- "Index dir '"
- + indexDir
- + "' of core '"
- + name
- + "' is already locked. "
- + "The most likely cause is another Solr server (or another solr core in this server) "
- + "also configured to use this directory; other possible causes may be specific to lockType: "
- + lockType);
- }
- } finally {
- directoryFactory.release(dir);
- }
+ if (indexExists) {
+ // Fails fast on a lock conflict (LUCENE-6507/6508); solrCoreState caches the writer.
+ solrCoreState.getIndexWriter(this, false).decref();
}
// Create the index if it doesn't exist.
@@ -1137,7 +1093,7 @@ public class SolrCore implements SolrInfoBean, Closeable {
this.solrDelPolicy = initDeletionPolicy(delPolicy);
this.codec = initCodec(solrConfig, this.schema);
- initIndex(prev != null, reload);
+ initIndex(reload);
initWriters();
qParserPlugins.init(QParserPlugin.standardPlugins, this);
diff --git a/solr/core/src/java/org/apache/solr/update/SolrIndexWriter.java b/solr/core/src/java/org/apache/solr/update/SolrIndexWriter.java
index 8e3fef1cf75..200c85728c0 100644
--- a/solr/core/src/java/org/apache/solr/update/SolrIndexWriter.java
+++ b/solr/core/src/java/org/apache/solr/update/SolrIndexWriter.java
@@ -35,6 +35,7 @@ import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.MergePolicy;
import org.apache.lucene.index.SegmentCommitInfo;
import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.util.InfoStream;
import org.apache.solr.common.util.IOUtils;
import org.apache.solr.common.util.SuppressForbidden;
@@ -117,6 +118,17 @@ public class SolrIndexWriter extends IndexWriter {
w = new SolrIndexWriter(core, name, path, d, create, schema, config, delPolicy, codec);
w.setDirectoryFactory(directoryFactory);
return w;
+ } catch (LockObtainFailedException e) {
+ throw new LockObtainFailedException(
+ "Index dir '"
+ + path
+ + "' of core '"
+ + core.getName()
+ + "' is already locked. "
+ + "The most likely cause is another Solr server (or another solr core in this server) "
+ + "also configured to use this directory; other possible causes may be specific to lockType: "
+ + config.lockType,
+ e);
} finally {
if (null == w && null != d) {
directoryFactory.doneWithDirectory(d);
(solr) 06/17: SOLR-18411: CrossDC: Configure security properties in KafkaMirroringSink initConsumer. (#4883)
Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
commit 5aca7607cbdf5df72edb71b04d331ca41cdffd75
Author: Andrzej BiaĆecki <ab...@apache.org>
AuthorDate: Tue Sep 8 18:53:24 2026 +0200
SOLR-18411: CrossDC: Configure security properties in KafkaMirroringSink initConsumer. (#4883)
(cherry picked from commit c43a9a56d199f9405bb0404822ddfd7c1391a936)
---
changelog/unreleased/solr-18411.yml | 8 ++
.../solr/crossdc/common/KafkaMirroringSink.java | 3 +
.../crossdc/common/KafkaMirroringSinkTest.java | 101 +++++++++++++++++++++
3 files changed, 112 insertions(+)
diff --git a/changelog/unreleased/solr-18411.yml b/changelog/unreleased/solr-18411.yml
new file mode 100644
index 00000000000..9c0db562f88
--- /dev/null
+++ b/changelog/unreleased/solr-18411.yml
@@ -0,0 +1,8 @@
+title: CrossDC KafkaProducerSink's KafkaConsumer gets no security config
+
+type: fixed
+authors:
+ - name: Andrzej Bialecki
+links:
+ - name: SOLR-18411
+ url: https://issues.apache.org/jira/browse/SOLR-18411
diff --git a/solr/modules/cross-dc/src/java/org/apache/solr/crossdc/common/KafkaMirroringSink.java b/solr/modules/cross-dc/src/java/org/apache/solr/crossdc/common/KafkaMirroringSink.java
index 8935160937f..bd7492d1947 100644
--- a/solr/modules/cross-dc/src/java/org/apache/solr/crossdc/common/KafkaMirroringSink.java
+++ b/solr/modules/cross-dc/src/java/org/apache/solr/crossdc/common/KafkaMirroringSink.java
@@ -214,6 +214,9 @@ public class KafkaMirroringSink implements RequestMirroringSink, Closeable {
conf.getInt(KafkaCrossDcConf.MAX_PARTITION_FETCH_BYTES));
kafkaConsumerProperties.put(
ConsumerConfig.REQUEST_TIMEOUT_MS_CONFIG, conf.getInt(KafkaCrossDcConf.REQUEST_TIMEOUT_MS));
+
+ KafkaCrossDcConf.addSecurityProps(conf, kafkaConsumerProperties);
+
kafkaConsumerProperties.putAll(conf.getAdditionalProperties());
return new KafkaConsumer<>(
diff --git a/solr/modules/cross-dc/src/test/org/apache/solr/crossdc/common/KafkaMirroringSinkTest.java b/solr/modules/cross-dc/src/test/org/apache/solr/crossdc/common/KafkaMirroringSinkTest.java
new file mode 100644
index 00000000000..bafded545cc
--- /dev/null
+++ b/solr/modules/cross-dc/src/test/org/apache/solr/crossdc/common/KafkaMirroringSinkTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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.crossdc.common;
+
+import static org.apache.solr.SolrTestCaseJ4.assumeWorkingMockito;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.same;
+import static org.mockito.Mockito.CALLS_REAL_METHODS;
+import static org.mockito.Mockito.mockConstruction;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import org.apache.kafka.clients.CommonClientConfigs;
+import org.apache.kafka.clients.consumer.ConsumerConfig;
+import org.apache.kafka.clients.consumer.KafkaConsumer;
+import org.apache.kafka.clients.producer.KafkaProducer;
+import org.apache.kafka.common.config.SslConfigs;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.MockedConstruction;
+import org.mockito.MockedStatic;
+
+public class KafkaMirroringSinkTest {
+
+ @BeforeClass
+ public static void ensureWorkingMockito() {
+ assumeWorkingMockito();
+ }
+
+ @Test
+ @SuppressWarnings({"rawtypes", "try"})
+ public void testSecurityPropsApplied() throws Exception {
+ Map<String, Object> properties = new HashMap<>();
+ properties.put(KafkaCrossDcConf.TOPIC_NAME, "test-topic");
+ properties.put(KafkaCrossDcConf.BOOTSTRAP_SERVERS, "localhost:9092");
+ properties.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, "SSL");
+ properties.put(SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG, "/tmp/truststore.jks");
+ properties.put(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG, "changeit");
+
+ KafkaCrossDcConf conf = new KafkaCrossDcConf(properties);
+
+ // KafkaProducer/KafkaConsumer construction is mocked out so no real client or network is used
+ // need to suppress "try" warning to ignore args that are unused on the surface
+ try (MockedConstruction<KafkaProducer> ignoredProducer = mockConstruction(KafkaProducer.class);
+ MockedConstruction<KafkaConsumer> mockedConsumer =
+ mockConstruction(
+ KafkaConsumer.class,
+ // need this topic, too
+ (mock, context) ->
+ when(mock.listTopics()).thenReturn(Map.of("test-topic", List.of())));
+ MockedStatic<KafkaCrossDcConf> mockedStatic =
+ mockStatic(KafkaCrossDcConf.class, CALLS_REAL_METHODS)) {
+
+ // collect all newly created properties
+ ArgumentCaptor<Properties> propsCaptor = ArgumentCaptor.forClass(Properties.class);
+
+ // create the sink, which will create the producer and consumer
+ // suppress "try" warning because of unused sink
+ try (KafkaMirroringSink sink = new KafkaMirroringSink(conf)) {
+ mockedStatic.verify(
+ () -> KafkaCrossDcConf.addSecurityProps(same(conf), propsCaptor.capture()), times(2));
+ }
+
+ List<Properties> allProps = propsCaptor.getAllValues();
+ Properties producerProps = allProps.get(0);
+ Properties consumerProps = allProps.get(1);
+
+ // check that the captured producer props and the consumer props are filled in
+ assertTrue(producerProps.containsKey("key.serializer"));
+ assertTrue(consumerProps.containsKey(ConsumerConfig.GROUP_ID_CONFIG));
+
+ for (Properties props : allProps) {
+ assertEquals("SSL", props.getProperty(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG));
+ assertEquals(
+ "/tmp/truststore.jks", props.getProperty(SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG));
+ assertEquals("changeit", props.getProperty(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG));
+ }
+ }
+ }
+}
(solr) 14/17: SOLR-18412: CrossDC - ZooKeeper /crossdc.properties no longer overrides solr.crossdc.kafka.* sysprops or env vars (#4884)
Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
commit ca957478839b2e03cf0a7a60732f3413c016af0b
Author: Andrzej BiaĆecki <ab...@apache.org>
AuthorDate: Wed Sep 9 11:31:27 2026 +0200
SOLR-18412: CrossDC - ZooKeeper /crossdc.properties no longer overrides solr.crossdc.kafka.* sysprops or env vars (#4884)
(cherry picked from commit 62aace94a13f1f2a6831e6b189393ceecb9195d4)
---
changelog/unreleased/SOLR-18412.yml | 8 +++
.../solr/crossdc/common/KafkaCrossDcConf.java | 13 +++-
.../apache/solr/crossdc/common/ConfUtilTest.java | 81 ++++++++++++++++++++++
3 files changed, 100 insertions(+), 2 deletions(-)
diff --git a/changelog/unreleased/SOLR-18412.yml b/changelog/unreleased/SOLR-18412.yml
new file mode 100644
index 00000000000..6fdc63a806f
--- /dev/null
+++ b/changelog/unreleased/SOLR-18412.yml
@@ -0,0 +1,8 @@
+title: CrossDC - ZooKeeper /crossdc.properties no longer overrides solr.crossdc.kafka.* sysprops or env vars
+type: fixed
+authors:
+ - name: Andrzej Bialecki
+ nick: ab
+links:
+ - name: SOLR-18412
+ url: https://issues.apache.org/jira/browse/SOLR-18412
diff --git a/solr/modules/cross-dc/src/java/org/apache/solr/crossdc/common/KafkaCrossDcConf.java b/solr/modules/cross-dc/src/java/org/apache/solr/crossdc/common/KafkaCrossDcConf.java
index 88db372683e..64dfc2cae7a 100644
--- a/solr/modules/cross-dc/src/java/org/apache/solr/crossdc/common/KafkaCrossDcConf.java
+++ b/solr/modules/cross-dc/src/java/org/apache/solr/crossdc/common/KafkaCrossDcConf.java
@@ -295,8 +295,17 @@ public class KafkaCrossDcConf extends CrossDcConf {
}
zkPropsUnprocessed.forEach(
(key, val) -> {
- if (properties.get(key) == null) {
- properties.put((String) key, val);
+ String strKey = (String) key;
+ String targetKey = strKey;
+ if (strKey.startsWith(ConfUtil.KAFKA_ENV_PREFIX)) {
+ targetKey = ConfUtil.normalizeKafkaEnvKey(strKey);
+ } else if (strKey.startsWith(ConfUtil.KAFKA_PROP_PREFIX)) {
+ targetKey = ConfUtil.normalizeKafkaSysPropKey(strKey);
+ }
+ // A JVM system property or env var pass-through override always takes precedence
+ // over the same property coming from ZooKeeper's /crossdc.properties.
+ if (properties.get(targetKey) == null) {
+ properties.put(targetKey, val);
}
});
}
diff --git a/solr/modules/cross-dc/src/test/org/apache/solr/crossdc/common/ConfUtilTest.java b/solr/modules/cross-dc/src/test/org/apache/solr/crossdc/common/ConfUtilTest.java
index 6afcc35ae2a..05591e8f8d5 100644
--- a/solr/modules/cross-dc/src/test/org/apache/solr/crossdc/common/ConfUtilTest.java
+++ b/solr/modules/cross-dc/src/test/org/apache/solr/crossdc/common/ConfUtilTest.java
@@ -426,6 +426,87 @@ public class ConfUtilTest extends SolrTestCaseJ4 {
assertEquals("lz4", conf.getAdditionalProperties().get("compression.type"));
}
+ @Test
+ public void testFillProperties_ZkOnlyKafkaPrefixPropIsNormalized() throws Exception {
+ Map<String, Object> properties = new HashMap<>();
+
+ System.setProperty(KafkaCrossDcConf.BOOTSTRAP_SERVERS, "sys-kafka:9092");
+ System.setProperty(KafkaCrossDcConf.TOPIC_NAME, "sys-topic");
+
+ Properties zkProps = new Properties();
+ zkProps.setProperty("solr.crossdc.kafka.compression.type", "zk-value");
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ OutputStreamWriter writer = new OutputStreamWriter(baos, StandardCharsets.UTF_8);
+ zkProps.store(writer, null);
+ writer.close();
+ byte[] zkData = baos.toByteArray();
+
+ when(mockZkClient.exists(anyString())).thenReturn(true);
+ when(mockZkClient.getData(anyString(), isNull(), isNull())).thenReturn(zkData);
+
+ ConfUtil.fillProperties(mockZkClient, properties);
+
+ // ZK value lands under the normalized key, not the raw solr.crossdc.kafka.* key.
+ assertEquals("zk-value", properties.get("compression.type"));
+ assertNull(properties.get("solr.crossdc.kafka.compression.type"));
+ }
+
+ @Test
+ public void testFillProperties_KafkaPrefixSysPropPrecedenceOverZk() throws Exception {
+ Map<String, Object> properties = new HashMap<>();
+
+ System.setProperty(KafkaCrossDcConf.BOOTSTRAP_SERVERS, "sys-kafka:9092");
+ System.setProperty(KafkaCrossDcConf.TOPIC_NAME, "sys-topic");
+ System.setProperty("solr.crossdc.kafka.compression.type", "sys-value");
+
+ Properties zkProps = new Properties();
+ zkProps.setProperty("solr.crossdc.kafka.compression.type", "zk-value");
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ OutputStreamWriter writer = new OutputStreamWriter(baos, StandardCharsets.UTF_8);
+ zkProps.store(writer, null);
+ writer.close();
+ byte[] zkData = baos.toByteArray();
+
+ when(mockZkClient.exists(anyString())).thenReturn(true);
+ when(mockZkClient.getData(anyString(), isNull(), isNull())).thenReturn(zkData);
+
+ ConfUtil.fillProperties(mockZkClient, properties);
+
+ assertEquals("sys-value", properties.get("compression.type"));
+ }
+
+ @Test
+ public void testFillProperties_SysPropPrecedenceOverDoubleZk() throws Exception {
+ Map<String, Object> properties = new HashMap<>();
+
+ System.setProperty(KafkaCrossDcConf.BOOTSTRAP_SERVERS, "sys-kafka:9092");
+ System.setProperty(KafkaCrossDcConf.TOPIC_NAME, "sys-topic");
+ System.setProperty("solr.crossdc.kafka.compression.type", "sys-value");
+
+ // First call, as Consumer.start() does, with no ZK client yet.
+ ConfUtil.fillProperties(null, properties);
+ assertEquals("sys-value", properties.get("compression.type"));
+
+ Properties zkProps = new Properties();
+ zkProps.setProperty("solr.crossdc.kafka.compression.type", "zk-value");
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ OutputStreamWriter writer = new OutputStreamWriter(baos, StandardCharsets.UTF_8);
+ zkProps.store(writer, null);
+ writer.close();
+ byte[] zkData = baos.toByteArray();
+
+ when(mockZkClient.exists(anyString())).thenReturn(true);
+ when(mockZkClient.getData(anyString(), isNull(), isNull())).thenReturn(zkData);
+
+ // Second call, now with the real ZK client, as Consumer.start() does.
+ ConfUtil.fillProperties(mockZkClient, properties);
+
+ assertEquals("sys-value", properties.get("compression.type"));
+ }
+
// we can't easily modify envvars, test just the key conversion in properties
@Test
public void testUnderscoreToDotsConversion() {
(solr) 05/17: DistributedUpdateProcessor: expose isLeader, setupRequest (#4878)
Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
commit 21e8d021e780b764d8b3668f43bf98247f29ebf2
Author: David Smiley <ds...@apache.org>
AuthorDate: Tue Sep 8 11:35:32 2026 -0400
DistributedUpdateProcessor: expose isLeader, setupRequest (#4878)
(cherry picked from commit 3e12f16c15ed637fb539214ddb9ce41130c699b2)
---
.../solr/update/processor/DistributedUpdateProcessor.java | 11 +++++++----
.../solr/update/processor/DistributedZkUpdateProcessor.java | 2 +-
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/solr/core/src/java/org/apache/solr/update/processor/DistributedUpdateProcessor.java b/solr/core/src/java/org/apache/solr/update/processor/DistributedUpdateProcessor.java
index 787b3292d42..1126cf60d36 100644
--- a/solr/core/src/java/org/apache/solr/update/processor/DistributedUpdateProcessor.java
+++ b/solr/core/src/java/org/apache/solr/update/processor/DistributedUpdateProcessor.java
@@ -213,7 +213,7 @@ public class DistributedUpdateProcessor extends UpdateRequestProcessor {
return Replica.Type.NRT;
}
- boolean isLeader() {
+ public boolean isLeader() {
return isLeader;
}
@@ -995,9 +995,12 @@ public class DistributedUpdateProcessor extends UpdateRequestProcessor {
}
}
- // internal helper method to setup request by processors who use this class.
- // NOTE: not called by this class!
- void setupRequest(UpdateCommand cmd) {
+ /**
+ * Set up / initialize. Exposed for other processors to determine {@link #isLeader()} afterward.
+ *
+ * @lucene.internal
+ */
+ public void setupRequest(UpdateCommand cmd) {
isLeader = getNonZkLeaderAssumption(req);
}
diff --git a/solr/core/src/java/org/apache/solr/update/processor/DistributedZkUpdateProcessor.java b/solr/core/src/java/org/apache/solr/update/processor/DistributedZkUpdateProcessor.java
index fad45bb70cb..b7fc69e8db3 100644
--- a/solr/core/src/java/org/apache/solr/update/processor/DistributedZkUpdateProcessor.java
+++ b/solr/core/src/java/org/apache/solr/update/processor/DistributedZkUpdateProcessor.java
@@ -685,7 +685,7 @@ public class DistributedZkUpdateProcessor extends DistributedUpdateProcessor {
}
@Override
- void setupRequest(UpdateCommand cmd) {
+ public void setupRequest(UpdateCommand cmd) {
zkCheck(cmd);
if (cmd instanceof AddUpdateCommand acmd) {
nodes = setupRequest(acmd.getIndexedIdStr(), acmd.getSolrInputDocument(), null, cmd);
(solr) 08/17: SOLR-18335 : SPLITSHARD now supports router.field with docValues (#4717)
Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
commit 6482df91420990bd93c8bb061615528cda061499
Author: Olivier Boudet <o....@gmail.com>
AuthorDate: Tue Sep 8 22:41:47 2026 +0200
SOLR-18335 : SPLITSHARD now supports router.field with docValues (#4717)
SPLITSHARD has expanded support for collection router.field, not only supporting indexed fields but also docValues.
Note: "Point" numeric fields only work in this case with docValues.
Co-authored-by: David Smiley <ds...@apache.org>
(cherry picked from commit 163df6a35b60c3b2ead5a43e599f51420191edc2)
---
...R-18335-splitshard-router-field-point-field.yml | 10 ++
.../org/apache/solr/update/SolrIndexSplitter.java | 154 +++++++++++++++++----
.../solr/cloud/api/collections/ShardSplitTest.java | 70 ++++++++++
.../apache/solr/update/SolrIndexSplitterTest.java | 91 ++++++++++++
.../pages/collection-management.adoc | 5 +-
5 files changed, 303 insertions(+), 27 deletions(-)
diff --git a/changelog/unreleased/SOLR-18335-splitshard-router-field-point-field.yml b/changelog/unreleased/SOLR-18335-splitshard-router-field-point-field.yml
new file mode 100644
index 00000000000..dab08ed0639
--- /dev/null
+++ b/changelog/unreleased/SOLR-18335-splitshard-router-field-point-field.yml
@@ -0,0 +1,10 @@
+title: >
+ SPLITSHARD has expanded support for collection router.field, not only supporting indexed fields but also docValues.
+ Note: "Point" numeric fields only work in this case with docValues.
+type: added
+authors:
+ - name: Olivier Boudet
+ - name: David Smiley
+links:
+ - name: SOLR-18335
+ url: https://issues.apache.org/jira/browse/SOLR-18335
diff --git a/solr/core/src/java/org/apache/solr/update/SolrIndexSplitter.java b/solr/core/src/java/org/apache/solr/update/SolrIndexSplitter.java
index 9312b831e75..b9e4c4722d1 100644
--- a/solr/core/src/java/org/apache/solr/update/SolrIndexSplitter.java
+++ b/solr/core/src/java/org/apache/solr/update/SolrIndexSplitter.java
@@ -41,6 +41,8 @@ import org.apache.lucene.index.SlowCodecReaderWrapper;
import org.apache.lucene.index.Terms;
import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.misc.store.HardlinkCopyDirectoryWrapper;
+import org.apache.lucene.queries.function.FunctionValues;
+import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.search.ConstantScoreScorer;
import org.apache.lucene.search.ConstantScoreWeight;
import org.apache.lucene.search.DocIdSetIterator;
@@ -679,7 +681,21 @@ public class SolrIndexSplitter {
Terms terms = reader.terms(field.getName());
TermsEnum termsEnum = terms == null ? null : terms.iterator();
- if (termsEnum == null) return docSets;
+ if (termsEnum == null) {
+ // No term dictionary for this field (e.g. a PointField, which has no Terms; or a
+ // docValues-only field that isn't indexed). Derive route values from docValues instead.
+ return splitUsingDocValues(
+ readerContext,
+ numPieces,
+ field,
+ rangesArr,
+ splitKey,
+ hashRouter,
+ delete,
+ docSets,
+ liveDocs,
+ currentPartition);
+ }
BytesRef term = null;
PostingsEnum postingsEnum = null;
@@ -746,38 +762,124 @@ public class SolrIndexSplitter {
}
if (docsMatchingRanges != null) {
- for (int ii = 0; ii < docsMatchingRanges.length; ii++) {
- if (0 == docsMatchingRanges[ii]) continue;
- switch (ii) {
- case 0:
- // document loss
- log.error(
- "Splitting {}: {} documents belong to no shards and will be dropped",
- reader,
- docsMatchingRanges[ii]);
- break;
- case 1:
- // normal case, each document moves to one of the sub-shards
- log.info(
- "Splitting {}: {} documents will move into a sub-shard",
- reader,
- docsMatchingRanges[ii]);
- break;
- default:
- // document duplication
- log.error(
- "Splitting {}: {} documents will be moved to multiple ({}) sub-shards",
- reader,
- docsMatchingRanges[ii],
- ii);
- break;
+ logDocsMatchingRanges(reader, docsMatchingRanges);
+ }
+
+ return docSets;
+ }
+
+ private static FixedBitSet[] splitUsingDocValues(
+ LeafReaderContext readerContext,
+ int numPieces,
+ SchemaField field,
+ DocRouter.Range[] rangesArr,
+ String splitKey,
+ HashBasedRouter hashRouter,
+ boolean delete,
+ FixedBitSet[] docSets,
+ Bits liveDocs,
+ AtomicInteger currentPartition)
+ throws IOException {
+ if (!field.hasDocValues()) {
+ throw new SolrException(
+ SolrException.ErrorCode.BAD_REQUEST,
+ "Route field '"
+ + field.getName()
+ + "' has no term index to split by and lacks docValues; unable to split shard.");
+ }
+ LeafReader reader = readerContext.reader();
+ ValueSource valueSource = field.getType().getValueSource(field, null);
+ FunctionValues routeFieldValues = valueSource.getValues(Map.of(), readerContext);
+
+ int[] docsMatchingRanges = null;
+ if (rangesArr != null) {
+ docsMatchingRanges = new int[rangesArr.length + 1];
+ }
+
+ for (int doc = 0; doc < reader.maxDoc(); doc++) {
+ if (liveDocs != null && !liveDocs.get(doc)) {
+ continue;
+ }
+
+ String routeValue = getRouteFieldValue(routeFieldValues, doc, field);
+ if (splitKey != null) {
+ String part1 = ((CompositeIdRouter) hashRouter).getRouteKeyNoSuffix(routeValue);
+ if (!splitKey.equals(part1)) {
+ continue;
}
}
+
+ if (rangesArr == null) {
+ if (delete) {
+ docSets[currentPartition.get()].clear(doc);
+ } else {
+ docSets[currentPartition.get()].set(doc);
+ }
+ currentPartition.set((currentPartition.get() + 1) % numPieces);
+ } else {
+ int hash = hashRouter.sliceHash(routeValue, null, null, null);
+ int matchingRangesCount = 0;
+ for (int i = 0; i < rangesArr.length; i++) {
+ if (rangesArr[i].includes(hash)) {
+ if (delete) {
+ docSets[i].clear(doc);
+ } else {
+ docSets[i].set(doc);
+ }
+ ++matchingRangesCount;
+ }
+ }
+ docsMatchingRanges[matchingRangesCount]++;
+ }
}
+ if (docsMatchingRanges != null) {
+ logDocsMatchingRanges(reader, docsMatchingRanges);
+ }
return docSets;
}
+ private static String getRouteFieldValue(
+ FunctionValues routeFieldValues, int doc, SchemaField field) throws IOException {
+ if (routeFieldValues.exists(doc)) {
+ return routeFieldValues.strVal(doc);
+ }
+
+ throw new SolrException(
+ SolrException.ErrorCode.SERVER_ERROR,
+ "Unable to read route field '" + field.getName() + "' for shard splitting.");
+ }
+
+ private static void logDocsMatchingRanges(LeafReader reader, int[] docsMatchingRanges) {
+ for (int ii = 0; ii < docsMatchingRanges.length; ii++) {
+ if (0 == docsMatchingRanges[ii]) continue;
+ switch (ii) {
+ case 0:
+ // document loss
+ log.error(
+ "Splitting {}: {} documents belong to no shards and will be dropped",
+ reader,
+ docsMatchingRanges[ii]);
+ break;
+ case 1:
+ // normal case, each document moves to one of the sub-shards
+ log.info(
+ "Splitting {}: {} documents will move into a sub-shard",
+ reader,
+ docsMatchingRanges[ii]);
+ break;
+ default:
+ // document duplication
+ log.error(
+ "Splitting {}: {} documents will be moved to multiple ({}) sub-shards",
+ reader,
+ docsMatchingRanges[ii],
+ ii);
+ break;
+ }
+ }
+ }
+
private static void checkRouterSupportsSplitKey(HashBasedRouter hashRouter, String splitKey) {
if (splitKey != null && !(hashRouter instanceof CompositeIdRouter)) {
throw new IllegalStateException(
diff --git a/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java b/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java
index 088eb242124..074d0431342 100644
--- a/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java
@@ -107,6 +107,7 @@ public class ShardSplitTest extends BasicDistributedZkTest {
incompleteOrOverlappingCustomRangeTest();
splitByUniqueKeyTest();
splitByRouteFieldTest();
+ splitByNumericRouteFieldTest();
splitByRouteKeyTest();
// todo can't call waitForThingsToLevelOut because it looks for jettys of all shards
@@ -1009,6 +1010,75 @@ public class ShardSplitTest extends BasicDistributedZkTest {
.query(new SolrQuery("*:*").setParam("shards", "shard1_1"))
.getResults()
.getNumFound());
+ assertEquals(101, collectionClient.query(new SolrQuery("*:*")).getResults().getNumFound());
+ }
+ }
+
+ public void splitByNumericRouteFieldTest() throws Exception {
+ log.info("Starting splitByNumericRouteFieldTest");
+ String collectionName = "numericRouteFieldColl";
+ int numShards = 4;
+ int replicationFactor = 2;
+
+ HashMap<String, List<Integer>> collectionInfos = new HashMap<>();
+ String shardField = "shard_l";
+ try (CloudSolrClient client = createCloudClient(null)) {
+ Map<String, Object> props =
+ Map.of(
+ REPLICATION_FACTOR,
+ replicationFactor,
+ CollectionHandlingUtils.NUM_SLICES,
+ numShards,
+ "router.field",
+ shardField);
+
+ createCollection(collectionInfos, collectionName, props, client);
+ }
+
+ List<Integer> list = collectionInfos.get(collectionName);
+ checkForCollection(collectionName, list);
+
+ waitForRecoveriesToFinish(false);
+
+ getCommonCloudSolrClient();
+ String baseUrl = getBaseUrlFromZk(cloudClient.getClusterState(), collectionName);
+
+ try (SolrClient collectionClient = getHttpSolrClient(baseUrl, collectionName)) {
+ ClusterState clusterState = cloudClient.getClusterState();
+ final DocRouter router = clusterState.getCollection(collectionName).getRouter();
+ Slice shard1 = clusterState.getCollection(collectionName).getSlice(SHARD1);
+ DocRouter.Range shard1Range =
+ shard1.getRange() != null ? shard1.getRange() : router.fullRange();
+ final List<DocRouter.Range> ranges = router.partitionRange(2, shard1Range);
+ final int[] docCounts = new int[ranges.size()];
+
+ for (int i = 100; i <= 200; i++) {
+ collectionClient.add(getDoc(id, i, "n_ti", i, shardField, i));
+ int idx = getHashRangeIdx(router, ranges, Integer.toString(i));
+ if (idx != -1) {
+ docCounts[idx]++;
+ }
+ }
+
+ collectionClient.commit();
+
+ trySplit(collectionName, null, SHARD1, 3);
+
+ waitForRecoveriesToFinish(collectionName, false);
+
+ assertEquals(
+ docCounts[0],
+ collectionClient
+ .query(new SolrQuery("*:*").setParam("shards", "shard1_0"))
+ .getResults()
+ .getNumFound());
+ assertEquals(
+ docCounts[1],
+ collectionClient
+ .query(new SolrQuery("*:*").setParam("shards", "shard1_1"))
+ .getResults()
+ .getNumFound());
+ assertEquals(101, collectionClient.query(new SolrQuery("*:*")).getResults().getNumFound());
}
}
diff --git a/solr/core/src/test/org/apache/solr/update/SolrIndexSplitterTest.java b/solr/core/src/test/org/apache/solr/update/SolrIndexSplitterTest.java
index d7f7fa4f2e1..9ae688f377a 100644
--- a/solr/core/src/test/org/apache/solr/update/SolrIndexSplitterTest.java
+++ b/solr/core/src/test/org/apache/solr/update/SolrIndexSplitterTest.java
@@ -55,6 +55,10 @@ public class SolrIndexSplitterTest extends SolrTestCaseJ4 {
// _version_
System.setProperty("solr.directoryFactory", "solr.NRTCachingDirectoryFactory");
System.setProperty("solr.tests.lockType", DirectoryFactory.LOCK_TYPE_SIMPLE);
+ // route_l needs docValues to be usable as a router.field when numerics are Point-based
+ if (Boolean.getBoolean(NUMERIC_POINTS_SYSPROP)) {
+ System.setProperty(NUMERIC_DOCVALUES_SYSPROP, "true");
+ }
initCore("solrconfig.xml", "schema15.xml");
}
@@ -413,6 +417,16 @@ public class SolrIndexSplitterTest extends SolrTestCaseJ4 {
doTestSplitByRouteKey(SolrIndexSplitter.SplitMethod.LINK);
}
+ @Test
+ public void testSplitByNumericRouteField() throws Exception {
+ doTestSplitByNumericRouteField(SolrIndexSplitter.SplitMethod.REWRITE);
+ }
+
+ @Test
+ public void testSplitByNumericRouteFieldLink() throws Exception {
+ doTestSplitByNumericRouteField(SolrIndexSplitter.SplitMethod.LINK);
+ }
+
private void doTestSplitByRouteKey(SolrIndexSplitter.SplitMethod splitMethod) throws Exception {
Path indexDir = createTempDir();
@@ -480,6 +494,83 @@ public class SolrIndexSplitterTest extends SolrTestCaseJ4 {
}
}
+ private void doTestSplitByNumericRouteField(SolrIndexSplitter.SplitMethod splitMethod)
+ throws Exception {
+ CompositeIdRouter router = new CompositeIdRouter();
+ List<DocRouter.Range> ranges = router.partitionRange(2, router.fullRange());
+ int[] expectedDocCounts = new int[ranges.size()];
+
+ for (int i = 100; i < 140; i++) {
+ String routeValue = Integer.toString(i);
+ assertU(adoc("id", "doc-" + i, "route_l", routeValue));
+
+ int hash = router.sliceHash(routeValue, null, null, null);
+ for (int rangeIndex = 0; rangeIndex < ranges.size(); rangeIndex++) {
+ if (ranges.get(rangeIndex).includes(hash)) {
+ expectedDocCounts[rangeIndex]++;
+ break;
+ }
+ }
+ }
+
+ assertU(commit());
+ assertJQ(req("q", "*:*"), "/response/numFound==40");
+
+ SolrQueryRequestBase request = null;
+ Directory directory = null;
+ try {
+ request = lrf.makeRequest("q", "dummy");
+ SolrQueryResponse rsp = new SolrQueryResponse();
+ SplitIndexCommand command =
+ new SplitIndexCommand(
+ request,
+ rsp,
+ List.of(indexDir1.toString(), indexDir2.toString()),
+ null,
+ ranges,
+ router,
+ "route_l",
+ null,
+ splitMethod);
+ doSplit(command);
+
+ directory =
+ h.getCore()
+ .getDirectoryFactory()
+ .get(
+ indexDir1.toString(),
+ DirectoryFactory.DirContext.DEFAULT,
+ h.getCore().getSolrConfig().indexConfig.lockType);
+ DirectoryReader reader = DirectoryReader.open(directory);
+ assertEquals(
+ "split index1 has wrong number of documents", expectedDocCounts[0], reader.numDocs());
+ reader.close();
+ h.getCore().getDirectoryFactory().release(directory);
+ directory = null;
+
+ directory =
+ h.getCore()
+ .getDirectoryFactory()
+ .get(
+ indexDir2.toString(),
+ DirectoryFactory.DirContext.DEFAULT,
+ h.getCore().getSolrConfig().indexConfig.lockType);
+ reader = DirectoryReader.open(directory);
+ assertEquals(
+ "split index2 has wrong number of documents", expectedDocCounts[1], reader.numDocs());
+ reader.close();
+ h.getCore().getDirectoryFactory().release(directory);
+ directory = null;
+ } finally {
+ if (request != null) {
+ request.close();
+ }
+ if (directory != null) {
+ h.getCore().getDirectoryFactory().release(directory);
+ }
+ }
+ }
+
@Test
public void testSplitWithChildDocs() throws Exception {
doTestSplitWithChildDocs(SolrIndexSplitter.SplitMethod.REWRITE);
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 46452619f7c..45b26e0af47 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
@@ -232,6 +232,8 @@ For nested documents, the route field must match among all the documents in the
+
Please note that xref:configuration-guide:realtime-get.adoc[] or retrieval by document ID would also require the parameter `\_route_` (or `shard.keys`) to avoid a distributed search.
+Use of docValues is highly encouraged on this field.
+
`perReplicaState`::
+
[%autowidth,frame=none]
@@ -1647,7 +1649,8 @@ s|Required |Default: none
What to name the backup that is created.
Provided as a query parameter for v1 requests, or as a path segment for v2 requests.
+
-For incremental backups, the backup name should be reused to add new backup points to the existing backup. For non-incremental backups (deprecated), this name is checked to ensure it doesn't already exist, and an error message is raised if it does.
+For incremental backups, the backup name should be reused to add new backup points to the existing backup.
+For non-incremental backups (deprecated), this name is checked to ensure it doesn't already exist, and an error message is raised if it does.
`location`::
+
(solr) 10/17: HttpSolrClient add withTheseParamNamesInTheUrl defaults (#4871)
Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
commit 5c3ae79fbde74ad67e22a11b520d3fd479cdbc50
Author: David Smiley <ds...@apache.org>
AuthorDate: Tue Sep 8 18:04:09 2026 -0400
HttpSolrClient add withTheseParamNamesInTheUrl defaults (#4871)
HttpSolrClient impls now sends certain interesting request parameters in the URL query string when a POST of parameters is submitted. In other words, withTheseParamNamesInTheUrl now has a default set. This improves observability, particularly for distributed search & admin commands.
(cherry picked from commit 125f7c011f3473dcfa3417cba1b0a492493edfef)
---
.../PR#4871-httpSolrClientDefaultUrlParams.yml | 9 ++++++++
.../solr/tracing/TestDistributedTracing/test.json | 12 ++++++----
.../tracing/TestDistributedTracing/testV2Api.json | 21 +++++++++++------
.../solr/opentelemetry/TestDistributedTracing.java | 2 +-
.../solr/client/solrj/impl/HttpSolrClient.java | 27 ++++++++++++++++++----
5 files changed, 54 insertions(+), 17 deletions(-)
diff --git a/changelog/unreleased/PR#4871-httpSolrClientDefaultUrlParams.yml b/changelog/unreleased/PR#4871-httpSolrClientDefaultUrlParams.yml
new file mode 100644
index 00000000000..7dfcae61bdf
--- /dev/null
+++ b/changelog/unreleased/PR#4871-httpSolrClientDefaultUrlParams.yml
@@ -0,0 +1,9 @@
+title: >
+ HttpSolrClient impls now sends certain interesting request parameters in the URL query string when a POST of parameters is submitted. In other words, withTheseParamNamesInTheUrl now has a default set.
+ This improves observability, particularly for distributed search & admin commands.
+type: changed
+authors:
+ - name: David Smiley
+links:
+ - name: PR#4871
+ url: https://github.com/apache/solr/pull/4871
diff --git a/solr/modules/opentelemetry/src/test-files/solr/tracing/TestDistributedTracing/test.json b/solr/modules/opentelemetry/src/test-files/solr/tracing/TestDistributedTracing/test.json
index 8cd2d28437a..87782172c2d 100644
--- a/solr/modules/opentelemetry/src/test-files/solr/tracing/TestDistributedTracing/test.json
+++ b/solr/modules/opentelemetry/src/test-files/solr/tracing/TestDistributedTracing/test.json
@@ -84,7 +84,8 @@
"db.type":"solr",
"http.request.method":"POST",
"http.response.status_code":200,
- "http.url":"http://NORMALIZED/solr/collection1_shard1_replica_nN/select"},
+ "http.url":"http://NORMALIZED/solr/collection1_shard1_replica_nN/select",
+ "http.params":"distrib=false&isShard=true&shards.purpose=16388"},
{
"name":"post:/{core}/select",
"kind":"SERVER",
@@ -92,7 +93,8 @@
"db.type":"solr",
"http.request.method":"POST",
"http.response.status_code":200,
- "http.url":"http://NORMALIZED/solr/collection1_shard1_replica_nN/select"},
+ "http.url":"http://NORMALIZED/solr/collection1_shard1_replica_nN/select",
+ "http.params":"distrib=false&isShard=true&shards.purpose=64"},
{
"name":"post:/{core}/select",
"kind":"SERVER",
@@ -100,7 +102,8 @@
"db.type":"solr",
"http.request.method":"POST",
"http.response.status_code":200,
- "http.url":"http://NORMALIZED/solr/collection1_shard2_replica_nN/select"},
+ "http.url":"http://NORMALIZED/solr/collection1_shard2_replica_nN/select",
+ "http.params":"distrib=false&isShard=true&shards.purpose=16388"},
{
"name":"post:/{core}/select",
"kind":"SERVER",
@@ -108,4 +111,5 @@
"db.type":"solr",
"http.request.method":"POST",
"http.response.status_code":200,
- "http.url":"http://NORMALIZED/solr/collection1_shard2_replica_nN/select"}]}]}]}
\ No newline at end of file
+ "http.url":"http://NORMALIZED/solr/collection1_shard2_replica_nN/select",
+ "http.params":"distrib=false&isShard=true&shards.purpose=64"}]}]}]}
\ No newline at end of file
diff --git a/solr/modules/opentelemetry/src/test-files/solr/tracing/TestDistributedTracing/testV2Api.json b/solr/modules/opentelemetry/src/test-files/solr/tracing/TestDistributedTracing/testV2Api.json
index 20ef31ae8ab..047c3acc1f0 100644
--- a/solr/modules/opentelemetry/src/test-files/solr/tracing/TestDistributedTracing/testV2Api.json
+++ b/solr/modules/opentelemetry/src/test-files/solr/tracing/TestDistributedTracing/testV2Api.json
@@ -14,7 +14,8 @@
"db.type":"solr",
"http.request.method":"POST",
"http.response.status_code":200,
- "http.url":"http://NORMALIZED/solr/admin/cores"},
+ "http.url":"http://NORMALIZED/solr/admin/cores",
+ "http.params":"action=RELOAD"},
{
"name":"reload:/admin/cores",
"kind":"SERVER",
@@ -22,7 +23,8 @@
"db.type":"solr",
"http.request.method":"POST",
"http.response.status_code":200,
- "http.url":"http://NORMALIZED/solr/admin/cores"},
+ "http.url":"http://NORMALIZED/solr/admin/cores",
+ "http.params":"action=RELOAD"},
{
"name":"reload:/admin/cores",
"kind":"SERVER",
@@ -30,7 +32,8 @@
"db.type":"solr",
"http.request.method":"POST",
"http.response.status_code":200,
- "http.url":"http://NORMALIZED/solr/admin/cores"},
+ "http.url":"http://NORMALIZED/solr/admin/cores",
+ "http.params":"action=RELOAD"},
{
"name":"reload:/admin/cores",
"kind":"SERVER",
@@ -38,7 +41,8 @@
"db.type":"solr",
"http.request.method":"POST",
"http.response.status_code":200,
- "http.url":"http://NORMALIZED/solr/admin/cores"}]},
+ "http.url":"http://NORMALIZED/solr/admin/cores",
+ "http.params":"action=RELOAD"}]},
{
"name":"post:/collections/{collection}/reload",
"kind":"SERVER",
@@ -124,7 +128,8 @@
"db.type":"solr",
"http.request.method":"POST",
"http.response.status_code":200,
- "http.url":"http://NORMALIZED/solr/collection1_shard1_replica_nN/select"},
+ "http.url":"http://NORMALIZED/solr/collection1_shard1_replica_nN/select",
+ "http.params":"distrib=false&isShard=true&shards.purpose=16388"},
{
"name":"post:/{core}/select",
"kind":"SERVER",
@@ -132,7 +137,8 @@
"db.type":"solr",
"http.request.method":"POST",
"http.response.status_code":200,
- "http.url":"http://NORMALIZED/solr/collection1_shard2_replica_nN/select"},
+ "http.url":"http://NORMALIZED/solr/collection1_shard2_replica_nN/select",
+ "http.params":"distrib=false&isShard=true&shards.purpose=16388"},
{
"name":"post:/{core}/select",
"kind":"SERVER",
@@ -140,4 +146,5 @@
"db.type":"solr",
"http.request.method":"POST",
"http.response.status_code":200,
- "http.url":"http://NORMALIZED/solr/collection1_shard2_replica_nN/select"}]}]}]}
\ No newline at end of file
+ "http.url":"http://NORMALIZED/solr/collection1_shard2_replica_nN/select",
+ "http.params":"distrib=false&isShard=true&shards.purpose=64"}]}]}]}
\ No newline at end of file
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 f667729eb60..22e4f9d87d6 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
@@ -201,7 +201,7 @@ public class TestDistributedTracing extends SolrCloudTestCase {
// db.instance=testInternalCollectionApiCommands
// - this will be the parent span, all following spans will have the same traceId
//
- // 3..6 (4 times) name=post:/admin/cores
+ // 3..6 (4 times) name=create:/admin/cores
// db.instance=testInternalCollectionApiCommands_shard1_replica_n2
// db.instance=testInternalCollectionApiCommands_shard2_replica_n4
// db.instance=testInternalCollectionApiCommands_shard2_replica_n1
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 fccc4357fcd..0ae5dd00dc8 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
@@ -46,8 +46,12 @@ import org.apache.solr.client.solrj.response.JavaBinResponseParser;
import org.apache.solr.client.solrj.response.ResponseParser;
import org.apache.solr.client.solrj.util.ClientUtils;
import org.apache.solr.common.SolrException;
+import org.apache.solr.common.params.CollectionAdminParams;
+import org.apache.solr.common.params.CommonAdminParams;
import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.params.CoreAdminParams;
import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.params.ShardParams;
import org.apache.solr.common.util.ContentStream;
import org.apache.solr.common.util.NamedList;
import org.slf4j.Logger;
@@ -66,6 +70,23 @@ public abstract class HttpSolrClient extends SolrClient {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
protected static final Charset FALLBACK_CHARSET = StandardCharsets.UTF_8;
+ /**
+ * See {@link #getUrlParamNames()}. Default set are interesting for routing or fundamental request
+ * purpose
+ */
+ public static final Set<String> DEFAULT_URL_PARAM_NAMES =
+ Set.of(
+ CoreAdminParams.ACTION,
+ CommonAdminParams.ASYNC,
+ CollectionAdminParams.COLLECTION,
+ "name", // core/collection name
+ "command", // e.g. for replication
+ ShardParams.IS_SHARD,
+ CommonParams.DISTRIB,
+ ShardParams._ROUTE_,
+ ShardParams.SHARDS_PREFERENCE,
+ ShardParams.SHARDS_PURPOSE);
+
protected final String baseUrl;
protected final long requestTimeoutMillis;
@@ -88,11 +109,7 @@ public abstract class HttpSolrClient extends SolrClient {
this.parser = builder.responseParser;
}
this.defaultCollection = builder.defaultCollection;
- if (builder.urlParamNames != null) {
- this.urlParamNames = builder.urlParamNames;
- } else {
- this.urlParamNames = Set.of();
- }
+ this.urlParamNames = Objects.requireNonNullElse(builder.urlParamNames, DEFAULT_URL_PARAM_NAMES);
}
private static String extractBaseUrl(String serverBaseUrl) {
(solr) 17/17: Update Error Prone to v2.50.0 (#4847)
Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
commit 7eb62d0ab67f369fc2f9af937867ac611ce264dc
Author: Solr Bot <12...@users.noreply.github.com>
AuthorDate: Wed Sep 9 03:09:15 2026 +0200
Update Error Prone to v2.50.0 (#4847)
Co-authored-by: Eric Pugh <ep...@opensourceconnections.com>
Co-authored-by: Claude Sonnet 5 <no...@anthropic.com>
(cherry picked from commit 090f5b995c156f5db5c238f44a13e4b804b66abe)
---
.../PR#4847-update-error-prone-to-v2-50-0.yml | 7 +++++++
gradle/libs.versions.toml | 2 +-
gradle/validation/error-prone.gradle | 17 ++++++++++++++---
solr/api/gradle.lockfile | 8 ++++----
.../api/model/GetClusterCommandStatusResponse.java | 10 +++++-----
solr/benchmark/gradle.lockfile | 8 ++++----
solr/core/gradle.lockfile | 8 ++++----
.../src/java/org/apache/solr/cli/ExportTool.java | 2 ++
.../solr/cloud/DistributedClusterStateUpdater.java | 4 ++++
.../src/java/org/apache/solr/cloud/LockTree.java | 2 ++
.../src/java/org/apache/solr/cloud/Overseer.java | 3 ---
.../org/apache/solr/cloud/ReplicateFromLeader.java | 3 +++
.../cloud/api/collections/CategoryRoutedAlias.java | 2 ++
.../api/collections/DimensionalRoutedAlias.java | 2 ++
.../cloud/api/collections/TimeRoutedAlias.java | 2 ++
.../apache/solr/cloud/overseer/ZkStateWriter.java | 6 ++++++
.../apache/solr/cloud/overseer/ZkWriteCommand.java | 2 ++
.../apache/solr/core/CachingDirectoryFactory.java | 4 ++++
.../java/org/apache/solr/core/CoreContainer.java | 1 +
.../src/java/org/apache/solr/core/PluginBag.java | 5 ++++-
.../src/java/org/apache/solr/core/SolrCore.java | 6 ++++++
.../src/java/org/apache/solr/core/SolrPaths.java | 2 ++
.../org/apache/solr/core/SolrResourceLoader.java | 9 +++++++++
.../apache/solr/handler/ReplicationHandler.java | 4 ++++
.../solr/handler/admin/CoreAdminHandler.java | 2 ++
.../solr/handler/admin/IndexSizeEstimator.java | 2 ++
.../solr/handler/admin/SecurityConfHandler.java | 4 ++++
.../solr/handler/admin/SystemInfoProvider.java | 2 ++
.../solr/handler/admin/api/ClusterCommands.java | 2 +-
.../handler/component/RealTimeGetComponent.java | 4 ++++
.../solr/handler/component/ResponseBuilder.java | 2 ++
.../solr/handler/component/SearchHandler.java | 3 +++
.../solr/handler/component/TermsComponent.java | 2 ++
.../apache/solr/handler/loader/JavabinLoader.java | 2 ++
.../java/org/apache/solr/handler/tagger/TagLL.java | 4 ++++
.../java/org/apache/solr/legacy/BBoxStrategy.java | 3 +++
.../org/apache/solr/logging/jul/JulWatcher.java | 3 +++
.../apache/solr/logging/log4j2/Log4j2Watcher.java | 2 ++
.../DualRegistryAttributedLongCounter.java | 2 ++
.../DualRegistryAttributedLongTimer.java | 2 ++
.../DualRegistryAttributedLongUpDownCounter.java | 2 ++
.../java/org/apache/solr/pkg/PackageListeners.java | 2 ++
.../org/apache/solr/pkg/PackagePluginHolder.java | 2 ++
.../apache/solr/response/TextResponseWriter.java | 1 +
.../transform/RawValueTransformerFactory.java | 2 ++
.../response/transform/ValueSourceAugmenter.java | 2 ++
.../src/java/org/apache/solr/schema/BBoxField.java | 1 +
.../java/org/apache/solr/schema/IndexSchema.java | 1 +
.../solr/schema/LatLonPointSpatialField.java | 3 +++
.../java/org/apache/solr/schema/SchemaManager.java | 2 ++
.../java/org/apache/solr/search/CaffeineCache.java | 1 +
.../solr/search/CollapsingQParserPlugin.java | 12 ++++++++++--
.../apache/solr/search/DocValuesIteratorCache.java | 1 +
.../apache/solr/search/ExtendedDismaxQParser.java | 1 +
.../solr/search/GraphTermsQParserPlugin.java | 5 +++++
.../src/java/org/apache/solr/search/JoinQuery.java | 3 +++
.../org/apache/solr/search/QueryResultKey.java | 1 +
.../org/apache/solr/search/SolrIndexSearcher.java | 2 ++
.../solr/search/facet/FacetFieldProcessor.java | 3 +++
.../apache/solr/search/facet/RelatednessAgg.java | 2 ++
.../java/org/apache/solr/search/facet/SlotAcc.java | 3 +++
.../apache/solr/search/facet/UnInvertedField.java | 2 ++
.../apache/solr/security/AllowListUrlChecker.java | 2 ++
.../solr/security/PKIAuthenticationPlugin.java | 2 ++
.../java/org/apache/solr/servlet/HttpSolrCall.java | 2 ++
.../apache/solr/servlet/RequestRateLimiter.java | 4 ++++
.../apache/solr/servlet/SolrRequestParsers.java | 6 +++++-
.../solr/spelling/ConjunctionSolrSpellChecker.java | 1 +
.../apache/solr/update/DirectUpdateHandler2.java | 1 +
.../org/apache/solr/update/MemOutputStream.java | 3 +++
.../src/java/org/apache/solr/update/PeerSync.java | 6 ++++++
.../org/apache/solr/update/PeerSyncWithLeader.java | 9 +++++++++
.../org/apache/solr/update/SolrIndexConfig.java | 3 +++
.../src/java/org/apache/solr/update/UpdateLog.java | 9 ++++++++-
...llValuesOrNoneFieldMutatingUpdateProcessor.java | 3 +++
.../processor/AtomicUpdateDocumentMerger.java | 3 +++
.../DocBasedVersionConstraintsProcessor.java | 2 ++
.../processor/FieldMutatingUpdateProcessor.java | 3 +++
.../FieldValueMutatingUpdateProcessor.java | 3 +++
.../SkipExistingDocumentsProcessorFactory.java | 2 ++
.../test/org/apache/solr/TestGroupingSearch.java | 3 +++
.../solr/cloud/LeaderElectionIntegrationTest.java | 2 ++
.../solr/handler/admin/TestApiFramework.java | 2 ++
.../handler/admin/api/ClusterCommandsTest.java | 22 ++++++++++++----------
.../src/test/org/apache/solr/pkg/TestPackages.java | 1 +
.../solr/schema/TestManagedSchemaThreadSafety.java | 2 ++
.../apache/solr/search/facet/TestJsonFacets.java | 2 ++
.../solr/search/function/AggValueSourceTest.java | 2 ++
.../solr/uninverting/TestFieldCacheSortRandom.java | 2 ++
.../solr/update/TestInPlaceUpdatesStandalone.java | 2 +-
solr/cross-dc-manager/gradle.lockfile | 8 ++++----
solr/modules/analysis-extras/gradle.lockfile | 8 ++++----
solr/modules/clustering/gradle.lockfile | 8 ++++----
solr/modules/cross-dc/gradle.lockfile | 8 ++++----
solr/modules/cuvs/gradle.lockfile | 8 ++++----
solr/modules/extraction/gradle.lockfile | 8 ++++----
solr/modules/gcs-repository/gradle.lockfile | 8 ++++----
solr/modules/jwt-auth/gradle.lockfile | 8 ++++----
solr/modules/langid/gradle.lockfile | 8 ++++----
solr/modules/language-models/gradle.lockfile | 8 ++++----
solr/modules/ltr/gradle.lockfile | 8 ++++----
.../org/apache/solr/ltr/feature/SolrFeature.java | 3 +++
.../org/apache/solr/ltr/model/LTRScoringModel.java | 2 ++
solr/modules/opentelemetry/gradle.lockfile | 8 ++++----
solr/modules/s3-repository/gradle.lockfile | 8 ++++----
solr/modules/scripting/gradle.lockfile | 8 ++++----
solr/modules/sql/gradle.lockfile | 8 ++++----
.../org/apache/solr/handler/sql/SolrAggregate.java | 2 ++
.../org/apache/solr/handler/sql/SolrFilter.java | 2 ++
.../org/apache/solr/handler/sql/SolrProject.java | 2 ++
.../java/org/apache/solr/handler/sql/SolrSort.java | 2 ++
.../org/apache/solr/handler/sql/SolrTableScan.java | 2 ++
solr/server/gradle.lockfile | 8 ++++----
solr/solr-ref-guide/gradle.lockfile | 8 ++++----
solr/solrj-jetty/gradle.lockfile | 8 ++++----
solr/solrj-streaming/gradle.lockfile | 8 ++++----
.../solr/client/solrj/io/comp/FieldComparator.java | 2 +-
.../solr/client/solrj/io/eq/FieldEqualitor.java | 2 +-
.../solrj/io/stream/JavabinTupleStreamParser.java | 7 ++++++-
solr/solrj-zookeeper/gradle.lockfile | 8 ++++----
.../apache/solr/common/cloud/ZkStateReader.java | 4 ++++
solr/solrj/gradle.lockfile | 8 ++++----
.../solrj/impl/ConcurrentUpdateBaseSolrClient.java | 2 ++
.../solrj/request/JavaBinUpdateRequestCodec.java | 2 ++
.../solr/client/solrj/response/ResponseParser.java | 1 +
.../RequestReplicaListTransformerGenerator.java | 2 +-
.../apache/solr/common/util/CommandOperation.java | 2 +-
.../org/apache/solr/common/util/JavaBinCodec.java | 6 ++++++
.../apache/solr/common/util/TestFastWriter.java | 2 ++
solr/test-framework/gradle.lockfile | 8 ++++----
.../apache/solr/BaseDistributedSearchTestCase.java | 1 +
.../src/java/org/apache/solr/JSONTestUtil.java | 1 +
.../src/java/org/apache/solr/SolrTestCaseJ4.java | 8 ++++++++
.../apache/solr/cluster/placement/Builders.java | 2 ++
.../org/apache/solr/embedded/JettySolrRunner.java | 2 ++
.../solr/util/RevertDefaultThreadHandlerRule.java | 2 ++
solr/webapp/gradle.lockfile | 8 ++++----
137 files changed, 427 insertions(+), 138 deletions(-)
diff --git a/changelog/unreleased/PR#4847-update-error-prone-to-v2-50-0.yml b/changelog/unreleased/PR#4847-update-error-prone-to-v2-50-0.yml
new file mode 100644
index 00000000000..0b5f3ad02de
--- /dev/null
+++ b/changelog/unreleased/PR#4847-update-error-prone-to-v2-50-0.yml
@@ -0,0 +1,7 @@
+title: Update Error Prone to v2.50.0
+type: dependency_update
+authors:
+- name: solrbot
+links:
+- name: PR#4847
+ url: https://github.com/apache/solr/pull/4847
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 12d7ee729b3..ec89c03db11 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -99,7 +99,7 @@ google-api-grpc-proto = "2.75.0"
# @keep for version alignment
google-autovalue = "1.11.1"
google-cloud-bom = "0.268.0"
-google-errorprone = "2.41.0"
+google-errorprone = "2.50.0"
# @keep for version alignment
google-gson = "2.14.0"
google-guava = "33.7.1-jre"
diff --git a/gradle/validation/error-prone.gradle b/gradle/validation/error-prone.gradle
index 3ca5341ef0f..ce8618939cd 100644
--- a/gradle/validation/error-prone.gradle
+++ b/gradle/validation/error-prone.gradle
@@ -456,7 +456,7 @@ allprojects {prj ->
'-Xep:NonCanonicalType:WARN',
'-Xep:NonOverridingEquals:WARN',
//'-Xep:NonFinalStaticField:WARN', // todo there are problems that should be fixed
- '-Xep:NotJavadoc:WARN',
+ // '-Xep:NotJavadoc:OFF', // we disagree; javadocs aren't purely for publishing
'-Xep:NullOptional:WARN',
// '-Xep:NullableConstructor:OFF', // we don't use this annotation
'-Xep:NullableOptional:WARN',
@@ -589,11 +589,12 @@ allprojects {prj ->
}
}
-// Exclude generated OpenAPI sources in solrj from Error Prone checks.
+// Exclude generated OpenAPI sources and the vendored noggit JSON parser (org.noggit, not our
+// code/conventions) in solrj from Error Prone checks.
configure(project(":solr:solrj")) {
plugins.withId(libs.plugins.ltgt.errorprone.get().pluginId) {
tasks.withType(JavaCompile) {
- options.errorprone.excludedPaths = ".*/build/generated/.*"
+ options.errorprone.excludedPaths = ".*/build/generated/.*|.*/org/noggit/.*"
}
}
}
@@ -606,3 +607,13 @@ configure(project(":solr:core")) {
}
}
}
+
+// Exclude vendored Tika sources (copied in to eliminate the Tika dependency) in
+// solr:modules:extraction from Error Prone checks.
+configure(project(":solr:modules:extraction")) {
+ plugins.withId(libs.plugins.ltgt.errorprone.get().pluginId) {
+ tasks.withType(JavaCompile) {
+ options.errorprone.excludedPaths = ".*/org/apache/solr/handler/extraction/fromtika/.*"
+ }
+ }
+}
diff --git a/solr/api/gradle.lockfile b/solr/api/gradle.lockfile
index 14de6e5a919..cffac736f54 100644
--- a/solr/api/gradle.lockfile
+++ b/solr/api/gradle.lockfile
@@ -21,11 +21,11 @@ com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,errorprone,jarValidation,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,errorprone,jarValidation,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,errorprone,jarValidation,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,errorprone,jarValidation,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/api/src/java/org/apache/solr/client/api/model/GetClusterCommandStatusResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/GetClusterCommandStatusResponse.java
index 6b96427cacd..c1b03cf5921 100644
--- a/solr/api/src/java/org/apache/solr/client/api/model/GetClusterCommandStatusResponse.java
+++ b/solr/api/src/java/org/apache/solr/client/api/model/GetClusterCommandStatusResponse.java
@@ -54,7 +54,7 @@ public class GetClusterCommandStatusResponse extends SolrJerseyResponse {
public static class CommandStatus implements ReflectWritable {
@JsonProperty("state")
@Schema(description = "Request state: submitted, running, completed, failed, or notfound.")
- public State state;
+ public RequestState state;
@JsonProperty("msg")
@Schema(description = "A message describing where the request was found, if at all.")
@@ -65,7 +65,7 @@ public class GetClusterCommandStatusResponse extends SolrJerseyResponse {
* org.apache.solr.client.solrj.response.RequestStatusState}'s constants and wire keys; kept as
* a separate type here since this module (solr:api) cannot depend on solrj.
*/
- public enum State {
+ public enum RequestState {
SUBMITTED("submitted"),
RUNNING("running"),
COMPLETED("completed"),
@@ -74,7 +74,7 @@ public class GetClusterCommandStatusResponse extends SolrJerseyResponse {
private final String key;
- State(String key) {
+ RequestState(String key) {
this.key = key;
}
@@ -84,8 +84,8 @@ public class GetClusterCommandStatusResponse extends SolrJerseyResponse {
}
@JsonCreator
- public static State fromKey(String key) {
- for (State state : values()) {
+ public static RequestState fromKey(String key) {
+ for (RequestState state : values()) {
if (state.key.equalsIgnoreCase(key)) {
return state;
}
diff --git a/solr/benchmark/gradle.lockfile b/solr/benchmark/gradle.lockfile
index 2060623c2b7..fab70d23da5 100644
--- a/solr/benchmark/gradle.lockfile
+++ b/solr/benchmark/gradle.lockfile
@@ -17,11 +17,11 @@ com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/core/gradle.lockfile b/solr/core/gradle.lockfile
index b0d9613610f..6d5dafcf58b 100644
--- a/solr/core/gradle.lockfile
+++ b/solr/core/gradle.lockfile
@@ -28,12 +28,12 @@ com.github.stephenc.jcip:jcip-annotations:1.0-1=compileClasspath,compileClasspat
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.47.0=compileClasspathCopy,runtimeClasspathCopy,testCompileClasspathCopy,testRuntimeClasspathCopy
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,compileClasspath,compileClasspathCopy,errorprone,jarValidation,runtimeClasspath,runtimeClasspathCopy,runtimeLibs,testAnnotationProcessor,testCompileClasspath,testCompileClasspathCopy,testRuntimeClasspath,testRuntimeClasspathCopy
com.google.guava:guava:33.6.0-jre=compileClasspathCopy,runtimeClasspathCopy,testCompileClasspathCopy,testRuntimeClasspathCopy
com.google.guava:guava:33.7.1-jre=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
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 9fb9a23e3d2..e377e37bc99 100644
--- a/solr/core/src/java/org/apache/solr/cli/ExportTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/ExportTool.java
@@ -594,6 +594,8 @@ public class ExportTool extends ToolBase {
}
}
+ @SuppressWarnings(
+ "ReferenceEquality") // EOFDOC is a unique sentinel; identity check is intentional
private void addConsumer(CountDownLatch consumerlatch) {
consumerThreadpool.execute(
() -> {
diff --git a/solr/core/src/java/org/apache/solr/cloud/DistributedClusterStateUpdater.java b/solr/core/src/java/org/apache/solr/cloud/DistributedClusterStateUpdater.java
index 3c4c152bdcf..9a8e249ca3c 100644
--- a/solr/core/src/java/org/apache/solr/cloud/DistributedClusterStateUpdater.java
+++ b/solr/core/src/java/org/apache/solr/cloud/DistributedClusterStateUpdater.java
@@ -755,6 +755,8 @@ public class DistributedClusterStateUpdater {
}
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // NO_OP is a unique sentinel; identity check is intentional
public void computeUpdates(ClusterState clusterState, SolrZkClient client) {
boolean hasJsonUpdates = false;
List<PerReplicaStatesOps> perReplicaStateOps = new ArrayList<>();
@@ -912,6 +914,8 @@ public class DistributedClusterStateUpdater {
}
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // NO_OP is a unique sentinel; identity check is intentional
public void computeUpdates(ClusterState clusterState, SolrZkClient client) {
final DocCollection docCollection = clusterState.getCollectionOrNull(collectionName);
Optional<ZkWriteCommand> result =
diff --git a/solr/core/src/java/org/apache/solr/cloud/LockTree.java b/solr/core/src/java/org/apache/solr/cloud/LockTree.java
index 6bb432abd8e..c99eae37e9c 100644
--- a/solr/core/src/java/org/apache/solr/cloud/LockTree.java
+++ b/solr/core/src/java/org/apache/solr/cloud/LockTree.java
@@ -214,6 +214,8 @@ public class LockTree {
return false;
}
+ @SuppressWarnings(
+ "ReferenceEquality") // releasing only the exact lock instance held, by identity
boolean unlock(LockImpl lockObject) {
if (--refCount > 0) {
return false;
diff --git a/solr/core/src/java/org/apache/solr/cloud/Overseer.java b/solr/core/src/java/org/apache/solr/cloud/Overseer.java
index cc8e65537c5..9d35afb7161 100644
--- a/solr/core/src/java/org/apache/solr/cloud/Overseer.java
+++ b/solr/core/src/java/org/apache/solr/cloud/Overseer.java
@@ -782,9 +782,6 @@ public class Overseer implements SolrCloseable {
assert ObjectReleaseTracker.track(this);
}
- /** Start {@link ClusterSingleton} plugins when we become the leader. */
-
- /** Stop {@link ClusterSingleton} plugins when we lose leadership. */
public Stats getStats() {
return stats;
}
diff --git a/solr/core/src/java/org/apache/solr/cloud/ReplicateFromLeader.java b/solr/core/src/java/org/apache/solr/cloud/ReplicateFromLeader.java
index a6998fe38cb..7458f3938d0 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ReplicateFromLeader.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ReplicateFromLeader.java
@@ -64,6 +64,9 @@ public class ReplicateFromLeader {
* @param switchTransactionLog if true, ReplicationHandler will rotate the transaction log once
* the replication is done
*/
+ @SuppressWarnings(
+ "ReferenceEquality") // IndexFetchResult constants are singletons; identity check is
+ // intentional
public void startReplication(boolean switchTransactionLog) {
try (SolrCore core = cc.getCore(coreName)) {
if (core == null) {
diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/CategoryRoutedAlias.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/CategoryRoutedAlias.java
index c787fdc80ce..b618d529f80 100644
--- a/solr/core/src/java/org/apache/solr/cloud/api/collections/CategoryRoutedAlias.java
+++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/CategoryRoutedAlias.java
@@ -80,6 +80,8 @@ public class CategoryRoutedAlias extends RoutedAlias {
}
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // Aliases is replaced wholesale, so identity means "possibly changed"
public boolean updateParsedCollectionAliases(ZkStateReader zkStateReader, boolean contextualize) {
final Aliases aliases =
zkStateReader.getAliases(); // note: might be different from last request
diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/DimensionalRoutedAlias.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/DimensionalRoutedAlias.java
index 0b2cb49678c..b752d098153 100644
--- a/solr/core/src/java/org/apache/solr/cloud/api/collections/DimensionalRoutedAlias.java
+++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/DimensionalRoutedAlias.java
@@ -212,6 +212,8 @@ public class DimensionalRoutedAlias extends RoutedAlias {
* @return A list of actions across the DRA.
*/
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // RoutedAlias dimension identity, not equality, is what matters here
protected List<Action> calculateActions(String targetCol) {
String[] routeValues = SEP_MATCHER.split(targetCol);
// remove the alias name to avoid all manner of off by one errors...
diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/TimeRoutedAlias.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/TimeRoutedAlias.java
index 8139956116e..4df16b611d2 100644
--- a/solr/core/src/java/org/apache/solr/cloud/api/collections/TimeRoutedAlias.java
+++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/TimeRoutedAlias.java
@@ -264,6 +264,8 @@ public class TimeRoutedAlias extends RoutedAlias {
}
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // Aliases is replaced wholesale, so identity means "possibly changed"
public boolean updateParsedCollectionAliases(ZkStateReader zkStateReader, boolean contextualize) {
final Aliases aliases = zkStateReader.getAliases();
if (this.parsedCollectionsAliases != aliases) {
diff --git a/solr/core/src/java/org/apache/solr/cloud/overseer/ZkStateWriter.java b/solr/core/src/java/org/apache/solr/cloud/overseer/ZkStateWriter.java
index 8059a2b16b6..1f12b9ad5f2 100644
--- a/solr/core/src/java/org/apache/solr/cloud/overseer/ZkStateWriter.java
+++ b/solr/core/src/java/org/apache/solr/cloud/overseer/ZkStateWriter.java
@@ -129,6 +129,8 @@ public class ZkStateWriter {
* a {@link org.apache.zookeeper.KeeperException.BadVersionException} this instance becomes
* unusable and must be discarded
*/
+ @SuppressWarnings(
+ "ReferenceEquality") // NO_OP is a unique sentinel; identity check is intentional
public ClusterState enqueueUpdate(
ClusterState prevState, List<ZkWriteCommand> cmds, ZkWriteCallback callback)
throws IllegalStateException, Exception {
@@ -189,6 +191,8 @@ public class ZkStateWriter {
return clusterState;
}
+ @SuppressWarnings(
+ "ReferenceEquality") // NO_OP is a unique sentinel; identity check is intentional
private boolean isNoOps(List<ZkWriteCommand> cmds) {
for (ZkWriteCommand cmd : cmds) {
if (cmd != NO_OP) return false;
@@ -229,6 +233,8 @@ public class ZkStateWriter {
* @throws KeeperException if any ZooKeeper operation results in an error
* @throws InterruptedException if the current thread is interrupted
*/
+ @SuppressWarnings(
+ "ReferenceEquality") // detecting "same map instance passed back in" means "flush all"
public ClusterState writePendingUpdates(
Map<String, ZkWriteCommand> updates, boolean resetPendingUpdateCounters)
throws IllegalStateException, KeeperException, InterruptedException {
diff --git a/solr/core/src/java/org/apache/solr/cloud/overseer/ZkWriteCommand.java b/solr/core/src/java/org/apache/solr/cloud/overseer/ZkWriteCommand.java
index f2d5466f760..a671aa3f749 100644
--- a/solr/core/src/java/org/apache/solr/cloud/overseer/ZkWriteCommand.java
+++ b/solr/core/src/java/org/apache/solr/cloud/overseer/ZkWriteCommand.java
@@ -49,6 +49,8 @@ public class ZkWriteCommand {
}
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // NO_OP is a unique sentinel; identity check is intentional
public String toString() {
return getClass().getSimpleName() + ": " + (this == NO_OP ? "no-op" : name + "=" + collection);
}
diff --git a/solr/core/src/java/org/apache/solr/core/CachingDirectoryFactory.java b/solr/core/src/java/org/apache/solr/core/CachingDirectoryFactory.java
index dcf084670f6..7d564542861 100644
--- a/solr/core/src/java/org/apache/solr/core/CachingDirectoryFactory.java
+++ b/solr/core/src/java/org/apache/solr/core/CachingDirectoryFactory.java
@@ -231,6 +231,7 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory {
// be sure the method is called with the sync lock on this object
// returns true if we closed the cacheValue, false if it will be closed later
+ @SuppressWarnings("ReferenceEquality") // CacheValue identity, not equality, is what matters here
private boolean closeCacheValue(CacheValue cacheValue, Set<CacheValue> deferRemove) {
log.debug("looking to close {} {}", cacheValue.path, cacheValue.closeEntries);
List<CloseListener> listeners = closeListeners.remove(cacheValue.directory);
@@ -308,6 +309,7 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory {
return vals.stream().sorted((a, b) -> b.path.compareTo(a.path)).collect(Collectors.toList());
}
+ @SuppressWarnings("ReferenceEquality") // CacheValue identity, not equality, is what matters here
private boolean maybeDeferClose(CacheValue maybeDefer) {
assert maybeDefer.deleteOnClose;
for (CacheValue maybeChildPath : byPathCache.values()) {
@@ -389,6 +391,8 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory {
* java.lang.String, boolean)
*/
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // same instance back from filterDirectory means "unfiltered"
public final Directory get(String path, DirContext dirContext, String rawLockType)
throws IOException {
String fullPath = normalize(path);
diff --git a/solr/core/src/java/org/apache/solr/core/CoreContainer.java b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
index 91871cd0d31..3c6feef32d5 100644
--- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java
+++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
@@ -1445,6 +1445,7 @@ public class CoreContainer {
return coreSorter;
}
+ @SuppressWarnings("ReferenceEquality") // SolrCore identity, not equality, is what matters here
protected SolrCore registerCore(
CoreDescriptor cd, SolrCore core, boolean registerInZk, boolean skipRecovery) {
if (core == null) {
diff --git a/solr/core/src/java/org/apache/solr/core/PluginBag.java b/solr/core/src/java/org/apache/solr/core/PluginBag.java
index 30bb8435214..27c33f3d3a5 100644
--- a/solr/core/src/java/org/apache/solr/core/PluginBag.java
+++ b/solr/core/src/java/org/apache/solr/core/PluginBag.java
@@ -229,7 +229,10 @@ public class PluginBag<T> implements AutoCloseable {
return old == null ? null : old.get();
}
- @SuppressWarnings({"unchecked"})
+ @SuppressWarnings({
+ "unchecked",
+ "ReferenceEquality" // detecting the same plugin instance re-registered vs. a real swap
+ })
public PluginHolder<T> put(String name, PluginHolder<T> plugin) {
Boolean registerApi = null; // i.e. register for V2
Boolean disableV1 = null; // i.e. do *not* register for v1
diff --git a/solr/core/src/java/org/apache/solr/core/SolrCore.java b/solr/core/src/java/org/apache/solr/core/SolrCore.java
index fe3bf4c9fe8..75175089b0c 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrCore.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java
@@ -2284,6 +2284,8 @@ public class SolrCore implements SolrInfoBean, Closeable {
*
* <p>This method acquires openSearcherLock - do not call with searchLock held!
*/
+ @SuppressWarnings(
+ "ReferenceEquality") // schema is only ever replaced wholesale, so identity is correct here
public RefCounted<SolrIndexSearcher> openNewSearcher(
boolean updateHandlerReopens, boolean realtime) {
if (isClosed()) { // catch some errors quicker
@@ -2500,6 +2502,8 @@ public class SolrCore implements SolrInfoBean, Closeable {
* SolrIndexSearcher}.
*/
// TODO waitSearcher should be an AtomicReference or something that is a more clear API
+ @SuppressWarnings(
+ "ReferenceEquality") // SolrIndexSearcher identity, not equality, is what matters here
public RefCounted<SolrIndexSearcher> getSearcher(
boolean forceNew,
boolean returnSearcher,
@@ -2786,6 +2790,8 @@ public class SolrCore implements SolrInfoBean, Closeable {
//
// onDeckSearchers will also be decremented (it should have been incremented
// as a result of opening a new searcher).
+ @SuppressWarnings(
+ "ReferenceEquality") // detecting re-registration of the exact same searcher holder
private void registerSearcher(RefCounted<SolrIndexSearcher> newSearcherHolder) {
synchronized (searcherLock) {
try {
diff --git a/solr/core/src/java/org/apache/solr/core/SolrPaths.java b/solr/core/src/java/org/apache/solr/core/SolrPaths.java
index dc2c245eada..9a9262872b4 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrPaths.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrPaths.java
@@ -123,6 +123,8 @@ public final class SolrPaths {
* Adds an allowed path. Detects "_ALL_" which means all paths are allowed. Does not detect "*"
* (not supported as a {@link Path} on Windows), see {@link #addPath(String)}.
*/
+ @SuppressWarnings(
+ "ReferenceEquality") // ALL_PATHS is a unique sentinel; identity check is intentional
public AllowPathBuilder addPath(Path path) {
if (path == null) {
return this;
diff --git a/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java b/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
index 206c7995e49..30d3503d7a9 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
@@ -216,6 +216,8 @@ public class SolrResourceLoader
*
* @param urls the URLs of files to add
*/
+ @SuppressWarnings(
+ "ReferenceEquality") // ClassLoader has no value-equality; identity check is intentional
synchronized void addToClassLoader(List<URL> urls) {
URLClassLoader newLoader = addURLsToClassLoader(classLoader, urls);
if (newLoader == classLoader) {
@@ -483,6 +485,8 @@ public class SolrResourceLoader
* @param subpackages the packages to be tried if the cname starts with solr.
* @return the loaded class. An exception is thrown if it fails
*/
+ @SuppressWarnings(
+ "ReferenceEquality") // detecting the default `packages` array vs. a caller-supplied one
public <T> Class<? extends T> findClass(
String cname, Class<T> expectedType, String... subpackages) {
if (subpackages == null || subpackages.length == 0 || subpackages == packages) {
@@ -694,6 +698,8 @@ public class SolrResourceLoader
}
}
+ @SuppressWarnings(
+ "ReferenceEquality") // detecting whether the same SolrConfig instance is being re-associated
protected final void setSolrConfig(SolrConfig config) {
if (this.config != null && this.config != config) {
throw new IllegalStateException("SolrConfig instance is already associated with this loader");
@@ -701,6 +707,9 @@ public class SolrResourceLoader
this.config = config;
}
+ @SuppressWarnings(
+ "ReferenceEquality") // detecting whether the same CoreContainer instance is being
+ // re-associated
protected final void setCoreContainer(CoreContainer coreContainer) {
if (this.coreContainer != null && this.coreContainer != coreContainer) {
throw new IllegalStateException(
diff --git a/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java b/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
index 7e429de374e..21d9754a9fd 100644
--- a/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
@@ -480,6 +480,8 @@ public class ReplicationHandler extends RequestHandlerBase
private volatile IndexFetcher currentIndexFetcher;
+ @SuppressWarnings(
+ "ReferenceEquality") // detecting the shared pollingIndexFetcher vs. a one-off, by identity
public IndexFetchResult doFetch(SolrParams solrParams, boolean forceReplication) {
String leaderUrl = solrParams.get(LEADER_URL, null);
if (!indexFetchLock.tryLock()) return IndexFetchResult.LOCK_OBTAIN_FAILED;
@@ -1446,6 +1448,8 @@ public class ReplicationHandler extends RequestHandlerBase
}
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // detecting the shared pollingIndexFetcher vs. a one-off
public void postClose(SolrCore core) {
if (pollingIndexFetcher != null) {
pollingIndexFetcher.destroy();
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java
index 494e3f89841..e1d02565b9b 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java
@@ -464,6 +464,8 @@ public class CoreAdminHandler extends RequestHandlerBase implements PermissionNa
}
}
+ @SuppressWarnings(
+ "ReferenceEquality") // detecting a cache-computed instance vs. our own taskObject
private void addTask(TaskObject taskObject) {
// Ensure task ID is not already in use
TaskObject taskInCache =
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/IndexSizeEstimator.java b/solr/core/src/java/org/apache/solr/handler/admin/IndexSizeEstimator.java
index 38eb8a464cf..96cc9be3a3b 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/IndexSizeEstimator.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/IndexSizeEstimator.java
@@ -585,6 +585,8 @@ public class IndexSizeEstimator {
}
}
+ @SuppressWarnings(
+ "ReferenceEquality") // detecting whether getMergeInstance() returned a new closeable clone
private void estimateStoredFields(Map<String, Object> result) throws IOException {
log.info("- estimating stored fields...");
Map<String, Map<String, Object>> stats = new HashMap<>();
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/SecurityConfHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/SecurityConfHandler.java
index 7e9476faf9e..c330b6f08b6 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/SecurityConfHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/SecurityConfHandler.java
@@ -316,6 +316,8 @@ public abstract class SecurityConfHandler extends RequestHandlerBase
apis.add(
new ReqHandlerToApi(this, authcSpecProvider) {
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // detecting whether the plugin instance was reloaded
public synchronized Map<String, JsonSchemaValidator> getCommandSchema() {
// it is possible that the Authentication plugin is modified since the last call.
// invalidate the cached commandSchema
@@ -336,6 +338,8 @@ public abstract class SecurityConfHandler extends RequestHandlerBase
apis.add(
new ApiBag.ReqHandlerToApi(this, authzSpecProvider) {
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // detecting whether the plugin instance was reloaded
public synchronized Map<String, JsonSchemaValidator> getCommandSchema() {
// it is possible that the Authorization plugin is modified since the last call.
// invalidate cached commandSchema
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/SystemInfoProvider.java b/solr/core/src/java/org/apache/solr/handler/admin/SystemInfoProvider.java
index 1af8b9a9c61..3006fb624a4 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/SystemInfoProvider.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/SystemInfoProvider.java
@@ -286,6 +286,8 @@ public class SystemInfoProvider {
}
/** Get Security Info */
+ // Identity against the internal singleton is intentionally stricter than equals().
+ @SuppressWarnings("ReferenceEquality")
public NodeSystemResponse.Security getSecurityInfo() {
NodeSystemResponse.Security info = new NodeSystemResponse.Security();
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/ClusterCommands.java b/solr/core/src/java/org/apache/solr/handler/admin/api/ClusterCommands.java
index 792642dbe6c..60cc18e483e 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/ClusterCommands.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/ClusterCommands.java
@@ -228,7 +228,7 @@ public class ClusterCommands extends AdminAPIBase implements ClusterCommandsApi
private static void setStatus(
GetClusterCommandStatusResponse response, RequestStatusState state, String requestId) {
final CommandStatus status = new CommandStatus();
- status.state = CommandStatus.State.valueOf(state.name());
+ status.state = CommandStatus.RequestState.valueOf(state.name());
status.msg = statusMessage(state, requestId);
response.status = status;
}
diff --git a/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java b/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java
index d251a7bfe4d..d221132c835 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java
@@ -643,6 +643,8 @@ public class RealTimeGetComponent extends SearchComponent {
*
* @see #getInputDocumentFromTlog(SolrCore, BytesRef, AtomicLong, Set, Resolution)
*/
+ @SuppressWarnings(
+ "ReferenceEquality") // DELETED is a unique sentinel; identity check is intentional
private static SolrInputDocument getInputDocumentFromTlog(
SolrCore core,
BytesRef idBytes,
@@ -755,6 +757,8 @@ public class RealTimeGetComponent extends SearchComponent {
* @param resolveStrategy {@link Resolution#DOC} or {@link Resolution#ROOT_WITH_CHILDREN}.
* @see Resolution
*/
+ @SuppressWarnings(
+ "ReferenceEquality") // DELETED is a unique sentinel; identity check is intentional
public static SolrInputDocument getInputDocument(
SolrCore core,
BytesRef idBytes,
diff --git a/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java b/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java
index aa85f9a69b4..e22356f5523 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java
@@ -191,6 +191,8 @@ public class ResponseBuilder {
return -1;
}
+ @SuppressWarnings(
+ "ReferenceEquality") // excluding "me" itself, by identity, from the other components
public void addRequest(SearchComponent me, ShardRequest sreq) {
outgoing.add(sreq);
if ((sreq.purpose & ShardRequest.PURPOSE_PRIVATE) == 0) {
diff --git a/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java b/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java
index 3e7a066841f..76f62bd7ca9 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java
@@ -513,6 +513,9 @@ public class SearchHandler extends RequestHandlerBase
}
/** Distributed request processing (AKA coordinator). */
+ @SuppressWarnings(
+ "ReferenceEquality") // ShardRequest.ALL_SHARDS is a unique sentinel; identity check is
+ // intentional
protected void processComponentsDistrib(
SolrQueryRequest req,
SolrQueryResponse rsp,
diff --git a/solr/core/src/java/org/apache/solr/handler/component/TermsComponent.java b/solr/core/src/java/org/apache/solr/handler/component/TermsComponent.java
index 36f22d69cdc..3f8694a37ab 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/TermsComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/TermsComponent.java
@@ -642,6 +642,8 @@ public class TermsComponent extends SearchComponent {
}
}
+ @SuppressWarnings(
+ "ReferenceEquality") // TermsEnum.EMPTY is a Lucene sentinel; identity check is intentional
private static void collectTermStates(
IndexReaderContext topReaderContext, TermStates[] contextArray, Term[] queryTerms)
throws IOException {
diff --git a/solr/core/src/java/org/apache/solr/handler/loader/JavabinLoader.java b/solr/core/src/java/org/apache/solr/handler/loader/JavabinLoader.java
index 0c8b47003ae..23ad278d491 100644
--- a/solr/core/src/java/org/apache/solr/handler/loader/JavabinLoader.java
+++ b/solr/core/src/java/org/apache/solr/handler/loader/JavabinLoader.java
@@ -141,6 +141,8 @@ public class JavabinLoader extends ContentStreamLoader {
}
}
+ @SuppressWarnings(
+ "ReferenceEquality") // END_OBJ is a unique sentinel; identity check is intentional
private void handleMultiStream(
SolrQueryRequest req,
SolrQueryResponse rsp,
diff --git a/solr/core/src/java/org/apache/solr/handler/tagger/TagLL.java b/solr/core/src/java/org/apache/solr/handler/tagger/TagLL.java
index a8f3682b479..1431c929f4a 100644
--- a/solr/core/src/java/org/apache/solr/handler/tagger/TagLL.java
+++ b/solr/core/src/java/org/apache/solr/handler/tagger/TagLL.java
@@ -95,6 +95,8 @@ public class TagLL {
* Removes this tag from the chain, connecting prevTag and nextTag. Does not modify "this"
* object's pointers, so the caller can refer to nextTag after removing it.
*/
+ @SuppressWarnings(
+ "ReferenceEquality") // linked-list node identity, not equality, is what matters here
public void removeLL() {
if (head[0] == this) head[0] = nextTag;
if (prevTag != null) {
@@ -105,6 +107,8 @@ public class TagLL {
}
}
+ @SuppressWarnings(
+ "ReferenceEquality") // linked-list node identity, not equality, is what matters here
void addBeforeLL(TagLL tag) {
assert tag.startOffset <= startOffset;
if (prevTag != null) {
diff --git a/solr/core/src/java/org/apache/solr/legacy/BBoxStrategy.java b/solr/core/src/java/org/apache/solr/legacy/BBoxStrategy.java
index ccbb5b2f8fc..3de20dced77 100644
--- a/solr/core/src/java/org/apache/solr/legacy/BBoxStrategy.java
+++ b/solr/core/src/java/org/apache/solr/legacy/BBoxStrategy.java
@@ -307,6 +307,9 @@ public class BBoxStrategy extends SpatialStrategy {
// }
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // SpatialOperation constants are singletons; identity check is
+ // intentional
public Query makeQuery(SpatialArgs args) {
Shape shape = args.getShape();
if (!(shape instanceof Rectangle bbox))
diff --git a/solr/core/src/java/org/apache/solr/logging/jul/JulWatcher.java b/solr/core/src/java/org/apache/solr/logging/jul/JulWatcher.java
index 9cb3acc0b0c..f9779b30455 100644
--- a/solr/core/src/java/org/apache/solr/logging/jul/JulWatcher.java
+++ b/solr/core/src/java/org/apache/solr/logging/jul/JulWatcher.java
@@ -84,6 +84,9 @@ public class JulWatcher extends LogWatcher<LogRecord> {
}
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // java.util.logging.Logger has no equals() override; identity check is
+ // intentional
public Collection<LoggerInfo> getAllLoggers() {
LogManager manager = LogManager.getLogManager();
diff --git a/solr/core/src/java/org/apache/solr/logging/log4j2/Log4j2Watcher.java b/solr/core/src/java/org/apache/solr/logging/log4j2/Log4j2Watcher.java
index f8c2391085f..4f2def7c462 100644
--- a/solr/core/src/java/org/apache/solr/logging/log4j2/Log4j2Watcher.java
+++ b/solr/core/src/java/org/apache/solr/logging/log4j2/Log4j2Watcher.java
@@ -177,6 +177,8 @@ public class Log4j2Watcher extends LogWatcher<LogEvent> {
}
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // fast-path identity check before the equals() fallback right after it
public Collection<LoggerInfo> getAllLoggers() {
Logger root = LogManager.getRootLogger();
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
diff --git a/solr/core/src/java/org/apache/solr/metrics/otel/instruments/DualRegistryAttributedLongCounter.java b/solr/core/src/java/org/apache/solr/metrics/otel/instruments/DualRegistryAttributedLongCounter.java
index 15fc27b85c5..9dbd9f8d2ef 100644
--- a/solr/core/src/java/org/apache/solr/metrics/otel/instruments/DualRegistryAttributedLongCounter.java
+++ b/solr/core/src/java/org/apache/solr/metrics/otel/instruments/DualRegistryAttributedLongCounter.java
@@ -27,6 +27,8 @@ public class DualRegistryAttributedLongCounter extends AttributedLongCounter {
private final AttributedLongCounter nodeCounter;
+ @SuppressWarnings(
+ "ReferenceEquality") // sanity check that two distinct counter instances were passed in
public DualRegistryAttributedLongCounter(
LongCounter coreCounter,
Attributes coreAttributes,
diff --git a/solr/core/src/java/org/apache/solr/metrics/otel/instruments/DualRegistryAttributedLongTimer.java b/solr/core/src/java/org/apache/solr/metrics/otel/instruments/DualRegistryAttributedLongTimer.java
index b42d869892c..c1707fffdef 100644
--- a/solr/core/src/java/org/apache/solr/metrics/otel/instruments/DualRegistryAttributedLongTimer.java
+++ b/solr/core/src/java/org/apache/solr/metrics/otel/instruments/DualRegistryAttributedLongTimer.java
@@ -27,6 +27,8 @@ public class DualRegistryAttributedLongTimer extends AttributedLongTimer {
private final AttributedLongTimer nodeTimer;
+ @SuppressWarnings(
+ "ReferenceEquality") // sanity check that two distinct histogram instances were passed in
public DualRegistryAttributedLongTimer(
LongHistogram coreHistogram,
Attributes coreAttributes,
diff --git a/solr/core/src/java/org/apache/solr/metrics/otel/instruments/DualRegistryAttributedLongUpDownCounter.java b/solr/core/src/java/org/apache/solr/metrics/otel/instruments/DualRegistryAttributedLongUpDownCounter.java
index 6cf505fb54e..fc98805b168 100644
--- a/solr/core/src/java/org/apache/solr/metrics/otel/instruments/DualRegistryAttributedLongUpDownCounter.java
+++ b/solr/core/src/java/org/apache/solr/metrics/otel/instruments/DualRegistryAttributedLongUpDownCounter.java
@@ -27,6 +27,8 @@ public class DualRegistryAttributedLongUpDownCounter extends AttributedLongUpDow
private final AttributedLongUpDownCounter nodeUpDownCounter;
+ @SuppressWarnings(
+ "ReferenceEquality") // sanity check that two distinct counter instances were passed in
public DualRegistryAttributedLongUpDownCounter(
LongUpDownCounter coreUpDownCounter,
Attributes coreAttributes,
diff --git a/solr/core/src/java/org/apache/solr/pkg/PackageListeners.java b/solr/core/src/java/org/apache/solr/pkg/PackageListeners.java
index 7535bb2c7fe..ff57f4775fa 100644
--- a/solr/core/src/java/org/apache/solr/pkg/PackageListeners.java
+++ b/solr/core/src/java/org/apache/solr/pkg/PackageListeners.java
@@ -60,6 +60,8 @@ public class PackageListeners {
}
}
+ @SuppressWarnings(
+ "ReferenceEquality") // removing the exact registered listener instance, not an equal one
public synchronized void removeListener(Listener listener) {
Iterator<Reference<Listener>> it = listeners.iterator();
while (it.hasNext()) {
diff --git a/solr/core/src/java/org/apache/solr/pkg/PackagePluginHolder.java b/solr/core/src/java/org/apache/solr/pkg/PackagePluginHolder.java
index 419cb033835..887b7b84dc1 100644
--- a/solr/core/src/java/org/apache/solr/pkg/PackagePluginHolder.java
+++ b/solr/core/src/java/org/apache/solr/pkg/PackagePluginHolder.java
@@ -90,6 +90,8 @@ public class PackagePluginHolder<T> extends PluginBag.PluginHolder<T> {
}
}
+ @SuppressWarnings(
+ "ReferenceEquality") // detecting the same package Version instance, not just an equal one
private synchronized void reload(SolrPackageLoader.SolrPackage pkg, SolrCore core) {
String lessThan = core.getSolrConfig().maxPackageVersion(info.pkgName);
SolrPackageLoader.SolrPackage.Version newest = pkg.getLatest(lessThan);
diff --git a/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java b/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java
index 6809e99e936..065255811cd 100644
--- a/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java
+++ b/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java
@@ -109,6 +109,7 @@ public abstract class TextResponseWriter implements TextWriter {
* NOTE: strict object equality check against {@link #rawReturnFields}; see javadocs for {@link
* #NO_RAW_FIELDS}
*/
+ @SuppressWarnings("ReferenceEquality") // strict object identity is intentional, see javadoc above
protected final boolean shouldWriteRaw(String fname, ReturnFields returnFields) {
return rawReturnFields == returnFields && rawFields.contains(fname);
}
diff --git a/solr/core/src/java/org/apache/solr/response/transform/RawValueTransformerFactory.java b/solr/core/src/java/org/apache/solr/response/transform/RawValueTransformerFactory.java
index b165b81e923..2c6b540e6ce 100644
--- a/solr/core/src/java/org/apache/solr/response/transform/RawValueTransformerFactory.java
+++ b/solr/core/src/java/org/apache/solr/response/transform/RawValueTransformerFactory.java
@@ -62,6 +62,8 @@ public class RawValueTransformerFactory extends TransformerFactory
}
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // QueryResponseWriter identity, not equality, is what matters here
public DocTransformer create(
String display,
SolrParams params,
diff --git a/solr/core/src/java/org/apache/solr/response/transform/ValueSourceAugmenter.java b/solr/core/src/java/org/apache/solr/response/transform/ValueSourceAugmenter.java
index e2fe53cf4d5..43c707980f0 100644
--- a/solr/core/src/java/org/apache/solr/response/transform/ValueSourceAugmenter.java
+++ b/solr/core/src/java/org/apache/solr/response/transform/ValueSourceAugmenter.java
@@ -143,6 +143,8 @@ public class ValueSourceAugmenter extends DocTransformer {
IntObjectHashMap<Object> cachedValuesById;
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // NULL_SENTINEL is a unique sentinel; identity check is intentional
public void transform(SolrDocument doc, int docid, DocIterationInfo docIterationInfo) {
Object cacheValue = (cachedValuesById != null) ? cachedValuesById.get(docid) : null;
if (cacheValue != null) {
diff --git a/solr/core/src/java/org/apache/solr/schema/BBoxField.java b/solr/core/src/java/org/apache/solr/schema/BBoxField.java
index 4b85573ad73..fbf0e051d03 100644
--- a/solr/core/src/java/org/apache/solr/schema/BBoxField.java
+++ b/solr/core/src/java/org/apache/solr/schema/BBoxField.java
@@ -75,6 +75,7 @@ public class BBoxField extends AbstractSpatialFieldType<BBoxStrategy> implements
}
@Override
+ @SuppressWarnings("ReferenceEquality") // FieldType identity, not equality, is what matters here
public void inform(IndexSchema schema) {
this.schema = schema;
FieldType numberType = schema.getFieldTypeByName(numberTypeName);
diff --git a/solr/core/src/java/org/apache/solr/schema/IndexSchema.java b/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
index 3980483fb7e..066c35c3811 100644
--- a/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
+++ b/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
@@ -2002,6 +2002,7 @@ public class IndexSchema {
}
/** Informs analyzers used by a fieldType. */
+ @SuppressWarnings("ReferenceEquality") // ref comparison is correct here (vs. equals)
private void informResourceLoaderAwareObjectsForFieldType(FieldType fieldType) {
// must inform any sub-components used in the
// tokenizer chain if they are ResourceLoaderAware
diff --git a/solr/core/src/java/org/apache/solr/schema/LatLonPointSpatialField.java b/solr/core/src/java/org/apache/solr/schema/LatLonPointSpatialField.java
index 238666d7165..0a2d4fd38c8 100644
--- a/solr/core/src/java/org/apache/solr/schema/LatLonPointSpatialField.java
+++ b/solr/core/src/java/org/apache/solr/schema/LatLonPointSpatialField.java
@@ -157,6 +157,9 @@ public class LatLonPointSpatialField
}
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // SpatialOperation constants are singletons; identity check is
+ // intentional
public Query makeQuery(SpatialArgs args) {
if (args.getOperation() != SpatialOperation.Intersects) {
throw new UnsupportedSpatialOperation(args.getOperation());
diff --git a/solr/core/src/java/org/apache/solr/schema/SchemaManager.java b/solr/core/src/java/org/apache/solr/schema/SchemaManager.java
index 05efe512c21..131e701199e 100644
--- a/solr/core/src/java/org/apache/solr/schema/SchemaManager.java
+++ b/solr/core/src/java/org/apache/solr/schema/SchemaManager.java
@@ -493,6 +493,8 @@ public class SchemaManager {
}
}
+ @SuppressWarnings(
+ "ReferenceEquality") // detecting a self-referencing exception cause loop, by identity
public static String getErrorStr(Exception e) {
StringBuilder sb = new StringBuilder();
Throwable cause = e;
diff --git a/solr/core/src/java/org/apache/solr/search/CaffeineCache.java b/solr/core/src/java/org/apache/solr/search/CaffeineCache.java
index e43acb704cc..60ccc26c7aa 100644
--- a/solr/core/src/java/org/apache/solr/search/CaffeineCache.java
+++ b/solr/core/src/java/org/apache/solr/search/CaffeineCache.java
@@ -271,6 +271,7 @@ public class CaffeineCache<K, V> extends SolrCacheBase
}
@Override
+ @SuppressWarnings("ReferenceEquality") // intentional, see the comment below re: Caffeine behavior
public V put(K key, V val) {
inserts.increment();
V old = cache.asMap().put(key, val);
diff --git a/solr/core/src/java/org/apache/solr/search/CollapsingQParserPlugin.java b/solr/core/src/java/org/apache/solr/search/CollapsingQParserPlugin.java
index 044b9894d97..de683b204d5 100644
--- a/solr/core/src/java/org/apache/solr/search/CollapsingQParserPlugin.java
+++ b/solr/core/src/java/org/apache/solr/search/CollapsingQParserPlugin.java
@@ -2997,7 +2997,11 @@ public class CollapsingQParserPlugin extends QParserPlugin {
* Constructs an instance based on the (raw, un-rewritten) SortFields to be used, and an initial
* number of expected groups (will grow as needed).
*/
- @SuppressWarnings({"rawtypes"})
+ @SuppressWarnings({
+ "rawtypes",
+ "ReferenceEquality" // SortField.STRING_LAST is a Lucene sentinel; identity check is
+ // intentional
+ })
public SortFieldsCompare(SortField[] sorts, int initNumGroups) {
this.sorts = sorts;
numClauses = sorts.length;
@@ -3140,7 +3144,11 @@ public class CollapsingQParserPlugin extends QParserPlugin {
* overwrites them (and returns true) if this document is the new group head in accordance with
* the SortFields. (otherwise returns false)
*/
- @SuppressWarnings({"unchecked", "rawtypes"})
+ @SuppressWarnings({
+ "unchecked",
+ "rawtypes",
+ "ReferenceEquality" // detecting whether the same DocValues instance is still in use
+ })
private boolean testAndSetGroupValues(Object[] values, int contextDoc) throws IOException {
Object[] stash = new Object[numClauses];
int lastCompare = 0;
diff --git a/solr/core/src/java/org/apache/solr/search/DocValuesIteratorCache.java b/solr/core/src/java/org/apache/solr/search/DocValuesIteratorCache.java
index eba8a731881..43167543744 100644
--- a/solr/core/src/java/org/apache/solr/search/DocValuesIteratorCache.java
+++ b/solr/core/src/java/org/apache/solr/search/DocValuesIteratorCache.java
@@ -94,6 +94,7 @@ public class DocValuesIteratorCache {
}
}
+ @SuppressWarnings("ReferenceEquality") // NONE is a unique sentinel; identity check is intentional
public FieldDocValuesSupplier getSupplier(String fieldName) {
FieldDocValuesSupplier ret = getSupplier.apply(fieldName);
return ret == NONE ? null : ret;
diff --git a/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java b/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java
index 4dd2745bf1e..809c0305be3 100644
--- a/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java
+++ b/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java
@@ -1488,6 +1488,7 @@ public class ExtendedDismaxQParser extends QParser {
}
}
+ @SuppressWarnings("ReferenceEquality") // Analyzer identity, not equality, is what matters here
private Analyzer noStopwordFilterAnalyzer(String fieldName) {
FieldType ft = parser.getReq().getSchema().getFieldType(fieldName);
Analyzer qa = ft.getQueryAnalyzer();
diff --git a/solr/core/src/java/org/apache/solr/search/GraphTermsQParserPlugin.java b/solr/core/src/java/org/apache/solr/search/GraphTermsQParserPlugin.java
index f7bfd3b7dc2..d898bdcce03 100644
--- a/solr/core/src/java/org/apache/solr/search/GraphTermsQParserPlugin.java
+++ b/solr/core/src/java/org/apache/solr/search/GraphTermsQParserPlugin.java
@@ -211,6 +211,9 @@ public class GraphTermsQParserPlugin extends QParserPlugin {
}
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // id is a unique marker Object created per non-clone construction, so
+ // identity is the intended equality check (clones share it, independent instances don't)
public boolean equals(Object other) {
return sameClassAs(other) && id == ((GraphTermsQuery) other).id;
}
@@ -290,6 +293,8 @@ public class GraphTermsQParserPlugin extends QParserPlugin {
};
}
+ @SuppressWarnings(
+ "ReferenceEquality") // TermsEnum.EMPTY is a Lucene sentinel; identity check is intentional
private void collectTermStates(
IndexReader reader,
List<LeafReaderContext> leaves,
diff --git a/solr/core/src/java/org/apache/solr/search/JoinQuery.java b/solr/core/src/java/org/apache/solr/search/JoinQuery.java
index 09fb728e7f9..fd1d0e7bdfd 100644
--- a/solr/core/src/java/org/apache/solr/search/JoinQuery.java
+++ b/solr/core/src/java/org/apache/solr/search/JoinQuery.java
@@ -105,6 +105,7 @@ class JoinQuery extends Query implements SolrSearcherRequirer {
ResponseBuilder rb;
ScoreMode scoreMode;
+ @SuppressWarnings("ReferenceEquality") // SolrCore identity, not equality, is what matters here
public JoinQueryWeight(SolrIndexSearcher searcher, ScoreMode scoreMode, float boost) {
super(JoinQuery.this, boost);
this.scoreMode = scoreMode;
@@ -248,6 +249,8 @@ class JoinQuery extends Query implements SolrSearcherRequirer {
return result;
}
+ @SuppressWarnings(
+ "ReferenceEquality") // SolrIndexSearcher identity, not equality, is what matters here
public DocSet getDocSetEnumerate() throws IOException {
FixedBitSet resultBits = null;
diff --git a/solr/core/src/java/org/apache/solr/search/QueryResultKey.java b/solr/core/src/java/org/apache/solr/search/QueryResultKey.java
index 671da8cda54..e76fb6e5716 100644
--- a/solr/core/src/java/org/apache/solr/search/QueryResultKey.java
+++ b/solr/core/src/java/org/apache/solr/search/QueryResultKey.java
@@ -144,6 +144,7 @@ public final class QueryResultKey implements Accountable {
*
* @return true if the lists of equivalent other then the ordering
*/
+ @SuppressWarnings("ReferenceEquality") // fast path: takes care of identity and null cases
private static boolean unorderedCompare(List<Query> fqList1, List<Query> fqList2) {
// Do fast version first, expecting that filters are usually in the same order
//
diff --git a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
index e7786f71d3b..0a5c9c7d2ad 100644
--- a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
+++ b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
@@ -965,6 +965,8 @@ public class SolrIndexSearcher extends IndexSearcher implements Closeable, SolrI
return new BitDocSet(bs, answer.size());
}
+ @SuppressWarnings(
+ "ReferenceEquality") // detecting whether makeBitDocSet had to allocate a new instance
public BitDocSet getDocSetBits(Query q) throws IOException {
DocSet answer = getDocSet(q);
BitDocSet answerBits = makeBitDocSet(answer);
diff --git a/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessor.java b/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessor.java
index 2dca4a5a35b..13b93c66eab 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessor.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessor.java
@@ -320,6 +320,7 @@ abstract class FacetFieldProcessor extends FacetProcessor<FacetField> {
/**
* Processes the collected data to finds the top slots, and composes it in the response NamedList.
*/
+ @SuppressWarnings("ReferenceEquality") // SlotAcc identity, not equality, is what matters here
SimpleOrderedMap<Object> findTopSlots(
final int numSlots,
final int slotCardinality,
@@ -578,6 +579,7 @@ abstract class FacetFieldProcessor extends FacetProcessor<FacetField> {
}
/** Helper method used solely when looping over buckets to be returned in findTopSlots */
+ @SuppressWarnings("ReferenceEquality") // SlotAcc identity, not equality, is what matters here
private void fillBucketFromSlot(SimpleOrderedMap<Object> target, Slot slot, SlotAcc resortAcc)
throws IOException {
final int slotOrd = slot.slot;
@@ -846,6 +848,7 @@ abstract class FacetFieldProcessor extends FacetProcessor<FacetField> {
}
@Override
+ @SuppressWarnings("ReferenceEquality") // SlotAcc identity, not equality, is what matters here
public SlotAcc registerSweepingAccs(SweepingCountSlotAcc baseSweepingAcc) {
final FacetFieldProcessor p = (FacetFieldProcessor) fcontext.processor;
int j = 0;
diff --git a/solr/core/src/java/org/apache/solr/search/facet/RelatednessAgg.java b/solr/core/src/java/org/apache/solr/search/facet/RelatednessAgg.java
index f55690bbd55..d35f5f46dec 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/RelatednessAgg.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/RelatednessAgg.java
@@ -138,6 +138,8 @@ public class RelatednessAgg extends AggValueSource {
}
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // FacetContext identity, not equality, is what matters here
public SlotAcc createSlotAcc(FacetContext fcontext, long numDocs, int numSlots)
throws IOException {
// TODO: Ideally this is where we should check fgQ/bgQ for 'null' and apply defaults...
diff --git a/solr/core/src/java/org/apache/solr/search/facet/SlotAcc.java b/solr/core/src/java/org/apache/solr/search/facet/SlotAcc.java
index ceba52b6fcb..904a489aab2 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/SlotAcc.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/SlotAcc.java
@@ -226,6 +226,8 @@ public abstract class SlotAcc implements Closeable {
return values;
}
+ @SuppressWarnings(
+ "ReferenceEquality") // fast-path: values array is prefilled with defaultValue already
public <T> T[] resize(T[] old, T defaultValue) {
@SuppressWarnings({"unchecked"})
T[] values = (T[]) Array.newInstance(old.getClass().getComponentType(), getNewSize());
@@ -757,6 +759,7 @@ public abstract class SlotAcc implements Closeable {
* @param toAcc - the replacement {@link SlotAcc}
* @see SweepableSlotAcc#registerSweepingAccs(SweepingCountSlotAcc)
*/
+ @SuppressWarnings("ReferenceEquality") // SlotAcc identity, not equality, is what matters here
public void registerMapping(SlotAcc fromAcc, SlotAcc toAcc) {
assert fromAcc.key.equals(toAcc.key);
output.add(toAcc);
diff --git a/solr/core/src/java/org/apache/solr/search/facet/UnInvertedField.java b/solr/core/src/java/org/apache/solr/search/facet/UnInvertedField.java
index 5ddd4705116..4da65e04bc8 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/UnInvertedField.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/UnInvertedField.java
@@ -633,6 +633,8 @@ public class UnInvertedField extends DocTermOrds {
}
// Returns null if not already populated
+ @SuppressWarnings(
+ "ReferenceEquality") // uifPlaceholder is a unique sentinel; identity check is intentional
public static UnInvertedField checkUnInvertedField(String field, SolrIndexSearcher searcher)
throws IOException {
SolrCache<String, UnInvertedField> cache = searcher.getFieldValueCache();
diff --git a/solr/core/src/java/org/apache/solr/security/AllowListUrlChecker.java b/solr/core/src/java/org/apache/solr/security/AllowListUrlChecker.java
index 039ce146f4d..5c85c4ee776 100644
--- a/solr/core/src/java/org/apache/solr/security/AllowListUrlChecker.java
+++ b/solr/core/src/java/org/apache/solr/security/AllowListUrlChecker.java
@@ -160,6 +160,8 @@ public class AllowListUrlChecker {
* Gets the set of live hosts urls (host:port) built from the set of live nodes. The set is cached
* to be reused until the live nodes change.
*/
+ @SuppressWarnings(
+ "ReferenceEquality") // live-nodes set is replaced wholesale, so identity means "unchanged"
private Set<String> getLiveHostUrls(ClusterState clusterState) {
if (clusterState == null) {
return Set.of();
diff --git a/solr/core/src/java/org/apache/solr/security/PKIAuthenticationPlugin.java b/solr/core/src/java/org/apache/solr/security/PKIAuthenticationPlugin.java
index b069218ee48..6f378c18356 100644
--- a/solr/core/src/java/org/apache/solr/security/PKIAuthenticationPlugin.java
+++ b/solr/core/src/java/org/apache/solr/security/PKIAuthenticationPlugin.java
@@ -366,6 +366,8 @@ public class PKIAuthenticationPlugin extends AuthenticationPlugin
listenerFactory.setDelegate(() -> listener);
}
+ // Identity against the internal singleton is intentionally stricter than equals().
+ @SuppressWarnings("ReferenceEquality")
public boolean needsAuthorization(HttpServletRequest req) {
return req.getUserPrincipal() != CLUSTER_MEMBER_NODE;
}
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 cec6cf3346b..0002e917d46 100644
--- a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
+++ b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
@@ -433,6 +433,8 @@ public class HttpSolrCall {
}
/** This method processes the request. */
+ @SuppressWarnings(
+ "ReferenceEquality") // detecting whether we're still at the outermost exception, by identity
public Action call() throws IOException {
if (cores == null) {
diff --git a/solr/core/src/java/org/apache/solr/servlet/RequestRateLimiter.java b/solr/core/src/java/org/apache/solr/servlet/RequestRateLimiter.java
index 0901a0e2873..bc4bba0ec18 100644
--- a/solr/core/src/java/org/apache/solr/servlet/RequestRateLimiter.java
+++ b/solr/core/src/java/org/apache/solr/servlet/RequestRateLimiter.java
@@ -90,6 +90,8 @@ public class RequestRateLimiter {
* Handles an incoming request. returns a metadata object representing the metadata for the
* acquired slot, if acquired. If a slot is not acquired, returns a null metadata object.
*/
+ @SuppressWarnings(
+ "ReferenceEquality") // detecting whether the pools are the same shared Semaphore instance
public SlotReservation handleRequest() throws InterruptedException {
if (!rateLimiterConfig.isEnabled) {
@@ -135,6 +137,8 @@ public class RequestRateLimiter {
* @lucene.experimental -- Can cause slots to be blocked if a request borrows a slot and is itself
* long lived.
*/
+ @SuppressWarnings(
+ "ReferenceEquality") // detecting whether the pools are the same shared Semaphore instance
public SlotReservation allowSlotBorrowing() throws InterruptedException {
if (borrowableSlotsPool == null) {
return null;
diff --git a/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java b/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java
index 42531d5fd4a..eb1a80773a7 100644
--- a/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java
+++ b/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java
@@ -270,7 +270,11 @@ public class SolrRequestParsers {
* @param charset to be used to decode resulting bytes after %-decoding
* @param map place all parameters in this map
*/
- @SuppressWarnings({"fallthrough", "resource"})
+ @SuppressWarnings({
+ "fallthrough",
+ "resource",
+ "ReferenceEquality" // currentStream points at keyStream or valueStream; identity is the flag
+ })
static long parseFormDataContent(
final InputStream postContent,
final long maxLen,
diff --git a/solr/core/src/java/org/apache/solr/spelling/ConjunctionSolrSpellChecker.java b/solr/core/src/java/org/apache/solr/spelling/ConjunctionSolrSpellChecker.java
index e031ade9938..dc67b47cb17 100644
--- a/solr/core/src/java/org/apache/solr/spelling/ConjunctionSolrSpellChecker.java
+++ b/solr/core/src/java/org/apache/solr/spelling/ConjunctionSolrSpellChecker.java
@@ -45,6 +45,7 @@ public class ConjunctionSolrSpellChecker extends SolrSpellChecker {
private List<SolrSpellChecker> checkers = new ArrayList<>();
private boolean initialized = false;
+ @SuppressWarnings("ReferenceEquality") // Analyzer identity, not equality, is what matters here
public void addChecker(SolrSpellChecker checker) {
if (initialized) {
throw new IllegalStateException("Need to add checkers before calling init()");
diff --git a/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java b/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java
index 76183c7f5a5..76276228a86 100644
--- a/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java
+++ b/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java
@@ -176,6 +176,7 @@ public class DirectUpdateHandler2 extends UpdateHandler
}
}
+ @SuppressWarnings("ReferenceEquality") // UpdateLog identity, not equality, is what matters here
public DirectUpdateHandler2(SolrCore core, UpdateHandler updateHandler) {
super(core, updateHandler.getUpdateLog(), false);
solrCoreState = core.getSolrCoreState();
diff --git a/solr/core/src/java/org/apache/solr/update/MemOutputStream.java b/solr/core/src/java/org/apache/solr/update/MemOutputStream.java
index 345d35bb193..6619a740d8d 100644
--- a/solr/core/src/java/org/apache/solr/update/MemOutputStream.java
+++ b/solr/core/src/java/org/apache/solr/update/MemOutputStream.java
@@ -32,6 +32,9 @@ public class MemOutputStream extends FastOutputStream {
}
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // arrays don't override equals(), so identity is the only real
+ // comparison
public void flush(byte[] arr, int offset, int len) throws IOException {
if (arr == buf && offset == 0 && len == buf.length) {
buffers.add(buf); // steal the buffer
diff --git a/solr/core/src/java/org/apache/solr/update/PeerSync.java b/solr/core/src/java/org/apache/solr/update/PeerSync.java
index 7d69b4de9c6..2552b898789 100644
--- a/solr/core/src/java/org/apache/solr/update/PeerSync.java
+++ b/solr/core/src/java/org/apache/solr/update/PeerSync.java
@@ -455,6 +455,9 @@ public class PeerSync implements SolrMetricProducer {
}
}
+ @SuppressWarnings(
+ "ReferenceEquality") // MissedUpdatesRequest constants are singletons; identity check is
+ // intentional
private boolean handleVersions(ShardResponse srsp) {
// we retrieved the last N updates from the replica
@SuppressWarnings({"unchecked"})
@@ -861,6 +864,9 @@ public class PeerSync implements SolrMetricProducer {
this.nUpdates = nUpdates;
}
+ @SuppressWarnings(
+ "ReferenceEquality") // MissedUpdatesRequest constants are singletons; identity check is
+ // intentional
public MissedUpdatesRequest find(List<Long> otherVersions, Object updateFrom) {
otherVersions.sort(absComparator);
if (debug) {
diff --git a/solr/core/src/java/org/apache/solr/update/PeerSyncWithLeader.java b/solr/core/src/java/org/apache/solr/update/PeerSyncWithLeader.java
index 272e610718b..a77274e9f5e 100644
--- a/solr/core/src/java/org/apache/solr/update/PeerSyncWithLeader.java
+++ b/solr/core/src/java/org/apache/solr/update/PeerSyncWithLeader.java
@@ -217,6 +217,9 @@ public class PeerSyncWithLeader implements SolrMetricProducer {
}
}
+ @SuppressWarnings(
+ "ReferenceEquality") // MissedUpdatesRequest constants are singletons; identity check is
+ // intentional
private boolean doSync(List<Long> ourUpdates, long ourLowThreshold, long ourHighThreshold) {
// get leader's recent versions and fingerprint
// note: by getting leader's versions later, we guarantee that leader's versions always super
@@ -246,6 +249,9 @@ public class PeerSyncWithLeader implements SolrMetricProducer {
return false;
}
+ @SuppressWarnings(
+ "ReferenceEquality") // MissedUpdatesRequest constants are singletons; identity check is
+ // intentional
private MissedUpdatesRequest buildMissedUpdatesRequest(NamedList<Object> rsp) {
// we retrieved the last N updates from the replica
@SuppressWarnings({"unchecked"})
@@ -430,6 +436,9 @@ public class PeerSyncWithLeader implements SolrMetricProducer {
this.nUpdates = nUpdates;
}
+ @SuppressWarnings(
+ "ReferenceEquality") // MissedUpdatesRequest constants are singletons; identity check is
+ // intentional
public MissedUpdatesRequest find(List<Long> leaderVersions, Object updateFrom) {
leaderVersions.sort(absComparator);
log.debug("{} sorted versions from {} = {}", logPrefix, updateFrom, leaderVersions);
diff --git a/solr/core/src/java/org/apache/solr/update/SolrIndexConfig.java b/solr/core/src/java/org/apache/solr/update/SolrIndexConfig.java
index b35a9b3651f..70330b89c71 100644
--- a/solr/core/src/java/org/apache/solr/update/SolrIndexConfig.java
+++ b/solr/core/src/java/org/apache/solr/update/SolrIndexConfig.java
@@ -196,6 +196,9 @@ public class SolrIndexConfig implements MapWriter {
}
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // InfoStream.NO_OUTPUT is a Lucene sentinel; identity check is
+ // intentional
public void writeMap(EntryWriter ew) throws IOException {
ew.put("useCompoundFile", useCompoundFile)
.put("maxBufferedDocs", maxBufferedDocs)
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 17fd8477b27..2b0f202a4bd 100644
--- a/solr/core/src/java/org/apache/solr/update/UpdateLog.java
+++ b/solr/core/src/java/org/apache/solr/update/UpdateLog.java
@@ -734,6 +734,8 @@ public class UpdateLog implements PluginInfoInitialized, SolrMetricProducer {
/* Takes over ownership of the log, keeping it until no longer needed
and then decrementing its reference and dropping it.
*/
+ @SuppressWarnings(
+ "ReferenceEquality") // TransactionLog identity, not equality, is what matters here
protected synchronized void addOldLog(TransactionLog oldLog, boolean removeOld) {
if (oldLog == null) return;
@@ -1546,6 +1548,8 @@ public class UpdateLog implements PluginInfoInitialized, SolrMetricProducer {
* @param commitVersion any updates that have version larger than the commitVersion will be copied
* over
*/
+ @SuppressWarnings(
+ "ReferenceEquality") // TransactionLog identity, not equality, is what matters here
public void copyOverOldUpdates(long commitVersion, TransactionLog oldTlog) {
copyOverOldUpdatesCounter.inc();
@@ -1701,7 +1705,10 @@ public class UpdateLog implements PluginInfoInitialized, SolrMetricProducer {
close(committed, false);
}
- @SuppressWarnings("try")
+ @SuppressWarnings({
+ "try",
+ "ReferenceEquality" // TransactionLog identity, not equality, is what matters here
+ })
public void close(boolean committed, boolean deleteOnClose) {
try (Closeable c = releaseTlogDir) {
recoveryExecutor.shutdown(); // no new tasks
diff --git a/solr/core/src/java/org/apache/solr/update/processor/AllValuesOrNoneFieldMutatingUpdateProcessor.java b/solr/core/src/java/org/apache/solr/update/processor/AllValuesOrNoneFieldMutatingUpdateProcessor.java
index fb4a9de1d8a..b7436751a2e 100644
--- a/solr/core/src/java/org/apache/solr/update/processor/AllValuesOrNoneFieldMutatingUpdateProcessor.java
+++ b/solr/core/src/java/org/apache/solr/update/processor/AllValuesOrNoneFieldMutatingUpdateProcessor.java
@@ -74,6 +74,9 @@ public abstract class AllValuesOrNoneFieldMutatingUpdateProcessor
protected abstract Object mutateValue(final Object srcVal);
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // *_SINGLETON constants are unique sentinels; identity check is
+ // intentional
protected final SolrInputField mutate(final SolrInputField srcField) {
Collection<Object> vals = srcField.getValues();
if (vals == null || vals.isEmpty()) return srcField;
diff --git a/solr/core/src/java/org/apache/solr/update/processor/AtomicUpdateDocumentMerger.java b/solr/core/src/java/org/apache/solr/update/processor/AtomicUpdateDocumentMerger.java
index 3cdb0706980..5bf1e6b77da 100644
--- a/solr/core/src/java/org/apache/solr/update/processor/AtomicUpdateDocumentMerger.java
+++ b/solr/core/src/java/org/apache/solr/update/processor/AtomicUpdateDocumentMerger.java
@@ -383,6 +383,9 @@ public class AtomicUpdateDocumentMerger {
* false is returned. A false return indicates that this update can be re-tried as a full
* atomic update. Returns true if the in-place update succeeds.
*/
+ @SuppressWarnings(
+ "ReferenceEquality") // RealTimeGetComponent.DELETED is a unique sentinel; identity check is
+ // intentional
public boolean doInPlaceUpdateMerge(AddUpdateCommand cmd, Set<String> updatedFields)
throws IOException {
SolrInputDocument inputDoc = cmd.getSolrInputDocument();
diff --git a/solr/core/src/java/org/apache/solr/update/processor/DocBasedVersionConstraintsProcessor.java b/solr/core/src/java/org/apache/solr/update/processor/DocBasedVersionConstraintsProcessor.java
index cbec1472649..7a6dbcde04d 100644
--- a/solr/core/src/java/org/apache/solr/update/processor/DocBasedVersionConstraintsProcessor.java
+++ b/solr/core/src/java/org/apache/solr/update/processor/DocBasedVersionConstraintsProcessor.java
@@ -188,6 +188,8 @@ public class DocBasedVersionConstraintsProcessor extends UpdateRequestProcessor
}
}
+ @SuppressWarnings(
+ "ReferenceEquality") // DELETED is a unique sentinel; identity check is intentional
private DocFoundAndOldUserAndSolrVersions getOldUserVersionsFromFieldCache(
BytesRef indexedDocId) {
SolrInputDocument oldDoc =
diff --git a/solr/core/src/java/org/apache/solr/update/processor/FieldMutatingUpdateProcessor.java b/solr/core/src/java/org/apache/solr/update/processor/FieldMutatingUpdateProcessor.java
index 8593294b6f2..25b0d5a96fa 100644
--- a/solr/core/src/java/org/apache/solr/update/processor/FieldMutatingUpdateProcessor.java
+++ b/solr/core/src/java/org/apache/solr/update/processor/FieldMutatingUpdateProcessor.java
@@ -132,6 +132,9 @@ public abstract class FieldMutatingUpdateProcessor extends UpdateRequestProcesso
* @return Either a new FieldNameSelector or one of the input selectors if the combination lends
* itself to optimization.
*/
+ @SuppressWarnings(
+ "ReferenceEquality") // SELECT_NO_FIELDS/SELECT_ALL_FIELDS are unique sentinels; identity
+ // check is intentional
public static FieldNameSelector wrap(
final FieldNameSelector includes, final FieldNameSelector excludes) {
diff --git a/solr/core/src/java/org/apache/solr/update/processor/FieldValueMutatingUpdateProcessor.java b/solr/core/src/java/org/apache/solr/update/processor/FieldValueMutatingUpdateProcessor.java
index 1d81d6d84ed..4e41bb61f72 100644
--- a/solr/core/src/java/org/apache/solr/update/processor/FieldValueMutatingUpdateProcessor.java
+++ b/solr/core/src/java/org/apache/solr/update/processor/FieldValueMutatingUpdateProcessor.java
@@ -57,6 +57,9 @@ public abstract class FieldValueMutatingUpdateProcessor extends FieldMutatingUpd
protected abstract Object mutateValue(final Object src);
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // DELETE_VALUE_SINGLETON is a unique sentinel; identity check is
+ // intentional
protected final SolrInputField mutate(final SolrInputField src) {
Collection<Object> values = src.getValues();
if (values == null) return src; // don't mutate
diff --git a/solr/core/src/java/org/apache/solr/update/processor/SkipExistingDocumentsProcessorFactory.java b/solr/core/src/java/org/apache/solr/update/processor/SkipExistingDocumentsProcessorFactory.java
index b93d2ef2527..59281eb4cb8 100644
--- a/solr/core/src/java/org/apache/solr/update/processor/SkipExistingDocumentsProcessorFactory.java
+++ b/solr/core/src/java/org/apache/solr/update/processor/SkipExistingDocumentsProcessorFactory.java
@@ -191,6 +191,8 @@ public class SkipExistingDocumentsProcessorFactory extends UpdateRequestProcesso
return this.skipUpdateIfMissing;
}
+ @SuppressWarnings(
+ "ReferenceEquality") // DELETED is a unique sentinel; identity check is intentional
boolean doesDocumentExist(BytesRef indexedDocId) {
assert null != indexedDocId;
diff --git a/solr/core/src/test/org/apache/solr/TestGroupingSearch.java b/solr/core/src/test/org/apache/solr/TestGroupingSearch.java
index 4ae2b55becb..c2f82da4989 100644
--- a/solr/core/src/test/org/apache/solr/TestGroupingSearch.java
+++ b/solr/core/src/test/org/apache/solr/TestGroupingSearch.java
@@ -1585,6 +1585,7 @@ public class TestGroupingSearch extends SolrTestCaseJ4 {
}
@Test
+ @SuppressWarnings("ReferenceEquality")
public void testRandomGrouping() throws Exception {
/*
* updateJ("{\"add\":{\"doc\":{\"id\":\"77\"}}}", params("commit","true"));
@@ -1725,6 +1726,8 @@ public class TestGroupingSearch extends SolrTestCaseJ4 {
// now sort the groups
// if sort != group.sort, we need to find the max doc by "sort"
+ // Identity check: groupComparator may deliberately be set to the same instance as
+ // sortComparator above.
if (groupComparator != sortComparator) {
for (Grp grp : groups.values()) grp.setMaxDoc(sortComparator);
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/LeaderElectionIntegrationTest.java b/solr/core/src/test/org/apache/solr/cloud/LeaderElectionIntegrationTest.java
index 2e190f60f89..6b23340af58 100644
--- a/solr/core/src/test/org/apache/solr/cloud/LeaderElectionIntegrationTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/LeaderElectionIntegrationTest.java
@@ -56,6 +56,7 @@ public class LeaderElectionIntegrationTest extends SolrCloudTestCase {
}
@Test
+ @SuppressWarnings("ReferenceEquality")
public void testSimpleSliceLeaderElection() throws Exception {
String collection = "collection1";
createCollection(collection);
@@ -126,6 +127,7 @@ public class LeaderElectionIntegrationTest extends SolrCloudTestCase {
// kill everyone but the first leader that should have reconnected by now
for (JettySolrRunner jetty2 : cluster.getJettySolrRunners()) {
+ // Identity check: skip the one instance we want to keep running.
if (jetty != jetty2) {
jetty2.stop();
}
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/TestApiFramework.java b/solr/core/src/test/org/apache/solr/handler/admin/TestApiFramework.java
index 101ee2a09b3..e581c574016 100644
--- a/solr/core/src/test/org/apache/solr/handler/admin/TestApiFramework.java
+++ b/solr/core/src/test/org/apache/solr/handler/admin/TestApiFramework.java
@@ -278,12 +278,14 @@ public class TestApiFramework extends SolrTestCaseJ4 {
return rsp;
}
+ @SuppressWarnings("ReferenceEquality")
private SolrQueryResponse invoke(
PluginBag<SolrRequestHandler> reqHandlers,
String path,
String fullPath,
CoreContainer mockCC) {
HashMap<String, String> parts = new HashMap<>();
+ // Identity check: is reqHandlers the container's own handler bag, or a substitute?
boolean containerHandlerLookup = mockCC.getRequestHandlers() == reqHandlers;
path = path == null ? fullPath : path;
Api api = null;
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/ClusterCommandsTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/ClusterCommandsTest.java
index dc6857cfa28..ff05e70c010 100644
--- a/solr/core/src/test/org/apache/solr/handler/admin/api/ClusterCommandsTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/admin/api/ClusterCommandsTest.java
@@ -19,7 +19,7 @@ package org.apache.solr.handler.admin.api;
import java.util.concurrent.TimeUnit;
import org.apache.solr.client.api.model.DeleteClusterCommandStatusResponse;
import org.apache.solr.client.api.model.GetClusterCommandStatusResponse;
-import org.apache.solr.client.api.model.GetClusterCommandStatusResponse.CommandStatus.State;
+import org.apache.solr.client.api.model.GetClusterCommandStatusResponse.CommandStatus.RequestState;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.request.ClusterApi;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
@@ -49,7 +49,7 @@ public class ClusterCommandsTest extends SolrCloudTestCase {
assertNotNull(rsp);
assertNull(rsp.error);
- assertEquals(State.NOT_FOUND, rsp.status.state);
+ assertEquals(RequestState.NOT_FOUND, rsp.status.state);
assertEquals("Did not find [does-not-exist] in any tasks queue", rsp.status.msg);
}
@@ -61,7 +61,7 @@ public class ClusterCommandsTest extends SolrCloudTestCase {
CollectionAdminRequest.createCollection(collection, "conf1", 1, 1).processAsync(client);
GetClusterCommandStatusResponse getRsp = waitForCompleted(asyncId, client);
- assertEquals(State.COMPLETED, getRsp.status.state);
+ assertEquals(RequestState.COMPLETED, getRsp.status.state);
assertEquals("found [" + asyncId + "] in completed tasks", getRsp.status.msg);
assertTrue(
"completed create should include sub-responses from the original command",
@@ -74,7 +74,7 @@ public class ClusterCommandsTest extends SolrCloudTestCase {
GetClusterCommandStatusResponse afterDelete =
new ClusterApi.GetClusterCommandStatus(asyncId).process(client);
- assertEquals(State.NOT_FOUND, afterDelete.status.state);
+ assertEquals(RequestState.NOT_FOUND, afterDelete.status.state);
}
@Test
@@ -102,9 +102,11 @@ public class ClusterCommandsTest extends SolrCloudTestCase {
assertEquals("successfully cleared stored collection api responses", flushRsp.status);
assertEquals(
- State.NOT_FOUND, new ClusterApi.GetClusterCommandStatus(id1).process(client).status.state);
+ RequestState.NOT_FOUND,
+ new ClusterApi.GetClusterCommandStatus(id1).process(client).status.state);
assertEquals(
- State.NOT_FOUND, new ClusterApi.GetClusterCommandStatus(id2).process(client).status.state);
+ RequestState.NOT_FOUND,
+ new ClusterApi.GetClusterCommandStatus(id2).process(client).status.state);
}
private static GetClusterCommandStatusResponse waitForCompleted(String id, SolrClient client)
@@ -113,16 +115,16 @@ public class ClusterCommandsTest extends SolrCloudTestCase {
long endTime = System.nanoTime() + TimeUnit.SECONDS.toNanos(MAX_WAIT_TIMEOUT);
while (System.nanoTime() < endTime) {
rsp = new ClusterApi.GetClusterCommandStatus(id).process(client);
- State state = rsp.status.state;
- assumeTrue("Error creating collection - skipping test", state != State.FAILED);
- if (state == State.COMPLETED) {
+ RequestState state = rsp.status.state;
+ assumeTrue("Error creating collection - skipping test", state != RequestState.FAILED);
+ if (state == RequestState.COMPLETED) {
return rsp;
}
TimeUnit.SECONDS.sleep(1);
}
assumeTrue(
"Timed out waiting for async request " + id,
- rsp != null && State.COMPLETED.equals(rsp.status.state));
+ rsp != null && RequestState.COMPLETED.equals(rsp.status.state));
return rsp;
}
}
diff --git a/solr/core/src/test/org/apache/solr/pkg/TestPackages.java b/solr/core/src/test/org/apache/solr/pkg/TestPackages.java
index 597e2044544..b519e2c3d3a 100644
--- a/solr/core/src/test/org/apache/solr/pkg/TestPackages.java
+++ b/solr/core/src/test/org/apache/solr/pkg/TestPackages.java
@@ -740,6 +740,7 @@ public class TestPackages extends SolrCloudTestCase {
}
@Test
+ @SuppressWarnings("ReferenceEquality")
public void testSchemaPlugins() throws Exception {
String COLLECTION_NAME = "testSchemaLoadingColl";
System.setProperty("managed.schema.mutable", "true");
diff --git a/solr/core/src/test/org/apache/solr/schema/TestManagedSchemaThreadSafety.java b/solr/core/src/test/org/apache/solr/schema/TestManagedSchemaThreadSafety.java
index e4cb2156890..4d79661b692 100644
--- a/solr/core/src/test/org/apache/solr/schema/TestManagedSchemaThreadSafety.java
+++ b/solr/core/src/test/org/apache/solr/schema/TestManagedSchemaThreadSafety.java
@@ -63,9 +63,11 @@ public class TestManagedSchemaThreadSafety extends SolrTestCaseJ4 {
.withTimeout(ZK_CLIENT_TIMEOUT, TimeUnit.MILLISECONDS));
}
+ @SuppressWarnings("ReferenceEquality")
boolean isSlowpoke() {
Thread youKnow;
if ((youKnow = slowpoke.get()) != null) {
+ // Thread identity comparison is intentional (and Thread has no meaningful equals()).
return youKnow == Thread.currentThread();
} else {
return slowpoke.compareAndSet(null, Thread.currentThread());
diff --git a/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java b/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java
index a061d6ea7b2..150efb6483c 100644
--- a/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java
+++ b/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java
@@ -3784,6 +3784,7 @@ public class TestJsonFacets extends SolrTestCaseHS {
* @param extraSubFacet if an extra sub facet should be included, this hits slightly diff code
* paths
*/
+ @SuppressWarnings("ReferenceEquality")
public void doTestPrelimSorting(
final Client client, final boolean extraAgg, final boolean extraSubFacet) throws Exception {
@@ -3799,6 +3800,7 @@ public class TestJsonFacets extends SolrTestCaseHS {
// (which will affect some assertions)
final SolrClient shardA = clients.get(0);
final SolrClient shardB = clients.get(clients.size() - 1);
+ // Identity check: same client instance means a single-node setup.
final int numShardsWithData = (shardA == shardB) ? 1 : 2;
// for simplicity, each foo_s "term" exists on each shard in the same number of docs as it's
diff --git a/solr/core/src/test/org/apache/solr/search/function/AggValueSourceTest.java b/solr/core/src/test/org/apache/solr/search/function/AggValueSourceTest.java
index 5946d4dc955..57099fcc6a6 100644
--- a/solr/core/src/test/org/apache/solr/search/function/AggValueSourceTest.java
+++ b/solr/core/src/test/org/apache/solr/search/function/AggValueSourceTest.java
@@ -45,8 +45,10 @@ public class AggValueSourceTest extends SolrTestCase {
}
@Override
+ @SuppressWarnings("ReferenceEquality")
public SlotAcc createSlotAcc(FacetContext fcontext, long numDocs, int numSlots) {
// check we can get access to the request and searcher, via the context
+ // Identity check: verifying request and searcher share the exact same SolrCore instance.
if (fcontext.getRequest().getCore() != fcontext.getSearcher().getCore()) {
throw new IllegalStateException("Searcher and request out of sync");
}
diff --git a/solr/core/src/test/org/apache/solr/uninverting/TestFieldCacheSortRandom.java b/solr/core/src/test/org/apache/solr/uninverting/TestFieldCacheSortRandom.java
index 3e9ee3b70b9..060d9d47c1b 100644
--- a/solr/core/src/test/org/apache/solr/uninverting/TestFieldCacheSortRandom.java
+++ b/solr/core/src/test/org/apache/solr/uninverting/TestFieldCacheSortRandom.java
@@ -351,7 +351,9 @@ public class TestFieldCacheSortRandom extends SolrTestCase {
return sameClassAs(other) && equalsTo(getClass().cast(other));
}
+ @SuppressWarnings("ReferenceEquality")
private boolean equalsTo(RandomQuery other) {
+ // Consistent with hashCode(), which uses System.identityHashCode(docValues) below.
return seed == other.seed && docValues == other.docValues && density == other.density;
}
diff --git a/solr/core/src/test/org/apache/solr/update/TestInPlaceUpdatesStandalone.java b/solr/core/src/test/org/apache/solr/update/TestInPlaceUpdatesStandalone.java
index a5109562d0d..65b9541d4c2 100644
--- a/solr/core/src/test/org/apache/solr/update/TestInPlaceUpdatesStandalone.java
+++ b/solr/core/src/test/org/apache/solr/update/TestInPlaceUpdatesStandalone.java
@@ -1216,7 +1216,7 @@ public class TestInPlaceUpdatesStandalone extends SolrTestCaseJ4 {
* TestInPlaceUpdatesStandalone#HARDCOMMIT} or {@link TestInPlaceUpdatesStandalone#SOFTCOMMIT}
* sentinel objects.
*/
- @SuppressWarnings({"unchecked", "rawtypes"})
+ @SuppressWarnings({"unchecked", "rawtypes", "ReferenceEquality"})
public void checkReplay(final String valField, Object... commands) throws Exception {
HashMap<Integer, DocInfo> model = new LinkedHashMap<>();
diff --git a/solr/cross-dc-manager/gradle.lockfile b/solr/cross-dc-manager/gradle.lockfile
index 76659e03178..3c8856bd3b6 100644
--- a/solr/cross-dc-manager/gradle.lockfile
+++ b/solr/cross-dc-manager/gradle.lockfile
@@ -23,11 +23,11 @@ com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,error
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
com.google.code.gson:gson:2.14.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/modules/analysis-extras/gradle.lockfile b/solr/modules/analysis-extras/gradle.lockfile
index c51f32bee3a..b2b0ab37f0d 100644
--- a/solr/modules/analysis-extras/gradle.lockfile
+++ b/solr/modules/analysis-extras/gradle.lockfile
@@ -17,11 +17,11 @@ com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/modules/clustering/gradle.lockfile b/solr/modules/clustering/gradle.lockfile
index 04d91500afc..23b3c7c1bb3 100644
--- a/solr/modules/clustering/gradle.lockfile
+++ b/solr/modules/clustering/gradle.lockfile
@@ -17,11 +17,11 @@ com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/modules/cross-dc/gradle.lockfile b/solr/modules/cross-dc/gradle.lockfile
index afc4960648f..9e8e275f22e 100644
--- a/solr/modules/cross-dc/gradle.lockfile
+++ b/solr/modules/cross-dc/gradle.lockfile
@@ -19,11 +19,11 @@ com.github.luben:zstd-jni:1.5.6-10=jarValidation,runtimeClasspath,runtimeLibs,te
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/modules/cuvs/gradle.lockfile b/solr/modules/cuvs/gradle.lockfile
index 3f99c0f218a..5bda84e3c57 100644
--- a/solr/modules/cuvs/gradle.lockfile
+++ b/solr/modules/cuvs/gradle.lockfile
@@ -17,11 +17,11 @@ com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/modules/extraction/gradle.lockfile b/solr/modules/extraction/gradle.lockfile
index b3f5b496805..6a0ac62c661 100644
--- a/solr/modules/extraction/gradle.lockfile
+++ b/solr/modules/extraction/gradle.lockfile
@@ -20,11 +20,11 @@ com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/modules/gcs-repository/gradle.lockfile b/solr/modules/gcs-repository/gradle.lockfile
index c69a180bb7c..ee5ed8ba92d 100644
--- a/solr/modules/gcs-repository/gradle.lockfile
+++ b/solr/modules/gcs-repository/gradle.lockfile
@@ -40,11 +40,11 @@ com.google.cloud:google-cloud-core:2.74.0=compileClasspath,jarValidation,runtime
com.google.cloud:google-cloud-nio:0.136.0=jarValidation,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-storage:2.72.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath
com.google.code.gson:gson:2.14.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/modules/jwt-auth/gradle.lockfile b/solr/modules/jwt-auth/gradle.lockfile
index 991610bcf72..644dc5f8ef0 100644
--- a/solr/modules/jwt-auth/gradle.lockfile
+++ b/solr/modules/jwt-auth/gradle.lockfile
@@ -23,11 +23,11 @@ com.github.stephenc.jcip:jcip-annotations:1.0-1=jarValidation,testCompileClasspa
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/modules/langid/gradle.lockfile b/solr/modules/langid/gradle.lockfile
index a6596278c44..b0659f7dc08 100644
--- a/solr/modules/langid/gradle.lockfile
+++ b/solr/modules/langid/gradle.lockfile
@@ -17,11 +17,11 @@ com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/modules/language-models/gradle.lockfile b/solr/modules/language-models/gradle.lockfile
index aa2d68a7bdc..0b3ca08a81f 100644
--- a/solr/modules/language-models/gradle.lockfile
+++ b/solr/modules/language-models/gradle.lockfile
@@ -18,11 +18,11 @@ com.github.stephenc.jcip:jcip-annotations:1.0-1=compileClasspath,compileOnlyHelp
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/modules/ltr/gradle.lockfile b/solr/modules/ltr/gradle.lockfile
index 0775e118e9d..96d7fdbd996 100644
--- a/solr/modules/ltr/gradle.lockfile
+++ b/solr/modules/ltr/gradle.lockfile
@@ -17,11 +17,11 @@ com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/modules/ltr/src/java/org/apache/solr/ltr/feature/SolrFeature.java b/solr/modules/ltr/src/java/org/apache/solr/ltr/feature/SolrFeature.java
index 37362c80642..ae0f23a0d1f 100644
--- a/solr/modules/ltr/src/java/org/apache/solr/ltr/feature/SolrFeature.java
+++ b/solr/modules/ltr/src/java/org/apache/solr/ltr/feature/SolrFeature.java
@@ -135,6 +135,7 @@ public class SolrFeature extends Feature {
public class SolrFeatureWeight extends FeatureWeight {
private final Weight solrQueryWeight;
+ @SuppressWarnings("ReferenceEquality")
public SolrFeatureWeight(
SolrIndexSearcher searcher,
SolrQueryRequest request,
@@ -189,6 +190,8 @@ public class SolrFeature extends Feature {
}
DocSet filtersDocSet = searcher.getDocSet(filterQueries); // execute
+ // getDocSet() returns the live docs instance itself when there's nothing to filter;
+ // identity comparison detects that no-op case.
if (filtersDocSet != searcher.getLiveDocSet()) {
filterDocSetQuery = filtersDocSet.makeQuery();
}
diff --git a/solr/modules/ltr/src/java/org/apache/solr/ltr/model/LTRScoringModel.java b/solr/modules/ltr/src/java/org/apache/solr/ltr/model/LTRScoringModel.java
index 21cca228858..33945bb8074 100644
--- a/solr/modules/ltr/src/java/org/apache/solr/ltr/model/LTRScoringModel.java
+++ b/solr/modules/ltr/src/java/org/apache/solr/ltr/model/LTRScoringModel.java
@@ -286,8 +286,10 @@ public abstract class LTRScoringModel implements Accountable {
}
}
+ @SuppressWarnings("ReferenceEquality")
public Explanation getNormalizerExplanation(Explanation e, int idx) {
Normalizer n = norms.get(idx);
+ // IdentityNormalizer.INSTANCE is a singleton; identity comparison is intentional.
if (n != IdentityNormalizer.INSTANCE) {
return n.explain(e);
}
diff --git a/solr/modules/opentelemetry/gradle.lockfile b/solr/modules/opentelemetry/gradle.lockfile
index 142b21cc2ec..c227cf1b6bc 100644
--- a/solr/modules/opentelemetry/gradle.lockfile
+++ b/solr/modules/opentelemetry/gradle.lockfile
@@ -17,11 +17,11 @@ com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/modules/s3-repository/gradle.lockfile b/solr/modules/s3-repository/gradle.lockfile
index f1da3c62ac3..3b03cac808f 100644
--- a/solr/modules/s3-repository/gradle.lockfile
+++ b/solr/modules/s3-repository/gradle.lockfile
@@ -21,11 +21,11 @@ com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/modules/scripting/gradle.lockfile b/solr/modules/scripting/gradle.lockfile
index 347f5fa96d4..b1348cf667c 100644
--- a/solr/modules/scripting/gradle.lockfile
+++ b/solr/modules/scripting/gradle.lockfile
@@ -17,11 +17,11 @@ com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/modules/sql/gradle.lockfile b/solr/modules/sql/gradle.lockfile
index b67757bbc5b..f2f9a3b6dd3 100644
--- a/solr/modules/sql/gradle.lockfile
+++ b/solr/modules/sql/gradle.lockfile
@@ -17,11 +17,11 @@ com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrAggregate.java b/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrAggregate.java
index 293d63e787a..57ce4922fc6 100644
--- a/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrAggregate.java
+++ b/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrAggregate.java
@@ -55,6 +55,7 @@ class SolrAggregate extends Aggregate implements SolrRel {
return String.format(Locale.ROOT, "%s(%s)", funcName, column);
}
+ @SuppressWarnings("ReferenceEquality")
SolrAggregate(
RelOptCluster cluster,
RelTraitSet traitSet,
@@ -64,6 +65,7 @@ class SolrAggregate extends Aggregate implements SolrRel {
List<ImmutableBitSet> groupSets,
List<AggregateCall> aggCalls) {
super(cluster, traitSet, hints, child, groupSet, groupSets, aggCalls);
+ // Conventions are singletons (see SolrRel.CONVENTION); identity comparison is intentional.
assert getConvention() == SolrRel.CONVENTION;
assert getConvention() == child.getConvention();
}
diff --git a/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrFilter.java b/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrFilter.java
index b8a326f6241..f168e3ad67a 100644
--- a/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrFilter.java
+++ b/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrFilter.java
@@ -77,8 +77,10 @@ class SolrFilter extends Filter implements SolrRel {
private final RexBuilder builder;
+ @SuppressWarnings("ReferenceEquality")
SolrFilter(RelOptCluster cluster, RelTraitSet traitSet, RelNode child, RexNode condition) {
super(cluster, traitSet, child, condition);
+ // Conventions are singletons (see SolrRel.CONVENTION); identity comparison is intentional.
assert getConvention() == SolrRel.CONVENTION;
assert getConvention() == child.getConvention();
builder = child.getCluster().getRexBuilder();
diff --git a/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrProject.java b/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrProject.java
index 87ac4633b8a..121f3536c2a 100644
--- a/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrProject.java
+++ b/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrProject.java
@@ -30,6 +30,7 @@ import org.apache.calcite.util.Pair;
/** Implementation of {@link org.apache.calcite.rel.core.Project} relational expression in Solr. */
class SolrProject extends Project implements SolrRel {
+ @SuppressWarnings("ReferenceEquality")
SolrProject(
RelOptCluster cluster,
RelTraitSet traitSet,
@@ -37,6 +38,7 @@ class SolrProject extends Project implements SolrRel {
List<? extends RexNode> projects,
RelDataType rowType) {
super(cluster, traitSet, input, projects, rowType);
+ // Conventions are singletons (see SolrRel.CONVENTION); identity comparison is intentional.
assert getConvention() == SolrRel.CONVENTION;
assert getConvention() == input.getConvention();
}
diff --git a/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrSort.java b/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrSort.java
index f5fb75d9d48..2c0c3ed9d64 100644
--- a/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrSort.java
+++ b/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrSort.java
@@ -33,6 +33,7 @@ import org.apache.calcite.rex.RexNode;
/** Implementation of {@link org.apache.calcite.rel.core.Sort} relational expression in Solr. */
class SolrSort extends Sort implements SolrRel {
+ @SuppressWarnings("ReferenceEquality")
SolrSort(
RelOptCluster cluster,
RelTraitSet traitSet,
@@ -42,6 +43,7 @@ class SolrSort extends Sort implements SolrRel {
RexNode fetch) {
super(cluster, traitSet, child, collation, offset, fetch);
+ // Conventions are singletons (see SolrRel.CONVENTION); identity comparison is intentional.
assert getConvention() == SolrRel.CONVENTION;
assert getConvention() == child.getConvention();
}
diff --git a/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrTableScan.java b/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrTableScan.java
index f2ae04e33fb..8217af20f0e 100644
--- a/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrTableScan.java
+++ b/solr/modules/sql/src/java/org/apache/solr/handler/sql/SolrTableScan.java
@@ -44,6 +44,7 @@ class SolrTableScan extends TableScan implements SolrRel {
* @param solrTable Solr table
* @param projectRowType Fields and types to project; null to project raw row
*/
+ @SuppressWarnings("ReferenceEquality")
SolrTableScan(
RelOptCluster cluster,
RelTraitSet traitSet,
@@ -55,6 +56,7 @@ class SolrTableScan extends TableScan implements SolrRel {
this.projectRowType = projectRowType;
assert solrTable != null;
+ // Conventions are singletons (see SolrRel.CONVENTION); identity comparison is intentional.
assert getConvention() == SolrRel.CONVENTION;
}
diff --git a/solr/server/gradle.lockfile b/solr/server/gradle.lockfile
index 6783934d89c..8bfbeeded03 100644
--- a/solr/server/gradle.lockfile
+++ b/solr/server/gradle.lockfile
@@ -16,11 +16,11 @@ com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,errorprone,jarValidation,runtimeClasspath,solrCore,testAnnotationProcessor
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,errorprone,jarValidation,runtimeClasspath,solrCore,testAnnotationProcessor
com.google.guava:guava:33.7.1-jre=annotationProcessor,errorprone,jarValidation,runtimeClasspath,solrCore,testAnnotationProcessor
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,errorprone,jarValidation,runtimeClasspath,solrCore,testAnnotationProcessor
diff --git a/solr/solr-ref-guide/gradle.lockfile b/solr/solr-ref-guide/gradle.lockfile
index e6da8d96c13..836819e50d8 100644
--- a/solr/solr-ref-guide/gradle.lockfile
+++ b/solr/solr-ref-guide/gradle.lockfile
@@ -17,11 +17,11 @@ com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,errorprone,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,errorprone,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,errorprone,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/solrj-jetty/gradle.lockfile b/solr/solrj-jetty/gradle.lockfile
index 893034d45fa..b69b1deb445 100644
--- a/solr/solrj-jetty/gradle.lockfile
+++ b/solr/solrj-jetty/gradle.lockfile
@@ -18,11 +18,11 @@ com.github.stephenc.jcip:jcip-annotations:1.0-1=compileClasspath,jarValidation
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,errorprone,jarValidation,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,errorprone,jarValidation,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,errorprone,jarValidation,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,errorprone,jarValidation,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/solrj-streaming/gradle.lockfile b/solr/solrj-streaming/gradle.lockfile
index afb70e09bb1..5b06e6bc039 100644
--- a/solr/solrj-streaming/gradle.lockfile
+++ b/solr/solrj-streaming/gradle.lockfile
@@ -17,11 +17,11 @@ com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,errorprone,jarValidation,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,errorprone,jarValidation,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,errorprone,jarValidation,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,errorprone,jarValidation,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/comp/FieldComparator.java b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/comp/FieldComparator.java
index 57f4f5da259..e8085508fe2 100644
--- a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/comp/FieldComparator.java
+++ b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/comp/FieldComparator.java
@@ -106,7 +106,7 @@ public class FieldComparator implements StreamComparator {
* check only once - we can do that in the constructor of this class, create a lambda, and then execute
* that lambda in the compare function. A bit of branch prediction savings right here.
*/
- @SuppressWarnings({"unchecked"})
+ @SuppressWarnings({"unchecked", "ReferenceEquality"}) // fast path: same ref implies equal
private void assignComparator() {
if (ComparatorOrder.DESCENDING == order) {
comparator =
diff --git a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/eq/FieldEqualitor.java b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/eq/FieldEqualitor.java
index 78ca78a9fdc..360e5897905 100644
--- a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/eq/FieldEqualitor.java
+++ b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/eq/FieldEqualitor.java
@@ -76,7 +76,7 @@ public class FieldEqualitor implements StreamEqualitor {
}
@Override
- @SuppressWarnings({"unchecked"})
+ @SuppressWarnings({"unchecked", "ReferenceEquality"}) // fast path: same ref implies equal
public boolean test(Tuple leftTuple, Tuple rightTuple) {
@SuppressWarnings({"rawtypes"})
diff --git a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/JavabinTupleStreamParser.java b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/JavabinTupleStreamParser.java
index 5209d29e4be..e49174bf241 100644
--- a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/JavabinTupleStreamParser.java
+++ b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/JavabinTupleStreamParser.java
@@ -43,6 +43,8 @@ public class JavabinTupleStreamParser extends JavaBinCodec implements TupleStrea
this.fis = initRead(is);
}
+ @SuppressWarnings(
+ "ReferenceEquality") // END_OBJ is a unique sentinel; identity check is intentional
private boolean readTillDocs() throws IOException {
if (isObjectType(fis)) {
if (tagByte == SOLRDOCLST) {
@@ -177,7 +179,10 @@ public class JavabinTupleStreamParser extends JavaBinCodec implements TupleStrea
}
@Override
- @SuppressWarnings({"unchecked"})
+ @SuppressWarnings({
+ "unchecked",
+ "ReferenceEquality" // END_OBJ is a unique sentinel; identity check is intentional
+ })
public Map<String, Object> next() throws IOException {
if (!atDocs) {
atDocs = true;
diff --git a/solr/solrj-zookeeper/gradle.lockfile b/solr/solrj-zookeeper/gradle.lockfile
index a2afeb14f7f..412ce16f6de 100644
--- a/solr/solrj-zookeeper/gradle.lockfile
+++ b/solr/solrj-zookeeper/gradle.lockfile
@@ -26,12 +26,12 @@ com.github.spotbugs:spotbugs-annotations:4.10.4=compileClasspath
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.47.0=compileClasspathCopy,runtimeClasspathCopy,testCompileClasspathCopy,testRuntimeClasspathCopy
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,compileClasspath,compileClasspathCopy,errorprone,jarValidation,runtimeClasspath,runtimeClasspathCopy,testAnnotationProcessor,testCompileClasspath,testCompileClasspathCopy,testRuntimeClasspath,testRuntimeClasspathCopy
com.google.guava:guava:33.6.0-jre=compileClasspathCopy,runtimeClasspathCopy,testCompileClasspathCopy,testRuntimeClasspathCopy
com.google.guava:guava:33.7.1-jre=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
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 659881033a9..b5eab171aa6 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
@@ -1270,6 +1270,8 @@ public class ZkStateReader implements SolrCloseable {
}
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // checking identity of the registered watcher, not equality
public void process(WatchedEvent event) {
// session events are not change events, and do not remove the watcher
if (EventType.None.equals(event.getType())) {
@@ -2017,6 +2019,8 @@ public class ZkStateReader implements SolrCloseable {
* modifications, giving up after 30 seconds with a SolrException. The caller should understand
* it's possible the aliases has further changed if it examines it.
*/
+ @SuppressWarnings(
+ "ReferenceEquality") // op.apply returning the same instance means "no change made"
public void applyModificationAndExportToZk(UnaryOperator<Aliases> op) {
// The current aliases hasn't been update()'ed yet -- which is impossible? Any way just
// update it first.
diff --git a/solr/solrj/gradle.lockfile b/solr/solrj/gradle.lockfile
index a092f8ba6b7..6f357c4c583 100644
--- a/solr/solrj/gradle.lockfile
+++ b/solr/solrj/gradle.lockfile
@@ -18,11 +18,11 @@ com.github.stephenc.jcip:jcip-annotations:1.0-1=compileClasspath,jarValidation
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,errorprone,jarValidation,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,errorprone,jarValidation,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,errorprone,jarValidation,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,errorprone,jarValidation,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/ConcurrentUpdateBaseSolrClient.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/ConcurrentUpdateBaseSolrClient.java
index 5baeaec60a9..50ab27f1dc4 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/ConcurrentUpdateBaseSolrClient.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/ConcurrentUpdateBaseSolrClient.java
@@ -141,6 +141,8 @@ public abstract class ConcurrentUpdateBaseSolrClient extends SolrClient {
return size() == 0;
}
+ @SuppressWarnings(
+ "ReferenceEquality") // backdoorE is a unique sentinel; identity check is intentional
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
E e = queue.poll(timeout, unit);
if (e == null) {
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/request/JavaBinUpdateRequestCodec.java b/solr/solrj/src/java/org/apache/solr/client/solrj/request/JavaBinUpdateRequestCodec.java
index 5da32870e04..9f232e48b5f 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/request/JavaBinUpdateRequestCodec.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/JavaBinUpdateRequestCodec.java
@@ -218,6 +218,8 @@ public class JavaBinUpdateRequestCodec {
return List.of(); // bogus; already processed
}
+ @SuppressWarnings(
+ "ReferenceEquality") // END_OBJ is a unique sentinel; identity check is intentional
private void readDocs(DataInputInputStream fis) throws IOException {
if (resultNamedList == null) resultNamedList = new NamedList<>();
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/response/ResponseParser.java b/solr/solrj/src/java/org/apache/solr/client/solrj/response/ResponseParser.java
index 9884d8a1ef5..47dfdccedee 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/response/ResponseParser.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/response/ResponseParser.java
@@ -34,6 +34,7 @@ public abstract class ResponseParser {
assert validateContentTypes();
}
+ @SuppressWarnings("ReferenceEquality") // Use of == is intentional here
private boolean validateContentTypes() {
Collection<String> contentTypes = getContentTypes();
assert contentTypes == getContentTypes()
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/routing/RequestReplicaListTransformerGenerator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/routing/RequestReplicaListTransformerGenerator.java
index 4071dd7527f..d3bfaf7eee6 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/routing/RequestReplicaListTransformerGenerator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/routing/RequestReplicaListTransformerGenerator.java
@@ -216,7 +216,7 @@ public class RequestReplicaListTransformerGenerator {
if (log.isDebugEnabled()) {
log.debug(
"Applied sorting preferences to replica list: {}",
- choices.stream().map(T::toString).collect(Collectors.joining(",", "[", "]")));
+ choices.stream().map(Object::toString).collect(Collectors.joining(",", "[", "]")));
}
}
}
diff --git a/solr/solrj/src/java/org/apache/solr/common/util/CommandOperation.java b/solr/solrj/src/java/org/apache/solr/common/util/CommandOperation.java
index f7c2b560c0a..eeea5684324 100644
--- a/solr/solrj/src/java/org/apache/solr/common/util/CommandOperation.java
+++ b/solr/solrj/src/java/org/apache/solr/common/util/CommandOperation.java
@@ -49,7 +49,7 @@ public class CommandOperation {
public String getStr(String key, String def) {
if (ROOT_OBJ.equals(key)) {
Object obj = getRootPrimitive();
- return obj == def ? null : String.valueOf(obj);
+ return obj == null ? def : String.valueOf(obj);
}
Object o = getMapVal(key);
return o == null ? def : String.valueOf(o);
diff --git a/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java b/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java
index 12f7f4cf4bb..f1db025fe4f 100644
--- a/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java
+++ b/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java
@@ -826,6 +826,8 @@ public class JavaBinCodec implements PushWriter {
}
}
+ @SuppressWarnings(
+ "ReferenceEquality") // END_OBJ is a unique sentinel; identity check is intentional
public Map<Object, Object> readMapIter(DataInputInputStream dis) throws IOException {
Map<Object, Object> m = newMap(-1);
for (; ; ) {
@@ -931,6 +933,8 @@ public class JavaBinCodec implements PushWriter {
writeTag(END);
}
+ @SuppressWarnings(
+ "ReferenceEquality") // END_OBJ is a unique sentinel; identity check is intentional
public List<Object> readIterator(DataInputInputStream fis) throws IOException {
ArrayList<Object> l = new ArrayList<>();
while (true) {
@@ -1237,6 +1241,8 @@ public class JavaBinCodec implements PushWriter {
daos.writeFloat(val);
}
+ @SuppressWarnings(
+ "ReferenceEquality") // END_OBJ is a unique sentinel; identity check is intentional
public boolean writePrimitive(Object val) throws IOException {
if (val == null) {
daos.writeByte(NULL);
diff --git a/solr/solrj/src/test/org/apache/solr/common/util/TestFastWriter.java b/solr/solrj/src/test/org/apache/solr/common/util/TestFastWriter.java
index 382c2093c98..71a95f4912b 100644
--- a/solr/solrj/src/test/org/apache/solr/common/util/TestFastWriter.java
+++ b/solr/solrj/src/test/org/apache/solr/common/util/TestFastWriter.java
@@ -33,7 +33,9 @@ class MemWriter extends FastWriter {
}
@Override
+ @SuppressWarnings("ReferenceEquality")
public void flush(char[] arr, int offset, int len) throws IOException {
+ // Identity check: only steal the internal buffer when it's the exact same array instance.
if (arr == buf && offset == 0 && len == buf.length) {
buffers.add(buf); // steal the buffer
buf = new char[r.nextInt(9000) + 1];
diff --git a/solr/test-framework/gradle.lockfile b/solr/test-framework/gradle.lockfile
index 9ccb010899f..24ab360f643 100644
--- a/solr/test-framework/gradle.lockfile
+++ b/solr/test-framework/gradle.lockfile
@@ -27,12 +27,12 @@ com.github.spotbugs:spotbugs-annotations:4.10.4=compileClasspath
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.47.0=compileClasspathCopy,runtimeClasspathCopy,testCompileClasspathCopy,testRuntimeClasspathCopy
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,compileClasspath,compileClasspathCopy,errorprone,jarValidation,runtimeClasspath,runtimeClasspathCopy,testAnnotationProcessor,testCompileClasspath,testCompileClasspathCopy,testRuntimeClasspath,testRuntimeClasspathCopy
com.google.guava:guava:33.6.0-jre=compileClasspathCopy,runtimeClasspathCopy,testCompileClasspathCopy,testRuntimeClasspathCopy
com.google.guava:guava:33.7.1-jre=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
diff --git a/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java b/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
index 219f5e19a03..ebb8f95c2c9 100644
--- a/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
+++ b/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
@@ -905,6 +905,7 @@ public abstract class BaseDistributedSearchTestCase extends SolrTestCaseJ4 {
return null;
}
+ @SuppressWarnings("ReferenceEquality") // fast path: same ref implies equal
public static String compare(Object a, Object b, int flags, Map<String, Integer> handle) {
if (a == b) return null;
if (a == null || b == null) return ":" + a + "!=" + b;
diff --git a/solr/test-framework/src/java/org/apache/solr/JSONTestUtil.java b/solr/test-framework/src/java/org/apache/solr/JSONTestUtil.java
index 08df42a6c8f..88bb48b1b1a 100644
--- a/solr/test-framework/src/java/org/apache/solr/JSONTestUtil.java
+++ b/solr/test-framework/src/java/org/apache/solr/JSONTestUtil.java
@@ -215,6 +215,7 @@ class CollectionTester {
return match();
}
+ @SuppressWarnings("ReferenceEquality") // fast path: same ref implies equal
boolean match() {
if (expected == val) {
return true;
diff --git a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
index 141b6db0a7f..e77fa41fcad 100644
--- a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
+++ b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
@@ -472,6 +472,8 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
randomizeNumericTypesProperties();
}
+ @SuppressWarnings(
+ "ReferenceEquality") // detecting a self-referencing exception cause loop, by identity
public static Throwable getWrappedException(Throwable e) {
while (e != null && e.getCause() != e && e.getCause() != null) {
e = e.getCause();
@@ -2285,6 +2287,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
Files.copy(top.resolve("synonyms.txt"), subHome.resolve("synonyms.txt"));
}
+ @SuppressWarnings("ReferenceEquality") // fast path: same ref implies equal
public boolean compareSolrDocument(Object expected, Object actual) {
if (!(expected instanceof SolrDocument solrDocument1)
@@ -2335,6 +2338,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
}
}
+ @SuppressWarnings("ReferenceEquality") // fast path: same ref implies equal
public boolean compareSolrDocumentList(Object expected, Object actual) {
if (!(expected instanceof SolrDocumentList list1)
|| !(actual instanceof SolrDocumentList list2)) {
@@ -2366,6 +2370,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
return true;
}
+ @SuppressWarnings("ReferenceEquality") // fast path: same ref implies equal
public boolean compareSolrInputDocument(Object expected, Object actual) {
if (!(expected instanceof SolrInputDocument sdoc1)
@@ -2440,6 +2445,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
}
}
+ @SuppressWarnings("ReferenceEquality") // fast path: same ref implies equal
public boolean assertSolrInputFieldEquals(Object expected, Object actual) {
if (!(expected instanceof SolrInputField sif1) || !(actual instanceof SolrInputField sif2)) {
return false;
@@ -2557,6 +2563,8 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
return result;
}
+ @SuppressWarnings(
+ "ReferenceEquality") // SolrIndexSearcher identity, not equality, is what matters here
protected static void waitForWarming(SolrCore core) throws InterruptedException {
RefCounted<SolrIndexSearcher> registeredSearcher = core.getRegisteredSearcher();
RefCounted<SolrIndexSearcher> newestSearcher = core.getNewestSearcher(false);
diff --git a/solr/test-framework/src/java/org/apache/solr/cluster/placement/Builders.java b/solr/test-framework/src/java/org/apache/solr/cluster/placement/Builders.java
index 03cc9522838..f363239a565 100644
--- a/solr/test-framework/src/java/org/apache/solr/cluster/placement/Builders.java
+++ b/solr/test-framework/src/java/org/apache/solr/cluster/placement/Builders.java
@@ -515,6 +515,8 @@ public class Builders {
return this;
}
+ @SuppressWarnings(
+ "ReferenceEquality") // ReplicaBuilder identity, not equality, is what matters here
public Shard build(SolrCollection collection) {
ClusterAbstractionsForTest.ShardImpl shard =
new ClusterAbstractionsForTest.ShardImpl(shardName, collection, Shard.ShardState.ACTIVE);
diff --git a/solr/test-framework/src/java/org/apache/solr/embedded/JettySolrRunner.java b/solr/test-framework/src/java/org/apache/solr/embedded/JettySolrRunner.java
index aea83190d9f..ff8253853ff 100644
--- a/solr/test-framework/src/java/org/apache/solr/embedded/JettySolrRunner.java
+++ b/solr/test-framework/src/java/org/apache/solr/embedded/JettySolrRunner.java
@@ -588,6 +588,8 @@ public class JettySolrRunner implements SolrBackend {
* @param ioe An IOException that might wrap a BindException
* @return A bind exception if present otherwise ioe
*/
+ @SuppressWarnings(
+ "ReferenceEquality") // detecting a self-referencing exception cause loop, by identity
Exception lookForBindException(IOException ioe) {
Exception e = ioe;
while (e.getCause() != null && !(e == e.getCause()) && !(e instanceof BindException)) {
diff --git a/solr/test-framework/src/java/org/apache/solr/util/RevertDefaultThreadHandlerRule.java b/solr/test-framework/src/java/org/apache/solr/util/RevertDefaultThreadHandlerRule.java
index 89778e80ae9..d178473034a 100644
--- a/solr/test-framework/src/java/org/apache/solr/util/RevertDefaultThreadHandlerRule.java
+++ b/solr/test-framework/src/java/org/apache/solr/util/RevertDefaultThreadHandlerRule.java
@@ -28,6 +28,8 @@ public final class RevertDefaultThreadHandlerRule implements TestRule {
private static final AtomicBoolean applied = new AtomicBoolean();
@Override
+ @SuppressWarnings(
+ "ReferenceEquality") // UncaughtExceptionHandler identity, not equality, is what matters here
public Statement apply(Statement s, Description d) {
return new StatementAdapter(s) {
@Override
diff --git a/solr/webapp/gradle.lockfile b/solr/webapp/gradle.lockfile
index ee223761850..a50871b28e7 100644
--- a/solr/webapp/gradle.lockfile
+++ b/solr/webapp/gradle.lockfile
@@ -17,11 +17,11 @@ com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.50.0=annotationProcessor,errorprone,jarValidation,solrCore,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_check_api:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.50.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.35.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,errorprone,jarValidation,solrCore,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.7.1-jre=annotationProcessor,errorprone,jarValidation,solrCore,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,errorprone,jarValidation,solrCore,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
(solr) 15/17: SOLR-18423: CrossDC Consumer: off-by-one error in ThreadDump handler. (#4889)
Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
commit 93dbb63f97196e75875346a0061343fa99b4e35b
Author: Andrzej BiaĆecki <ab...@apache.org>
AuthorDate: Wed Sep 9 11:46:02 2026 +0200
SOLR-18423: CrossDC Consumer: off-by-one error in ThreadDump handler. (#4889)
(cherry picked from commit a9d0bc7ca7213ec01b83d0ff59e7b570a2c5ce31)
---
changelog/unreleased/solr-18423.yml | 8 ++
.../solr/crossdc/manager/consumer/ThreadDump.java | 2 +-
.../crossdc/manager/consumer/ThreadDumpTest.java | 126 +++++++++++++++++++++
3 files changed, 135 insertions(+), 1 deletion(-)
diff --git a/changelog/unreleased/solr-18423.yml b/changelog/unreleased/solr-18423.yml
new file mode 100644
index 00000000000..c3ef790cb22
--- /dev/null
+++ b/changelog/unreleased/solr-18423.yml
@@ -0,0 +1,8 @@
+title: CrossDC Consumer off-by-one error in the ThreadDump handler.
+
+type: fixed
+authors:
+ - name: Andrzej Bialecki
+links:
+ - name: SOLR-18423
+ url: https://issues.apache.org/jira/browse/SOLR-18423
diff --git a/solr/cross-dc-manager/src/java/org/apache/solr/crossdc/manager/consumer/ThreadDump.java b/solr/cross-dc-manager/src/java/org/apache/solr/crossdc/manager/consumer/ThreadDump.java
index aed28f2c952..080b27e8846 100644
--- a/solr/cross-dc-manager/src/java/org/apache/solr/crossdc/manager/consumer/ThreadDump.java
+++ b/solr/cross-dc-manager/src/java/org/apache/solr/crossdc/manager/consumer/ThreadDump.java
@@ -117,7 +117,7 @@ public class ThreadDump {
for (int i = 0; i < elements.length; i++) {
final StackTraceElement element = elements[i];
writer.printf(Locale.ROOT, " at %s%n", element);
- for (int j = 1; j < monitors.length; j++) {
+ for (int j = 0; j < monitors.length; j++) {
final MonitorInfo monitor = monitors[j];
if (monitor.getLockedStackDepth() == i) {
writer.printf(Locale.ROOT, " - locked %s%n", monitor);
diff --git a/solr/cross-dc-manager/src/test/org/apache/solr/crossdc/manager/consumer/ThreadDumpTest.java b/solr/cross-dc-manager/src/test/org/apache/solr/crossdc/manager/consumer/ThreadDumpTest.java
new file mode 100644
index 00000000000..67182aa3e30
--- /dev/null
+++ b/solr/cross-dc-manager/src/test/org/apache/solr/crossdc/manager/consumer/ThreadDumpTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.crossdc.manager.consumer;
+
+import static org.apache.solr.SolrTestCaseJ4.assumeWorkingMockito;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayOutputStream;
+import java.lang.management.LockInfo;
+import java.lang.management.MonitorInfo;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Verifies that {@link ThreadDump} helper pairs each locked {@link MonitorInfo} with the {@link
+ * StackTraceElement} at the matching stack depth, including a monitor locked at stack depth 0. This
+ * bug was inherited from the original Dropwizard implementation.
+ */
+public class ThreadDumpTest {
+
+ @BeforeClass
+ public static void beforeClass() {
+ assumeWorkingMockito();
+ }
+
+ @Test
+ public void testAllLockedMonitorsAreReported() {
+ StackTraceElement frame0 = new StackTraceElement("com.example.Inner", "run", "Inner.java", 42);
+ StackTraceElement frame1 =
+ new StackTraceElement("com.example.Middle", "call", "Middle.java", 21);
+ StackTraceElement frame2 = new StackTraceElement("com.example.Outer", "outer", "Outer.java", 7);
+ StackTraceElement[] stackTrace = {frame0, frame1, frame2};
+
+ // one monitor locked at the innermost frame (depth 0) and one at the outermost (depth 2);
+ // depth 1 intentionally has no locked monitor.
+ MonitorInfo monitorAtDepth0 = mock(MonitorInfo.class);
+ when(monitorAtDepth0.getLockedStackDepth()).thenReturn(0);
+ when(monitorAtDepth0.toString()).thenReturn("MONITOR_AT_DEPTH_0");
+
+ MonitorInfo monitorAtDepth2 = mock(MonitorInfo.class);
+ when(monitorAtDepth2.getLockedStackDepth()).thenReturn(2);
+ when(monitorAtDepth2.toString()).thenReturn("MONITOR_AT_DEPTH_2");
+
+ // monitor at depth 0 is deliberately first in the array, so the old loop (starting at
+ // index 1) would silently drop it.
+ MonitorInfo[] lockedMonitors = {monitorAtDepth0, monitorAtDepth2};
+
+ ThreadInfo threadInfo = mock(ThreadInfo.class);
+ when(threadInfo.getThreadName()).thenReturn("test-thread");
+ when(threadInfo.getThreadId()).thenReturn(1L);
+ when(threadInfo.getThreadState()).thenReturn(Thread.State.RUNNABLE);
+ when(threadInfo.getLockInfo()).thenReturn(null);
+ when(threadInfo.getLockOwnerName()).thenReturn(null);
+ when(threadInfo.isSuspended()).thenReturn(false);
+ when(threadInfo.isInNative()).thenReturn(false);
+ when(threadInfo.getStackTrace()).thenReturn(stackTrace);
+ when(threadInfo.getLockedMonitors()).thenReturn(lockedMonitors);
+ when(threadInfo.getLockedSynchronizers()).thenReturn(new LockInfo[0]);
+
+ ThreadMXBean threadMXBean = mock(ThreadMXBean.class);
+ when(threadMXBean.dumpAllThreads(true, true)).thenReturn(new ThreadInfo[] {threadInfo});
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ new ThreadDump(threadMXBean).dump(out);
+
+ List<String> lines = out.toString(StandardCharsets.UTF_8).lines().collect(Collectors.toList());
+
+ int frame0Line = indexOfLineContaining(lines, frame0.toString());
+ int frame1Line = indexOfLineContaining(lines, frame1.toString());
+ int frame2Line = indexOfLineContaining(lines, frame2.toString());
+
+ assertTrue("frame0 should be printed", frame0Line >= 0);
+ assertTrue("frame1 should be printed", frame1Line >= 0);
+ assertTrue("frame2 should be printed", frame2Line >= 0);
+
+ // the monitor locked at depth 0 must be reported immediately after frame0's "at" line -
+ // this is the case the off-by-one bug broke
+ assertEquals(
+ "monitor locked at stack depth 0 must immediately follow its frame",
+ " - locked MONITOR_AT_DEPTH_0",
+ lines.get(frame0Line + 1));
+
+ // depth 1 has no locked monitor, so the very next line must be the next stack frame.
+ assertEquals(
+ "no monitor line expected between frame1 and frame2",
+ lines.get(frame2Line),
+ lines.get(frame1Line + 1));
+
+ // the monitor locked at depth 2 must immediately follow frame2's "at" line.
+ assertEquals(
+ "monitor locked at stack depth 2 must immediately follow its frame",
+ " - locked MONITOR_AT_DEPTH_2",
+ lines.get(frame2Line + 1));
+ }
+
+ private static int indexOfLineContaining(List<String> lines, String needle) {
+ for (int i = 0; i < lines.size(); i++) {
+ if (lines.get(i).contains(needle)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+}
(solr) 04/17: Review and tidy solr/modules/language-models code (#4836)
Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
commit f650e7e3d7bfeef83716d30f7d97da0b0ec39f61
Author: Eric Pugh <ep...@opensourceconnections.com>
AuthorDate: Tue Sep 8 09:28:27 2026 -0400
Review and tidy solr/modules/language-models code (#4836)
(cherry picked from commit 2ffb3b97db10b6c9ed0a99698d6e47cebec5904b)
---
.../languagemodels/update/processor/TextToVectorUpdateProcessor.java | 2 +-
.../src/test/org/apache/solr/languagemodels/TestLanguageModelBase.java | 2 +-
.../solr/languagemodels/store/rest/TestLargeLanguageModelManager.java | 2 +-
.../solr/languagemodels/store/rest/TestTextToVectorModelManager.java | 2 +-
.../factory/DocumentEnrichmentUpdateProcessorFactoryTest.java | 3 +--
5 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/update/processor/TextToVectorUpdateProcessor.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/update/processor/TextToVectorUpdateProcessor.java
index 44c75988e7f..d775b70c47e 100644
--- a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/update/processor/TextToVectorUpdateProcessor.java
+++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/update/processor/TextToVectorUpdateProcessor.java
@@ -65,7 +65,7 @@ public class TextToVectorUpdateProcessor extends UpdateRequestProcessor {
try {
String textToVectorise = inputFieldContent.getValue().toString();
float[] vector = textToVector.vectorise(textToVectorise);
- List<Float> vectorAsList = new ArrayList<Float>(vector.length);
+ List<Float> vectorAsList = new ArrayList<>(vector.length);
for (float f : vector) {
vectorAsList.add(f);
}
diff --git a/solr/modules/language-models/src/test/org/apache/solr/languagemodels/TestLanguageModelBase.java b/solr/modules/language-models/src/test/org/apache/solr/languagemodels/TestLanguageModelBase.java
index 99d241fdde5..908754bd1c6 100644
--- a/solr/modules/language-models/src/test/org/apache/solr/languagemodels/TestLanguageModelBase.java
+++ b/solr/modules/language-models/src/test/org/apache/solr/languagemodels/TestLanguageModelBase.java
@@ -150,7 +150,7 @@ public class TestLanguageModelBase extends RestTestBase {
assertJPut(LargeLanguageModelStore.REST_END_POINT, model, "/responseHeader/status==0");
}
- protected static void prepareIndex() throws Exception {
+ protected static void prepareIndex() {
List<SolrInputDocument> docsToIndex = prepareDocs();
for (SolrInputDocument doc : docsToIndex) {
assertU(adoc(doc));
diff --git a/solr/modules/language-models/src/test/org/apache/solr/languagemodels/store/rest/TestLargeLanguageModelManager.java b/solr/modules/language-models/src/test/org/apache/solr/languagemodels/store/rest/TestLargeLanguageModelManager.java
index bb785d90719..051b67a2124 100644
--- a/solr/modules/language-models/src/test/org/apache/solr/languagemodels/store/rest/TestLargeLanguageModelManager.java
+++ b/solr/modules/language-models/src/test/org/apache/solr/languagemodels/store/rest/TestLargeLanguageModelManager.java
@@ -58,7 +58,7 @@ public class TestLargeLanguageModelManager extends TestLanguageModelBase {
final ManagedResource res = restManager.getManagedResource(resourceId);
assertTrue(res instanceof LargeLanguageModelStore);
- assertEquals(res.getResourceId(), resourceId);
+ assertEquals(resourceId, res.getResourceId());
}
@Test
diff --git a/solr/modules/language-models/src/test/org/apache/solr/languagemodels/store/rest/TestTextToVectorModelManager.java b/solr/modules/language-models/src/test/org/apache/solr/languagemodels/store/rest/TestTextToVectorModelManager.java
index 0dba83a8d97..b63635a19ca 100644
--- a/solr/modules/language-models/src/test/org/apache/solr/languagemodels/store/rest/TestTextToVectorModelManager.java
+++ b/solr/modules/language-models/src/test/org/apache/solr/languagemodels/store/rest/TestTextToVectorModelManager.java
@@ -58,7 +58,7 @@ public class TestTextToVectorModelManager extends TestLanguageModelBase {
final ManagedResource res = restManager.getManagedResource(resourceId);
assertTrue(res instanceof TextToVectorModelStore);
- assertEquals(res.getResourceId(), resourceId);
+ assertEquals(resourceId, res.getResourceId());
}
@Test
diff --git a/solr/modules/language-models/src/test/org/apache/solr/languagemodels/update/processor/factory/DocumentEnrichmentUpdateProcessorFactoryTest.java b/solr/modules/language-models/src/test/org/apache/solr/languagemodels/update/processor/factory/DocumentEnrichmentUpdateProcessorFactoryTest.java
index 10c0137bd32..45f56803110 100644
--- a/solr/modules/language-models/src/test/org/apache/solr/languagemodels/update/processor/factory/DocumentEnrichmentUpdateProcessorFactoryTest.java
+++ b/solr/modules/language-models/src/test/org/apache/solr/languagemodels/update/processor/factory/DocumentEnrichmentUpdateProcessorFactoryTest.java
@@ -419,8 +419,7 @@ public class DocumentEnrichmentUpdateProcessorFactoryTest extends TestLanguageMo
String outputFieldName,
String prompt,
SolrCore core,
- String modelName)
- throws Exception {
+ String modelName) {
LargeLanguageModelStore.getManagedModelStore(core)
.addModel(new SolrLargeLanguageModel(modelName, null, null));
(solr) 03/17: prevent warning in gradle console output about plugin name (#4885)
Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
commit f66fd9307a91a05045122ed8c75bc6752207091f
Author: Eric Pugh <ep...@opensourceconnections.com>
AuthorDate: Tue Sep 8 07:40:28 2026 -0400
prevent warning in gradle console output about plugin name (#4885)
(cherry picked from commit 25e3dbea19c3a2d4123fe810cdd1ec92ba29c090)
---
gradle/libs.versions.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 415ebe1aee0..12d7ee729b3 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -204,7 +204,7 @@ xerial-snappy = "1.1.10.8"
[plugins]
barfuin-jacocolog = { id = "org.barfuin.gradle.jacocolog", version.ref = "barfuin-jacocolog" }
-benmanes-versions = { id = "com.github.ben-manes.versions", version.ref = "benmanes-versions" }
+benmanes-versions = { id = "io.github.ben-manes.versions", version.ref = "benmanes-versions" }
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
diffplug-spotless = { id = "com.diffplug.spotless", version.ref = "diffplug-spotless" }
jetbrains-compose = { id = "org.jetbrains.compose", version.ref = "compose" }