Search in sources :

Example 91 with RoutingNodes

use of org.elasticsearch.cluster.routing.RoutingNodes in project crate by crate.

the class AllocateEmptyPrimaryAllocationCommand method execute.

@Override
public RerouteExplanation execute(RoutingAllocation allocation, boolean explain) {
    final DiscoveryNode discoNode;
    try {
        discoNode = allocation.nodes().resolveNode(node);
    } catch (IllegalArgumentException e) {
        return explainOrThrowRejectedCommand(explain, allocation, e);
    }
    final RoutingNodes routingNodes = allocation.routingNodes();
    RoutingNode routingNode = routingNodes.node(discoNode.getId());
    if (routingNode == null) {
        return explainOrThrowMissingRoutingNode(allocation, explain, discoNode);
    }
    try {
        allocation.routingTable().shardRoutingTable(index, shardId).primaryShard();
    } catch (IndexNotFoundException | ShardNotFoundException e) {
        return explainOrThrowRejectedCommand(explain, allocation, e);
    }
    ShardRouting shardRouting = null;
    for (ShardRouting shard : allocation.routingNodes().unassigned()) {
        if (shard.getIndexName().equals(index) && shard.getId() == shardId && shard.primary()) {
            shardRouting = shard;
            break;
        }
    }
    if (shardRouting == null) {
        return explainOrThrowRejectedCommand(explain, allocation, "primary [" + index + "][" + shardId + "] is already assigned");
    }
    if (shardRouting.recoverySource().getType() != RecoverySource.Type.EMPTY_STORE && acceptDataLoss == false) {
        String dataLossWarning = "allocating an empty primary for [" + index + "][" + shardId + "] can result in data loss. Please confirm by setting the accept_data_loss parameter to true";
        return explainOrThrowRejectedCommand(explain, allocation, dataLossWarning);
    }
    UnassignedInfo unassignedInfoToUpdate = null;
    if (shardRouting.unassignedInfo().getReason() != UnassignedInfo.Reason.FORCED_EMPTY_PRIMARY) {
        String unassignedInfoMessage = "force empty allocation from previous reason " + shardRouting.unassignedInfo().getReason() + ", " + shardRouting.unassignedInfo().getMessage();
        unassignedInfoToUpdate = new UnassignedInfo(UnassignedInfo.Reason.FORCED_EMPTY_PRIMARY, unassignedInfoMessage, shardRouting.unassignedInfo().getFailure(), 0, System.nanoTime(), System.currentTimeMillis(), false, shardRouting.unassignedInfo().getLastAllocationStatus(), Collections.emptySet());
    }
    initializeUnassignedShard(allocation, routingNodes, routingNode, shardRouting, unassignedInfoToUpdate, EmptyStoreRecoverySource.INSTANCE);
    return new RerouteExplanation(this, allocation.decision(Decision.YES, name() + " (allocation command)", "ignore deciders"));
}
Also used : DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) RoutingNode(org.elasticsearch.cluster.routing.RoutingNode) ShardNotFoundException(org.elasticsearch.index.shard.ShardNotFoundException) RoutingNodes(org.elasticsearch.cluster.routing.RoutingNodes) UnassignedInfo(org.elasticsearch.cluster.routing.UnassignedInfo) IndexNotFoundException(org.elasticsearch.index.IndexNotFoundException) RerouteExplanation(org.elasticsearch.cluster.routing.allocation.RerouteExplanation) ShardRouting(org.elasticsearch.cluster.routing.ShardRouting)

Example 92 with RoutingNodes

use of org.elasticsearch.cluster.routing.RoutingNodes in project crate by crate.

the class ReplicaShardAllocator method makeAllocationDecision.

