Search in sources :

Example 1 with AckedClusterStateUpdateTask

use of org.elasticsearch.cluster.AckedClusterStateUpdateTask in project crate by crate.

the class RepositoriesService method registerRepository.

/**
 * Registers new repository in the cluster
 * <p>
 * This method can be only called on the master node. It tries to create a new repository on the master
 * and if it was successful it adds new repository to cluster metadata.
 *
 * @param request  register repository request
 * @param listener register repository listener
 */
public void registerRepository(final PutRepositoryRequest request, final ActionListener<ClusterStateUpdateResponse> listener) {
    final RepositoryMetadata newRepositoryMetadata = new RepositoryMetadata(request.name(), request.type(), request.settings());
    final ActionListener<ClusterStateUpdateResponse> registrationListener;
    if (request.verify()) {
        registrationListener = ActionListener.delegateFailure(listener, (delegatedListener, clusterStateUpdateResponse) -> {
            if (clusterStateUpdateResponse.isAcknowledged()) {
                // The response was acknowledged - all nodes should know about the new repository, let's verify them
                verifyRepository(request.name(), ActionListener.delegateFailure(delegatedListener, (innerDelegatedListener, discoveryNodes) -> innerDelegatedListener.onResponse(clusterStateUpdateResponse)));
            } else {
                delegatedListener.onResponse(clusterStateUpdateResponse);
            }
        });
    } else {
        registrationListener = listener;
    }
    clusterService.submitStateUpdateTask("put_repository [" + request.name() + "]", new AckedClusterStateUpdateTask<ClusterStateUpdateResponse>(request, registrationListener) {

        @Override
        protected ClusterStateUpdateResponse newResponse(boolean acknowledged) {
            return new ClusterStateUpdateResponse(acknowledged);
        }

        @Override
        public ClusterState execute(ClusterState currentState) throws IOException {
            ensureRepositoryNotInUse(currentState, request.name());
            // Trying to create the new repository on master to make sure it works
            if (!registerRepository(newRepositoryMetadata)) {
                // The new repository has the same settings as the old one - ignore
                return currentState;
            }
            Metadata metadata = currentState.metadata();
            Metadata.Builder mdBuilder = Metadata.builder(currentState.metadata());
            RepositoriesMetadata repositories = metadata.custom(RepositoriesMetadata.TYPE);
            if (repositories == null) {
                LOGGER.info("put repository [{}]", request.name());
                repositories = new RepositoriesMetadata(Collections.singletonList(new RepositoryMetadata(request.name(), request.type(), request.settings())));
            } else {
                boolean found = false;
                List<RepositoryMetadata> repositoriesMetadata = new ArrayList<>(repositories.repositories().size() + 1);
                for (RepositoryMetadata repositoryMetadata : repositories.repositories()) {
                    if (repositoryMetadata.name().equals(newRepositoryMetadata.name())) {
                        if (newRepositoryMetadata.equalsIgnoreGenerations(repositoryMetadata)) {
                            // Previous version is the same as this one no update is needed.
                            return currentState;
                        }
                        found = true;
                        repositoriesMetadata.add(newRepositoryMetadata);
                    } else {
                        repositoriesMetadata.add(repositoryMetadata);
                    }
                }
                if (!found) {
                    LOGGER.info("put repository [{}]", request.name());
                    repositoriesMetadata.add(new RepositoryMetadata(request.name(), request.type(), request.settings()));
                } else {
                    LOGGER.info("update repository [{}]", request.name());
                }
                repositories = new RepositoriesMetadata(repositoriesMetadata);
            }
            mdBuilder.putCustom(RepositoriesMetadata.TYPE, repositories);
            return ClusterState.builder(currentState).metadata(mdBuilder).build();
        }

        @Override
        public void onFailure(String source, Exception e) {
            LOGGER.warn(() -> new ParameterizedMessage("failed to create repository [{}]", request.name()), e);
            super.onFailure(source, e);
        }

        @Override
        public boolean mustAck(DiscoveryNode discoveryNode) {
            // repository is created on both master and data nodes
            return discoveryNode.isMasterEligibleNode() || discoveryNode.isDataNode();
        }
    });
}
Also used : DeleteRepositoryRequest(org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryRequest) AckedClusterStateUpdateTask(org.elasticsearch.cluster.AckedClusterStateUpdateTask) ClusterService(org.elasticsearch.cluster.service.ClusterService) HashMap(java.util.HashMap) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) ArrayList(java.util.ArrayList) RepositoryMetadata(org.elasticsearch.cluster.metadata.RepositoryMetadata) PutRepositoryRequest(org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest) ClusterState(org.elasticsearch.cluster.ClusterState) Metadata(org.elasticsearch.cluster.metadata.Metadata) DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) RepositoriesMetadata(org.elasticsearch.cluster.metadata.RepositoriesMetadata) Settings(org.elasticsearch.common.settings.Settings) Map(java.util.Map) Regex(org.elasticsearch.common.regex.Regex) ThreadPool(org.elasticsearch.threadpool.ThreadPool) TransportService(org.elasticsearch.transport.TransportService) ActionRunnable(org.elasticsearch.action.ActionRunnable) ClusterStateApplier(org.elasticsearch.cluster.ClusterStateApplier) SnapshotsService(org.elasticsearch.snapshots.SnapshotsService) Collection(java.util.Collection) IOUtils(io.crate.common.io.IOUtils) IOException(java.io.IOException) RestoreService(org.elasticsearch.snapshots.RestoreService) ClusterChangedEvent(org.elasticsearch.cluster.ClusterChangedEvent) List(java.util.List) Logger(org.apache.logging.log4j.Logger) ClusterStateUpdateResponse(org.elasticsearch.cluster.ack.ClusterStateUpdateResponse) Collections(java.util.Collections) LogManager(org.apache.logging.log4j.LogManager) ActionListener(org.elasticsearch.action.ActionListener) ClusterState(org.elasticsearch.cluster.ClusterState) DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) RepositoryMetadata(org.elasticsearch.cluster.metadata.RepositoryMetadata) Metadata(org.elasticsearch.cluster.metadata.Metadata) RepositoriesMetadata(org.elasticsearch.cluster.metadata.RepositoriesMetadata) IOException(java.io.IOException) IOException(java.io.IOException) RepositoriesMetadata(org.elasticsearch.cluster.metadata.RepositoriesMetadata) RepositoryMetadata(org.elasticsearch.cluster.metadata.RepositoryMetadata) ArrayList(java.util.ArrayList) List(java.util.List) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) ClusterStateUpdateResponse(org.elasticsearch.cluster.ack.ClusterStateUpdateResponse)

