diff --git a/server/src/main/java/org/elasticsearch/index/shard/RemoveCorruptedShardDataCommand.java b/server/src/main/java/org/elasticsearch/index/shard/RemoveCorruptedShardDataCommand.java index 92dc44d0d8beb..929e301fd9d5f 100644 --- a/server/src/main/java/org/elasticsearch/index/shard/RemoveCorruptedShardDataCommand.java +++ b/server/src/main/java/org/elasticsearch/index/shard/RemoveCorruptedShardDataCommand.java @@ -160,7 +160,7 @@ protected void findAndProcessShardPath(OptionSet options, Environment environmen .resolve(Integer.toString(shId.id())); if (Files.exists(shardPathLocation)) { final ShardPath shardPath = ShardPath.loadShardPath(logger, shId, indexSettings.customDataPath(), - shardPathLocation, dataPath); + new Path[]{shardPathLocation}, dataPath); if (shardPath != null) { consumer.accept(shardPath); } diff --git a/server/src/main/java/org/elasticsearch/index/shard/ShardPath.java b/server/src/main/java/org/elasticsearch/index/shard/ShardPath.java index 12172d09fe0af..ea8203556ccb2 100644 --- a/server/src/main/java/org/elasticsearch/index/shard/ShardPath.java +++ b/server/src/main/java/org/elasticsearch/index/shard/ShardPath.java @@ -99,44 +99,59 @@ public boolean isCustomDataPath() { } /** - * This method resolves the node's shard path using the given {@link NodeEnvironment}. + * This method walks through the nodes shard paths to find the data and state path for the given shard. If multiple + * directories with a valid shard state exist the one with the highest version will be used. * Note: this method resolves custom data locations for the shard if such a custom data path is provided. */ public static ShardPath loadShardPath(Logger logger, NodeEnvironment env, ShardId shardId, String customDataPath) throws IOException { final Path shardPath = env.availableShardPath(shardId); final Path sharedDataPath = env.sharedDataPath(); - return loadShardPath(logger, shardId, customDataPath, shardPath, sharedDataPath); + return loadShardPath(logger, shardId, customDataPath, new Path[] { shardPath }, sharedDataPath); } /** - * This method resolves the node's shard path using the given data paths. + * This method walks through the nodes shard paths to find the data and state path for the given shard. If multiple + * directories with a valid shard state exist the one with the highest version will be used. * Note: this method resolves custom data locations for the shard. */ - public static ShardPath loadShardPath(Logger logger, ShardId shardId, String customDataPath, Path shardPath, + public static ShardPath loadShardPath(Logger logger, ShardId shardId, String customDataPath, Path[] availableShardPaths, Path sharedDataPath) throws IOException { final String indexUUID = shardId.getIndex().getUUID(); - // EMPTY is safe here because we never call namedObject - ShardStateMetadata load = ShardStateMetadata.FORMAT.loadLatestState(logger, NamedXContentRegistry.EMPTY, shardPath); - if (load != null) { - if (load.indexUUID.equals(indexUUID) == false && IndexMetadata.INDEX_UUID_NA_VALUE.equals(load.indexUUID) == false) { - logger.warn("{} found shard on path: [{}] with a different index UUID - this " - + "shard seems to be leftover from a different index with the same name. " - + "Remove the leftover shard in order to reuse the path with the current index", shardId, shardPath); - throw new IllegalStateException(shardId + " index UUID in shard state was: " + load.indexUUID - + " expected: " + indexUUID + " on shard path: " + shardPath); + Path loadedPath = null; + for (Path path : availableShardPaths) { + // EMPTY is safe here because we never call namedObject + ShardStateMetadata load = ShardStateMetadata.FORMAT.loadLatestState(logger, NamedXContentRegistry.EMPTY, path); + if (load != null) { + if (load.indexUUID.equals(indexUUID) == false && IndexMetadata.INDEX_UUID_NA_VALUE.equals(load.indexUUID) == false) { + logger.warn("{} found shard on path: [{}] with a different index UUID - this " + + "shard seems to be leftover from a different index with the same name. " + + "Remove the leftover shard in order to reuse the path with the current index", shardId, path); + throw new IllegalStateException(shardId + " index UUID in shard state was: " + load.indexUUID + + " expected: " + indexUUID + " on shard path: " + path); + } + if (loadedPath == null) { + loadedPath = path; + } else{ + throw new IllegalStateException(shardId + " more than one shard state found"); + } } + + } + if (loadedPath == null) { + return null; + } else { final Path dataPath; + final Path statePath = loadedPath; final boolean hasCustomDataPath = Strings.isNotEmpty(customDataPath); if (hasCustomDataPath) { dataPath = NodeEnvironment.resolveCustomLocation(customDataPath, shardId, sharedDataPath); } else { - dataPath = shardPath; + dataPath = statePath; } - logger.debug("{} loaded data path [{}], state path [{}]", shardId, dataPath, shardPath); - return new ShardPath(hasCustomDataPath, dataPath, shardPath, shardId); + logger.debug("{} loaded data path [{}], state path [{}]", shardId, dataPath, statePath); + return new ShardPath(hasCustomDataPath, dataPath, statePath, shardId); } - return null; } /**