@Override
public AllocateUnassignedDecision makeAllocationDecision(final ShardRouting unassignedShard, final RoutingAllocation allocation, final Logger logger) {
    if (isResponsibleFor(unassignedShard) == false) {
        // this allocator is not responsible for deciding on this shard
        return AllocateUnassignedDecision.NOT_TAKEN;
    }
    final RoutingNodes routingNodes = allocation.routingNodes();
    final boolean explain = allocation.debugDecision();
    // pre-check if it can be allocated to any node that currently exists, so we won't list the store for it for nothing
    Tuple<Decision, Map<String, NodeAllocationResult>> result = canBeAllocatedToAtLeastOneNode(unassignedShard, allocation);
    Decision allocateDecision = result.v1();
    if (allocateDecision.type() != Decision.Type.YES && (explain == false || hasInitiatedFetching(unassignedShard) == false)) {
        // only return early if we are not in explain mode, or we are in explain mode but we have not
        // yet attempted to fetch any shard data
        logger.trace("{}: ignoring allocation, can't be allocated on any node", unassignedShard);
        return AllocateUnassignedDecision.no(UnassignedInfo.AllocationStatus.fromDecision(allocateDecision.type()), result.v2() != null ? new ArrayList<>(result.v2().values()) : null);
    }
    AsyncShardFetch.FetchResult<NodeStoreFilesMetadata> shardStores = fetchData(unassignedShard, allocation);
    if (shardStores.hasData() == false) {
        logger.trace("{}: ignoring allocation, still fetching shard stores", unassignedShard);
        allocation.setHasPendingAsyncFetch();
        List<NodeAllocationResult> nodeDecisions = null;
        if (explain) {
            nodeDecisions = buildDecisionsForAllNodes(unassignedShard, allocation);
        }
        return AllocateUnassignedDecision.no(AllocationStatus.FETCHING_SHARD_DATA, nodeDecisions);
    }
    ShardRouting primaryShard = routingNodes.activePrimary(unassignedShard.shardId());
    if (primaryShard == null) {
        assert explain : "primary should only be null here if we are in explain mode, so we didn't " + "exit early when canBeAllocatedToAtLeastOneNode didn't return a YES decision";
        return AllocateUnassignedDecision.no(UnassignedInfo.AllocationStatus.fromDecision(allocateDecision.type()), new ArrayList<>(result.v2().values()));
    }
    assert primaryShard.currentNodeId() != null;
    final DiscoveryNode primaryNode = allocation.nodes().get(primaryShard.currentNodeId());
    final TransportNodesListShardStoreMetadata.StoreFilesMetadata primaryStore = findStore(primaryNode, shardStores);
    if (primaryStore == null) {
        // if we can't find the primary data, it is probably because the primary shard is corrupted (and listing failed)
        // we want to let the replica be allocated in order to expose the actual problem with the primary that the replica
        // will try and recover from
        // Note, this is the existing behavior, as exposed in running CorruptFileTest#testNoPrimaryData
        logger.trace("{}: no primary shard store found or allocated, letting actual allocation figure it out", unassignedShard);
        return AllocateUnassignedDecision.NOT_TAKEN;
    }
    MatchingNodes matchingNodes = findMatchingNodes(unassignedShard, allocation, false, primaryNode, primaryStore, shardStores, explain);
    assert explain == false || matchingNodes.nodeDecisions != null : "in explain mode, we must have individual node decisions";
    List<NodeAllocationResult> nodeDecisions = augmentExplanationsWithStoreInfo(result.v2(), matchingNodes.nodeDecisions);
    if (allocateDecision.type() != Decision.Type.YES) {
        return AllocateUnassignedDecision.no(UnassignedInfo.AllocationStatus.fromDecision(allocateDecision.type()), nodeDecisions);
    } else if (matchingNodes.getNodeWithHighestMatch() != null) {
        RoutingNode nodeWithHighestMatch = allocation.routingNodes().node(matchingNodes.getNodeWithHighestMatch().getId());
        // we only check on THROTTLE since we checked before before on NO
        Decision decision = allocation.deciders().canAllocate(unassignedShard, nodeWithHighestMatch, allocation);
        if (decision.type() == Decision.Type.THROTTLE) {
            logger.debug("[{}][{}]: throttling allocation [{}] to [{}] in order to reuse its unallocated persistent store", unassignedShard.index(), unassignedShard.id(), unassignedShard, nodeWithHighestMatch.node());
            // we are throttling this, as we have enough other shards to allocate to this node, so ignore it for now
            return AllocateUnassignedDecision.throttle(nodeDecisions);
        } else {
            logger.debug("[{}][{}]: allocating [{}] to [{}] in order to reuse its unallocated persistent store", unassignedShard.index(), unassignedShard.id(), unassignedShard, nodeWithHighestMatch.node());
            // we found a match
            return AllocateUnassignedDecision.yes(nodeWithHighestMatch.node(), null, nodeDecisions, true);
        }
    } else if (matchingNodes.hasAnyData() == false && unassignedShard.unassignedInfo().isDelayed()) {
        // if we didn't manage to find *any* data (regardless of matching sizes), and the replica is
        // unassigned due to a node leaving, so we delay allocation of this replica to see if the
        // node with the shard copy will rejoin so we can re-use the copy it has
        logger.debug("{}: allocation of [{}] is delayed", unassignedShard.shardId(), unassignedShard);
        long remainingDelayMillis = 0L;
        long totalDelayMillis = 0L;
        if (explain) {
            UnassignedInfo unassignedInfo = unassignedShard.unassignedInfo();
            Metadata metadata = allocation.metadata();
            IndexMetadata indexMetadata = metadata.index(unassignedShard.index());
            totalDelayMillis = INDEX_DELAYED_NODE_LEFT_TIMEOUT_SETTING.get(indexMetadata.getSettings()).getMillis();
            long remainingDelayNanos = unassignedInfo.getRemainingDelay(System.nanoTime(), indexMetadata.getSettings());
            remainingDelayMillis = TimeValue.timeValueNanos(remainingDelayNanos).millis();
        }
        return AllocateUnassignedDecision.delayed(remainingDelayMillis, totalDelayMillis, nodeDecisions);
    }
    return AllocateUnassignedDecision.NOT_TAKEN;
}
Also used : NodeStoreFilesMetadata(org.elasticsearch.indices.store.TransportNodesListShardStoreMetadata.NodeStoreFilesMetadata) DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) RoutingNodes(org.elasticsearch.cluster.routing.RoutingNodes) UnassignedInfo(org.elasticsearch.cluster.routing.UnassignedInfo) ArrayList(java.util.ArrayList) IndexMetadata(org.elasticsearch.cluster.metadata.IndexMetadata) StoreFileMetadata(org.elasticsearch.index.store.StoreFileMetadata) Metadata(org.elasticsearch.cluster.metadata.Metadata) TransportNodesListShardStoreMetadata(org.elasticsearch.indices.store.TransportNodesListShardStoreMetadata) NodeStoreFilesMetadata(org.elasticsearch.indices.store.TransportNodesListShardStoreMetadata.NodeStoreFilesMetadata) AllocateUnassignedDecision(org.elasticsearch.cluster.routing.allocation.AllocateUnassignedDecision) Decision(org.elasticsearch.cluster.routing.allocation.decider.Decision) RoutingNode(org.elasticsearch.cluster.routing.RoutingNode) TransportNodesListShardStoreMetadata(org.elasticsearch.indices.store.TransportNodesListShardStoreMetadata) ShardRouting(org.elasticsearch.cluster.routing.ShardRouting) IndexMetadata(org.elasticsearch.cluster.metadata.IndexMetadata) HashMap(java.util.HashMap) Map(java.util.Map) NodeAllocationResult(org.elasticsearch.cluster.routing.allocation.NodeAllocationResult)

