Merge pull request #17106 from s1monw/fix_can_delete

IndicesStore checks for `allocated elsewhere` for every shard not alocated on the local node

On each cluster-state update we check on the local node if we can delete some shards content.
For this we linearly walk all shards and check if they are allocated and started on another node
and if we can delete them locally. if we can delete them locally we go and ask other nodes if we can
delete them and then if the shared IS active elsewhere issue a state update task to delete it. Yet,
there is a bug in IndicesService#canDeleteShardContent which returns `true` even if that shards
datapath doesn't exist on the node which causes tons of unnecessary node to node communication and
as many state update task to be issued. This can have large impact on the cluster state processing
speed. 

**NOTE:** This only happens for shards that have at least one shard allocated on the node ie. if an `IndexService` exists.
This commit is contained in:
Simon Willnauer 2016-03-15 12:59:45 +01:00
commit 8b201fda46
2 changed files with 11 additions and 4 deletions

View File

@ -624,12 +624,17 @@ public class IndicesService extends AbstractLifecycleComponent<IndicesService> i
assert shardId.getIndex().equals(indexSettings.getIndex()); assert shardId.getIndex().equals(indexSettings.getIndex());
final IndexService indexService = indexService(shardId.getIndex()); final IndexService indexService = indexService(shardId.getIndex());
if (indexSettings.isOnSharedFilesystem() == false) { if (indexSettings.isOnSharedFilesystem() == false) {
if (indexService != null && nodeEnv.hasNodeFile()) { if (nodeEnv.hasNodeFile()) {
return indexService.hasShard(shardId.id()) == false; final boolean isAllocated = indexService != null && indexService.hasShard(shardId.id());
} else if (nodeEnv.hasNodeFile()) { if (isAllocated) {
if (indexSettings.hasCustomDataPath()) { return false; // we are allocated - can't delete the shard
} else if (indexSettings.hasCustomDataPath()) {
// lets see if it's on a custom path (return false if the shared doesn't exist)
// we don't need to delete anything that is not there
return Files.exists(nodeEnv.resolveCustomLocation(indexSettings, shardId)); return Files.exists(nodeEnv.resolveCustomLocation(indexSettings, shardId));
} else { } else {
// lets see if it's path is available (return false if the shared doesn't exist)
// we don't need to delete anything that is not there
return FileSystemUtils.exists(nodeEnv.availableShardPaths(shardId)); return FileSystemUtils.exists(nodeEnv.availableShardPaths(shardId));
} }
} }

View File

@ -81,6 +81,8 @@ public class IndicesServiceTests extends ESSingleNodeTestCase {
assertFalse("shard is allocated", indicesService.canDeleteShardContent(shardId, test.getIndexSettings())); assertFalse("shard is allocated", indicesService.canDeleteShardContent(shardId, test.getIndexSettings()));
test.removeShard(0, "boom"); test.removeShard(0, "boom");
assertTrue("shard is removed", indicesService.canDeleteShardContent(shardId, test.getIndexSettings())); assertTrue("shard is removed", indicesService.canDeleteShardContent(shardId, test.getIndexSettings()));
ShardId notAllocated = new ShardId(test.index(), 100);
assertFalse("shard that was never on this node should NOT be deletable", indicesService.canDeleteShardContent(notAllocated, test.getIndexSettings()));
} }
public void testDeleteIndexStore() throws Exception { public void testDeleteIndexStore() throws Exception {