forked from elastic/elasticsearch
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add support for internal custom allocation commands, including allocation, move, and cancel (shard). also, fix elastic#2242, which causes the cluster state to be in inconsistent state when a shard being the source of relocation is failed
- Loading branch information
Showing
19 changed files
with
1,235 additions
and
192 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
326 changes: 157 additions & 169 deletions
326
src/main/java/org/elasticsearch/cluster/routing/allocation/AllocationService.java
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
86 changes: 86 additions & 0 deletions
86
.../java/org/elasticsearch/cluster/routing/allocation/command/AllocateAllocationCommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
/* | ||
* Licensed to ElasticSearch and Shay Banon under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. ElasticSearch 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.elasticsearch.cluster.routing.allocation.command; | ||
|
||
import org.elasticsearch.ElasticSearchException; | ||
import org.elasticsearch.ElasticSearchIllegalArgumentException; | ||
import org.elasticsearch.cluster.node.DiscoveryNode; | ||
import org.elasticsearch.cluster.routing.MutableShardRouting; | ||
import org.elasticsearch.cluster.routing.RoutingNode; | ||
import org.elasticsearch.cluster.routing.allocation.RoutingAllocation; | ||
import org.elasticsearch.index.shard.ShardId; | ||
|
||
import java.util.Iterator; | ||
|
||
/** | ||
* Allocates an unassigned shard to a specific node. Note, primary allocation will "force" | ||
* allocation which might mean one will loose data if using local gateway..., use with care | ||
* with the <tt>allowPrimary</tt> flag. | ||
*/ | ||
public class AllocateAllocationCommand implements AllocationCommand { | ||
|
||
private final ShardId shardId; | ||
private final String nodeId; | ||
private final boolean allowPrimary; | ||
|
||
public AllocateAllocationCommand(ShardId shardId, String nodeId, boolean allowPrimary) { | ||
this.shardId = shardId; | ||
this.nodeId = nodeId; | ||
this.allowPrimary = allowPrimary; | ||
} | ||
|
||
@Override | ||
public void execute(RoutingAllocation allocation) throws ElasticSearchException { | ||
DiscoveryNode node = allocation.nodes().resolveNode(nodeId); | ||
|
||
MutableShardRouting shardRouting = null; | ||
for (MutableShardRouting routing : allocation.routingNodes().unassigned()) { | ||
if (routing.shardId().equals(shardId)) { | ||
// prefer primaries first to allocate | ||
if (shardRouting == null || routing.primary()) { | ||
shardRouting = routing; | ||
} | ||
} | ||
} | ||
|
||
if (shardRouting == null) { | ||
throw new ElasticSearchIllegalArgumentException("[allocate] failed to find " + shardId + " on the list of unassigned shards"); | ||
} | ||
|
||
if (shardRouting.primary() && !allowPrimary) { | ||
throw new ElasticSearchIllegalArgumentException("[allocate] trying to allocate a primary shard " + shardId + "], which is disabled"); | ||
} | ||
|
||
RoutingNode routingNode = allocation.routingNodes().node(node.id()); | ||
allocation.addIgnoreDisable(shardRouting.shardId(), routingNode.nodeId()); | ||
if (!allocation.deciders().canAllocate(shardRouting, routingNode, allocation).allowed()) { | ||
throw new ElasticSearchIllegalArgumentException("[allocate] allocation of " + shardId + " on node " + node + " is not allowed"); | ||
} | ||
// go over and remove it from the unassigned | ||
for (Iterator<MutableShardRouting> it = allocation.routingNodes().unassigned().iterator(); it.hasNext(); ) { | ||
if (it.next() != shardRouting) { | ||
continue; | ||
} | ||
it.remove(); | ||
routingNode.add(shardRouting); | ||
break; | ||
} | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
src/main/java/org/elasticsearch/cluster/routing/allocation/command/AllocationCommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
* Licensed to ElasticSearch and Shay Banon under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. ElasticSearch 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.elasticsearch.cluster.routing.allocation.command; | ||
|
||
import org.elasticsearch.ElasticSearchException; | ||
import org.elasticsearch.cluster.routing.allocation.RoutingAllocation; | ||
|
||
/** | ||
*/ | ||
public interface AllocationCommand { | ||
|
||
void execute(RoutingAllocation allocation) throws ElasticSearchException; | ||
} |
53 changes: 53 additions & 0 deletions
53
src/main/java/org/elasticsearch/cluster/routing/allocation/command/AllocationCommands.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/* | ||
* Licensed to ElasticSearch and Shay Banon under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. ElasticSearch 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.elasticsearch.cluster.routing.allocation.command; | ||
|
||
import com.google.common.collect.Lists; | ||
import org.elasticsearch.ElasticSearchException; | ||
import org.elasticsearch.cluster.routing.allocation.RoutingAllocation; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
/** | ||
*/ | ||
public class AllocationCommands { | ||
|
||
private final List<AllocationCommand> commands = Lists.newArrayList(); | ||
|
||
public AllocationCommands(AllocationCommand... commands) { | ||
if (commands != null) { | ||
this.commands.addAll(Arrays.asList(commands)); | ||
} | ||
} | ||
|
||
public AllocationCommands add(AllocationCommand... commands) { | ||
if (commands != null) { | ||
this.commands.addAll(Arrays.asList(commands)); | ||
} | ||
return this; | ||
} | ||
|
||
public void execute(RoutingAllocation allocation) throws ElasticSearchException { | ||
for (AllocationCommand command : commands) { | ||
command.execute(allocation); | ||
} | ||
} | ||
} |
114 changes: 114 additions & 0 deletions
114
...in/java/org/elasticsearch/cluster/routing/allocation/command/CancelAllocationCommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/* | ||
* Licensed to ElasticSearch and Shay Banon under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. ElasticSearch 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.elasticsearch.cluster.routing.allocation.command; | ||
|
||
import org.elasticsearch.ElasticSearchException; | ||
import org.elasticsearch.ElasticSearchIllegalArgumentException; | ||
import org.elasticsearch.cluster.node.DiscoveryNode; | ||
import org.elasticsearch.cluster.routing.MutableShardRouting; | ||
import org.elasticsearch.cluster.routing.RoutingNode; | ||
import org.elasticsearch.cluster.routing.ShardRoutingState; | ||
import org.elasticsearch.cluster.routing.allocation.RoutingAllocation; | ||
import org.elasticsearch.index.shard.ShardId; | ||
|
||
import java.util.Iterator; | ||
|
||
import static org.elasticsearch.cluster.routing.ShardRoutingState.INITIALIZING; | ||
import static org.elasticsearch.cluster.routing.ShardRoutingState.RELOCATING; | ||
|
||
/** | ||
* A command that cancel relocation, or recovery of a given shard on a node. | ||
*/ | ||
public class CancelAllocationCommand implements AllocationCommand { | ||
|
||
private final ShardId shardId; | ||
|
||
private final String nodeId; | ||
|
||
public CancelAllocationCommand(ShardId shardId, String node) { | ||
this.shardId = shardId; | ||
this.nodeId = node; | ||
} | ||
|
||
@Override | ||
public void execute(RoutingAllocation allocation) throws ElasticSearchException { | ||
DiscoveryNode node = allocation.nodes().resolveNode(nodeId); | ||
|
||
boolean found = false; | ||
for (Iterator<MutableShardRouting> it = allocation.routingNodes().node(node.id()).iterator(); it.hasNext(); ) { | ||
MutableShardRouting shardRouting = it.next(); | ||
if (!shardRouting.shardId().equals(shardId)) { | ||
continue; | ||
} | ||
found = true; | ||
if (shardRouting.relocatingNodeId() != null) { | ||
if (shardRouting.initializing()) { | ||
// the shard is initializing and recovering from another node, simply cancel the recovery | ||
it.remove(); | ||
shardRouting.deassignNode(); | ||
// and cancel the relocating state from the shard its being relocated from | ||
RoutingNode relocatingFromNode = allocation.routingNodes().node(shardRouting.relocatingNodeId()); | ||
if (relocatingFromNode != null) { | ||
for (MutableShardRouting fromShardRouting : relocatingFromNode) { | ||
if (fromShardRouting.shardId().equals(shardRouting.shardId()) && shardRouting.state() == RELOCATING) { | ||
fromShardRouting.cancelRelocation(); | ||
break; | ||
} | ||
} | ||
} | ||
} else if (shardRouting.relocating()) { | ||
// the shard is relocating to another node, cancel the recovery on the other node, and deallocate this one | ||
if (shardRouting.primary()) { | ||
// can't cancel a primary shard being initialized | ||
throw new ElasticSearchIllegalArgumentException("[cancel_allocation] can't cancel " + shardId + " on node " + node + ", shard is primary and initializing its state"); | ||
} | ||
it.remove(); | ||
allocation.routingNodes().unassigned().add(new MutableShardRouting(shardRouting.index(), shardRouting.id(), | ||
null, shardRouting.primary(), ShardRoutingState.UNASSIGNED, shardRouting.version() + 1)); | ||
|
||
// now, go and find the shard that is initializing on the target node, and cancel it as well... | ||
RoutingNode initializingNode = allocation.routingNodes().node(shardRouting.relocatingNodeId()); | ||
if (initializingNode != null) { | ||
for (Iterator<MutableShardRouting> itX = initializingNode.iterator(); itX.hasNext(); ) { | ||
MutableShardRouting initializingShardRouting = itX.next(); | ||
if (initializingShardRouting.shardId().equals(shardRouting.shardId()) && initializingShardRouting.state() == INITIALIZING) { | ||
shardRouting.deassignNode(); | ||
itX.remove(); | ||
} | ||
} | ||
} | ||
} | ||
} else { | ||
// the shard is not relocating, its either started, or initializing, just cancel it and move on... | ||
if (shardRouting.primary()) { | ||
// can't cancel a primary shard being initialized | ||
throw new ElasticSearchIllegalArgumentException("[cancel_allocation] can't cancel " + shardId + " on node " + node + ", shard is primary and initializing its state"); | ||
} | ||
it.remove(); | ||
allocation.routingNodes().unassigned().add(new MutableShardRouting(shardRouting.index(), shardRouting.id(), | ||
null, shardRouting.primary(), ShardRoutingState.UNASSIGNED, shardRouting.version() + 1)); | ||
} | ||
} | ||
|
||
if (!found) { | ||
throw new ElasticSearchIllegalArgumentException("[cancel_allocation] can't cancel " + shardId + ", failed to find it on node " + node); | ||
} | ||
} | ||
} |
Oops, something went wrong.