Example 93 with RoutingNodes

use of org.elasticsearch.cluster.routing.RoutingNodes in project crate by crate.

the class ReplicaShardAllocator method processExistingRecoveries.

/**
 * Process existing recoveries of replicas and see if we need to cancel them if we find a better
 * match. Today, a better match is one that can perform a no-op recovery while the previous recovery
 * has to copy segment files.
 */
public void processExistingRecoveries(RoutingAllocation allocation) {
    Metadata metadata = allocation.metadata();
    RoutingNodes routingNodes = allocation.routingNodes();
    List<Runnable> shardCancellationActions = new ArrayList<>();
    for (RoutingNode routingNode : routingNodes) {
        for (ShardRouting shard : routingNode) {
            if (shard.primary()) {
                continue;
            }
            if (shard.initializing() == false) {
                continue;
            }
            if (shard.relocatingNodeId() != null) {
                continue;
            }
            // if we are allocating a replica because of index creation, no need to go and find a copy, there isn't one...
            if (shard.unassignedInfo() != null && shard.unassignedInfo().getReason() == UnassignedInfo.Reason.INDEX_CREATED) {
                continue;
            }
            AsyncShardFetch.FetchResult<NodeStoreFilesMetadata> shardStores = fetchData(shard, allocation);
            if (shardStores.hasData() == false) {
                logger.trace("{}: fetching new stores for initializing shard", shard);
                // still fetching
                continue;
            }
            ShardRouting primaryShard = allocation.routingNodes().activePrimary(shard.shardId());
            assert primaryShard != null : "the replica shard can be allocated on at least one node, so there must be an active primary";
            assert primaryShard.currentNodeId() != null;
            final DiscoveryNode primaryNode = allocation.nodes().get(primaryShard.currentNodeId());
            final TransportNodesListShardStoreMetadata.StoreFilesMetadata primaryStore = findStore(primaryNode, shardStores);
            if (primaryStore == null) {
                // if we can't find the primary data, it is probably because the primary shard is corrupted (and listing failed)
                // just let the recovery find it out, no need to do anything about it for the initializing shard
                logger.trace("{}: no primary shard store found or allocated, letting actual allocation figure it out", shard);
                continue;
            }
            MatchingNodes matchingNodes = findMatchingNodes(shard, allocation, true, primaryNode, primaryStore, shardStores, false);
            if (matchingNodes.getNodeWithHighestMatch() != null) {
                DiscoveryNode currentNode = allocation.nodes().get(shard.currentNodeId());
                DiscoveryNode nodeWithHighestMatch = matchingNodes.getNodeWithHighestMatch();
                // current node will not be in matchingNodes as it is filtered away by SameShardAllocationDecider
                if (currentNode.equals(nodeWithHighestMatch) == false && matchingNodes.canPerformNoopRecovery(nodeWithHighestMatch) && canPerformOperationBasedRecovery(primaryStore, shardStores, currentNode) == false) {
                    // we found a better match that can perform noop recovery, cancel the existing allocation.
                    logger.debug("cancelling allocation of replica on [{}], can perform a noop recovery on node [{}]", currentNode, nodeWithHighestMatch);
                    final Set<String> failedNodeIds = shard.unassignedInfo() == null ? Collections.emptySet() : shard.unassignedInfo().getFailedNodeIds();
                    UnassignedInfo unassignedInfo = new UnassignedInfo(UnassignedInfo.Reason.REALLOCATED_REPLICA, "existing allocation of replica to [" + currentNode + "] cancelled, can perform a noop recovery on [" + nodeWithHighestMatch + "]", null, 0, allocation.getCurrentNanoTime(), System.currentTimeMillis(), false, UnassignedInfo.AllocationStatus.NO_ATTEMPT, failedNodeIds);
                    // don't cancel shard in the loop as it will cause a ConcurrentModificationException
                    shardCancellationActions.add(() -> routingNodes.failShard(logger, shard, unassignedInfo, metadata.getIndexSafe(shard.index()), allocation.changes()));
                }
            }
        }
    }
    for (Runnable action : shardCancellationActions) {
        action.run();
    }
}
Also used : NodeStoreFilesMetadata(org.elasticsearch.indices.store.TransportNodesListShardStoreMetadata.NodeStoreFilesMetadata) DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) RoutingNodes(org.elasticsearch.cluster.routing.RoutingNodes) UnassignedInfo(org.elasticsearch.cluster.routing.UnassignedInfo) IndexMetadata(org.elasticsearch.cluster.metadata.IndexMetadata) StoreFileMetadata(org.elasticsearch.index.store.StoreFileMetadata) Metadata(org.elasticsearch.cluster.metadata.Metadata) TransportNodesListShardStoreMetadata(org.elasticsearch.indices.store.TransportNodesListShardStoreMetadata) NodeStoreFilesMetadata(org.elasticsearch.indices.store.TransportNodesListShardStoreMetadata.NodeStoreFilesMetadata) ArrayList(java.util.ArrayList) RoutingNode(org.elasticsearch.cluster.routing.RoutingNode) TransportNodesListShardStoreMetadata(org.elasticsearch.indices.store.TransportNodesListShardStoreMetadata) ShardRouting(org.elasticsearch.cluster.routing.ShardRouting)

