/*
*
* * Copyright (c) 2011-2015 EPFL DATA Laboratory
* * Copyright (c) 2014-2015 The Squall Collaboration (see NOTICE)
* *
* * All rights reserved.
* *
* * 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 ch.epfl.data.squall.thetajoin.matrix_assignment;
import ch.epfl.data.squall.storm_components.hash_hypercube.HashHyperCubeGrouping.EmitterDesc;
import ch.epfl.data.squall.types.Type;
import org.apache.log4j.Logger;
import java.io.Serializable;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Arrays;
import java.util.Set;
import java.util.HashSet;
import java.util.Random;
public class ManualHybridHyperCubeAssignment implements Serializable, HybridHyperCubeAssignment {
private Random rand;
private static Logger LOG = Logger.getLogger(ManualHybridHyperCubeAssignment.class);
Map<String, Dimension> dimensions;
int[] dimensionSizes;
Map<String, Integer> regionIDsMap;
public ManualHybridHyperCubeAssignment(Map<String, Dimension> dimensions) {
rand = new Random();
this.dimensions = dimensions;
createDimensionSizes();
createRegionMap();
}
public void createDimensionSizes() {
dimensionSizes = new int[dimensions.size()];
for (String key : dimensions.keySet()) {
Dimension d = dimensions.get(key);
dimensionSizes[d.index] = d.size;
}
}
@Override
public List<Integer> getRegionIDs(String emitterName, Map<String, String> c) {
if (isRandom(emitterName)) {
return getRandomRegion(emitterName);
} else {
return getHashRegion(c);
}
}
public List<Integer> getRandomRegion(String emitterName) {
final List<Integer> regionIDs = new ArrayList<Integer>();
Dimension dim = dimensions.get(emitterName);
final int fixedIndex = rand.nextInt(dim.size);
CellIterator gen = new CellIterator(dimensionSizes, dim.index, fixedIndex);
while (gen.hasNext()) {
List<Integer> cellIndex = gen.next();
int regionID = mapRegionID(mapRegionKey(cellIndex));
regionIDs.add(regionID);
}
return regionIDs;
}
public List<Integer> getHashRegion(Map<String, String> c) {
List<Integer> regions = new ArrayList<Integer>();
List<Integer> fixedDim = new ArrayList<Integer>();
List<Integer> fixedIndex = new ArrayList<Integer>();
for (String columnName : c.keySet()) {
if (dimensions.containsKey(columnName)) {
Dimension dim = dimensions.get(columnName);
String value = c.get(columnName);
int hashValue = Math.abs(value.hashCode()) % dim.size;
fixedDim.add(dim.index);
fixedIndex.add(hashValue);
}
}
CellIterator gen = new CellIterator(dimensionSizes, toIntArray(fixedDim), toIntArray(fixedIndex));
while (gen.hasNext()) {
List<Integer> cellIndex = gen.next();
int regionID = mapRegionID(mapRegionKey(cellIndex));
regions.add(regionID);
}
return regions;
}
public int[] toIntArray(List<Integer> list) {
int[] tmp = new int[list.size()];
int i = 0;
for (Integer number : list) {
tmp[i++] = number;
}
return tmp;
}
private boolean isRandom(String emitterName) {
return dimensions.containsKey(emitterName);
}
private void createRegionMap() {
regionIDsMap = new HashMap<String, Integer>();
CellIterator gen = new CellIterator(dimensionSizes);
int i = 0;
while (gen.hasNext()) {
List<Integer> cellIndex = gen.next();
regionIDsMap.put(mapRegionKey(cellIndex), i++);
}
}
private int mapRegionID(String key) {
return regionIDsMap.get(key);
}
private String mapRegionKey(List<Integer> cellIndex) {
StringBuilder key = new StringBuilder("");
for (Integer index : cellIndex) {
key.append(" " + index);
}
return key.toString();
}
@Override
public int getNumberOfRegions(String column) {
throw new RuntimeException("Dimension is invalid");
}
@Override
public String getMappingDimensions() {
StringBuilder sb = new StringBuilder();
for (String key : dimensions.keySet()) {
sb.append(dimensions.get(key).name).append(" : ").append(dimensions.get(key).size);
sb.append("\n");
}
return sb.toString();
}
public static class Dimension implements Serializable {
public String name;
public int size;
public int index;
public Dimension(String name, int size, int index) {
this.name = name;
this.size = size;
this.index = index;
}
public Dimension(String name, int index) {
this.name = name;
this.index = index;
}
public String toString() {
return name + ", " + size + ", " + index;
}
}
}