diff --git a/changelog/unreleased/solr-18081-shard-request-tracker-replica-name.yml b/changelog/unreleased/solr-18081-shard-request-tracker-replica-name.yml new file mode 100644 index 000000000000..b5b390ccce6d --- /dev/null +++ b/changelog/unreleased/solr-18081-shard-request-tracker-replica-name.yml @@ -0,0 +1,9 @@ +# See https://github.com/apache/solr/blob/main/dev-docs/changelog.adoc +title: ShardRequestTracker now indexes Admin API results by node and replica rather than just node. This fixes situations where multiple sub-requests are sent to a single node. +type: fixed # added, changed, fixed, deprecated, removed, dependency_update, security, other +authors: + - name: Houston Putman + nick: HoustonPutman +links: + - name: SOLR-18081 + url: https://issues.apache.org/jira/browse/SOLR-18081 diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/AddReplicaCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/AddReplicaCmd.java index a13bce718d8a..91392c111466 100644 --- a/solr/core/src/java/org/apache/solr/cloud/api/collections/AddReplicaCmd.java +++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/AddReplicaCmd.java @@ -175,7 +175,8 @@ List addReplica( ModifiableSolrParams params = getReplicaParams( message, collectionName, coll, skipCreateReplicaInClusterState, createReplica); - shardRequestTracker.sendShardRequest(createReplica.node, params, shardHandler); + shardRequestTracker.sendShardRequest( + createReplica.node, createReplica.coreNodeName, params, shardHandler); } Runnable runnable = diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/BackupCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/BackupCmd.java index 60ec1cb7e6c8..04b2a1417bb7 100644 --- a/solr/core/src/java/org/apache/solr/cloud/api/collections/BackupCmd.java +++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/BackupCmd.java @@ -350,7 +350,7 @@ private void incrementalCopyIndexFiles( slice.getName(), backupManager.getBackupId().getId()); params.set(CoreAdminParams.SHARD_BACKUP_ID, shardBackupId.getIdAsString()); - shardRequestTracker.sendShardRequest(replica.getNodeName(), params, shardHandler); + shardRequestTracker.sendShardRequest(replica, params, shardHandler); log.debug("Sent backup request to core={} for backupName={}", coreName, backupName); } log.debug("Sent backup requests to all shard leaders for backupName={}", backupName); @@ -532,7 +532,7 @@ private void copyIndexFiles( params.set(CoreAdminParams.COMMIT_NAME, snapshotMeta.get().getName()); } - shardRequestTracker.sendShardRequest(replica.getNodeName(), params, shardHandler); + shardRequestTracker.sendShardRequest(replica, params, shardHandler); log.debug("Sent backup request to core={} for backupName={}", coreName, backupName); } log.debug("Sent backup requests to all shard leaders for backupName={}", backupName); diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/CollApiCmds.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/CollApiCmds.java index 454b53638419..3840683d6eff 100644 --- a/solr/core/src/java/org/apache/solr/cloud/api/collections/CollApiCmds.java +++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/CollApiCmds.java @@ -314,7 +314,8 @@ public void call(AdminCmdContext clusterState, ZkNodeProps message, NamedList collectionCmd( } static void processResponse( - NamedList results, ShardResponse srsp, Set okayExceptions) { + NamedList results, ShardResponse srsp, Set okayExceptions, String asyncId) { Throwable e = srsp.getException(); String nodeName = srsp.getNodeName(); + // Use core or coreNodeName if given as a param, otherwise use nodeName + String coreNodeName = srsp.getShardRequest().coreNodeName; SolrResponse solrResponse = srsp.getSolrResponse(); String shard = srsp.getShard(); - processResponse(results, e, nodeName, solrResponse, shard, okayExceptions); + processResponse( + results, e, nodeName, coreNodeName, solrResponse, shard, okayExceptions, asyncId); } static void processResponse( NamedList results, Throwable e, String nodeName, + String coreNodeName, SolrResponse solrResponse, String shard, - Set okayExceptions) { + Set okayExceptions, + String asyncId) { String rootThrowable = null; if (e instanceof RemoteSolrException remoteSolrException) { rootThrowable = remoteSolrException.getRootThrowable(); @@ -442,9 +460,10 @@ static void processResponse( if (e != null && (rootThrowable == null || !okayExceptions.contains(rootThrowable))) { log.error("Error from shard: {}", shard, e); - addFailure(results, nodeName, e.getClass().getName() + ":" + e.getMessage()); - } else { - addSuccess(results, nodeName, solrResponse.getResponse()); + addFailure(results, nodeName, coreNodeName, e); + } else if (asyncId == null) { + // Do not add a success for async requests, that will be done when the async result is found + addSuccess(results, nodeName, coreNodeName, solrResponse.getResponse()); } } @@ -468,24 +487,38 @@ public static void addExceptionToNamedList( results.add("exception", nl); } - private static void addFailure(NamedList results, String key, Object value) { + public static String requestKey(Replica replica) { + return requestKey(replica.getNodeName(), replica.getName()); + } + + public static String requestKey(String nodeName, String coreNodeName) { + if (coreNodeName == null) { + return nodeName; + } else { + return nodeName + "/" + coreNodeName; + } + } + + private static void addFailure( + NamedList results, String nodeName, String coreNodeName, Object value) { @SuppressWarnings("unchecked") SimpleOrderedMap failure = (SimpleOrderedMap) results.get("failure"); if (failure == null) { failure = new SimpleOrderedMap<>(); results.add("failure", failure); } - failure.add(key, value); + failure.add(requestKey(nodeName, coreNodeName), value); } - private static void addSuccess(NamedList results, String key, Object value) { + private static void addSuccess( + NamedList results, String nodeName, String coreNodeName, Object value) { @SuppressWarnings("unchecked") SimpleOrderedMap success = (SimpleOrderedMap) results.get("success"); if (success == null) { success = new SimpleOrderedMap<>(); results.add("success", success); } - success.add(key, value); + success.add(requestKey(nodeName, coreNodeName), value); } private static NamedList waitForCoreAdminAsyncCallToComplete( @@ -493,6 +526,7 @@ private static NamedList waitForCoreAdminAsyncCallToComplete( String adminPath, ZkStateReader zkStateReader, String nodeName, + String coreNodeName, String requestId) { ShardHandler shardHandler = shardHandlerFactory.getShardHandler(); ModifiableSolrParams params = new ModifiableSolrParams(); @@ -508,6 +542,8 @@ private static NamedList waitForCoreAdminAsyncCallToComplete( sreq.shards = new String[] {replica}; sreq.actualShards = sreq.shards; sreq.params = params; + sreq.nodeName = nodeName; + sreq.coreNodeName = coreNodeName; shardHandler.submit(sreq, replica, sreq.params); @@ -515,8 +551,6 @@ private static NamedList waitForCoreAdminAsyncCallToComplete( do { srsp = shardHandler.takeCompletedOrError(); if (srsp != null) { - NamedList results = new NamedList<>(); - processResponse(results, srsp, Collections.emptySet()); if (srsp.getSolrResponse().getResponse() == null) { NamedList response = new NamedList<>(); response.add("STATUS", "failed"); @@ -524,6 +558,16 @@ private static NamedList waitForCoreAdminAsyncCallToComplete( } String r = (String) srsp.getSolrResponse().getResponse().get("STATUS"); + if (r == null) { + // For Collections API Calls + r = (String) srsp.getSolrResponse().getResponse()._get("status/state"); + } + if (r == null) { + throw new SolrException( + SolrException.ErrorCode.SERVER_ERROR, + "Could not find status of async command in response: " + + srsp.getSolrResponse().getResponse().toString()); + } if (r.equals("running")) { log.debug("The task is still RUNNING, continuing to wait."); try { @@ -533,6 +577,15 @@ private static NamedList waitForCoreAdminAsyncCallToComplete( } continue; + } else if (r.equals("submitted")) { + log.debug("The task is still SUBMITTED, continuing to wait."); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + continue; + } else if (r.equals("completed")) { log.debug("The task is COMPLETED, returning"); return srsp.getSolrResponse().getResponse(); @@ -571,21 +624,28 @@ private static NamedList waitForCoreAdminAsyncCallToComplete( public static ShardRequestTracker syncRequestTracker( AdminCmdContext adminCmdContext, CollectionCommandContext ccc) { - return requestTracker(null, ccc); + return syncRequestTracker(adminCmdContext, ccc.getAdminPath(), ccc); + } + + public static ShardRequestTracker syncRequestTracker( + AdminCmdContext adminCmdContext, String adminPath, CollectionCommandContext ccc) { + return requestTracker(null, adminPath, ccc); } public static ShardRequestTracker asyncRequestTracker( AdminCmdContext adminCmdContext, CollectionCommandContext ccc) { - return requestTracker(adminCmdContext.getAsyncId(), ccc); + return asyncRequestTracker(adminCmdContext, ccc.getAdminPath(), ccc); + } + + public static ShardRequestTracker asyncRequestTracker( + AdminCmdContext adminCmdContext, String adminPath, CollectionCommandContext ccc) { + return requestTracker(adminCmdContext.getAsyncId(), adminPath, ccc); } protected static ShardRequestTracker requestTracker( - String asyncId, CollectionCommandContext ccc) { + String asyncId, String adminPath, CollectionCommandContext ccc) { return new ShardRequestTracker( - asyncId, - ccc.getAdminPath(), - ccc.getZkStateReader(), - ccc.newShardHandler().getShardHandlerFactory()); + asyncId, adminPath, ccc.getZkStateReader(), ccc.newShardHandler().getShardHandlerFactory()); } public static class ShardRequestTracker { @@ -593,7 +653,7 @@ public static class ShardRequestTracker { private final String adminPath; private final ZkStateReader zkStateReader; private final ShardHandlerFactory shardHandlerFactory; - private final NamedList shardAsyncIdByNode = new NamedList(); + private final List shardAsyncCmds = new ArrayList<>(); public ShardRequestTracker( String asyncId, @@ -621,14 +681,13 @@ public List sliceCmd( for (Replica replica : slice.getReplicas()) { if ((stateMatcher == null || Replica.State.getState(replica.getStr(ZkStateReader.STATE_PROP)) == stateMatcher)) { - if (clusterState.liveNodesContain(replica.getStr(ZkStateReader.NODE_NAME_PROP))) { + if (clusterState.liveNodesContain(replica.getNodeName())) { // For thread safety, only simple clone the ModifiableSolrParams ModifiableSolrParams cloneParams = new ModifiableSolrParams(); cloneParams.add(params); - cloneParams.set(CoreAdminParams.CORE, replica.getStr(ZkStateReader.CORE_NAME_PROP)); + cloneParams.set(CoreAdminParams.CORE, replica.getCoreName()); - sendShardRequest( - replica.getStr(ZkStateReader.NODE_NAME_PROP), cloneParams, shardHandler); + sendShardRequest(replica.getNodeName(), replica.getName(), cloneParams, shardHandler); } else { notLiveReplicas.add(replica); } @@ -638,12 +697,22 @@ public List sliceCmd( } public void sendShardRequest( - String nodeName, ModifiableSolrParams params, ShardHandler shardHandler) { - sendShardRequest(nodeName, params, shardHandler, adminPath, zkStateReader); + Replica replica, ModifiableSolrParams params, ShardHandler shardHandler) { + sendShardRequest( + replica.getNodeName(), replica.getName(), params, shardHandler, adminPath, zkStateReader); + } + + public void sendShardRequest( + String nodeName, + String coreNodeName, + ModifiableSolrParams params, + ShardHandler shardHandler) { + sendShardRequest(nodeName, coreNodeName, params, shardHandler, adminPath, zkStateReader); } public void sendShardRequest( String nodeName, + String coreNodeName, ModifiableSolrParams params, ShardHandler shardHandler, String adminPath, @@ -652,7 +721,7 @@ public void sendShardRequest( String coreAdminAsyncId = asyncId + Math.abs(System.nanoTime()); params.set(ASYNC, coreAdminAsyncId); // Track async requests - shardAsyncIdByNode.add(nodeName, coreAdminAsyncId); + shardAsyncCmds.add(AsyncCmdInfo.from(nodeName, coreNodeName, coreAdminAsyncId)); } ShardRequest sreq = new ShardRequest(); @@ -662,6 +731,7 @@ public void sendShardRequest( sreq.shards = new String[] {replica}; sreq.actualShards = sreq.shards; sreq.nodeName = nodeName; + sreq.coreNodeName = coreNodeName; sreq.params = params; shardHandler.submit(sreq, replica, sreq.params); @@ -684,9 +754,12 @@ void processResponses( // Processes all shard responses ShardResponse srsp; do { - srsp = shardHandler.takeCompletedOrError(); + srsp = + abortOnError + ? shardHandler.takeCompletedOrError() + : shardHandler.takeCompletedIncludingErrors(); if (srsp != null) { - processResponse(results, srsp, okayExceptions); + processResponse(results, srsp, okayExceptions, asyncId); Throwable exception = srsp.getException(); if (abortOnError && exception != null) { // drain pending requests @@ -702,25 +775,53 @@ void processResponses( if (asyncId != null) { // TODO: Shouldn't we abort with msgOnError exception when failure? waitForAsyncCallsToComplete(results); - shardAsyncIdByNode.clear(); + shardAsyncCmds.clear(); } } private void waitForAsyncCallsToComplete(NamedList results) { - for (Map.Entry nodeToAsync : shardAsyncIdByNode) { - final String node = nodeToAsync.getKey(); - final String shardAsyncId = nodeToAsync.getValue(); - log.debug("I am Waiting for :{}/{}", node, shardAsyncId); + for (AsyncCmdInfo asyncCmdInfo : shardAsyncCmds) { + Object failure = + results._get("failure/" + requestKey(asyncCmdInfo.nodeName, asyncCmdInfo.coreNodeName)); + // Do not wait for Async calls that have already failed + if (failure != null) { + return; + } + final String node = asyncCmdInfo.nodeName; + final String coreNodeName = asyncCmdInfo.coreNodeName; + final String shardAsyncId = asyncCmdInfo.asyncId; + log.info("I am Waiting for: {}/{}/{}", node, coreNodeName, shardAsyncId); NamedList reqResult = waitForCoreAdminAsyncCallToComplete( - shardHandlerFactory, adminPath, zkStateReader, node, shardAsyncId); - if ("failed".equalsIgnoreCase(((String) reqResult.get("STATUS")))) { - log.error("Error from shard {}: {}", node, reqResult); - addFailure(results, node, reqResult); + shardHandlerFactory, adminPath, zkStateReader, node, coreNodeName, shardAsyncId); + String status = (String) reqResult.get("STATUS"); + if (status == null) { + // For Collections API Calls + status = (String) reqResult._get("status/state"); + } + if ("failed".equalsIgnoreCase(status)) { + log.error("Error from shard {}/{}: {}", node, coreNodeName, reqResult); + addFailure(results, node, coreNodeName, reqResult); } else { - addSuccess(results, node, reqResult); + addSuccess(results, node, coreNodeName, reqResult); } } } } + + private static class AsyncCmdInfo { + protected final String nodeName; + protected final String coreNodeName; + protected final String asyncId; + + public AsyncCmdInfo(String nodeName, String coreNodeName, String asyncId) { + this.nodeName = nodeName; + this.coreNodeName = coreNodeName; + this.asyncId = asyncId; + } + + public static AsyncCmdInfo from(String nodeName, String coreNodeName, String asyncId) { + return new AsyncCmdInfo(nodeName, coreNodeName, asyncId); + } + } } diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateCollectionCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateCollectionCmd.java index f9aab00769dd..ff2d92378f30 100644 --- a/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateCollectionCmd.java +++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateCollectionCmd.java @@ -411,7 +411,8 @@ public void call(AdminCmdContext adminCmdContext, ZkNodeProps message, NamedList ModifiableSolrParams params = e.getValue(); String nodeName = nodeNames.get(e.getKey()); params.set(CoreAdminParams.CORE_NODE_NAME, replicas.get(e.getKey()).getName()); - shardRequestTracker.sendShardRequest(nodeName, params, shardHandler); + shardRequestTracker.sendShardRequest( + nodeName, replicas.get(e.getKey()).getCoreName(), params, shardHandler); } shardRequestTracker.processResponses( diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateSnapshotCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateSnapshotCmd.java index 97e24fc82795..db4918f77594 100644 --- a/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateSnapshotCmd.java +++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateSnapshotCmd.java @@ -119,7 +119,7 @@ public void call(AdminCmdContext adminCmdContext, ZkNodeProps message, NamedList params.set(CORE_NAME_PROP, coreName); params.set(CoreAdminParams.COMMIT_NAME, commitName); - shardRequestTracker.sendShardRequest(replica.getNodeName(), params, shardHandler); + shardRequestTracker.sendShardRequest(replica, params, shardHandler); log.debug( "Sent createsnapshot request to core={} with commitName={}", coreName, commitName); diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/DeleteReplicaCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/DeleteReplicaCmd.java index 5246401db6e9..a2ad2cdd5b54 100644 --- a/solr/core/src/java/org/apache/solr/cloud/api/collections/DeleteReplicaCmd.java +++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/DeleteReplicaCmd.java @@ -313,7 +313,7 @@ void deleteCore( final ShardRequestTracker shardRequestTracker = CollectionHandlingUtils.asyncRequestTracker(adminCmdContext, ccc); if (isLive) { - shardRequestTracker.sendShardRequest(replica.getNodeName(), params, shardHandler); + shardRequestTracker.sendShardRequest(replica, params, shardHandler); } Callable callable = diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/DeleteSnapshotCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/DeleteSnapshotCmd.java index ffb93c48fc2e..af321c7b6707 100644 --- a/solr/core/src/java/org/apache/solr/cloud/api/collections/DeleteSnapshotCmd.java +++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/DeleteSnapshotCmd.java @@ -123,7 +123,7 @@ public void call(AdminCmdContext adminCmdContext, ZkNodeProps message, NamedList log.info( "Sending deletesnapshot request to core={} with commitName={}", coreName, commitName); - shardRequestTracker.sendShardRequest(replica.getNodeName(), params, shardHandler); + shardRequestTracker.sendShardRequest(replica, params, shardHandler); } } } diff --git 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 index ba56c8ab9dda..2869f9866b6e 100644 --- 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 @@ -232,7 +232,7 @@ private void migrateKey( { final ShardRequestTracker shardRequestTracker = CollectionHandlingUtils.asyncRequestTracker(adminCmdContext, ccc); - shardRequestTracker.sendShardRequest(targetLeader.getNodeName(), params, shardHandler); + shardRequestTracker.sendShardRequest(targetLeader, params, shardHandler); shardRequestTracker.processResponses( results, shardHandler, true, "MIGRATE failed to request node to buffer updates"); @@ -358,7 +358,7 @@ private void migrateKey( CollectionHandlingUtils.syncRequestTracker(adminCmdContext, ccc); // we don't want this to happen asynchronously syncRequestTracker.sendShardRequest( - tempSourceLeader.getNodeName(), new ModifiableSolrParams(cmd.getParams()), shardHandler); + tempSourceLeader, new ModifiableSolrParams(cmd.getParams()), shardHandler); syncRequestTracker.processResponses( results, @@ -376,12 +376,10 @@ private void migrateKey( params.set(CoreAdminParams.RANGES, splitRange.toString()); params.set("split.key", splitKey); - String tempNodeName = sourceLeader.getNodeName(); - { final ShardRequestTracker shardRequestTracker = CollectionHandlingUtils.asyncRequestTracker(adminCmdContext, ccc); - shardRequestTracker.sendShardRequest(tempNodeName, params, shardHandler); + shardRequestTracker.sendShardRequest(sourceLeader, params, shardHandler); shardRequestTracker.processResponses( results, shardHandler, true, "MIGRATE failed to invoke SPLIT core admin command"); } @@ -447,7 +445,7 @@ private void migrateKey( { final ShardRequestTracker shardRequestTracker = CollectionHandlingUtils.asyncRequestTracker(adminCmdContext, ccc); - shardRequestTracker.sendShardRequest(tempSourceLeader.getNodeName(), params, shardHandler); + shardRequestTracker.sendShardRequest(tempSourceLeader, params, shardHandler); shardRequestTracker.processResponses( results, @@ -468,7 +466,7 @@ private void migrateKey( final ShardRequestTracker shardRequestTracker = CollectionHandlingUtils.asyncRequestTracker(adminCmdContext, ccc); - shardRequestTracker.sendShardRequest(targetLeader.getNodeName(), params, shardHandler); + shardRequestTracker.sendShardRequest(targetLeader, params, shardHandler); String msg = "MIGRATE failed to merge " + tempCollectionReplica2 @@ -487,7 +485,7 @@ private void migrateKey( { final ShardRequestTracker shardRequestTracker = CollectionHandlingUtils.asyncRequestTracker(adminCmdContext, ccc); - shardRequestTracker.sendShardRequest(targetLeader.getNodeName(), params, shardHandler); + shardRequestTracker.sendShardRequest(targetLeader, params, shardHandler); shardRequestTracker.processResponses( results, shardHandler, true, "MIGRATE failed to request node to apply buffered updates"); } diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java index c2f0fd3d500b..baf0bf408478 100644 --- a/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java +++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java @@ -275,8 +275,7 @@ public boolean split( { final ShardRequestTracker shardRequestTracker = CollectionHandlingUtils.syncRequestTracker(adminCmdContext, ccc); - shardRequestTracker.sendShardRequest( - parentShardLeader.getNodeName(), params, shardHandler); + shardRequestTracker.sendShardRequest(parentShardLeader, params, shardHandler); SimpleOrderedMap getRangesResults = new SimpleOrderedMap<>(); String msgOnError = "SPLITSHARD failed to invoke SPLIT.getRanges core admin command"; shardRequestTracker.processResponses(getRangesResults, shardHandler, true, msgOnError); @@ -459,7 +458,7 @@ public boolean split( cmd.setOnlyIfLeader(true); ModifiableSolrParams p = new ModifiableSolrParams(cmd.getParams()); - shardRequestTracker.sendShardRequest(nodeName, p, shardHandler); + shardRequestTracker.sendShardRequest(nodeName, subShardName, p, shardHandler); } String msgOnError = "SPLITSHARD timed out waiting for subshard leaders to come up"; @@ -498,7 +497,7 @@ public boolean split( { final ShardRequestTracker shardRequestTracker = CollectionHandlingUtils.asyncRequestTracker(adminCmdContext, ccc); - shardRequestTracker.sendShardRequest(parentShardLeader.getNodeName(), params, shardHandler); + shardRequestTracker.sendShardRequest(parentShardLeader, params, shardHandler); String msgOnError = "SPLITSHARD failed to invoke SPLIT core admin command"; shardRequestTracker.processResponses(results, shardHandler, true, msgOnError); @@ -527,7 +526,7 @@ public boolean split( CoreAdminParams.CoreAdminAction.REQUESTAPPLYUPDATES.toString()); params.set(CoreAdminParams.NAME, subShardName); - shardRequestTracker.sendShardRequest(nodeName, params, shardHandler); + shardRequestTracker.sendShardRequest(nodeName, subShardName, params, shardHandler); } String msgOnError = diff --git a/solr/core/src/java/org/apache/solr/handler/component/ShardRequest.java b/solr/core/src/java/org/apache/solr/handler/component/ShardRequest.java index d7d7da04f224..5222b38abee3 100644 --- a/solr/core/src/java/org/apache/solr/handler/component/ShardRequest.java +++ b/solr/core/src/java/org/apache/solr/handler/component/ShardRequest.java @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; import org.apache.solr.common.params.ModifiableSolrParams; // todo... when finalized make accessors @@ -56,6 +57,12 @@ public class ShardRequest { /** may be null */ public String nodeName; + /** may be null */ + public String coreNodeName; + + /** may be null */ + public Map headers; + // TODO: one could store a list of numbers to correlate where returned docs // go in the top-level response rather than looking up by id... // this would work well if we ever transitioned to using internal ids and diff --git a/solr/core/src/test/org/apache/solr/cloud/api/collections/AsyncCallRequestStatusResponseTest.java b/solr/core/src/test/org/apache/solr/cloud/api/collections/AsyncCallRequestStatusResponseTest.java index 4c4f476e48ed..ca683c4d764f 100644 --- a/solr/core/src/test/org/apache/solr/cloud/api/collections/AsyncCallRequestStatusResponseTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/api/collections/AsyncCallRequestStatusResponseTest.java @@ -68,8 +68,9 @@ public void testAsyncCallStatusResponse() throws Exception { final NamedList success = (NamedList) r.get("success"); assertNotNull("Expected 'success' response" + r, success); - final int actualSuccessElems = 2 * (numShards * numReplicas); - // every replica responds once on submit and once on complete + final int actualSuccessElems = numShards * numReplicas; + // every replica responds either once on submit (failure) or once on complete (if submit + // succeeds) assertEquals( "Expected " + actualSuccessElems + " elements in the success element" + success.jsonStr(), actualSuccessElems,