eu.stratosphere.api.common.distributions.SimpleDistribution Maven / Gradle / Ivy
/***********************************************************************************************************************
* Copyright (C) 2010-2013 by the Stratosphere project (http://stratosphere.eu)
*
* 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 eu.stratosphere.api.common.distributions;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import eu.stratosphere.types.Key;
import eu.stratosphere.util.InstantiationUtil;
public class SimpleDistribution implements DataDistribution {
private static final long serialVersionUID = 1L;
protected Key>[][] boundaries;
protected int dim;
public SimpleDistribution() {
boundaries = new Key[0][];
}
public SimpleDistribution(Key>[] bucketBoundaries) {
if (bucketBoundaries == null) {
throw new IllegalArgumentException("Bucket boundaries must not be null.");
}
if (bucketBoundaries.length == 0) {
throw new IllegalArgumentException("Bucket boundaries must not be empty.");
}
// dimensionality is one in this case
dim = 1;
@SuppressWarnings("unchecked")
Class extends Key>> clazz = (Class extends Key>>) bucketBoundaries[0].getClass();
// make the array 2-dimensional
boundaries = new Key[bucketBoundaries.length][];
for (int i = 0; i < bucketBoundaries.length; i++) {
if (bucketBoundaries[i].getClass() != clazz) {
throw new IllegalArgumentException("The bucket boundaries are of different class types.");
}
boundaries[i] = new Key[] { bucketBoundaries[i] };
}
}
@SuppressWarnings("unchecked")
public SimpleDistribution(Key>[][] bucketBoundaries) {
if (bucketBoundaries == null) {
throw new IllegalArgumentException("Bucket boundaries must not be null.");
}
if (bucketBoundaries.length == 0) {
throw new IllegalArgumentException("Bucket boundaries must not be empty.");
}
// dimensionality is one in this case
dim = bucketBoundaries[0].length;
Class extends Key>>[] types = new Class[dim];
for (int i = 0; i < dim; i++) {
types[i] = (Class extends Key>>) bucketBoundaries[0][i].getClass();
}
// check the array
for (int i = 1; i < bucketBoundaries.length; i++) {
if (bucketBoundaries[i].length != dim) {
throw new IllegalArgumentException("All bucket boundaries must have the same dimensionality.");
}
for (int d = 0; d < dim; d++) {
if (types[d] != bucketBoundaries[i][d].getClass()) {
throw new IllegalArgumentException("The bucket boundaries are of different class types.");
}
}
}
boundaries = bucketBoundaries;
}
@Override
public int getNumberOfFields() {
return this.dim;
}
@Override
public Key>[] getBucketBoundary(int bucketNum, int totalNumBuckets) {
// check validity of arguments
if(bucketNum < 0) {
throw new IllegalArgumentException("Requested bucket must be greater than or equal to 0.");
} else if(bucketNum >= (totalNumBuckets - 1)) {
throw new IllegalArgumentException("Request bucket must be smaller than the total number of buckets minus 1.");
}
if(totalNumBuckets < 1) {
throw new IllegalArgumentException("Total number of bucket must be larger than 0.");
}
final int maxNumBuckets = boundaries.length + 1;
// check if max number of buckets is equal to or an even multiple of the requested number of buckets
if((maxNumBuckets % totalNumBuckets) == 0) {
// easy case, just use each n-th boundary
final int n = maxNumBuckets / totalNumBuckets;
final int bucketId = bucketNum * n + (n - 1);
return boundaries[bucketId];
} else {
throw new IllegalArgumentException("Interpolation of bucket boundaries currently not supported. " +
"Please use an even divider of the maximum possible buckets (here: "+maxNumBuckets+") as totalBuckets.");
// TODO: might be relaxed if much more boundary records are available than requested
}
}
@Override
public void write(DataOutput out) throws IOException {
out.writeInt(this.dim);
out.writeInt(boundaries.length);
// write types
for (int i = 0; i < dim; i++) {
out.writeUTF(boundaries[0][i].getClass().getName());
}
for (int i = 0; i < boundaries.length; i++) {
for (int d = 0; d < dim; d++) {
boundaries[i][d].write(out);
}
}
}
@SuppressWarnings("unchecked")
@Override
public void read(DataInput in) throws IOException {
this.dim = in.readInt();
final int len = in.readInt();
boundaries = new Key[len][];
// read types
Class extends Key>>[] types = new Class[dim];
for (int i = 0; i < dim; i++) {
String className = in.readUTF();
try {
types[i] = (Class extends Key>>) Class.forName(className, true, getClass().getClassLoader()).asSubclass(Key.class);
} catch (ClassNotFoundException e) {
throw new IOException("Could not load type class '" + className + "'.");
} catch (Throwable t) {
throw new IOException("Error loading type class '" + className + "'.", t);
}
}
for (int i = 0; i < len; i++) {
Key>[] bucket = new Key[dim];
for (int d = 0; d < dim; d++) {
Key> val = InstantiationUtil.instantiate(types[d], Key.class);
val.read(in);
bucket[d] = val;
}
boundaries[i] = bucket;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy