|  | @@ -27,6 +27,7 @@ import org.apache.logging.log4j.Logger;
 | 
	
		
			
				|  |  |  import org.apache.logging.log4j.message.ParameterizedMessage;
 | 
	
		
			
				|  |  |  import org.elasticsearch.Version;
 | 
	
		
			
				|  |  |  import org.elasticsearch.action.ActionListener;
 | 
	
		
			
				|  |  | +import org.elasticsearch.action.StepListener;
 | 
	
		
			
				|  |  |  import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotRequest;
 | 
	
		
			
				|  |  |  import org.elasticsearch.cluster.ClusterChangedEvent;
 | 
	
		
			
				|  |  |  import org.elasticsearch.cluster.ClusterState;
 | 
	
	
		
			
				|  | @@ -176,359 +177,364 @@ public class RestoreService implements ClusterStateApplier {
 | 
	
		
			
				|  |  |              // Read snapshot info and metadata from the repository
 | 
	
		
			
				|  |  |              final String repositoryName = request.repository();
 | 
	
		
			
				|  |  |              Repository repository = repositoriesService.repository(repositoryName);
 | 
	
		
			
				|  |  | -            final RepositoryData repositoryData = repository.getRepositoryData();
 | 
	
		
			
				|  |  | -            final String snapshotName = request.snapshot();
 | 
	
		
			
				|  |  | -            final Optional<SnapshotId> matchingSnapshotId = repositoryData.getSnapshotIds().stream()
 | 
	
		
			
				|  |  | -                .filter(s -> snapshotName.equals(s.getName())).findFirst();
 | 
	
		
			
				|  |  | -            if (matchingSnapshotId.isPresent() == false) {
 | 
	
		
			
				|  |  | -                throw new SnapshotRestoreException(repositoryName, snapshotName, "snapshot does not exist");
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +            final StepListener<RepositoryData> repositoryDataListener = new StepListener<>();
 | 
	
		
			
				|  |  | +            repository.getRepositoryData(repositoryDataListener);
 | 
	
		
			
				|  |  | +            repositoryDataListener.whenComplete(repositoryData -> {
 | 
	
		
			
				|  |  | +                final String snapshotName = request.snapshot();
 | 
	
		
			
				|  |  | +                final Optional<SnapshotId> matchingSnapshotId = repositoryData.getSnapshotIds().stream()
 | 
	
		
			
				|  |  | +                    .filter(s -> snapshotName.equals(s.getName())).findFirst();
 | 
	
		
			
				|  |  | +                if (matchingSnapshotId.isPresent() == false) {
 | 
	
		
			
				|  |  | +                    throw new SnapshotRestoreException(repositoryName, snapshotName, "snapshot does not exist");
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            final SnapshotId snapshotId = matchingSnapshotId.get();
 | 
	
		
			
				|  |  | -            final SnapshotInfo snapshotInfo = repository.getSnapshotInfo(snapshotId);
 | 
	
		
			
				|  |  | -            final Snapshot snapshot = new Snapshot(repositoryName, snapshotId);
 | 
	
		
			
				|  |  | +                final SnapshotId snapshotId = matchingSnapshotId.get();
 | 
	
		
			
				|  |  | +                final SnapshotInfo snapshotInfo = repository.getSnapshotInfo(snapshotId);
 | 
	
		
			
				|  |  | +                final Snapshot snapshot = new Snapshot(repositoryName, snapshotId);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            // Make sure that we can restore from this snapshot
 | 
	
		
			
				|  |  | -            validateSnapshotRestorable(repositoryName, snapshotInfo);
 | 
	
		
			
				|  |  | +                // Make sure that we can restore from this snapshot
 | 
	
		
			
				|  |  | +                validateSnapshotRestorable(repositoryName, snapshotInfo);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            // Resolve the indices from the snapshot that need to be restored
 | 
	
		
			
				|  |  | -            final List<String> indicesInSnapshot = filterIndices(snapshotInfo.indices(), request.indices(), request.indicesOptions());
 | 
	
		
			
				|  |  | +                // Resolve the indices from the snapshot that need to be restored
 | 
	
		
			
				|  |  | +                final List<String> indicesInSnapshot = filterIndices(snapshotInfo.indices(), request.indices(), request.indicesOptions());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            final MetaData.Builder metaDataBuilder;
 | 
	
		
			
				|  |  | -            if (request.includeGlobalState()) {
 | 
	
		
			
				|  |  | -                metaDataBuilder = MetaData.builder(repository.getSnapshotGlobalMetaData(snapshotId));
 | 
	
		
			
				|  |  | -            } else {
 | 
	
		
			
				|  |  | -                metaDataBuilder = MetaData.builder();
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +                final MetaData.Builder metaDataBuilder;
 | 
	
		
			
				|  |  | +                if (request.includeGlobalState()) {
 | 
	
		
			
				|  |  | +                    metaDataBuilder = MetaData.builder(repository.getSnapshotGlobalMetaData(snapshotId));
 | 
	
		
			
				|  |  | +                } else {
 | 
	
		
			
				|  |  | +                    metaDataBuilder = MetaData.builder();
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            final List<IndexId> indexIdsInSnapshot = repositoryData.resolveIndices(indicesInSnapshot);
 | 
	
		
			
				|  |  | -            for (IndexId indexId : indexIdsInSnapshot) {
 | 
	
		
			
				|  |  | -                metaDataBuilder.put(repository.getSnapshotIndexMetaData(snapshotId, indexId), false);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +                final List<IndexId> indexIdsInSnapshot = repositoryData.resolveIndices(indicesInSnapshot);
 | 
	
		
			
				|  |  | +                for (IndexId indexId : indexIdsInSnapshot) {
 | 
	
		
			
				|  |  | +                    metaDataBuilder.put(repository.getSnapshotIndexMetaData(snapshotId, indexId), false);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            final MetaData metaData = metaDataBuilder.build();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            // Apply renaming on index names, returning a map of names where
 | 
	
		
			
				|  |  | -            // the key is the renamed index and the value is the original name
 | 
	
		
			
				|  |  | -            final Map<String, String> indices = renamedIndices(request, indicesInSnapshot);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            // Now we can start the actual restore process by adding shards to be recovered in the cluster state
 | 
	
		
			
				|  |  | -            // and updating cluster metadata (global and index) as needed
 | 
	
		
			
				|  |  | -            clusterService.submitStateUpdateTask("restore_snapshot[" + snapshotName + ']', new ClusterStateUpdateTask() {
 | 
	
		
			
				|  |  | -                final String restoreUUID = UUIDs.randomBase64UUID();
 | 
	
		
			
				|  |  | -                RestoreInfo restoreInfo = null;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                @Override
 | 
	
		
			
				|  |  | -                public ClusterState execute(ClusterState currentState) {
 | 
	
		
			
				|  |  | -                    RestoreInProgress restoreInProgress = currentState.custom(RestoreInProgress.TYPE);
 | 
	
		
			
				|  |  | -                    // Check if the snapshot to restore is currently being deleted
 | 
	
		
			
				|  |  | -                    SnapshotDeletionsInProgress deletionsInProgress = currentState.custom(SnapshotDeletionsInProgress.TYPE);
 | 
	
		
			
				|  |  | -                    if (deletionsInProgress != null && deletionsInProgress.hasDeletionsInProgress()) {
 | 
	
		
			
				|  |  | -                        throw new ConcurrentSnapshotExecutionException(snapshot,
 | 
	
		
			
				|  |  | -                            "cannot restore a snapshot while a snapshot deletion is in-progress [" +
 | 
	
		
			
				|  |  | -                                deletionsInProgress.getEntries().get(0).getSnapshot() + "]");
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | +                final MetaData metaData = metaDataBuilder.build();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                // Apply renaming on index names, returning a map of names where
 | 
	
		
			
				|  |  | +                // the key is the renamed index and the value is the original name
 | 
	
		
			
				|  |  | +                final Map<String, String> indices = renamedIndices(request, indicesInSnapshot);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                // Now we can start the actual restore process by adding shards to be recovered in the cluster state
 | 
	
		
			
				|  |  | +                // and updating cluster metadata (global and index) as needed
 | 
	
		
			
				|  |  | +                clusterService.submitStateUpdateTask("restore_snapshot[" + snapshotName + ']', new ClusterStateUpdateTask() {
 | 
	
		
			
				|  |  | +                    final String restoreUUID = UUIDs.randomBase64UUID();
 | 
	
		
			
				|  |  | +                    RestoreInfo restoreInfo = null;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    @Override
 | 
	
		
			
				|  |  | +                    public ClusterState execute(ClusterState currentState) {
 | 
	
		
			
				|  |  | +                        RestoreInProgress restoreInProgress = currentState.custom(RestoreInProgress.TYPE);
 | 
	
		
			
				|  |  | +                        // Check if the snapshot to restore is currently being deleted
 | 
	
		
			
				|  |  | +                        SnapshotDeletionsInProgress deletionsInProgress = currentState.custom(SnapshotDeletionsInProgress.TYPE);
 | 
	
		
			
				|  |  | +                        if (deletionsInProgress != null && deletionsInProgress.hasDeletionsInProgress()) {
 | 
	
		
			
				|  |  | +                            throw new ConcurrentSnapshotExecutionException(snapshot,
 | 
	
		
			
				|  |  | +                                "cannot restore a snapshot while a snapshot deletion is in-progress [" +
 | 
	
		
			
				|  |  | +                                    deletionsInProgress.getEntries().get(0).getSnapshot() + "]");
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                    // Updating cluster state
 | 
	
		
			
				|  |  | -                    ClusterState.Builder builder = ClusterState.builder(currentState);
 | 
	
		
			
				|  |  | -                    MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData());
 | 
	
		
			
				|  |  | -                    ClusterBlocks.Builder blocks = ClusterBlocks.builder().blocks(currentState.blocks());
 | 
	
		
			
				|  |  | -                    RoutingTable.Builder rtBuilder = RoutingTable.builder(currentState.routingTable());
 | 
	
		
			
				|  |  | -                    ImmutableOpenMap<ShardId, RestoreInProgress.ShardRestoreStatus> shards;
 | 
	
		
			
				|  |  | -                    Set<String> aliases = new HashSet<>();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                    if (indices.isEmpty() == false) {
 | 
	
		
			
				|  |  | -                        // We have some indices to restore
 | 
	
		
			
				|  |  | -                        ImmutableOpenMap.Builder<ShardId, RestoreInProgress.ShardRestoreStatus> shardsBuilder = ImmutableOpenMap.builder();
 | 
	
		
			
				|  |  | -                        final Version minIndexCompatibilityVersion = currentState.getNodes().getMaxNodeVersion()
 | 
	
		
			
				|  |  | -                            .minimumIndexCompatibilityVersion();
 | 
	
		
			
				|  |  | -                        for (Map.Entry<String, String> indexEntry : indices.entrySet()) {
 | 
	
		
			
				|  |  | -                            String index = indexEntry.getValue();
 | 
	
		
			
				|  |  | -                            boolean partial = checkPartial(index);
 | 
	
		
			
				|  |  | -                            SnapshotRecoverySource recoverySource =
 | 
	
		
			
				|  |  | -                                new SnapshotRecoverySource(restoreUUID, snapshot, snapshotInfo.version(), index);
 | 
	
		
			
				|  |  | -                            String renamedIndexName = indexEntry.getKey();
 | 
	
		
			
				|  |  | -                            IndexMetaData snapshotIndexMetaData = metaData.index(index);
 | 
	
		
			
				|  |  | -                            snapshotIndexMetaData = updateIndexSettings(snapshotIndexMetaData,
 | 
	
		
			
				|  |  | -                                                                        request.indexSettings(), request.ignoreIndexSettings());
 | 
	
		
			
				|  |  | -                            try {
 | 
	
		
			
				|  |  | -                                snapshotIndexMetaData = metaDataIndexUpgradeService.upgradeIndexMetaData(snapshotIndexMetaData,
 | 
	
		
			
				|  |  | -                                    minIndexCompatibilityVersion);
 | 
	
		
			
				|  |  | -                            } catch (Exception ex) {
 | 
	
		
			
				|  |  | -                                throw new SnapshotRestoreException(snapshot, "cannot restore index [" + index + "] because it cannot be " +
 | 
	
		
			
				|  |  | -                                    "upgraded", ex);
 | 
	
		
			
				|  |  | -                            }
 | 
	
		
			
				|  |  | -                            // Check that the index is closed or doesn't exist
 | 
	
		
			
				|  |  | -                            IndexMetaData currentIndexMetaData = currentState.metaData().index(renamedIndexName);
 | 
	
		
			
				|  |  | -                            IntSet ignoreShards = new IntHashSet();
 | 
	
		
			
				|  |  | -                            final Index renamedIndex;
 | 
	
		
			
				|  |  | -                            if (currentIndexMetaData == null) {
 | 
	
		
			
				|  |  | -                                // Index doesn't exist - create it and start recovery
 | 
	
		
			
				|  |  | -                                // Make sure that the index we are about to create has a validate name
 | 
	
		
			
				|  |  | -                                MetaDataCreateIndexService.validateIndexName(renamedIndexName, currentState);
 | 
	
		
			
				|  |  | -                                createIndexService.validateIndexSettings(renamedIndexName, snapshotIndexMetaData.getSettings(), false);
 | 
	
		
			
				|  |  | -                                IndexMetaData.Builder indexMdBuilder = IndexMetaData.builder(snapshotIndexMetaData)
 | 
	
		
			
				|  |  | -                                                                                    .state(IndexMetaData.State.OPEN)
 | 
	
		
			
				|  |  | -                                                                                    .index(renamedIndexName);
 | 
	
		
			
				|  |  | -                                indexMdBuilder.settings(Settings.builder()
 | 
	
		
			
				|  |  | -                                                                .put(snapshotIndexMetaData.getSettings())
 | 
	
		
			
				|  |  | -                                                                .put(IndexMetaData.SETTING_INDEX_UUID, UUIDs.randomBase64UUID()));
 | 
	
		
			
				|  |  | -                                MetaDataCreateIndexService.checkShardLimit(snapshotIndexMetaData.getSettings(), currentState);
 | 
	
		
			
				|  |  | -                                if (!request.includeAliases() && !snapshotIndexMetaData.getAliases().isEmpty()) {
 | 
	
		
			
				|  |  | -                                    // Remove all aliases - they shouldn't be restored
 | 
	
		
			
				|  |  | -                                    indexMdBuilder.removeAllAliases();
 | 
	
		
			
				|  |  | -                                } else {
 | 
	
		
			
				|  |  | -                                    for (ObjectCursor<String> alias : snapshotIndexMetaData.getAliases().keys()) {
 | 
	
		
			
				|  |  | -                                        aliases.add(alias.value);
 | 
	
		
			
				|  |  | -                                    }
 | 
	
		
			
				|  |  | -                                }
 | 
	
		
			
				|  |  | -                                IndexMetaData updatedIndexMetaData = indexMdBuilder.build();
 | 
	
		
			
				|  |  | -                                if (partial) {
 | 
	
		
			
				|  |  | -                                    populateIgnoredShards(index, ignoreShards);
 | 
	
		
			
				|  |  | +                        // Updating cluster state
 | 
	
		
			
				|  |  | +                        ClusterState.Builder builder = ClusterState.builder(currentState);
 | 
	
		
			
				|  |  | +                        MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData());
 | 
	
		
			
				|  |  | +                        ClusterBlocks.Builder blocks = ClusterBlocks.builder().blocks(currentState.blocks());
 | 
	
		
			
				|  |  | +                        RoutingTable.Builder rtBuilder = RoutingTable.builder(currentState.routingTable());
 | 
	
		
			
				|  |  | +                        ImmutableOpenMap<ShardId, RestoreInProgress.ShardRestoreStatus> shards;
 | 
	
		
			
				|  |  | +                        Set<String> aliases = new HashSet<>();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                        if (indices.isEmpty() == false) {
 | 
	
		
			
				|  |  | +                            // We have some indices to restore
 | 
	
		
			
				|  |  | +                            ImmutableOpenMap.Builder<ShardId, RestoreInProgress.ShardRestoreStatus> shardsBuilder =
 | 
	
		
			
				|  |  | +                                ImmutableOpenMap.builder();
 | 
	
		
			
				|  |  | +                            final Version minIndexCompatibilityVersion = currentState.getNodes().getMaxNodeVersion()
 | 
	
		
			
				|  |  | +                                .minimumIndexCompatibilityVersion();
 | 
	
		
			
				|  |  | +                            for (Map.Entry<String, String> indexEntry : indices.entrySet()) {
 | 
	
		
			
				|  |  | +                                String index = indexEntry.getValue();
 | 
	
		
			
				|  |  | +                                boolean partial = checkPartial(index);
 | 
	
		
			
				|  |  | +                                SnapshotRecoverySource recoverySource =
 | 
	
		
			
				|  |  | +                                    new SnapshotRecoverySource(restoreUUID, snapshot, snapshotInfo.version(), index);
 | 
	
		
			
				|  |  | +                                String renamedIndexName = indexEntry.getKey();
 | 
	
		
			
				|  |  | +                                IndexMetaData snapshotIndexMetaData = metaData.index(index);
 | 
	
		
			
				|  |  | +                                snapshotIndexMetaData = updateIndexSettings(snapshotIndexMetaData,
 | 
	
		
			
				|  |  | +                                    request.indexSettings(), request.ignoreIndexSettings());
 | 
	
		
			
				|  |  | +                                try {
 | 
	
		
			
				|  |  | +                                    snapshotIndexMetaData = metaDataIndexUpgradeService.upgradeIndexMetaData(snapshotIndexMetaData,
 | 
	
		
			
				|  |  | +                                        minIndexCompatibilityVersion);
 | 
	
		
			
				|  |  | +                                } catch (Exception ex) {
 | 
	
		
			
				|  |  | +                                    throw new SnapshotRestoreException(snapshot, "cannot restore index [" + index +
 | 
	
		
			
				|  |  | +                                        "] because it cannot be upgraded", ex);
 | 
	
		
			
				|  |  |                                  }
 | 
	
		
			
				|  |  | -                                rtBuilder.addAsNewRestore(updatedIndexMetaData, recoverySource, ignoreShards);
 | 
	
		
			
				|  |  | -                                blocks.addBlocks(updatedIndexMetaData);
 | 
	
		
			
				|  |  | -                                mdBuilder.put(updatedIndexMetaData, true);
 | 
	
		
			
				|  |  | -                                renamedIndex = updatedIndexMetaData.getIndex();
 | 
	
		
			
				|  |  | -                            } else {
 | 
	
		
			
				|  |  | -                                validateExistingIndex(currentIndexMetaData, snapshotIndexMetaData, renamedIndexName, partial);
 | 
	
		
			
				|  |  | -                                // Index exists and it's closed - open it in metadata and start recovery
 | 
	
		
			
				|  |  | -                                IndexMetaData.Builder indexMdBuilder =
 | 
	
		
			
				|  |  | +                                // Check that the index is closed or doesn't exist
 | 
	
		
			
				|  |  | +                                IndexMetaData currentIndexMetaData = currentState.metaData().index(renamedIndexName);
 | 
	
		
			
				|  |  | +                                IntSet ignoreShards = new IntHashSet();
 | 
	
		
			
				|  |  | +                                final Index renamedIndex;
 | 
	
		
			
				|  |  | +                                if (currentIndexMetaData == null) {
 | 
	
		
			
				|  |  | +                                    // Index doesn't exist - create it and start recovery
 | 
	
		
			
				|  |  | +                                    // Make sure that the index we are about to create has a validate name
 | 
	
		
			
				|  |  | +                                    MetaDataCreateIndexService.validateIndexName(renamedIndexName, currentState);
 | 
	
		
			
				|  |  | +                                    createIndexService.validateIndexSettings(renamedIndexName, snapshotIndexMetaData.getSettings(), false);
 | 
	
		
			
				|  |  | +                                    IndexMetaData.Builder indexMdBuilder = IndexMetaData.builder(snapshotIndexMetaData)
 | 
	
		
			
				|  |  | +                                        .state(IndexMetaData.State.OPEN)
 | 
	
		
			
				|  |  | +                                        .index(renamedIndexName);
 | 
	
		
			
				|  |  | +                                    indexMdBuilder.settings(Settings.builder()
 | 
	
		
			
				|  |  | +                                        .put(snapshotIndexMetaData.getSettings())
 | 
	
		
			
				|  |  | +                                        .put(IndexMetaData.SETTING_INDEX_UUID, UUIDs.randomBase64UUID()));
 | 
	
		
			
				|  |  | +                                    MetaDataCreateIndexService.checkShardLimit(snapshotIndexMetaData.getSettings(), currentState);
 | 
	
		
			
				|  |  | +                                    if (!request.includeAliases() && !snapshotIndexMetaData.getAliases().isEmpty()) {
 | 
	
		
			
				|  |  | +                                        // Remove all aliases - they shouldn't be restored
 | 
	
		
			
				|  |  | +                                        indexMdBuilder.removeAllAliases();
 | 
	
		
			
				|  |  | +                                    } else {
 | 
	
		
			
				|  |  | +                                        for (ObjectCursor<String> alias : snapshotIndexMetaData.getAliases().keys()) {
 | 
	
		
			
				|  |  | +                                            aliases.add(alias.value);
 | 
	
		
			
				|  |  | +                                        }
 | 
	
		
			
				|  |  | +                                    }
 | 
	
		
			
				|  |  | +                                    IndexMetaData updatedIndexMetaData = indexMdBuilder.build();
 | 
	
		
			
				|  |  | +                                    if (partial) {
 | 
	
		
			
				|  |  | +                                        populateIgnoredShards(index, ignoreShards);
 | 
	
		
			
				|  |  | +                                    }
 | 
	
		
			
				|  |  | +                                    rtBuilder.addAsNewRestore(updatedIndexMetaData, recoverySource, ignoreShards);
 | 
	
		
			
				|  |  | +                                    blocks.addBlocks(updatedIndexMetaData);
 | 
	
		
			
				|  |  | +                                    mdBuilder.put(updatedIndexMetaData, true);
 | 
	
		
			
				|  |  | +                                    renamedIndex = updatedIndexMetaData.getIndex();
 | 
	
		
			
				|  |  | +                                } else {
 | 
	
		
			
				|  |  | +                                    validateExistingIndex(currentIndexMetaData, snapshotIndexMetaData, renamedIndexName, partial);
 | 
	
		
			
				|  |  | +                                    // Index exists and it's closed - open it in metadata and start recovery
 | 
	
		
			
				|  |  | +                                    IndexMetaData.Builder indexMdBuilder =
 | 
	
		
			
				|  |  |                                          IndexMetaData.builder(snapshotIndexMetaData).state(IndexMetaData.State.OPEN);
 | 
	
		
			
				|  |  | -                                indexMdBuilder.version(
 | 
	
		
			
				|  |  | +                                    indexMdBuilder.version(
 | 
	
		
			
				|  |  |                                          Math.max(snapshotIndexMetaData.getVersion(), 1 + currentIndexMetaData.getVersion()));
 | 
	
		
			
				|  |  | -                                indexMdBuilder.mappingVersion(
 | 
	
		
			
				|  |  | +                                    indexMdBuilder.mappingVersion(
 | 
	
		
			
				|  |  |                                          Math.max(snapshotIndexMetaData.getMappingVersion(), 1 + currentIndexMetaData.getMappingVersion()));
 | 
	
		
			
				|  |  | -                                indexMdBuilder.settingsVersion(
 | 
	
		
			
				|  |  | +                                    indexMdBuilder.settingsVersion(
 | 
	
		
			
				|  |  |                                          Math.max(
 | 
	
		
			
				|  |  | -                                                snapshotIndexMetaData.getSettingsVersion(),
 | 
	
		
			
				|  |  | -                                                1 + currentIndexMetaData.getSettingsVersion()));
 | 
	
		
			
				|  |  | -                                indexMdBuilder.aliasesVersion(
 | 
	
		
			
				|  |  | +                                            snapshotIndexMetaData.getSettingsVersion(),
 | 
	
		
			
				|  |  | +                                            1 + currentIndexMetaData.getSettingsVersion()));
 | 
	
		
			
				|  |  | +                                    indexMdBuilder.aliasesVersion(
 | 
	
		
			
				|  |  |                                          Math.max(snapshotIndexMetaData.getAliasesVersion(), 1 + currentIndexMetaData.getAliasesVersion()));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                                for (int shard = 0; shard < snapshotIndexMetaData.getNumberOfShards(); shard++) {
 | 
	
		
			
				|  |  | -                                    indexMdBuilder.primaryTerm(shard,
 | 
	
		
			
				|  |  | -                                        Math.max(snapshotIndexMetaData.primaryTerm(shard), currentIndexMetaData.primaryTerm(shard)));
 | 
	
		
			
				|  |  | -                                }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                                if (!request.includeAliases()) {
 | 
	
		
			
				|  |  | -                                    // Remove all snapshot aliases
 | 
	
		
			
				|  |  | -                                    if (!snapshotIndexMetaData.getAliases().isEmpty()) {
 | 
	
		
			
				|  |  | -                                        indexMdBuilder.removeAllAliases();
 | 
	
		
			
				|  |  | +                                    for (int shard = 0; shard < snapshotIndexMetaData.getNumberOfShards(); shard++) {
 | 
	
		
			
				|  |  | +                                        indexMdBuilder.primaryTerm(shard,
 | 
	
		
			
				|  |  | +                                            Math.max(snapshotIndexMetaData.primaryTerm(shard), currentIndexMetaData.primaryTerm(shard)));
 | 
	
		
			
				|  |  |                                      }
 | 
	
		
			
				|  |  | -                                    /// Add existing aliases
 | 
	
		
			
				|  |  | -                                    for (ObjectCursor<AliasMetaData> alias : currentIndexMetaData.getAliases().values()) {
 | 
	
		
			
				|  |  | -                                        indexMdBuilder.putAlias(alias.value);
 | 
	
		
			
				|  |  | -                                    }
 | 
	
		
			
				|  |  | -                                } else {
 | 
	
		
			
				|  |  | -                                    for (ObjectCursor<String> alias : snapshotIndexMetaData.getAliases().keys()) {
 | 
	
		
			
				|  |  | -                                        aliases.add(alias.value);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                                    if (!request.includeAliases()) {
 | 
	
		
			
				|  |  | +                                        // Remove all snapshot aliases
 | 
	
		
			
				|  |  | +                                        if (!snapshotIndexMetaData.getAliases().isEmpty()) {
 | 
	
		
			
				|  |  | +                                            indexMdBuilder.removeAllAliases();
 | 
	
		
			
				|  |  | +                                        }
 | 
	
		
			
				|  |  | +                                        /// Add existing aliases
 | 
	
		
			
				|  |  | +                                        for (ObjectCursor<AliasMetaData> alias : currentIndexMetaData.getAliases().values()) {
 | 
	
		
			
				|  |  | +                                            indexMdBuilder.putAlias(alias.value);
 | 
	
		
			
				|  |  | +                                        }
 | 
	
		
			
				|  |  | +                                    } else {
 | 
	
		
			
				|  |  | +                                        for (ObjectCursor<String> alias : snapshotIndexMetaData.getAliases().keys()) {
 | 
	
		
			
				|  |  | +                                            aliases.add(alias.value);
 | 
	
		
			
				|  |  | +                                        }
 | 
	
		
			
				|  |  |                                      }
 | 
	
		
			
				|  |  | +                                    indexMdBuilder.settings(Settings.builder()
 | 
	
		
			
				|  |  | +                                        .put(snapshotIndexMetaData.getSettings())
 | 
	
		
			
				|  |  | +                                        .put(IndexMetaData.SETTING_INDEX_UUID,
 | 
	
		
			
				|  |  | +                                            currentIndexMetaData.getIndexUUID()));
 | 
	
		
			
				|  |  | +                                    IndexMetaData updatedIndexMetaData = indexMdBuilder.index(renamedIndexName).build();
 | 
	
		
			
				|  |  | +                                    rtBuilder.addAsRestore(updatedIndexMetaData, recoverySource);
 | 
	
		
			
				|  |  | +                                    blocks.updateBlocks(updatedIndexMetaData);
 | 
	
		
			
				|  |  | +                                    mdBuilder.put(updatedIndexMetaData, true);
 | 
	
		
			
				|  |  | +                                    renamedIndex = updatedIndexMetaData.getIndex();
 | 
	
		
			
				|  |  |                                  }
 | 
	
		
			
				|  |  | -                                indexMdBuilder.settings(Settings.builder()
 | 
	
		
			
				|  |  | -                                                                .put(snapshotIndexMetaData.getSettings())
 | 
	
		
			
				|  |  | -                                                                .put(IndexMetaData.SETTING_INDEX_UUID,
 | 
	
		
			
				|  |  | -                                                                    currentIndexMetaData.getIndexUUID()));
 | 
	
		
			
				|  |  | -                                IndexMetaData updatedIndexMetaData = indexMdBuilder.index(renamedIndexName).build();
 | 
	
		
			
				|  |  | -                                rtBuilder.addAsRestore(updatedIndexMetaData, recoverySource);
 | 
	
		
			
				|  |  | -                                blocks.updateBlocks(updatedIndexMetaData);
 | 
	
		
			
				|  |  | -                                mdBuilder.put(updatedIndexMetaData, true);
 | 
	
		
			
				|  |  | -                                renamedIndex = updatedIndexMetaData.getIndex();
 | 
	
		
			
				|  |  | -                            }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                            for (int shard = 0; shard < snapshotIndexMetaData.getNumberOfShards(); shard++) {
 | 
	
		
			
				|  |  | -                                if (!ignoreShards.contains(shard)) {
 | 
	
		
			
				|  |  | -                                    shardsBuilder.put(new ShardId(renamedIndex, shard),
 | 
	
		
			
				|  |  | +                                for (int shard = 0; shard < snapshotIndexMetaData.getNumberOfShards(); shard++) {
 | 
	
		
			
				|  |  | +                                    if (!ignoreShards.contains(shard)) {
 | 
	
		
			
				|  |  | +                                        shardsBuilder.put(new ShardId(renamedIndex, shard),
 | 
	
		
			
				|  |  |                                              new RestoreInProgress.ShardRestoreStatus(clusterService.state().nodes().getLocalNodeId()));
 | 
	
		
			
				|  |  | -                                } else {
 | 
	
		
			
				|  |  | -                                    shardsBuilder.put(new ShardId(renamedIndex, shard),
 | 
	
		
			
				|  |  | +                                    } else {
 | 
	
		
			
				|  |  | +                                        shardsBuilder.put(new ShardId(renamedIndex, shard),
 | 
	
		
			
				|  |  |                                              new RestoreInProgress.ShardRestoreStatus(clusterService.state().nodes().getLocalNodeId(),
 | 
	
		
			
				|  |  |                                                  RestoreInProgress.State.FAILURE));
 | 
	
		
			
				|  |  | +                                    }
 | 
	
		
			
				|  |  |                                  }
 | 
	
		
			
				|  |  |                              }
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                        shards = shardsBuilder.build();
 | 
	
		
			
				|  |  | -                        RestoreInProgress.Entry restoreEntry = new RestoreInProgress.Entry(
 | 
	
		
			
				|  |  | -                            restoreUUID, snapshot, overallState(RestoreInProgress.State.INIT, shards),
 | 
	
		
			
				|  |  | -                            List.copyOf(indices.keySet()),
 | 
	
		
			
				|  |  | -                            shards
 | 
	
		
			
				|  |  | -                        );
 | 
	
		
			
				|  |  | -                        RestoreInProgress.Builder restoreInProgressBuilder;
 | 
	
		
			
				|  |  | -                        if (restoreInProgress != null) {
 | 
	
		
			
				|  |  | -                            restoreInProgressBuilder = new RestoreInProgress.Builder(restoreInProgress);
 | 
	
		
			
				|  |  | +                            shards = shardsBuilder.build();
 | 
	
		
			
				|  |  | +                            RestoreInProgress.Entry restoreEntry = new RestoreInProgress.Entry(
 | 
	
		
			
				|  |  | +                                restoreUUID, snapshot, overallState(RestoreInProgress.State.INIT, shards),
 | 
	
		
			
				|  |  | +                                List.copyOf(indices.keySet()),
 | 
	
		
			
				|  |  | +                                shards
 | 
	
		
			
				|  |  | +                            );
 | 
	
		
			
				|  |  | +                            RestoreInProgress.Builder restoreInProgressBuilder;
 | 
	
		
			
				|  |  | +                            if (restoreInProgress != null) {
 | 
	
		
			
				|  |  | +                                restoreInProgressBuilder = new RestoreInProgress.Builder(restoreInProgress);
 | 
	
		
			
				|  |  | +                            } else {
 | 
	
		
			
				|  |  | +                                restoreInProgressBuilder = new RestoreInProgress.Builder();
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                            builder.putCustom(RestoreInProgress.TYPE, restoreInProgressBuilder.add(restoreEntry).build());
 | 
	
		
			
				|  |  |                          } else {
 | 
	
		
			
				|  |  | -                            restoreInProgressBuilder = new RestoreInProgress.Builder();
 | 
	
		
			
				|  |  | +                            shards = ImmutableOpenMap.of();
 | 
	
		
			
				|  |  |                          }
 | 
	
		
			
				|  |  | -                        builder.putCustom(RestoreInProgress.TYPE, restoreInProgressBuilder.add(restoreEntry).build());
 | 
	
		
			
				|  |  | -                    } else {
 | 
	
		
			
				|  |  | -                        shards = ImmutableOpenMap.of();
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                    checkAliasNameConflicts(indices, aliases);
 | 
	
		
			
				|  |  | +                        checkAliasNameConflicts(indices, aliases);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                    // Restore global state if needed
 | 
	
		
			
				|  |  | -                    if (request.includeGlobalState()) {
 | 
	
		
			
				|  |  | -                        if (metaData.persistentSettings() != null) {
 | 
	
		
			
				|  |  | -                            Settings settings = metaData.persistentSettings();
 | 
	
		
			
				|  |  | -                            clusterSettings.validateUpdate(settings);
 | 
	
		
			
				|  |  | -                            mdBuilder.persistentSettings(settings);
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  | -                        if (metaData.templates() != null) {
 | 
	
		
			
				|  |  | -                            // TODO: Should all existing templates be deleted first?
 | 
	
		
			
				|  |  | -                            for (ObjectCursor<IndexTemplateMetaData> cursor : metaData.templates().values()) {
 | 
	
		
			
				|  |  | -                                mdBuilder.put(cursor.value);
 | 
	
		
			
				|  |  | +                        // Restore global state if needed
 | 
	
		
			
				|  |  | +                        if (request.includeGlobalState()) {
 | 
	
		
			
				|  |  | +                            if (metaData.persistentSettings() != null) {
 | 
	
		
			
				|  |  | +                                Settings settings = metaData.persistentSettings();
 | 
	
		
			
				|  |  | +                                clusterSettings.validateUpdate(settings);
 | 
	
		
			
				|  |  | +                                mdBuilder.persistentSettings(settings);
 | 
	
		
			
				|  |  |                              }
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  | -                        if (metaData.customs() != null) {
 | 
	
		
			
				|  |  | -                            for (ObjectObjectCursor<String, MetaData.Custom> cursor : metaData.customs()) {
 | 
	
		
			
				|  |  | -                                if (!RepositoriesMetaData.TYPE.equals(cursor.key)) {
 | 
	
		
			
				|  |  | -                                    // Don't restore repositories while we are working with them
 | 
	
		
			
				|  |  | -                                    // TODO: Should we restore them at the end?
 | 
	
		
			
				|  |  | -                                    mdBuilder.putCustom(cursor.key, cursor.value);
 | 
	
		
			
				|  |  | +                            if (metaData.templates() != null) {
 | 
	
		
			
				|  |  | +                                // TODO: Should all existing templates be deleted first?
 | 
	
		
			
				|  |  | +                                for (ObjectCursor<IndexTemplateMetaData> cursor : metaData.templates().values()) {
 | 
	
		
			
				|  |  | +                                    mdBuilder.put(cursor.value);
 | 
	
		
			
				|  |  | +                                }
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                            if (metaData.customs() != null) {
 | 
	
		
			
				|  |  | +                                for (ObjectObjectCursor<String, MetaData.Custom> cursor : metaData.customs()) {
 | 
	
		
			
				|  |  | +                                    if (!RepositoriesMetaData.TYPE.equals(cursor.key)) {
 | 
	
		
			
				|  |  | +                                        // Don't restore repositories while we are working with them
 | 
	
		
			
				|  |  | +                                        // TODO: Should we restore them at the end?
 | 
	
		
			
				|  |  | +                                        mdBuilder.putCustom(cursor.key, cursor.value);
 | 
	
		
			
				|  |  | +                                    }
 | 
	
		
			
				|  |  |                                  }
 | 
	
		
			
				|  |  |                              }
 | 
	
		
			
				|  |  |                          }
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                    if (completed(shards)) {
 | 
	
		
			
				|  |  | -                        // We don't have any indices to restore - we are done
 | 
	
		
			
				|  |  | -                        restoreInfo = new RestoreInfo(snapshotId.getName(),
 | 
	
		
			
				|  |  | -                                                      List.copyOf(indices.keySet()),
 | 
	
		
			
				|  |  | -                                                      shards.size(),
 | 
	
		
			
				|  |  | -                                                      shards.size() - failedShards(shards));
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | +                        if (completed(shards)) {
 | 
	
		
			
				|  |  | +                            // We don't have any indices to restore - we are done
 | 
	
		
			
				|  |  | +                            restoreInfo = new RestoreInfo(snapshotId.getName(),
 | 
	
		
			
				|  |  | +                                List.copyOf(indices.keySet()),
 | 
	
		
			
				|  |  | +                                shards.size(),
 | 
	
		
			
				|  |  | +                                shards.size() - failedShards(shards));
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                    RoutingTable rt = rtBuilder.build();
 | 
	
		
			
				|  |  | -                    ClusterState updatedState = builder.metaData(mdBuilder).blocks(blocks).routingTable(rt).build();
 | 
	
		
			
				|  |  | -                    return allocationService.reroute(updatedState, "restored snapshot [" + snapshot + "]");
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | +                        RoutingTable rt = rtBuilder.build();
 | 
	
		
			
				|  |  | +                        ClusterState updatedState = builder.metaData(mdBuilder).blocks(blocks).routingTable(rt).build();
 | 
	
		
			
				|  |  | +                        return allocationService.reroute(updatedState, "restored snapshot [" + snapshot + "]");
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                private void checkAliasNameConflicts(Map<String, String> renamedIndices, Set<String> aliases) {
 | 
	
		
			
				|  |  | -                    for (Map.Entry<String, String> renamedIndex : renamedIndices.entrySet()) {
 | 
	
		
			
				|  |  | -                        if (aliases.contains(renamedIndex.getKey())) {
 | 
	
		
			
				|  |  | -                            throw new SnapshotRestoreException(snapshot,
 | 
	
		
			
				|  |  | -                                "cannot rename index [" + renamedIndex.getValue() + "] into [" + renamedIndex.getKey() + "] because of " +
 | 
	
		
			
				|  |  | -                                    "conflict with an alias with the same name");
 | 
	
		
			
				|  |  | +                    private void checkAliasNameConflicts(Map<String, String> renamedIndices, Set<String> aliases) {
 | 
	
		
			
				|  |  | +                        for (Map.Entry<String, String> renamedIndex : renamedIndices.entrySet()) {
 | 
	
		
			
				|  |  | +                            if (aliases.contains(renamedIndex.getKey())) {
 | 
	
		
			
				|  |  | +                                throw new SnapshotRestoreException(snapshot,
 | 
	
		
			
				|  |  | +                                    "cannot rename index [" + renamedIndex.getValue() + "] into [" + renamedIndex.getKey()
 | 
	
		
			
				|  |  | +                                        + "] because of conflict with an alias with the same name");
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  |                          }
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                private void populateIgnoredShards(String index, IntSet ignoreShards) {
 | 
	
		
			
				|  |  | -                    for (SnapshotShardFailure failure : snapshotInfo.shardFailures()) {
 | 
	
		
			
				|  |  | -                        if (index.equals(failure.index())) {
 | 
	
		
			
				|  |  | -                            ignoreShards.add(failure.shardId());
 | 
	
		
			
				|  |  | +                    private void populateIgnoredShards(String index, IntSet ignoreShards) {
 | 
	
		
			
				|  |  | +                        for (SnapshotShardFailure failure : snapshotInfo.shardFailures()) {
 | 
	
		
			
				|  |  | +                            if (index.equals(failure.index())) {
 | 
	
		
			
				|  |  | +                                ignoreShards.add(failure.shardId());
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  |                          }
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                private boolean checkPartial(String index) {
 | 
	
		
			
				|  |  | -                    // Make sure that index was fully snapshotted
 | 
	
		
			
				|  |  | -                    if (failed(snapshotInfo, index)) {
 | 
	
		
			
				|  |  | -                        if (request.partial()) {
 | 
	
		
			
				|  |  | -                            return true;
 | 
	
		
			
				|  |  | +                    private boolean checkPartial(String index) {
 | 
	
		
			
				|  |  | +                        // Make sure that index was fully snapshotted
 | 
	
		
			
				|  |  | +                        if (failed(snapshotInfo, index)) {
 | 
	
		
			
				|  |  | +                            if (request.partial()) {
 | 
	
		
			
				|  |  | +                                return true;
 | 
	
		
			
				|  |  | +                            } else {
 | 
	
		
			
				|  |  | +                                throw new SnapshotRestoreException(snapshot, "index [" + index + "] wasn't fully snapshotted - cannot " +
 | 
	
		
			
				|  |  | +                                    "restore");
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  |                          } else {
 | 
	
		
			
				|  |  | -                            throw new SnapshotRestoreException(snapshot, "index [" + index + "] wasn't fully snapshotted - cannot " +
 | 
	
		
			
				|  |  | -                                "restore");
 | 
	
		
			
				|  |  | +                            return false;
 | 
	
		
			
				|  |  |                          }
 | 
	
		
			
				|  |  | -                    } else {
 | 
	
		
			
				|  |  | -                        return false;
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                private void validateExistingIndex(IndexMetaData currentIndexMetaData, IndexMetaData snapshotIndexMetaData,
 | 
	
		
			
				|  |  | -                                                   String renamedIndex, boolean partial) {
 | 
	
		
			
				|  |  | -                    // Index exist - checking that it's closed
 | 
	
		
			
				|  |  | -                    if (currentIndexMetaData.getState() != IndexMetaData.State.CLOSE) {
 | 
	
		
			
				|  |  | -                        // TODO: Enable restore for open indices
 | 
	
		
			
				|  |  | -                        throw new SnapshotRestoreException(snapshot, "cannot restore index [" + renamedIndex + "] because an open index " +
 | 
	
		
			
				|  |  | -                            "with same name already exists in the cluster. Either close or delete the existing index or restore the " +
 | 
	
		
			
				|  |  | -                            "index under a different name by providing a rename pattern and replacement name");
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    // Index exist - checking if it's partial restore
 | 
	
		
			
				|  |  | -                    if (partial) {
 | 
	
		
			
				|  |  | -                        throw new SnapshotRestoreException(snapshot, "cannot restore partial index [" + renamedIndex + "] because such " +
 | 
	
		
			
				|  |  | -                            "index already exists");
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    // Make sure that the number of shards is the same. That's the only thing that we cannot change
 | 
	
		
			
				|  |  | -                    if (currentIndexMetaData.getNumberOfShards() != snapshotIndexMetaData.getNumberOfShards()) {
 | 
	
		
			
				|  |  | -                        throw new SnapshotRestoreException(snapshot,
 | 
	
		
			
				|  |  | -                            "cannot restore index [" + renamedIndex + "] with [" + currentIndexMetaData.getNumberOfShards() + "] shards " +
 | 
	
		
			
				|  |  | -                                "from a snapshot of index [" + snapshotIndexMetaData.getIndex().getName() + "] with [" +
 | 
	
		
			
				|  |  | -                                snapshotIndexMetaData.getNumberOfShards() + "] shards");
 | 
	
		
			
				|  |  | +                    private void validateExistingIndex(IndexMetaData currentIndexMetaData, IndexMetaData snapshotIndexMetaData,
 | 
	
		
			
				|  |  | +                        String renamedIndex, boolean partial) {
 | 
	
		
			
				|  |  | +                        // Index exist - checking that it's closed
 | 
	
		
			
				|  |  | +                        if (currentIndexMetaData.getState() != IndexMetaData.State.CLOSE) {
 | 
	
		
			
				|  |  | +                            // TODO: Enable restore for open indices
 | 
	
		
			
				|  |  | +                            throw new SnapshotRestoreException(snapshot, "cannot restore index [" + renamedIndex
 | 
	
		
			
				|  |  | +                                + "] because an open index " +
 | 
	
		
			
				|  |  | +                                "with same name already exists in the cluster. Either close or delete the existing index or restore the " +
 | 
	
		
			
				|  |  | +                                "index under a different name by providing a rename pattern and replacement name");
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                        // Index exist - checking if it's partial restore
 | 
	
		
			
				|  |  | +                        if (partial) {
 | 
	
		
			
				|  |  | +                            throw new SnapshotRestoreException(snapshot, "cannot restore partial index [" + renamedIndex
 | 
	
		
			
				|  |  | +                                + "] because such index already exists");
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                        // Make sure that the number of shards is the same. That's the only thing that we cannot change
 | 
	
		
			
				|  |  | +                        if (currentIndexMetaData.getNumberOfShards() != snapshotIndexMetaData.getNumberOfShards()) {
 | 
	
		
			
				|  |  | +                            throw new SnapshotRestoreException(snapshot,
 | 
	
		
			
				|  |  | +                                "cannot restore index [" + renamedIndex + "] with [" + currentIndexMetaData.getNumberOfShards()
 | 
	
		
			
				|  |  | +                                    + "] shards from a snapshot of index [" + snapshotIndexMetaData.getIndex().getName() + "] with [" +
 | 
	
		
			
				|  |  | +                                    snapshotIndexMetaData.getNumberOfShards() + "] shards");
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                /**
 | 
	
		
			
				|  |  | -                 * Optionally updates index settings in indexMetaData by removing settings listed in ignoreSettings and
 | 
	
		
			
				|  |  | -                 * merging them with settings in changeSettings.
 | 
	
		
			
				|  |  | -                 */
 | 
	
		
			
				|  |  | -                private IndexMetaData updateIndexSettings(IndexMetaData indexMetaData, Settings changeSettings, String[] ignoreSettings) {
 | 
	
		
			
				|  |  | -                    Settings normalizedChangeSettings = Settings.builder()
 | 
	
		
			
				|  |  | -                                                                .put(changeSettings)
 | 
	
		
			
				|  |  | -                                                                .normalizePrefix(IndexMetaData.INDEX_SETTING_PREFIX)
 | 
	
		
			
				|  |  | -                                                                .build();
 | 
	
		
			
				|  |  | -                    IndexMetaData.Builder builder = IndexMetaData.builder(indexMetaData);
 | 
	
		
			
				|  |  | -                    Settings settings = indexMetaData.getSettings();
 | 
	
		
			
				|  |  | -                    Set<String> keyFilters = new HashSet<>();
 | 
	
		
			
				|  |  | -                    List<String> simpleMatchPatterns = new ArrayList<>();
 | 
	
		
			
				|  |  | -                    for (String ignoredSetting : ignoreSettings) {
 | 
	
		
			
				|  |  | -                        if (!Regex.isSimpleMatchPattern(ignoredSetting)) {
 | 
	
		
			
				|  |  | -                            if (UNREMOVABLE_SETTINGS.contains(ignoredSetting)) {
 | 
	
		
			
				|  |  | -                                throw new SnapshotRestoreException(snapshot, "cannot remove setting [" + ignoredSetting + "] on restore");
 | 
	
		
			
				|  |  | +                    /**
 | 
	
		
			
				|  |  | +                     * Optionally updates index settings in indexMetaData by removing settings listed in ignoreSettings and
 | 
	
		
			
				|  |  | +                     * merging them with settings in changeSettings.
 | 
	
		
			
				|  |  | +                     */
 | 
	
		
			
				|  |  | +                    private IndexMetaData updateIndexSettings(IndexMetaData indexMetaData, Settings changeSettings,
 | 
	
		
			
				|  |  | +                                                              String[] ignoreSettings) {
 | 
	
		
			
				|  |  | +                        Settings normalizedChangeSettings = Settings.builder()
 | 
	
		
			
				|  |  | +                            .put(changeSettings)
 | 
	
		
			
				|  |  | +                            .normalizePrefix(IndexMetaData.INDEX_SETTING_PREFIX)
 | 
	
		
			
				|  |  | +                            .build();
 | 
	
		
			
				|  |  | +                        IndexMetaData.Builder builder = IndexMetaData.builder(indexMetaData);
 | 
	
		
			
				|  |  | +                        Settings settings = indexMetaData.getSettings();
 | 
	
		
			
				|  |  | +                        Set<String> keyFilters = new HashSet<>();
 | 
	
		
			
				|  |  | +                        List<String> simpleMatchPatterns = new ArrayList<>();
 | 
	
		
			
				|  |  | +                        for (String ignoredSetting : ignoreSettings) {
 | 
	
		
			
				|  |  | +                            if (!Regex.isSimpleMatchPattern(ignoredSetting)) {
 | 
	
		
			
				|  |  | +                                if (UNREMOVABLE_SETTINGS.contains(ignoredSetting)) {
 | 
	
		
			
				|  |  | +                                    throw new SnapshotRestoreException(
 | 
	
		
			
				|  |  | +                                        snapshot, "cannot remove setting [" + ignoredSetting + "] on restore");
 | 
	
		
			
				|  |  | +                                } else {
 | 
	
		
			
				|  |  | +                                    keyFilters.add(ignoredSetting);
 | 
	
		
			
				|  |  | +                                }
 | 
	
		
			
				|  |  |                              } else {
 | 
	
		
			
				|  |  | -                                keyFilters.add(ignoredSetting);
 | 
	
		
			
				|  |  | +                                simpleMatchPatterns.add(ignoredSetting);
 | 
	
		
			
				|  |  |                              }
 | 
	
		
			
				|  |  | -                        } else {
 | 
	
		
			
				|  |  | -                            simpleMatchPatterns.add(ignoredSetting);
 | 
	
		
			
				|  |  |                          }
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    Predicate<String> settingsFilter = k -> {
 | 
	
		
			
				|  |  | -                        if (UNREMOVABLE_SETTINGS.contains(k) == false) {
 | 
	
		
			
				|  |  | -                            for (String filterKey : keyFilters) {
 | 
	
		
			
				|  |  | -                                if (k.equals(filterKey)) {
 | 
	
		
			
				|  |  | -                                    return false;
 | 
	
		
			
				|  |  | +                        Predicate<String> settingsFilter = k -> {
 | 
	
		
			
				|  |  | +                            if (UNREMOVABLE_SETTINGS.contains(k) == false) {
 | 
	
		
			
				|  |  | +                                for (String filterKey : keyFilters) {
 | 
	
		
			
				|  |  | +                                    if (k.equals(filterKey)) {
 | 
	
		
			
				|  |  | +                                        return false;
 | 
	
		
			
				|  |  | +                                    }
 | 
	
		
			
				|  |  |                                  }
 | 
	
		
			
				|  |  | -                            }
 | 
	
		
			
				|  |  | -                            for (String pattern : simpleMatchPatterns) {
 | 
	
		
			
				|  |  | -                                if (Regex.simpleMatch(pattern, k)) {
 | 
	
		
			
				|  |  | -                                    return false;
 | 
	
		
			
				|  |  | +                                for (String pattern : simpleMatchPatterns) {
 | 
	
		
			
				|  |  | +                                    if (Regex.simpleMatch(pattern, k)) {
 | 
	
		
			
				|  |  | +                                        return false;
 | 
	
		
			
				|  |  | +                                    }
 | 
	
		
			
				|  |  |                                  }
 | 
	
		
			
				|  |  |                              }
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  | -                        return true;
 | 
	
		
			
				|  |  | -                    };
 | 
	
		
			
				|  |  | -                    Settings.Builder settingsBuilder = Settings.builder()
 | 
	
		
			
				|  |  | -                        .put(settings.filter(settingsFilter))
 | 
	
		
			
				|  |  | -                        .put(normalizedChangeSettings.filter(k -> {
 | 
	
		
			
				|  |  | -                            if (UNMODIFIABLE_SETTINGS.contains(k)) {
 | 
	
		
			
				|  |  | -                                throw new SnapshotRestoreException(snapshot, "cannot modify setting [" + k + "] on restore");
 | 
	
		
			
				|  |  | -                            } else {
 | 
	
		
			
				|  |  | -                                return true;
 | 
	
		
			
				|  |  | -                            }
 | 
	
		
			
				|  |  | -                        }));
 | 
	
		
			
				|  |  | -                    settingsBuilder.remove(MetaDataIndexStateService.VERIFIED_BEFORE_CLOSE_SETTING.getKey());
 | 
	
		
			
				|  |  | -                    return builder.settings(settingsBuilder).build();
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                @Override
 | 
	
		
			
				|  |  | -                public void onFailure(String source, Exception e) {
 | 
	
		
			
				|  |  | -                    logger.warn(() -> new ParameterizedMessage("[{}] failed to restore snapshot", snapshotId), e);
 | 
	
		
			
				|  |  | -                    listener.onFailure(e);
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                @Override
 | 
	
		
			
				|  |  | -                public TimeValue timeout() {
 | 
	
		
			
				|  |  | -                    return request.masterNodeTimeout();
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | +                            return true;
 | 
	
		
			
				|  |  | +                        };
 | 
	
		
			
				|  |  | +                        Settings.Builder settingsBuilder = Settings.builder()
 | 
	
		
			
				|  |  | +                            .put(settings.filter(settingsFilter))
 | 
	
		
			
				|  |  | +                            .put(normalizedChangeSettings.filter(k -> {
 | 
	
		
			
				|  |  | +                                if (UNMODIFIABLE_SETTINGS.contains(k)) {
 | 
	
		
			
				|  |  | +                                    throw new SnapshotRestoreException(snapshot, "cannot modify setting [" + k + "] on restore");
 | 
	
		
			
				|  |  | +                                } else {
 | 
	
		
			
				|  |  | +                                    return true;
 | 
	
		
			
				|  |  | +                                }
 | 
	
		
			
				|  |  | +                            }));
 | 
	
		
			
				|  |  | +                        settingsBuilder.remove(MetaDataIndexStateService.VERIFIED_BEFORE_CLOSE_SETTING.getKey());
 | 
	
		
			
				|  |  | +                        return builder.settings(settingsBuilder).build();
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                @Override
 | 
	
		
			
				|  |  | -                public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
 | 
	
		
			
				|  |  | -                    listener.onResponse(new RestoreCompletionResponse(restoreUUID, snapshot, restoreInfo));
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            });
 | 
	
		
			
				|  |  | +                    @Override
 | 
	
		
			
				|  |  | +                    public void onFailure(String source, Exception e) {
 | 
	
		
			
				|  |  | +                        logger.warn(() -> new ParameterizedMessage("[{}] failed to restore snapshot", snapshotId), e);
 | 
	
		
			
				|  |  | +                        listener.onFailure(e);
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +                    @Override
 | 
	
		
			
				|  |  | +                    public TimeValue timeout() {
 | 
	
		
			
				|  |  | +                        return request.masterNodeTimeout();
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +                    @Override
 | 
	
		
			
				|  |  | +                    public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
 | 
	
		
			
				|  |  | +                        listener.onResponse(new RestoreCompletionResponse(restoreUUID, snapshot, restoreInfo));
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                });
 | 
	
		
			
				|  |  | +            }, listener::onFailure);
 | 
	
		
			
				|  |  |          } catch (Exception e) {
 | 
	
		
			
				|  |  |              logger.warn(() -> new ParameterizedMessage("[{}] failed to restore snapshot",
 | 
	
		
			
				|  |  |                  request.repository() + ":" + request.snapshot()), e);
 |