blob: 62953e08052d75b89ac5296f7b604d5945b41e66 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.drill.exec.planner.fragment;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import org.apache.drill.exec.physical.EndpointAffinity;
import org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint;
import java.util.List;
import java.util.Map;
/**
* Captures parallelization parameters for a given operator/fragments. It consists of min and max width of
* parallelization and affinity to drillbit endpoints.
*/
public class ParallelizationInfo {
/* Default parallelization width is [1, Integer.MAX_VALUE] and no endpoint affinity. */
public static final ParallelizationInfo UNLIMITED_WIDTH_NO_ENDPOINT_AFFINITY =
ParallelizationInfo.create(1, Integer.MAX_VALUE);
private final Map<DrillbitEndpoint, EndpointAffinity> affinityMap;
private final int minWidth;
private final int maxWidth;
private ParallelizationInfo(int minWidth, int maxWidth, Map<DrillbitEndpoint, EndpointAffinity> affinityMap) {
this.minWidth = minWidth;
this.maxWidth = maxWidth;
this.affinityMap = ImmutableMap.copyOf(affinityMap);
}
public static ParallelizationInfo create(int minWidth, int maxWidth) {
return create(minWidth, maxWidth, ImmutableList.<EndpointAffinity>of());
}
public static ParallelizationInfo create(int minWidth, int maxWidth, List<EndpointAffinity> endpointAffinities) {
Map<DrillbitEndpoint, EndpointAffinity> affinityMap = Maps.newHashMap();
for(EndpointAffinity epAffinity : endpointAffinities) {
affinityMap.put(epAffinity.getEndpoint(), epAffinity);
}
return new ParallelizationInfo(minWidth, maxWidth, affinityMap);
}
public int getMinWidth() {
return minWidth;
}
public int getMaxWidth() {
return maxWidth;
}
public Map<DrillbitEndpoint, EndpointAffinity> getEndpointAffinityMap() {
return affinityMap;
}
@Override
public String toString() {
return getDigest(minWidth, maxWidth, affinityMap);
}
private static String getDigest(int minWidth, int maxWidth, Map<DrillbitEndpoint, EndpointAffinity> affinityMap) {
StringBuilder sb = new StringBuilder();
sb.append(String.format("[minWidth = %d, maxWidth=%d, epAff=[", minWidth, maxWidth));
sb.append(Joiner.on(",").join(affinityMap.values()));
sb.append("]]");
return sb.toString();
}
/**
* Collects/merges one or more ParallelizationInfo instances.
*/
public static class ParallelizationInfoCollector {
private int minWidth = 1;
private int maxWidth = Integer.MAX_VALUE;
private final Map<DrillbitEndpoint, EndpointAffinity> affinityMap = Maps.newHashMap();
public void add(ParallelizationInfo parallelizationInfo) {
minWidth = Math.max(minWidth, parallelizationInfo.minWidth);
maxWidth = Math.min(maxWidth, parallelizationInfo.maxWidth);
Map<DrillbitEndpoint, EndpointAffinity> affinityMap = parallelizationInfo.getEndpointAffinityMap();
for(Map.Entry<DrillbitEndpoint, EndpointAffinity> epAff : affinityMap.entrySet()) {
addEndpointAffinity(epAff.getValue());
}
}
public void addMaxWidth(int newMaxWidth) {
maxWidth = Math.min(maxWidth, newMaxWidth);
}
public void addMinWidth(int newMinWidth) {
minWidth = Math.max(minWidth, newMinWidth);
}
public void addEndpointAffinities(List<EndpointAffinity> endpointAffinities) {
for(EndpointAffinity epAff : endpointAffinities) {
addEndpointAffinity(epAff);
}
}
// Helper method to add the given EndpointAffinity to the global affinity map
private void addEndpointAffinity(EndpointAffinity epAff) {
final EndpointAffinity epAffAgg = affinityMap.get(epAff.getEndpoint());
if (epAffAgg != null) {
epAffAgg.addAffinity(epAff.getAffinity());
if (epAff.isAssignmentRequired()) {
epAffAgg.setAssignmentRequired();
}
epAffAgg.setMaxWidth(epAff.getMaxWidth());
} else {
affinityMap.put(epAff.getEndpoint(), epAff);
}
}
/**
* Get a ParallelizationInfo instance based on the current state of collected info.
*/
public ParallelizationInfo get() {
return new ParallelizationInfo(minWidth, maxWidth, affinityMap);
}
@Override
public String toString() {
return getDigest(minWidth, maxWidth, affinityMap);
}
}
}