Example 2 with AckedClusterStateUpdateTask

use of org.elasticsearch.cluster.AckedClusterStateUpdateTask in project crate by crate.

the class TransportClusterUpdateSettingsAction method masterOperation.

@Override
protected void masterOperation(final ClusterUpdateSettingsRequest request, final ClusterState state, final ActionListener<ClusterUpdateSettingsResponse> listener) {
    final SettingsUpdater updater = new SettingsUpdater(clusterSettings);
    clusterService.submitStateUpdateTask("cluster_update_settings", new AckedClusterStateUpdateTask<>(Priority.IMMEDIATE, request, listener) {

        private volatile boolean changed = false;

        @Override
        protected ClusterUpdateSettingsResponse newResponse(boolean acknowledged) {
            return new ClusterUpdateSettingsResponse(acknowledged, updater.getTransientUpdates(), updater.getPersistentUpdate());
        }

        @Override
        public void onAllNodesAcked(@Nullable Exception e) {
            if (changed) {
                reroute(true);
            } else {
                super.onAllNodesAcked(e);
            }
        }

        @Override
        public void onAckTimeout() {
            if (changed) {
                reroute(false);
            } else {
                super.onAckTimeout();
            }
        }

        private void reroute(final boolean updateSettingsAcked) {
            // so we should *not* execute the reroute.
            if (!clusterService.state().nodes().isLocalNodeElectedMaster()) {
                logger.debug("Skipping reroute after cluster update settings, because node is no longer master");
                listener.onResponse(new ClusterUpdateSettingsResponse(updateSettingsAcked, updater.getTransientUpdates(), updater.getPersistentUpdate()));
                return;
            }
            // The reason the reroute needs to be send as separate update task, is that all the *cluster* settings are encapsulate
            // in the components (e.g. FilterAllocationDecider), so the changes made by the first call aren't visible
            // to the components until the ClusterStateListener instances have been invoked, but are visible after
            // the first update task has been completed.
            clusterService.submitStateUpdateTask("reroute_after_cluster_update_settings", new AckedClusterStateUpdateTask<ClusterUpdateSettingsResponse>(Priority.URGENT, request, listener) {

                @Override
                public boolean mustAck(DiscoveryNode discoveryNode) {
                    // we wait for the reroute ack only if the update settings was acknowledged
                    return updateSettingsAcked;
                }

                @Override
                protected // update settings was acknowledged
                ClusterUpdateSettingsResponse newResponse(boolean acknowledged) {
                    return new ClusterUpdateSettingsResponse(updateSettingsAcked && acknowledged, updater.getTransientUpdates(), updater.getPersistentUpdate());
                }

                @Override
                public void onNoLongerMaster(String source) {
                    logger.debug("failed to preform reroute after cluster settings were updated - current node is no longer a master");
                    listener.onResponse(new ClusterUpdateSettingsResponse(updateSettingsAcked, updater.getTransientUpdates(), updater.getPersistentUpdate()));
                }

                @Override
                public void onFailure(String source, Exception e) {
                    // if the reroute fails we only log
                    logger.debug(() -> new ParameterizedMessage("failed to perform [{}]", source), e);
                    listener.onFailure(new ElasticsearchException("reroute after update settings failed", e));
                }

                @Override
                public ClusterState execute(final ClusterState currentState) {
                    // now, reroute in case things that require it changed (e.g. number of replicas)
                    return allocationService.reroute(currentState, "reroute after cluster update settings");
                }
            });
        }

        @Override
        public void onFailure(String source, Exception e) {
            logger.debug(() -> new ParameterizedMessage("failed to perform [{}]", source), e);
            super.onFailure(source, e);
        }

        @Override
        public ClusterState execute(final ClusterState currentState) {
            final ClusterState clusterState = updater.updateSettings(currentState, clusterSettings.upgradeSettings(request.transientSettings()), clusterSettings.upgradeSettings(request.persistentSettings()), logger);
            changed = clusterState != currentState;
            return clusterState;
        }
    });
}
Also used : ClusterState(org.elasticsearch.cluster.ClusterState) DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) AckedClusterStateUpdateTask(org.elasticsearch.cluster.AckedClusterStateUpdateTask) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) ElasticsearchException(org.elasticsearch.ElasticsearchException) ElasticsearchException(org.elasticsearch.ElasticsearchException) IOException(java.io.IOException) ClusterBlockException(org.elasticsearch.cluster.block.ClusterBlockException)

Example 3 with AckedClusterStateUpdateTask

use of org.elasticsearch.cluster.AckedClusterStateUpdateTask in project elasticsearch by elastic.

the class MetaDataCreateIndexService method onlyCreateIndex.

