You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by da...@apache.org on 2018/12/01 17:10:20 UTC

[32/32] lucene-solr:jira/http2: Merge with master

Merge with master


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/6c6fd559
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/6c6fd559
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/6c6fd559

Branch: refs/heads/jira/http2
Commit: 6c6fd5599bcfdc9a67261874b125cbe60e795ee5
Parents: 49c067a cbe9f82
Author: Cao Manh Dat <da...@apache.org>
Authored: Sat Dec 1 17:09:29 2018 +0000
Committer: Cao Manh Dat <da...@apache.org>
Committed: Sat Dec 1 17:09:29 2018 +0000

----------------------------------------------------------------------
 dev-tools/scripts/buildAndPushRelease.py        |   4 +-
 lucene/CHANGES.txt                              |  17 +-
 lucene/MIGRATE.txt                              |   8 +
 .../org/apache/lucene/index/SegmentInfo.java    |  12 +-
 .../search/similarities/BM25Similarity.java     |   4 +-
 .../apache/lucene/index/TestSegmentInfos.java   |  53 ++
 lucene/ivy-versions.properties                  |  12 +-
 lucene/licenses/httpclient-4.5.3.jar.sha1       |   1 -
 lucene/licenses/httpclient-4.5.6.jar.sha1       |   1 +
 lucene/licenses/httpcore-4.4.10.jar.sha1        |   1 +
 lucene/licenses/httpcore-4.4.6.jar.sha1         |   1 -
 ...jetty-continuation-9.4.11.v20180605.jar.sha1 |   1 -
 ...jetty-continuation-9.4.14.v20181114.jar.sha1 |   1 +
 .../jetty-http-9.4.11.v20180605.jar.sha1        |   1 -
 .../jetty-http-9.4.14.v20181114.jar.sha1        |   1 +
 .../licenses/jetty-io-9.4.11.v20180605.jar.sha1 |   1 -
 .../licenses/jetty-io-9.4.14.v20181114.jar.sha1 |   1 +
 .../jetty-server-9.4.11.v20180605.jar.sha1      |   1 -
 .../jetty-server-9.4.14.v20181114.jar.sha1      |   1 +
 .../jetty-servlet-9.4.11.v20180605.jar.sha1     |   1 -
 .../jetty-servlet-9.4.14.v20181114.jar.sha1     |   1 +
 .../jetty-util-9.4.11.v20180605.jar.sha1        |   1 -
 .../jetty-util-9.4.14.v20181114.jar.sha1        |   1 +
 .../search/similarity/LegacyBM25Similarity.java |  96 +++
 .../lucene/search/similarity/package.html       |  22 +
 .../similarity/TestLegacyBM25Similarity.java    | 122 +++
 lucene/tools/junit4/solr-tests.policy           |   4 +
 solr/CHANGES.txt                                |  62 +-
 .../LegacyAbstractAnalyticsCloudTest.java       |  23 +-
 .../legacy/LegacyNoFacetCloudTest.java          |  14 +-
 .../legacy/facet/LegacyFieldFacetCloudTest.java |   7 +-
 .../facet/LegacyFieldFacetExtrasCloudTest.java  |   7 +-
 .../legacy/facet/LegacyQueryFacetCloudTest.java |   7 +-
 .../legacy/facet/LegacyRangeFacetCloudTest.java |   7 +-
 .../dataimport/TestContentStreamDataSource.java |   4 +-
 .../TestSolrEntityProcessorEndToEnd.java        |   4 +-
 .../dataimport/TestZKPropertiesWriter.java      |   3 +-
 .../org/apache/solr/ltr/LTRThreadModule.java    |  47 +-
 .../LTRFeatureLoggerTransformerFactory.java     |   5 +-
 .../solr/ltr/search/LTRQParserPlugin.java       |   4 +-
 .../org/apache/solr/ltr/TestLTROnSolrCloud.java |   3 +-
 .../solr/client/solrj/embedded/JettyConfig.java |  15 +-
 .../client/solrj/embedded/JettySolrRunner.java  | 281 +++++--
 .../org/apache/solr/cloud/ElectionContext.java  |  75 +-
 .../org/apache/solr/cloud/LeaderElector.java    |   3 +
 .../java/org/apache/solr/cloud/Overseer.java    |  88 +-
 .../OverseerCollectionConfigSetProcessor.java   |  18 +-
 .../solr/cloud/OverseerNodePrioritizer.java     |  14 +-
 .../solr/cloud/OverseerTaskProcessor.java       |  48 +-
 .../org/apache/solr/cloud/RecoveryStrategy.java | 188 +++--
 .../apache/solr/cloud/ReplicateFromLeader.java  |   8 +-
 .../org/apache/solr/cloud/SyncStrategy.java     |  29 +-
 .../org/apache/solr/cloud/ZkController.java     | 151 ++--
 .../apache/solr/cloud/ZkDistributedQueue.java   |   9 +-
 .../org/apache/solr/cloud/ZkShardTerms.java     |  33 +-
 .../cloud/api/collections/AddReplicaCmd.java    |   3 +-
 .../solr/cloud/api/collections/Assign.java      |  23 +-
 .../api/collections/CreateCollectionCmd.java    |   8 +-
 .../cloud/api/collections/CreateShardCmd.java   |   3 +-
 .../api/collections/DeleteCollectionCmd.java    |  35 +-
 .../cloud/api/collections/DeleteReplicaCmd.java |   2 +-
 .../cloud/api/collections/DeleteShardCmd.java   |  43 +-
 .../solr/cloud/api/collections/MigrateCmd.java  |   5 +-
 .../OverseerCollectionMessageHandler.java       | 134 ++--
 .../solr/cloud/api/collections/RestoreCmd.java  |  35 +-
 .../cloud/api/collections/SplitShardCmd.java    |  24 +-
 .../solr/cloud/autoscaling/NodeLostTrigger.java |  12 +-
 .../autoscaling/OverseerTriggerThread.java      |  13 +-
 .../cloud/autoscaling/ScheduledTrigger.java     |   4 +-
 .../cloud/autoscaling/ScheduledTriggers.java    |  49 +-
 .../solr/cloud/autoscaling/TriggerBase.java     |   7 +-
 .../cloud/autoscaling/TriggerEventQueue.java    |   7 +-
 .../java/org/apache/solr/core/CloudConfig.java  |   4 +-
 .../org/apache/solr/core/CoreContainer.java     | 216 +++--
 .../src/java/org/apache/solr/core/SolrCore.java |  72 +-
 .../core/TransientSolrCoreCacheFactory.java     |   2 +-
 .../TransientSolrCoreCacheFactoryDefault.java   |   2 +-
 .../java/org/apache/solr/core/ZkContainer.java  |  16 +-
 .../solr/handler/CdcrReplicatorManager.java     |   1 +
 .../org/apache/solr/handler/IndexFetcher.java   |   2 +-
 .../apache/solr/handler/ReplicationHandler.java |   4 +-
 .../admin/AutoscalingHistoryHandler.java        |   2 +-
 .../solr/handler/admin/CollectionsHandler.java  |  93 ++-
 .../solr/handler/admin/CoreAdminHandler.java    |   2 +-
 .../handler/admin/MetricsHistoryHandler.java    |  12 +-
 .../solr/handler/admin/PrepRecoveryOp.java      | 202 +++--
 .../component/IterativeMergeStrategy.java       |  47 +-
 .../solr/handler/loader/JavabinLoader.java      |   8 -
 .../org/apache/solr/handler/sql/SolrSchema.java |   4 +-
 .../org/apache/solr/request/SimpleFacets.java   |  13 +-
 .../apache/solr/request/SolrRequestInfo.java    |   2 +-
 .../apache/solr/search/facet/FacetField.java    |  25 +-
 .../solr/search/facet/FacetFieldMerger.java     |   2 +-
 .../solr/search/facet/FacetFieldProcessor.java  | 334 ++++++--
 .../solr/search/facet/FacetRangeMerger.java     |   4 +-
 .../apache/solr/search/facet/FacetRequest.java  |  70 +-
 .../search/facet/FacetRequestSortedMerger.java  |  25 +-
 .../similarities/BM25SimilarityFactory.java     |   8 +-
 .../similarities/SchemaSimilarityFactory.java   |   6 +-
 .../solr/security/PKIAuthenticationPlugin.java  |   2 +-
 .../org/apache/solr/servlet/HttpSolrCall.java   |   5 +-
 .../apache/solr/servlet/SolrDispatchFilter.java |  56 +-
 .../org/apache/solr/update/CommitTracker.java   |   2 +-
 .../solr/update/DirectUpdateHandler2.java       | 109 +--
 .../org/apache/solr/update/SolrCoreState.java   |   8 +-
 .../java/org/apache/solr/update/UpdateLog.java  |  16 +-
 .../apache/solr/update/UpdateShardHandler.java  |  29 +-
 .../processor/DistributedUpdateProcessor.java   | 159 +++-
 .../TimeRoutedAliasUpdateProcessor.java         |  21 +-
 .../src/java/org/apache/solr/util/SolrCLI.java  |   2 +-
 .../org/apache/solr/util/TestInjection.java     |  91 ++-
 .../src/java/org/apache/solr/util/TimeOut.java  |   7 +-
 .../src/test-files/solr/solr-jmxreporter.xml    |   1 +
 solr/core/src/test-files/solr/solr.xml          |  12 +-
 .../org/apache/solr/TestDistributedSearch.java  | 193 +++--
 .../apache/solr/TestHighlightDedupGrouping.java |  12 +-
 .../org/apache/solr/TestTolerantSearch.java     |   2 +-
 .../org/apache/solr/cloud/AddReplicaTest.java   |  26 +-
 .../apache/solr/cloud/AliasIntegrationTest.java |  47 +-
 .../cloud/AssignBackwardCompatibilityTest.java  |   3 +-
 .../AsyncCallRequestStatusResponseTest.java     |   2 +-
 .../solr/cloud/BasicDistributedZk2Test.java     |   6 +-
 .../solr/cloud/BasicDistributedZkTest.java      | 162 +++-
 .../test/org/apache/solr/cloud/BasicZkTest.java |   2 +-
 .../cloud/ChaosMonkeyNothingIsSafeTest.java     |  58 +-
 ...MonkeyNothingIsSafeWithPullReplicasTest.java |  52 +-
 .../solr/cloud/ChaosMonkeySafeLeaderTest.java   |   6 +-
 ...aosMonkeySafeLeaderWithPullReplicasTest.java |  13 +-
 .../solr/cloud/ChaosMonkeyShardSplitTest.java   |  15 +-
 .../apache/solr/cloud/CleanupOldIndexTest.java  |   4 +-
 .../org/apache/solr/cloud/CloudTestUtils.java   |   8 +-
 .../solr/cloud/ClusterStateUpdateTest.java      |   6 +-
 .../solr/cloud/CollectionStateFormat2Test.java  |  16 +-
 .../solr/cloud/CollectionsAPISolrJTest.java     |  74 +-
 .../solr/cloud/ConnectionManagerTest.java       |  23 +-
 .../solr/cloud/CreateRoutedAliasTest.java       |  20 +-
 .../org/apache/solr/cloud/DeleteNodeTest.java   |   1 -
 .../apache/solr/cloud/DeleteReplicaTest.java    |  89 ++-
 .../org/apache/solr/cloud/DeleteShardTest.java  |  25 +-
 .../solr/cloud/DocValuesNotIndexedTest.java     |  37 +-
 .../org/apache/solr/cloud/ForceLeaderTest.java  |  34 +-
 .../FullThrottleStoppableIndexingThread.java    |  18 +-
 .../solr/cloud/HttpPartitionOnCommitTest.java   |  14 +-
 .../apache/solr/cloud/HttpPartitionTest.java    |  43 +-
 .../apache/solr/cloud/KerberosTestServices.java |  48 +-
 .../apache/solr/cloud/LeaderElectionTest.java   |  32 +-
 .../cloud/LeaderFailoverAfterPartitionTest.java |   1 +
 .../cloud/LeaderFailureAfterFreshStartTest.java |   4 +-
 .../solr/cloud/LeaderTragicEventTest.java       |   9 +-
 .../solr/cloud/LeaderVoteWaitTimeoutTest.java   |  82 +-
 .../solr/cloud/LegacyCloudClusterPropTest.java  |  15 +
 .../cloud/MetricsHistoryIntegrationTest.java    |  11 +-
 .../solr/cloud/MockSimpleZkController.java      |  36 +
 .../org/apache/solr/cloud/MockSolrSource.java   |  48 ++
 .../org/apache/solr/cloud/MockZkController.java |  36 -
 .../solr/cloud/MoveReplicaHDFSFailoverTest.java |   2 +
 .../apache/solr/cloud/MoveReplicaHDFSTest.java  |   4 +-
 .../org/apache/solr/cloud/MoveReplicaTest.java  |  32 +-
 .../apache/solr/cloud/MultiThreadedOCPTest.java |   8 +-
 ...rriddenZkACLAndCredentialsProvidersTest.java |   2 +-
 ...verseerCollectionConfigSetProcessorTest.java | 245 ++++--
 .../apache/solr/cloud/OverseerRolesTest.java    |  10 +-
 .../org/apache/solr/cloud/OverseerTest.java     | 793 +++++++++++--------
 .../solr/cloud/PeerSyncReplicationTest.java     |   8 +-
 .../solr/cloud/RecoveryAfterSoftCommitTest.java |   3 +-
 .../solr/cloud/ReplaceNodeNoTargetTest.java     |   2 +-
 .../org/apache/solr/cloud/ReplaceNodeTest.java  |  18 +-
 .../solr/cloud/ReplicationFactorTest.java       |   3 +-
 .../solr/cloud/RestartWhileUpdatingTest.java    |   2 -
 .../apache/solr/cloud/RollingRestartTest.java   |   2 +-
 .../org/apache/solr/cloud/SSLMigrationTest.java |   3 +-
 .../solr/cloud/SaslZkACLProviderTest.java       |  16 +-
 .../solr/cloud/ShardRoutingCustomTest.java      |  17 +-
 .../cloud/SharedFSAutoReplicaFailoverTest.java  |  12 +-
 .../org/apache/solr/cloud/SolrXmlInZkTest.java  |   3 +-
 .../org/apache/solr/cloud/SplitShardTest.java   |   5 +-
 .../org/apache/solr/cloud/SyncSliceTest.java    |   6 +-
 .../solr/cloud/TestAuthenticationFramework.java |  12 +-
 .../apache/solr/cloud/TestCloudConsistency.java |  54 +-
 .../solr/cloud/TestCloudDeleteByQuery.java      |   3 +-
 .../apache/solr/cloud/TestCloudRecovery.java    |  63 +-
 .../solr/cloud/TestCloudSearcherWarming.java    |  55 +-
 .../cloud/TestDeleteCollectionOnDownNodes.java  |  36 +-
 .../apache/solr/cloud/TestDistributedMap.java   |   4 +-
 .../solr/cloud/TestDownShardTolerantSearch.java |   5 +-
 .../TestLeaderElectionWithEmptyReplica.java     |   7 +-
 .../solr/cloud/TestLeaderElectionZkExpiry.java  |   2 -
 .../solr/cloud/TestMiniSolrCloudClusterSSL.java |   2 +
 .../org/apache/solr/cloud/TestPrepRecovery.java |  20 +-
 .../org/apache/solr/cloud/TestPullReplica.java  |  29 +-
 .../cloud/TestPullReplicaErrorHandling.java     |  11 +-
 .../apache/solr/cloud/TestRandomFlRTGCloud.java |   4 +-
 .../cloud/TestRandomRequestDistribution.java    |   2 +-
 .../solr/cloud/TestRequestForwarding.java       |   2 +-
 .../apache/solr/cloud/TestSegmentSorting.java   |   2 +-
 .../solr/cloud/TestSkipOverseerOperations.java  |  94 ++-
 .../TestSolrCloudWithDelegationTokens.java      |   1 +
 .../cloud/TestSolrCloudWithKerberosAlt.java     |   3 +-
 .../TestSolrCloudWithSecureImpersonation.java   |   5 +-
 .../TestStressCloudBlindAtomicUpdates.java      |   4 +-
 .../solr/cloud/TestStressInPlaceUpdates.java    |  10 +-
 .../apache/solr/cloud/TestStressLiveNodes.java  |   3 -
 .../org/apache/solr/cloud/TestTlogReplica.java  |  46 +-
 .../cloud/TestTolerantUpdateProcessorCloud.java |  40 +-
 .../TestTolerantUpdateProcessorRandomCloud.java |   8 +-
 .../org/apache/solr/cloud/TestUtilizeNode.java  |   1 -
 .../apache/solr/cloud/TestWithCollection.java   |  48 +-
 .../TlogReplayBufferedWhileIndexingTest.java    |   6 +-
 ...MParamsZkACLAndCredentialsProvidersTest.java |   7 +-
 .../org/apache/solr/cloud/ZkControllerTest.java |  16 +-
 .../org/apache/solr/cloud/ZkFailoverTest.java   |  16 +-
 .../org/apache/solr/cloud/ZkSolrClientTest.java |  63 +-
 .../solr/cloud/api/collections/AssignTest.java  |  26 +-
 .../CollectionsAPIAsyncDistributedZkTest.java   |  69 +-
 .../CollectionsAPIDistributedZkTest.java        |  96 ++-
 .../HdfsCollectionsAPIDistributedZkTest.java    |   3 +-
 .../cloud/api/collections/ShardSplitTest.java   |  54 +-
 .../SimpleCollectionCreateDeleteTest.java       |  35 +
 .../TestCollectionsAPIViaSolrCloudCluster.java  |  20 +-
 .../collections/TestHdfsCloudBackupRestore.java |   5 +-
 .../TestLocalFSCloudBackupRestore.java          |  12 +-
 .../AutoAddReplicasIntegrationTest.java         |  57 +-
 .../AutoAddReplicasPlanActionTest.java          | 103 ++-
 .../autoscaling/ComputePlanActionTest.java      |  45 +-
 .../autoscaling/ExecutePlanActionTest.java      |  40 +-
 .../HdfsAutoAddReplicasIntegrationTest.java     |   2 +
 .../autoscaling/HttpTriggerListenerTest.java    |   1 +
 .../cloud/autoscaling/IndexSizeTriggerTest.java |  60 +-
 .../MetricTriggerIntegrationTest.java           |   4 +-
 .../cloud/autoscaling/MetricTriggerTest.java    |   1 +
 .../NodeAddedTriggerIntegrationTest.java        |  51 +-
 .../cloud/autoscaling/NodeAddedTriggerTest.java |  17 +-
 .../NodeLostTriggerIntegrationTest.java         |  62 +-
 .../cloud/autoscaling/NodeLostTriggerTest.java  |  58 +-
 .../NodeMarkersRegistrationTest.java            |  66 +-
 .../autoscaling/RestoreTriggerStateTest.java    |   4 +-
 .../ScheduledMaintenanceTriggerTest.java        |   2 +-
 .../ScheduledTriggerIntegrationTest.java        |  23 +-
 .../cloud/autoscaling/ScheduledTriggerTest.java |   9 +-
 .../SearchRateTriggerIntegrationTest.java       |   2 +
 .../autoscaling/SearchRateTriggerTest.java      |  31 +-
 .../autoscaling/SystemLogListenerTest.java      |  60 +-
 .../solr/cloud/autoscaling/TestPolicyCloud.java |  12 +-
 .../TriggerCooldownIntegrationTest.java         |   1 +
 .../autoscaling/TriggerIntegrationTest.java     |  17 +-
 .../cloud/autoscaling/sim/LiveNodesSet.java     |   4 +
 .../sim/SimClusterStateProvider.java            |  48 +-
 .../autoscaling/sim/SimSolrCloudTestCase.java   |  33 +-
 .../sim/TestSimClusterStateProvider.java        |   4 +-
 .../sim/TestSimComputePlanAction.java           |  20 +-
 .../sim/TestSimDistributedQueue.java            |   4 +-
 .../sim/TestSimExecutePlanAction.java           |   3 +-
 .../autoscaling/sim/TestSimExtremeIndexing.java |   4 +-
 .../autoscaling/sim/TestSimLargeCluster.java    |  51 +-
 .../autoscaling/sim/TestSimPolicyCloud.java     |  12 +-
 .../sim/TestSimTriggerIntegration.java          | 117 +--
 .../cloud/cdcr/BaseCdcrDistributedZkTest.java   |   8 +-
 .../solr/cloud/cdcr/CdcrBidirectionalTest.java  |   2 -
 .../solr/cloud/cdcr/CdcrBootstrapTest.java      |  18 +-
 .../cloud/cdcr/CdcrOpsAndBoundariesTest.java    |   5 +-
 .../cloud/cdcr/CdcrReplicationHandlerTest.java  |  11 +-
 .../apache/solr/cloud/cdcr/CdcrTestsUtil.java   |   5 +-
 .../cloud/cdcr/CdcrWithNodesRestartsTest.java   |  13 +-
 .../hdfs/HdfsChaosMonkeyNothingIsSafeTest.java  |   7 +-
 .../apache/solr/cloud/hdfs/StressHdfsTest.java  |   7 +-
 .../solr/cloud/overseer/ZkStateReaderTest.java  |   9 -
 .../solr/cloud/overseer/ZkStateWriterTest.java  |  11 -
 .../test/org/apache/solr/core/SolrCoreTest.java |   3 +
 .../org/apache/solr/core/TestDynamicURP.java    |   9 +-
 .../apache/solr/core/TestSolrConfigHandler.java |  82 +-
 .../core/snapshots/TestSolrCloudSnapshots.java  |   1 +
 .../core/snapshots/TestSolrCoreSnapshots.java   |   1 -
 .../solr/handler/TestHdfsBackupRestoreCore.java |   2 +-
 .../solr/handler/TestReplicationHandler.java    |  52 +-
 .../handler/TestReplicationHandlerBackup.java   |   4 +-
 .../apache/solr/handler/TestReqParamsAPI.java   |   1 +
 .../apache/solr/handler/TestRestoreCore.java    |   4 +-
 .../solr/handler/TestSQLHandlerNonCloud.java    |   2 +-
 .../handler/TestSolrConfigHandlerCloud.java     |  26 +-
 .../solr/handler/V2ApiIntegrationTest.java      |   1 +
 .../admin/AutoscalingHistoryHandlerTest.java    |   8 +-
 .../admin/MetricsHistoryHandlerTest.java        |  17 +-
 .../admin/ShowFileRequestHandlerTest.java       |   2 +-
 .../admin/ZookeeperStatusHandlerTest.java       |   2 +-
 .../DistributedDebugComponentTest.java          |   2 +-
 .../DistributedFacetExistsSmallTest.java        |   5 +-
 .../org/apache/solr/metrics/JvmMetricsTest.java |   2 +-
 .../reporters/solr/SolrCloudReportersTest.java  |  26 +-
 .../solr/request/TestRemoteStreaming.java       |   2 +-
 .../solr/rest/TestManagedResourceStorage.java   |   4 +-
 .../solr/rest/schema/TestBulkSchemaAPI.java     |  35 +-
 .../org/apache/solr/schema/TestBinaryField.java |   2 +-
 .../solr/schema/TestBulkSchemaConcurrent.java   |   3 +-
 .../schema/TestManagedSchemaThreadSafety.java   |   3 +-
 .../solr/search/AnalyticsMergeStrategyTest.java |   2 -
 .../org/apache/solr/search/TestRecovery.java    |  40 +-
 .../apache/solr/search/TestSolr4Spatial2.java   |   2 +-
 .../apache/solr/search/TestStressRecovery.java  |  51 +-
 .../org/apache/solr/search/facet/DebugAgg.java  |  39 +-
 .../search/facet/TestJsonFacetRefinement.java   | 127 +++
 .../solr/search/facet/TestJsonFacets.java       | 491 +++++++++++-
 .../facet/TestJsonFacetsStatsParsing.java       |  15 +
 .../search/join/BlockJoinFacetDistribTest.java  |   2 +
 .../solr/search/mlt/CloudMLTQParserTest.java    |  51 +-
 .../similarities/TestBM25SimilarityFactory.java |   8 +-
 .../TestNonDefinedSimilarityFactory.java        |   4 +-
 .../similarities/TestPerFieldSimilarity.java    |   8 +-
 .../solr/search/stats/TestDistribIDF.java       |   6 +-
 .../solr/security/BasicAuthIntegrationTest.java |   8 +
 .../solr/security/BasicAuthStandaloneTest.java  |   4 +-
 .../security/TestPKIAuthenticationPlugin.java   |   5 +-
 .../hadoop/TestDelegationWithHadoopAuth.java    |   1 +
 .../apache/solr/servlet/CacheHeaderTest.java    |   2 +-
 .../apache/solr/servlet/NoCacheHeaderTest.java  |   2 +-
 .../apache/solr/servlet/ResponseHeaderTest.java |   2 +-
 .../solr/store/hdfs/HdfsLockFactoryTest.java    |   2 +
 .../apache/solr/update/SoftAutoCommitTest.java  |   2 +-
 .../solr/update/SolrCmdDistributorTest.java     |   3 +-
 .../apache/solr/update/TestHdfsUpdateLog.java   |   2 -
 .../solr/update/TestInPlaceUpdatesDistrib.java  |  72 +-
 .../TimeRoutedAliasUpdateProcessorTest.java     |  39 +-
 .../apache/solr/util/TestSolrCLIRunExample.java |  12 +-
 solr/licenses/byte-buddy-1.6.2.jar.sha1         |   1 -
 solr/licenses/byte-buddy-1.9.3.jar.sha1         |   1 +
 solr/licenses/httpclient-4.5.3.jar.sha1         |   1 -
 solr/licenses/httpclient-4.5.6.jar.sha1         |   1 +
 solr/licenses/httpcore-4.4.10.jar.sha1          |   1 +
 solr/licenses/httpcore-4.4.6.jar.sha1           |   1 -
 solr/licenses/httpmime-4.5.3.jar.sha1           |   1 -
 solr/licenses/httpmime-4.5.6.jar.sha1           |   1 +
 ...jetty-continuation-9.4.11.v20180605.jar.sha1 |   1 -
 ...jetty-continuation-9.4.14.v20181114.jar.sha1 |   1 +
 .../jetty-deploy-9.4.11.v20180605.jar.sha1      |   1 -
 .../jetty-deploy-9.4.14.v20181114.jar.sha1      |   1 +
 .../jetty-http-9.4.11.v20180605.jar.sha1        |   1 -
 .../jetty-http-9.4.14.v20181114.jar.sha1        |   1 +
 .../licenses/jetty-io-9.4.11.v20180605.jar.sha1 |   1 -
 .../licenses/jetty-io-9.4.14.v20181114.jar.sha1 |   1 +
 .../jetty-jmx-9.4.11.v20180605.jar.sha1         |   1 -
 .../jetty-jmx-9.4.14.v20181114.jar.sha1         |   1 +
 .../jetty-rewrite-9.4.11.v20180605.jar.sha1     |   1 -
 .../jetty-rewrite-9.4.14.v20181114.jar.sha1     |   1 +
 .../jetty-security-9.4.11.v20180605.jar.sha1    |   1 -
 .../jetty-security-9.4.14.v20181114.jar.sha1    |   1 +
 .../jetty-server-9.4.11.v20180605.jar.sha1      |   1 -
 .../jetty-server-9.4.14.v20181114.jar.sha1      |   1 +
 .../jetty-servlet-9.4.11.v20180605.jar.sha1     |   1 -
 .../jetty-servlet-9.4.14.v20181114.jar.sha1     |   1 +
 .../jetty-servlets-9.4.11.v20180605.jar.sha1    |   1 -
 .../jetty-servlets-9.4.14.v20181114.jar.sha1    |   1 +
 .../jetty-util-9.4.11.v20180605.jar.sha1        |   1 -
 .../jetty-util-9.4.14.v20181114.jar.sha1        |   1 +
 .../jetty-webapp-9.4.11.v20180605.jar.sha1      |   1 -
 .../jetty-webapp-9.4.14.v20181114.jar.sha1      |   1 +
 .../jetty-xml-9.4.11.v20180605.jar.sha1         |   1 -
 .../jetty-xml-9.4.14.v20181114.jar.sha1         |   1 +
 solr/licenses/mockito-core-2.23.4.jar.sha1      |   1 +
 solr/licenses/mockito-core-2.6.2.jar.sha1       |   1 -
 solr/licenses/objenesis-2.5.jar.sha1            |   1 -
 solr/licenses/objenesis-2.6.jar.sha1            |   1 +
 solr/licenses/start.jar.sha1                    |   2 +-
 solr/solr-ref-guide/src/blob-store-api.adoc     |  34 +-
 solr/solr-ref-guide/src/json-facet-api.adoc     |  36 +-
 .../solr/client/solrj/cloud/SocketProxy.java    | 460 +++++++++++
 .../solr/client/solrj/impl/CloudSolrClient.java |  29 +-
 .../solr/client/solrj/impl/HttpClientUtil.java  |   2 +-
 .../client/solrj/impl/LBHttpSolrClient.java     |   4 +-
 .../solr/client/solrj/impl/LBSolrClient.java    |  20 +-
 .../client/solrj/impl/SolrClientBuilder.java    |   4 +-
 .../solrj/impl/SolrClientNodeStateProvider.java |  69 +-
 .../impl/ZkClientClusterStateProvider.java      |  12 +-
 .../solrj/impl/ZkDistribStateManager.java       |  28 +-
 .../solr/client/solrj/io/SolrClientCache.java   |   2 +-
 .../client/solrj/io/stream/FacetStream.java     |   2 +-
 .../client/solrj/io/stream/RandomStream.java    |   2 +-
 .../solr/common/AlreadyClosedException.java     |  40 +
 .../solr/common/cloud/ConnectionManager.java    |  30 +-
 .../common/cloud/DefaultConnectionStrategy.java |   3 +
 .../apache/solr/common/cloud/DocCollection.java |  14 +-
 .../solr/common/cloud/LiveNodesListener.java    |   4 +-
 .../solr/common/cloud/LiveNodesPredicate.java   |  31 +
 .../solr/common/cloud/LiveNodesWatcher.java     |  26 +
 .../org/apache/solr/common/cloud/Replica.java   |   2 +-
 .../apache/solr/common/cloud/SolrZkClient.java  | 119 +--
 .../apache/solr/common/cloud/SolrZooKeeper.java |   3 -
 .../apache/solr/common/cloud/ZkCmdExecutor.java |  17 +-
 .../apache/solr/common/cloud/ZkStateReader.java | 138 +++-
 .../UsingSolrJRefGuideExamplesTest.java         |   1 +
 .../client/solrj/SolrExampleBinaryTest.java     |   2 +-
 .../solr/client/solrj/SolrExampleXMLTest.java   |   2 +-
 .../client/solrj/SolrSchemalessExampleTest.java |   2 +-
 .../solr/client/solrj/TestBatchUpdate.java      |   2 +-
 .../solr/client/solrj/TestLBHttpSolrClient.java | 143 ++--
 .../client/solrj/TestSolrJErrorHandling.java    |   2 +-
 .../embedded/LargeVolumeBinaryJettyTest.java    |   2 +-
 .../solrj/embedded/LargeVolumeJettyTest.java    |   2 +-
 .../solrj/embedded/SolrExampleJettyTest.java    |   2 +-
 .../embedded/SolrExampleStreamingTest.java      |   2 +-
 .../solrj/impl/BasicHttpSolrClientTest.java     |   2 +-
 .../client/solrj/impl/CloudSolrClientTest.java  | 104 ++-
 .../ConcurrentUpdateSolrClientBadInputTest.java |   2 +-
 .../impl/ConcurrentUpdateSolrClientTest.java    |   2 +-
 .../solrj/impl/HttpSolrClientBadInputTest.java  |   2 +-
 .../solrj/impl/HttpSolrClientConPoolTest.java   |   4 +-
 .../impl/LBHttpSolrClientBadInputTest.java      |   2 +-
 .../impl/TestCloudSolrClientConnections.java    |   2 +
 .../solr/client/solrj/io/graph/GraphTest.java   |   5 +-
 .../solr/client/solrj/io/sql/JdbcTest.java      |   3 +
 .../solrj/io/stream/MathExpressionTest.java     |  81 +-
 .../io/stream/SelectWithEvaluatorsTest.java     |   2 +-
 .../solrj/io/stream/StreamDecoratorTest.java    |  62 +-
 .../solrj/io/stream/StreamExpressionTest.java   |  10 +-
 .../client/solrj/io/stream/StreamingTest.java   |   4 +-
 .../client/solrj/request/TestV2Request.java     |  16 +-
 .../solrj/response/NoOpResponseParserTest.java  |   2 +-
 .../cloud/TestCloudCollectionsListeners.java    |  38 +-
 .../cloud/TestCollectionStateWatchers.java      |  24 +-
 .../solr/common/cloud/TestZkConfigManager.java  |   2 +-
 .../solr/BaseDistributedSearchTestCase.java     | 129 ++-
 .../apache/solr/SolrIgnoredThreadsFilter.java   |  24 +-
 .../java/org/apache/solr/SolrJettyTestBase.java |  18 +-
 .../java/org/apache/solr/SolrTestCaseJ4.java    |  90 ++-
 .../solr/cloud/AbstractDistribZkTestBase.java   | 203 +++--
 .../cloud/AbstractFullDistribZkTestBase.java    | 414 ++++++----
 .../apache/solr/cloud/AbstractZkTestCase.java   | 137 +---
 .../java/org/apache/solr/cloud/ChaosMonkey.java | 167 +---
 .../apache/solr/cloud/MiniSolrCloudCluster.java | 266 ++++++-
 .../java/org/apache/solr/cloud/SocketProxy.java | 460 -----------
 .../apache/solr/cloud/SolrCloudTestCase.java    |  73 +-
 .../org/apache/solr/cloud/ZkTestServer.java     | 383 ++++++---
 .../component/TrackingShardHandlerFactory.java  |  53 +-
 .../apache/solr/util/BadHdfsThreadsFilter.java  |   7 +
 .../java/org/apache/solr/util/RestTestBase.java |   2 +-
 .../java/org/apache/solr/util/TestHarness.java  |   7 -
 434 files changed, 8844 insertions(+), 4883 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/lucene/ivy-versions.properties
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/lucene/tools/junit4/solr-tests.policy
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/CHANGES.txt
----------------------------------------------------------------------
diff --cc solr/CHANGES.txt
index 7794676,22b6721..0f8be68
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@@ -156,12 -130,8 +130,8 @@@ Upgrade Note
  New Features
  ----------------------
  
