in src/core-metadata/src/main/java/org/apache/kylin/metadata/cube/model/RuleBasedIndex.java [308:394]
private Set<LayoutEntity> genCuboidLayouts(Set<LayoutEntity> previousLayouts, Set<LayoutEntity> needDelLayouts,
boolean excludeDel, boolean useCostBasedList) {
Set<LayoutEntity> genLayouts = Sets.newHashSet();
Map<LayoutEntity, Long> existLayouts = Maps.newHashMap();
previousLayouts.forEach(layout -> existLayouts.put(layout, layout.getId()));
indexPlan.getWhitelistLayouts().forEach(layout -> existLayouts.put(layout, layout.getId()));
Map<LayoutEntity, Long> delLayouts = Maps.newHashMap();
needDelLayouts.forEach(layout -> delLayouts.put(layout, layout.getId()));
Map<LayoutEntity, Long> toBeDeletedLayouts = Maps.newHashMap();
Map<IndexIdentifier, IndexEntity> toBeDeletedIndexesMap = Maps.newHashMap();
indexPlan.getToBeDeletedIndexes().forEach(index -> {
toBeDeletedIndexesMap.put(index.createIndexIdentifier(), index);
index.getLayouts().forEach(layout -> toBeDeletedLayouts.put(layout, layout.getId()));
});
Map<IndexIdentifier, IndexEntity> identifierIndexMap = existLayouts.keySet().stream()
.map(LayoutEntity::getIndex).collect(Collectors.groupingBy(IndexEntity::createIndexIdentifier,
Collectors.reducing(null, (l, r) -> r)));
val colOrders = getCuboidScheduler().getAllColOrders();
boolean needAllocationId = layoutIdMapping.isEmpty();
boolean isBaseCuboidValid = getIndexPlan().getConfig().isBaseCuboidAlwaysValid();
val baseColOrder = new ColOrder(getDimensions(), getMeasures());
long proposalId = indexStartId + 1;
for (int i = 0; i < colOrders.size(); i++) {
val colOrder = colOrders.get(i);
val layout = createLayout(colOrder, getModel().getStorageTypeValue());
val dimensionsInLayout = colOrder.getDimensions();
val measuresInLayout = colOrder.getMeasures();
// if a cuboid is same as the layout's one, then reuse it
val indexIdentifier = new IndexEntity.IndexIdentifier(dimensionsInLayout, measuresInLayout, false);
var layoutIndex = identifierIndexMap.get(indexIdentifier);
IndexEntity toBeDelLayoutIndex = toBeDeletedIndexesMap.get(indexIdentifier);
long nextLayoutId = getNextLayoutId(layoutIndex, toBeDelLayoutIndex);
if (needAllocationId) {
// if two layout is equal, the id should be same
Long prevId = getExistLayoutId(layout, toBeDelLayoutIndex, existLayouts, toBeDeletedLayouts);
if (prevId != null) {
layout.setId(prevId);
} else if (delLayouts.containsKey(layout)) {
layout.setId(delLayouts.get(layout));
layoutBlackList.add(delLayouts.get(layout));
} else if (nextLayoutId > 0) {
layout.setId(nextLayoutId);
} else {
layout.setId(proposalId);
proposalId += IndexEntity.INDEX_ID_STEP;
}
layoutIdMapping.add(layout.getId());
} else {
layout.setId(layoutIdMapping.get(i));
}
if (layoutIndex == null) {
long indexId = layout.getIndexId();
layoutIndex = new IndexEntity();
layoutIndex.setId(indexId);
layoutIndex.setDimensions(dimensionsInLayout);
layoutIndex.setMeasures(measuresInLayout);
layoutIndex.setIndexPlan(indexPlan);
layoutIndex.setNextLayoutOffset(layout.getId() % IndexEntity.INDEX_ID_STEP + 1);
identifierIndexMap.putIfAbsent(layoutIndex.createIndexIdentifier(), layoutIndex);
} else {
layoutIndex.setNextLayoutOffset(
Math.max(layout.getId() % IndexEntity.INDEX_ID_STEP + 1, layoutIndex.getNextLayoutOffset()));
}
layout.setIndex(layoutIndex);
if (!isBaseCuboidValid && colOrder.equals(baseColOrder)) {
continue;
}
genLayouts.add(layout);
}
// remove layout in blacklist
if (excludeDel) {
genLayouts.removeIf(layout -> layoutBlackList.contains(layout.getId()));
}
return tryLayoutsOfCostBasedPlanner(useCostBasedList, genLayouts);
}