/*
* Copyright (C) 2015 SoftIndex LLC.
*
* 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 io.datakernel.datagraph.stream;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Ordering;
import com.google.common.net.InetAddresses;
import io.datakernel.async.AssertingCompletionCallback;
import io.datakernel.async.IgnoreCompletionCallback;
import io.datakernel.datagraph.dataset.Dataset;
import io.datakernel.datagraph.dataset.LocallySortedDataset;
import io.datakernel.datagraph.dataset.SortedDataset;
import io.datakernel.datagraph.dataset.impl.DatasetListConsumer;
import io.datakernel.datagraph.graph.DataGraph;
import io.datakernel.datagraph.graph.Partition;
import io.datakernel.datagraph.helper.StreamMergeSorterStorageStub;
import io.datakernel.datagraph.server.*;
import io.datakernel.eventloop.Eventloop;
import io.datakernel.serializer.annotations.Deserialize;
import io.datakernel.serializer.annotations.Serialize;
import io.datakernel.stream.StreamConsumers;
import io.datakernel.stream.StreamProducer;
import io.datakernel.stream.processor.StreamMergeSorterStorage;
import org.junit.Test;
import java.net.InetSocketAddress;
import static io.datakernel.datagraph.dataset.Datasets.*;
import static io.datakernel.eventloop.FatalErrorHandlers.rethrowOnAnyError;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;
public class DatagraphServerTest {
public static final class TestItem {
@Serialize(order = 0)
public final long value;
public TestItem(@Deserialize("value") long value) {
this.value = value;
}
@Override
public String toString() {
return "TestItem{value=" + value + '}';
}
public static class KeyFunction implements Function<TestItem, Long> {
@Override
public Long apply(TestItem item) {
return item.value;
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TestItem testItem = (TestItem) o;
return value == testItem.value;
}
@Override
public int hashCode() {
return (int) (value ^ (value >>> 32));
}
}
@Test
public void testForward() throws Exception {
DatagraphSerialization serialization = new DatagraphSerialization();
InetSocketAddress address1 = new InetSocketAddress(InetAddresses.forString("127.0.0.1"), 1511);
InetSocketAddress address2 = new InetSocketAddress(InetAddresses.forString("127.0.0.1"), 1512);
final Eventloop eventloop = Eventloop.create().withFatalErrorHandler(rethrowOnAnyError());
StreamConsumers.ToList<TestItem> result1 = new StreamConsumers.ToList<>(eventloop);
StreamConsumers.ToList<TestItem> result2 = new StreamConsumers.ToList<>(eventloop);
DatagraphEnvironment environment = DatagraphEnvironment.create()
.setInstance(DatagraphSerialization.class, serialization);
DatagraphEnvironment environment1 = environment.extend()
.set("items", asList(new TestItem(1), new TestItem(3), new TestItem(5)))
.set("result", result1);
DatagraphEnvironment environment2 = environment.extend()
.set("items", asList(new TestItem(2), new TestItem(4), new TestItem(6)))
.set("result", result2);
final DatagraphServer server1 = new DatagraphServer(eventloop, environment1)
.withListenAddress(address1);
final DatagraphServer server2 = new DatagraphServer(eventloop, environment2)
.withListenAddress(address2);
DatagraphClient client = new DatagraphClient(eventloop, serialization);
Partition partition1 = new Partition(client, address1);
Partition partition2 = new Partition(client, address2);
final DataGraph graph = new DataGraph(serialization,
asList(partition1, partition2));
Dataset<TestItem> items = datasetOfList("items", TestItem.class);
DatasetListConsumer<?> consumerNode = listConsumer(items, "result");
consumerNode.compileInto(graph);
System.out.println(graph);
server1.listen();
server2.listen();
result1.setCompletionCallback(new AssertingCompletionCallback() {
@Override
protected void onComplete() {
server1.close(IgnoreCompletionCallback.create());
}
});
result2.setCompletionCallback(new AssertingCompletionCallback() {
@Override
protected void onComplete() {
server2.close(IgnoreCompletionCallback.create());
}
});
graph.execute();
eventloop.run();
assertEquals(asList(new TestItem(1), new TestItem(3), new TestItem(5)), result1.getList());
assertEquals(asList(new TestItem(2), new TestItem(4), new TestItem(6)), result2.getList());
}
@Test
public void testRepartitionAndSort() throws Exception {
DatagraphSerialization serialization = new DatagraphSerialization();
InetSocketAddress address1 = new InetSocketAddress(InetAddresses.forString("127.0.0.1"), 1511);
InetSocketAddress address2 = new InetSocketAddress(InetAddresses.forString("127.0.0.1"), 1512);
final Eventloop eventloop = Eventloop.create().withFatalErrorHandler(rethrowOnAnyError());
StreamConsumers.ToList<TestItem> result1 = new StreamConsumers.ToList<>(eventloop);
StreamConsumers.ToList<TestItem> result2 = new StreamConsumers.ToList<>(eventloop);
DatagraphClient client = new DatagraphClient(eventloop, serialization);
DatagraphEnvironment environment = DatagraphEnvironment.create()
.setInstance(DatagraphSerialization.class, serialization)
.setInstance(DatagraphClient.class, client);
DatagraphEnvironment environment1 = environment.extend()
.set("items", asList(new TestItem(1), new TestItem(2), new TestItem(3), new TestItem(4), new TestItem(5), new TestItem(6)))
.set("result", result1);
DatagraphEnvironment environment2 = environment.extend()
.set("items", asList(new TestItem(1), new TestItem(6)))
.set("result", result2);
final DatagraphServer server1 = new DatagraphServer(eventloop, environment1)
.withListenAddress(address1);
final DatagraphServer server2 = new DatagraphServer(eventloop, environment2)
.withListenAddress(address2);
Partition partition1 = new Partition(client, address1);
Partition partition2 = new Partition(client, address2);
final DataGraph graph = new DataGraph(serialization,
asList(partition1, partition2));
SortedDataset<Long, TestItem> items = repartition_Sort(sortedDatasetOfList("items",
TestItem.class, Long.class, new TestItem.KeyFunction(), Ordering.<Long>natural()));
DatasetListConsumer<?> consumerNode = listConsumer(items, "result");
consumerNode.compileInto(graph);
System.out.println(graph);
server1.listen();
server2.listen();
result1.setCompletionCallback(new AssertingCompletionCallback() {
@Override
protected void onComplete() {
server1.close(IgnoreCompletionCallback.create());
}
});
result2.setCompletionCallback(new AssertingCompletionCallback() {
@Override
protected void onComplete() {
server2.close(IgnoreCompletionCallback.create());
}
});
graph.execute();
eventloop.run();
assertEquals(asList(new TestItem(2), new TestItem(4), new TestItem(6), new TestItem(6)), result1.getList());
assertEquals(asList(new TestItem(1), new TestItem(1), new TestItem(3), new TestItem(5)), result2.getList());
}
@Test
public void testFilter() throws Exception {
DatagraphSerialization serialization = new DatagraphSerialization();
InetSocketAddress address1 = new InetSocketAddress(InetAddresses.forString("127.0.0.1"), 1511);
InetSocketAddress address2 = new InetSocketAddress(InetAddresses.forString("127.0.0.1"), 1512);
final Eventloop eventloop = Eventloop.create().withFatalErrorHandler(rethrowOnAnyError());
DatagraphClient client = new DatagraphClient(eventloop, serialization);
StreamConsumers.ToList<TestItem> result1 = new StreamConsumers.ToList<>(eventloop);
StreamConsumers.ToList<TestItem> result2 = new StreamConsumers.ToList<>(eventloop);
DatagraphEnvironment environment = DatagraphEnvironment.create()
.setInstance(DatagraphSerialization.class, serialization)
.setInstance(DatagraphClient.class, client)
.setInstance(StreamMergeSorterStorage.class, new StreamMergeSorterStorageStub(eventloop));
DatagraphEnvironment environment1 = environment.extend()
.set("items", asList(new TestItem(6), new TestItem(4), new TestItem(2),
new TestItem(3), new TestItem(1)))
.set("result", result1);
DatagraphEnvironment environment2 = environment.extend()
.set("items", asList(new TestItem(7), new TestItem(7), new TestItem(8),
new TestItem(2), new TestItem(5)))
.set("result", result2);
final DatagraphServer server1 = new DatagraphServer(eventloop, environment1)
.withListenAddress(address1);
final DatagraphServer server2 = new DatagraphServer(eventloop, environment2)
.withListenAddress(address2);
Partition partition1 = new Partition(client, address1);
Partition partition2 = new Partition(client, address2);
final DataGraph graph = new DataGraph(serialization, asList(partition1, partition2));
Dataset<TestItem> filterDataset = filter(datasetOfList("items", TestItem.class),
new Predicate<TestItem>() {
@Override
public boolean apply(TestItem input) {
return input.value % 2 == 0;
}
});
LocallySortedDataset<Long, TestItem> sortedDataset =
localSort(filterDataset, long.class, new TestItem.KeyFunction(), Ordering.<Long>natural());
DatasetListConsumer<?> consumerNode = listConsumer(sortedDataset, "result");
consumerNode.compileInto(graph);
System.out.println("Graph: ");
System.out.println(graph);
server1.listen();
server2.listen();
result1.setCompletionCallback(new AssertingCompletionCallback() {
@Override
protected void onComplete() {
server1.close(IgnoreCompletionCallback.create());
}
});
result2.setCompletionCallback(new AssertingCompletionCallback() {
@Override
protected void onComplete() {
server2.close(IgnoreCompletionCallback.create());
}
});
graph.execute();
eventloop.run();
assertEquals(asList(new TestItem(2), new TestItem(4), new TestItem(6)), result1.getList());
assertEquals(asList(new TestItem(2), new TestItem(8)), result2.getList());
}
@Test
public void testCollector() throws Exception {
DatagraphSerialization serialization = new DatagraphSerialization();
InetSocketAddress address1 = new InetSocketAddress(InetAddresses.forString("127.0.0.1"), 1511);
InetSocketAddress address2 = new InetSocketAddress(InetAddresses.forString("127.0.0.1"), 1512);
final Eventloop eventloop = Eventloop.create().withFatalErrorHandler(rethrowOnAnyError());
DatagraphClient client = new DatagraphClient(eventloop, serialization);
final StreamConsumers.ToList<TestItem> resultConsumer = new StreamConsumers.ToList<>(eventloop);
DatagraphEnvironment environment = DatagraphEnvironment.create()
.setInstance(DatagraphSerialization.class, serialization)
.setInstance(DatagraphClient.class, client)
.setInstance(StreamMergeSorterStorage.class, new StreamMergeSorterStorageStub(eventloop));
DatagraphEnvironment environment1 = environment.extend()
.set("items", asList(new TestItem(1), new TestItem(2), new TestItem(3),
new TestItem(4), new TestItem(5)));
DatagraphEnvironment environment2 = environment.extend()
.set("items", asList(new TestItem(6), new TestItem(7), new TestItem(8),
new TestItem(9), new TestItem(10)));
final DatagraphServer server1 = new DatagraphServer(eventloop, environment1)
.withListenAddress(address1);
final DatagraphServer server2 = new DatagraphServer(eventloop, environment2)
.withListenAddress(address2);
Partition partition1 = new Partition(client, address1);
Partition partition2 = new Partition(client, address2);
final DataGraph graph = new DataGraph(serialization, asList(partition1, partition2));
Dataset<TestItem> filterDataset = filter(datasetOfList("items", TestItem.class),
new Predicate<TestItem>() {
@Override
public boolean apply(TestItem input) {
return input.value % 2 == 0;
}
});
LocallySortedDataset<Long, TestItem> sortedDataset =
localSort(filterDataset, long.class, new TestItem.KeyFunction(), Ordering.<Long>natural());
System.out.println("Graph: ");
System.out.println(graph);
server1.listen();
server2.listen();
Collector<TestItem> collector = new Collector<>(sortedDataset, TestItem.class, client, eventloop);
StreamProducer<TestItem> resultProducer = collector.compile(graph);
resultProducer.streamTo(resultConsumer);
resultConsumer.setCompletionCallback(new AssertingCompletionCallback() {
@Override
protected void onComplete() {
server1.close(IgnoreCompletionCallback.create());
server2.close(IgnoreCompletionCallback.create());
}
});
graph.execute();
eventloop.run();
assertEquals(asList(new TestItem(2), new TestItem(4), new TestItem(6), new TestItem(8), new TestItem(10)),
resultConsumer.getList());
}
}