All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.yahoo.vespa.model.content.ClusterControllerConfig Maven / Gradle / Ivy

There is a newer version: 8.409.18
Show newest version
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.model.content;

import com.yahoo.config.model.deploy.DeployState;
import com.yahoo.config.model.producer.AbstractConfigProducerRoot;
import com.yahoo.config.model.producer.AnyConfigProducer;
import com.yahoo.config.model.producer.TreeConfigProducer;
import com.yahoo.vespa.config.content.FleetcontrollerConfig;
import com.yahoo.vespa.model.VespaModel;
import com.yahoo.vespa.model.builder.xml.dom.ModelElement;
import com.yahoo.vespa.model.builder.xml.dom.VespaDomBuilder;
import com.yahoo.vespa.model.content.cluster.ContentCluster;
import com.yahoo.vespa.model.utils.Duration;
import org.w3c.dom.Element;

import java.util.Optional;

/**
 * Config generation for parameters for fleet controllers.
 */
public class ClusterControllerConfig extends AnyConfigProducer implements FleetcontrollerConfig.Producer {

    public static class Builder extends VespaDomBuilder.DomConfigProducerBuilderBase {
        private final String clusterName;
        private final ModelElement clusterElement;
        private final ResourceLimits resourceLimits;

        public Builder(String clusterName, ModelElement clusterElement, ResourceLimits resourceLimits) {
            this.clusterName = clusterName;
            this.clusterElement = clusterElement;
            this.resourceLimits = resourceLimits;
        }

        @Override
        protected ClusterControllerConfig doBuild(DeployState deployState, TreeConfigProducer ancestor, Element producerSpec) {
            ModelElement tuning = clusterElement.child("tuning");
            ModelElement clusterControllerTuning = null;

            Optional minNodeRatioPerGroup = Optional.of(deployState.featureFlags().minNodeRatioPerGroup());
            Optional bucketSplittingMinimumBits = Optional.empty();
            if (tuning != null) {
                minNodeRatioPerGroup = Optional.ofNullable(tuning.childAsDouble("min-node-ratio-per-group"));
                bucketSplittingMinimumBits = Optional.ofNullable(tuning.childAsInteger("bucket-splitting.minimum-bits"));
                clusterControllerTuning = tuning.child("cluster-controller");
            }

            var numberOfLeafGroups = ((ContentCluster) ancestor).getRootGroup().getNumberOfLeafGroups();
            var tuningConfig = new ClusterControllerTuningBuilder(clusterControllerTuning,
                                                                  minNodeRatioPerGroup,
                                                                  bucketSplittingMinimumBits,
                                                                  numberOfLeafGroups)
                    .build();

            return new ClusterControllerConfig(ancestor,
                                               clusterName,
                                               tuningConfig,
                                               resourceLimits,
                                               deployState.featureFlags().distributionConfigFromClusterController());
        }

    }

    private final String clusterName;
    private final ClusterControllerTuning tuning;
    private final ResourceLimits resourceLimits;
    private final boolean distributionConfigFromClusterController;

    private ClusterControllerConfig(TreeConfigProducer parent,
                                    String clusterName,
                                    ClusterControllerTuning tuning,
                                    ResourceLimits resourceLimits,
                                    boolean distributionConfigFromClusterController) {
        super(parent, "fleetcontroller");
        this.clusterName = clusterName;
        this.tuning = tuning;
        this.resourceLimits = resourceLimits;
        this.distributionConfigFromClusterController = distributionConfigFromClusterController;
    }

    @Override
    public void getConfig(FleetcontrollerConfig.Builder builder) {
        AbstractConfigProducerRoot root = getRoot();
        if (root instanceof VespaModel) {
            String zooKeeperAddress = root.getAdmin().getZooKeepersConfigProvider().getZooKeepersConnectionSpec();
            builder.zookeeper_server(zooKeeperAddress);
        } else {
            builder.zookeeper_server("");
        }

        builder.index(0);
        builder.cluster_name(clusterName);
        builder.fleet_controller_count(getChildren().size());
        builder.include_distribution_config_in_cluster_state_bundle(distributionConfigFromClusterController);

        tuning.initProgressTime.ifPresent(i -> builder.init_progress_time((int) i.getMilliSeconds()));
        tuning.transitionTime.ifPresent(t -> builder.storage_transition_time((int) t.getMilliSeconds()));
        tuning.maxPrematureCrashes.ifPresent(var -> builder.max_premature_crashes(var.intValue()));
        tuning.stableStateTimePeriod.ifPresent(var -> builder.stable_state_time_period((int) var.getMilliSeconds()));
        tuning.minDistributorUpRatio.ifPresent(builder::min_distributor_up_ratio);
        tuning.minStorageUpRatio.ifPresent(builder::min_storage_up_ratio);
        tuning.minSplitBits.ifPresent(builder::ideal_distribution_bits);
        tuning.minNodeRatioPerGroup.ifPresent(builder::min_node_ratio_per_group);
        tuning.maxGroupsAllowedDown.ifPresent(builder::max_number_of_groups_allowed_to_be_down);

        resourceLimits.getConfig(builder);
    }

