/*
* Copyright 2012 Amazon.com, Inc. or its affiliates. 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.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 com.amazonaws.services.simpleworkflow.flow.examples.splitmerge;
import java.util.ArrayList;
import java.util.List;
import com.amazonaws.services.simpleworkflow.flow.annotations.Asynchronous;
import com.amazonaws.services.simpleworkflow.flow.annotations.Wait;
import com.amazonaws.services.simpleworkflow.flow.core.Promise;
public class PartitionedAverageCalculatorImpl implements PartitionedAverageCalculator {
private final AverageCalculatorActivitiesClient client = new AverageCalculatorActivitiesClientImpl();
private final int numberOfWorkers;
private final String bucketName;
public PartitionedAverageCalculatorImpl(int numberOfWorkers, String bucketName) {
this.numberOfWorkers = numberOfWorkers;
this.bucketName = bucketName;
}
@Override
public Promise<Double> computeAverage(String inputFile) {
Promise<Integer> dataSize = client.computeDataSizeForInputData(bucketName, inputFile);
return computeAverageDistributed(inputFile, dataSize);
}
@Asynchronous
private Promise<Double> computeAverageDistributed(String inputFile, Promise<Integer> dataSize) {
int chunkSize = dataSize.get() / numberOfWorkers;
// Create an array list to hold the result returned by each worker
List<Promise<Integer>> results = new ArrayList<Promise<Integer>>();
for (int chunkNumber = 0; chunkNumber < numberOfWorkers; chunkNumber++) {
// Splitting computation for each chunk as separate activity
results.add(client.computeSumForChunk(bucketName, inputFile, chunkNumber, chunkSize));
}
// Merge phase
return mergeSumAndComputeAverage(results, dataSize.get());
}
@Asynchronous
private Promise<Double> mergeSumAndComputeAverage(@Wait List<Promise<Integer>> results, int dataSize){
int totalSum = 0;
for(Promise<Integer> workerSum: results){
totalSum += workerSum.get();
}
return Promise.asPromise((double) totalSum / (double) dataSize);
}
@Override
@Asynchronous
public void reportResult(Promise<Double> result){
client.reportResult(result);
}
}