/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.facebook.presto.resourceGroups; import com.facebook.presto.spi.resourceGroups.SchedulingPolicy; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.collect.ImmutableList; import io.airlift.units.DataSize; import io.airlift.units.Duration; import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import static com.google.common.base.MoreObjects.toStringHelper; import static com.google.common.base.Preconditions.checkArgument; import static java.util.Objects.requireNonNull; public class ResourceGroupSpec { private static final Pattern PERCENT_PATTERN = Pattern.compile("(\\d{1,3}(:?\\.\\d+)?)%"); private final ResourceGroupNameTemplate name; private final Optional<DataSize> softMemoryLimit; private final Optional<Double> softMemoryLimitFraction; private final int maxQueued; private final int maxRunning; private final Optional<SchedulingPolicy> schedulingPolicy; private final Optional<Integer> schedulingWeight; private final List<ResourceGroupSpec> subGroups; private final Optional<Boolean> jmxExport; private final Optional<Duration> softCpuLimit; private final Optional<Duration> hardCpuLimit; @JsonCreator public ResourceGroupSpec( @JsonProperty("name") ResourceGroupNameTemplate name, @JsonProperty("softMemoryLimit") String softMemoryLimit, @JsonProperty("maxQueued") int maxQueued, @JsonProperty("maxRunning") int maxRunning, @JsonProperty("schedulingPolicy") Optional<String> schedulingPolicy, @JsonProperty("schedulingWeight") Optional<Integer> schedulingWeight, @JsonProperty("subGroups") Optional<List<ResourceGroupSpec>> subGroups, @JsonProperty("jmxExport") Optional<Boolean> jmxExport, @JsonProperty("softCpuLimit") Optional<Duration> softCpuLimit, @JsonProperty("hardCpuLimit") Optional<Duration> hardCpuLimit) { this.softCpuLimit = requireNonNull(softCpuLimit, "softCpuLimit is null"); this.hardCpuLimit = requireNonNull(hardCpuLimit, "hardCpuLimit is null"); this.jmxExport = requireNonNull(jmxExport, "jmxExport is null"); this.name = requireNonNull(name, "name is null"); checkArgument(maxQueued >= 0, "maxQueued is negative"); this.maxQueued = maxQueued; checkArgument(maxRunning >= 0, "maxRunning is negative"); this.maxRunning = maxRunning; this.schedulingPolicy = requireNonNull(schedulingPolicy, "schedulingPolicy is null").map(value -> SchedulingPolicy.valueOf(value.toUpperCase())); this.schedulingWeight = requireNonNull(schedulingWeight, "schedulingWeight is null"); requireNonNull(softMemoryLimit, "softMemoryLimit is null"); Optional<DataSize> absoluteSize; Optional<Double> fraction; Matcher matcher = PERCENT_PATTERN.matcher(softMemoryLimit); if (matcher.matches()) { absoluteSize = Optional.empty(); fraction = Optional.of(Double.parseDouble(matcher.group(1)) / 100.0); } else { absoluteSize = Optional.of(DataSize.valueOf(softMemoryLimit)); fraction = Optional.empty(); } this.softMemoryLimit = absoluteSize; this.softMemoryLimitFraction = fraction; this.subGroups = ImmutableList.copyOf(requireNonNull(subGroups, "subGroups is null").orElse(ImmutableList.of())); Set<ResourceGroupNameTemplate> names = new HashSet<>(); for (ResourceGroupSpec subGroup : this.subGroups) { checkArgument(!names.contains(subGroup.getName()), "Duplicated sub group: %s", subGroup.getName()); names.add(subGroup.getName()); } } public Optional<DataSize> getSoftMemoryLimit() { return softMemoryLimit; } public Optional<Double> getSoftMemoryLimitFraction() { return softMemoryLimitFraction; } public int getMaxQueued() { return maxQueued; } public int getMaxRunning() { return maxRunning; } public Optional<SchedulingPolicy> getSchedulingPolicy() { return schedulingPolicy; } public Optional<Integer> getSchedulingWeight() { return schedulingWeight; } public ResourceGroupNameTemplate getName() { return name; } public List<ResourceGroupSpec> getSubGroups() { return subGroups; } public Optional<Boolean> getJmxExport() { return jmxExport; } public Optional<Duration> getSoftCpuLimit() { return softCpuLimit; } public Optional<Duration> getHardCpuLimit() { return hardCpuLimit; } @Override public boolean equals(Object other) { if (other == this) { return true; } if (!(other instanceof ResourceGroupSpec)) { return false; } ResourceGroupSpec that = (ResourceGroupSpec) other; return (name.equals(that.name) && softMemoryLimit.equals(that.softMemoryLimit) && maxQueued == that.maxQueued && maxRunning == that.maxRunning && schedulingPolicy.equals(that.schedulingPolicy) && schedulingWeight.equals(that.schedulingWeight) && subGroups.equals(that.subGroups) && jmxExport.equals(that.jmxExport) && softCpuLimit.equals(that.softCpuLimit) && hardCpuLimit.equals(that.hardCpuLimit)); } // Subgroups not included, used to determine whether a group needs to be reconfigured public boolean sameConfig(ResourceGroupSpec other) { if (other == null) { return false; } return (name.equals(other.name) && softMemoryLimit.equals(other.softMemoryLimit) && maxQueued == other.maxQueued && maxRunning == other.maxRunning && schedulingPolicy.equals(other.schedulingPolicy) && schedulingWeight.equals(other.schedulingWeight) && jmxExport.equals(other.jmxExport) && softCpuLimit.equals(other.softCpuLimit) && hardCpuLimit.equals(other.hardCpuLimit)); } @Override public int hashCode() { return Objects.hash( name, softMemoryLimit, maxQueued, maxRunning, schedulingPolicy, schedulingWeight, subGroups, jmxExport, softCpuLimit, hardCpuLimit); } @Override public String toString() { return toStringHelper(this) .add("name", name) .add("softMemoryLimit", softMemoryLimit) .add("maxQueued", maxQueued) .add("maxRunning", maxRunning) .add("schedulingPolicy", schedulingPolicy) .add("schedulingWeight", schedulingWeight) .add("jmxExport", jmxExport) .add("softCpuLimit", softCpuLimit) .add("hardCpuLimit", hardCpuLimit) .toString(); } }