    public ClusterControllerTuning tuning() {return tuning;}

    private static class ClusterControllerTuningBuilder {

        private final Optional minNodeRatioPerGroup;
        private final Optional initProgressTime;
        private final Optional transitionTime;
        private final Optional maxPrematureCrashes;
        private final Optional stableStateTimePeriod;
        private final Optional minDistributorUpRatio;
        private final Optional minStorageUpRatio;
        private final Optional minSplitBits;
        private final Optional maxGroupsAllowedDown;

        ClusterControllerTuningBuilder(ModelElement tuning,
                                       Optional minNodeRatioPerGroup,
                                       Optional bucketSplittingMinimumBits,
                                       int numberOfLeafGroups) {
            this.minSplitBits = bucketSplittingMinimumBits;
            this.minNodeRatioPerGroup = minNodeRatioPerGroup;
            if (tuning == null) {
                this.initProgressTime = Optional.empty();
                this.transitionTime = Optional.empty();
                this.maxPrematureCrashes = Optional.empty();
                this.stableStateTimePeriod = Optional.empty();
                this.minDistributorUpRatio = Optional.empty();
                this.minStorageUpRatio = Optional.empty();
                this.maxGroupsAllowedDown = Optional.empty();
            }
            else {
                this.initProgressTime = Optional.ofNullable(tuning.childAsDuration("init-progress-time"));
                this.transitionTime = Optional.ofNullable(tuning.childAsDuration("transition-time"));
                this.maxPrematureCrashes = Optional.ofNullable(tuning.childAsLong("max-premature-crashes"));
                this.stableStateTimePeriod = Optional.ofNullable(tuning.childAsDuration("stable-state-period"));
                this.minDistributorUpRatio = Optional.ofNullable(tuning.childAsDouble("min-distributor-up-ratio"));
                this.minStorageUpRatio = Optional.ofNullable(tuning.childAsDouble("min-storage-up-ratio"));
                this.maxGroupsAllowedDown = maxGroupsAllowedDown(tuning, numberOfLeafGroups);
            }
        }


        private static Optional maxGroupsAllowedDown(ModelElement tuning, int numberOfLeafGroups) {
            var groupsAllowedDownRatio = tuning.childAsDouble("groups-allowed-down-ratio");

            if (groupsAllowedDownRatio != null) {
                if (groupsAllowedDownRatio < 0 || groupsAllowedDownRatio > 1)
                    throw new IllegalArgumentException("groups-allowed-down-ratio must be between 0 and 1, got " + groupsAllowedDownRatio);

                var maxGroupsAllowedDown = Math.max(1, (int) Math.floor(groupsAllowedDownRatio * numberOfLeafGroups));
                return Optional.of(maxGroupsAllowedDown);
            }

            return Optional.empty();
        }

        private ClusterControllerTuning build() {
            return new ClusterControllerTuning(initProgressTime,
                                               transitionTime,
                                               maxPrematureCrashes,
                                               stableStateTimePeriod,
                                               minDistributorUpRatio,
                                               minStorageUpRatio,
                                               maxGroupsAllowedDown,
                                               minNodeRatioPerGroup,
                                               minSplitBits);
        }

    }

    private record ClusterControllerTuning(Optional initProgressTime,
                                           Optional transitionTime,
                                           Optional maxPrematureCrashes,
                                           Optional stableStateTimePeriod,
                                           Optional minDistributorUpRatio,
                                           Optional minStorageUpRatio,
                                           Optional maxGroupsAllowedDown,
                                           Optional minNodeRatioPerGroup,
                                           Optional minSplitBits) {
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy