From 43f8f1ac725b30f3d91752fed51bbd8f59d9d5de Mon Sep 17 00:00:00 2001 From: Zhong Date: Wed, 2 Aug 2017 15:18:08 +0800 Subject: [PATCH] APACHE-KYLIN-2718: use Guava Library to check overflow when calculating combination --- .../main/java/org/apache/kylin/cube/model/AggregationGroup.java | 7 ++++--- core-cube/src/main/java/org/apache/kylin/cube/model/CubeDesc.java | 7 +++++++ .../kylin/cube/model/validation/rule/AggregationGroupRule.java | 7 +++++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/core-cube/src/main/java/org/apache/kylin/cube/model/AggregationGroup.java b/core-cube/src/main/java/org/apache/kylin/cube/model/AggregationGroup.java index 0533ea1..a123aff 100644 --- a/core-cube/src/main/java/org/apache/kylin/cube/model/AggregationGroup.java +++ b/core-cube/src/main/java/org/apache/kylin/cube/model/AggregationGroup.java @@ -37,6 +37,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.common.math.LongMath; @SuppressWarnings("serial") @JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE) @@ -304,14 +305,14 @@ public class AggregationGroup implements Serializable { Set hierarchyDims = new TreeSet<>(); for (String[] ss : selectRule.hierarchyDims) { hierarchyDims.addAll(Arrays.asList(ss)); - combination = combination * (ss.length + 1); + combination = LongMath.checkedMultiply(combination, (ss.length + 1)); } Set jointDims = new TreeSet<>(); for (String[] ss : selectRule.jointDims) { jointDims.addAll(Arrays.asList(ss)); - combination = combination * 2; } + combination = LongMath.checkedMultiply(combination, (1L << selectRule.jointDims.length)); Set normalDims = new TreeSet<>(); normalDims.addAll(includeDims); @@ -319,7 +320,7 @@ public class AggregationGroup implements Serializable { normalDims.removeAll(hierarchyDims); normalDims.removeAll(jointDims); - combination = combination * (1L << normalDims.size()); + combination = LongMath.checkedMultiply(combination, (1L << normalDims.size())); if (cubeDesc.getConfig().getCubeAggrGroupIsMandatoryOnlyValid() && !mandatoryDims.isEmpty()) { combination += 1; } diff --git a/core-cube/src/main/java/org/apache/kylin/cube/model/CubeDesc.java b/core-cube/src/main/java/org/apache/kylin/cube/model/CubeDesc.java index 56fc9fa..49bdf48 100644 --- a/core-cube/src/main/java/org/apache/kylin/cube/model/CubeDesc.java +++ b/core-cube/src/main/java/org/apache/kylin/cube/model/CubeDesc.java @@ -639,9 +639,16 @@ public class CubeDesc extends RootPersistentEntity implements IEngineAware { long combination = 0L; try { combination = agg.calculateCuboidCombination(); + } catch (ArithmeticException ae) { + combination = -1; } catch (Exception ex) { combination = config.getCubeAggrGroupMaxCombination() + 1; } finally { + if (combination < 0) { + String msg = "Aggregation group " + index + " has too many combinations, current combination is larger than Long.MAX_VALUE " + Long.MAX_VALUE + "; use 'mandatory'/'hierarchy'/'joint' to optimize; or remove less used columns from 'includes'"; + logger.error(msg); + throw new IllegalStateException(msg); + } if (combination > config.getCubeAggrGroupMaxCombination()) { String msg = "Aggregation group " + index + " has too many combinations, use 'mandatory'/'hierarchy'/'joint' to optimize; or update 'kylin.cube.aggrgroup.max-combination' to a bigger value."; logger.error("Aggregation group " + index + " has " + combination + " combinations;"); diff --git a/core-cube/src/main/java/org/apache/kylin/cube/model/validation/rule/AggregationGroupRule.java b/core-cube/src/main/java/org/apache/kylin/cube/model/validation/rule/AggregationGroupRule.java index 33fc390..8aa3424 100644 --- a/core-cube/src/main/java/org/apache/kylin/cube/model/validation/rule/AggregationGroupRule.java +++ b/core-cube/src/main/java/org/apache/kylin/cube/model/validation/rule/AggregationGroupRule.java @@ -182,9 +182,16 @@ public class AggregationGroupRule implements IValidatorRule { long combination = 0; try { combination = agg.calculateCuboidCombination(); + } catch (ArithmeticException ae) { + combination = -1; } catch (Exception ex) { combination = getMaxCombinations(cube) + 1; } finally { + if (combination < 0) { + String msg = "Aggregation group " + index + " has too many combinations, current combination is larger than Long.MAX_VALUE " + Long.MAX_VALUE + ", max allowed combination is " + getMaxCombinations(cube) + "; use 'mandatory'/'hierarchy'/'joint' to optimize; or remove less used columns from 'includes'"; + context.addResult(ResultLevel.ERROR, msg); + continue; + } if (combination > getMaxCombinations(cube)) { String msg = "Aggregation group " + index + " has too many combinations, current combination is " + combination + ", max allowed combination is " + getMaxCombinations(cube) + "; use 'mandatory'/'hierarchy'/'joint' to optimize; or update 'kylin.cube.aggrgroup.max-combination' to a bigger value."; context.addResult(ResultLevel.ERROR, msg); -- 2.5.4 (Apple Git-61)