Search in sources :

Example 11 with StepListener

use of org.elasticsearch.action.StepListener in project crate by crate.

the class SnapshotsService method createSnapshot.

/**
 * Initializes the snapshotting process.
 * <p>
 * This method is used by clients to start snapshot. It makes sure that there is no snapshots are currently running and
 * creates a snapshot record in cluster state metadata.
 *
 * @param request  snapshot request
 * @param listener snapshot creation listener
 */
public void createSnapshot(final CreateSnapshotRequest request, final ActionListener<Snapshot> listener) {
    final String repositoryName = request.repository();
    final String snapshotName = request.snapshot();
    validate(repositoryName, snapshotName);
    // new UUID for the snapshot
    final SnapshotId snapshotId = new SnapshotId(snapshotName, UUIDs.randomBase64UUID());
    final StepListener<RepositoryData> repositoryDataListener = new StepListener<>();
    repositoriesService.repository(repositoryName).getRepositoryData(repositoryDataListener);
    repositoryDataListener.whenComplete(repositoryData -> {
        clusterService.submitStateUpdateTask("create_snapshot [" + snapshotName + ']', new ClusterStateUpdateTask() {

            private SnapshotsInProgress.Entry newSnapshot = null;

            @Override
            public ClusterState execute(ClusterState currentState) {
                validate(repositoryName, snapshotName, currentState);
                SnapshotDeletionsInProgress deletionsInProgress = currentState.custom(SnapshotDeletionsInProgress.TYPE);
                if (deletionsInProgress != null && deletionsInProgress.hasDeletionsInProgress()) {
                    throw new ConcurrentSnapshotExecutionException(repositoryName, snapshotName, "cannot snapshot while a snapshot deletion is in-progress in [" + deletionsInProgress + "]");
                }
                SnapshotsInProgress snapshots = currentState.custom(SnapshotsInProgress.TYPE);
                if (snapshots == null || snapshots.entries().isEmpty()) {
                    // Store newSnapshot here to be processed in clusterStateProcessed
                    List<String> indices = Arrays.asList(indexNameExpressionResolver.concreteIndexNames(currentState, request.indicesOptions(), request.indices()));
                    LOGGER.trace("[{}][{}] creating snapshot for indices [{}]", repositoryName, snapshotName, indices);
                    List<IndexId> snapshotIndices = repositoryData.resolveNewIndices(indices);
                    newSnapshot = new SnapshotsInProgress.Entry(new Snapshot(repositoryName, snapshotId), request.includeGlobalState(), request.partial(), State.INIT, snapshotIndices, List.of(request.templates()), threadPool.absoluteTimeInMillis(), repositoryData.getGenId(), null, clusterService.state().nodes().getMinNodeVersion().onOrAfter(SHARD_GEN_IN_REPO_DATA_VERSION));
                    initializingSnapshots.add(newSnapshot.snapshot());
                    snapshots = new SnapshotsInProgress(newSnapshot);
                } else {
                    throw new ConcurrentSnapshotExecutionException(repositoryName, snapshotName, " a snapshot is already running");
                }
                return ClusterState.builder(currentState).putCustom(SnapshotsInProgress.TYPE, snapshots).build();
            }

            @Override
            public void onFailure(String source, Exception e) {
                LOGGER.warn(() -> new ParameterizedMessage("[{}][{}] failed to create snapshot", repositoryName, snapshotName), e);
                if (newSnapshot != null) {
                    initializingSnapshots.remove(newSnapshot.snapshot());
                }
                newSnapshot = null;
                listener.onFailure(e);
            }

            @Override
            public void clusterStateProcessed(String source, ClusterState oldState, final ClusterState newState) {
                if (newSnapshot != null) {
                    final Snapshot current = newSnapshot.snapshot();
                    assert initializingSnapshots.contains(current);
                    beginSnapshot(newState, newSnapshot, request.partial(), new ActionListener<>() {

                        @Override
                        public void onResponse(final Snapshot snapshot) {
                            initializingSnapshots.remove(snapshot);
                            listener.onResponse(snapshot);
                        }

                        @Override
                        public void onFailure(final Exception e) {
                            initializingSnapshots.remove(current);
                            listener.onFailure(e);
                        }
                    });
                }
            }

            @Override
            public TimeValue timeout() {
                return request.masterNodeTimeout();
            }
        });
    }, listener::onFailure);
}
Also used : ClusterState(org.elasticsearch.cluster.ClusterState) ClusterStateUpdateTask(org.elasticsearch.cluster.ClusterStateUpdateTask) FailedToCommitClusterStateException(org.elasticsearch.cluster.coordination.FailedToCommitClusterStateException) RepositoryException(org.elasticsearch.repositories.RepositoryException) RepositoryMissingException(org.elasticsearch.repositories.RepositoryMissingException) NotMasterException(org.elasticsearch.cluster.NotMasterException) RepositoryData(org.elasticsearch.repositories.RepositoryData) SnapshotDeletionsInProgress(org.elasticsearch.cluster.SnapshotDeletionsInProgress) GroupedActionListener(org.elasticsearch.action.support.GroupedActionListener) ActionListener(org.elasticsearch.action.ActionListener) SnapshotsInProgress(org.elasticsearch.cluster.SnapshotsInProgress) StepListener(org.elasticsearch.action.StepListener) Collections.unmodifiableList(java.util.Collections.unmodifiableList) List(java.util.List) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) TimeValue(io.crate.common.unit.TimeValue)

Example 12 with StepListener

use of org.elasticsearch.action.StepListener in project crate by crate.

the class SnapshotsService method snapshots.

/**
 * Returns a list of snapshots from repository sorted by snapshot creation date
 *
 * @param repositoryName repository name
 * @param snapshotIds       snapshots for which to fetch snapshot information
 * @param ignoreUnavailable if true, snapshots that could not be read will only be logged with a warning,
 *                          if false, they will throw an error
 * @return list of snapshots
 */
public void snapshots(final String repositoryName, final List<SnapshotId> snapshotIds, final boolean ignoreUnavailable, ActionListener<Collection<SnapshotInfo>> listener) {
    final Set<SnapshotInfo> snapshotSet = new HashSet<>();
    final Set<SnapshotId> snapshotIdsToIterate = new HashSet<>(snapshotIds);
    // first, look at the snapshots in progress
    final List<SnapshotsInProgress.Entry> entries = currentSnapshots(repositoryName, snapshotIdsToIterate.stream().map(SnapshotId::getName).collect(Collectors.toList()));
    for (SnapshotsInProgress.Entry entry : entries) {
        snapshotSet.add(inProgressSnapshot(entry));
        snapshotIdsToIterate.remove(entry.snapshot().getSnapshotId());
    }
    if (snapshotIdsToIterate.isEmpty()) {
        listener.onResponse(snapshotSet);
        return;
    }
    // then, look in the repository
    final Repository repository = repositoriesService.repository(repositoryName);
    GroupedActionListener<SnapshotInfo> snapshotInfosListener = new GroupedActionListener<>(ActionListener.wrap(snapshotInfos -> {
        final ArrayList<SnapshotInfo> snapshotList = new ArrayList<>(snapshotSet);
        snapshotList.addAll(snapshotInfos);
        CollectionUtil.timSort(snapshotList);
        listener.onResponse(unmodifiableList(snapshotList));
    }, listener::onFailure), snapshotIdsToIterate.size());
    for (SnapshotId snapshotId : snapshotIdsToIterate) {
        StepListener<SnapshotInfo> future = new StepListener<>();
        future.whenComplete(snapshotInfosListener::onResponse, (ex) -> {
            if (ignoreUnavailable) {
                LOGGER.warn(() -> new ParameterizedMessage("failed to get snapshot [{}]", snapshotId), ex);
                snapshotInfosListener.onResponse(null);
            } else {
                snapshotInfosListener.onFailure(ex);
            }
        });
        repository.getSnapshotInfo(snapshotId, future);
    }
}
Also used : ShardId(org.elasticsearch.index.shard.ShardId) Arrays(java.util.Arrays) Collections.unmodifiableList(java.util.Collections.unmodifiableList) IndexMetadata(org.elasticsearch.cluster.metadata.IndexMetadata) ObjectObjectCursor(com.carrotsearch.hppc.cursors.ObjectObjectCursor) ClusterState(org.elasticsearch.cluster.ClusterState) ClusterStateUpdateTask(org.elasticsearch.cluster.ClusterStateUpdateTask) Settings(org.elasticsearch.common.settings.Settings) RestoreInProgress(org.elasticsearch.cluster.RestoreInProgress) Locale(java.util.Locale) Map(java.util.Map) ThreadPool(org.elasticsearch.threadpool.ThreadPool) FailedToCommitClusterStateException(org.elasticsearch.cluster.coordination.FailedToCommitClusterStateException) ActionRunnable(org.elasticsearch.action.ActionRunnable) StepListener(org.elasticsearch.action.StepListener) RepositoryException(org.elasticsearch.repositories.RepositoryException) Priority(org.elasticsearch.common.Priority) SnapshotDeletionsInProgress(org.elasticsearch.cluster.SnapshotDeletionsInProgress) PlainActionFuture(org.elasticsearch.action.support.PlainActionFuture) Collection(java.util.Collection) UUIDs(org.elasticsearch.common.UUIDs) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) State(org.elasticsearch.cluster.SnapshotsInProgress.State) IndexShardRoutingTable(org.elasticsearch.cluster.routing.IndexShardRoutingTable) ObjectCursor(com.carrotsearch.hppc.cursors.ObjectCursor) ClusterChangedEvent(org.elasticsearch.cluster.ClusterChangedEvent) Collectors(java.util.stream.Collectors) AbstractRunnable(org.elasticsearch.common.util.concurrent.AbstractRunnable) List(java.util.List) Logger(org.apache.logging.log4j.Logger) Version(org.elasticsearch.Version) IndexRoutingTable(org.elasticsearch.cluster.routing.IndexRoutingTable) RepositoryMissingException(org.elasticsearch.repositories.RepositoryMissingException) TimeValue(io.crate.common.unit.TimeValue) Optional(java.util.Optional) ShardState(org.elasticsearch.cluster.SnapshotsInProgress.ShardState) ShardSnapshotStatus(org.elasticsearch.cluster.SnapshotsInProgress.ShardSnapshotStatus) RepositoryData(org.elasticsearch.repositories.RepositoryData) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ShardRouting(org.elasticsearch.cluster.routing.ShardRouting) Tuple(io.crate.common.collections.Tuple) ImmutableOpenMap(org.elasticsearch.common.collect.ImmutableOpenMap) ShardGenerations(org.elasticsearch.repositories.ShardGenerations) NotMasterException(org.elasticsearch.cluster.NotMasterException) ClusterService(org.elasticsearch.cluster.service.ClusterService) HashMap(java.util.HashMap) Index(org.elasticsearch.index.Index) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) IndexId(org.elasticsearch.repositories.IndexId) SnapshotsInProgress.completed(org.elasticsearch.cluster.SnapshotsInProgress.completed) Strings(org.elasticsearch.common.Strings) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Metadata(org.elasticsearch.cluster.metadata.Metadata) DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) RepositoriesMetadata(org.elasticsearch.cluster.metadata.RepositoriesMetadata) StreamSupport(java.util.stream.StreamSupport) ClusterStateApplier(org.elasticsearch.cluster.ClusterStateApplier) Nullable(javax.annotation.Nullable) DiscoveryNodes(org.elasticsearch.cluster.node.DiscoveryNodes) Repository(org.elasticsearch.repositories.Repository) GroupedActionListener(org.elasticsearch.action.support.GroupedActionListener) CreateSnapshotRequest(org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest) RepositoriesService(org.elasticsearch.repositories.RepositoriesService) AbstractLifecycleComponent(org.elasticsearch.common.component.AbstractLifecycleComponent) CollectionUtil(org.apache.lucene.util.CollectionUtil) ExceptionsHelper(org.elasticsearch.ExceptionsHelper) RoutingTable(org.elasticsearch.cluster.routing.RoutingTable) SnapshotsInProgress(org.elasticsearch.cluster.SnapshotsInProgress) IndexNameExpressionResolver(org.elasticsearch.cluster.metadata.IndexNameExpressionResolver) LogManager(org.apache.logging.log4j.LogManager) Collections(java.util.Collections) ActionListener(org.elasticsearch.action.ActionListener) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) Repository(org.elasticsearch.repositories.Repository) GroupedActionListener(org.elasticsearch.action.support.GroupedActionListener) SnapshotsInProgress(org.elasticsearch.cluster.SnapshotsInProgress) StepListener(org.elasticsearch.action.StepListener) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) HashSet(java.util.HashSet)