Example 94 with RoutingNodes

use of org.elasticsearch.cluster.routing.RoutingNodes in project crate by crate.

the class SysAllocations method iterator.

@Override
public Iterator<SysAllocation> iterator() {
    final ClusterState state = clusterService.state();
    final RoutingNodes routingNodes = state.getRoutingNodes();
    final ClusterInfo clusterInfo = clusterInfoService.getClusterInfo();
    final RoutingAllocation allocation = new RoutingAllocation(allocationDeciders, routingNodes, state, clusterInfo, System.nanoTime());
    return allocation.routingTable().allShards().stream().filter(shardRouting -> !IndexParts.isDangling(shardRouting.getIndexName())).map(shardRouting -> createSysAllocations(allocation, shardRouting)).iterator();
}
Also used : ShardRouting(org.elasticsearch.cluster.routing.ShardRouting) IndexParts(io.crate.metadata.IndexParts) Iterator(java.util.Iterator) MoveDecision(org.elasticsearch.cluster.routing.allocation.MoveDecision) ShardAllocationDecision(org.elasticsearch.cluster.routing.allocation.ShardAllocationDecision) ClusterService(org.elasticsearch.cluster.service.ClusterService) RoutingAllocation(org.elasticsearch.cluster.routing.allocation.RoutingAllocation) ShardsAllocator(org.elasticsearch.cluster.routing.allocation.allocator.ShardsAllocator) Supplier(java.util.function.Supplier) Inject(org.elasticsearch.common.inject.Inject) ClusterInfo(org.elasticsearch.cluster.ClusterInfo) ClusterState(org.elasticsearch.cluster.ClusterState) Singleton(org.elasticsearch.common.inject.Singleton) AllocationDeciders(org.elasticsearch.cluster.routing.allocation.decider.AllocationDeciders) RoutingNodes(org.elasticsearch.cluster.routing.RoutingNodes) AllocateUnassignedDecision(org.elasticsearch.cluster.routing.allocation.AllocateUnassignedDecision) ClusterInfoService(org.elasticsearch.cluster.ClusterInfoService) GatewayAllocator(org.elasticsearch.gateway.GatewayAllocator) ClusterState(org.elasticsearch.cluster.ClusterState) ClusterInfo(org.elasticsearch.cluster.ClusterInfo) RoutingNodes(org.elasticsearch.cluster.routing.RoutingNodes) RoutingAllocation(org.elasticsearch.cluster.routing.allocation.RoutingAllocation)

Example 95 with RoutingNodes

use of org.elasticsearch.cluster.routing.RoutingNodes in project crate by crate.

the class AllocationService method reroute.

public CommandsResult reroute(final ClusterState clusterState, AllocationCommands commands, boolean explain, boolean retryFailed) {
    RoutingNodes routingNodes = getMutableRoutingNodes(clusterState);
    // we don't shuffle the unassigned shards here, to try and get as close as possible to
    // a consistent result of the effect the commands have on the routing
    // this allows systems to dry run the commands, see the resulting cluster state, and act on it
    RoutingAllocation allocation = new RoutingAllocation(allocationDeciders, routingNodes, clusterState, clusterInfoService.getClusterInfo(), currentNanoTime());
    // don't short circuit deciders, we want a full explanation
    allocation.debugDecision(true);
    // we ignore disable allocation, because commands are explicit
    allocation.ignoreDisable(true);
    if (retryFailed) {
        resetFailedAllocationCounter(allocation);
    }
    RoutingExplanations explanations = commands.execute(allocation, explain);
    // we revert the ignore disable flag, since when rerouting, we want the original setting to take place
    allocation.ignoreDisable(false);
    // the assumption is that commands will move / act on shards (or fail through exceptions)
    // so, there will always be shard "movements", so no need to check on reroute
    reroute(allocation);
    return new CommandsResult(explanations, buildResultAndLogHealthChange(clusterState, allocation, "reroute commands"));
}
Also used : RoutingNodes(org.elasticsearch.cluster.routing.RoutingNodes)

Aggregations

RoutingNodes (org.elasticsearch.cluster.routing.RoutingNodes)104 ClusterState (org.elasticsearch.cluster.ClusterState)72 RoutingTable (org.elasticsearch.cluster.routing.RoutingTable)64 IndexMetaData (org.elasticsearch.cluster.metadata.IndexMetaData)55 MetaData (org.elasticsearch.cluster.metadata.MetaData)53 ShardRouting (org.elasticsearch.cluster.routing.ShardRouting)39 RoutingNode (org.elasticsearch.cluster.routing.RoutingNode)24 DiscoveryNode (org.elasticsearch.cluster.node.DiscoveryNode)20 IndexMetadata (org.elasticsearch.cluster.metadata.IndexMetadata)15 IndexShardRoutingTable (org.elasticsearch.cluster.routing.IndexShardRoutingTable)15 DiscoveryNodes (org.elasticsearch.cluster.node.DiscoveryNodes)14 UnassignedInfo (org.elasticsearch.cluster.routing.UnassignedInfo)14 RoutingAllocation (org.elasticsearch.cluster.routing.allocation.RoutingAllocation)14 Metadata (org.elasticsearch.cluster.metadata.Metadata)13 IndexRoutingTable (org.elasticsearch.cluster.routing.IndexRoutingTable)11 TestShardRouting (org.elasticsearch.cluster.routing.TestShardRouting)11 ArrayList (java.util.ArrayList)9 Settings (org.elasticsearch.common.settings.Settings)9 ClusterInfo (org.elasticsearch.cluster.ClusterInfo)8 RerouteExplanation (org.elasticsearch.cluster.routing.allocation.RerouteExplanation)8