/*
* Copyright 2014 Higher Frequency Trading
*
* http://www.higherfrequencytrading.com
*
* 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 net.openhft.chronicle.engine;
import net.openhft.chronicle.core.Jvm;
import net.openhft.chronicle.engine.api.map.MapView;
import net.openhft.chronicle.engine.api.tree.AssetTree;
import net.openhft.chronicle.engine.server.ServerEndpoint;
import net.openhft.chronicle.engine.tree.VanillaAssetTree;
import net.openhft.chronicle.network.TCPRegistry;
import net.openhft.chronicle.network.connection.TcpChannelHub;
import net.openhft.chronicle.threads.NamedThreadFactory;
import net.openhft.chronicle.wire.WireType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.*;
/**
* test using the listener both remotely or locally via the engine
*
* @author Rob Austin.
*/
public class TcpManyClientConnectionsOnManyMapsTest extends ThreadMonitoringTest {
public static final WireType WIRE_TYPE = WireType.TEXT;
public static final int MAX = 50;
private static final String NAME = "test";
private static final String CONNECTION = "host.port.TcpManyConnectionsTest";
@NotNull
private static MapView[] maps = new MapView[MAX];
@NotNull
private AssetTree[] trees = new AssetTree[MAX];
private VanillaAssetTree serverAssetTree;
private ServerEndpoint serverEndpoint;
@Before
public void before() throws IOException {
serverAssetTree = new VanillaAssetTree().forTesting();
TCPRegistry.createServerSocketChannelFor(CONNECTION);
serverEndpoint = new ServerEndpoint(CONNECTION, serverAssetTree);
for (int i = 0; i < MAX; i++) {
trees[i] = new VanillaAssetTree().forRemoteAccess(CONNECTION, WIRE_TYPE);
maps[i] = trees[i].acquireMap(NAME + i, String.class, String.class);
}
}
public void preAfter() {
shutdownTrees();
serverAssetTree.close();
serverEndpoint.close();
TcpChannelHub.closeAllHubs();
TCPRegistry.reset();
}
private void shutdownTrees() {
@NotNull ExecutorService c = Executors.newCachedThreadPool(
new NamedThreadFactory("Tree Closer", true));
for (int i = 0; i < MAX; i++) {
final int j = i;
c.execute(trees[j]::close);
}
c.shutdown();
try {
c.awaitTermination(2, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new AssertionError(e);
}
}
/**
* test many clients connecting to a single server
*/
@Test
public void test() throws IOException, InterruptedException, ExecutionException {
@NotNull final ExecutorService executorService = Executors.newCachedThreadPool();
@NotNull List<Future> futures = new ArrayList<>();
for (int i = 0; i < MAX; i++) {
final int j = i;
futures.add(executorService.submit(() -> {
MapView map = maps[j];
assert map.size() == 0;
map.put("hello" + j, "world" + j);
Assert.assertEquals("world" + j, map.get("hello" + j));
}));
}
futures.forEach(f -> {
try {
f.get();
} catch (@NotNull InterruptedException | ExecutionException e) {
Jvm.rethrow(e);
}
});
@NotNull List<Future<String>> futures2 = new ArrayList<Future<String>>();
for (int i = 0; i < MAX; i++) {
final int j = i;
futures2.add(executorService.submit(() -> {
assert maps[j].size() == 1;
return (String) (maps[j].get("hello" + j));
}));
}
@NotNull final Iterator<Future<String>> iterator = futures2.iterator();
for (int i = 0; i < MAX; i++) {
final Future<String> s = iterator.next();
final String actual = s.get();
Assert.assertEquals("world" + (i), actual);
}
executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.SECONDS);
}
/**
* test many clients connecting to a single server
*/
@Test
public void andresTest() throws IOException, InterruptedException {
@NotNull final ExecutorService executorService = Executors.newCachedThreadPool();
@NotNull List<Future> futures = new ArrayList<>();
for (int i = 0; i < MAX; i++) {
final int j = i;
futures.add(executorService.submit(() -> {
assert maps[j].size() == 0;
maps[j].clear();
maps[j].getAndPut("x", "y");
@Nullable final Object x = maps[j].get("x");
assert "y".equals(x) : "get(\"x\")=" + x;
assert maps[j].size() == 1;
maps[j].clear();
}));
}
futures.forEach(f -> {
try {
f.get();
} catch (@NotNull InterruptedException | ExecutionException e) {
Jvm.rethrow(e);
}
});
executorService.shutdown();
}
}