private void onlyCreateIndex(final CreateIndexClusterStateUpdateRequest request, final ActionListener<ClusterStateUpdateResponse> listener) {
    Settings.Builder updatedSettingsBuilder = Settings.builder();
    updatedSettingsBuilder.put(request.settings()).normalizePrefix(IndexMetaData.INDEX_SETTING_PREFIX);
    indexScopedSettings.validate(updatedSettingsBuilder);
    request.settings(updatedSettingsBuilder.build());
    clusterService.submitStateUpdateTask("create-index [" + request.index() + "], cause [" + request.cause() + "]", new AckedClusterStateUpdateTask<ClusterStateUpdateResponse>(Priority.URGENT, request, wrapPreservingContext(listener)) {

        @Override
        protected ClusterStateUpdateResponse newResponse(boolean acknowledged) {
            return new ClusterStateUpdateResponse(acknowledged);
        }

        @Override
        public ClusterState execute(ClusterState currentState) throws Exception {
            Index createdIndex = null;
            String removalExtraInfo = null;
            IndexRemovalReason removalReason = IndexRemovalReason.FAILURE;
            try {
                validate(request, currentState);
                for (Alias alias : request.aliases()) {
                    aliasValidator.validateAlias(alias, request.index(), currentState.metaData());
                }
                // we only find a template when its an API call (a new index)
                // find templates, highest order are better matching
                List<IndexTemplateMetaData> templates = findTemplates(request, currentState);
                Map<String, Custom> customs = new HashMap<>();
                // add the request mapping
                Map<String, Map<String, Object>> mappings = new HashMap<>();
                Map<String, AliasMetaData> templatesAliases = new HashMap<>();
                List<String> templateNames = new ArrayList<>();
                for (Map.Entry<String, String> entry : request.mappings().entrySet()) {
                    mappings.put(entry.getKey(), MapperService.parseMapping(xContentRegistry, entry.getValue()));
                }
                for (Map.Entry<String, Custom> entry : request.customs().entrySet()) {
                    customs.put(entry.getKey(), entry.getValue());
                }
                // apply templates, merging the mappings into the request mapping if exists
                for (IndexTemplateMetaData template : templates) {
                    templateNames.add(template.getName());
                    for (ObjectObjectCursor<String, CompressedXContent> cursor : template.mappings()) {
                        String mappingString = cursor.value.string();
                        if (mappings.containsKey(cursor.key)) {
                            XContentHelper.mergeDefaults(mappings.get(cursor.key), MapperService.parseMapping(xContentRegistry, mappingString));
                        } else {
                            mappings.put(cursor.key, MapperService.parseMapping(xContentRegistry, mappingString));
                        }
                    }
                    // handle custom
                    for (ObjectObjectCursor<String, Custom> cursor : template.customs()) {
                        String type = cursor.key;
                        IndexMetaData.Custom custom = cursor.value;
                        IndexMetaData.Custom existing = customs.get(type);
                        if (existing == null) {
                            customs.put(type, custom);
                        } else {
                            IndexMetaData.Custom merged = existing.mergeWith(custom);
                            customs.put(type, merged);
                        }
                    }
                    //handle aliases
                    for (ObjectObjectCursor<String, AliasMetaData> cursor : template.aliases()) {
                        AliasMetaData aliasMetaData = cursor.value;
                        // ignore this one taken from the index template
                        if (request.aliases().contains(new Alias(aliasMetaData.alias()))) {
                            continue;
                        }
                        //if an alias with same name was already processed, ignore this one
                        if (templatesAliases.containsKey(cursor.key)) {
                            continue;
                        }
                        //Allow templatesAliases to be templated by replacing a token with the name of the index that we are applying it to
                        if (aliasMetaData.alias().contains("{index}")) {
                            String templatedAlias = aliasMetaData.alias().replace("{index}", request.index());
                            aliasMetaData = AliasMetaData.newAliasMetaData(aliasMetaData, templatedAlias);
                        }
                        aliasValidator.validateAliasMetaData(aliasMetaData, request.index(), currentState.metaData());
                        templatesAliases.put(aliasMetaData.alias(), aliasMetaData);
                    }
                }
                Settings.Builder indexSettingsBuilder = Settings.builder();
                // apply templates, here, in reverse order, since first ones are better matching
                for (int i = templates.size() - 1; i >= 0; i--) {
                    indexSettingsBuilder.put(templates.get(i).settings());
                }
                // now, put the request settings, so they override templates
                indexSettingsBuilder.put(request.settings());
                if (indexSettingsBuilder.get(SETTING_NUMBER_OF_SHARDS) == null) {
                    indexSettingsBuilder.put(SETTING_NUMBER_OF_SHARDS, settings.getAsInt(SETTING_NUMBER_OF_SHARDS, 5));
                }
                if (indexSettingsBuilder.get(SETTING_NUMBER_OF_REPLICAS) == null) {
                    indexSettingsBuilder.put(SETTING_NUMBER_OF_REPLICAS, settings.getAsInt(SETTING_NUMBER_OF_REPLICAS, 1));
                }
                if (settings.get(SETTING_AUTO_EXPAND_REPLICAS) != null && indexSettingsBuilder.get(SETTING_AUTO_EXPAND_REPLICAS) == null) {
                    indexSettingsBuilder.put(SETTING_AUTO_EXPAND_REPLICAS, settings.get(SETTING_AUTO_EXPAND_REPLICAS));
                }
                if (indexSettingsBuilder.get(SETTING_VERSION_CREATED) == null) {
                    DiscoveryNodes nodes = currentState.nodes();
                    final Version createdVersion = Version.min(Version.CURRENT, nodes.getSmallestNonClientNodeVersion());
                    indexSettingsBuilder.put(SETTING_VERSION_CREATED, createdVersion);
                }
                if (indexSettingsBuilder.get(SETTING_CREATION_DATE) == null) {
                    indexSettingsBuilder.put(SETTING_CREATION_DATE, new DateTime(DateTimeZone.UTC).getMillis());
                }
                indexSettingsBuilder.put(IndexMetaData.SETTING_INDEX_PROVIDED_NAME, request.getProvidedName());
                indexSettingsBuilder.put(SETTING_INDEX_UUID, UUIDs.randomBase64UUID());
                final Index shrinkFromIndex = request.shrinkFrom();
                int routingNumShards = IndexMetaData.INDEX_NUMBER_OF_SHARDS_SETTING.get(indexSettingsBuilder.build());
                ;
                if (shrinkFromIndex != null) {
                    prepareShrinkIndexSettings(currentState, mappings.keySet(), indexSettingsBuilder, shrinkFromIndex, request.index());
                    IndexMetaData sourceMetaData = currentState.metaData().getIndexSafe(shrinkFromIndex);
                    routingNumShards = sourceMetaData.getRoutingNumShards();
                }
                Settings actualIndexSettings = indexSettingsBuilder.build();
                IndexMetaData.Builder tmpImdBuilder = IndexMetaData.builder(request.index()).setRoutingNumShards(routingNumShards);
                // Set up everything, now locally create the index to see that things are ok, and apply
                final IndexMetaData tmpImd = tmpImdBuilder.settings(actualIndexSettings).build();
                ActiveShardCount waitForActiveShards = request.waitForActiveShards();
                if (waitForActiveShards == ActiveShardCount.DEFAULT) {
                    waitForActiveShards = tmpImd.getWaitForActiveShards();
                }
                if (waitForActiveShards.validate(tmpImd.getNumberOfReplicas()) == false) {
                    throw new IllegalArgumentException("invalid wait_for_active_shards[" + request.waitForActiveShards() + "]: cannot be greater than number of shard copies [" + (tmpImd.getNumberOfReplicas() + 1) + "]");
                }
                // create the index here (on the master) to validate it can be created, as well as adding the mapping
                final IndexService indexService = indicesService.createIndex(tmpImd, Collections.emptyList(), shardId -> {
                });
                createdIndex = indexService.index();
                // now add the mappings
                MapperService mapperService = indexService.mapperService();
                try {
                    mapperService.merge(mappings, MergeReason.MAPPING_UPDATE, request.updateAllTypes());
                } catch (Exception e) {
                    removalExtraInfo = "failed on parsing default mapping/mappings on index creation";
                    throw e;
                }
                // the context is only used for validation so it's fine to pass fake values for the shard id and the current
                // timestamp
                final QueryShardContext queryShardContext = indexService.newQueryShardContext(0, null, () -> 0L);
                for (Alias alias : request.aliases()) {
                    if (Strings.hasLength(alias.filter())) {
                        aliasValidator.validateAliasFilter(alias.name(), alias.filter(), queryShardContext, xContentRegistry);
                    }
                }
                for (AliasMetaData aliasMetaData : templatesAliases.values()) {
                    if (aliasMetaData.filter() != null) {
                        aliasValidator.validateAliasFilter(aliasMetaData.alias(), aliasMetaData.filter().uncompressed(), queryShardContext, xContentRegistry);
                    }
                }
                // now, update the mappings with the actual source
                Map<String, MappingMetaData> mappingsMetaData = new HashMap<>();
                for (DocumentMapper mapper : mapperService.docMappers(true)) {
                    MappingMetaData mappingMd = new MappingMetaData(mapper);
                    mappingsMetaData.put(mapper.type(), mappingMd);
                }
                final IndexMetaData.Builder indexMetaDataBuilder = IndexMetaData.builder(request.index()).settings(actualIndexSettings).setRoutingNumShards(routingNumShards);
                for (MappingMetaData mappingMd : mappingsMetaData.values()) {
                    indexMetaDataBuilder.putMapping(mappingMd);
                }
                for (AliasMetaData aliasMetaData : templatesAliases.values()) {
                    indexMetaDataBuilder.putAlias(aliasMetaData);
                }
                for (Alias alias : request.aliases()) {
                    AliasMetaData aliasMetaData = AliasMetaData.builder(alias.name()).filter(alias.filter()).indexRouting(alias.indexRouting()).searchRouting(alias.searchRouting()).build();
                    indexMetaDataBuilder.putAlias(aliasMetaData);
                }
                for (Map.Entry<String, Custom> customEntry : customs.entrySet()) {
                    indexMetaDataBuilder.putCustom(customEntry.getKey(), customEntry.getValue());
                }
                indexMetaDataBuilder.state(request.state());
                final IndexMetaData indexMetaData;
                try {
                    indexMetaData = indexMetaDataBuilder.build();
                } catch (Exception e) {
                    removalExtraInfo = "failed to build index metadata";
                    throw e;
                }
                indexService.getIndexEventListener().beforeIndexAddedToCluster(indexMetaData.getIndex(), indexMetaData.getSettings());
                MetaData newMetaData = MetaData.builder(currentState.metaData()).put(indexMetaData, false).build();
                String maybeShadowIndicator = indexMetaData.isIndexUsingShadowReplicas() ? "s" : "";
                logger.info("[{}] creating index, cause [{}], templates {}, shards [{}]/[{}{}], mappings {}", request.index(), request.cause(), templateNames, indexMetaData.getNumberOfShards(), indexMetaData.getNumberOfReplicas(), maybeShadowIndicator, mappings.keySet());
                ClusterBlocks.Builder blocks = ClusterBlocks.builder().blocks(currentState.blocks());
                if (!request.blocks().isEmpty()) {
                    for (ClusterBlock block : request.blocks()) {
                        blocks.addIndexBlock(request.index(), block);
                    }
                }
                blocks.updateBlocks(indexMetaData);
                ClusterState updatedState = ClusterState.builder(currentState).blocks(blocks).metaData(newMetaData).build();
                if (request.state() == State.OPEN) {
                    RoutingTable.Builder routingTableBuilder = RoutingTable.builder(updatedState.routingTable()).addAsNew(updatedState.metaData().index(request.index()));
                    updatedState = allocationService.reroute(ClusterState.builder(updatedState).routingTable(routingTableBuilder.build()).build(), "index [" + request.index() + "] created");
                }
                removalExtraInfo = "cleaning up after validating index on master";
                removalReason = IndexRemovalReason.NO_LONGER_ASSIGNED;
                return updatedState;
            } finally {
                if (createdIndex != null) {
                    // Index was already partially created - need to clean up
                    indicesService.removeIndex(createdIndex, removalReason, removalExtraInfo);
                }
            }
        }

        @Override
        public void onFailure(String source, Exception e) {
            if (e instanceof ResourceAlreadyExistsException) {
                logger.trace((Supplier<?>) () -> new ParameterizedMessage("[{}] failed to create", request.index()), e);
            } else {
                logger.debug((Supplier<?>) () -> new ParameterizedMessage("[{}] failed to create", request.index()), e);
            }
            super.onFailure(source, e);
        }
    });
}
Also used : ElasticsearchException(org.elasticsearch.ElasticsearchException) SETTING_INDEX_UUID(org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_INDEX_UUID) DateTimeZone(org.joda.time.DateTimeZone) QueryShardContext(org.elasticsearch.index.query.QueryShardContext) Alias(org.elasticsearch.action.admin.indices.alias.Alias) Environment(org.elasticsearch.env.Environment) BiFunction(java.util.function.BiFunction) AllocationService(org.elasticsearch.cluster.routing.allocation.AllocationService) ClusterBlocks(org.elasticsearch.cluster.block.ClusterBlocks) ObjectObjectCursor(com.carrotsearch.hppc.cursors.ObjectObjectCursor) ClusterState(org.elasticsearch.cluster.ClusterState) Settings(org.elasticsearch.common.settings.Settings) CreateIndexClusterStateUpdateResponse(org.elasticsearch.cluster.ack.CreateIndexClusterStateUpdateResponse) ClusterBlock(org.elasticsearch.cluster.block.ClusterBlock) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) CompressedXContent(org.elasticsearch.common.compress.CompressedXContent) IndexNotFoundException(org.elasticsearch.index.IndexNotFoundException) IndexCreationException(org.elasticsearch.indices.IndexCreationException) Locale(java.util.Locale) Map(java.util.Map) ValidationException(org.elasticsearch.common.ValidationException) ThreadPool(org.elasticsearch.threadpool.ThreadPool) State(org.elasticsearch.cluster.metadata.IndexMetaData.State) Path(java.nio.file.Path) NamedXContentRegistry(org.elasticsearch.common.xcontent.NamedXContentRegistry) CreateIndexClusterStateUpdateRequest(org.elasticsearch.action.admin.indices.create.CreateIndexClusterStateUpdateRequest) Priority(org.elasticsearch.common.Priority) Predicate(java.util.function.Predicate) UUIDs(org.elasticsearch.common.UUIDs) Set(java.util.Set) ObjectCursor(com.carrotsearch.hppc.cursors.ObjectCursor) ActiveShardCount(org.elasticsearch.action.support.ActiveShardCount) ContextPreservingActionListener(org.elasticsearch.action.support.ContextPreservingActionListener) MapperService(org.elasticsearch.index.mapper.MapperService) List(java.util.List) Version(org.elasticsearch.Version) IndexRoutingTable(org.elasticsearch.cluster.routing.IndexRoutingTable) Supplier(org.apache.logging.log4j.util.Supplier) ClusterStateUpdateResponse(org.elasticsearch.cluster.ack.ClusterStateUpdateResponse) InvalidIndexNameException(org.elasticsearch.indices.InvalidIndexNameException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) ShardRouting(org.elasticsearch.cluster.routing.ShardRouting) AckedClusterStateUpdateTask(org.elasticsearch.cluster.AckedClusterStateUpdateTask) ClusterService(org.elasticsearch.cluster.service.ClusterService) HashMap(java.util.HashMap) Index(org.elasticsearch.index.Index) ShardRoutingState(org.elasticsearch.cluster.routing.ShardRoutingState) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) ResourceAlreadyExistsException(org.elasticsearch.ResourceAlreadyExistsException) ActiveShardsObserver(org.elasticsearch.action.support.ActiveShardsObserver) Strings(org.elasticsearch.common.Strings) Inject(org.elasticsearch.common.inject.Inject) ArrayList(java.util.ArrayList) SETTING_NUMBER_OF_REPLICAS(org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_REPLICAS) XContentHelper(org.elasticsearch.common.xcontent.XContentHelper) IndexRemovalReason(org.elasticsearch.indices.cluster.IndicesClusterStateService.AllocatedIndices.IndexRemovalReason) Custom(org.elasticsearch.cluster.metadata.IndexMetaData.Custom) Regex(org.elasticsearch.common.regex.Regex) SETTING_VERSION_CREATED(org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_VERSION_CREATED) IndicesService(org.elasticsearch.indices.IndicesService) SETTING_AUTO_EXPAND_REPLICAS(org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_AUTO_EXPAND_REPLICAS) ClusterBlockLevel(org.elasticsearch.cluster.block.ClusterBlockLevel) SETTING_CREATION_DATE(org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_CREATION_DATE) PathUtils(org.elasticsearch.common.io.PathUtils) DocumentMapper(org.elasticsearch.index.mapper.DocumentMapper) DiscoveryNodes(org.elasticsearch.cluster.node.DiscoveryNodes) AbstractComponent(org.elasticsearch.common.component.AbstractComponent) SETTING_NUMBER_OF_SHARDS(org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_SHARDS) IndexService(org.elasticsearch.index.IndexService) DateTime(org.joda.time.DateTime) IOException(java.io.IOException) IndexScopedSettings(org.elasticsearch.common.settings.IndexScopedSettings) CollectionUtil(org.apache.lucene.util.CollectionUtil) RoutingTable(org.elasticsearch.cluster.routing.RoutingTable) MergeReason(org.elasticsearch.index.mapper.MapperService.MergeReason) Comparator(java.util.Comparator) Collections(java.util.Collections) ActionListener(org.elasticsearch.action.ActionListener) IndexService(org.elasticsearch.index.IndexService) Index(org.elasticsearch.index.Index) DateTime(org.joda.time.DateTime) ClusterBlock(org.elasticsearch.cluster.block.ClusterBlock) Version(org.elasticsearch.Version) QueryShardContext(org.elasticsearch.index.query.QueryShardContext) List(java.util.List) ArrayList(java.util.ArrayList) Supplier(org.apache.logging.log4j.util.Supplier) CreateIndexClusterStateUpdateResponse(org.elasticsearch.cluster.ack.CreateIndexClusterStateUpdateResponse) ClusterStateUpdateResponse(org.elasticsearch.cluster.ack.ClusterStateUpdateResponse) Settings(org.elasticsearch.common.settings.Settings) IndexScopedSettings(org.elasticsearch.common.settings.IndexScopedSettings) DiscoveryNodes(org.elasticsearch.cluster.node.DiscoveryNodes) ClusterState(org.elasticsearch.cluster.ClusterState) DocumentMapper(org.elasticsearch.index.mapper.DocumentMapper) ResourceAlreadyExistsException(org.elasticsearch.ResourceAlreadyExistsException) Custom(org.elasticsearch.cluster.metadata.IndexMetaData.Custom) ActiveShardCount(org.elasticsearch.action.support.ActiveShardCount) ElasticsearchException(org.elasticsearch.ElasticsearchException) IndexNotFoundException(org.elasticsearch.index.IndexNotFoundException) IndexCreationException(org.elasticsearch.indices.IndexCreationException) ValidationException(org.elasticsearch.common.ValidationException) InvalidIndexNameException(org.elasticsearch.indices.InvalidIndexNameException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) ResourceAlreadyExistsException(org.elasticsearch.ResourceAlreadyExistsException) IOException(java.io.IOException) IndexRemovalReason(org.elasticsearch.indices.cluster.IndicesClusterStateService.AllocatedIndices.IndexRemovalReason) Alias(org.elasticsearch.action.admin.indices.alias.Alias) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) ObjectObjectCursor(com.carrotsearch.hppc.cursors.ObjectObjectCursor) Map(java.util.Map) HashMap(java.util.HashMap) MapperService(org.elasticsearch.index.mapper.MapperService)

Example 4 with AckedClusterStateUpdateTask

use of org.elasticsearch.cluster.AckedClusterStateUpdateTask in project elasticsearch by elastic.

the class TransportClusterUpdateSettingsAction method masterOperation.

@Override
protected void masterOperation(final ClusterUpdateSettingsRequest request, final ClusterState state, final ActionListener<ClusterUpdateSettingsResponse> listener) {
    final SettingsUpdater updater = new SettingsUpdater(clusterSettings);
    clusterService.submitStateUpdateTask("cluster_update_settings", new AckedClusterStateUpdateTask<ClusterUpdateSettingsResponse>(Priority.IMMEDIATE, request, listener) {

        private volatile boolean changed = false;

        @Override
        protected ClusterUpdateSettingsResponse newResponse(boolean acknowledged) {
            return new ClusterUpdateSettingsResponse(acknowledged, updater.getTransientUpdates(), updater.getPersistentUpdate());
        }

        @Override
        public void onAllNodesAcked(@Nullable Exception e) {
            if (changed) {
                reroute(true);
            } else {
                super.onAllNodesAcked(e);
            }
        }

        @Override
        public void onAckTimeout() {
            if (changed) {
                reroute(false);
            } else {
                super.onAckTimeout();
            }
        }

        private void reroute(final boolean updateSettingsAcked) {
            // so we should *not* execute the reroute.
            if (!clusterService.state().nodes().isLocalNodeElectedMaster()) {
                logger.debug("Skipping reroute after cluster update settings, because node is no longer master");
                listener.onResponse(new ClusterUpdateSettingsResponse(updateSettingsAcked, updater.getTransientUpdates(), updater.getPersistentUpdate()));
                return;
            }
            // The reason the reroute needs to be send as separate update task, is that all the *cluster* settings are encapsulate
            // in the components (e.g. FilterAllocationDecider), so the changes made by the first call aren't visible
            // to the components until the ClusterStateListener instances have been invoked, but are visible after
            // the first update task has been completed.
            clusterService.submitStateUpdateTask("reroute_after_cluster_update_settings", new AckedClusterStateUpdateTask<ClusterUpdateSettingsResponse>(Priority.URGENT, request, listener) {

                @Override
                public boolean mustAck(DiscoveryNode discoveryNode) {
                    //we wait for the reroute ack only if the update settings was acknowledged
                    return updateSettingsAcked;
                }

                @Override
                protected // update settings was acknowledged
                ClusterUpdateSettingsResponse newResponse(boolean acknowledged) {
                    return new ClusterUpdateSettingsResponse(updateSettingsAcked && acknowledged, updater.getTransientUpdates(), updater.getPersistentUpdate());
                }

                @Override
                public void onNoLongerMaster(String source) {
                    logger.debug("failed to preform reroute after cluster settings were updated - current node is no longer a master");
                    listener.onResponse(new ClusterUpdateSettingsResponse(updateSettingsAcked, updater.getTransientUpdates(), updater.getPersistentUpdate()));
                }

                @Override
                public void onFailure(String source, Exception e) {
                    //if the reroute fails we only log
                    logger.debug((Supplier<?>) () -> new ParameterizedMessage("failed to perform [{}]", source), e);
                    listener.onFailure(new ElasticsearchException("reroute after update settings failed", e));
                }

                @Override
                public ClusterState execute(final ClusterState currentState) {
                    // now, reroute in case things that require it changed (e.g. number of replicas)
                    return allocationService.reroute(currentState, "reroute after cluster update settings");
                }
            });
        }

        @Override
        public void onFailure(String source, Exception e) {
            logger.debug((Supplier<?>) () -> new ParameterizedMessage("failed to perform [{}]", source), e);
            super.onFailure(source, e);
        }

        @Override
        public ClusterState execute(final ClusterState currentState) {
            ClusterState clusterState = updater.updateSettings(currentState, request.transientSettings(), request.persistentSettings());
            changed = clusterState != currentState;
            return clusterState;
        }
    });
}
Also used : ClusterState(org.elasticsearch.cluster.ClusterState) DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) ElasticsearchException(org.elasticsearch.ElasticsearchException) ElasticsearchException(org.elasticsearch.ElasticsearchException) ClusterBlockException(org.elasticsearch.cluster.block.ClusterBlockException) AckedClusterStateUpdateTask(org.elasticsearch.cluster.AckedClusterStateUpdateTask) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) Supplier(org.apache.logging.log4j.util.Supplier)