- (No Changes)
- 
- Other Changes
- ----------------------
- 
- * SOLR-12972: deprecate unused SolrIndexConfig.luceneVersion (Christine Poerschke)
 -* SOLR-12839: JSON 'terms' Faceting now supports a 'prelim_sort' option to use when initially selecting 
++* SOLR-12839: JSON 'terms' Faceting now supports a 'prelim_sort' option to use when initially selecting
+   the top ranking buckets, prior to the final 'sort' option used after refinement.  (hossman)
  
  Bug Fixes
  ----------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettyConfig.java
----------------------------------------------------------------------
diff --cc solr/core/src/java/org/apache/solr/client/solrj/embedded/JettyConfig.java
index 8dfe0be,748aee9..5952ff8
--- a/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettyConfig.java
+++ b/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettyConfig.java
@@@ -41,10 -38,11 +41,13 @@@ public class JettyConfig 
    public final Map<Class<? extends Filter>, String> extraFilters;
  
    public final SSLConfig sslConfig;
+   
+   public final int portRetryTime;
  
-   private JettyConfig(boolean onlyHttp1, int port, String context, boolean stopAtShutdown, Long waitForLoadingCoresToFinishMs, Map<ServletHolder, String> extraServlets,
 -  private JettyConfig(int port, int portRetryTime, String context, boolean stopAtShutdown, Long waitForLoadingCoresToFinishMs, Map<ServletHolder, String> extraServlets,
++  private JettyConfig(boolean onlyHttp1, int port, int portRetryTime , String context, boolean stopAtShutdown,
++                      Long waitForLoadingCoresToFinishMs, Map<ServletHolder, String> extraServlets,
                        Map<Class<? extends Filter>, String> extraFilters, SSLConfig sslConfig) {
 +    this.onlyHttp1 = onlyHttp1;
      this.port = port;
      this.context = context;
      this.stopAtShutdown = stopAtShutdown;
@@@ -79,12 -77,8 +83,13 @@@
      Map<ServletHolder, String> extraServlets = new TreeMap<>();
      Map<Class<? extends Filter>, String> extraFilters = new LinkedHashMap<>();
      SSLConfig sslConfig = null;
+     int portRetryTime = 60;
  
 +    public Builder useOnlyHttp1(boolean useOnlyHttp1) {
 +      this.onlyHttp1 = useOnlyHttp1;
 +      return this;
 +    }
 +
      public Builder setPort(int port) {
        this.port = port;
        return this;
@@@ -131,9 -125,15 +136,15 @@@
        this.sslConfig = sslConfig;
        return this;
      }
+     
+     public Builder withPortRetryTime(int portRetryTime) {
+       this.portRetryTime = portRetryTime;
+       return this;
+     }
+ 
  
      public JettyConfig build() {
-       return new JettyConfig(onlyHttp1, port, context, stopAtShutdown, waitForLoadingCoresToFinishMs, extraServlets, extraFilters, sslConfig);
 -      return new JettyConfig(port, portRetryTime, context, stopAtShutdown, waitForLoadingCoresToFinishMs, extraServlets, extraFilters, sslConfig);
++      return new JettyConfig(onlyHttp1, port, portRetryTime, context, stopAtShutdown, waitForLoadingCoresToFinishMs, extraServlets, extraFilters, sslConfig);
      }
  
    }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettySolrRunner.java
----------------------------------------------------------------------
diff --cc solr/core/src/java/org/apache/solr/client/solrj/embedded/JettySolrRunner.java
index 5161406,5b5a032..b66f74c
--- a/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettySolrRunner.java
+++ b/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettySolrRunner.java
@@@ -41,14 -33,26 +33,30 @@@ import java.util.concurrent.TimeUnit
  import java.util.concurrent.atomic.AtomicInteger;
  import java.util.concurrent.atomic.AtomicLong;
  
+ import javax.servlet.DispatcherType;
+ import javax.servlet.Filter;
+ import javax.servlet.FilterChain;
+ import javax.servlet.FilterConfig;
+ import javax.servlet.ServletException;
+ import javax.servlet.ServletRequest;
+ import javax.servlet.ServletResponse;
+ import javax.servlet.http.HttpServlet;
+ import javax.servlet.http.HttpServletRequest;
+ import javax.servlet.http.HttpServletResponse;
+ 
  import org.apache.solr.client.solrj.SolrClient;
+ import org.apache.solr.client.solrj.cloud.SocketProxy;
  import org.apache.solr.client.solrj.impl.HttpSolrClient;
+ import org.apache.solr.common.util.ExecutorUtil;
+ import org.apache.solr.common.util.SolrjNamedThreadFactory;
+ import org.apache.solr.common.util.TimeSource;
  import org.apache.solr.core.CoreContainer;
  import org.apache.solr.servlet.SolrDispatchFilter;
 +import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory;
 +import org.eclipse.jetty.http2.HTTP2Cipher;
 +import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory;
 +import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
+ import org.apache.solr.util.TimeOut;
  import org.eclipse.jetty.server.Connector;
  import org.eclipse.jetty.server.HttpConfiguration;
  import org.eclipse.jetty.server.HttpConnectionFactory;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/core/src/java/org/apache/solr/cloud/OverseerNodePrioritizer.java
----------------------------------------------------------------------
diff --cc solr/core/src/java/org/apache/solr/cloud/OverseerNodePrioritizer.java
index 34ee041,6851141..05d0dbd
--- a/solr/core/src/java/org/apache/solr/cloud/OverseerNodePrioritizer.java
+++ b/solr/core/src/java/org/apache/solr/cloud/OverseerNodePrioritizer.java
@@@ -96,7 -104,7 +104,7 @@@ public class OverseerNodePrioritizer 
  
    private void invokeOverseerOp(String electionNode, String op) {
      ModifiableSolrParams params = new ModifiableSolrParams();
-     ShardHandler shardHandler = shardHandlerFactory.getShardHandler();
 -    ShardHandler shardHandler = ((HttpShardHandlerFactory)shardHandlerFactory).getShardHandler(httpClient);
++    ShardHandler shardHandler = ((HttpShardHandlerFactory)shardHandlerFactory).getShardHandler();
      params.set(CoreAdminParams.ACTION, CoreAdminAction.OVERSEEROP.toString());
      params.set("op", op);
      params.set("qt", adminPath);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/core/src/java/org/apache/solr/cloud/SyncStrategy.java
----------------------------------------------------------------------
diff --cc solr/core/src/java/org/apache/solr/cloud/SyncStrategy.java
index 3d9a964,2391414..4d4071a
--- a/solr/core/src/java/org/apache/solr/cloud/SyncStrategy.java
+++ b/solr/core/src/java/org/apache/solr/cloud/SyncStrategy.java
@@@ -70,7 -71,7 +71,7 @@@ public class SyncStrategy 
    public SyncStrategy(CoreContainer cc) {
      UpdateShardHandler updateShardHandler = cc.getUpdateShardHandler();
      client = updateShardHandler.getDefaultHttpClient();
-     shardHandler = cc.getShardHandlerFactory().getShardHandler();
 -    shardHandler = ((HttpShardHandlerFactory)cc.getShardHandlerFactory()).getShardHandler(cc.getUpdateShardHandler().getDefaultHttpClient());
++    shardHandler = ((HttpShardHandlerFactory)cc.getShardHandlerFactory()).getShardHandler();
      updateExecutor = updateShardHandler.getUpdateExecutor();
    }
    

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateCollectionCmd.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/core/src/java/org/apache/solr/cloud/api/collections/DeleteReplicaCmd.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/core/src/java/org/apache/solr/cloud/api/collections/MigrateCmd.java
----------------------------------------------------------------------
diff --cc solr/core/src/java/org/apache/solr/cloud/api/collections/MigrateCmd.java
index 59b7218,f22544a..ec366ef
--- a/solr/core/src/java/org/apache/solr/cloud/api/collections/MigrateCmd.java
+++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/MigrateCmd.java
@@@ -146,7 -147,7 +147,7 @@@ public class MigrateCmd implements Over
      DocRouter.Range keyHashRange = sourceRouter.keyHashRange(splitKey);
  
      ShardHandlerFactory shardHandlerFactory = ocmh.shardHandlerFactory;
-     ShardHandler shardHandler = shardHandlerFactory.getShardHandler();
 -    ShardHandler shardHandler = ((HttpShardHandlerFactory)shardHandlerFactory).getShardHandler(ocmh.overseer.getCoreContainer().getUpdateShardHandler().getDefaultHttpClient());
++    ShardHandler shardHandler = ((HttpShardHandlerFactory)shardHandlerFactory).getShardHandler();
  
      log.info("Hash range for split.key: {} is: {}", splitKey, keyHashRange);
      // intersect source range, keyHashRange and target range

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/core/src/java/org/apache/solr/cloud/api/collections/OverseerCollectionMessageHandler.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/core/src/java/org/apache/solr/cloud/api/collections/RestoreCmd.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/core/src/java/org/apache/solr/core/CoreContainer.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/core/src/java/org/apache/solr/security/PKIAuthenticationPlugin.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java
----------------------------------------------------------------------
diff --cc solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java
index 2d9ebb0,4bb201f..8e3486b
--- a/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java
+++ b/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java
@@@ -72,10 -64,16 +72,16 @@@ public class UpdateShardHandler impleme
    
    private ExecutorService recoveryExecutor;
    
 -  private final CloseableHttpClient updateOnlyClient;
 +  private final Http2SolrClient updateOnlyClient;
    
+   private final CloseableHttpClient recoveryOnlyClient;
+   
    private final CloseableHttpClient defaultClient;
  
+   private final InstrumentedPoolingHttpClientConnectionManager updateOnlyConnectionManager;
+   
+   private final InstrumentedPoolingHttpClientConnectionManager recoveryOnlyConnectionManager;
+   
    private final InstrumentedPoolingHttpClientConnectionManager defaultConnectionManager;
  
    private final InstrumentedHttpRequestExecutor httpRequestExecutor;
@@@ -90,41 -86,49 +96,47 @@@
    private int connectionTimeout = HttpClientUtil.DEFAULT_CONNECT_TIMEOUT;
  
    public UpdateShardHandler(UpdateShardHandlerConfig cfg) {
+     updateOnlyConnectionManager = new InstrumentedPoolingHttpClientConnectionManager(HttpClientUtil.getSchemaRegisteryProvider().getSchemaRegistry());
+     recoveryOnlyConnectionManager = new InstrumentedPoolingHttpClientConnectionManager(HttpClientUtil.getSchemaRegisteryProvider().getSchemaRegistry());
      defaultConnectionManager = new InstrumentedPoolingHttpClientConnectionManager(HttpClientUtil.getSchemaRegisteryProvider().getSchemaRegistry());
 +    ModifiableSolrParams clientParams = new ModifiableSolrParams();
      if (cfg != null ) {
+       updateOnlyConnectionManager.setMaxTotal(cfg.getMaxUpdateConnections());
+       updateOnlyConnectionManager.setDefaultMaxPerRoute(cfg.getMaxUpdateConnectionsPerHost());
+       recoveryOnlyConnectionManager.setMaxTotal(cfg.getMaxUpdateConnections());
+       recoveryOnlyConnectionManager.setDefaultMaxPerRoute(cfg.getMaxUpdateConnectionsPerHost());
        defaultConnectionManager.setMaxTotal(cfg.getMaxUpdateConnections());
        defaultConnectionManager.setDefaultMaxPerRoute(cfg.getMaxUpdateConnectionsPerHost());
 -    }
 -
 -    ModifiableSolrParams clientParams = new ModifiableSolrParams();
 -    if (cfg != null)  {
        clientParams.set(HttpClientUtil.PROP_SO_TIMEOUT, cfg.getDistributedSocketTimeout());
        clientParams.set(HttpClientUtil.PROP_CONNECTION_TIMEOUT, cfg.getDistributedConnectionTimeout());
 +      // following is done only for logging complete configuration.
 +      // The maxConnections and maxConnectionsPerHost have already been specified on the connection manager
 +      clientParams.set(HttpClientUtil.PROP_MAX_CONNECTIONS, cfg.getMaxUpdateConnections());
 +      clientParams.set(HttpClientUtil.PROP_MAX_CONNECTIONS_PER_HOST, cfg.getMaxUpdateConnectionsPerHost());
        socketTimeout = cfg.getDistributedSocketTimeout();
        connectionTimeout = cfg.getDistributedConnectionTimeout();
      }
 -    HttpClientMetricNameStrategy metricNameStrategy = KNOWN_METRIC_NAME_STRATEGIES.get(UpdateShardHandlerConfig.DEFAULT_METRICNAMESTRATEGY);
 -    if (cfg != null)  {
 -      metricNameStrategy = KNOWN_METRIC_NAME_STRATEGIES.get(cfg.getMetricNameStrategy());
 -      if (metricNameStrategy == null) {
 -        throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
 -            "Unknown metricNameStrategy: " + cfg.getMetricNameStrategy() + " found. Must be one of: " + KNOWN_METRIC_NAME_STRATEGIES.keySet());
 -      }
 -    }
 -
 +    log.debug("Created default UpdateShardHandler HTTP client with params: {}", clientParams);
  
 -    httpRequestExecutor = new InstrumentedHttpRequestExecutor(metricNameStrategy);
 -    updateOnlyClient = HttpClientUtil.createClient(clientParams, updateOnlyConnectionManager, false, httpRequestExecutor);
 +    httpRequestExecutor = new InstrumentedHttpRequestExecutor(getMetricNameStrategy(cfg));
 +    updateHttpListenerFactory = new InstrumentedHttpListenerFactory(getNameStrategy(cfg));
+     recoveryOnlyClient = HttpClientUtil.createClient(clientParams, recoveryOnlyConnectionManager, false, httpRequestExecutor);
+     defaultClient = HttpClientUtil.createClient(clientParams, defaultConnectionManager, false, httpRequestExecutor);
  
 -    // following is done only for logging complete configuration.
 -    // The maxConnections and maxConnectionsPerHost have already been specified on the connection manager
 -    if (cfg != null)  {
 -      clientParams.set(HttpClientUtil.PROP_MAX_CONNECTIONS, cfg.getMaxUpdateConnections());
 -      clientParams.set(HttpClientUtil.PROP_MAX_CONNECTIONS_PER_HOST, cfg.getMaxUpdateConnectionsPerHost());
 +    Http2SolrClient.Builder updateOnlyClientBuilder = new Http2SolrClient.Builder();
 +    if (cfg != null) {
 +      updateOnlyClientBuilder
 +          .connectionTimeout(cfg.getDistributedConnectionTimeout())
 +          .idleTimeout(cfg.getDistributedSocketTimeout())
 +          .maxConnectionsPerHost(cfg.getMaxUpdateConnectionsPerHost());
      }
 -    log.debug("Created default UpdateShardHandler HTTP client with params: {}", clientParams);
 -    log.debug("Created update only UpdateShardHandler HTTP client with params: {}", clientParams);
 +    updateOnlyClient = updateOnlyClientBuilder.build();
 +    updateOnlyClient.addListenerFactory(updateHttpListenerFactory);
 +    Set<String> queryParams = new HashSet<>(2);
 +    queryParams.add(DistributedUpdateProcessor.DISTRIB_FROM);
 +    queryParams.add(DistributingUpdateProcessorFactory.DISTRIB_UPDATE_PARAM);
 +    updateOnlyClient.setQueryParams(queryParams);
  
-     defaultClient = HttpClientUtil.createClient(clientParams, defaultConnectionManager, false, httpRequestExecutor);
- 
      ThreadFactory recoveryThreadFactory = new SolrjNamedThreadFactory("recoveryExecutor");
      if (cfg != null && cfg.getMaxRecoveryThreads() > 0) {
        log.debug("Creating recoveryExecutor with pool size {}", cfg.getMaxRecoveryThreads());
@@@ -236,11 -223,14 +257,13 @@@
        ExecutorUtil.shutdownAndAwaitTermination(updateExecutor);
        ExecutorUtil.shutdownAndAwaitTermination(recoveryExecutor);
      } catch (Exception e) {
-       SolrException.log(log, e);
+       throw new RuntimeException(e);
      } finally {
 -      HttpClientUtil.close(updateOnlyClient);
 +      IOUtils.closeQuietly(updateOnlyClient);
+       HttpClientUtil.close(recoveryOnlyClient);
        HttpClientUtil.close(defaultClient);
 -      updateOnlyConnectionManager.close();
        defaultConnectionManager.close();
+       recoveryOnlyConnectionManager.close();
      }
    }
  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/core/src/java/org/apache/solr/update/processor/DistributedUpdateProcessor.java
----------------------------------------------------------------------
diff --cc solr/core/src/java/org/apache/solr/update/processor/DistributedUpdateProcessor.java
index b545656,74bd86e..875a896
--- a/solr/core/src/java/org/apache/solr/update/processor/DistributedUpdateProcessor.java
+++ b/solr/core/src/java/org/apache/solr/update/processor/DistributedUpdateProcessor.java
@@@ -116,8 -118,8 +118,7 @@@ public class DistributedUpdateProcesso
    /**
     * Request forwarded to a leader of a different shard will be retried up to this amount of times by default
     */
-   static final int MAX_RETRIES_ON_FORWARD_DEAULT = 25;
- 
+   static final int MAX_RETRIES_ON_FORWARD_DEAULT = Integer.getInteger("solr.retries.on.forward",  25);
 -  
    /**
     * Requests from leader to it's followers will be retried this amount of times by default
     */
@@@ -1860,43 -1901,47 +1900,47 @@@
  
    @Override
    public void processCommit(CommitUpdateCommand cmd) throws IOException {
 -    
 +
      assert TestInjection.injectFailUpdateRequests();
 -    
 +
      updateCommand = cmd;
      List<Node> nodes = null;
-     boolean singleLeader = false;
+     Replica leaderReplica = null;
      if (zkEnabled) {
        zkCheck();
- 
-       nodes = getCollectionUrls(collection, EnumSet.of(Replica.Type.TLOG,Replica.Type.NRT));
+       try {
+         leaderReplica = zkController.getZkStateReader().getLeaderRetry(collection, cloudDesc.getShardId());
+       } catch (InterruptedException e) {
+         Thread.interrupted();
+         throw new SolrException(ErrorCode.SERVICE_UNAVAILABLE, "Exception finding leader for shard " + cloudDesc.getShardId(), e);
+       }
+       isLeader = leaderReplica.getName().equals(cloudDesc.getCoreNodeName());
+       
+       nodes = getCollectionUrls(collection, EnumSet.of(Replica.Type.TLOG,Replica.Type.NRT), true);
        if (nodes == null) {
          // This could happen if there are only pull replicas
 -        throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, 
 +        throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
              "Unable to distribute commit operation. No replicas available of types " + Replica.Type.TLOG + " or " + Replica.Type.NRT);
        }
-       if (isLeader && nodes.size() == 1 && replicaType != Replica.Type.PULL) {
-         singleLeader = true;
-       }
-     }
  
-     if (!zkEnabled || req.getParams().getBool(COMMIT_END_POINT, false) || singleLeader) {
+       nodes.removeIf((node) -> node.getNodeProps().getNodeName().equals(zkController.getNodeName())
+           && node.getNodeProps().getCoreName().equals(req.getCore().getName()));
+     }
+     
+     CompletionService<Exception> completionService = new ExecutorCompletionService<>(req.getCore().getCoreContainer().getUpdateShardHandler().getUpdateExecutor());
+     Set<Future<Exception>> pending = new HashSet<>();
+     if (!zkEnabled || (!isLeader && req.getParams().get(COMMIT_END_POINT, "").equals("replicas"))) {
        if (replicaType == Replica.Type.TLOG) {
-         try {
-           Replica leaderReplica = zkController.getZkStateReader().getLeaderRetry(
-               collection, cloudDesc.getShardId());
-           isLeader = leaderReplica.getName().equals(cloudDesc.getCoreNodeName());
-           if (isLeader) {
-             long commitVersion = vinfo.getNewClock();
-             cmd.setVersion(commitVersion);
-             doLocalCommit(cmd);
-           } else {
-             assert TestInjection.waitForInSyncWithLeader(req.getCore(),
-                 zkController, collection, cloudDesc.getShardId()): "Core " + req.getCore() + " not in sync with leader";
-           }
-         } catch (InterruptedException e) {
-           throw new SolrException(ErrorCode.SERVICE_UNAVAILABLE, "Exception finding leader for shard " + cloudDesc.getShardId(), e);
+ 
+         if (isLeader) {
+           long commitVersion = vinfo.getNewClock();
+           cmd.setVersion(commitVersion);
+           doLocalCommit(cmd);
+         } else {
+           assert TestInjection.waitForInSyncWithLeader(req.getCore(),
+               zkController, collection, cloudDesc.getShardId()) : "Core " + req.getCore() + " not in sync with leader";
          }
+ 
        } else if (replicaType == Replica.Type.PULL) {
          log.warn("Commit not supported on replicas of type " + Replica.Type.PULL);
        } else {
@@@ -1962,9 -2037,16 +2036,16 @@@
      final List<Node> urls = new ArrayList<>(slices.size());
      for (Map.Entry<String,Slice> sliceEntry : slices.entrySet()) {
        Slice replicas = slices.get(sliceEntry.getKey());
- 
+       if (onlyLeaders) {
+         Replica replica = docCollection.getLeader(replicas.getName());
+         if (replica != null) {
+           ZkCoreNodeProps nodeProps = new ZkCoreNodeProps(replica);
+           urls.add(new StdNode(nodeProps, collection, replicas.getName()));
+         }
+         continue;
+       }
        Map<String,Replica> shardMap = replicas.getReplicasMap();
 -      
 +
        for (Entry<String,Replica> entry : shardMap.entrySet()) {
          if (!types.contains(entry.getValue().getType())) {
            continue;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/core/src/test/org/apache/solr/cloud/SSLMigrationTest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithKerberosAlt.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/core/src/test/org/apache/solr/update/SolrCmdDistributorTest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrClient.java
----------------------------------------------------------------------
diff --cc solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrClient.java
index e18d761,b0322a7..63add2c
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrClient.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrClient.java
@@@ -69,19 -120,77 +69,19 @@@ public class LBHttpSolrClient extends L
  
    private final HttpClient httpClient;
    private final boolean clientIsInternal;
 +  private final ConcurrentHashMap<String, HttpSolrClient> urlToClient = new ConcurrentHashMap<>();
-   private HttpSolrClient.Builder httpSolrClientBuilder;
+   private final HttpSolrClient.Builder httpSolrClientBuilder;
 -  private final AtomicInteger counter = new AtomicInteger(-1);
  
 -  private static final SolrQuery solrQuery = new SolrQuery("*:*");
 -  private volatile ResponseParser parser;
 -  private volatile RequestWriter requestWriter;
 -
 -  private Set<String> queryParams = new HashSet<>();
    private Integer connectionTimeout;
-   private Integer soTimeout;
 -
+   private volatile Integer soTimeout;
  
 -  static {
 -    solrQuery.setRows(0);
 -    /**
 -     * Default sort (if we don't supply a sort) is by score and since
 -     * we request 0 rows any sorting and scoring is not necessary.
 -     * SolrQuery.DOCID schema-independently specifies a non-scoring sort.
 -     * <code>_docid_ asc</code> sort is efficient,
 -     * <code>_docid_ desc</code> sort is not, so choose ascending DOCID sort.
 -     */
 -    solrQuery.setSort(SolrQuery.DOCID, SolrQuery.ORDER.asc);
 -    // not a top-level request, we are interested only in the server being sent to i.e. it need not distribute our request to further servers    
 -    solrQuery.setDistrib(false);
 -  }
 -
 -  protected static class ServerWrapper {
 -
 -    final HttpSolrClient client;
 -
 -    // "standard" servers are used by default.  They normally live in the alive list
 -    // and move to the zombie list when unavailable.  When they become available again,
 -    // they move back to the alive list.
 -    boolean standard = true;
 -
 -    int failedPings = 0;
 -
 -    public ServerWrapper(HttpSolrClient client) {
 -      this.client = client;
 -    }
 -
 -    @Override
 -    public String toString() {
 -      return client.getBaseURL();
 -    }
 -
 -    public String getKey() {
 -      return client.getBaseURL();
 -    }
 -
 -    @Override
 -    public int hashCode() {
 -      return this.getKey().hashCode();
 -    }
 -
 -    @Override
 -    public boolean equals(Object obj) {
 -      if (this == obj) return true;
 -      if (!(obj instanceof ServerWrapper)) return false;
 -      return this.getKey().equals(((ServerWrapper)obj).getKey());
 -    }
 -  }
 -
 -  public static class Req {
 -    protected SolrRequest request;
 -    protected List<String> servers;
 -    protected int numDeadServersToTry;
 -    private final Integer numServersToTry;
 -
 +  /**
 +   * @deprecated use {@link LBSolrClient.Req} instead
 +   */
 +  @Deprecated
 +  public static class Req extends LBSolrClient.Req {
      public Req(SolrRequest request, List<String> servers) {
 -      this(request, servers, null);
 +      super(request, servers);
      }
  
      public Req(SolrRequest request, List<String> servers, Integer numServersToTry) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBSolrClient.java
----------------------------------------------------------------------
diff --cc solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBSolrClient.java
index f982a45,0000000..30e093e
mode 100644,000000..100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBSolrClient.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBSolrClient.java
@@@ -1,709 -1,0 +1,703 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one or more
 + * contributor license agreements.  See the NOTICE file distributed with
 + * this work for additional information regarding copyright ownership.
 + * The ASF licenses this file to You under the Apache License, Version 2.0
 + * (the "License"); you may not use this file except in compliance with
 + * the License.  You may obtain a copy of the License at
 + *
 + *     http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing, software
 + * distributed under the License is distributed on an "AS IS" BASIS,
 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 + * See the License for the specific language governing permissions and
 + * limitations under the License.
 + */
 +
 +package org.apache.solr.client.solrj.impl;
 +
 +import java.io.IOException;
 +import java.lang.ref.WeakReference;
 +import java.net.ConnectException;
 +import java.net.MalformedURLException;
 +import java.net.SocketException;
 +import java.net.SocketTimeoutException;
 +import java.net.URL;
 +import java.util.ArrayList;
 +import java.util.Arrays;
 +import java.util.HashMap;
 +import java.util.HashSet;
 +import java.util.LinkedHashMap;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.Set;
 +import java.util.concurrent.ConcurrentHashMap;
 +import java.util.concurrent.Executors;
 +import java.util.concurrent.ScheduledExecutorService;
 +import java.util.concurrent.TimeUnit;
 +import java.util.concurrent.atomic.AtomicInteger;
 +
 +import org.apache.solr.client.solrj.ResponseParser;
 +import org.apache.solr.client.solrj.SolrClient;
 +import org.apache.solr.client.solrj.SolrQuery;
 +import org.apache.solr.client.solrj.SolrRequest;
 +import org.apache.solr.client.solrj.SolrServerException;
 +import org.apache.solr.client.solrj.request.IsUpdateRequest;
 +import org.apache.solr.client.solrj.request.QueryRequest;
 +import org.apache.solr.client.solrj.request.RequestWriter;
 +import org.apache.solr.client.solrj.response.QueryResponse;
 +import org.apache.solr.common.SolrException;
 +import org.apache.solr.common.params.CommonParams;
 +import org.apache.solr.common.params.SolrParams;
++import org.apache.solr.common.util.ExecutorUtil;
 +import org.apache.solr.common.util.NamedList;
 +import org.apache.solr.common.util.SolrjNamedThreadFactory;
 +import org.slf4j.MDC;
 +
 +import static org.apache.solr.common.params.CommonParams.ADMIN_PATHS;
 +
 +public abstract class LBSolrClient extends SolrClient {
 +
 +  // defaults
 +  private static final Set<Integer> RETRY_CODES = new HashSet<>(Arrays.asList(404, 403, 503, 500));
 +  private static final int CHECK_INTERVAL = 60 * 1000; //1 minute between checks
 +  private static final int NONSTANDARD_PING_LIMIT = 5;  // number of times we'll ping dead servers not in the server list
 +
 +  // keys to the maps are currently of the form "http://localhost:8983/solr"
 +  // which should be equivalent to HttpSolrServer.getBaseURL()
 +  private final Map<String, ServerWrapper> aliveServers = new LinkedHashMap<>();
 +  // access to aliveServers should be synchronized on itself
 +
 +  private final Map<String, ServerWrapper> zombieServers = new ConcurrentHashMap<>();
 +
 +  // changes to aliveServers are reflected in this array, no need to synchronize
 +  private volatile ServerWrapper[] aliveServerList = new ServerWrapper[0];
 +
 +
-   private ScheduledExecutorService aliveCheckExecutor;
++  private volatile ScheduledExecutorService aliveCheckExecutor;
 +
 +  private int interval = CHECK_INTERVAL;
 +  private final AtomicInteger counter = new AtomicInteger(-1);
 +
 +  private static final SolrQuery solrQuery = new SolrQuery("*:*");
 +  protected volatile ResponseParser parser;
 +  protected volatile RequestWriter requestWriter;
 +
 +  protected Set<String> queryParams = new HashSet<>();
 +
 +  static {
 +    solrQuery.setRows(0);
 +    /**
 +     * Default sort (if we don't supply a sort) is by score and since
 +     * we request 0 rows any sorting and scoring is not necessary.
 +     * SolrQuery.DOCID schema-independently specifies a non-scoring sort.
 +     * <code>_docid_ asc</code> sort is efficient,
 +     * <code>_docid_ desc</code> sort is not, so choose ascending DOCID sort.
 +     */
 +    solrQuery.setSort(SolrQuery.DOCID, SolrQuery.ORDER.asc);
 +    // not a top-level request, we are interested only in the server being sent to i.e. it need not distribute our request to further servers
 +    solrQuery.setDistrib(false);
 +  }
 +
 +  protected static class ServerWrapper {
 +    final String baseUrl;
 +
 +    // "standard" servers are used by default.  They normally live in the alive list
 +    // and move to the zombie list when unavailable.  When they become available again,
 +    // they move back to the alive list.
 +    boolean standard = true;
 +
 +    int failedPings = 0;
 +
 +    ServerWrapper(String baseUrl) {
 +      this.baseUrl = baseUrl;
 +    }
 +
 +    public String getBaseUrl() {
 +      return baseUrl;
 +    }
 +
 +    @Override
 +    public String toString() {
 +      return baseUrl;
 +    }
 +
 +    @Override
 +    public int hashCode() {
 +      return baseUrl.hashCode();
 +    }
 +
 +    @Override
 +    public boolean equals(Object obj) {
 +      if (this == obj) return true;
 +      if (!(obj instanceof ServerWrapper)) return false;
 +      return baseUrl.equals(((ServerWrapper)obj).baseUrl);
 +    }
 +  }
 +
 +
 +  public static class Req {
 +    protected SolrRequest request;
 +    protected List<String> servers;
 +    protected int numDeadServersToTry;
 +    private final Integer numServersToTry;
 +
 +    public Req(SolrRequest request, List<String> servers) {
 +      this(request, servers, null);
 +    }
 +
 +    public Req(SolrRequest request, List<String> servers, Integer numServersToTry) {
 +      this.request = request;
 +      this.servers = servers;
 +      this.numDeadServersToTry = servers.size();
 +      this.numServersToTry = numServersToTry;
 +    }
 +
 +    public SolrRequest getRequest() {
 +      return request;
 +    }
 +    public List<String> getServers() {
 +      return servers;
 +    }
 +
 +    /** @return the number of dead servers to try if there are no live servers left */
 +    public int getNumDeadServersToTry() {
 +      return numDeadServersToTry;
 +    }
 +
 +    /** @param numDeadServersToTry The number of dead servers to try if there are no live servers left.
 +     * Defaults to the number of servers in this request. */
 +    public void setNumDeadServersToTry(int numDeadServersToTry) {
 +      this.numDeadServersToTry = numDeadServersToTry;
 +    }
 +
 +    public Integer getNumServersToTry() {
 +      return numServersToTry;
 +    }
 +  }
 +
 +  public static class Rsp {
 +    protected String server;
 +    protected NamedList<Object> rsp;
 +
 +    /** The response from the server */
 +    public NamedList<Object> getResponse() {
 +      return rsp;
 +    }
 +
 +    /** The server that returned the response */
 +    public String getServer() {
 +      return server;
 +    }
 +  }
 +
 +  public LBSolrClient(List<String> baseSolrUrls) {
 +    if (!baseSolrUrls.isEmpty()) {
 +      for (String s : baseSolrUrls) {
 +        ServerWrapper wrapper = createServerWrapper(s);
 +        aliveServers.put(wrapper.getBaseUrl(), wrapper);
 +      }
 +      updateAliveList();
 +    }
 +  }
 +
 +  protected void updateAliveList() {
 +    synchronized (aliveServers) {
 +      aliveServerList = aliveServers.values().toArray(new ServerWrapper[0]);
 +    }
 +  }
 +
 +  protected ServerWrapper createServerWrapper(String baseUrl) {
 +    return new ServerWrapper(baseUrl);
 +  }
 +
 +  public Set<String> getQueryParams() {
 +    return queryParams;
 +  }
 +
 +  /**
 +   * Expert Method.
 +   * @param queryParams set of param keys to only send via the query string
 +   */
 +  public void setQueryParams(Set<String> queryParams) {
 +    this.queryParams = queryParams;
 +  }
 +  public void addQueryParams(String queryOnlyParam) {
 +    this.queryParams.add(queryOnlyParam) ;
 +  }
 +
 +  public static String normalize(String server) {
 +    if (server.endsWith("/"))
 +      server = server.substring(0, server.length() - 1);
 +    return server;
 +  }
 +
 +
 +  /**
 +   * Tries to query a live server from the list provided in Req. Servers in the dead pool are skipped.
 +   * If a request fails due to an IOException, the server is moved to the dead pool for a certain period of
 +   * time, or until a test request on that server succeeds.
 +   *
 +   * Servers are queried in the exact order given (except servers currently in the dead pool are skipped).
 +   * If no live servers from the provided list remain to be tried, a number of previously skipped dead servers will be tried.
 +   * Req.getNumDeadServersToTry() controls how many dead servers will be tried.
 +   *
 +   * If no live servers are found a SolrServerException is thrown.
 +   *
 +   * @param req contains both the request as well as the list of servers to query
 +   *
 +   * @return the result of the request
 +   *
 +   * @throws IOException If there is a low-level I/O error.
 +   */
 +  public Rsp request(Req req) throws SolrServerException, IOException {
 +    Rsp rsp = new Rsp();
 +    Exception ex = null;
 +    boolean isNonRetryable = req.request instanceof IsUpdateRequest || ADMIN_PATHS.contains(req.request.getPath());
 +    List<ServerWrapper> skipped = null;
 +
 +    final Integer numServersToTry = req.getNumServersToTry();
 +    int numServersTried = 0;
 +
 +    boolean timeAllowedExceeded = false;
 +    long timeAllowedNano = getTimeAllowedInNanos(req.getRequest());
 +    long timeOutTime = System.nanoTime() + timeAllowedNano;
 +    for (String serverStr : req.getServers()) {
 +      if (timeAllowedExceeded = isTimeExceeded(timeAllowedNano, timeOutTime)) {
 +        break;
 +      }
 +
 +      serverStr = normalize(serverStr);
 +      // if the server is currently a zombie, just skip to the next one
 +      ServerWrapper wrapper = zombieServers.get(serverStr);
 +      if (wrapper != null) {
 +        // System.out.println("ZOMBIE SERVER QUERIED: " + serverStr);
 +        final int numDeadServersToTry = req.getNumDeadServersToTry();
 +        if (numDeadServersToTry > 0) {
 +          if (skipped == null) {
 +            skipped = new ArrayList<>(numDeadServersToTry);
 +            skipped.add(wrapper);
 +          }
 +          else if (skipped.size() < numDeadServersToTry) {
 +            skipped.add(wrapper);
 +          }
 +        }
 +        continue;
 +      }
 +      try {
 +        MDC.put("LBSolrClient.url", serverStr);
 +
 +        if (numServersToTry != null && numServersTried > numServersToTry.intValue()) {
 +          break;
 +        }
 +
 +        ++numServersTried;
 +        ex = doRequest(serverStr, req, rsp, isNonRetryable, false);
 +        if (ex == null) {
 +          return rsp; // SUCCESS
 +        }
 +      } finally {
 +        MDC.remove("LBSolrClient.url");
 +      }
 +    }
 +
 +    // try the servers we previously skipped
 +    if (skipped != null) {
 +      for (ServerWrapper wrapper : skipped) {
 +        if (timeAllowedExceeded = isTimeExceeded(timeAllowedNano, timeOutTime)) {
 +          break;
 +        }
 +
 +        if (numServersToTry != null && numServersTried > numServersToTry.intValue()) {
 +          break;
 +        }
 +
 +        try {
 +          MDC.put("LBSolrClient.url", wrapper.getBaseUrl());
 +          ++numServersTried;
 +          ex = doRequest(wrapper.baseUrl, req, rsp, isNonRetryable, true);
 +          if (ex == null) {
 +            return rsp; // SUCCESS
 +          }
 +        } finally {
 +          MDC.remove("LBSolrClient.url");
 +        }
 +      }
 +    }
 +
 +
 +    final String solrServerExceptionMessage;
 +    if (timeAllowedExceeded) {
 +      solrServerExceptionMessage = "Time allowed to handle this request exceeded";
 +    } else {
 +      if (numServersToTry != null && numServersTried > numServersToTry.intValue()) {
 +        solrServerExceptionMessage = "No live SolrServers available to handle this request:"
 +            + " numServersTried="+numServersTried
 +            + " numServersToTry="+numServersToTry.intValue();
 +      } else {
 +        solrServerExceptionMessage = "No live SolrServers available to handle this request";
 +      }
 +    }
 +    if (ex == null) {
 +      throw new SolrServerException(solrServerExceptionMessage);
 +    } else {
 +      throw new SolrServerException(solrServerExceptionMessage+":" + zombieServers.keySet(), ex);
 +    }
 +  }
 +
 +  /**
 +   * @return time allowed in nanos, returns -1 if no time_allowed is specified.
 +   */
 +  private long getTimeAllowedInNanos(final SolrRequest req) {
 +    SolrParams reqParams = req.getParams();
 +    return reqParams == null ? -1 :
 +        TimeUnit.NANOSECONDS.convert(reqParams.getInt(CommonParams.TIME_ALLOWED, -1), TimeUnit.MILLISECONDS);
 +  }
 +
 +  private boolean isTimeExceeded(long timeAllowedNano, long timeOutTime) {
 +    return timeAllowedNano > 0 && System.nanoTime() > timeOutTime;
 +  }
 +
 +  protected Exception doRequest(String baseUrl, Req req, Rsp rsp, boolean isNonRetryable,
 +                                boolean isZombie) throws SolrServerException, IOException {
 +    Exception ex = null;
 +    try {
 +      rsp.server = baseUrl;
 +      req.getRequest().setBasePath(baseUrl);
 +      rsp.rsp = getClient(baseUrl).request(req.getRequest(), (String) null);
 +      if (isZombie) {
 +        zombieServers.remove(baseUrl);
 +      }
 +    } catch (HttpSolrClient.RemoteExecutionException e){
 +      throw e;
 +    } catch(SolrException e) {
 +      // we retry on 404 or 403 or 503 or 500
 +      // unless it's an update - then we only retry on connect exception
 +      if (!isNonRetryable && RETRY_CODES.contains(e.code())) {
 +        ex = (!isZombie) ? addZombie(baseUrl, e) : e;
 +      } else {
 +        // Server is alive but the request was likely malformed or invalid
 +        if (isZombie) {
 +          zombieServers.remove(baseUrl);
 +        }
 +        throw e;
 +      }
 +    } catch (SocketException e) {
 +      if (!isNonRetryable || e instanceof ConnectException) {
 +        ex = (!isZombie) ? addZombie(baseUrl, e) : e;
 +      } else {
 +        throw e;
 +      }
 +    } catch (SocketTimeoutException e) {
 +      if (!isNonRetryable) {
 +        ex = (!isZombie) ? addZombie(baseUrl, e) : e;
 +      } else {
 +        throw e;
 +      }
 +    } catch (SolrServerException e) {
 +      Throwable rootCause = e.getRootCause();
 +      if (!isNonRetryable && rootCause instanceof IOException) {
 +        ex = (!isZombie) ? addZombie(baseUrl, e) : e;
 +      } else if (isNonRetryable && rootCause instanceof ConnectException) {
 +        ex = (!isZombie) ? addZombie(baseUrl, e) : e;
 +      } else {
 +        throw e;
 +      }
 +    } catch (Exception e) {
 +      throw new SolrServerException(e);
 +    }
 +
 +    return ex;
 +  }
 +
 +  protected abstract SolrClient getClient(String baseUrl);
 +
 +  private Exception addZombie(String serverStr, Exception e) {
 +    ServerWrapper wrapper = createServerWrapper(serverStr);
 +    wrapper.standard = false;
 +    zombieServers.put(serverStr, wrapper);
 +    startAliveCheckExecutor();
 +    return e;
 +  }
 +
 +  /**
 +   * LBHttpSolrServer keeps pinging the dead servers at fixed interval to find if it is alive. Use this to set that
 +   * interval
 +   *
 +   * @param interval time in milliseconds
 +   */
 +  public void setAliveCheckInterval(int interval) {
 +    if (interval <= 0) {
 +      throw new IllegalArgumentException("Alive check interval must be " +
 +          "positive, specified value = " + interval);
 +    }
 +    this.interval = interval;
 +  }
 +
 +  private void startAliveCheckExecutor() {
 +    // double-checked locking, but it's OK because we don't *do* anything with aliveCheckExecutor
 +    // if it's not null.
 +    if (aliveCheckExecutor == null) {
 +      synchronized (this) {
 +        if (aliveCheckExecutor == null) {
 +          aliveCheckExecutor = Executors.newSingleThreadScheduledExecutor(
 +              new SolrjNamedThreadFactory("aliveCheckExecutor"));
 +          aliveCheckExecutor.scheduleAtFixedRate(
 +              getAliveCheckRunner(new WeakReference<>(this)),
 +              this.interval, this.interval, TimeUnit.MILLISECONDS);
 +        }
 +      }
 +    }
 +  }
 +
 +  private static Runnable getAliveCheckRunner(final WeakReference<LBSolrClient> lbRef) {
 +    return () -> {
 +      LBSolrClient lb = lbRef.get();
 +      if (lb != null && lb.zombieServers != null) {
 +        for (Object zombieServer : lb.zombieServers.values()) {
 +          lb.checkAZombieServer((ServerWrapper)zombieServer);
 +        }
 +      }
 +    };
 +  }
 +
 +  public ResponseParser getParser() {
 +    return parser;
 +  }
 +
 +  /**
 +   * Changes the {@link ResponseParser} that will be used for the internal
 +   * SolrServer objects.
 +   *
 +   * @param parser Default Response Parser chosen to parse the response if the parser
 +   *               were not specified as part of the request.
 +   * @see org.apache.solr.client.solrj.SolrRequest#getResponseParser()
 +   */
 +  public void setParser(ResponseParser parser) {
 +    this.parser = parser;
 +  }
 +
 +  /**
 +   * Changes the {@link RequestWriter} that will be used for the internal
 +   * SolrServer objects.
 +   *
 +   * @param requestWriter Default RequestWriter, used to encode requests sent to the server.
 +   */
 +  public void setRequestWriter(RequestWriter requestWriter) {
 +    this.requestWriter = requestWriter;
 +  }
 +
 +  public RequestWriter getRequestWriter() {
 +    return requestWriter;
 +  }
 +
-   @Override
-   protected void finalize() throws Throwable {
-     try {
-       if(this.aliveCheckExecutor!=null)
-         this.aliveCheckExecutor.shutdownNow();
-     } finally {
-       super.finalize();
-     }
-   }
- 
 +  private void checkAZombieServer(ServerWrapper zombieServer) {
 +    try {
 +      QueryRequest queryRequest = new QueryRequest(solrQuery);
 +      queryRequest.setBasePath(zombieServer.baseUrl);
 +      QueryResponse resp = queryRequest.process(getClient(zombieServer.getBaseUrl()));
 +      if (resp.getStatus() == 0) {
 +        // server has come back up.
 +        // make sure to remove from zombies before adding to alive to avoid a race condition
 +        // where another thread could mark it down, move it back to zombie, and then we delete
 +        // from zombie and lose it forever.
 +        ServerWrapper wrapper = zombieServers.remove(zombieServer.getBaseUrl());
 +        if (wrapper != null) {
 +          wrapper.failedPings = 0;
 +          if (wrapper.standard) {
 +            addToAlive(wrapper);
 +          }
 +        } else {
 +          // something else already moved the server from zombie to alive
 +        }
 +      }
 +    } catch (Exception e) {
 +      //Expected. The server is still down.
 +      zombieServer.failedPings++;
 +
 +      // If the server doesn't belong in the standard set belonging to this load balancer
 +      // then simply drop it after a certain number of failed pings.
 +      if (!zombieServer.standard && zombieServer.failedPings >= NONSTANDARD_PING_LIMIT) {
 +        zombieServers.remove(zombieServer.getBaseUrl());
 +      }
 +    }
 +  }
 +
 +  private ServerWrapper removeFromAlive(String key) {
 +    synchronized (aliveServers) {
 +      ServerWrapper wrapper = aliveServers.remove(key);
 +      if (wrapper != null)
 +        updateAliveList();
 +      return wrapper;
 +    }
 +  }
 +
 +
 +  private void addToAlive(ServerWrapper wrapper) {
 +    synchronized (aliveServers) {
 +      ServerWrapper prev = aliveServers.put(wrapper.getBaseUrl(), wrapper);
 +      // TODO: warn if there was a previous entry?
 +      updateAliveList();
 +    }
 +  }
 +
 +  public void addSolrServer(String server) throws MalformedURLException {
 +    addToAlive(createServerWrapper(server));
 +  }
 +
 +  public String removeSolrServer(String server) {
 +    try {
 +      server = new URL(server).toExternalForm();
 +    } catch (MalformedURLException e) {
 +      throw new RuntimeException(e);
 +    }
 +    if (server.endsWith("/")) {
 +      server = server.substring(0, server.length() - 1);
 +    }
 +
 +    // there is a small race condition here - if the server is in the process of being moved between
 +    // lists, we could fail to remove it.
 +    removeFromAlive(server);
 +    zombieServers.remove(server);
 +    return null;
 +  }
 +
 +  /**
 +   * Tries to query a live server. A SolrServerException is thrown if all servers are dead.
 +   * If the request failed due to IOException then the live server is moved to dead pool and the request is
 +   * retried on another live server.  After live servers are exhausted, any servers previously marked as dead
 +   * will be tried before failing the request.
 +   *
 +   * @param request the SolrRequest.
 +   *
 +   * @return response
 +   *
 +   * @throws IOException If there is a low-level I/O error.
 +   */
 +  @Override
 +  public NamedList<Object> request(final SolrRequest request, String collection)
 +      throws SolrServerException, IOException {
 +    return request(request, collection, null);
 +  }
 +
 +  public NamedList<Object> request(final SolrRequest request, String collection,
 +                                   final Integer numServersToTry) throws SolrServerException, IOException {
 +    Exception ex = null;
 +    ServerWrapper[] serverList = aliveServerList;
 +
 +    final int maxTries = (numServersToTry == null ? serverList.length : numServersToTry.intValue());
 +    int numServersTried = 0;
 +    Map<String,ServerWrapper> justFailed = null;
 +
 +    boolean timeAllowedExceeded = false;
 +    long timeAllowedNano = getTimeAllowedInNanos(request);
 +    long timeOutTime = System.nanoTime() + timeAllowedNano;
 +    for (int attempts=0; attempts<maxTries; attempts++) {
 +      if (timeAllowedExceeded = isTimeExceeded(timeAllowedNano, timeOutTime)) {
 +        break;
 +      }
 +
 +      ServerWrapper wrapper = pickServer(serverList, request);
 +      try {
 +        ++numServersTried;
 +        request.setBasePath(wrapper.baseUrl);
 +        return getClient(wrapper.getBaseUrl()).request(request, collection);
 +      } catch (SolrException e) {
 +        // Server is alive but the request was malformed or invalid
 +        throw e;
 +      } catch (SolrServerException e) {
 +        if (e.getRootCause() instanceof IOException) {
 +          ex = e;
 +          moveAliveToDead(wrapper);
 +          if (justFailed == null) justFailed = new HashMap<>();
 +          justFailed.put(wrapper.getBaseUrl(), wrapper);
 +        } else {
 +          throw e;
 +        }
 +      } catch (Exception e) {
 +        throw new SolrServerException(e);
 +      }
 +    }
 +
 +    // try other standard servers that we didn't try just now
 +    for (ServerWrapper wrapper : zombieServers.values()) {
 +      if (timeAllowedExceeded = isTimeExceeded(timeAllowedNano, timeOutTime)) {
 +        break;
 +      }
 +
 +      if (wrapper.standard==false || justFailed!=null && justFailed.containsKey(wrapper.getBaseUrl())) continue;
 +      try {
 +        ++numServersTried;
 +        request.setBasePath(wrapper.baseUrl);
 +        NamedList<Object> rsp = getClient(wrapper.baseUrl).request(request, collection);
 +        // remove from zombie list *before* adding to alive to avoid a race that could lose a server
 +        zombieServers.remove(wrapper.getBaseUrl());
 +        addToAlive(wrapper);
 +        return rsp;
 +      } catch (SolrException e) {
 +        // Server is alive but the request was malformed or invalid
 +        throw e;
 +      } catch (SolrServerException e) {
 +        if (e.getRootCause() instanceof IOException) {
 +          ex = e;
 +          // still dead
 +        } else {
 +          throw e;
 +        }
 +      } catch (Exception e) {
 +        throw new SolrServerException(e);
 +      }
 +    }
 +
 +
 +    final String solrServerExceptionMessage;
 +    if (timeAllowedExceeded) {
 +      solrServerExceptionMessage = "Time allowed to handle this request exceeded";
 +    } else {
 +      if (numServersToTry != null && numServersTried > numServersToTry.intValue()) {
 +        solrServerExceptionMessage = "No live SolrServers available to handle this request:"
 +            + " numServersTried="+numServersTried
 +            + " numServersToTry="+numServersToTry.intValue();
 +      } else {
 +        solrServerExceptionMessage = "No live SolrServers available to handle this request";
 +      }
 +    }
 +    if (ex == null) {
 +      throw new SolrServerException(solrServerExceptionMessage);
 +    } else {
 +      throw new SolrServerException(solrServerExceptionMessage, ex);
 +    }
 +  }
 +
 +  /**
 +   * Pick a server from list to execute request.
 +   * By default servers are picked in round-robin manner,
 +   * custom classes can override this method for more advance logic
 +   * @param aliveServerList list of currently alive servers
 +   * @param request the request will be sent to the picked server
 +   * @return the picked server
 +   */
 +  protected ServerWrapper pickServer(ServerWrapper[] aliveServerList, SolrRequest request) {
 +    int count = counter.incrementAndGet() & Integer.MAX_VALUE;
 +    return aliveServerList[count % aliveServerList.length];
 +  }
 +
 +  private void moveAliveToDead(ServerWrapper wrapper) {
 +    wrapper = removeFromAlive(wrapper.getBaseUrl());
 +    if (wrapper == null)
 +      return;  // another thread already detected the failure and removed it
 +    zombieServers.put(wrapper.getBaseUrl(), wrapper);
 +    startAliveCheckExecutor();
 +  }
 +
 +  @Override
 +  public void close() {
-     if (aliveCheckExecutor != null) {
-       aliveCheckExecutor.shutdownNow();
++    synchronized (this) {
++      if (aliveCheckExecutor != null) {
++        aliveCheckExecutor.shutdownNow();
++        ExecutorUtil.shutdownAndAwaitTermination(aliveCheckExecutor);
++      }
 +    }
 +  }
 +}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/solrj/src/java/org/apache/solr/client/solrj/impl/SolrClientBuilder.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/solrj/src/test/org/apache/solr/client/solrj/impl/BasicHttpSolrClientTest.java
----------------------------------------------------------------------
diff --cc solr/solrj/src/test/org/apache/solr/client/solrj/impl/BasicHttpSolrClientTest.java
index 83b228d,dafba26..5b5566d
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/BasicHttpSolrClientTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/BasicHttpSolrClientTest.java
@@@ -200,9 -200,9 +200,9 @@@ public class BasicHttpSolrClientTest ex
          .withServlet(new ServletHolder(RedirectServlet.class), "/redirect/*")
          .withServlet(new ServletHolder(SlowServlet.class), "/slow/*")
          .withServlet(new ServletHolder(DebugServlet.class), "/debug/*")
 -        .withSSLConfig(sslConfig)
 +        .withSSLConfig(sslConfig.buildServerSSLConfig())
          .build();
-     createJetty(legacyExampleCollection1SolrHome(), jettyConfig);
+     createAndStartJetty(legacyExampleCollection1SolrHome(), jettyConfig);
    }
    
    @Test

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientBadInputTest.java
----------------------------------------------------------------------
diff --cc solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientBadInputTest.java
index ac755eb,62a60b0..dd17089
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientBadInputTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientBadInputTest.java
@@@ -41,9 -41,9 +41,9 @@@ public class ConcurrentUpdateSolrClient
    @BeforeClass
    public static void beforeTest() throws Exception {
      JettyConfig jettyConfig = JettyConfig.builder()
 -        .withSSLConfig(sslConfig)
 +        .withSSLConfig(sslConfig.buildServerSSLConfig())
          .build();
-     createJetty(legacyExampleCollection1SolrHome(), jettyConfig);
+     createAndStartJetty(legacyExampleCollection1SolrHome(), jettyConfig);
    }
  
    @Test

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientTest.java
----------------------------------------------------------------------
diff --cc solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientTest.java
index 2deaa27,ad6f037..1a200f9
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientTest.java
@@@ -129,9 -128,9 +129,9 @@@ public class ConcurrentUpdateSolrClient
    public static void beforeTest() throws Exception {
      JettyConfig jettyConfig = JettyConfig.builder()
          .withServlet(new ServletHolder(TestServlet.class), "/cuss/*")
 -        .withSSLConfig(sslConfig)
 +        .withSSLConfig(sslConfig.buildServerSSLConfig())
          .build();
-     createJetty(legacyExampleCollection1SolrHome(), jettyConfig);
+     createAndStartJetty(legacyExampleCollection1SolrHome(), jettyConfig);
    }
    
    @Test

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpSolrClientBadInputTest.java
----------------------------------------------------------------------
diff --cc solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpSolrClientBadInputTest.java
index e2dd6af,6157c32..000141a
--- 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
@@@ -40,9 -40,9 +40,9 @@@ public class HttpSolrClientBadInputTes
    @BeforeClass
    public static void beforeTest() throws Exception {
      JettyConfig jettyConfig = JettyConfig.builder()
 -        .withSSLConfig(sslConfig)
 +        .withSSLConfig(sslConfig.buildServerSSLConfig())
          .build();
-     createJetty(legacyExampleCollection1SolrHome(), jettyConfig);
+     createAndStartJetty(legacyExampleCollection1SolrHome(), jettyConfig);
    }
  
    private void assertExceptionThrownWithMessageContaining(Class expectedType, List<String> expectedStrings, ThrowingRunnable runnable) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/solrj/src/test/org/apache/solr/client/solrj/impl/LBHttpSolrClientBadInputTest.java
----------------------------------------------------------------------
diff --cc solr/solrj/src/test/org/apache/solr/client/solrj/impl/LBHttpSolrClientBadInputTest.java
index 76ec934,dd7b14e..ea67498
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/LBHttpSolrClientBadInputTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/LBHttpSolrClientBadInputTest.java
@@@ -39,9 -39,9 +39,9 @@@ public class LBHttpSolrClientBadInputTe
    @BeforeClass
    public static void beforeTest() throws Exception {
      JettyConfig jettyConfig = JettyConfig.builder()
 -        .withSSLConfig(sslConfig)
 +        .withSSLConfig(sslConfig.buildServerSSLConfig())
          .build();
-     createJetty(legacyExampleCollection1SolrHome(), jettyConfig);
+     createAndStartJetty(legacyExampleCollection1SolrHome(), jettyConfig);
    }
  
    @Test

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6c6fd559/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
----------------------------------------------------------------------
diff --cc solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
index 705c72e,4728aa3..5e4cab2
--- a/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
+++ b/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
@@@ -336,13 -358,10 +357,14 @@@ public abstract class BaseDistributedSe
        seedSolrHome(jettyHomeFile);
        seedCoreRootDirWithDefaultTestCore(jettyHome.resolve("cores"));
        JettySolrRunner j = createJetty(jettyHomeFile, null, null, getSolrConfigFile(), getSchemaFile());
+       j.start();
        jettys.add(j);
        clients.add(createNewSolrClient(j.getLocalPort()));
 -      String shardStr = buildUrl(j.getLocalPort()) + "/" + DEFAULT_TEST_CORENAME;
 +      String shardStr = buildUrl(j.getLocalPort());
 +
 +      if (shardStr.endsWith("/")) shardStr += DEFAULT_TEST_CORENAME;
 +      else shardStr += "/" + DEFAULT_TEST_CORENAME;
 +
        shardsArr[i] = shardStr;
        sb.append(shardStr);
      }
@@@ -421,11 -468,9 +471,9 @@@
          .setContext(context)
          .withFilters(getExtraRequestFilters())
          .withServlets(getExtraServlets())
 -        .withSSLConfig(sslConfig)
 +        .withSSLConfig(sslConfig.buildServerSSLConfig())
          .build());
  
-     jetty.start();
-     
      return jetty;
    }