Example 13 with StepListener

use of org.elasticsearch.action.StepListener in project crate by crate.

the class BlobStoreRepository method writeIndexGen.

/**
 * Writing a new index generation is a three step process.
 * First, the {@link RepositoryMetadata} entry for this repository is set into a pending state by incrementing its
 * pending generation {@code P} while its safe generation {@code N} remains unchanged.
 * Second, the updated {@link RepositoryData} is written to generation {@code P + 1}.
 * Lastly, the {@link RepositoryMetadata} entry for this repository is updated to the new generation {@code P + 1} and thus
 * pending and safe generation are set to the same value marking the end of the update of the repository data.
 *
 * @param repositoryData RepositoryData to write
 * @param expectedGen    expected repository generation at the start of the operation
 * @param writeShardGens whether to write {@link ShardGenerations} to the new {@link RepositoryData} blob
 * @param listener       completion listener
 */
protected void writeIndexGen(RepositoryData repositoryData, long expectedGen, boolean writeShardGens, ActionListener<Void> listener) {
    // can not write to a read only repository
    assert isReadOnly() == false;
    final long currentGen = repositoryData.getGenId();
    if (currentGen != expectedGen) {
        // the index file was updated by a concurrent operation, so we were operating on stale
        // repository data
        listener.onFailure(new RepositoryException(metadata.name(), "concurrent modification of the index-N file, expected current generation [" + expectedGen + "], actual current generation [" + currentGen + "]"));
        return;
    }
    // Step 1: Set repository generation state to the next possible pending generation
    final StepListener<Long> setPendingStep = new StepListener<>();
    clusterService.submitStateUpdateTask("set pending repository generation [" + metadata.name() + "][" + expectedGen + "]", new ClusterStateUpdateTask() {

        private long newGen;

        @Override
        public ClusterState execute(ClusterState currentState) {
            final RepositoryMetadata meta = getRepoMetadata(currentState);
            final String repoName = metadata.name();
            final long genInState = meta.generation();
            final boolean uninitializedMeta = meta.generation() == RepositoryData.UNKNOWN_REPO_GEN || bestEffortConsistency;
            if (uninitializedMeta == false && meta.pendingGeneration() != genInState) {
                LOGGER.info("Trying to write new repository data over unfinished write, repo [{}] is at " + "safe generation [{}] and pending generation [{}]", meta.name(), genInState, meta.pendingGeneration());
            }
            assert expectedGen == RepositoryData.EMPTY_REPO_GEN || uninitializedMeta || expectedGen == meta.generation() : "Expected non-empty generation [" + expectedGen + "] does not match generation tracked in [" + meta + "]";
            // If we run into the empty repo generation for the expected gen, the repo is assumed to have been cleared of
            // all contents by an external process so we reset the safe generation to the empty generation.
            final long safeGeneration = expectedGen == RepositoryData.EMPTY_REPO_GEN ? RepositoryData.EMPTY_REPO_GEN : (uninitializedMeta ? expectedGen : genInState);
            // Regardless of whether or not the safe generation has been reset, the pending generation always increments so that
            // even if a repository has been manually cleared of all contents we will never reuse the same repository generation.
            // This is motivated by the consistency behavior the S3 based blob repository implementation has to support which does
            // not offer any consistency guarantees when it comes to overwriting the same blob name with different content.
            final long nextPendingGen = metadata.pendingGeneration() + 1;
            newGen = uninitializedMeta ? Math.max(expectedGen + 1, nextPendingGen) : nextPendingGen;
            assert newGen > latestKnownRepoGen.get() : "Attempted new generation [" + newGen + "] must be larger than latest known generation [" + latestKnownRepoGen.get() + "]";
            return ClusterState.builder(currentState).metadata(Metadata.builder(currentState.getMetadata()).putCustom(RepositoriesMetadata.TYPE, currentState.metadata().<RepositoriesMetadata>custom(RepositoriesMetadata.TYPE).withUpdatedGeneration(repoName, safeGeneration, newGen)).build()).build();
        }

        @Override
        public void onFailure(String source, Exception e) {
            listener.onFailure(new RepositoryException(metadata.name(), "Failed to execute cluster state update [" + source + "]", e));
        }

        @Override
        public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
            setPendingStep.onResponse(newGen);
        }
    });
    final StepListener<RepositoryData> filterRepositoryDataStep = new StepListener<>();
    // Step 2: Write new index-N blob to repository and update index.latest
    setPendingStep.whenComplete(newGen -> threadPool().executor(ThreadPool.Names.SNAPSHOT).execute(ActionRunnable.wrap(listener, l -> {
        // BwC logic: Load snapshot version information if any snapshot is missing a version in RepositoryData so that the new
        // RepositoryData contains a version for every snapshot
        final List<SnapshotId> snapshotIdsWithoutVersion = repositoryData.getSnapshotIds().stream().filter(snapshotId -> repositoryData.getVersion(snapshotId) == null).collect(Collectors.toList());
        if (snapshotIdsWithoutVersion.isEmpty() == false) {
            final Map<SnapshotId, Version> updatedVersionMap = new ConcurrentHashMap<>();
            final GroupedActionListener<Void> loadAllVersionsListener = new GroupedActionListener<>(ActionListener.runAfter(new ActionListener<Collection<Void>>() {

                @Override
                public void onResponse(Collection<Void> voids) {
                    LOGGER.info("Successfully loaded all snapshot's version information for {} from snapshot metadata", AllocationService.firstListElementsToCommaDelimitedString(snapshotIdsWithoutVersion, SnapshotId::toString, LOGGER.isDebugEnabled()));
                }

                @Override
                public void onFailure(Exception e) {
                    LOGGER.warn("Failure when trying to load missing version information from snapshot metadata", e);
                }
            }, () -> filterRepositoryDataStep.onResponse(repositoryData.withVersions(updatedVersionMap))), snapshotIdsWithoutVersion.size());
            for (SnapshotId snapshotId : snapshotIdsWithoutVersion) {
                threadPool().executor(ThreadPool.Names.SNAPSHOT).execute(ActionRunnable.run(loadAllVersionsListener, () -> {
                    ActionListener<SnapshotInfo> snapshotInfoListener = ActionListener.delegateFailure(loadAllVersionsListener, (delegate, snapshotInfo) -> {
                        updatedVersionMap.put(snapshotId, snapshotInfo.version());
                        delegate.onResponse(null);
                    });
                    getSnapshotInfo(snapshotId, snapshotInfoListener);
                }));
            }
        } else {
            filterRepositoryDataStep.onResponse(repositoryData);
        }
    })), listener::onFailure);
    filterRepositoryDataStep.whenComplete(filteredRepositoryData -> {
        final long newGen = setPendingStep.result();
        if (latestKnownRepoGen.get() >= newGen) {
            throw new IllegalArgumentException("Tried writing generation [" + newGen + "] but repository is at least at generation [" + latestKnownRepoGen.get() + "] already");
        }
        // write the index file
        final String indexBlob = INDEX_FILE_PREFIX + Long.toString(newGen);
        LOGGER.debug("Repository [{}] writing new index generational blob [{}]", metadata.name(), indexBlob);
        writeAtomic(indexBlob, BytesReference.bytes(filteredRepositoryData.snapshotsToXContent(XContentFactory.jsonBuilder(), writeShardGens)), true);
        // write the current generation to the index-latest file
        final BytesReference genBytes;
        try (BytesStreamOutput bStream = new BytesStreamOutput()) {
            bStream.writeLong(newGen);
            genBytes = bStream.bytes();
        }
        LOGGER.debug("Repository [{}] updating index.latest with generation [{}]", metadata.name(), newGen);
        writeAtomic(INDEX_LATEST_BLOB, genBytes, false);
        // Step 3: Update CS to reflect new repository generation.
        clusterService.submitStateUpdateTask("set safe repository generation [" + metadata.name() + "][" + newGen + "]", new ClusterStateUpdateTask() {

            @Override
            public ClusterState execute(ClusterState currentState) {
                final RepositoryMetadata meta = getRepoMetadata(currentState);
                if (meta.generation() != expectedGen) {
                    throw new IllegalStateException("Tried to update repo generation to [" + newGen + "] but saw unexpected generation in state [" + meta + "]");
                }
                if (meta.pendingGeneration() != newGen) {
                    throw new IllegalStateException("Tried to update from unexpected pending repo generation [" + meta.pendingGeneration() + "] after write to generation [" + newGen + "]");
                }
                return ClusterState.builder(currentState).metadata(Metadata.builder(currentState.getMetadata()).putCustom(RepositoriesMetadata.TYPE, currentState.metadata().<RepositoriesMetadata>custom(RepositoriesMetadata.TYPE).withUpdatedGeneration(metadata.name(), newGen, newGen)).build()).build();
            }

            @Override
            public void onFailure(String source, Exception e) {
                listener.onFailure(new RepositoryException(metadata.name(), "Failed to execute cluster state update [" + source + "]", e));
            }

            @Override
            public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
                threadPool.executor(ThreadPool.Names.SNAPSHOT).execute(ActionRunnable.run(listener, () -> {
                    // Delete all now outdated index files up to 1000 blobs back from the new generation.
                    // If there are more than 1000 dangling index-N cleanup functionality on repo delete will take care of them.
                    // Deleting one older than the current expectedGen is done for BwC reasons as older versions used to keep
                    // two index-N blobs around.
                    final List<String> oldIndexN = LongStream.range(Math.max(Math.max(expectedGen - 1, 0), newGen - 1000), newGen).mapToObj(gen -> INDEX_FILE_PREFIX + gen).collect(Collectors.toList());
                    try {
                        blobContainer().deleteBlobsIgnoringIfNotExists(oldIndexN);
                    } catch (IOException e) {
                        LOGGER.warn("Failed to clean up old index blobs {}", oldIndexN);
                    }
                }));
            }
        });
    }, listener::onFailure);
}
Also used : ShardId(org.elasticsearch.index.shard.ShardId) SnapshotFiles(org.elasticsearch.index.snapshots.blobstore.SnapshotFiles) IndexShardSnapshotFailedException(org.elasticsearch.index.snapshots.IndexShardSnapshotFailedException) ByteSizeUnit(org.elasticsearch.common.unit.ByteSizeUnit) IndexFormatTooNewException(org.apache.lucene.index.IndexFormatTooNewException) IndexMetadata(org.elasticsearch.cluster.metadata.IndexMetadata) AllocationService(org.elasticsearch.cluster.routing.allocation.AllocationService) ClusterState(org.elasticsearch.cluster.ClusterState) ClusterStateUpdateTask(org.elasticsearch.cluster.ClusterStateUpdateTask) Map(java.util.Map) BlobContainer(org.elasticsearch.common.blobstore.BlobContainer) RateLimitingInputStream(org.elasticsearch.index.snapshots.blobstore.RateLimitingInputStream) IOContext(org.apache.lucene.store.IOContext) InvalidArgumentException(io.crate.exceptions.InvalidArgumentException) SnapshotDeletionsInProgress(org.elasticsearch.cluster.SnapshotDeletionsInProgress) UUIDs(org.elasticsearch.common.UUIDs) Set(java.util.Set) BlockingQueue(java.util.concurrent.BlockingQueue) StandardCharsets(java.nio.charset.StandardCharsets) AbstractRunnable(org.elasticsearch.common.util.concurrent.AbstractRunnable) Stream(java.util.stream.Stream) Logger(org.apache.logging.log4j.Logger) InputStreamIndexInput(org.elasticsearch.common.lucene.store.InputStreamIndexInput) BlobStore(org.elasticsearch.common.blobstore.BlobStore) SnapshotException(org.elasticsearch.snapshots.SnapshotException) FileInfo.canonicalName(org.elasticsearch.index.snapshots.blobstore.BlobStoreIndexShardSnapshot.FileInfo.canonicalName) IndexCommit(org.apache.lucene.index.IndexCommit) XContentFactory(org.elasticsearch.common.xcontent.XContentFactory) SnapshotId(org.elasticsearch.snapshots.SnapshotId) Tuple(io.crate.common.collections.Tuple) ShardGenerations(org.elasticsearch.repositories.ShardGenerations) ClusterService(org.elasticsearch.cluster.service.ClusterService) SnapshotShardFailure(org.elasticsearch.snapshots.SnapshotShardFailure) BytesStreamOutput(org.elasticsearch.common.io.stream.BytesStreamOutput) LoggingDeprecationHandler(org.elasticsearch.common.xcontent.LoggingDeprecationHandler) ArrayList(java.util.ArrayList) BytesArray(org.elasticsearch.common.bytes.BytesArray) Metadata(org.elasticsearch.cluster.metadata.Metadata) DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) Store(org.elasticsearch.index.store.Store) Nullable(javax.annotation.Nullable) LongStream(java.util.stream.LongStream) IndexInput(org.apache.lucene.store.IndexInput) SetOnce(org.apache.lucene.util.SetOnce) Executor(java.util.concurrent.Executor) IOException(java.io.IOException) XContentParser(org.elasticsearch.common.xcontent.XContentParser) AtomicLong(java.util.concurrent.atomic.AtomicLong) CounterMetric(org.elasticsearch.common.metrics.CounterMetric) ActionListener(org.elasticsearch.action.ActionListener) FsBlobContainer(org.elasticsearch.common.blobstore.fs.FsBlobContainer) SnapshotMissingException(org.elasticsearch.snapshots.SnapshotMissingException) NoSuchFileException(java.nio.file.NoSuchFileException) ConcurrentSnapshotExecutionException(org.elasticsearch.snapshots.ConcurrentSnapshotExecutionException) SnapshotInfo(org.elasticsearch.snapshots.SnapshotInfo) CorruptIndexException(org.apache.lucene.index.CorruptIndexException) StoreFileMetadata(org.elasticsearch.index.store.StoreFileMetadata) RepositoryMetadata(org.elasticsearch.cluster.metadata.RepositoryMetadata) Settings(org.elasticsearch.common.settings.Settings) Locale(java.util.Locale) Streams(org.elasticsearch.common.io.Streams) ThreadPool(org.elasticsearch.threadpool.ThreadPool) IndexShardRestoreFailedException(org.elasticsearch.index.snapshots.IndexShardRestoreFailedException) ActionRunnable(org.elasticsearch.action.ActionRunnable) StepListener(org.elasticsearch.action.StepListener) NamedXContentRegistry(org.elasticsearch.common.xcontent.NamedXContentRegistry) RepositoryException(org.elasticsearch.repositories.RepositoryException) ByteSizeValue(org.elasticsearch.common.unit.ByteSizeValue) NotXContentException(org.elasticsearch.common.compress.NotXContentException) Setting(org.elasticsearch.common.settings.Setting) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) BlobMetadata(org.elasticsearch.common.blobstore.BlobMetadata) BytesReference(org.elasticsearch.common.bytes.BytesReference) LinkedBlockingQueue(java.util.concurrent.LinkedBlockingQueue) Collectors(java.util.stream.Collectors) IndexShardSnapshotException(org.elasticsearch.index.snapshots.IndexShardSnapshotException) MapperService(org.elasticsearch.index.mapper.MapperService) List(java.util.List) BlobStoreIndexShardSnapshot(org.elasticsearch.index.snapshots.blobstore.BlobStoreIndexShardSnapshot) Version(org.elasticsearch.Version) RecoveryState(org.elasticsearch.indices.recovery.RecoveryState) RepositoryData(org.elasticsearch.repositories.RepositoryData) ThreadPoolExecutor(java.util.concurrent.ThreadPoolExecutor) XContentType(org.elasticsearch.common.xcontent.XContentType) IndexShardSnapshotStatus(org.elasticsearch.index.snapshots.IndexShardSnapshotStatus) Index(org.elasticsearch.index.Index) Lucene(org.elasticsearch.common.lucene.Lucene) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) IndexId(org.elasticsearch.repositories.IndexId) FilterInputStream(java.io.FilterInputStream) RepositoriesMetadata(org.elasticsearch.cluster.metadata.RepositoriesMetadata) RepositoryVerificationException(org.elasticsearch.repositories.RepositoryVerificationException) BlobPath(org.elasticsearch.common.blobstore.BlobPath) IndexOutput(org.apache.lucene.store.IndexOutput) Numbers(org.elasticsearch.common.Numbers) Repository(org.elasticsearch.repositories.Repository) SnapshotsService(org.elasticsearch.snapshots.SnapshotsService) GroupedActionListener(org.elasticsearch.action.support.GroupedActionListener) IndexFormatTooOldException(org.apache.lucene.index.IndexFormatTooOldException) AbstractLifecycleComponent(org.elasticsearch.common.component.AbstractLifecycleComponent) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) ExceptionsHelper(org.elasticsearch.ExceptionsHelper) SlicedInputStream(org.elasticsearch.index.snapshots.blobstore.SlicedInputStream) SnapshotsInProgress(org.elasticsearch.cluster.SnapshotsInProgress) BlobStoreIndexShardSnapshots(org.elasticsearch.index.snapshots.blobstore.BlobStoreIndexShardSnapshots) Collections(java.util.Collections) LogManager(org.apache.logging.log4j.LogManager) RepositoryOperation(org.elasticsearch.repositories.RepositoryOperation) Snapshot(org.elasticsearch.snapshots.Snapshot) RateLimiter(org.apache.lucene.store.RateLimiter) InputStream(java.io.InputStream) BytesStreamOutput(org.elasticsearch.common.io.stream.BytesStreamOutput) RepositoriesMetadata(org.elasticsearch.cluster.metadata.RepositoriesMetadata) GroupedActionListener(org.elasticsearch.action.support.GroupedActionListener) Version(org.elasticsearch.Version) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) BytesReference(org.elasticsearch.common.bytes.BytesReference) ClusterState(org.elasticsearch.cluster.ClusterState) ClusterStateUpdateTask(org.elasticsearch.cluster.ClusterStateUpdateTask) RepositoryException(org.elasticsearch.repositories.RepositoryException) IOException(java.io.IOException) IndexShardSnapshotFailedException(org.elasticsearch.index.snapshots.IndexShardSnapshotFailedException) IndexFormatTooNewException(org.apache.lucene.index.IndexFormatTooNewException) InvalidArgumentException(io.crate.exceptions.InvalidArgumentException) SnapshotException(org.elasticsearch.snapshots.SnapshotException) IOException(java.io.IOException) SnapshotMissingException(org.elasticsearch.snapshots.SnapshotMissingException) NoSuchFileException(java.nio.file.NoSuchFileException) ConcurrentSnapshotExecutionException(org.elasticsearch.snapshots.ConcurrentSnapshotExecutionException) CorruptIndexException(org.apache.lucene.index.CorruptIndexException) IndexShardRestoreFailedException(org.elasticsearch.index.snapshots.IndexShardRestoreFailedException) RepositoryException(org.elasticsearch.repositories.RepositoryException) NotXContentException(org.elasticsearch.common.compress.NotXContentException) IndexShardSnapshotException(org.elasticsearch.index.snapshots.IndexShardSnapshotException) RepositoryVerificationException(org.elasticsearch.repositories.RepositoryVerificationException) IndexFormatTooOldException(org.apache.lucene.index.IndexFormatTooOldException) RepositoryData(org.elasticsearch.repositories.RepositoryData) SnapshotId(org.elasticsearch.snapshots.SnapshotId) ActionListener(org.elasticsearch.action.ActionListener) GroupedActionListener(org.elasticsearch.action.support.GroupedActionListener) RepositoryMetadata(org.elasticsearch.cluster.metadata.RepositoryMetadata) AtomicLong(java.util.concurrent.atomic.AtomicLong) Collection(java.util.Collection) StepListener(org.elasticsearch.action.StepListener)

Example 14 with StepListener

use of org.elasticsearch.action.StepListener in project crate by crate.

the class RestoreService method restoreSnapshot.

/**
 * Restores snapshot specified in the restore request.
 *
 * @param request  restore request
 * @param listener restore listener
 */
public void restoreSnapshot(final RestoreRequest request, final ActionListener<RestoreCompletionResponse> listener) {
    try {
        // Read snapshot info and metadata from the repository
        final String repositoryName = request.repositoryName;
        Repository repository = repositoriesService.repository(repositoryName);
        final StepListener<RepositoryData> repositoryDataListener = new StepListener<>();
        repository.getRepositoryData(repositoryDataListener);
        repositoryDataListener.whenComplete(repositoryData -> {
            final String snapshotName = request.snapshotName;
            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();
            repository.getSnapshotInfo(snapshotId, ActionListener.delegateFailure(listener, (delegate, snapshotInfo) -> {
                final Snapshot snapshot = new Snapshot(repositoryName, snapshotId);
                // 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 = request.includeIndices() ? filterIndices(snapshotInfo.indices(), request.indices(), request.indicesOptions()) : List.of();
                final StepListener<Metadata> globalMetadataListener = new StepListener<>();
                if (request.includeCustomMetadata() || request.includeGlobalSettings() || request.allTemplates() || (request.templates() != null && request.templates().length > 0)) {
                    repository.getSnapshotGlobalMetadata(snapshotId, globalMetadataListener);
                } else {
                    globalMetadataListener.onResponse(Metadata.EMPTY_METADATA);
                }
                globalMetadataListener.whenComplete(globalMetadata -> {
                    var metadataBuilder = Metadata.builder(globalMetadata);
                    var indexIdsInSnapshot = repositoryData.resolveIndices(indicesInSnapshot);
                    var snapshotIndexMetadataListener = new StepListener<Collection<IndexMetadata>>();
                    repository.getSnapshotIndexMetadata(snapshotId, indexIdsInSnapshot, snapshotIndexMetadataListener);
                    snapshotIndexMetadataListener.whenComplete(snapshotIndexMetadata -> {
                        for (IndexMetadata indexMetadata : snapshotIndexMetadata) {
                            metadataBuilder.put(indexMetadata, 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.getEntries().stream().anyMatch(entry -> entry.getSnapshot().equals(snapshot))) {
                                    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(), currentState, 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()));
                                            shardLimitValidator.validateShardLimit(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(Math.max(snapshotIndexMetadata.getVersion(), 1 + currentIndexMetadata.getVersion()));
                                            indexMdBuilder.mappingVersion(Math.max(snapshotIndexMetadata.getMappingVersion(), 1 + currentIndexMetadata.getMappingVersion()));
                                            indexMdBuilder.settingsVersion(Math.max(snapshotIndexMetadata.getSettingsVersion(), 1 + currentIndexMetadata.getSettingsVersion()));
                                            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();
                                                }
                                                // 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();
                                        }
                                        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), 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);
                                    } else {
                                        restoreInProgressBuilder = new RestoreInProgress.Builder();
                                    }
                                    builder.putCustom(RestoreInProgress.TYPE, restoreInProgressBuilder.add(restoreEntry).build());
                                } else {
                                    shards = ImmutableOpenMap.of();
                                }
                                validateExistingTemplates();
                                checkAliasNameConflicts(indices, aliases);
                                // Restore templates (but do NOT overwrite existing templates)
                                restoreTemplates(mdBuilder, currentState);
                                // Restore global state if needed
                                if (request.includeGlobalSettings() && metadata.persistentSettings() != null) {
                                    Settings settings = metadata.persistentSettings();
                                    // CrateDB patch to only restore defined settings
                                    if (request.globalSettings().length > 0) {
                                        var filteredSettingBuilder = Settings.builder();
                                        for (String prefix : request.globalSettings()) {
                                            filteredSettingBuilder.put(settings.filter(s -> s.startsWith(prefix)));
                                        }
                                        settings = filteredSettingBuilder.build();
                                    }
                                    clusterSettings.validateUpdate(settings);
                                    mdBuilder.persistentSettings(settings);
                                }
                                if (request.includeCustomMetadata() && metadata.customs() != null) {
                                    // CrateDB patch to only restore defined custom metadata types
                                    List<String> customMetadataTypes = Arrays.asList(request.customMetadataTypes());
                                    boolean includeAll = customMetadataTypes.size() == 0;
                                    for (ObjectObjectCursor<String, Metadata.Custom> cursor : metadata.customs()) {
                                        if (!RepositoriesMetadata.TYPE.equals(cursor.key)) {
                                            if (includeAll || customMetadataTypes.contains(cursor.key)) {
                                                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(), Collections.unmodifiableList(new ArrayList<>(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 + "]");
                            }

                            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 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 {
                                    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");
                                }
                            }

                            /**
                             * 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) {
                                if (changeSettings.names().isEmpty() && ignoreSettings.length == 0) {
                                    return indexMetadata;
                                }
                                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 {
                                        simpleMatchPatterns.add(ignoredSetting);
                                    }
                                }
                                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;
                                            }
                                        }
                                    }
                                    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(IndexMetadata.VERIFIED_BEFORE_CLOSE_SETTING.getKey());
                                return builder.settings(settingsBuilder).build();
                            }

                            private void restoreTemplates(Metadata.Builder mdBuilder, ClusterState currentState) {
                                List<String> toRestore = Arrays.asList(request.templates());
                                if (metadata.templates() != null) {
                                    for (ObjectCursor<IndexTemplateMetadata> cursor : metadata.templates().values()) {
                                        if (currentState.metadata().templates().get(cursor.value.name()) == null && (request.allTemplates() || toRestore.contains(cursor.value.name()))) {
                                            mdBuilder.put(cursor.value);
                                        }
                                    }
                                }
                            }

                            private void validateExistingTemplates() {
                                if (request.indicesOptions().ignoreUnavailable() || request.allTemplates()) {
                                    return;
                                }
                                for (String template : request.templates()) {
                                    if (!metadata.templates().containsKey(template)) {
                                        throw new ResourceNotFoundException("[{}] template not found", template);
                                    }
                                }
                            }

                            @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);
                }, listener::onFailure);
            }));
        }, listener::onFailure);
    } catch (Exception e) {
        LOGGER.warn(() -> new ParameterizedMessage("[{}] failed to restore snapshot", request.repositoryName + ":" + request.snapshotName), e);
        listener.onFailure(e);
    }
}
Also used : ShardId(org.elasticsearch.index.shard.ShardId) MetadataIndexUpgradeService(org.elasticsearch.cluster.metadata.MetadataIndexUpgradeService) Arrays(java.util.Arrays) SETTING_AUTO_EXPAND_REPLICAS(org.elasticsearch.cluster.metadata.IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS) ShardLimitValidator(org.elasticsearch.indices.ShardLimitValidator) SETTING_VERSION_CREATED(org.elasticsearch.cluster.metadata.IndexMetadata.SETTING_VERSION_CREATED) IndexMetadata(org.elasticsearch.cluster.metadata.IndexMetadata) SnapshotRecoverySource(org.elasticsearch.cluster.routing.RecoverySource.SnapshotRecoverySource) AllocationService(org.elasticsearch.cluster.routing.allocation.AllocationService) ClusterBlocks(org.elasticsearch.cluster.block.ClusterBlocks) ObjectObjectCursor(com.carrotsearch.hppc.cursors.ObjectObjectCursor) ClusterState(org.elasticsearch.cluster.ClusterState) ClusterStateUpdateTask(org.elasticsearch.cluster.ClusterStateUpdateTask) Settings(org.elasticsearch.common.settings.Settings) RestoreInProgress(org.elasticsearch.cluster.RestoreInProgress) Map(java.util.Map) IndicesOptions(org.elasticsearch.action.support.IndicesOptions) AliasMetadata(org.elasticsearch.cluster.metadata.AliasMetadata) ResourceNotFoundException(org.elasticsearch.ResourceNotFoundException) StepListener(org.elasticsearch.action.StepListener) Priority(org.elasticsearch.common.Priority) SnapshotDeletionsInProgress(org.elasticsearch.cluster.SnapshotDeletionsInProgress) Predicate(java.util.function.Predicate) Collection(java.util.Collection) UUIDs(org.elasticsearch.common.UUIDs) Set(java.util.Set) ObjectCursor(com.carrotsearch.hppc.cursors.ObjectCursor) ClusterChangedEvent(org.elasticsearch.cluster.ClusterChangedEvent) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) RecoverySource(org.elasticsearch.cluster.routing.RecoverySource) List(java.util.List) Logger(org.apache.logging.log4j.Logger) Version(org.elasticsearch.Version) TimeValue(io.crate.common.unit.TimeValue) Optional(java.util.Optional) SETTING_INDEX_UUID(org.elasticsearch.cluster.metadata.IndexMetadata.SETTING_INDEX_UUID) RepositoryData(org.elasticsearch.repositories.RepositoryData) ShardRouting(org.elasticsearch.cluster.routing.ShardRouting) SETTING_NUMBER_OF_SHARDS(org.elasticsearch.cluster.metadata.IndexMetadata.SETTING_NUMBER_OF_SHARDS) SETTING_VERSION_UPGRADED(org.elasticsearch.cluster.metadata.IndexMetadata.SETTING_VERSION_UPGRADED) ImmutableOpenMap(org.elasticsearch.common.collect.ImmutableOpenMap) ClusterService(org.elasticsearch.cluster.service.ClusterService) SnapshotUtils.filterIndices(org.elasticsearch.snapshots.SnapshotUtils.filterIndices) HashMap(java.util.HashMap) Index(org.elasticsearch.index.Index) Lucene(org.elasticsearch.common.lucene.Lucene) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Metadata(org.elasticsearch.cluster.metadata.Metadata) RepositoriesMetadata(org.elasticsearch.cluster.metadata.RepositoriesMetadata) ClusterStateTaskListener(org.elasticsearch.cluster.ClusterStateTaskListener) SETTING_NUMBER_OF_REPLICAS(org.elasticsearch.cluster.metadata.IndexMetadata.SETTING_NUMBER_OF_REPLICAS) IndexSettings(org.elasticsearch.index.IndexSettings) Regex(org.elasticsearch.common.regex.Regex) ShardRestoreStatus(org.elasticsearch.cluster.RestoreInProgress.ShardRestoreStatus) ClusterStateApplier(org.elasticsearch.cluster.ClusterStateApplier) Repository(org.elasticsearch.repositories.Repository) Collections.emptySet(java.util.Collections.emptySet) IndexShard(org.elasticsearch.index.shard.IndexShard) IntHashSet(com.carrotsearch.hppc.IntHashSet) IntSet(com.carrotsearch.hppc.IntSet) ClusterStateTaskConfig(org.elasticsearch.cluster.ClusterStateTaskConfig) SETTING_CREATION_DATE(org.elasticsearch.cluster.metadata.IndexMetadata.SETTING_CREATION_DATE) ClusterStateTaskExecutor(org.elasticsearch.cluster.ClusterStateTaskExecutor) IndexTemplateMetadata(org.elasticsearch.cluster.metadata.IndexTemplateMetadata) RoutingChangesObserver(org.elasticsearch.cluster.routing.RoutingChangesObserver) UnassignedInfo(org.elasticsearch.cluster.routing.UnassignedInfo) RepositoriesService(org.elasticsearch.repositories.RepositoriesService) MetadataCreateIndexService(org.elasticsearch.cluster.metadata.MetadataCreateIndexService) ClusterSettings(org.elasticsearch.common.settings.ClusterSettings) Collections.unmodifiableSet(java.util.Collections.unmodifiableSet) RoutingTable(org.elasticsearch.cluster.routing.RoutingTable) LogManager(org.apache.logging.log4j.LogManager) Collections(java.util.Collections) ActionListener(org.elasticsearch.action.ActionListener) IntHashSet(com.carrotsearch.hppc.IntHashSet) ArrayList(java.util.ArrayList) Index(org.elasticsearch.index.Index) SnapshotDeletionsInProgress(org.elasticsearch.cluster.SnapshotDeletionsInProgress) Version(org.elasticsearch.Version) List(java.util.List) ArrayList(java.util.ArrayList) IndexMetadata(org.elasticsearch.cluster.metadata.IndexMetadata) ResourceNotFoundException(org.elasticsearch.ResourceNotFoundException) Settings(org.elasticsearch.common.settings.Settings) IndexSettings(org.elasticsearch.index.IndexSettings) ClusterSettings(org.elasticsearch.common.settings.ClusterSettings) HashSet(java.util.HashSet) IntHashSet(com.carrotsearch.hppc.IntHashSet) ClusterState(org.elasticsearch.cluster.ClusterState) ShardRestoreStatus(org.elasticsearch.cluster.RestoreInProgress.ShardRestoreStatus) RestoreInProgress(org.elasticsearch.cluster.RestoreInProgress) SnapshotRecoverySource(org.elasticsearch.cluster.routing.RecoverySource.SnapshotRecoverySource) RoutingTable(org.elasticsearch.cluster.routing.RoutingTable) Collection(java.util.Collection) Map(java.util.Map) ImmutableOpenMap(org.elasticsearch.common.collect.ImmutableOpenMap) HashMap(java.util.HashMap) Set(java.util.Set) HashSet(java.util.HashSet) Collections.emptySet(java.util.Collections.emptySet) IntHashSet(com.carrotsearch.hppc.IntHashSet) IntSet(com.carrotsearch.hppc.IntSet) Collections.unmodifiableSet(java.util.Collections.unmodifiableSet) IntSet(com.carrotsearch.hppc.IntSet) IndexMetadata(org.elasticsearch.cluster.metadata.IndexMetadata) AliasMetadata(org.elasticsearch.cluster.metadata.AliasMetadata) Metadata(org.elasticsearch.cluster.metadata.Metadata) RepositoriesMetadata(org.elasticsearch.cluster.metadata.RepositoriesMetadata) IndexTemplateMetadata(org.elasticsearch.cluster.metadata.IndexTemplateMetadata) ImmutableOpenMap(org.elasticsearch.common.collect.ImmutableOpenMap) ShardId(org.elasticsearch.index.shard.ShardId) AliasMetadata(org.elasticsearch.cluster.metadata.AliasMetadata) ClusterBlocks(org.elasticsearch.cluster.block.ClusterBlocks) IndexTemplateMetadata(org.elasticsearch.cluster.metadata.IndexTemplateMetadata) ClusterStateUpdateTask(org.elasticsearch.cluster.ClusterStateUpdateTask) ResourceNotFoundException(org.elasticsearch.ResourceNotFoundException) RepositoryData(org.elasticsearch.repositories.RepositoryData) Repository(org.elasticsearch.repositories.Repository) ShardRestoreStatus(org.elasticsearch.cluster.RestoreInProgress.ShardRestoreStatus) StepListener(org.elasticsearch.action.StepListener) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage)

Aggregations

StepListener (org.elasticsearch.action.StepListener)14 ArrayList (java.util.ArrayList)12 List (java.util.List)11 ActionListener (org.elasticsearch.action.ActionListener)11 ParameterizedMessage (org.apache.logging.log4j.message.ParameterizedMessage)10 Collections (java.util.Collections)9 Logger (org.apache.logging.log4j.Logger)9 Version (org.elasticsearch.Version)9 TimeValue (io.crate.common.unit.TimeValue)8 IOException (java.io.IOException)8 Locale (java.util.Locale)8 CorruptIndexException (org.apache.lucene.index.CorruptIndexException)8 ExceptionsHelper (org.elasticsearch.ExceptionsHelper)8 ActionRunnable (org.elasticsearch.action.ActionRunnable)8 ClusterState (org.elasticsearch.cluster.ClusterState)8 ClusterStateUpdateTask (org.elasticsearch.cluster.ClusterStateUpdateTask)8 SnapshotDeletionsInProgress (org.elasticsearch.cluster.SnapshotDeletionsInProgress)8 Store (org.elasticsearch.index.store.Store)8 StoreFileMetadata (org.elasticsearch.index.store.StoreFileMetadata)8 Collection (java.util.Collection)7