/*
* Copyright (c) 2008-2017, Hazelcast, Inc. 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.
*/
/*
* 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 com.hazelcast.mapreduce;
import com.hazelcast.core.ExecutionCallback;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.ICompletableFuture;
import com.hazelcast.core.IMap;
import com.hazelcast.test.HazelcastParallelClassRunner;
import com.hazelcast.test.HazelcastTestSupport;
import com.hazelcast.test.TestHazelcastInstanceFactory;
import com.hazelcast.test.annotation.ParallelTest;
import com.hazelcast.test.annotation.QuickTest;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Semaphore;
import static com.hazelcast.mapreduce.MapReduceTest.integerKvSource;
import static org.junit.Assert.assertEquals;
@RunWith(HazelcastParallelClassRunner.class)
@Category({QuickTest.class, ParallelTest.class})
@Ignore
@SuppressWarnings("unused")
public class DistributedMapperMapReduceTest
extends HazelcastTestSupport {
private static final String MAP_NAME = "default";
@Test(timeout = 30000)
public void testMapperReducer() throws Exception {
TestHazelcastInstanceFactory nodeFactory = createHazelcastInstanceFactory(4);
HazelcastInstance h1 = nodeFactory.newHazelcastInstance();
HazelcastInstance h2 = nodeFactory.newHazelcastInstance();
HazelcastInstance h3 = nodeFactory.newHazelcastInstance();
assertClusterSize(3, h1, h3);
assertClusterSizeEventually(3, h2);
IMap<Integer, Integer> m1 = h1.getMap(MAP_NAME);
for (int i = 0; i < 100; i++) {
m1.put(i, i);
}
JobTracker tracker = h1.getJobTracker("default");
Job<Integer, Integer> job = tracker.newJob(integerKvSource(m1));
ICompletableFuture<Map<String, Integer>> future = job.mapper(new GroupingTestMapper()).combiner(new TestCombinerFactory())
.reducer(new TestReducerFactory()).submit();
// Precalculate results
int[] expectedResults = new int[4];
for (int i = 0; i < 100; i++) {
int index = i % 4;
expectedResults[index] += i;
}
Map<String, Integer> result = future.get();
for (int i = 0; i < 4; i++) {
assertEquals(expectedResults[i], (int) result.get(String.valueOf(i)));
}
}
@Test(timeout = 30000)
public void testMapperCustomIntermediateCombinerReducer() throws Exception {
TestHazelcastInstanceFactory nodeFactory = createHazelcastInstanceFactory(4);
HazelcastInstance h1 = nodeFactory.newHazelcastInstance();
HazelcastInstance h2 = nodeFactory.newHazelcastInstance();
HazelcastInstance h3 = nodeFactory.newHazelcastInstance();
assertClusterSize(3, h1, h3);
assertClusterSizeEventually(3, h2);
IMap<Integer, Integer> m1 = h1.getMap(MAP_NAME);
for (int i = 0; i < 100; i++) {
m1.put(i, i);
}
JobTracker tracker = h1.getJobTracker("default");
Job<Integer, Integer> job = tracker.newJob(integerKvSource(m1));
ICompletableFuture<Map<String, Long>> future = job.mapper(new GroupingTestMapper())
.combiner(new TestIntermediateCombinerFactory())
.reducer(new TestIntermediateReducerFactory()).submit();
// Pre-calculate results
int[] expectedResults = new int[4];
for (int i = 0; i < 100; i++) {
int index = i % 4;
expectedResults[index] += i;
}
Map<String, Long> result = future.get();
for (int i = 0; i < 4; i++) {
assertEquals(expectedResults[i], (long) result.get(String.valueOf(i)));
}
}
@Test(timeout = 30000)
public void testMapperReducerCollator() throws Exception {
TestHazelcastInstanceFactory nodeFactory = createHazelcastInstanceFactory(4);
HazelcastInstance h1 = nodeFactory.newHazelcastInstance();
HazelcastInstance h2 = nodeFactory.newHazelcastInstance();
HazelcastInstance h3 = nodeFactory.newHazelcastInstance();
assertClusterSize(3, h1, h3);
assertClusterSizeEventually(3, h2);
IMap<Integer, Integer> m1 = h1.getMap(MAP_NAME);
for (int i = 0; i < 100; i++) {
m1.put(i, i);
}
JobTracker tracker = h1.getJobTracker("default");
Job<Integer, Integer> job = tracker.newJob(integerKvSource(m1));
ICompletableFuture<Integer> future = job.mapper(new GroupingTestMapper()).combiner(new TestCombinerFactory())
.reducer(new TestReducerFactory()).submit(new TestCollator());
// Precalculate result
int expectedResult = 0;
for (int i = 0; i < 100; i++) {
expectedResult += i;
}
int result = future.get();
for (int i = 0; i < 4; i++) {
assertEquals(expectedResult, result);
}
}
@Test(timeout = 30000)
public void testAsyncMapperReducer() throws Exception {
TestHazelcastInstanceFactory nodeFactory = createHazelcastInstanceFactory(4);
HazelcastInstance h1 = nodeFactory.newHazelcastInstance();
HazelcastInstance h2 = nodeFactory.newHazelcastInstance();
HazelcastInstance h3 = nodeFactory.newHazelcastInstance();
assertClusterSize(3, h1, h3);
assertClusterSizeEventually(3, h2);
IMap<Integer, Integer> m1 = h1.getMap(MAP_NAME);
for (int i = 0; i < 100; i++) {
m1.put(i, i);
}
final Map<String, Integer> listenerResults = new HashMap<String, Integer>();
final Semaphore semaphore = new Semaphore(1);
semaphore.acquire();
JobTracker tracker = h1.getJobTracker("default");
Job<Integer, Integer> job = tracker.newJob(integerKvSource(m1));
ICompletableFuture<Map<String, Integer>> future = job.mapper(new GroupingTestMapper()).combiner(new TestCombinerFactory())
.reducer(new TestReducerFactory()).submit();
future.andThen(new ExecutionCallback<Map<String, Integer>>() {
@Override
public void onResponse(Map<String, Integer> response) {
listenerResults.putAll(response);
semaphore.release();
}
@Override
public void onFailure(Throwable t) {
semaphore.release();
}
});
// Precalculate results
int[] expectedResults = new int[4];
for (int i = 0; i < 100; i++) {
int index = i % 4;
expectedResults[index] += i;
}
semaphore.acquire();
for (int i = 0; i < 4; i++) {
assertEquals(expectedResults[i], (int) listenerResults.get(String.valueOf(i)));
}
}
@Test(timeout = 30000)
public void testAsyncMapperReducerCollator() throws Exception {
TestHazelcastInstanceFactory nodeFactory = createHazelcastInstanceFactory(4);
HazelcastInstance h1 = nodeFactory.newHazelcastInstance();
HazelcastInstance h2 = nodeFactory.newHazelcastInstance();
HazelcastInstance h3 = nodeFactory.newHazelcastInstance();
assertClusterSize(3, h1, h3);
assertClusterSizeEventually(3, h2);
IMap<Integer, Integer> m1 = h1.getMap(MAP_NAME);
for (int i = 0; i < 100; i++) {
m1.put(i, i);
}
final int[] result = new int[1];
final Semaphore semaphore = new Semaphore(1);
semaphore.acquire();
JobTracker tracker = h1.getJobTracker("default");
Job<Integer, Integer> job = tracker.newJob(integerKvSource(m1));
ICompletableFuture<Integer> future = job.mapper(new GroupingTestMapper()).combiner(new TestCombinerFactory())
.reducer(new TestReducerFactory()).submit(new TestCollator());
future.andThen(new ExecutionCallback<Integer>() {
@Override
public void onResponse(Integer response) {
result[0] = response.intValue();
semaphore.release();
}
@Override
public void onFailure(Throwable t) {
semaphore.release();
}
});
// Precalculate result
int expectedResult = 0;
for (int i = 0; i < 100; i++) {
expectedResult += i;
}
semaphore.acquire();
for (int i = 0; i < 4; i++) {
assertEquals(expectedResult, result[0]);
}
}
public static class GroupingTestMapper
implements Mapper<Integer, Integer, String, Integer> {
private int moduleKey = -1;
public GroupingTestMapper() {
}
public GroupingTestMapper(int moduleKey) {
this.moduleKey = moduleKey;
}
@Override
public void map(Integer key, Integer value, Context<String, Integer> collector) {
if (moduleKey == -1 || (key % 4) == moduleKey) {
collector.emit(String.valueOf(key % 4), value);
}
}
}
public static class TestCombiner
extends Combiner<Integer, Integer> {
private transient int sum;
@Override
public void combine(Integer value) {
sum += value;
}
@Override
public Integer finalizeChunk() {
int v = sum;
sum = 0;
return v;
}
}
public static class TestCombinerFactory
implements CombinerFactory<String, Integer, Integer> {
public TestCombinerFactory() {
}
@Override
public Combiner<Integer, Integer> newCombiner(String key) {
return new TestCombiner();
}
}
public static class TestReducer
extends Reducer<Integer, Integer> {
private int sum;
@Override
public void reduce(Integer value) {
sum += value;
}
@Override
public Integer finalizeReduce() {
return sum;
}
}
public static class TestReducerFactory
implements ReducerFactory<String, Integer, Integer> {
public TestReducerFactory() {
}
@Override
public Reducer<Integer, Integer> newReducer(String key) {
return new TestReducer();
}
}
public static class TestCollator
implements Collator<Map.Entry<String, Integer>, Integer> {
@Override
public Integer collate(Iterable<Map.Entry<String, Integer>> values) {
int sum = 0;
for (Map.Entry<String, Integer> entry : values) {
sum += entry.getValue();
}
return sum;
}
}
public static class TestIntermediateCombiner
extends Combiner<Integer, Long> {
private transient int sum;
@Override
public void combine(Integer value) {
sum += value;
}
@Override
public Long finalizeChunk() {
int v = sum;
sum = 0;
return Long.valueOf(v);
}
}
public static class TestIntermediateCombinerFactory
implements CombinerFactory<String, Integer, Long> {
public TestIntermediateCombinerFactory() {
}
@Override
public Combiner<Integer, Long> newCombiner(String key) {
return new TestIntermediateCombiner();
}
}
public static class TestIntermediateReducer
extends Reducer<Long, Long> {
private long sum;
@Override
public void reduce(Long value) {
sum += value;
}
@Override
public Long finalizeReduce() {
return sum;
}
}
public static class TestIntermediateReducerFactory
implements ReducerFactory<String, Long, Long> {
public TestIntermediateReducerFactory() {
}
@Override
public Reducer<Long, Long> newReducer(String key) {
return new TestIntermediateReducer();
}
}
}