package ru.yandex.market.graphouse.retention; import com.google.common.base.Preconditions; import com.google.common.collect.Range; import com.google.common.collect.RangeMap; import com.google.common.collect.TreeRangeMap; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import java.util.stream.Collectors; /** * @author Vlad Vinogradov <a href="mailto:vladvin@yandex-team.ru"></a> * @date 23.11.16 */ public class MetricRetention { private final Pattern pattern; private final String function; private final RangeMap<Integer, Integer> ranges; private MetricRetention(Pattern pattern, String function) { this.pattern = pattern; this.function = function; this.ranges = TreeRangeMap.create(); } public String getFunction() { return function; } boolean matches(String name) { return pattern.matcher(name).matches(); } public int getStepSize(int ageSeconds) { Integer step = ranges.get(Math.max(ageSeconds, 0)); Preconditions.checkNotNull( step, "Could find retention step for age " + ageSeconds + ", values: " + ranges.toString() ); return step; } public static MetricDataRetentionBuilder newBuilder(String pattern, String function) { return new MetricDataRetentionBuilder(pattern, function); } public static class MetricDataRetentionBuilder { private final Map<Integer, Integer> ageRetentionMap = new HashMap<>(); private final MetricRetention result; public MetricDataRetentionBuilder(String pattern, String function) { result = new MetricRetention(Pattern.compile(pattern), function); } public MetricRetention build() { refillRetentions(); return result; } public MetricDataRetentionBuilder addRetention(int age, int retention) { ageRetentionMap.put(age, retention); return this; } private void refillRetentions() { result.ranges.clear(); int counter = 0; final int valuesMaxIndex = ageRetentionMap.values().size() - 1; final List<Map.Entry<Integer, Integer>> entryList = ageRetentionMap.entrySet() .stream() .sorted(Map.Entry.comparingByKey()) .collect(Collectors.toList()); for (Map.Entry<Integer, Integer> retention : entryList) { final Integer age = retention.getKey(); final Integer precision = retention.getValue(); final boolean isLast = (counter == valuesMaxIndex); if (!isLast) { final Integer nextAge = entryList.get(counter + 1).getKey(); result.ranges.put(Range.closedOpen(age, nextAge), precision); } else { result.ranges.put(Range.atLeast(age), precision); } counter++; } } } }