Example 5 with AckedClusterStateUpdateTask

use of org.elasticsearch.cluster.AckedClusterStateUpdateTask in project crate by crate.

the class MetadataUpdateSettingsService method updateSettings.

public void updateSettings(final UpdateSettingsClusterStateUpdateRequest request, final ActionListener<ClusterStateUpdateResponse> listener) {
    final Settings normalizedSettings = Settings.builder().put(request.settings()).normalizePrefix(IndexMetadata.INDEX_SETTING_PREFIX).build();
    Settings.Builder settingsForClosedIndices = Settings.builder();
    Settings.Builder settingsForOpenIndices = Settings.builder();
    final Set<String> skippedSettings = new HashSet<>();
    indexScopedSettings.validate(// don't validate wildcards
    normalizedSettings.filter(s -> Regex.isSimpleMatchPattern(s) == false), // don't validate dependencies here we check it below never allow to change the number of shards
    false, // validate internal or private index settings
    true);
    for (String key : normalizedSettings.keySet()) {
        Setting setting = indexScopedSettings.get(key);
        boolean isWildcard = setting == null && Regex.isSimpleMatchPattern(key);
        assert // we already validated the normalized settings
        setting != null || (isWildcard && normalizedSettings.hasValue(key) == false) : "unknown setting: " + key + " isWildcard: " + isWildcard + " hasValue: " + normalizedSettings.hasValue(key);
        settingsForClosedIndices.copy(key, normalizedSettings);
        if (isWildcard || setting.isDynamic()) {
            settingsForOpenIndices.copy(key, normalizedSettings);
        } else {
            skippedSettings.add(key);
        }
    }
    final Settings closedSettings = settingsForClosedIndices.build();
    final Settings openSettings = settingsForOpenIndices.build();
    final boolean preserveExisting = request.isPreserveExisting();
    clusterService.submitStateUpdateTask("update-settings", new AckedClusterStateUpdateTask<ClusterStateUpdateResponse>(Priority.URGENT, request, listener) {

        @Override
        protected ClusterStateUpdateResponse newResponse(boolean acknowledged) {
            return new ClusterStateUpdateResponse(acknowledged);
        }

        @Override
        public ClusterState execute(ClusterState currentState) {
            RoutingTable.Builder routingTableBuilder = RoutingTable.builder(currentState.routingTable());
            Metadata.Builder metadataBuilder = Metadata.builder(currentState.metadata());
            // allow to change any settings to a close index, and only allow dynamic settings to be changed
            // on an open index
            Set<Index> openIndices = new HashSet<>();
            Set<Index> closeIndices = new HashSet<>();
            final String[] actualIndices = new String[request.indices().length];
            for (int i = 0; i < request.indices().length; i++) {
                Index index = request.indices()[i];
                actualIndices[i] = index.getName();
                final IndexMetadata metadata = currentState.metadata().getIndexSafe(index);
                if (metadata.getState() == IndexMetadata.State.OPEN) {
                    openIndices.add(index);
                } else {
                    closeIndices.add(index);
                }
            }
            if (!skippedSettings.isEmpty() && !openIndices.isEmpty()) {
                throw new IllegalArgumentException(String.format(Locale.ROOT, "Can't update non dynamic settings [%s] for open indices %s", skippedSettings, openIndices));
            }
            if (IndexMetadata.INDEX_NUMBER_OF_REPLICAS_SETTING.exists(openSettings)) {
                final int updatedNumberOfReplicas = IndexMetadata.INDEX_NUMBER_OF_REPLICAS_SETTING.get(openSettings);
                if (preserveExisting == false) {
                    // Verify that this won't take us over the cluster shard limit.
                    int totalNewShards = Arrays.stream(request.indices()).mapToInt(i -> getTotalNewShards(i, currentState, updatedNumberOfReplicas)).sum();
                    Optional<String> error = shardLimitValidator.checkShardLimit(totalNewShards, currentState);
                    if (error.isPresent()) {
                        ValidationException ex = new ValidationException();
                        ex.addValidationError(error.get());
                        throw ex;
                    }
                    /*
                                 * We do not update the in-sync allocation IDs as they will be removed upon the first index operation which makes
                                 * these copies stale.
                                 *
                                 * TODO: should we update the in-sync allocation IDs once the data is deleted by the node?
                                 */
                    routingTableBuilder.updateNumberOfReplicas(updatedNumberOfReplicas, actualIndices);
                    metadataBuilder.updateNumberOfReplicas(updatedNumberOfReplicas, actualIndices);
                    LOGGER.info("updating number_of_replicas to [{}] for indices {}", updatedNumberOfReplicas, actualIndices);
                }
            }
            ClusterBlocks.Builder blocks = ClusterBlocks.builder().blocks(currentState.blocks());
            maybeUpdateClusterBlock(actualIndices, blocks, IndexMetadata.INDEX_READ_ONLY_BLOCK, IndexMetadata.INDEX_READ_ONLY_SETTING, openSettings);
            maybeUpdateClusterBlock(actualIndices, blocks, IndexMetadata.INDEX_READ_ONLY_ALLOW_DELETE_BLOCK, IndexMetadata.INDEX_BLOCKS_READ_ONLY_ALLOW_DELETE_SETTING, openSettings);
            maybeUpdateClusterBlock(actualIndices, blocks, IndexMetadata.INDEX_METADATA_BLOCK, IndexMetadata.INDEX_BLOCKS_METADATA_SETTING, openSettings);
            maybeUpdateClusterBlock(actualIndices, blocks, IndexMetadata.INDEX_WRITE_BLOCK, IndexMetadata.INDEX_BLOCKS_WRITE_SETTING, openSettings);
            maybeUpdateClusterBlock(actualIndices, blocks, IndexMetadata.INDEX_READ_BLOCK, IndexMetadata.INDEX_BLOCKS_READ_SETTING, openSettings);
            if (!openIndices.isEmpty()) {
                for (Index index : openIndices) {
                    IndexMetadata indexMetadata = metadataBuilder.getSafe(index);
                    Settings.Builder updates = Settings.builder();
                    Settings.Builder indexSettings = Settings.builder().put(indexMetadata.getSettings());
                    if (indexScopedSettings.updateDynamicSettings(openSettings, indexSettings, updates, index.getName())) {
                        if (preserveExisting) {
                            indexSettings.put(indexMetadata.getSettings());
                        }
                        Settings finalSettings = indexSettings.build();
                        indexScopedSettings.validate(finalSettings.filter(k -> indexScopedSettings.isPrivateSetting(k) == false), true);
                        metadataBuilder.put(IndexMetadata.builder(indexMetadata).settings(finalSettings));
                    }
                }
            }
            if (!closeIndices.isEmpty()) {
                for (Index index : closeIndices) {
                    IndexMetadata indexMetadata = metadataBuilder.getSafe(index);
                    Settings.Builder updates = Settings.builder();
                    Settings.Builder indexSettings = Settings.builder().put(indexMetadata.getSettings());
                    if (indexScopedSettings.updateSettings(closedSettings, indexSettings, updates, index.getName())) {
                        if (preserveExisting) {
                            indexSettings.put(indexMetadata.getSettings());
                        }
                        Settings finalSettings = indexSettings.build();
                        indexScopedSettings.validate(finalSettings.filter(k -> indexScopedSettings.isPrivateSetting(k) == false), true);
                        metadataBuilder.put(IndexMetadata.builder(indexMetadata).settings(finalSettings));
                    }
                }
            }
            // increment settings versions
            for (final String index : actualIndices) {
                if (same(currentState.metadata().index(index).getSettings(), metadataBuilder.get(index).getSettings()) == false) {
                    final IndexMetadata.Builder builder = IndexMetadata.builder(metadataBuilder.get(index));
                    builder.settingsVersion(1 + builder.settingsVersion());
                    metadataBuilder.put(builder);
                }
            }
            ClusterState updatedState = ClusterState.builder(currentState).metadata(metadataBuilder).routingTable(routingTableBuilder.build()).blocks(blocks).build();
            // now, reroute in case things change that require it (like number of replicas)
            updatedState = allocationService.reroute(updatedState, "settings update");
            try {
                for (Index index : openIndices) {
                    final IndexMetadata currentMetadata = currentState.getMetadata().getIndexSafe(index);
                    final IndexMetadata updatedMetadata = updatedState.metadata().getIndexSafe(index);
                    indicesService.verifyIndexMetadata(currentMetadata, updatedMetadata);
                }
                for (Index index : closeIndices) {
                    final IndexMetadata currentMetadata = currentState.getMetadata().getIndexSafe(index);
                    final IndexMetadata updatedMetadata = updatedState.metadata().getIndexSafe(index);
                    // Verifies that the current index settings can be updated with the updated dynamic settings.
                    indicesService.verifyIndexMetadata(currentMetadata, updatedMetadata);
                    // Now check that we can create the index with the updated settings (dynamic and non-dynamic).
                    // This step is mandatory since we allow to update non-dynamic settings on closed indices.
                    indicesService.verifyIndexMetadata(updatedMetadata, updatedMetadata);
                }
            } catch (IOException ex) {
                throw new UncheckedIOException(ex);
            }
            return updatedState;
        }
    });
}
Also used : Arrays(java.util.Arrays) AckedClusterStateUpdateTask(org.elasticsearch.cluster.AckedClusterStateUpdateTask) Tuple(io.crate.common.collections.Tuple) ShardLimitValidator(org.elasticsearch.indices.ShardLimitValidator) ClusterService(org.elasticsearch.cluster.service.ClusterService) AllocationService(org.elasticsearch.cluster.routing.allocation.AllocationService) UpgradeSettingsClusterStateUpdateRequest(org.elasticsearch.action.admin.indices.upgrade.post.UpgradeSettingsClusterStateUpdateRequest) ClusterBlocks(org.elasticsearch.cluster.block.ClusterBlocks) Index(org.elasticsearch.index.Index) Inject(org.elasticsearch.common.inject.Inject) HashSet(java.util.HashSet) ClusterState(org.elasticsearch.cluster.ClusterState) Settings(org.elasticsearch.common.settings.Settings) ClusterBlock(org.elasticsearch.cluster.block.ClusterBlock) Locale(java.util.Locale) Map(java.util.Map) Regex(org.elasticsearch.common.regex.Regex) ValidationException(org.elasticsearch.common.ValidationException) IndicesService(org.elasticsearch.indices.IndicesService) Priority(org.elasticsearch.common.Priority) Setting(org.elasticsearch.common.settings.Setting) IndexSettings.same(org.elasticsearch.index.IndexSettings.same) Set(java.util.Set) IOException(java.io.IOException) IndexScopedSettings(org.elasticsearch.common.settings.IndexScopedSettings) UncheckedIOException(java.io.UncheckedIOException) Logger(org.apache.logging.log4j.Logger) Version(org.elasticsearch.Version) RoutingTable(org.elasticsearch.cluster.routing.RoutingTable) Optional(java.util.Optional) ClusterStateUpdateResponse(org.elasticsearch.cluster.ack.ClusterStateUpdateResponse) UpdateSettingsClusterStateUpdateRequest(org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsClusterStateUpdateRequest) LogManager(org.apache.logging.log4j.LogManager) ActionListener(org.elasticsearch.action.ActionListener) ClusterState(org.elasticsearch.cluster.ClusterState) HashSet(java.util.HashSet) Set(java.util.Set) ValidationException(org.elasticsearch.common.ValidationException) Optional(java.util.Optional) Setting(org.elasticsearch.common.settings.Setting) Index(org.elasticsearch.index.Index) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) UncheckedIOException(java.io.UncheckedIOException) ClusterStateUpdateResponse(org.elasticsearch.cluster.ack.ClusterStateUpdateResponse) Settings(org.elasticsearch.common.settings.Settings) IndexScopedSettings(org.elasticsearch.common.settings.IndexScopedSettings) HashSet(java.util.HashSet)

Aggregations

AckedClusterStateUpdateTask (org.elasticsearch.cluster.AckedClusterStateUpdateTask)6 ClusterState (org.elasticsearch.cluster.ClusterState)6 IOException (java.io.IOException)4 Map (java.util.Map)4 ParameterizedMessage (org.apache.logging.log4j.message.ParameterizedMessage)4 ElasticsearchException (org.elasticsearch.ElasticsearchException)4 DiscoveryNode (org.elasticsearch.cluster.node.DiscoveryNode)4 Settings (org.elasticsearch.common.settings.Settings)4 ArrayList (java.util.ArrayList)3 HashMap (java.util.HashMap)3 List (java.util.List)3 Set (java.util.Set)3 LogManager (org.apache.logging.log4j.LogManager)3 Logger (org.apache.logging.log4j.Logger)3 Version (org.elasticsearch.Version)3 ActionListener (org.elasticsearch.action.ActionListener)3 ClusterStateUpdateResponse (org.elasticsearch.cluster.ack.ClusterStateUpdateResponse)3 ClusterBlocks (org.elasticsearch.cluster.block.ClusterBlocks)3 ClusterService (org.elasticsearch.cluster.service.ClusterService)3 Priority (org.elasticsearch.common.Priority)3