When shard data is still being fetched from nodes in the cluster,
the ReplicaShardAllocator, when in explain mode, would get the node decisions for all nodes in the cluster. The PrimaryShardAllocator neglected to do this and tried to use the shard fetch data in explain mode, which had not yet been fully fetched. This commit fixes this by ensuring the PrimaryShardAllocator gets node decisions in the same way the ReplicaShardAllocator does in explain mode, if shard data is still being fetched.
This commit is contained in:
parent
317866894e
commit
30bcb06606
|
@ -20,14 +20,20 @@
|
||||||
package org.elasticsearch.gateway;
|
package org.elasticsearch.gateway;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.elasticsearch.cluster.routing.RoutingNode;
|
||||||
import org.elasticsearch.cluster.routing.RoutingNodes;
|
import org.elasticsearch.cluster.routing.RoutingNodes;
|
||||||
import org.elasticsearch.cluster.routing.ShardRouting;
|
import org.elasticsearch.cluster.routing.ShardRouting;
|
||||||
import org.elasticsearch.cluster.routing.allocation.AllocateUnassignedDecision;
|
import org.elasticsearch.cluster.routing.allocation.AllocateUnassignedDecision;
|
||||||
import org.elasticsearch.cluster.routing.allocation.AllocationDecision;
|
import org.elasticsearch.cluster.routing.allocation.AllocationDecision;
|
||||||
|
import org.elasticsearch.cluster.routing.allocation.NodeAllocationResult;
|
||||||
import org.elasticsearch.cluster.routing.allocation.RoutingAllocation;
|
import org.elasticsearch.cluster.routing.allocation.RoutingAllocation;
|
||||||
|
import org.elasticsearch.cluster.routing.allocation.decider.Decision;
|
||||||
import org.elasticsearch.common.component.AbstractComponent;
|
import org.elasticsearch.common.component.AbstractComponent;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract class that implements basic functionality for allocating
|
* An abstract class that implements basic functionality for allocating
|
||||||
* shards to nodes based on shard copies that already exist in the cluster.
|
* shards to nodes based on shard copies that already exist in the cluster.
|
||||||
|
@ -85,4 +91,17 @@ public abstract class BaseGatewayShardAllocator extends AbstractComponent {
|
||||||
public abstract AllocateUnassignedDecision makeAllocationDecision(ShardRouting unassignedShard,
|
public abstract AllocateUnassignedDecision makeAllocationDecision(ShardRouting unassignedShard,
|
||||||
RoutingAllocation allocation,
|
RoutingAllocation allocation,
|
||||||
Logger logger);
|
Logger logger);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds decisions for all nodes in the cluster, so that the explain API can provide information on
|
||||||
|
* allocation decisions for each node, while still waiting to allocate the shard (e.g. due to fetching shard data).
|
||||||
|
*/
|
||||||
|
protected List<NodeAllocationResult> buildDecisionsForAllNodes(ShardRouting shard, RoutingAllocation allocation) {
|
||||||
|
List<NodeAllocationResult> results = new ArrayList<>();
|
||||||
|
for (RoutingNode node : allocation.routingNodes()) {
|
||||||
|
Decision decision = allocation.deciders().canAllocate(shard, node, allocation);
|
||||||
|
results.add(new NodeAllocationResult(node.node(), null, decision));
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,9 +124,11 @@ public abstract class PrimaryShardAllocator extends BaseGatewayShardAllocator {
|
||||||
final FetchResult<NodeGatewayStartedShards> shardState = fetchData(unassignedShard, allocation);
|
final FetchResult<NodeGatewayStartedShards> shardState = fetchData(unassignedShard, allocation);
|
||||||
if (shardState.hasData() == false) {
|
if (shardState.hasData() == false) {
|
||||||
allocation.setHasPendingAsyncFetch();
|
allocation.setHasPendingAsyncFetch();
|
||||||
if (explain == false) {
|
List<NodeAllocationResult> nodeDecisions = null;
|
||||||
return AllocateUnassignedDecision.no(AllocationStatus.FETCHING_SHARD_DATA, null);
|
if (explain) {
|
||||||
|
nodeDecisions = buildDecisionsForAllNodes(unassignedShard, allocation);
|
||||||
}
|
}
|
||||||
|
return AllocateUnassignedDecision.no(AllocationStatus.FETCHING_SHARD_DATA, nodeDecisions);
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't create a new IndexSetting object for every shard as this could cause a lot of garbage
|
// don't create a new IndexSetting object for every shard as this could cause a lot of garbage
|
||||||
|
|
|
@ -238,19 +238,6 @@ public abstract class ReplicaShardAllocator extends BaseGatewayShardAllocator {
|
||||||
return AllocateUnassignedDecision.NOT_TAKEN;
|
return AllocateUnassignedDecision.NOT_TAKEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds decisions for all nodes in the cluster, so that the explain API can provide information on
|
|
||||||
* allocation decisions for each node, while still waiting to allocate the shard (e.g. due to fetching shard data).
|
|
||||||
*/
|
|
||||||
private List<NodeAllocationResult> buildDecisionsForAllNodes(ShardRouting shard, RoutingAllocation allocation) {
|
|
||||||
List<NodeAllocationResult> results = new ArrayList<>();
|
|
||||||
for (RoutingNode node : allocation.routingNodes()) {
|
|
||||||
Decision decision = allocation.deciders().canAllocate(shard, node, allocation);
|
|
||||||
results.add(new NodeAllocationResult(node.node(), null, decision));
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if the shard can be allocated on at least one node based on the allocation deciders.
|
* Determines if the shard can be allocated on at least one node based on the allocation deciders.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue