diff --git a/pom.xml b/pom.xml index 1f0319ac3..e167e36ec 100755 --- a/pom.xml +++ b/pom.xml @@ -230,13 +230,9 @@ net/openhft/chronicle/hash/ChronicleHashBuilderPrivateAPI.java - net/openhft/chronicle/hash/KeyContext.java net/openhft/chronicle/hash/Segment.java net/openhft/chronicle/hash/locks/LockingStrategy.java net/openhft/chronicle/map/ConstantValueProvider.java - net/openhft/chronicle/map/MapEntryCallback.java - net/openhft/chronicle/map/MapEventListener.java - net/openhft/chronicle/map/MapKeyContext.java net/openhft/chronicle/map/VanillaChronicleMap.java net/openhft/chronicle/map/Replica.java net/openhft/chronicle/map/ReplicatedChronicleMap.java diff --git a/src/main/java/net/openhft/chronicle/hash/ChronicleHashStatelessClientBuilder.java b/src/main/java/net/openhft/chronicle/hash/ChronicleHashStatelessClientBuilder.java deleted file mode 100644 index 3e52c9928..000000000 --- a/src/main/java/net/openhft/chronicle/hash/ChronicleHashStatelessClientBuilder.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2015 higherfrequencytrading.com - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package net.openhft.chronicle.hash; - -import net.openhft.chronicle.map.ChronicleMap; -import net.openhft.chronicle.set.ChronicleSet; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; - -/** - * Builder of stateless {@link ChronicleHash} implementation, this stateless implementation will be - * referred to as a stateless client as it - * will not hold any of its own data locally, the stateless client will perform Remote Procedure - * Calls ( RPC ) to another {@link ChronicleMap} or {@link ChronicleSet} which we will refer to - * as the server. The server will hold all your data, the server can not it’s self be a - * stateless client. Your stateless client must be connected to the server via TCP/IP. The - * stateless client will delegate all your method calls to the remote sever. The stateless - * client operations will block, in other words the stateless client will wait for the server to - * send a response before continuing to the next operation. The stateless client could be - * consider to be a ClientProxy to {@link ChronicleMap} or {@link ChronicleSet} running on - * another host - * - * @param the type of {@code ChronicleHash} accessed remotely, {@code ChronicleMap} or - * {@code ChronicleSet} - */ -public interface ChronicleHashStatelessClientBuilder< - B extends ChronicleHashStatelessClientBuilder, H extends ChronicleHash> { - B timeout(long timeout, TimeUnit units); - - B name(String name); - - B tcpBufferSize(int tcpBufferSize); - - H create() throws IOException; -} diff --git a/src/main/java/net/openhft/chronicle/map/AbstractChannelReplicator.java b/src/main/java/net/openhft/chronicle/map/AbstractChannelReplicator.java index 3d220ed36..2deb66d20 100644 --- a/src/main/java/net/openhft/chronicle/map/AbstractChannelReplicator.java +++ b/src/main/java/net/openhft/chronicle/map/AbstractChannelReplicator.java @@ -55,6 +55,8 @@ abstract class AbstractChannelReplicator implements Closeable { static final int SIZE_OF_SIZE = 4; public static final int SIZE_OF_TRANSACTION_ID = 8; + static final byte STATEFUL_UPDATE = 1; + private static final Logger LOG = LoggerFactory.getLogger(AbstractChannelReplicator.class); // currently this is not safe to use as it wont work with the stateless client @@ -503,8 +505,8 @@ abstract class AbstractChannelReplicator implements Closeable { long pos0 = in.position(); long start = 0; try { - // used to denote that this is not a stateless map event - in.writeByte(StatelessChronicleMap.EventId.STATEFUL_UPDATE.ordinal()); + // used to denote that this is not a heartbeat + in.writeByte(STATEFUL_UPDATE); long sizeLocation = in.position(); diff --git a/src/main/java/net/openhft/chronicle/map/ChannelProvider.java b/src/main/java/net/openhft/chronicle/map/ChannelProvider.java index a5b184d6f..d3e04c257 100644 --- a/src/main/java/net/openhft/chronicle/map/ChannelProvider.java +++ b/src/main/java/net/openhft/chronicle/map/ChannelProvider.java @@ -64,7 +64,7 @@ public final class ChannelProvider implements Closeable { final TcpReplicator tcpReplicator = new TcpReplicator( channelProvider.asReplica, channelProvider.asEntryExternalizable, - tcpConfig, hub.remoteNodeValidator(), null, hub.name(), + tcpConfig, hub.remoteNodeValidator(), hub.name(), hub.connectionListener()); channelProvider.add(tcpReplicator); } diff --git a/src/main/java/net/openhft/chronicle/map/ChroncileMapJsonSerializer.java b/src/main/java/net/openhft/chronicle/map/ChroncileMapJsonSerializer.java index f9471f4f0..3a21d6371 100644 --- a/src/main/java/net/openhft/chronicle/map/ChroncileMapJsonSerializer.java +++ b/src/main/java/net/openhft/chronicle/map/ChroncileMapJsonSerializer.java @@ -20,7 +20,6 @@ import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver; import net.openhft.xstream.converters.ByteBufferConverter; import net.openhft.xstream.converters.DataValueConverter; -import net.openhft.xstream.converters.StatelessChronicleMapConverter; import net.openhft.xstream.converters.VanillaChronicleMapConverter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,7 +35,7 @@ import java.util.zip.GZIPOutputStream; */ class JsonSerializer { - private static final Logger LOG = LoggerFactory.getLogger(StatelessChronicleMap.class); + private static final Logger LOG = LoggerFactory.getLogger(JsonSerializer.class); static synchronized void getAll(File toFile, Map map, List jsonConverters) throws IOException { final XStream xstream = xStream(map, jsonConverters); @@ -106,12 +105,7 @@ class JsonSerializer { } private static void registerChronicleMapConverter(Map map, XStream xstream) { - - Converter converter = map instanceof StatelessChronicleMap ? - new StatelessChronicleMapConverter(map) : - new VanillaChronicleMapConverter(map); - - xstream.registerConverter(converter); + xstream.registerConverter(new VanillaChronicleMapConverter<>(map)); } } diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java index d3febd456..f17550af1 100755 --- a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java +++ b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java @@ -51,9 +51,7 @@ import java.io.*; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; +import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @@ -110,8 +108,7 @@ import static net.openhft.lang.model.DataValueGenerator.firstPrimitiveFieldType; * @see ChronicleSetBuilder */ public final class ChronicleMapBuilder implements - ChronicleHashBuilder, ChronicleMapBuilder>, - MapBuilder> { + ChronicleHashBuilder, ChronicleMapBuilder> { static final byte UDP_REPLICATION_MODIFICATION_ITERATOR_ID = (byte) 127; private static final int DEFAULT_KEY_OR_VALUE_SIZE = 120; @@ -213,12 +210,6 @@ public final class ChronicleMapBuilder implements return new ChronicleMapBuilder<>(keyClass, valueClass); } - public static ChronicleMapStatelessClientBuilder of( - @NotNull Class keyClass, @NotNull Class valueClass, - InetSocketAddress socketAddress) { - return ChronicleMapStatelessClientBuilder.of(socketAddress); - } - private static long roundUpMapHeaderSize(long headerSize) { long roundUp = (headerSize + 127L) & ~127L; if (roundUp - headerSize < 64) @@ -980,7 +971,26 @@ public final class ChronicleMapBuilder implements return segments <= 16 * 1024 ? 64 : 32; } - @Override + /** + * Configures if the maps created by this {@code ChronicleMapBuilder} should return {@code null} + * instead of previous mapped values on {@link ChronicleMap#put(Object, Object) + * ChornicleMap.put(key, value)} calls. + * + *

{@link Map#put(Object, Object) Map.put()} returns the previous value, functionality + * which is rarely used but fairly cheap for simple in-process, on-heap implementations like + * {@link HashMap}. But an off-heap collection has to create a new object and deserialize + * the data from off-heap memory. A collection hiding remote queries over the network should + * send the value back in addition to that. It's expensive for something you probably don't use. + * + *

By default, of cause, {@code ChronicleMap} conforms the general {@code Map} contract and + * returns the previous mapped value on {@code put()} calls. + * + * @param putReturnsNull {@code true} if you want {@link ChronicleMap#put(Object, Object) + * ChronicleMap.put()} to not return the value that was replaced but + * instead return {@code null} + * @return this builder back + * @see #removeReturnsNull(boolean) + */ public ChronicleMapBuilder putReturnsNull(boolean putReturnsNull) { this.putReturnsNull = putReturnsNull; return this; @@ -990,7 +1000,26 @@ public final class ChronicleMapBuilder implements return putReturnsNull; } - @Override + /** + * Configures if the maps created by this {@code ChronicleMapBuilder} should return {@code null} + * instead of the last mapped value on {@link ChronicleMap#remove(Object) + * ChronicleMap.remove(key)} calls. + * + *

{@link Map#remove(Object) Map.remove()} returns the previous value, functionality which is + * rarely used but fairly cheap for simple in-process, on-heap implementations like {@link + * HashMap}. But an off-heap collection has to create a new object and deserialize the data + * from off-heap memory. A collection hiding remote queries over the network should send + * the value back in addition to that. It's expensive for something you probably don't use. + * + *

By default, of cause, {@code ChronicleMap} conforms the general {@code Map} contract and + * returns the mapped value on {@code remove()} calls. + * + * @param removeReturnsNull {@code true} if you want {@link ChronicleMap#remove(Object) + * ChronicleMap.remove()} to not return the value of the removed entry + * but instead return {@code null} + * @return this builder back + * @see #putReturnsNull(boolean) + */ public ChronicleMapBuilder removeReturnsNull(boolean removeReturnsNull) { this.removeReturnsNull = removeReturnsNull; return this; @@ -1465,8 +1494,6 @@ public final class ChronicleMapBuilder implements } // This is needed to property initialize key and value serialization builders, // which are later used in replication - // TODO don't use SerializationBuilders in replication, extract marshallers - // needed to transmit to stateless clients directly from map instance preMapConstruction(singleHashReplication != null || channel != null); return establishReplication(map, singleHashReplication, channel); } diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMapStatelessClientBuilder.java b/src/main/java/net/openhft/chronicle/map/ChronicleMapStatelessClientBuilder.java deleted file mode 100644 index 5888b4f84..000000000 --- a/src/main/java/net/openhft/chronicle/map/ChronicleMapStatelessClientBuilder.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2015 higherfrequencytrading.com - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package net.openhft.chronicle.map; - -import net.openhft.chronicle.hash.ChronicleHashStatelessClientBuilder; -import net.openhft.lang.MemoryUnit; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * @author Rob Austin. - */ -public final class ChronicleMapStatelessClientBuilder implements - ChronicleHashStatelessClientBuilder, - ChronicleMap>, - MapBuilder> { - - public static ChronicleMapStatelessClientBuilder of( - InetSocketAddress serverAddress) { - return new ChronicleMapStatelessClientBuilder<>(serverAddress); - } - - // This method is meaningful, despite you could call of().create(), because Java 7 doesn't - // infer type parameters if case of chained calls, like this; and then you couldn't omit class - // name. Then it is - // ChronicleMapStatelessClientBuilder..of(addr).create() - // vs - // createClientOf(addr) // static import - // -- the second is really shorter. - - /** - * Equivalent of {@code ChronicleMapStatelessClientBuilder.of(serverAddress).create()}. - * - * @param serverAddress address of the server map - * @param key type of the map - * @param value type of the map - * @return stateless client of the ChronicleMap of server - * @throws IOException if it not possible to connect to the {@code serverAddress} - */ - public static ChronicleMap createClientOf(InetSocketAddress serverAddress) - throws IOException { - return ChronicleMapStatelessClientBuilder.of(serverAddress).create(); - } - - private final InetSocketAddress remoteAddress; - private boolean putReturnsNull = false; - private boolean removeReturnsNull = false; - private long timeoutMs = TimeUnit.SECONDS.toMillis(10); - private String name; - private int tcpBufferSize = (int) MemoryUnit.KILOBYTES.toBytes(64); - - private final AtomicBoolean used = new AtomicBoolean(false); - - ChronicleMapStatelessClientBuilder(InetSocketAddress remoteAddress) { - this.remoteAddress = remoteAddress; - } - - InetSocketAddress remoteAddress() { - return remoteAddress; - } - - @Override - public ChronicleMapStatelessClientBuilder putReturnsNull(boolean putReturnsNull) { - this.putReturnsNull = putReturnsNull; - return this; - } - - boolean putReturnsNull() { - return putReturnsNull; - } - - @Override - public ChronicleMapStatelessClientBuilder removeReturnsNull(boolean removeReturnsNull) { - this.removeReturnsNull = removeReturnsNull; - return this; - } - - boolean removeReturnsNull() { - return removeReturnsNull; - } - - @Override - public ChronicleMapStatelessClientBuilder timeout(long timeout, TimeUnit units) { - this.timeoutMs = units.toMillis(timeout); - return this; - } - - long timeoutMs() { - return timeoutMs; - } - - @Override - public ChronicleMapStatelessClientBuilder name(String name) { - this.name = name; - return this; - } - - String name() { - return name; - } - - @Override - public ChronicleMapStatelessClientBuilder tcpBufferSize(int tcpBufferSize) { - this.tcpBufferSize = tcpBufferSize; - return this; - } - - int tcpBufferSize() { - return tcpBufferSize; - } - - @Override - public ChronicleMap create() throws IOException { - if (!used.getAndSet(true)) { - return new StatelessChronicleMap<>(this); - } else { - throw new IllegalStateException( - "A stateless client has already been created using this builder. " + - "Create a new ChronicleMapStatelessClientBuilder " + - "to create a new stateless client"); - } - } -} diff --git a/src/main/java/net/openhft/chronicle/map/MapBuilder.java b/src/main/java/net/openhft/chronicle/map/MapBuilder.java index e4c4e9511..c4f3321f5 100644 --- a/src/main/java/net/openhft/chronicle/map/MapBuilder.java +++ b/src/main/java/net/openhft/chronicle/map/MapBuilder.java @@ -20,55 +20,14 @@ import java.util.HashMap; import java.util.Map; /** - * Common configurations of {@link ChronicleMapBuilder} and - * {@link ChronicleMapStatelessClientBuilder}. + * Common configurations of {@link ChronicleMapBuilder}. * * @param concrete builder class */ public interface MapBuilder> { - /** - * Configures if the maps created by this {@code MapBuilder} should return {@code null} - * instead of previous mapped values on {@link ChronicleMap#put(Object, Object) - * ChornicleMap.put(key, value)} calls. - * - *

{@link Map#put(Object, Object) Map.put()} returns the previous value, functionality - * which is rarely used but fairly cheap for simple in-process, on-heap implementations like - * {@link HashMap}. But an off-heap collection has to create a new object and deserialize - * the data from off-heap memory. A collection hiding remote queries over the network should - * send the value back in addition to that. It's expensive for something you probably don't use. - * - *

By default, of cause, {@code ChronicleMap} conforms the general {@code Map} contract and - * returns the previous mapped value on {@code put()} calls. - * - * @param putReturnsNull {@code true} if you want {@link ChronicleMap#put(Object, Object) - * ChronicleMap.put()} to not return the value that was replaced but - * instead return {@code null} - * @return {@code MapBuilder} with this configuration applied - * @see #removeReturnsNull(boolean) - */ + C putReturnsNull(boolean putReturnsNull); - - /** - * Configures if the maps created by this {@code MapBuilder} should return {@code null} - * instead of the last mapped value on {@link ChronicleMap#remove(Object) - * ChronicleMap.remove(key)} calls. - * - *

{@link Map#remove(Object) Map.remove()} returns the previous value, functionality which is - * rarely used but fairly cheap for simple in-process, on-heap implementations like {@link - * HashMap}. But an off-heap collection has to create a new object and deserialize the data - * from off-heap memory. A collection hiding remote queries over the network should send - * the value back in addition to that. It's expensive for something you probably don't use. - * - *

By default, of cause, {@code ChronicleMap} conforms the general {@code Map} contract and - * returns the mapped value on {@code remove()} calls. - * - * @param removeReturnsNull {@code true} if you want {@link ChronicleMap#remove(Object) - * ChronicleMap.remove()} to not return the value of the removed entry - * but instead return {@code null} - * @return {@code MapBuilder} with this configuration applied - * @see #putReturnsNull(boolean) - */ C removeReturnsNull(boolean removeReturnsNull); } diff --git a/src/main/java/net/openhft/chronicle/map/MapEntryCallback.java b/src/main/java/net/openhft/chronicle/map/MapEntryCallback.java deleted file mode 100644 index 29fed8e92..000000000 --- a/src/main/java/net/openhft/chronicle/map/MapEntryCallback.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2015 higherfrequencytrading.com - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ -package net.openhft.chronicle.map; - -/** - * Created by Rob Austin - */ -public interface MapEntryCallback { - - void onEntry(K key, V value); - - void onFinished(); -} diff --git a/src/main/java/net/openhft/chronicle/map/Replicators.java b/src/main/java/net/openhft/chronicle/map/Replicators.java index 63f1550bb..72d02fad1 100644 --- a/src/main/java/net/openhft/chronicle/map/Replicators.java +++ b/src/main/java/net/openhft/chronicle/map/Replicators.java @@ -118,16 +118,9 @@ final class Replicators { TcpTransportAndNetworkConfig tcpConfig = replication.tcpTransportAndNetwork(); - TcpReplicator.StatelessClientParameters statelessClientParameters = - new TcpReplicator.StatelessClientParameters( - replicatedMap, - builder.keyBuilder, - builder.valueBuilder); - return new TcpReplicator(replica, entryExternalizable, tcpConfig, replication.remoteNodeValidator(), - statelessClientParameters, replication.name(), replication.connectionListener()); } diff --git a/src/main/java/net/openhft/chronicle/map/StatelessChronicleMap.java b/src/main/java/net/openhft/chronicle/map/StatelessChronicleMap.java deleted file mode 100644 index 676f45ad8..000000000 --- a/src/main/java/net/openhft/chronicle/map/StatelessChronicleMap.java +++ /dev/null @@ -1,1939 +0,0 @@ -/* - * Copyright (C) 2015 higherfrequencytrading.com - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package net.openhft.chronicle.map; - -import net.openhft.chronicle.bytes.IORuntimeException; -import net.openhft.chronicle.core.io.CloseablesManager; -import net.openhft.chronicle.hash.Data; -import net.openhft.chronicle.hash.function.SerializableFunction; -import net.openhft.chronicle.hash.impl.util.BuildVersion; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.chronicle.hash.serialization.internal.ReaderWithSize; -import net.openhft.chronicle.hash.serialization.internal.SerializationBuilder; -import net.openhft.lang.io.ByteBufferBytes; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.NativeBytes; -import net.openhft.lang.threadlocal.ThreadLocalCopies; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.Closeable; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.AsynchronousCloseException; -import java.nio.channels.SocketChannel; -import java.util.*; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Consumer; -import java.util.function.Predicate; - -import static java.nio.ByteBuffer.allocateDirect; -import static java.util.Collections.emptyList; -import static net.openhft.chronicle.map.AbstractChannelReplicator.SIZE_OF_SIZE; -import static net.openhft.chronicle.map.AbstractChannelReplicator.SIZE_OF_TRANSACTION_ID; -import static net.openhft.chronicle.map.StatelessChronicleMap.EventId.*; - -/** - * @author Rob Austin. - */ -class StatelessChronicleMap implements ChronicleMap, Closeable, Cloneable { - - private static final Logger LOG = LoggerFactory.getLogger(StatelessChronicleMap.class); - private static final byte STATELESS_CLIENT_IDENTIFIER = (byte) -127; - - private final byte[] connectionByte = new byte[1]; - private final ByteBuffer connectionOutBuffer = ByteBuffer.wrap(connectionByte); - private final String name; - - private ByteBuffer outBuffer; - private ByteBufferBytes outBytes; - - private ByteBuffer inBuffer; - private ByteBufferBytes inBytes; - private ReaderWithSize keyReaderWithSize; - private WriterWithSize keyWriterWithSize; - private ReaderWithSize valueReaderWithSize; - private WriterWithSize valueWriterWithSize; - private SocketChannel clientChannel; - - @Nullable - private CloseablesManager closeables; - private final InetSocketAddress remoteAddress; - private final long timeoutMs; - private final int tcpBufferSize; - - private Class kClass; - private Class vClass; - private boolean putReturnsNull; - private boolean removeReturnsNull; - - - private final ReentrantLock inBytesLock = new ReentrantLock(true); - private final ReentrantLock outBytesLock = new ReentrantLock(); - - private final BufferResizer outBufferResizer = newCapacity -> resizeBufferOutBuffer(newCapacity); - - enum EventId { - HEARTBEAT, - STATEFUL_UPDATE, - LONG_SIZE, - SIZE, - IS_EMPTY, - CONTAINS_KEY, - CONTAINS_VALUE, - GET, - PUT, - PUT_WITHOUT_ACC, - REMOVE, - REMOVE_WITHOUT_ACC, - CLEAR, - KEY_SET, - VALUES, - ENTRY_SET, - REPLACE, - REPLACE_WITH_OLD_AND_NEW_VALUE, - PUT_IF_ABSENT, - REMOVE_WITH_VALUE, - TO_STRING, - APPLICATION_VERSION, - PERSISTED_DATA_VERSION, - PUT_ALL, - PUT_ALL_WITHOUT_ACC, - HASH_CODE, - MAP_FOR_KEY, - PUT_MAPPED, - KEY_BUILDER, - VALUE_BUILDER - } - - - // used by the enterprise version - private int identifier; - - @SuppressWarnings("UnusedDeclaration") - void identifier(int identifier) { - this.identifier = identifier; - } - - - @NotNull - private final AtomicLong transactionID = new AtomicLong(0); - - StatelessChronicleMap(@NotNull final ChronicleMapStatelessClientBuilder config) { - this.remoteAddress = config.remoteAddress(); - this.timeoutMs = config.timeoutMs(); - this.tcpBufferSize = config.tcpBufferSize(); - this.name = config.name(); - this.putReturnsNull = config.putReturnsNull(); - this.removeReturnsNull = config.removeReturnsNull(); - - outBuffer = allocateDirect(128).order(ByteOrder.nativeOrder()); - outBytes = new ByteBufferBytes(outBuffer.slice()); - - inBuffer = allocateDirect(128).order(ByteOrder.nativeOrder()); - inBytes = new ByteBufferBytes(inBuffer.slice()); - - attemptConnect(remoteAddress); - - checkVersion(); - loadKeyValueSerializers(); - } - - private void loadKeyValueSerializers() { - final SerializationBuilder keyBuilder = - fetchObject(SerializationBuilder.class, KEY_BUILDER); - kClass = keyBuilder.eClass; - final SerializationBuilder valueBuilder = - fetchObject(SerializationBuilder.class, VALUE_BUILDER); - vClass = valueBuilder.eClass; - - keyReaderWithSize = new ReaderWithSize(keyBuilder); - keyWriterWithSize = new WriterWithSize(keyBuilder, outBufferResizer); - - valueReaderWithSize = new ReaderWithSize(valueBuilder); - valueWriterWithSize = new WriterWithSize(valueBuilder, outBufferResizer); - - } - - private void checkVersion() { - - String serverVersion = serverApplicationVersion(); - String clientVersion = clientVersion(); - - if (!serverVersion.equals(clientVersion)) { - LOG.warn("DIFFERENT CHRONICLE-MAP VERSIONS: The Chronicle-Map-Server and " + - "Stateless-Client are on different " + - "versions, " + - " we suggest that you use the same version, server=" + serverApplicationVersion() + ", " + - "client=" + clientVersion); - } - } - - @Override - public void getAll(File toFile) throws IOException { - JsonSerializer.getAll(toFile, this, emptyList()); - } - - @Override - public void putAll(File fromFile) throws IOException { - JsonSerializer.putAll(fromFile, this, emptyList()); - } - - @Override - public V newValueInstance() { - if (vClass.equals(CharSequence.class) || vClass.equals(StringBuilder.class)) { - return (V) new StringBuilder(); - } - return VanillaChronicleMap.newInstance(vClass, false); - } - - @Override - public K newKeyInstance() { - return VanillaChronicleMap.newInstance(kClass, true); - } - - @Override - public Class keyClass() { - return kClass; - } - - @Override - public boolean forEachEntryWhile(Predicate> predicate) { - // TODO implement! - throw new UnsupportedOperationException(); - } - - @Override - public void forEachEntry(Consumer> action) { - // TODO implement! - throw new UnsupportedOperationException(); - } - - @Override - public Class valueClass() { - return vClass; - } - - - private void checkTimeout(long timeoutTime) { -// if (timeoutTime < System.currentTimeMillis() && !IS_DEBUG) -// throw new RemoteCallTimeoutException(); - } - - private synchronized void lazyConnect(final long timeoutMs, - final InetSocketAddress remoteAddress) { - if (clientChannel != null) - return; - - if (LOG.isDebugEnabled()) - LOG.debug("attempting to connect to " + remoteAddress + " ,name=" + name); - - SocketChannel result; - - long timeoutAt = System.currentTimeMillis() + timeoutMs; - - for (; ; ) { - checkTimeout(timeoutAt); - - // ensures that the excising connection are closed - closeExisting(); - - try { - result = AbstractChannelReplicator.openSocketChannel(closeables); - if (!result.connect(remoteAddress)) { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - continue; - } - - result.socket().setTcpNoDelay(true); - doHandShaking(result); - break; - } catch (IOException e) { - if (closeables != null) closeables.closeQuietly(); - } catch (Exception e) { - if (closeables != null) closeables.closeQuietly(); - throw e; - } - } - clientChannel = result; - byte[] bytes = copyBufferBytes(); - - long position = outBytes.position(); - int limit = outBuffer.limit(); - - outBuffer.clear(); - outBytes.clear(); - // outBytesLock.unlock(); - // assert !outBytesLock.isHeldByCurrentThread(); - try { - checkVersion(); - loadKeyValueSerializers(); - } finally { - outBuffer.clear(); - outBuffer.put(bytes); - outBytes.limit(limit); - outBytes.position(position); - // outBytesLock.lock(); - } - - } - - private byte[] copyBufferBytes() { - byte[] bytes = new byte[outBuffer.limit()]; - outBuffer.position(0); - outBuffer.get(bytes); - return bytes; - } - - /** - * attempts a single connect without a timeout and eat any IOException used typically in the - * constructor, its possible the server is not running with this instance is created, {@link - * net.openhft.chronicle.map.StatelessChronicleMap#lazyConnect(long, - * java.net.InetSocketAddress)} will attempt to establish the connection when the client make - * the first map method call. - * - * @param remoteAddress the Inet Socket Address - * @throws java.io.IOException - * @see net.openhft.chronicle.map.StatelessChronicleMap#lazyConnect(long, - * java.net.InetSocketAddress) - */ - - private synchronized void attemptConnect(final InetSocketAddress remoteAddress) { - - // ensures that the excising connection are closed - closeExisting(); - - try { - SocketChannel socketChannel = AbstractChannelReplicator.openSocketChannel(closeables); - if (socketChannel.connect(remoteAddress)) { - doHandShaking(socketChannel); - clientChannel = socketChannel; - } - - } catch (IOException e) { - if (closeables != null) closeables.closeQuietly(); - clientChannel = null; - } - - - } - - /** - * closes the existing connections and establishes a new closeables - */ - private void closeExisting() { - // ensure that any excising connection are first closed - if (closeables != null) - closeables.closeQuietly(); - - closeables = new CloseablesManager(); - } - - /** - * initiates a very simple level of handshaking with the remote server, we send a special ID of - * -127 ( when the server receives this it knows its dealing with a stateless client, receive - * back an identifier from the server - * - * @param clientChannel clientChannel - * @throws java.io.IOException - */ - private synchronized void doHandShaking(@NotNull final SocketChannel clientChannel) throws IOException { - - connectionByte[0] = STATELESS_CLIENT_IDENTIFIER; - this.connectionOutBuffer.clear(); - - long timeoutTime = System.currentTimeMillis() + timeoutMs; - - // write a single byte - while (connectionOutBuffer.hasRemaining()) { - clientChannel.write(connectionOutBuffer); - checkTimeout(timeoutTime); - } - - this.connectionOutBuffer.clear(); - - if (!clientChannel.finishConnect() || !clientChannel.socket().isBound()) - return; - - // read a single byte back - while (this.connectionOutBuffer.position() <= 0) { - int read = clientChannel.read(this.connectionOutBuffer);// the remote identifier - if (read == -1) - throw new IOException("server conncetion closed"); - checkTimeout(timeoutTime); - } - - byte remoteIdentifier = connectionByte[0]; - - if (LOG.isDebugEnabled()) - LOG.debug("Attached to a map with a remote identifier=" + remoteIdentifier + " ,name=" + name); - - } - - @NotNull - public File file() { - throw new UnsupportedOperationException(); - } - - public synchronized void close() { - - if (closeables != null) - closeables.closeQuietly(); - closeables = null; - clientChannel = null; - - } - - @Override - public boolean isOpen() { - return closeables != null; - } - - /** - * the transaction id are generated as unique timestamps - * - * @param time in milliseconds - * @return a unique transactionId - */ - private long nextUniqueTransaction(long time) { - long id = time * TcpReplicator.TIMESTAMP_FACTOR; - for (; ; ) { - long old = transactionID.get(); - if (old >= id) id = old + 1; - if (transactionID.compareAndSet(old, id)) - break; - } - return id; - } - - @SuppressWarnings("NullableProblems") - public V putIfAbsent(K key, V value) { - - if (key == null || value == null) - throw new NullPointerException(); - - return fetchObject(vClass, PUT_IF_ABSENT, key, value); - } - - - @SuppressWarnings("NullableProblems") - public boolean remove(Object key, Object value) { - - if (key == null) - throw new NullPointerException(); - - return value != null && fetchBoolean(REMOVE_WITH_VALUE, (K) key, (V) value); - - } - - - @SuppressWarnings("NullableProblems") - public boolean replace(K key, V oldValue, V newValue) { - if (key == null || oldValue == null || newValue == null) - throw new NullPointerException(); - - return fetchBoolean(REPLACE_WITH_OLD_AND_NEW_VALUE, key, oldValue, newValue); - } - - @SuppressWarnings("NullableProblems") - public V replace(K key, V value) { - if (key == null || value == null) - throw new NullPointerException(); - - return fetchObject(vClass, REPLACE, key, value); - } - - public int size() { - return (int) longSize(); - } - - /** - * calling this method should be avoided at all cost, as the entire {@code object} is - * serialized. This equals can be used to compare map that extends ChronicleMap. So two - * Chronicle Maps that contain the same data are considered equal, even if the instances of the - * chronicle maps were of different types - * - * @param object the object that you are comparing against - * @return true if the contain the same data - */ - @Override - public boolean equals(@Nullable Object object) { - if (this == object) return true; - if (object == null || object.getClass().isAssignableFrom(Map.class)) - return false; - - final Map that = (Map) object; - - final int size = size(); - - if (that.size() != size) - return false; - - final Set> entries = entrySet(); - return that.entrySet().equals(entries); - } - - @Override - public int hashCode() { - return fetchInt(HASH_CODE); - } - - @NotNull - public String toString() { - return fetchObject(String.class, TO_STRING); - } - - @NotNull - public String serverApplicationVersion() { - return fetchObject(String.class, APPLICATION_VERSION); - } - - @NotNull - public String serverPersistedDataVersion() { - return fetchObject(String.class, PERSISTED_DATA_VERSION); - } - - @SuppressWarnings("WeakerAccess") - @NotNull - public String clientVersion() { - return BuildVersion.version(); - } - - public boolean isEmpty() { - return fetchBoolean(IS_EMPTY); - } - - - public boolean containsKey(Object key) { - return fetchBooleanK(CONTAINS_KEY, (K) key); - } - - @NotNull - private NullPointerException keyNotNullNPE() { - return new NullPointerException("key can not be null"); - } - - public boolean containsValue(Object value) { - return fetchBooleanV(CONTAINS_VALUE, (V) value); - } - - public long longSize() { - return fetchLong(LONG_SIZE); - } - - @NotNull - @Override - public ExternalMapQueryContext queryContext(K key) { - throw new UnsupportedOperationException("Contexts are not supported by stateless clients"); - } - - @NotNull - @Override - public ExternalMapQueryContext queryContext(Data key) { - throw new UnsupportedOperationException("Contexts are not supported by stateless clients"); - } - - @Override - public MapSegmentContext segmentContext(int segmentIndex) { - throw new UnsupportedOperationException(); - } - - @Override - public int segments() { - throw new UnsupportedOperationException(); - } - - public V get(Object key) { - return fetchObject(vClass, GET, (K) key); - } - - @Nullable - public V getUsing(K key, V usingValue) { - - - final long startTime = System.currentTimeMillis(); - ThreadLocalCopies copies; - - long transactionId; - - outBytesLock.lock(); - try { - - final long sizeLocation = writeEventAnSkip(GET); - - copies = writeKey((K) key); - transactionId = send(sizeLocation, startTime); - } finally { - outBytesLock.unlock(); - } - - if (eventReturnsNull(GET)) - return null; - - return (V) readValue(transactionId, startTime, copies, usingValue); - - } - - @NotNull - public V acquireUsing(@NotNull K key, V usingValue) { - throw new UnsupportedOperationException("acquireUsing() is not supported for stateless " + - "clients"); - } - - @NotNull - @Override - public net.openhft.chronicle.core.io.Closeable acquireContext(@NotNull K key, @NotNull V usingValue) { - throw new UnsupportedOperationException("Contexts are not supported by stateless clients"); - } - - public V remove(Object key) { - if (key == null) - throw keyNotNullNPE(); - return fetchObject(vClass, removeReturnsNull ? REMOVE_WITHOUT_ACC : REMOVE, (K) key); - } - - public V put(K key, V value) { - if (key == null || value == null) - throw new NullPointerException(); - return fetchObject(vClass, putReturnsNull ? PUT_WITHOUT_ACC : PUT, key, value); - } - - @Nullable - public R getMapped(@Nullable K key, @NotNull SerializableFunction function) { - if (key == null) - throw keyNotNullNPE(); - return fetchObject(MAP_FOR_KEY, key, function); - } - - - @Nullable - @Override - public V putMapped(@Nullable K key, @NotNull UnaryOperator unaryOperator) { - if (key == null) - throw keyNotNullNPE(); - return fetchObject(PUT_MAPPED, key, unaryOperator); - } - - - private Bytes resizeBufferOutBuffer(int newCapacity) { - return resizeBufferOutBuffer(newCapacity, outBytes.position()); - } - - private Bytes resizeBufferOutBuffer(int newCapacity, long start) { - assert outBytesLock.isHeldByCurrentThread(); - assert !inBytesLock.isHeldByCurrentThread(); - - if (LOG.isDebugEnabled()) - LOG.debug("resizing buffer to newCapacity=" + newCapacity + " ,name=" + name); - - if (newCapacity < outBuffer.capacity()) - throw new IllegalStateException("it not possible to resize the buffer smaller"); - - assert newCapacity < Integer.MAX_VALUE; - - final ByteBuffer result = ByteBuffer.allocate(newCapacity).order(ByteOrder.nativeOrder()); - final long bytesPosition = outBytes.position(); - - outBytes = new ByteBufferBytes(result.slice()); - - outBuffer.position(0); - outBuffer.limit((int) bytesPosition); - - int numberOfLongs = (int) bytesPosition / 8; - - // chunk in longs first - for (int i = 0; i < numberOfLongs; i++) { - outBytes.writeLong(outBuffer.getLong()); - } - - for (int i = numberOfLongs * 8; i < bytesPosition; i++) { - outBytes.writeByte(outBuffer.get()); - } - - outBuffer = result; - - assert outBuffer.capacity() == outBytes.capacity(); - - assert outBuffer.capacity() == newCapacity; - assert outBuffer.capacity() == outBytes.capacity(); - assert outBytes.limit() == outBytes.capacity(); - outBytes.position(start); - return outBytes; - } - - - private void resizeBufferInBuffer(int newCapacity, long start) { -// assert !outBytesLock.isHeldByCurrentThread(); - assert inBytesLock.isHeldByCurrentThread(); - - if (LOG.isDebugEnabled()) - LOG.debug("InBuffer resizing buffer to newCapacity=" + newCapacity + " ,name=" + name); - - if (newCapacity < inBuffer.capacity()) - throw new IllegalStateException("it not possible to resize the buffer smaller"); - - assert newCapacity < Integer.MAX_VALUE; - - final ByteBuffer result = ByteBuffer.allocate(newCapacity).order(ByteOrder.nativeOrder()); - final long bytesPosition = inBytes.position(); - - inBytes = new ByteBufferBytes(result.slice()); - - inBuffer.position(0); - inBuffer.limit((int) bytesPosition); - - int numberOfLongs = (int) bytesPosition / 8; - - // chunk in longs first - for (int i = 0; i < numberOfLongs; i++) { - inBytes.writeLong(inBuffer.getLong()); - } - - for (int i = numberOfLongs * 8; i < bytesPosition; i++) { - inBytes.writeByte(inBuffer.get()); - } - - inBuffer = result; - - assert inBuffer.capacity() == inBytes.capacity(); - assert inBuffer.capacity() == newCapacity; - assert inBuffer.capacity() == inBytes.capacity(); - assert inBytes.limit() == inBytes.capacity(); - - inBytes.position(start); - } - - public void clear() { - fetchVoid(CLEAR); - } - - @NotNull - public Collection values() { - - final long timeoutTime; - final long transactionId; - - outBytesLock.lock(); - try { - - final long sizeLocation = writeEventAnSkip(VALUES); - final long startTime = System.currentTimeMillis(); - - timeoutTime = System.currentTimeMillis() + timeoutMs; - transactionId = send(sizeLocation, startTime); - } finally { - outBytesLock.unlock(); - } - - // get the data back from the server - final Collection result = new ArrayList(); - - BytesReader valueReader = valueReaderWithSize.readerForLoop(null); - for (; ; ) { - inBytesLock.lock(); - try { - - final Bytes in = blockingFetchReadOnly(timeoutTime, transactionId); - - final boolean hasMoreEntries = in.readBoolean(); - - // number of entries in this chunk - final long size = in.readInt(); - - for (int i = 0; i < size; i++) { - result.add(valueReaderWithSize.readInLoop(in, valueReader)); - } - - if (!hasMoreEntries) - break; - - } finally { - inBytesLock.unlock(); - } - } - return result; - } - - @NotNull - public Set> entrySet() { - final long transactionId; - final long timeoutTime; - - outBytesLock.lock(); - try { - final long sizeLocation = writeEventAnSkip(ENTRY_SET); - final long startTime = System.currentTimeMillis(); - timeoutTime = System.currentTimeMillis() + timeoutMs; - transactionId = send(sizeLocation, startTime); - } finally { - outBytesLock.unlock(); - } - - // get the data back from the server - ThreadLocalCopies copies = keyReaderWithSize.getCopies(null); - final BytesReader keyReader = keyReaderWithSize.readerForLoop(copies); - copies = valueReaderWithSize.getCopies(copies); - final BytesReader valueReader = valueReaderWithSize.readerForLoop(copies); - final Map result = new HashMap(); - - for (; ; ) { - - inBytesLock.lock(); - try { - - Bytes in = blockingFetchReadOnly(timeoutTime, transactionId); - - final boolean hasMoreEntries = in.readBoolean(); - - // number of entries in this chunk - final long size = in.readInt(); - - for (int i = 0; i < size; i++) { - final K k = keyReaderWithSize.readInLoop(in, keyReader); - final V v = valueReaderWithSize.readInLoop(in, valueReader); - result.put(k, v); - } - - if (!hasMoreEntries) - break; - - } finally { - inBytesLock.unlock(); - } - } - - return result.entrySet(); - - } - - /** - * @param callback each entry is passed to the callback - */ - void entrySet(@NotNull MapEntryCallback callback) { - final long transactionId; - final long timeoutTime; - - outBytesLock.lock(); - try { - final long sizeLocation = writeEventAnSkip(ENTRY_SET); - final long startTime = System.currentTimeMillis(); - timeoutTime = System.currentTimeMillis() + timeoutMs; - transactionId = send(sizeLocation, startTime); - } finally { - outBytesLock.unlock(); - } - - // get the data back from the server - ThreadLocalCopies copies = keyReaderWithSize.getCopies(null); - final BytesReader keyReader = keyReaderWithSize.readerForLoop(copies); - copies = valueReaderWithSize.getCopies(copies); - final BytesReader valueReader = valueReaderWithSize.readerForLoop(copies); - - for (; ; ) { - - inBytesLock.lock(); - try { - - Bytes in = blockingFetchReadOnly(timeoutTime, transactionId); - - final boolean hasMoreEntries = in.readBoolean(); - - // number of entries in this chunk - final long size = in.readInt(); - - for (int i = 0; i < size; i++) { - final K k = keyReaderWithSize.readInLoop(in, keyReader); - final V v = valueReaderWithSize.readInLoop(in, valueReader); - callback.onEntry(k, v); - } - - if (!hasMoreEntries) - break; - - } finally { - inBytesLock.unlock(); - } - } - - - } - - public void putAll(@NotNull Map map) { - - final long sizeLocation; - - outBytesLock.lock(); - try { - sizeLocation = putReturnsNull ? writeEventAnSkip(PUT_ALL_WITHOUT_ACC) : - writeEventAnSkip(PUT_ALL); - } finally { - outBytesLock.unlock(); - } - final long startTime = System.currentTimeMillis(); - final long timeoutTime = startTime + timeoutMs; - final long transactionId; - final int numberOfEntries = map.size(); - int numberOfEntriesReadSoFar = 0; - - outBytesLock.lock(); - try { - - outBytes.writeStopBit(numberOfEntries); - assert outBytes.limit() == outBytes.capacity(); - ThreadLocalCopies copies = keyWriterWithSize.getCopies(null); - final Object keyWriter = keyWriterWithSize.writerForLoop(copies); - copies = valueWriterWithSize.getCopies(copies); - final Object valueWriter = valueWriterWithSize.writerForLoop(copies); - - for (final Map.Entry e : map.entrySet()) { - final K key = e.getKey(); - final V value = e.getValue(); - if (key == null || value == null) - throw new NullPointerException(); - - numberOfEntriesReadSoFar++; - - long start = outBytes.position(); - - final Class keyClass = key.getClass(); - if (!kClass.isAssignableFrom(keyClass)) { - throw new ClassCastException("key=" + key + " is of type=" + keyClass + " " + - "and should" + - " be of type=" + kClass); - } - - writeKeyInLoop(key, keyWriter, copies); - - final Class valueClass = value.getClass(); - if (!vClass.isAssignableFrom(valueClass)) - throw new ClassCastException("value=" + value + " is of type=" + valueClass + - " and " + - "should be of type=" + vClass); - - writeValueInLoop(value, valueWriter, copies); - - } - - transactionId = send(sizeLocation, startTime); - } finally { - outBytesLock.unlock(); - } - - - if (!putReturnsNull) { - inBytesLock.lock(); - try { - blockingFetchReadOnly(timeoutTime, transactionId); - } finally { - inBytesLock.unlock(); - } - } - } - - @NotNull - public Set keySet() { - final long transactionId; - final long timeoutTime; - - outBytesLock.lock(); - try { - final long sizeLocation = writeEventAnSkip(KEY_SET); - final long startTime = System.currentTimeMillis(); - timeoutTime = startTime + timeoutMs; - transactionId = send(sizeLocation, startTime); - } finally { - outBytesLock.unlock(); - } - - final Set result = new HashSet<>(); - final BytesReader keyReader = keyReaderWithSize.readerForLoop(null); - - for (; ; ) { - - inBytesLock.lock(); - try { - - final Bytes in = blockingFetchReadOnly(timeoutTime, transactionId); - final boolean hasMoreEntries = in.readBoolean(); - - // number of entries in the chunk - long size = in.readInt(); - - for (int i = 0; i < size; i++) { - result.add(keyReaderWithSize.readInLoop(in, keyReader)); - } - - if (!hasMoreEntries) - break; - - } finally { - inBytesLock.unlock(); - } - } - - return result; - } - - - private long readLong(long transactionId, long startTime) { - - assert !outBytesLock.isHeldByCurrentThread(); - - final long timeoutTime = startTime + this.timeoutMs; - - // receive - inBytesLock.lock(); - try { - return blockingFetchReadOnly(timeoutTime, transactionId).readLong(); - } finally { - inBytesLock.unlock(); - } - } - - - private long writeEvent(@NotNull StatelessChronicleMap.EventId event) { - assert outBytesLock.isHeldByCurrentThread(); - assert !inBytesLock.isHeldByCurrentThread(); - assert event != HEARTBEAT; - - if (outBytes.remaining() < 128) - resizeBufferOutBuffer((int) outBytes.capacity() + 128, outBytes.position()); - - outBytes.writeByte((byte) event.ordinal()); - - - return markSizeLocation(); - } - - /** - * skips for the transactionid - */ - private long writeEventAnSkip(@NotNull EventId event) { - - assert outBytesLock.isHeldByCurrentThread(); - assert !inBytesLock.isHeldByCurrentThread(); - - final long sizeLocation = writeEvent(event); - assert outBytes.readByte(sizeLocation - 1) == event.ordinal(); - - assert outBytes.position() > 0; - - // skips for the transaction id - outBytes.skip(SIZE_OF_TRANSACTION_ID); - outBytes.writeByte(identifier); - outBytes.writeInt(0); - assert outBytes.readByte(sizeLocation - 1) == event.ordinal(); - return sizeLocation; - } - - class Entry implements Map.Entry { - - final K key; - final V value; - - /** - * Creates new entry. - */ - Entry(K k1, V v) { - value = v; - key = k1; - } - - public final K getKey() { - return key; - } - - public final V getValue() { - return value; - } - - public final V setValue(V newValue) { - V oldValue = value; - StatelessChronicleMap.this.put(getKey(), newValue); - return oldValue; - } - - public final boolean equals(Object o) { - if (!(o instanceof Map.Entry)) - return false; - final Map.Entry e = (Map.Entry) o; - final Object k1 = getKey(); - final Object k2 = e.getKey(); - if (k1 == k2 || (k1 != null && k1.equals(k2))) { - Object v1 = getValue(); - Object v2 = e.getValue(); - if (v1 == v2 || (v1 != null && v1.equals(v2))) - return true; - } - return false; - } - - public final int hashCode() { - return (key == null ? 0 : key.hashCode()) ^ - (value == null ? 0 : value.hashCode()); - } - - @NotNull - public final String toString() { - return getKey() + "=" + getValue(); - } - } - - - /** - * sends data to the server via TCP/IP - * - * @param sizeLocation the position of the bit that marks the size - * @param startTime the current time - * @return a unique transaction id - */ - private long send(long sizeLocation, final long startTime) { - - assert outBytesLock.isHeldByCurrentThread(); - assert !inBytesLock.isHeldByCurrentThread(); - - long transactionId = nextUniqueTransaction(startTime); - final long timeoutTime = startTime + this.timeoutMs; - try { - - for (; ; ) { - if (clientChannel == null) { - lazyConnect(timeoutMs, remoteAddress); - } - try { - - if (LOG.isDebugEnabled()) - LOG.debug("sending data with transactionId=" + transactionId + " ,name=" + name); - - writeSizeAndTransactionIdAt(sizeLocation, transactionId); - - // send out all the bytes - writeBytesToSocket(timeoutTime); - - break; - - } catch (@NotNull java.nio.channels.ClosedChannelException /*| ClosedConnectionException*/ e) { - checkTimeout(timeoutTime); - lazyConnect(timeoutMs, remoteAddress); - } - } - } catch (IOException e) { - close(); - throw new IORuntimeException(e); - } catch (Exception e) { - close(); - throw e; - } - return transactionId; - } - - private Bytes blockingFetchReadOnly(long timeoutTime, final long transactionId) { - - - assert inBytesLock.isHeldByCurrentThread(); - // assert !outBytesLock.isHeldByCurrentThread(); - try { - - return blockingFetchThrowable(timeoutTime, transactionId); - } catch (AsynchronousCloseException e) { - LOG.error("name=" + name, e); - throw new RuntimeException(e); - } catch (IOException e) { - close(); - throw new IORuntimeException(e); - } catch (RuntimeException e) { - close(); - throw e; - } catch (Exception e) { - close(); - throw new RuntimeException(e); - } catch (AssertionError e) { - LOG.error("name=" + name, e); - throw e; - } - } - - // this is a transaction id and size that has been read by another thread. - private volatile long parkedTransactionId; - private volatile int parkedRemainingBytes; - private volatile long parkedTransactionTimeStamp; - - private Bytes blockingFetchThrowable(long timeoutTime, long transactionId) throws IOException, - InterruptedException { - -// assert !outBytesLock.isHeldByCurrentThread(); - assert inBytesLock.isHeldByCurrentThread(); - - int remainingBytes = nextEntry(timeoutTime, transactionId); - - if (inBytes.capacity() < remainingBytes) { - long pos = inBytes.position(); - long limit = inBytes.position(); - inBytes.position(limit); - resizeBufferInBuffer(remainingBytes, pos); - } else - inBytes.limit(inBytes.capacity()); - - try { - // block until we have received all the bytes in this chunk - receiveBytesFromSocket(remainingBytes, timeoutTime); - }catch (java.nio.channels.AsynchronousCloseException e ){ - return inBytes; - } - - final boolean isException = inBytes.readBoolean(); - - if (isException) { - Throwable throwable = (Throwable) inBytes.readObject(); - try { - Field stackTrace = Throwable.class.getDeclaredField("stackTrace"); - stackTrace.setAccessible(true); - List stes = new ArrayList<>(Arrays.asList((StackTraceElement[]) stackTrace.get(throwable))); - // prune the end of the stack. - for (int i = stes.size() - 1; i > 0 && stes.get(i).getClassName().startsWith("Thread"); i--) { - stes.remove(i); - } - InetSocketAddress address = remoteAddress; - stes.add(new StackTraceElement("~ remote", "tcp ~", address.getHostName(), address.getPort())); - StackTraceElement[] stackTrace2 = Thread.currentThread().getStackTrace(); - //noinspection ManualArrayToCollectionCopy - for (int i = 4; i < stackTrace2.length; i++) - stes.add(stackTrace2[i]); - stackTrace.set(throwable, stes.toArray(new StackTraceElement[stes.size()])); - } catch (Exception ignore) { - } - NativeBytes.UNSAFE.throwException(throwable); - } - - - return inBytes; - } - - private int nextEntry(long timeoutTime, long transactionId) throws IOException { -// assert !outBytesLock.isHeldByCurrentThread(); - assert inBytesLock.isHeldByCurrentThread(); - - int remainingBytes; - for (; ; ) { - - // read the next item from the socket - if (parkedTransactionId == 0) { - - assert parkedTransactionTimeStamp == 0; - assert parkedRemainingBytes == 0; - - receiveBytesFromSocket(SIZE_OF_SIZE + SIZE_OF_TRANSACTION_ID, timeoutTime); - - final int messageSize = inBytes.readInt(); - assert messageSize > 0 : "Invalid message size " + messageSize; - assert messageSize < 16 << 20 : "Invalid message size " + messageSize; - - final int remainingBytes0 = messageSize - (SIZE_OF_SIZE + SIZE_OF_TRANSACTION_ID); - final long transactionId0 = inBytes.readLong(); - - // check the transaction id is reasonable - assert transactionId0 > 1410000000000L * TcpReplicator.TIMESTAMP_FACTOR : - "TransactionId too small " + transactionId0 + " messageSize " + messageSize; - assert transactionId0 < 2100000000000L * TcpReplicator.TIMESTAMP_FACTOR : - "TransactionId too large " + transactionId0 + " messageSize " + messageSize; - - // if the transaction id is for this thread process it - if (transactionId0 == transactionId) { - - // we have the correct transaction id ! - parkedTransactionId = 0; - remainingBytes = remainingBytes0; - assert remainingBytes > 0; - - clearParked(); - break; - - } else { - // if the transaction id is not for this thread, park it and read the next one - parkedTransactionTimeStamp = System.currentTimeMillis(); - parkedRemainingBytes = remainingBytes0; - parkedTransactionId = transactionId0; - - pause(); - continue; - } - } - - // the transaction id was read by another thread, but is for this thread, process it - if (parkedTransactionId == transactionId) { - remainingBytes = parkedRemainingBytes; - clearParked(); - break; - } - - - // time out the old transaction id - if (System.currentTimeMillis() - timeoutTime > - parkedTransactionTimeStamp) { - - LOG.error("name=" + name, new IllegalStateException("Skipped Message with " + - "transaction-id=" + - parkedTransactionTimeStamp + - ", this can occur when you have another thread which has called the " + - "stateless client and terminated abruptly before the message has been " + - "returned from the server")); - - // read the the next message - receiveBytesFromSocket(parkedRemainingBytes, timeoutTime); - clearParked(); - - } - - pause(); - } - return remainingBytes; - } - - private void clearParked() { -// assert !outBytesLock.isHeldByCurrentThread(); - assert inBytesLock.isHeldByCurrentThread(); - parkedTransactionId = 0; - parkedRemainingBytes = 0; - parkedTransactionTimeStamp = 0; - } - - private void pause() { - - assert !outBytesLock.isHeldByCurrentThread(); - assert inBytesLock.isHeldByCurrentThread(); - - /// don't call inBytesLock.isHeldByCurrentThread() as it not atomic - inBytesLock.unlock(); - inBytesLock.lock(); - } - - - /** - * reads up to the number of byte in {@code requiredNumberOfBytes} - * - * @param requiredNumberOfBytes the number of bytes to read - * @param timeoutTime timeout in milliseconds - * @return bytes read from the TCP/IP socket - * @throws IOException socket failed to read data - */ - @SuppressWarnings("UnusedReturnValue") - private Bytes receiveBytesFromSocket(int requiredNumberOfBytes, long timeoutTime) throws IOException { - - -// assert !outBytesLock.isHeldByCurrentThread(); - assert inBytesLock.isHeldByCurrentThread(); - - inBytes.position(0); - inBytes.limit(requiredNumberOfBytes); - inBytes.buffer().position(0); - inBytes.buffer().limit(requiredNumberOfBytes); - SocketChannel clientChannel0 = clientChannel; - if (clientChannel0 == null) - return inBytes; - - while (inBytes.buffer().remaining() > 0) { - assert requiredNumberOfBytes <= inBytes.capacity(); - - int len = clientChannel0.read(inBytes.buffer()); - - if (len == -1) - throw new IORuntimeException("Disconnection to server"); - - checkTimeout(timeoutTime); - } - - inBytes.position(0); - inBytes.limit(requiredNumberOfBytes); - return inBytes; - } - - - long largestEntrySoFar = 0; - private long limitOfLast = 0; - - private void writeBytesToSocket(long timeoutTime) throws IOException { - - assert outBytesLock.isHeldByCurrentThread(); - assert !inBytesLock.isHeldByCurrentThread(); - - // if we have other threads waiting to send and the buffer is not full, let the other threads - // write to the buffer - if (outBytesLock.hasQueuedThreads() && - outBytes.position() + largestEntrySoFar <= tcpBufferSize) { - return; - } - - outBuffer.limit((int) outBytes.position()); - outBuffer.position(0); - - int sizeOfThisMessage = (int) (outBuffer.limit() - limitOfLast); - if (largestEntrySoFar < sizeOfThisMessage) - largestEntrySoFar = sizeOfThisMessage; - - limitOfLast = outBuffer.limit(); - - - while (outBuffer.remaining() > 0) { - - int len = clientChannel.write(outBuffer); - if (len == -1) - throw new IORuntimeException("Disconnection to server"); - - - // if we have queued threads then we don't have to write all the bytes as the other - // threads will write the remains bytes. - if (outBuffer.remaining() > 0 && outBytesLock.hasQueuedThreads() && - outBuffer.remaining() + largestEntrySoFar <= tcpBufferSize) { - - LOG.debug("continuing - without all the data being written to the buffer as " + - "it will be written by the next thread"); - outBuffer.compact(); - outBytes.limit(outBuffer.limit()); - outBytes.position(outBuffer.position()); - return; - } - - checkTimeout(timeoutTime); - - } - - outBuffer.clear(); - outBytes.clear(); - - } - - - private void writeSizeAndTransactionIdAt(long locationOfSize, final long transactionId) { - - assert outBytesLock.isHeldByCurrentThread(); - assert !inBytesLock.isHeldByCurrentThread(); - - assert outBytes.readByte(locationOfSize - 1) >= LONG_SIZE.ordinal(); - - - final long size = outBytes.position() - locationOfSize; - final long pos = outBytes.position(); - outBytes.position(locationOfSize); - try { - outBuffer.position((int) locationOfSize); - - } catch (IllegalArgumentException e) { - LOG.error("locationOfSize=" + locationOfSize + ", limit=" + outBuffer.limit(), e); - } - int size0 = (int) size - SIZE_OF_SIZE; - - outBytes.writeInt(size0); - assert transactionId != 0; - outBytes.writeLong(transactionId); - - outBytes.position(pos); - } - - private long markSizeLocation() { - assert outBytesLock.isHeldByCurrentThread(); - assert !inBytesLock.isHeldByCurrentThread(); - - final long position = outBytes.position(); - outBytes.writeInt(0); // skip the size - return position; - } - - private ThreadLocalCopies writeKey(K key) { - return writeKey(key, null); - } - - @SuppressWarnings("SameParameterValue") - private ThreadLocalCopies writeKey(K key, ThreadLocalCopies copies) { - assert outBytesLock.isHeldByCurrentThread(); - assert !inBytesLock.isHeldByCurrentThread(); - return keyWriterWithSize.write(outBytes, key, copies); - } - - @SuppressWarnings("UnusedReturnValue") - private ThreadLocalCopies writeKeyInLoop(K key, Object writer, ThreadLocalCopies copies) { - - assert outBytesLock.isHeldByCurrentThread(); - assert !inBytesLock.isHeldByCurrentThread(); - return keyWriterWithSize.writeInLoop(outBytes, key, writer, copies); - - } - - private ThreadLocalCopies writeValue(V value, ThreadLocalCopies copies) { - assert outBytesLock.isHeldByCurrentThread(); - assert !inBytesLock.isHeldByCurrentThread(); - - long start = outBytes.position(); - - assert outBytes.position() == start; - outBytes.limit(outBytes.capacity()); - return valueWriterWithSize.write(outBytes, value, copies); - - } - - @SuppressWarnings("UnusedReturnValue") - private ThreadLocalCopies writeValueInLoop(V value, Object writer, ThreadLocalCopies copies) { - assert outBytesLock.isHeldByCurrentThread(); - assert !inBytesLock.isHeldByCurrentThread(); - long start = outBytes.position(); - - - assert outBytes.position() == start; - outBytes.limit(outBytes.capacity()); - return valueWriterWithSize.writeInLoop(outBytes, value, writer, copies); - - } - - private V readValue(long transactionId, long startTime, ThreadLocalCopies copies, V usingValue) { - assert !outBytesLock.isHeldByCurrentThread(); - - long timeoutTime = startTime + this.timeoutMs; - - // receive - inBytesLock.lock(); - try { - - if (usingValue != null) - return readValue(copies, blockingFetchReadOnly(timeoutTime, transactionId), usingValue); - else - - return readValue(copies, blockingFetchReadOnly(timeoutTime, transactionId)); - } finally { - inBytesLock.unlock(); - } - } - - @Nullable - private O readObject(long transactionId, long startTime) { - assert !outBytesLock.isHeldByCurrentThread(); - - long timeoutTime = startTime + this.timeoutMs; - - // receive - inBytesLock.lock(); - try { - return (O) blockingFetchReadOnly(timeoutTime, transactionId).readObject(); - } finally { - inBytesLock.unlock(); - } - } - - private boolean readBoolean(long transactionId, long startTime) { - assert !outBytesLock.isHeldByCurrentThread(); - - long timeoutTime = startTime + this.timeoutMs; - - // receive - inBytesLock.lock(); - try { - return blockingFetchReadOnly(timeoutTime, transactionId).readBoolean(); - } finally { - inBytesLock.unlock(); - } - } - - - private int readInt(long transactionId, long startTime) { - assert !outBytesLock.isHeldByCurrentThread(); - assert inBytesLock.isHeldByCurrentThread(); - long timeoutTime = startTime + this.timeoutMs; - - // receive - inBytesLock.lock(); - try { - return blockingFetchReadOnly(timeoutTime, transactionId).readInt(); - } finally { - inBytesLock.unlock(); - } - } - - private long send(@NotNull final EventId eventId, final long startTime) { - - assert outBytesLock.isHeldByCurrentThread(); - assert !inBytesLock.isHeldByCurrentThread(); - - assert eventId.ordinal() != 0; - // send - outBytesLock.lock(); - try { - final long sizeLocation = writeEventAnSkip(eventId); - assert sizeLocation == 1; - return send(sizeLocation, startTime); - } finally { - outBytesLock.unlock(); - } - } - - private V readValue(ThreadLocalCopies copies, Bytes in) { - assert !outBytesLock.isHeldByCurrentThread(); - assert inBytesLock.isHeldByCurrentThread(); - return valueReaderWithSize.readNullable(in, copies, null); - } - - private V readValue(ThreadLocalCopies copies, Bytes in, V using) { - assert !outBytesLock.isHeldByCurrentThread(); - assert inBytesLock.isHeldByCurrentThread(); - return valueReaderWithSize.readNullable(in, copies, using); - } - - @SuppressWarnings("SameParameterValue") - private boolean fetchBoolean(@NotNull final EventId eventId, K key, V value) { - final long startTime = System.currentTimeMillis(); - ThreadLocalCopies copies; - - long transactionId; - - outBytesLock.lock(); - try { - final long sizeLocation = writeEventAnSkip(eventId); - - copies = writeKey(key); - writeValue(value, copies); - - transactionId = send(sizeLocation, startTime); - } finally { - outBytesLock.unlock(); - } - - - return readBoolean(transactionId, startTime); - - } - - @SuppressWarnings("SameParameterValue") - private boolean fetchBoolean(@NotNull final EventId eventId, K key, V value1, V value2) { - final long startTime = System.currentTimeMillis(); - ThreadLocalCopies copies; - - long transactionId; - - outBytesLock.lock(); - try { - final long sizeLocation = writeEventAnSkip(eventId); - - - copies = writeKey(key); - copies = writeValue(value1, copies); - writeValue(value2, copies); - transactionId = send(sizeLocation, startTime); - } finally { - outBytesLock.unlock(); - } - - - return readBoolean(transactionId, startTime); - - } - - @SuppressWarnings("SameParameterValue") - private boolean fetchBooleanV(@NotNull final EventId eventId, V value) { - final long startTime = System.currentTimeMillis(); - - long transactionId; - - outBytesLock.lock(); - try { - final long sizeLocation = writeEventAnSkip(eventId); - writeValue(value, null); - transactionId = send(sizeLocation, startTime); - } finally { - outBytesLock.unlock(); - } - - return readBoolean(transactionId, startTime); - } - - - @SuppressWarnings("SameParameterValue") - private boolean fetchBooleanK(@NotNull final EventId eventId, K key) { - final long startTime = System.currentTimeMillis(); - - long transactionId; - - outBytesLock.lock(); - try { - final long sizeLocation = writeEventAnSkip(eventId); - writeKey(key, null); - transactionId = send(sizeLocation, startTime); - } finally { - outBytesLock.unlock(); - } - - return readBoolean(transactionId, startTime); - } - - - @SuppressWarnings("SameParameterValue") - private long fetchLong(@NotNull final EventId eventId) { - final long startTime = System.currentTimeMillis(); - - long transactionId; - - outBytesLock.lock(); - try { - final long sizeLocation = writeEventAnSkip(eventId); - transactionId = send(sizeLocation, startTime); - } finally { - outBytesLock.unlock(); - } - - return readLong(transactionId, startTime); - } - - @SuppressWarnings("SameParameterValue") - private boolean fetchBoolean(@NotNull final EventId eventId) { - final long startTime = System.currentTimeMillis(); - - long transactionId; - - outBytesLock.lock(); - try { - final long sizeLocation = writeEventAnSkip(eventId); - transactionId = send(sizeLocation, startTime); - } finally { - outBytesLock.unlock(); - } - - return readBoolean(transactionId, startTime); - } - - @SuppressWarnings("SameParameterValue") - private void fetchVoid(@NotNull final EventId eventId) { - - final long startTime = System.currentTimeMillis(); - - long transactionId; - - outBytesLock.lock(); - try { - final long sizeLocation = writeEventAnSkip(eventId); - transactionId = send(sizeLocation, startTime); - } finally { - outBytesLock.unlock(); - } - - readVoid(transactionId, startTime); - } - - private void readVoid(long transactionId, long startTime) { - long timeoutTime = startTime + this.timeoutMs; - - // receive - inBytesLock.lock(); - try { - blockingFetchReadOnly(timeoutTime, transactionId); - } finally { - inBytesLock.unlock(); - } - } - - - @SuppressWarnings("SameParameterValue") - @Nullable - private O fetchObject(final Class tClass, @NotNull final EventId eventId) { - final long startTime = System.currentTimeMillis(); - long transactionId; - - outBytesLock.lock(); - try { - transactionId = send(eventId, startTime); - } finally { - outBytesLock.unlock(); - } - - long timeoutTime = startTime + this.timeoutMs; - - // receive - inBytesLock.lock(); - try { - return blockingFetchReadOnly(timeoutTime, transactionId).readObject(tClass); - } finally { - inBytesLock.unlock(); - } - } - - - @SuppressWarnings("SameParameterValue") - private int fetchInt(@NotNull final EventId eventId) { - final long startTime = System.currentTimeMillis(); - - long transactionId; - - outBytesLock.lock(); - try { - final long sizeLocation = writeEventAnSkip(eventId); - transactionId = send(sizeLocation, startTime); - } finally { - outBytesLock.unlock(); - } - - return readInt(transactionId, startTime); - } - - - @Nullable - private R fetchObject(Class rClass, @NotNull final EventId eventId, K key, V value) { - final long startTime = System.currentTimeMillis(); - ThreadLocalCopies copies; - - long transactionId; - - outBytesLock.lock(); - try { - - final long sizeLocation = writeEventAnSkip(eventId); - - copies = writeKey(key); - copies = writeValue(value, copies); - transactionId = send(sizeLocation, startTime); - } finally { - outBytesLock.unlock(); - } - - - if (eventReturnsNull(eventId)) - return null; - - if (rClass == vClass) - return (R) readValue(transactionId, startTime, copies, null); - else - throw new UnsupportedOperationException("class of type class=" + rClass + " is not " + - "supported"); - } - - - @Nullable - private R fetchObject(Class rClass, @NotNull final EventId eventId, K key) { - final long startTime = System.currentTimeMillis(); - ThreadLocalCopies copies; - - long transactionId; - - outBytesLock.lock(); - try { - - final long sizeLocation = writeEventAnSkip(eventId); - - copies = writeKey(key); - transactionId = send(sizeLocation, startTime); - } finally { - outBytesLock.unlock(); - } - - if (eventReturnsNull(eventId)) - return null; - - if (rClass == vClass) - return (R) readValue(transactionId, startTime, copies, null); - else - throw new UnsupportedOperationException("class of type class=" + rClass + " is not " + - "supported"); - } - - - private boolean eventReturnsNull(@NotNull EventId eventId) { - - switch (eventId) { - case PUT_ALL_WITHOUT_ACC: - case PUT_WITHOUT_ACC: - case REMOVE_WITHOUT_ACC: - return true; - default: - return false; - } - - } - - private void writeObject(@NotNull Object function) { - - assert outBytesLock.isHeldByCurrentThread(); - assert !inBytesLock.isHeldByCurrentThread(); - - long start = outBytes.position(); - for (; ; ) { - try { - outBytes.writeObject(function); - return; - } catch (IllegalStateException e) { - Throwable cause = e.getCause(); - - if (cause instanceof IOException && cause.getMessage().contains("Not enough available space")) { - LOG.debug("resizing buffer, name=" + name); - - try { - resizeToMessageOutBuffer(start, e); - } catch (Exception e2) { - throw e; - } - - } else - throw e; - } - } - } - - private void resizeToMessageOutBuffer(long start, @NotNull T e) throws T { - assert outBytesLock.isHeldByCurrentThread(); - assert !inBytesLock.isHeldByCurrentThread(); - String message = e.getMessage(); - if (message.startsWith("java.io.IOException: Not enough available space for writing ")) { - String substring = message.substring("java.io.IOException: Not enough available space for writing ".length(), message.length()); - int i = substring.indexOf(' '); - if (i != -1) { - int size = Integer.parseInt(substring.substring(0, i)); - - long requiresExtra = size - outBytes.remaining(); - resizeBufferOutBuffer((int) (outBytes.capacity() + requiresExtra), start); - } else - throw e; - } else - throw e; - } - - - @Nullable - private R fetchObject(@NotNull final EventId eventId, K key, @NotNull Object object) { - final long startTime = System.currentTimeMillis(); - long transactionId; - - outBytesLock.lock(); - try { - final long sizeLocation = writeEventAnSkip(eventId); - writeKey(key); - writeObject(object); - transactionId = send(sizeLocation, startTime); - } finally { - outBytesLock.unlock(); - } - - if (eventReturnsNull(eventId)) - return null; - - return (R) readObject(transactionId, startTime); - } -} - diff --git a/src/main/java/net/openhft/chronicle/map/TcpReplicator.java b/src/main/java/net/openhft/chronicle/map/TcpReplicator.java index a394a2ebb..ab7901829 100644 --- a/src/main/java/net/openhft/chronicle/map/TcpReplicator.java +++ b/src/main/java/net/openhft/chronicle/map/TcpReplicator.java @@ -16,23 +16,17 @@ package net.openhft.chronicle.map; -import net.openhft.chronicle.hash.function.SerializableFunction; import net.openhft.chronicle.hash.impl.util.BuildVersion; import net.openhft.chronicle.hash.replication.ConnectionListener; import net.openhft.chronicle.hash.replication.RemoteNodeValidator; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; import net.openhft.chronicle.hash.replication.ThrottlingConfig; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.chronicle.hash.serialization.internal.ReaderWithSize; import net.openhft.chronicle.hash.serialization.internal.SerializationBuilder; -import net.openhft.chronicle.map.impl.CompiledReplicatedMapQueryContext; import net.openhft.lang.collection.ATSDirectBitSet; import net.openhft.lang.collection.DirectBitSet; -import net.openhft.lang.io.AbstractBytes; import net.openhft.lang.io.ByteBufferBytes; import net.openhft.lang.io.Bytes; import net.openhft.lang.io.DirectStore; -import net.openhft.lang.threadlocal.ThreadLocalCopies; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -45,15 +39,13 @@ import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.channels.*; -import java.util.*; +import java.util.BitSet; +import java.util.Set; import java.util.concurrent.TimeUnit; import static java.nio.channels.SelectionKey.*; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static net.openhft.chronicle.hash.impl.util.BuildVersion.version; -import static net.openhft.chronicle.map.AbstractChannelReplicator.SIZE_OF_SIZE; -import static net.openhft.chronicle.map.AbstractChannelReplicator.SIZE_OF_TRANSACTION_ID; -import static net.openhft.chronicle.map.StatelessChronicleMap.EventId.HEARTBEAT; import static net.openhft.lang.MemoryUnit.*; interface Work { @@ -75,7 +67,8 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme public static final long TIMESTAMP_FACTOR = 10000; private static final int STATELESS_CLIENT = -127; - private static final byte NOT_SET = (byte) HEARTBEAT.ordinal(); + private static final byte HEARTBEAT = 0; + private static final byte NOT_SET = 0;//(byte) HEARTBEAT.ordinal(); private static final Logger LOG = LoggerFactory.getLogger(TcpReplicator.class.getName()); private static final int BUFFER_SIZE = 0x100000; // 1MB @@ -107,21 +100,6 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme private long selectorTimeout; - StatelessClientParameters statelessClientParameters; - - static class StatelessClientParameters { - public StatelessClientParameters(ReplicatedChronicleMap map, - SerializationBuilder keySerializationBuilder, - SerializationBuilder valueSerializationBuilder) { - this.map = map; - this.keySerializationBuilder = keySerializationBuilder; - this.valueSerializationBuilder = valueSerializationBuilder; - } - - ReplicatedChronicleMap map; - SerializationBuilder keySerializationBuilder; - SerializationBuilder valueSerializationBuilder; - } /** * @throws IOException on an io error. @@ -130,15 +108,12 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme @NotNull final Replica.EntryExternalizable externalizable, @NotNull final TcpTransportAndNetworkConfig replicationConfig, @Nullable final RemoteNodeValidator remoteNodeValidator, - @Nullable final StatelessClientParameters statelessClientParameters, String name, @Nullable final ConnectionListener connectionListener) throws IOException { super("TcpSocketReplicator-" + replica.identifier(), replicationConfig.throttlingConfig()); - this.statelessClientParameters = statelessClientParameters; - final ThrottlingConfig throttlingConfig = replicationConfig.throttlingConfig(); long throttleBucketInterval = throttlingConfig.bucketInterval(MILLISECONDS); @@ -1083,17 +1058,9 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme @Nullable public Work uncompletedWork; private long lastSentTime; - StatelessServerConnector statelessServer; private TcpSocketChannelEntryWriter() { entryCallback = new EntryCallback(externalizable, replicationConfig.tcpBufferSize()); - - if (statelessClientParameters != null) - statelessServer = new StatelessServerConnector( - statelessClientParameters.map, entryCallback, - replicationConfig.tcpBufferSize(), - statelessClientParameters.keySerializationBuilder, - statelessClientParameters.valueSerializationBuilder); } public boolean isWorkIncomplete() { @@ -1251,7 +1218,7 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme */ private void writeHeartbeatToBuffer() { // denotes the state - 0 for a heartbeat - in().writeByte(HEARTBEAT.ordinal()); + in().writeByte(HEARTBEAT); // denotes the size in bytes in().writeInt(0); @@ -1354,7 +1321,7 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme if (out.remaining() < SIZE_OF_SIZE + 1) return; - // state is used for both heartbeat and stateless + // state is used for heartbeat state = out.readByte(); sizeInBytes = out.readInt(); @@ -1368,10 +1335,7 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme attached.entryReader.resizeBuffer(requiredSize + HEADROOM); } - // this is the : - // -- heartbeat if its 0 - // -- stateful update if its 1 - // -- the id of the stateful event + // means this is heartbeat if (state == NOT_SET) continue; } @@ -1385,43 +1349,7 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme final long limit = out.limit(); out.limit(nextEntryPos); - boolean isStatelessClient = (state != 1); - - if (isStatelessClient) { - - final StatelessServerConnector statelessServerConnector = attached - .entryWriter.statelessServer; - - if (statelessServerConnector == null) { - LOG.error("", new IllegalArgumentException("received an event " + - "from a stateless map, stateless maps are not " + - "currently supported when using Chronicle Channels")); - } else { - - final Work futureWork = - statelessServerConnector.processStatelessEvent(state, - attached.entryWriter, attached.entryReader.out); - - // turn the OP_WRITE on - key.interestOps(key.interestOps() | OP_WRITE); - - // in some cases it may not be possible to send out all the data before - // we fill out the write buffer, so this data will be send when - // the buffer is no longer full, and as such is treated as future work - if (futureWork != null) { - try { // we will complete what we can for now - boolean isComplete = futureWork.doWork(attached.entryWriter - .in()); - if (!isComplete) - attached.entryWriter.uncompletedWork = futureWork; - } catch (Exception e) { - LOG.error("", e); - } - } - } - } else { - externalizable.readExternalEntry(out); - } + externalizable.readExternalEntry(out); out.limit(limit); @@ -1491,789 +1419,3 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme } } -/** - * @author Rob Austin. - */ -class StatelessServerConnector { - - private static final Logger LOG = LoggerFactory.getLogger(StatelessServerConnector.class - .getName()); - public static final StatelessChronicleMap.EventId[] VALUES - = StatelessChronicleMap.EventId.values(); - public static final int SIZE_OF_IS_EXCEPTION = 1; - public static final int HEADER_SIZE = SIZE_OF_SIZE + SIZE_OF_IS_EXCEPTION + - SIZE_OF_TRANSACTION_ID; - - @NotNull - private final ReaderWithSize keyReaderWithSize; - - @NotNull - private final WriterWithSize keyWriterWithSize; - - @NotNull - private final ReaderWithSize valueReaderWithSize; - - @NotNull - private final WriterWithSize valueWriterWithSize; - - @NotNull - private final ReplicatedChronicleMap map; - private final SerializationBuilder keySerializationBuilder; - private final SerializationBuilder valueSerializationBuilder; - private final int tcpBufferSize; - - - StatelessServerConnector( - @NotNull ReplicatedChronicleMap map, - @NotNull final BufferResizer bufferResizer, int tcpBufferSize, - final SerializationBuilder keySerializationBuilder, - final SerializationBuilder valueSerializationBuilder) { - this.tcpBufferSize = tcpBufferSize; - - this.keySerializationBuilder = keySerializationBuilder; - this.valueSerializationBuilder = valueSerializationBuilder; - keyReaderWithSize = new ReaderWithSize<>(keySerializationBuilder); - keyWriterWithSize = new WriterWithSize<>(keySerializationBuilder, bufferResizer); - valueReaderWithSize = new ReaderWithSize<>(valueSerializationBuilder); - valueWriterWithSize = new WriterWithSize<>(valueSerializationBuilder, bufferResizer); - this.map = map; - } - - @Nullable - Work processStatelessEvent(final byte eventId, - @NotNull final TcpReplicator.TcpSocketChannelEntryWriter writer, - @NotNull final ByteBufferBytes reader) { - final StatelessChronicleMap.EventId event = VALUES[eventId]; - - long transactionId = reader.readLong(); - - // the time stamp and the transaction are usually the same, or out by the shift - long timestamp = transactionId / TcpReplicator.TIMESTAMP_FACTOR; - byte identifier = reader.readByte(); - int headerSize = reader.readInt(); - reader.skip(headerSize); - - - // these methods don't return a result to the client or don't return a result to the - // client immediately - switch (event) { - case KEY_SET: - return keySet(reader, writer, transactionId); - - case VALUES: - return values(reader, writer, transactionId); - - case ENTRY_SET: - return entrySet(reader, writer, transactionId); - - case PUT_WITHOUT_ACC: - return put(reader, timestamp, identifier); - - case PUT_ALL_WITHOUT_ACC: - return putAll(reader, timestamp, identifier); - - case REMOVE_WITHOUT_ACC: - return remove(reader, timestamp, identifier); - } - - final long sizeLocation = reflectTransactionId(writer.in(), transactionId); - - - // these methods return a result - - switch (event) { - case LONG_SIZE: - return longSize(writer, sizeLocation); - - case IS_EMPTY: - return isEmpty(writer, sizeLocation); - - case CONTAINS_KEY: - return containsKey(reader, writer, sizeLocation); - - case CONTAINS_VALUE: - return containsValue(reader, writer, sizeLocation); - - case GET: - return get(reader, writer, sizeLocation, timestamp); - - case PUT: - return put(reader, writer, sizeLocation, timestamp, identifier); - - case REMOVE: - return remove(reader, writer, sizeLocation, timestamp, identifier); - - case CLEAR: - return clear(writer, sizeLocation, timestamp, identifier); - - case REPLACE: - return replace(reader, writer, sizeLocation, timestamp, identifier); - - case REPLACE_WITH_OLD_AND_NEW_VALUE: - return replaceWithOldAndNew(reader, writer, - sizeLocation, timestamp, identifier); - - case PUT_IF_ABSENT: - return putIfAbsent(reader, writer, sizeLocation, timestamp, identifier); - - case REMOVE_WITH_VALUE: - return removeWithValue(reader, writer, sizeLocation, timestamp, identifier); - - case TO_STRING: - return toString(writer, sizeLocation); - - case APPLICATION_VERSION: - return applicationVersion(writer, sizeLocation); - - case PERSISTED_DATA_VERSION: - return persistedDataVersion(writer, sizeLocation); - - case PUT_ALL: - return putAll(reader, writer, sizeLocation, timestamp, identifier); - - case HASH_CODE: - return hashCode(writer, sizeLocation); - - case MAP_FOR_KEY: - return mapForKey(reader, writer, sizeLocation); - - case PUT_MAPPED: - return putMapped(reader, writer, sizeLocation); - - case KEY_BUILDER: - return writeBuilder(writer, sizeLocation, keySerializationBuilder); - - case VALUE_BUILDER: - return writeBuilder(writer, sizeLocation, valueSerializationBuilder); - - default: - throw new IllegalStateException("unsupported event=" + event); - } - } - - private void writeObject(TcpReplicator.TcpSocketChannelEntryWriter writer, Object o) { - for (; ; ) { - long position = writer.in().position(); - - try { - writer.in().writeObject(o); - return; - } catch (IllegalStateException e) { - if (e.getMessage().contains("Not enough available space")) { - writer.resizeToMessage(e); - writer.in().position(position); - } else - throw e; - } - } - } - - private Work writeBuilder(TcpReplicator.TcpSocketChannelEntryWriter writer, - long sizeLocation, SerializationBuilder builder) { - - try { - writeObject(writer, builder); - } catch (Exception e) { - LOG.info("", e); - - return sendException(writer, sizeLocation, e); - } - - writeSizeAndFlags(sizeLocation, false, writer.in()); - return null; - } - - - @Nullable - public Work mapForKey(@NotNull ByteBufferBytes reader, - @NotNull TcpReplicator.TcpSocketChannelEntryWriter writer, - long sizeLocation) { - final K key = keyReaderWithSize.read(reader, null, null); - final SerializableFunction function = (SerializableFunction) reader.readObject(); - try { - Object result = map.getMapped(key, function); - writeObject(writer, result); - } catch (Throwable e) { - LOG.info("", e); - return sendException(writer, sizeLocation, e); - } - - writeSizeAndFlags(sizeLocation, false, writer.in()); - return null; - } - - @Nullable - public Work putMapped(@NotNull ByteBufferBytes reader, - @NotNull TcpReplicator.TcpSocketChannelEntryWriter writer, - long sizeLocation) { - final K key = keyReaderWithSize.read(reader, null, null); - final UnaryOperator unaryOperator = (UnaryOperator) reader.readObject(); - try { - Object result = map.putMapped(key, unaryOperator); - writeObject(writer, result); - } catch (Throwable e) { - LOG.info("", e); - return sendException(writer, sizeLocation, e); - } - - writeSizeAndFlags(sizeLocation, false, writer.in()); - return null; - } - - private CompiledReplicatedMapQueryContext query(Bytes reader) { - CompiledReplicatedMapQueryContext q = map.mapContext(); - q.initInputBytes(reader); - q.initInputKey(q.inputKeyBytesValue()); - return q; - } - - @Nullable - private Work removeWithValue(Bytes reader, - @NotNull TcpReplicator.TcpSocketChannelEntryWriter writer, - final long sizeLocation, long timestamp, byte id) { - try { - writer.ensureBufferSize(1L); - try (CompiledReplicatedMapQueryContext q = query(reader)) { - writer.in().writeBoolean(map.methods.remove(q, q.inputFirstValueBytesValue())); - } - } catch (Throwable e) { - return sendException(writer, sizeLocation, e); - } - writeSizeAndFlags(sizeLocation, false, writer.in()); - return null; - } - - @Nullable - private Work replaceWithOldAndNew(Bytes reader, - @NotNull TcpReplicator.TcpSocketChannelEntryWriter writer, - final long sizeLocation, long timestamp, byte id) { - try { - writer.ensureBufferSize(1L); - try (CompiledReplicatedMapQueryContext q = query(reader)) { - writer.in().writeBoolean(map.methods.replace(q, q.inputFirstValueBytesValue(), - q.inputSecondValueBytesValue())); - } - } catch (Throwable e) { - return sendException(writer, sizeLocation, e); - } - writeSizeAndFlags(sizeLocation, false, writer.in()); - return null; - } - - @Nullable - private Work longSize(@NotNull TcpReplicator.TcpSocketChannelEntryWriter writer, - final long sizeLocation) { - try { - writer.in().writeLong(map.longSize()); - } catch (Throwable e) { - return sendException(writer, sizeLocation, e); - } - writeSizeAndFlags(sizeLocation, false, writer.in()); - return null; - } - - @Nullable - private Work hashCode(@NotNull TcpReplicator.TcpSocketChannelEntryWriter writer, - final long sizeLocation) { - try { - writer.in().writeInt(map.hashCode()); - } catch (Throwable e) { - return sendException(writer, sizeLocation, e); - } - - writeSizeAndFlags(sizeLocation, false, writer.in()); - return null; - } - - @Nullable - private Work toString(@NotNull TcpReplicator.TcpSocketChannelEntryWriter writer, - final long sizeLocation) { - final String str; - - final long remaining = writer.in().remaining(); - try { - str = map.toString(); - } catch (Throwable e) { - return sendException(writer, sizeLocation, e); - } - - assert remaining > 4; - - // this stops the toString overflowing the buffer - final String result = (str.length() < remaining) ? - str : - str.substring(0, (int) (remaining - 4)) + "..."; - - writeObject(writer, result); - writeSizeAndFlags(sizeLocation, false, writer.in()); - return null; - } - - - @Nullable - private Work applicationVersion(@NotNull TcpReplicator.TcpSocketChannelEntryWriter writer, - final long sizeLocation) { - - - final long remaining = writer.in().remaining(); - try { - String result = map.applicationVersion(); - writeObject(writer, result); - } catch (Throwable e) { - return sendException(writer, sizeLocation, e); - } - - assert remaining > 4; - - writeSizeAndFlags(sizeLocation, false, writer.in()); - return null; - } - - - @Nullable - private Work persistedDataVersion(@NotNull TcpReplicator.TcpSocketChannelEntryWriter writer, - final long sizeLocation) { - final long remaining = writer.in().remaining(); - try { - String result = map.persistedDataVersion(); - writeObject(writer, result); - } catch (Throwable e) { - return sendException(writer, sizeLocation, e); - } - - assert remaining > 4; - - writeSizeAndFlags(sizeLocation, false, writer.in()); - return null; - } - - @SuppressWarnings("SameReturnValue") - @Nullable - private Work sendException(@NotNull TcpReplicator.TcpSocketChannelEntryWriter writer, - long sizeLocation, @NotNull Throwable e) { - - LOG.error("cause by remote stateless client call", e); - - // move the position to ignore any bytes written so far - writer.in().position(sizeLocation + HEADER_SIZE); - - writeException(writer, e); - - writeSizeAndFlags(sizeLocation, true, writer.in()); - - return null; - } - - @Nullable - private Work isEmpty(@NotNull TcpReplicator.TcpSocketChannelEntryWriter writer, - final long sizeLocation) { - try { - writer.in().writeBoolean(map.isEmpty()); - } catch (Throwable e) { - return sendException(writer, sizeLocation, e); - } - - writeSizeAndFlags(sizeLocation, false, writer.in()); - return null; - } - - @Nullable - private Work containsKey(Bytes reader, - @NotNull TcpReplicator.TcpSocketChannelEntryWriter writer, - final long sizeLocation) { - try { - writer.ensureBufferSize(1L); - try (CompiledReplicatedMapQueryContext q = query(reader)) { - writer.in().writeBoolean(map.methods.containsKey(q)); - } - } catch (Throwable e) { - return sendException(writer, sizeLocation, e); - } - writeSizeAndFlags(sizeLocation, false, writer.in()); - return null; - } - - @Nullable - private Work containsValue(Bytes reader, - @NotNull TcpReplicator.TcpSocketChannelEntryWriter writer, - final long sizeLocation) { - // todo optimize -- eliminate - final V v = valueReaderWithSize.read(reader, null, null); - - try { - writer.in().writeBoolean(map.containsValue(v)); - } catch (Throwable e) { - return sendException(writer, sizeLocation, e); - } - writeSizeAndFlags(sizeLocation, false, writer.in()); - return null; - } - - @Nullable - private Work get(Bytes reader, - TcpReplicator.TcpSocketChannelEntryWriter writer, - final long sizeLocation, long transactionId) { - //bytesMap.output = writer; - try { - //bytesMap.get(reader); - } catch (Throwable e) { - return sendException(writer, sizeLocation, e); - } finally { - //bytesMap.output = null; - } - writeSizeAndFlags(sizeLocation, false, writer.in()); - return null; - } - - @SuppressWarnings("SameReturnValue") - @Nullable - private Work put(Bytes reader, long timestamp, byte id) { - //bytesMap.put(reader, reader); - return null; - } - - @Nullable - private Work put(Bytes reader, TcpReplicator.TcpSocketChannelEntryWriter writer, - final long sizeLocation, long timestamp, byte id) { - //bytesMap.output = writer; - try { - //bytesMap.put(reader, reader); - } catch (Throwable e) { - return sendException(writer, sizeLocation, e); - } finally { - //bytesMap.output = null; - } - writeSizeAndFlags(sizeLocation, false, writer.in()); - return null; - } - - @SuppressWarnings("SameReturnValue") - @Nullable - private Work remove(Bytes reader, long timestamp, byte id) { -// bytesMap.remove(reader); - return null; - } - - @Nullable - private Work remove(Bytes reader, TcpReplicator.TcpSocketChannelEntryWriter writer, - final long sizeLocation, long timestamp, byte id) { -// bytesMap.output = writer; - try { -// bytesMap.remove(reader); - } catch (Throwable e) { - return sendException(writer, sizeLocation, e); - } finally { -// bytesMap.output = null; - } - writeSizeAndFlags(sizeLocation, false, writer.in()); - return null; - } - - @Nullable - private Work putAll(@NotNull Bytes reader, - @NotNull TcpReplicator.TcpSocketChannelEntryWriter writer, - final long sizeLocation, - long timestamp, byte id) { - try { -// bytesMap.putAll(reader); - } catch (Throwable e) { - return sendException(writer, sizeLocation, e); - } - writeSizeAndFlags(sizeLocation, false, writer.in()); - return null; - } - - @SuppressWarnings("SameReturnValue") - @Nullable - private Work putAll(@NotNull Bytes reader, long timestamp, byte id) { -// bytesMap.putAll(reader); - return null; - } - - @Nullable - private Work clear(@NotNull TcpReplicator.TcpSocketChannelEntryWriter writer, - final long sizeLocation, long timestamp, byte id) { - try { - map.clear(); - } catch (Throwable e) { - return sendException(writer, sizeLocation, e); - } - - writeSizeAndFlags(sizeLocation, false, writer.in()); - return null; - } - - @Nullable - private Work values(@NotNull Bytes reader, - @NotNull TcpReplicator.TcpSocketChannelEntryWriter writer, - final long transactionId) { - - Collection values; - - try { - values = map.values(); - } catch (Throwable e) { - return sendException(reader, writer, e); - } - - final Iterator iterator = values.iterator(); - - // this allows us to write more data than the buffer will allow - return new Work() { - @Override - public boolean doWork(@NotNull Bytes out) { - final long sizeLocation = header(out, transactionId); - - ThreadLocalCopies copies = valueWriterWithSize.getCopies(null); - Object valueWriter = valueWriterWithSize.writerForLoop(copies); - - int count = 0; - while (iterator.hasNext()) { - // we've filled up the buffer, so lets give another channel a chance to send - // some data, we don't know the max key size, we will use the entrySize instead - if (out.position() > tcpBufferSize) { - writeHeader(out, sizeLocation, count, true); - return false; - } - - count++; - - valueWriterWithSize.writeInLoop(out, iterator.next(), valueWriter, copies); - } - - writeHeader(out, sizeLocation, count, false); - return true; - } - }; - } - - @Nullable - private Work keySet(@NotNull Bytes reader, - @NotNull final TcpReplicator.TcpSocketChannelEntryWriter writer, - final long transactionId) { - - Set ks; - - try { - ks = map.keySet(); - } catch (Throwable e) { - return sendException(reader, writer, e); - } - - final Iterator iterator = ks.iterator(); - - // this allows us to write more data than the buffer will allow - return new Work() { - @Override - public boolean doWork(@NotNull Bytes out) { - final long sizeLocation = header(out, transactionId); - - ThreadLocalCopies copies = keyWriterWithSize.getCopies(null); - Object keyWriter = keyWriterWithSize.writerForLoop(copies); - - int count = 0; - while (iterator.hasNext()) { - // we've filled up the buffer, so lets give another channel a chance to send - // some data, we don't know the max key size, we will use the entrySize instead - if (out.position() > tcpBufferSize) { - writeHeader(out, sizeLocation, count, true); - return false; - } - - count++; - K key = iterator.next(); - keyWriterWithSize.writeInLoop(out, key, keyWriter, copies); - } - - writeHeader(out, sizeLocation, count, false); - return true; - } - }; - } - - @Nullable - private Work entrySet(@NotNull final Bytes reader, - @NotNull TcpReplicator.TcpSocketChannelEntryWriter writer, - final long transactionId) { - - final Set> entries; - - try { - entries = map.entrySet(); - } catch (Throwable e) { - return sendException(reader, writer, e); - } - - final Iterator> iterator = entries.iterator(); - - // this allows us to write more data than the buffer will allow - return new Work() { - @Override - public boolean doWork(@NotNull Bytes out) { - if (out.position() > tcpBufferSize) - return false; - - final long sizeLocation = header(out, transactionId); - - ThreadLocalCopies copies = keyWriterWithSize.getCopies(null); - Object keyWriter = keyWriterWithSize.writerForLoop(copies); - copies = valueWriterWithSize.getCopies(copies); - Object valueWriter = valueWriterWithSize.writerForLoop(copies); - - int count = 0; - while (iterator.hasNext()) { - // we've filled up the buffer, so lets give another channel a chance to send - // some data, we don't know the max key size, we will use the entrySize instead - if (out.position() > tcpBufferSize) { - writeHeader(out, sizeLocation, count, true); - return false; - } - - count++; - final Map.Entry next = iterator.next(); - keyWriterWithSize.writeInLoop(out, next.getKey(), keyWriter, copies); - valueWriterWithSize.writeInLoop(out, next.getValue(), valueWriter, copies); - } - - writeHeader(out, sizeLocation, count, false); - return true; - } - }; - } - - @Nullable - private Work putIfAbsent(Bytes reader, TcpReplicator.TcpSocketChannelEntryWriter writer, - final long sizeLocation, long timestamp, byte id) { -// bytesMap.output = writer; - try { -// bytesMap.putIfAbsent(reader, reader); - } catch (Throwable e) { - return sendException(writer, sizeLocation, e); - } finally { -// bytesMap.output = null; - } - writeSizeAndFlags(sizeLocation, false, writer.in()); - return null; - } - - @Nullable - private Work replace(Bytes reader, TcpReplicator.TcpSocketChannelEntryWriter writer, - final long sizeLocation, long timestamp, byte id) { -// bytesMap.output = writer; - try { -// bytesMap.replace(reader, reader); - } catch (Throwable e) { - return sendException(writer, sizeLocation, e); - } finally { -// bytesMap.output = null; - } - writeSizeAndFlags(sizeLocation, false, writer.in()); - return null; - } - - private long reflectTransactionId(@NotNull Bytes writer, final long transactionId) { - final long sizeLocation = writer.position(); - writer.skip(SIZE_OF_SIZE); - assert transactionId != 0; - writer.writeLong(transactionId); - writer.writeBoolean(false); // isException - return sizeLocation; - } - - private void writeSizeAndFlags(long locationOfSize, boolean isException, @NotNull Bytes out) { - final long size = out.position() - locationOfSize; - - out.writeInt(locationOfSize, (int) size); // size - - // write isException - out.writeBoolean(locationOfSize + SIZE_OF_SIZE + SIZE_OF_TRANSACTION_ID, isException); - - long pos = out.position(); - long limit = out.limit(); - - // System.out.println("Sending with size=" + size); - - if (LOG.isDebugEnabled()) { - out.position(locationOfSize); - out.limit(pos); - LOG.info("Sending to the stateless client, bytes=" + AbstractBytes.toHex(out) + "," + - "len=" + out.remaining()); - out.limit(limit); - out.position(pos); - } - - - } - - private void writeException(@NotNull TcpReplicator.TcpSocketChannelEntryWriter out, - Throwable e) { - writeObject(out, e); - } - - @NotNull - private Map readEntries(@NotNull Bytes reader) { - final long numberOfEntries = reader.readStopBit(); - final Map result = new HashMap(); - - ThreadLocalCopies copies = keyReaderWithSize.getCopies(null); - BytesReader keyReader = keyReaderWithSize.readerForLoop(copies); - copies = valueReaderWithSize.getCopies(copies); - BytesReader valueReader = valueReaderWithSize.readerForLoop(copies); - - for (long i = 0; i < numberOfEntries; i++) { - K key = keyReaderWithSize.readInLoop(reader, keyReader); - V value = valueReaderWithSize.readInLoop(reader, valueReader); - result.put(key, value); - } - return result; - } - - @Nullable - private Work sendException(@NotNull Bytes reader, - @NotNull TcpReplicator.TcpSocketChannelEntryWriter writer, - @NotNull Throwable e) { - final long sizeLocation = reflectTransactionId(writer.in(), reader.readLong()); - return sendException(writer, sizeLocation, e); - } - - private long header(@NotNull Bytes writer, final long transactionId) { - final long sizeLocation = writer.position(); - - writer.skip(SIZE_OF_SIZE); - writer.writeLong(transactionId); - - // exception - writer.skip(1); - - // hasAnotherChunk - writer.skip(1); - - // count - writer.skip(4); - return sizeLocation; - } - - private void writeHeader(@NotNull Bytes writer, long sizeLocation, int count, - final boolean hasAnotherChunk) { - final long end = writer.position(); - final int size = (int) (end - sizeLocation); - writer.position(sizeLocation); - - // size in bytes - writer.writeInt(size); - - //transaction id; - writer.skip(8); - - // is exception - writer.writeBoolean(false); - - writer.writeBoolean(hasAnotherChunk); - - // count - writer.writeInt(count); - writer.position(end); - } - -} - diff --git a/src/main/java/net/openhft/chronicle/set/ChronicleSetStatelessClientBuilder.java b/src/main/java/net/openhft/chronicle/set/ChronicleSetStatelessClientBuilder.java deleted file mode 100644 index 37acefbfe..000000000 --- a/src/main/java/net/openhft/chronicle/set/ChronicleSetStatelessClientBuilder.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2015 higherfrequencytrading.com - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package net.openhft.chronicle.set; - -import net.openhft.chronicle.hash.ChronicleHashStatelessClientBuilder; -import net.openhft.chronicle.hash.serialization.internal.DummyValue; -import net.openhft.chronicle.map.ChronicleMapBuilder; -import net.openhft.chronicle.map.ChronicleMapStatelessClientBuilder; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.concurrent.TimeUnit; - -public final class ChronicleSetStatelessClientBuilder implements - ChronicleHashStatelessClientBuilder< - ChronicleSetStatelessClientBuilder, ChronicleSet> { - - public static ChronicleSetStatelessClientBuilder of(InetSocketAddress serverAddress) { - return new ChronicleSetStatelessClientBuilder<>(serverAddress); - } - - private final ChronicleMapStatelessClientBuilder mapClientBuilder; - - ChronicleSetStatelessClientBuilder(InetSocketAddress serverAddress) { - Class eClass = null; - this.mapClientBuilder = ChronicleMapBuilder.of(eClass, DummyValue.class, serverAddress); - } - - @Override - public ChronicleSetStatelessClientBuilder timeout(long timeout, TimeUnit units) { - mapClientBuilder.timeout(timeout, units); - return this; - } - - @Override - public ChronicleSetStatelessClientBuilder name(String name) { - mapClientBuilder.name(name); - return this; - } - - @Override - public ChronicleSetStatelessClientBuilder tcpBufferSize(int tcpBufferSize) { - mapClientBuilder.tcpBufferSize(tcpBufferSize); - return this; - } - - @Override - public ChronicleSet create() throws IOException { - return new SetFromMap<>(mapClientBuilder.create()); - } -} diff --git a/src/main/java/net/openhft/chronicle/set/SetFromMap.java b/src/main/java/net/openhft/chronicle/set/SetFromMap.java index 45533bbf0..dd66104e2 100644 --- a/src/main/java/net/openhft/chronicle/set/SetFromMap.java +++ b/src/main/java/net/openhft/chronicle/set/SetFromMap.java @@ -92,8 +92,6 @@ class SetFromMap extends AbstractSet return o == this || s.equals(o); } - // TODO optimize in case of stateless clients -- because bulk ops are optimized on maps - // but on key set they delegate to individual element queries => individual remote calls public boolean containsAll(Collection c) { return s.containsAll(c); } diff --git a/src/main/java/net/openhft/xstream/converters/StatelessChronicleMapConverter.java b/src/main/java/net/openhft/xstream/converters/StatelessChronicleMapConverter.java deleted file mode 100644 index c7c11bf5a..000000000 --- a/src/main/java/net/openhft/xstream/converters/StatelessChronicleMapConverter.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2015 higherfrequencytrading.com - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ -package net.openhft.xstream.converters; - -import com.thoughtworks.xstream.converters.ConversionException; -import com.thoughtworks.xstream.converters.MarshallingContext; -import com.thoughtworks.xstream.io.HierarchicalStreamWriter; -import net.openhft.chronicle.map.MapEntryCallback; -import net.openhft.lang.model.constraints.NotNull; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Map; -import java.util.concurrent.CountDownLatch; - -/** - * @author Rob Austin. - */ -public class StatelessChronicleMapConverter extends AbstractChronicleMapConverter { - - public StatelessChronicleMapConverter(@NotNull Map map) { - super(map); - } - - @Override - public void marshal(Object o, final HierarchicalStreamWriter writer, final MarshallingContext - marshallingContext) { - - final CountDownLatch countDownLatch = new CountDownLatch(1); - - try { - - final Method entrySize = o.getClass() - .getDeclaredMethod("entrySet", MapEntryCallback.class); - entrySize.setAccessible(true); - entrySize.invoke(o, - - new MapEntryCallback() { - - @Override - public void onEntry(Object key, Object value) { - writer.startNode("entry"); - { - writer.startNode(key.getClass().getName()); - marshallingContext.convertAnother(key); - writer.endNode(); - - writer.startNode(value.getClass().getName()); - marshallingContext.convertAnother(value); - writer.endNode(); - } - writer.endNode(); - } - - @Override - public void onFinished() { - countDownLatch.countDown(); - } - }); - } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { - throw new ConversionException("", e); - } - - - } - - -} - diff --git a/src/test/java/net/openhft/chronicle/map/CHMUseCasesTest.java b/src/test/java/net/openhft/chronicle/map/CHMUseCasesTest.java index 4f08861c1..d461a728a 100644 --- a/src/test/java/net/openhft/chronicle/map/CHMUseCasesTest.java +++ b/src/test/java/net/openhft/chronicle/map/CHMUseCasesTest.java @@ -46,7 +46,6 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import static java.util.Arrays.asList; -import static net.openhft.chronicle.map.StatelessClientTest.localClient; import static net.openhft.chronicle.map.fromdocs.OpenJDKAndHashMapExamplesTest.parseYYYYMMDD; import static org.junit.Assert.*; @@ -57,7 +56,7 @@ import static org.junit.Assert.*; public class CHMUseCasesTest { - enum TypeOfMap {STATELESS, SIMPLE, SIMPLE_PERSISTED, REPLICATED} + enum TypeOfMap {SIMPLE, SIMPLE_PERSISTED, REPLICATED} private final TypeOfMap typeOfMap; @@ -96,12 +95,6 @@ public class CHMUseCasesTest { TypeOfMap.REPLICATED }, - // it pointless to run these test as the Function and UnaryOperator are not - // serializable as inner classes adn the getUsingLock is not supported by the - // stateless client -// { -// TypeOfMap.STATELESS -// }, { TypeOfMap.SIMPLE_PERSISTED } @@ -312,34 +305,6 @@ public class CHMUseCasesTest { } - - case STATELESS: { - { - final TcpTransportAndNetworkConfig tcpConfig1 = TcpTransportAndNetworkConfig - .of(8086) - .heartBeatInterval(1, TimeUnit.SECONDS) - .tcpBufferSize(1024 * 64); - - - map2 = builder - .replication(SingleChronicleHashReplication.builder() - .tcpTransportAndNetwork(tcpConfig1).name("server") - .createWithId((byte) 1)) - .instance() - .name("server") - .create(); - closeables.add(map2); - - } - { - map1 = localClient(8086); - - closeables.add(map1); - return map1; - - } - } - default: throw new IllegalStateException(); } @@ -468,9 +433,6 @@ public class CHMUseCasesTest { @Test public void bondExample() throws IOException, InterruptedException { - if (typeOfMap == TypeOfMap.STATELESS) - return; // acquireContext not supported by the STATELESS client - ChronicleMapBuilder builder = ChronicleMapBuilder.of(String.class, BondVOInterface.class) .averageKeySize(10); @@ -665,9 +627,6 @@ public class CHMUseCasesTest { public void testCharSequenceCharSequenceMap() throws ExecutionException, InterruptedException, IOException { - if (typeOfMap == TypeOfMap.STATELESS) - return; // Function supported by the STATELESS client - ChronicleMapBuilder builder = ChronicleMapBuilder .of(CharSequence.class, CharSequence.class); @@ -731,9 +690,6 @@ public class CHMUseCasesTest { @Test public void testAcquireUsingWithCharSequence() throws IOException { - if (typeOfMap == TypeOfMap.STATELESS) - return; // context supported by the STATELESS client - ChronicleMapBuilder builder = ChronicleMapBuilder .of(CharSequence.class, CharSequence.class); @@ -755,9 +711,6 @@ public class CHMUseCasesTest { @Test public void testGetUsingWithIntValueNoValue() throws IOException { - if (typeOfMap == TypeOfMap.STATELESS) - return; // context supported by the STATELESS client - ChronicleMapBuilder builder = ChronicleMapBuilder .of(CharSequence.class, IntValue.class); @@ -775,9 +728,6 @@ public class CHMUseCasesTest { @Test(expected = IllegalArgumentException.class) public void testAcquireUsingImmutableUsing() throws IOException { - if (typeOfMap == TypeOfMap.STATELESS) - throw new IllegalArgumentException(); // acquireContext supported by the STATELESS - ChronicleMapBuilder builder = ChronicleMapBuilder .of(IntValue.class, CharSequence.class); @@ -800,9 +750,6 @@ public class CHMUseCasesTest { @Test public void testAcquireUsingWithIntValueKeyStringBuilderValue() throws IOException { - if (typeOfMap == TypeOfMap.STATELESS) - return; // acquireContext supported by the STATELESS client - ChronicleMapBuilder builder = ChronicleMapBuilder .of(IntValue.class, StringBuilder.class); @@ -826,9 +773,6 @@ public class CHMUseCasesTest { @Test public void testAcquireUsingWithIntValueKey() throws IOException { - if (typeOfMap == TypeOfMap.STATELESS) - return; // context supported by the STATELESS client - ChronicleMapBuilder builder = ChronicleMapBuilder .of(IntValue.class, CharSequence.class); @@ -857,10 +801,6 @@ public class CHMUseCasesTest { @Test public void testAcquireUsingWithByteBufferBytesValue() throws IOException { - - if (typeOfMap == TypeOfMap.STATELESS) - return; - ChronicleMapBuilder builder = ChronicleMapBuilder .of(IntValue.class, CharSequence.class); @@ -889,9 +829,6 @@ public class CHMUseCasesTest { @Test public void testStringValueStringValueMap() throws IOException { - if (typeOfMap == TypeOfMap.STATELESS) - return; // context supported by the STATELESS client - ChronicleMapBuilder builder = ChronicleMapBuilder .of(StringValue.class, StringValue.class); @@ -1028,10 +965,6 @@ public class CHMUseCasesTest { public void testIntegerIntegerMap() throws ExecutionException, InterruptedException, IOException { - - if (typeOfMap == TypeOfMap.STATELESS) - return; // Function supported by the STATELESS client - ChronicleMapBuilder builder = ChronicleMapBuilder .of(Integer.class, Integer.class); @@ -1097,10 +1030,6 @@ public class CHMUseCasesTest { public void testLongLongMap() throws ExecutionException, InterruptedException, IOException { - if (typeOfMap == TypeOfMap.STATELESS) - return; - - ChronicleMapBuilder builder = ChronicleMapBuilder .of(Long.class, Long.class); @@ -1151,10 +1080,6 @@ public class CHMUseCasesTest { public void testDoubleDoubleMap() throws ExecutionException, InterruptedException, IOException { - if (typeOfMap == TypeOfMap.STATELESS) - return; - - ChronicleMapBuilder builder = ChronicleMapBuilder .of(Double.class, Double.class); @@ -1202,10 +1127,6 @@ public class CHMUseCasesTest { public void testByteArrayByteArrayMap() throws ExecutionException, InterruptedException, IOException { - - if (typeOfMap == TypeOfMap.STATELESS) - return; - ChronicleMapBuilder builder = ChronicleMapBuilder .of(byte[].class, byte[].class).averageKeySize(4).averageValueSize(4) .entries(1000); @@ -1289,9 +1210,6 @@ public class CHMUseCasesTest { public void testByteBufferByteBufferMap() throws ExecutionException, InterruptedException, IOException { - if (typeOfMap == TypeOfMap.STATELESS) - return; // context supported by the STATELESS client - ChronicleMapBuilder builder = ChronicleMapBuilder .of(ByteBuffer.class, ByteBuffer.class) .averageKeySize(8) @@ -1412,9 +1330,6 @@ public class CHMUseCasesTest { public void testByteBufferDirectByteBufferMap() throws ExecutionException, InterruptedException, IOException { - if (typeOfMap == TypeOfMap.STATELESS) - return; // not supported by the STATELESS client - ChronicleMapBuilder builder = ChronicleMapBuilder .of(ByteBuffer.class, ByteBuffer.class) .averageKeySize(5).averageValueSize(5) @@ -1466,8 +1381,6 @@ public class CHMUseCasesTest { @Test public void testIntValueIntValueMap() throws IOException { - if (typeOfMap == TypeOfMap.STATELESS) - return; // context supported by the STATELESS client ChronicleMapBuilder builder = ChronicleMapBuilder .of(IntValue.class, IntValue.class); @@ -1598,9 +1511,6 @@ public class CHMUseCasesTest { @Test public void testUnsignedIntValueUnsignedIntValueMap() throws IOException { - if (typeOfMap == TypeOfMap.STATELESS) - return; // context supported by the STATELESS client - ChronicleMapBuilder builder = ChronicleMapBuilder .of(UnsignedIntValue.class, UnsignedIntValue.class); @@ -1709,9 +1619,6 @@ public class CHMUseCasesTest { @Test public void testIntValueShortValueMap() throws IOException { - if (typeOfMap == TypeOfMap.STATELESS) - return; // context supported by the STATELESS client - ChronicleMapBuilder builder = ChronicleMapBuilder .of(IntValue.class, ShortValue.class); @@ -1818,10 +1725,6 @@ public class CHMUseCasesTest { @Test public void testIntValueUnsignedShortValueMap() throws IOException { - - if (typeOfMap == TypeOfMap.STATELESS) - return; - ChronicleMapBuilder builder = ChronicleMapBuilder .of(IntValue.class, UnsignedShortValue.class); @@ -1926,9 +1829,6 @@ public class CHMUseCasesTest { @Test public void testIntValueCharValueMap() throws IOException { - if (typeOfMap == TypeOfMap.STATELESS) - return; // context supported by the STATELESS client - ChronicleMapBuilder builder = ChronicleMapBuilder .of(IntValue.class, CharValue.class); @@ -2028,9 +1928,6 @@ public class CHMUseCasesTest { @Test public void testIntValueUnsignedByteMap() throws IOException { - if (typeOfMap == TypeOfMap.STATELESS) - return; // context supported by the STATELESS client - ChronicleMapBuilder builder = ChronicleMapBuilder .of(IntValue.class, UnsignedByteValue.class); @@ -2137,9 +2034,6 @@ public class CHMUseCasesTest { @Test public void testIntValueBooleanValueMap() throws IOException { - if (typeOfMap == TypeOfMap.STATELESS) - return; // context supported by the STATELESS client - ChronicleMapBuilder builder = ChronicleMapBuilder .of(IntValue.class, BooleanValue.class); @@ -2243,10 +2137,6 @@ public class CHMUseCasesTest { @Test public void testFloatValueFloatValueMap() throws IOException { - - if (typeOfMap == TypeOfMap.STATELESS) - return; // context supported by the STATELESS client - ChronicleMapBuilder builder = ChronicleMapBuilder .of(FloatValue.class, FloatValue.class); @@ -2350,9 +2240,6 @@ public class CHMUseCasesTest { @Test public void testDoubleValueDoubleValueMap() throws IOException { - if (typeOfMap == TypeOfMap.STATELESS) - return; // context supported by the STATELESS client - ChronicleMapBuilder builder = ChronicleMapBuilder .of(DoubleValue.class, DoubleValue.class); @@ -2459,10 +2346,6 @@ public class CHMUseCasesTest { @Test public void testLongValueLongValueMap() throws IOException { - - if (typeOfMap == TypeOfMap.STATELESS) - return; - ChronicleMapBuilder builder = ChronicleMapBuilder .of(LongValue.class, LongValue.class); @@ -2571,9 +2454,6 @@ public class CHMUseCasesTest { @Test public void testListValue() throws IOException { - if (typeOfMap == TypeOfMap.STATELESS) - return; // context supported by the STATELESS client - ChronicleMapBuilder> builder = ChronicleMapBuilder .of(String.class, (Class>) (Class) List.class) .valueMarshaller(ListMarshaller.of(new StringMarshaller(8))); @@ -2620,9 +2500,6 @@ public class CHMUseCasesTest { @Test public void testSetValue() throws IOException { - if (typeOfMap == TypeOfMap.STATELESS) - return; // context supported by the STATELESS client - ChronicleMapBuilder> builder = ChronicleMapBuilder .of(String.class, (Class>) (Class) Set.class) .valueMarshaller(SetMarshaller.of(new StringMarshaller(8))); @@ -2669,9 +2546,6 @@ public class CHMUseCasesTest { @Test public void testMapStringStringValue() throws IOException { - if (typeOfMap == TypeOfMap.STATELESS) - return; // context supported by the STATELESS client - ChronicleMapBuilder> builder = ChronicleMapBuilder .of(String.class, (Class>) (Class) Map.class) .valueMarshaller(MapMarshaller.of(new StringMarshaller(16), new StringMarshaller @@ -2712,10 +2586,6 @@ public class CHMUseCasesTest { @Test public void testMapStringIntegerValue() throws IOException { - - if (typeOfMap == TypeOfMap.STATELESS) - return; // context not supported by the STATELESS client - ChronicleMapBuilder> builder = ChronicleMapBuilder .of(String.class, (Class>) (Class) Map.class) .valueMarshaller(MapMarshaller.of(new StringMarshaller(16), new @@ -2779,9 +2649,6 @@ public class CHMUseCasesTest { @Test public void testGeneratedDataValue() throws IOException { - if (typeOfMap == TypeOfMap.STATELESS) - return; // acquireContext not supported by the STATELESS client - ChronicleMapBuilder builder = ChronicleMapBuilder .of(String.class, IBean.class).averageKeySize(5).entries(1000); try (ChronicleMap map = newInstance(builder)) { diff --git a/src/test/java/net/openhft/chronicle/map/ChannelReplicationTest.java b/src/test/java/net/openhft/chronicle/map/ChannelReplicationTest.java index c6794313c..75a6b1426 100644 --- a/src/test/java/net/openhft/chronicle/map/ChannelReplicationTest.java +++ b/src/test/java/net/openhft/chronicle/map/ChannelReplicationTest.java @@ -23,6 +23,7 @@ import org.junit.*; import java.io.Closeable; import java.io.IOException; import java.net.InetSocketAddress; +import java.util.Map; import java.util.Set; import static java.util.concurrent.TimeUnit.SECONDS; @@ -44,6 +45,40 @@ public class ChannelReplicationTest { private ReplicationHub hubA; private ReplicationHub hubB; + public static void checkThreadsShutdown(Set threads) { + // give them a change to stop if there were killed. + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + Map threadMap = Thread.getAllStackTraces(); + threadMap.keySet().removeAll(threads); + if (!threadMap.isEmpty()) { + System.out.println("### threads still running after the test ###"); + for (Map.Entry entry : threadMap.entrySet()) { + System.out.println(entry.getKey()); + for (StackTraceElement ste : entry.getValue()) { + System.out.println("\t" + ste); + } + } + try { + for (Thread thread : threadMap.keySet()) { + if (thread.isAlive()) { + System.out.println("Waiting for " + thread); + thread.join(1000); + if (thread.isAlive()) { + System.out.println("Forcing " + thread + " to die"); + thread.stop(); + } + } + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + @Before public void setup() throws IOException { { @@ -98,7 +133,7 @@ public class ChannelReplicationTest { @After public void checkThreadsShutdown() { - StatelessClientTest.checkThreadsShutdown(threads); + checkThreadsShutdown(threads); } @Test diff --git a/src/test/java/net/openhft/chronicle/map/ChronicleMapImportExportTest.java b/src/test/java/net/openhft/chronicle/map/ChronicleMapImportExportTest.java index f9af224bb..74253174f 100644 --- a/src/test/java/net/openhft/chronicle/map/ChronicleMapImportExportTest.java +++ b/src/test/java/net/openhft/chronicle/map/ChronicleMapImportExportTest.java @@ -19,11 +19,9 @@ package net.openhft.chronicle.map; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver; import net.openhft.chronicle.core.io.Closeable; -import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; import net.openhft.chronicle.map.fromdocs.BondVOInterface; import net.openhft.lang.values.LongValue; import org.junit.Assert; -import org.junit.Ignore; import org.junit.Test; import java.io.File; @@ -32,7 +30,6 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -import static net.openhft.chronicle.map.StatelessClientTest.localClient; import static org.junit.Assert.assertEquals; /** @@ -221,44 +218,6 @@ public class ChronicleMapImportExportTest { file.deleteOnExit(); } - - @Test - @Ignore - public void testToJsonWithStatelessClient() throws IOException, InterruptedException { - File file = new File(TMP + "/chronicle-map-" + System.nanoTime() + ".json"); - file.deleteOnExit(); - File file2 = new File(TMP + "/chronicle-map-" + System.nanoTime() + "-2.json"); - file.deleteOnExit(); - try (ChronicleMap expected = - ChronicleMapBuilder.of(CharSequence.class, CharSequence.class).create()) { - try (ChronicleMap serverMap = ChronicleMapBuilder - .of(CharSequence.class, CharSequence.class) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(8056)).create()) { - try (ChronicleMap actual = localClient(8056)) { - - expected.put("hello", "world"); - expected.getAll(file); - - actual.putAll(file); - - - Assert.assertEquals(expected, actual); - - actual.getAll(file2); - actual.clear(); - actual.putAll(file2); - - Assert.assertEquals(expected, actual); - - } - } - } - - file.delete(); - file2.delete(); - } - - @Test public void testWithLongValue() throws IOException, InterruptedException { diff --git a/src/test/java/net/openhft/chronicle/map/ChronicleMapTest.java b/src/test/java/net/openhft/chronicle/map/ChronicleMapTest.java index 0d63d3fa2..58b4426da 100755 --- a/src/test/java/net/openhft/chronicle/map/ChronicleMapTest.java +++ b/src/test/java/net/openhft/chronicle/map/ChronicleMapTest.java @@ -20,14 +20,11 @@ import com.google.common.collect.HashBiMap; import com.google.common.primitives.Ints; import net.openhft.chronicle.bytes.BytesStore; import net.openhft.chronicle.hash.Data; -import net.openhft.chronicle.hash.replication.SingleChronicleHashReplication; -import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; import net.openhft.lang.model.DataValueClasses; import net.openhft.lang.model.DataValueGenerator; import net.openhft.lang.values.IntValue; import net.openhft.lang.values.LongValue; import net.openhft.lang.values.LongValue$$Native; -import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; @@ -40,7 +37,6 @@ import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; import static net.openhft.chronicle.map.Alignment.*; -import static net.openhft.chronicle.map.StatelessClientTest.localClient; import static org.junit.Assert.*; @SuppressWarnings({"unchecked", "ResultOfMethodCallIgnored"}) @@ -1814,43 +1810,6 @@ public class ChronicleMapTest { } } - - @Test - @Ignore("TODO investigate, debug") - public void testByteArrayKeySizeBySample() throws IOException { - TcpTransportAndNetworkConfig serverConfig = TcpTransportAndNetworkConfig.of(8877); - - - // this test only appear to fail when we reuse the mapFile - for (int i = 0; i < 2; i++) { - - try (ChronicleMap server = ChronicleMapBuilder.of(byte[].class, byte[][].class) - .replication(SingleChronicleHashReplication.builder() - .tcpTransportAndNetwork(serverConfig) - .name("serverMap") - .createWithId((byte) 1)) - .constantKeySizeBySample(new byte[14]) - .create()) { - - try (ChronicleMap map2 = localClient(8877)) { - - - byte[] key = new byte[14]; - System.arraycopy("A".getBytes(), 0, key, 0, "A".length()); - byte[][] value = {new byte[11], new byte[11]}; - System.arraycopy("A".getBytes(), 0, value[0], 0, "A".length()); - System.arraycopy("A".getBytes(), 0, value[1], 0, "A".length()); - - - map2.put(key, value); - Assert.assertNotNull(map2.get(key)); - } - } - - } - - } - @Test(expected = IllegalArgumentException.class) public void testAcquireUsingLockedWithString() throws IOException { diff --git a/src/test/java/net/openhft/chronicle/map/StatelessClientDuplicateKeyTest.java b/src/test/java/net/openhft/chronicle/map/StatelessClientDuplicateKeyTest.java deleted file mode 100644 index 380a19c6e..000000000 --- a/src/test/java/net/openhft/chronicle/map/StatelessClientDuplicateKeyTest.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2015 higherfrequencytrading.com - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package net.openhft.chronicle.map; - -import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.*; - -import static net.openhft.chronicle.map.ChronicleMapStatelessClientBuilder.*; - -@Ignore -public class StatelessClientDuplicateKeyTest { - - @Test - public void statelessClientDuplicateIntegerKeyTest() - throws IOException, InterruptedException, ExecutionException { - ChronicleMap map = - ChronicleMapBuilder.of(Integer.class, Integer.class) - .replication((byte) 1, TcpTransportAndNetworkConfig.of(8080)) - .create(); - - map.put(42, 1); - - final ChronicleMap client = - createClientOf(new InetSocketAddress("localhost", 8080)); - - ExecutorService runner = new ThreadPoolExecutor(16, 256, 300L, TimeUnit.SECONDS, - new LinkedBlockingDeque()); - - class Run implements Callable { - - @Override - public Integer call() { - return client.get(42); - } - } - Collection items = new ArrayList<>(1000); - for (int i = 0; i < 1000; i++) { - items.add(new Run()); - } - List> futures = runner.invokeAll(items); - for (Future future : futures) { - Assert.assertEquals((Integer) 1, future.get()); - } - } - - @Test - public void statelessClientDuplicateBytesKeyTest() - throws IOException, InterruptedException, ExecutionException, TimeoutException { - ChronicleMap map = - ChronicleMapBuilder.of(byte[].class, byte[].class) - .averageKeySize(10).averageValueSize(10) - .entries(100) - .actualSegments(4) - .replication((byte) 1, TcpTransportAndNetworkConfig.of(8081)) - .create(); - - byte[] _42 = {42}; - map.put(_42, new byte[] {1, 2, 3}); - map.put(new byte[]{1, 2, 3}, _42); - byte[] longKey = "fooBarFooBarFooBarFooBar".getBytes(); - map.put(longKey, "bar".getBytes()); - - final ChronicleMap client = - createClientOf(new InetSocketAddress("localhost", 8081)); - - ExecutorService runner = new ThreadPoolExecutor(16, 256, 300L, TimeUnit.SECONDS, - new LinkedBlockingDeque()); - - class Run implements Callable { - final byte[] key; - - Run(byte[] key) { - this.key = key; - } - - @Override - public byte[] call() { - return client.get(key); - } - } - - List items = new ArrayList<>(1000); - for (int i = 0; i < 1000; i++) { - byte[] bs = i % 3 == 0 ? _42 : (i % 3 == 1 ? new byte[] {(byte) i} : longKey); - items.add(new Run(bs)); - } - - List> futures = runner.invokeAll(items); - for (Future future : futures) { - future.get(1, TimeUnit.MILLISECONDS); - } - } -} diff --git a/src/test/java/net/openhft/chronicle/map/StatelessClientTest.java b/src/test/java/net/openhft/chronicle/map/StatelessClientTest.java deleted file mode 100644 index 8d1248a6e..000000000 --- a/src/test/java/net/openhft/chronicle/map/StatelessClientTest.java +++ /dev/null @@ -1,827 +0,0 @@ -/* - * Copyright (C) 2015 higherfrequencytrading.com - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package net.openhft.chronicle.map; - -import junit.framework.Assert; -import net.openhft.chronicle.hash.function.SerializableFunction; -import net.openhft.chronicle.hash.replication.SingleChronicleHashReplication; -import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; -import net.openhft.lang.io.ByteBufferBytes; -import net.openhft.lang.io.Bytes; -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; - -import static net.openhft.chronicle.map.ChronicleMapStatelessClientBuilder.createClientOf; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Rob Austin. - */ -@Ignore("Stateless clients in this form are deprecated and left not working") -public class StatelessClientTest { - private static final Logger LOG = LoggerFactory.getLogger(StatelessClientTest.class); - - public static final int SIZE = 2500; - static int s_port = 9070; - - enum ToString implements SerializableFunction { - INSTANCE; - - @Override - public String apply(Object obj) { - return obj.toString(); - } - } - - Set threads; - - @Before - public void sampleThreads() { - threads = Thread.getAllStackTraces().keySet(); - } - - @After - public void checkThreadsShutdown() { - checkThreadsShutdown(threads); - } - - public static void checkThreadsShutdown(Set threads) { - // give them a change to stop if there were killed. - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - Map threadMap = Thread.getAllStackTraces(); - threadMap.keySet().removeAll(threads); - if (!threadMap.isEmpty()) { - System.out.println("### threads still running after the test ###"); - for (Map.Entry entry : threadMap.entrySet()) { - System.out.println(entry.getKey()); - for (StackTraceElement ste : entry.getValue()) { - System.out.println("\t" + ste); - } - } - try { - for (Thread thread : threadMap.keySet()) { - if (thread.isAlive()) { - System.out.println("Waiting for " + thread); - thread.join(1000); - if (thread.isAlive()) { - System.out.println("Forcing " + thread + " to die"); - thread.stop(); - } - } - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - @Test(timeout = 10000) - public void testMapForKeyWithEntry() throws IOException, InterruptedException { - int port = s_port++; - try (ChronicleMap serverMap = ChronicleMapBuilder - .of(Integer.class, StringBuilder.class) - .putReturnsNull(true) - .entries(SIZE) - .defaultValue(new StringBuilder()) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(port)) - .create()) { - serverMap.put(10, new StringBuilder("Hello World")); - - try (ChronicleMap statelessMap = - ChronicleMapBuilder - .of(Integer.class, StringBuilder.class, new InetSocketAddress("localhost", port)) - .putReturnsNull(true) - .create()) { - String actual = statelessMap.getMapped(10, ToString.INSTANCE); - - assertEquals("{10=Hello World}", statelessMap.toString()); - assertEquals("Hello World", actual); - } - } - } - - public static ChronicleMap localClient(int port) throws IOException { - return createClientOf(new InetSocketAddress("localhost", port)); - } - - @Test(timeout = 10000) - public void testMapForKeyWhenNoEntry() throws IOException, InterruptedException { - int port = s_port++; - try (ChronicleMap serverMap = ChronicleMapBuilder - .of(Integer.class, StringBuilder.class) - .defaultValue(new StringBuilder()) - .entries(SIZE) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(port)).create()) { - serverMap.put(10, new StringBuilder("Hello World")); - - try (ChronicleMap statelessMap = localClient(port)) { - String actual = statelessMap.getMapped(11, ToString.INSTANCE); - - assertEquals(null, actual); - } - } - } - - - @Test(timeout = 10000) - public void testBufferOverFlowPutAllAndEntrySet() throws IOException, InterruptedException { - int port = s_port++; - try (ChronicleMap serverMap = ChronicleMapBuilder - .of(Integer.class, CharSequence.class) - .entries(SIZE) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(port)) - .create()) { - try (ChronicleMap statelessMap = localClient(port)) { - Map payload = new HashMap(); - - for (int i = 0; i < SIZE; i++) { - payload.put(i, "some value=" + i); - } - - statelessMap.putAll(payload); - assertEquals(SIZE, serverMap.size()); - - Set> entries = statelessMap.entrySet(); - - Map.Entry next = entries.iterator().next(); - assertEquals("some value=" + next.getKey(), next.getValue()); - - assertEquals(SIZE, entries.size()); - } - } - } - - @Test(timeout = 10000) - public void testBufferOverFlowPutAllAndValues() throws IOException, InterruptedException { - int port = s_port++; - - try (ChronicleMap serverMap = ChronicleMapBuilder - .of(Integer.class, CharSequence.class) - .entries(SIZE) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(port)) - .create()) { - try (ChronicleMap statelessMap = localClient(port)) { - Map payload = new HashMap(); - - for (int i = 0; i < SIZE; i++) { - payload.put(i, "some value=" + i); - } - - statelessMap.putAll(payload); - - Collection values = statelessMap.values(); - - assertEquals(values.size(), SIZE); - } - } - } - - - /** - * test that when the map is full and exception is thrown back to the user - * - * @throws IOException - * @throws InterruptedException - */ - @Test(timeout = 10000, expected = IllegalStateException.class) - public void testExceptionFromServer() throws IOException, InterruptedException { - int port = s_port++; - - final int size = 100; - - try (ChronicleMap serverMap = ChronicleMapBuilder - .of(Integer.class, CharSequence.class) - .entries(10) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(port)) - .create()) { - try (ChronicleMap statelessMap = localClient(port)) { - - - for (int i = 0; i < size; i++) { - statelessMap.put(i, "hello"); - } - - assertEquals(statelessMap.size(), size); - - } - } - } - - - - @Test - public void testBufferOverFlowPutAllAndKeySet() throws IOException, InterruptedException { - int port = 10 + s_port++; - - try (ChronicleMap serverMap = ChronicleMapBuilder - .of(Integer.class, CharSequence.class) - .entries(SIZE) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(port)) - .create()) { - - Thread.sleep(100); - try (ChronicleMap statelessMap = localClient(port)) { - Map payload = new HashMap(); - - for (int i = 0; i < SIZE; i++) { - payload.put(i, "some value=" + i); - } - - statelessMap.putAll(payload); - - final Set keys = statelessMap.keySet(); - - assertEquals(keys.size(), payload.size()); - } - } - } - - @Test(timeout = 10000) - public void test() throws IOException, InterruptedException { - int port = s_port++; - - try (ChronicleMap serverMap = ChronicleMapBuilder - .of(Integer.class, CharSequence.class) - .entries(SIZE) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(port)) - .create()) { - serverMap.put(10, "EXAMPLE-10"); - try (ChronicleMap statelessMap = localClient(port)) { - assertEquals("EXAMPLE-10", statelessMap.get(10)); - - int size = statelessMap.size(); - assertEquals(1, size); - } - } - } - - @Test(timeout = 10000) - public void testClientCreatedBeforeServer() throws IOException, InterruptedException { - int port = s_port++; - - try (ChronicleMap serverMap = - ChronicleMapBuilder.of(Integer.class, CharSequence.class) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(port)).create()) { - try (ChronicleMap statelessMap = localClient(port)) { - serverMap.put(10, "EXAMPLE-10"); - - assertEquals("EXAMPLE-10", statelessMap.get(10)); - assertEquals(1, statelessMap.size()); - } - } - } - - @Test(timeout = 10000) - public void testServerPutStringKeyMap() throws IOException, InterruptedException { - - try (ChronicleMap serverMap = ChronicleMapBuilder - .of(String.class, Map.class) - .entries(SIZE) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(8056)) - .create()) { - try (ChronicleMap statelessMap = localClient(8056)) { - serverMap.put("hello", Collections.singletonMap("hello", "world")); - - assertEquals(Collections.singletonMap("hello", "world"), statelessMap.get("hello")); - assertEquals(1, statelessMap.size()); - } - } - } - - - @Test(timeout = 10000) - public void testServerPutClientReplace() throws IOException, InterruptedException { - - try (ChronicleMap serverMap = ChronicleMapBuilder - .of(String.class, String.class) - .entries(SIZE) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(8056)) - .create()) { - try (ChronicleMap statelessMap = localClient(8056)) { - - serverMap.put("hello", "world"); - - assertTrue(statelessMap.replace("hello", "world", "hello")); - - assertEquals("hello", statelessMap.get("hello")); - assertEquals(1, statelessMap.size()); - - - } - } - } - - - @Test(timeout = 10000) - public void testIsEmpty() throws IOException, InterruptedException { - - try (ChronicleMap serverMap = ChronicleMapBuilder - .of(String.class, String.class) - .entries(SIZE) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(8056)) - .create()) { - try (ChronicleMap statelessMap = localClient(8056)) { - - assertTrue(statelessMap.isEmpty()); - assertEquals(0, statelessMap.size()); - - - } - } - } - - @Test(timeout = 10000) - public void testStringKeyMapPutIfAbsentIntoStatelessMap() throws IOException, - InterruptedException { - - final Map data = new HashMap(); - - String value = new String(new char[10]); - for (int i = 0; i < 1000; i++) { - data.put("" + i, value); - } - - try (ChronicleMap serverMap = ChronicleMapBuilder - .of(String.class, Map.class) - .entries(1000) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(8056)) - .create()) { - try (ChronicleMap statelessMap = localClient(8056)) { - statelessMap.putIfAbsent("hello", data); - - assertEquals(data, serverMap.get("hello")); - assertEquals(1, statelessMap.size()); - } - } - } - - @Test(timeout = 10000) - public void testBufferOverFlowPutAll() throws IOException, InterruptedException { - try (ChronicleMap serverMap = ChronicleMapBuilder - .of(Integer.class, CharSequence.class) - .entries(SIZE) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(8056)) - .create()) { - try (ChronicleMap statelessMap = localClient(8056)) { - Map payload = new HashMap(); - - for (int i = 0; i < SIZE; i++) { - payload.put(i, "some value=" + i); - } - - statelessMap.putAll(payload); - - int value = SIZE - 10; - - assertEquals("some value=" + value, statelessMap.get(value)); - assertEquals(SIZE, statelessMap.size()); - } - } - } - - @Test(timeout = 10000) - public void testBufferOverFlowPutAllWherePutReturnsNull() - throws IOException, InterruptedException { - - try (ChronicleMap serverMap = ChronicleMapBuilder - .of(Integer.class, CharSequence.class) - .entries(SIZE) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(8056)) - .create()) { - try (ChronicleMap statelessMap = localClient(8056)) { - Map payload = new HashMap(); - - for (int i = 0; i < SIZE; i++) { - payload.put(i, "some value=" + i); - } - - statelessMap.putAll(payload); - - int value = SIZE - 10; - - assertEquals("some value=" + value, statelessMap.get(value)); - assertEquals(SIZE, statelessMap.size()); - } - } - } - - @Test(timeout = 10000) - public void testPutWherePutReturnsNull() throws IOException, - InterruptedException { - - try (ChronicleMap serverMap = ChronicleMapBuilder - .of(Integer.class, CharSequence.class) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(8056)).create()) { - try (ChronicleMap statelessMap = localClient(8056)) { - statelessMap.put(1, "some value"); - - assertEquals("some value", statelessMap.get(1)); - assertEquals(1, statelessMap.size()); - } - } - } - - @Test(timeout = 10000) - public void testRemoveWhereRemoveReturnsNull() throws IOException, - InterruptedException { - - try (ChronicleMap serverMap = ChronicleMapBuilder - .of(Integer.class, CharSequence.class) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(8056)).create()) { - try (ChronicleMap statelessMap = localClient(8056)) { - statelessMap.put(1, "some value"); - - assertEquals("some value", statelessMap.get(1)); - assertEquals(1, statelessMap.size()); - - statelessMap.remove(1); - - assertEquals(null, statelessMap.get(1)); - assertEquals(0, statelessMap.size()); - } - } - } - - - @Test(timeout = 10000) - public void testLargeEntries() throws IOException, - InterruptedException { - int valueSize = 1_000; - - char[] value = new char[valueSize]; - - Arrays.fill(value, 'X'); - - String sampleValue = new String(value); - try (ChronicleMap serverMap = - ChronicleMapBuilder.of(Integer.class, CharSequence.class) - .constantValueSizeBySample(sampleValue) - .entries(1) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(8056) - .tcpBufferSize(128)) - .create()) { - try (ChronicleMap statelessMap = localClient(8056)) { - - statelessMap.put(1, new String(value)); - - assertEquals(new String(value), statelessMap.get(1)); - assertEquals(1, statelessMap.size()); - - - assertEquals(null, statelessMap.get(0)); - assertEquals(1, statelessMap.size()); - } - } - } - - - @Test(timeout = 10000) - public void testGetAndEntryWeDontHave() throws IOException, - InterruptedException, ExecutionException { - - try (ChronicleMap serverMap = ChronicleMapBuilder - .of(Integer.class, CharSequence.class) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(8056)).create()) { - try (ChronicleMap statelessMap = localClient(8056)) { - assertEquals(null, statelessMap.get(3)); - - } - } - } - - @Test(timeout = 10000) - public void testEquals() throws IOException, InterruptedException { - - final ChronicleMap serverMap1; - final ChronicleMap serverMap2; - final ChronicleMap statelessMap1; - final ChronicleMap statelessMap2; - - // server - { - serverMap1 = ChronicleMapBuilder.of(Integer.class, CharSequence.class) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(8056)).create(); - serverMap2 = ChronicleMapBuilder.of(Integer.class, CharSequence.class) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(8077)).create(); - } - - // stateless client - { - statelessMap1 = localClient(8056); - statelessMap2 = localClient(8077); - } - - Map payload = new HashMap(); - for (int i = 0; i < 1000; i++) { - payload.put(i, "some value=" + i); - } - - statelessMap1.putAll(payload); - assertTrue(statelessMap1.equals(payload)); - - statelessMap1.close(); - statelessMap2.close(); - - serverMap1.close(); - serverMap2.close(); - } - - - @Test - public void testThreadSafeness() throws IOException, InterruptedException { - - int nThreads = 2; - final ExecutorService executorService = Executors.newFixedThreadPool(nThreads); - - int count = 50000; - final CountDownLatch latch = new CountDownLatch(count * 2); - final AtomicInteger got = new AtomicInteger(); - - long startTime = System.currentTimeMillis(); - // server - try (ChronicleMap server = ChronicleMapBuilder - .of(Integer.class, Integer.class) - .putReturnsNull(true) - .replication((byte) 1, TcpTransportAndNetworkConfig.of(8047)).create()) { - - // stateless client - try (ChronicleMap client = localClient(8047)) { - - for (int i = 0; i < count; i++) { - - final int j = i; - executorService.submit(new Runnable() { - @Override - public void run() { - try { - // System.out.print("put("+j+")"); - client.put(j, j); - latch.countDown(); - } catch (Error | Exception e) { - LOG.error("", e); - //executorService.shutdown(); - - } - } - }); - } - - - for (int i = 0; i < count; i++) { - final int j = i; - - executorService.submit(new Runnable() { - @Override - public void run() { - try { - - Integer result = client.get(j); - - if (result == null) { - System.out.print("entry not found so re-submitting"); - executorService.submit(this); - return; - } - - if (result.equals(j)) { - got.incrementAndGet(); - } else { - System.out.println("expected j=" + j + " but got back=" + - result); - } - - latch.countDown(); - } catch (Error | Exception e) { - e.printStackTrace(); - LOG.error("", e); - // executorService.shutdown(); - } - } - }); - - - } - - latch.await(25, TimeUnit.SECONDS); - System.out.println("" + count + " messages took " + - TimeUnit.MILLISECONDS.toSeconds(System - .currentTimeMillis() - startTime) + " seconds, using " + nThreads + - " threads"); - - assertEquals(count, got.get()); - - } - } finally { - executorService.shutdownNow(); - executorService.awaitTermination(1000, TimeUnit.SECONDS); - - } - - - } - - - @Test - public void testPutsStatelessClientWithReplication() throws IOException, InterruptedException { - - int nThreads = 2; - final ExecutorService executorService = Executors.newFixedThreadPool(nThreads); - - int count = 50000; - final CountDownLatch latch = new CountDownLatch(count * 2); - final AtomicInteger got = new AtomicInteger(); - - long startTime = System.currentTimeMillis(); - - - // server - try (ChronicleMap server = ChronicleMapBuilder - .of(Integer.class, Integer.class) - .putReturnsNull(true) - .replication((byte) 1, TcpTransportAndNetworkConfig.of(8047)).create()) { - - try (ChronicleMap server2 = ChronicleMapBuilder - .of(Integer.class, Integer.class) - .putReturnsNull(true) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(8046, new - InetSocketAddress("localhost", 8047))).create()) { - - - // stateless client - try (ChronicleMap client = localClient(8046)) { - - for (int i = 0; i < count; i++) { - - final int j = i; - executorService.submit(new Runnable() { - @Override - public void run() { - try { - // System.out.print("put("+j+")"); - client.put(j, j); - latch.countDown(); - } catch (Error | Exception e) { - LOG.error("", e); - //executorService.shutdown(); - - } - } - }); - } - - - for (int i = 0; i < count; i++) { - final int j = i; - - executorService.submit(new Runnable() { - @Override - public void run() { - try { - - Integer result = server.get(j); - - if (result == null) { - System.out.print("entry not found so re-submitting"); - executorService.submit(this); - return; - } - - if (result.equals(j)) { - got.incrementAndGet(); - } else { - System.out.println("expected j=" + j + " but got back=" + - result); - } - - latch.countDown(); - } catch (Error | Exception e) { - e.printStackTrace(); - LOG.error("", e); - // executorService.shutdown(); - } - } - }); - - - } - - latch.await(25, TimeUnit.SECONDS); - System.out.println("" + count + " messages took " + - TimeUnit.MILLISECONDS.toSeconds(System - .currentTimeMillis() - startTime) + " seconds, using " + - nThreads + " threads"); - - assertEquals(count, got.get()); - - } - } - } finally { - executorService.shutdownNow(); - executorService.awaitTermination(1000, TimeUnit.SECONDS); - } - - } - - - @Test(timeout = 10000) - public void testCreateWithByteArrayKeyValue() throws IOException, InterruptedException { - - byte[] key = new byte[4]; - Bytes keyBuffer = new ByteBufferBytes(ByteBuffer.wrap(key)); - - try (ChronicleMap serverMap = ChronicleMapBuilder - .of(byte[].class, byte[].class) - .averageKeySize(4) - .averageValueSize(4) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(8056)) - .create()) { - - try (ChronicleMap statelessMap = localClient(8056)) { - - for (int i = 0; i < SIZE; i++) { - keyBuffer.clear(); - keyBuffer.writeInt(i); - statelessMap.put(key, key); - } - - assertEquals(SIZE, statelessMap.size()); - } - } - } - - @Test - public void testsConstantKeySizeBySampleIsSentFromServer() throws IOException { - - try (ChronicleMap server = ChronicleMapBuilder.of(byte[].class, CharSequence.class) - .replication(SingleChronicleHashReplication.builder() - .tcpTransportAndNetwork(TcpTransportAndNetworkConfig.of(8875)) - .name("serverMap") - .createWithId((byte) 1)) - .constantKeySizeBySample(new byte[14]) - .create()) { - - try (ChronicleMap map2 = localClient(8875)) { - - byte[] key = new byte[14]; - System.arraycopy("A".getBytes(), 0, key, 0, "A".length()); - - map2.put(key, "hello world"); - Assert.assertNotNull(map2.get(key)); - - } - } - - } - - @Test(timeout = 10000) - public void testGetServerVersion() throws IOException, InterruptedException { - int port = s_port++; - try (ChronicleMap serverMap = ChronicleMapBuilder - .of(Integer.class, StringBuilder.class) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(port)) - .create()) { - - try (ChronicleMap statelessMap = localClient(port)) { - - assertTrue(!((StatelessChronicleMap) statelessMap).serverApplicationVersion() - .isEmpty()); - - } - } - } - -} - - - - diff --git a/src/test/java/net/openhft/chronicle/map/TCPSocketReplication3VoidValueTest.java b/src/test/java/net/openhft/chronicle/map/TCPSocketReplication3VoidValueTest.java index 70ea7a813..7ee848696 100755 --- a/src/test/java/net/openhft/chronicle/map/TCPSocketReplication3VoidValueTest.java +++ b/src/test/java/net/openhft/chronicle/map/TCPSocketReplication3VoidValueTest.java @@ -19,7 +19,6 @@ package net.openhft.chronicle.map; import net.openhft.chronicle.hash.serialization.internal.DummyValue; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import java.io.Closeable; @@ -72,7 +71,7 @@ public class TCPSocketReplication3VoidValueTest { @After public void checkThreadsShutdown() { - StatelessClientTest.checkThreadsShutdown(threads); + ChannelReplicationTest.checkThreadsShutdown(threads); } @Test diff --git a/src/test/java/net/openhft/chronicle/map/TCPSocketReplication3wayPutReturnsNullTest.java b/src/test/java/net/openhft/chronicle/map/TCPSocketReplication3wayPutReturnsNullTest.java index 60d3774ed..5b120a449 100755 --- a/src/test/java/net/openhft/chronicle/map/TCPSocketReplication3wayPutReturnsNullTest.java +++ b/src/test/java/net/openhft/chronicle/map/TCPSocketReplication3wayPutReturnsNullTest.java @@ -88,7 +88,7 @@ public class TCPSocketReplication3wayPutReturnsNullTest { @After public void checkThreadsShutdown() { - StatelessClientTest.checkThreadsShutdown(threads); + ChannelReplicationTest.checkThreadsShutdown(threads); } @Test diff --git a/src/test/java/net/openhft/chronicle/map/TCPSocketReplication3wayTest.java b/src/test/java/net/openhft/chronicle/map/TCPSocketReplication3wayTest.java index 1d8eb3464..eb091a328 100755 --- a/src/test/java/net/openhft/chronicle/map/TCPSocketReplication3wayTest.java +++ b/src/test/java/net/openhft/chronicle/map/TCPSocketReplication3wayTest.java @@ -18,7 +18,6 @@ package net.openhft.chronicle.map; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import java.io.Closeable; @@ -68,7 +67,7 @@ public class TCPSocketReplication3wayTest { @After public void checkThreadsShutdown() { - StatelessClientTest.checkThreadsShutdown(threads); + ChannelReplicationTest.checkThreadsShutdown(threads); } @Test diff --git a/src/test/java/net/openhft/chronicle/map/TCPSocketReplication4WayMapTest.java b/src/test/java/net/openhft/chronicle/map/TCPSocketReplication4WayMapTest.java index 4b9563680..ac976a95a 100644 --- a/src/test/java/net/openhft/chronicle/map/TCPSocketReplication4WayMapTest.java +++ b/src/test/java/net/openhft/chronicle/map/TCPSocketReplication4WayMapTest.java @@ -18,7 +18,6 @@ package net.openhft.chronicle.map; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import java.io.Closeable; @@ -83,7 +82,7 @@ public class TCPSocketReplication4WayMapTest { @After public void checkThreadsShutdown() { - StatelessClientTest.checkThreadsShutdown(threads); + ChannelReplicationTest.checkThreadsShutdown(threads); } @Test diff --git a/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationBootStrapTest.java b/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationBootStrapTest.java index a39aff893..c73d8882c 100644 --- a/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationBootStrapTest.java +++ b/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationBootStrapTest.java @@ -20,7 +20,6 @@ import net.openhft.chronicle.hash.replication.SingleChronicleHashReplication; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import java.io.Closeable; @@ -177,7 +176,7 @@ public class TCPSocketReplicationBootStrapTest { @After public void checkThreadsShutdown() { - StatelessClientTest.checkThreadsShutdown(threads); + ChannelReplicationTest.checkThreadsShutdown(threads); } /** diff --git a/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationIntValueTest.java b/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationIntValueTest.java index d66abe2c6..d7df06d5a 100644 --- a/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationIntValueTest.java +++ b/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationIntValueTest.java @@ -22,7 +22,6 @@ import net.openhft.lang.model.DataValueClasses; import net.openhft.lang.values.IntValue; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import java.io.Closeable; @@ -88,7 +87,7 @@ public class TCPSocketReplicationIntValueTest { @After public void checkThreadsShutdown() { - StatelessClientTest.checkThreadsShutdown(threads); + ChannelReplicationTest.checkThreadsShutdown(threads); } @Test diff --git a/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationNativeTest.java b/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationNativeTest.java index df41af70d..9f4e76ad8 100644 --- a/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationNativeTest.java +++ b/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationNativeTest.java @@ -81,7 +81,7 @@ public class TCPSocketReplicationNativeTest { @After public void checkThreadsShutdown() { - StatelessClientTest.checkThreadsShutdown(threads); + ChannelReplicationTest.checkThreadsShutdown(threads); } @Test diff --git a/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationPostConnectionTest.java b/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationPostConnectionTest.java index 1441bbba2..b12e114ce 100755 --- a/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationPostConnectionTest.java +++ b/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationPostConnectionTest.java @@ -18,7 +18,6 @@ package net.openhft.chronicle.map; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import java.io.Closeable; @@ -50,7 +49,7 @@ public class TCPSocketReplicationPostConnectionTest { @After public void checkThreadsShutdown() { - StatelessClientTest.checkThreadsShutdown(threads); + ChannelReplicationTest.checkThreadsShutdown(threads); } @Test diff --git a/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationTest.java b/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationTest.java index df7fcf9c4..c27e6c670 100644 --- a/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationTest.java +++ b/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationTest.java @@ -18,7 +18,6 @@ package net.openhft.chronicle.map; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import java.io.Closeable; @@ -81,7 +80,7 @@ public class TCPSocketReplicationTest { @After public void checkThreadsShutdown() { - StatelessClientTest.checkThreadsShutdown(threads); + ChannelReplicationTest.checkThreadsShutdown(threads); } @Test diff --git a/src/test/java/net/openhft/chronicle/map/TcpReplicationLargeEntryTest.java b/src/test/java/net/openhft/chronicle/map/TcpReplicationLargeEntryTest.java index c6c1954d1..87c538f42 100644 --- a/src/test/java/net/openhft/chronicle/map/TcpReplicationLargeEntryTest.java +++ b/src/test/java/net/openhft/chronicle/map/TcpReplicationLargeEntryTest.java @@ -116,7 +116,7 @@ public class TcpReplicationLargeEntryTest { @After public void checkThreadsShutdown() { - StatelessClientTest.checkThreadsShutdown(threads); + ChannelReplicationTest.checkThreadsShutdown(threads); } diff --git a/src/test/java/net/openhft/chronicle/map/TcpReplicationSoakCrdtTest.java b/src/test/java/net/openhft/chronicle/map/TcpReplicationSoakCrdtTest.java index 936f984b0..b44191e6c 100644 --- a/src/test/java/net/openhft/chronicle/map/TcpReplicationSoakCrdtTest.java +++ b/src/test/java/net/openhft/chronicle/map/TcpReplicationSoakCrdtTest.java @@ -169,7 +169,7 @@ public class TcpReplicationSoakCrdtTest { @After public void checkThreadsShutdown() { - StatelessClientTest.checkThreadsShutdown(threads); + ChannelReplicationTest.checkThreadsShutdown(threads); } diff --git a/src/test/java/net/openhft/chronicle/map/TcpReplicationSoakTest.java b/src/test/java/net/openhft/chronicle/map/TcpReplicationSoakTest.java index 18979a148..6e54d7402 100644 --- a/src/test/java/net/openhft/chronicle/map/TcpReplicationSoakTest.java +++ b/src/test/java/net/openhft/chronicle/map/TcpReplicationSoakTest.java @@ -22,7 +22,6 @@ import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; import net.openhft.lang.io.ByteBufferBytes; import net.openhft.lang.model.Byteable; import net.openhft.lang.model.DataValueClasses; -import net.openhft.lang.threadlocal.ThreadLocalCopies; import net.openhft.lang.values.IntValue; import org.junit.*; @@ -117,7 +116,7 @@ public class TcpReplicationSoakTest { @After public void checkThreadsShutdown() { - StatelessClientTest.checkThreadsShutdown(threads); + ChannelReplicationTest.checkThreadsShutdown(threads); } diff --git a/src/test/java/net/openhft/chronicle/map/TcpTimeBasedReplicationSoakTest.java b/src/test/java/net/openhft/chronicle/map/TcpTimeBasedReplicationSoakTest.java index ebe0ebf31..acf7e4b98 100644 --- a/src/test/java/net/openhft/chronicle/map/TcpTimeBasedReplicationSoakTest.java +++ b/src/test/java/net/openhft/chronicle/map/TcpTimeBasedReplicationSoakTest.java @@ -123,7 +123,7 @@ public class TcpTimeBasedReplicationSoakTest { @After public void checkThreadsShutdown() { - StatelessClientTest.checkThreadsShutdown(threads); + ChannelReplicationTest.checkThreadsShutdown(threads); } diff --git a/src/test/java/net/openhft/chronicle/map/TimeBasedReplicationTest.java b/src/test/java/net/openhft/chronicle/map/TimeBasedReplicationTest.java index b29fae41d..d79faf284 100644 --- a/src/test/java/net/openhft/chronicle/map/TimeBasedReplicationTest.java +++ b/src/test/java/net/openhft/chronicle/map/TimeBasedReplicationTest.java @@ -21,7 +21,6 @@ import net.openhft.chronicle.hash.replication.TimeProvider; import net.openhft.chronicle.map.jsr166.JSR166TestCase; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.mockito.Mockito; @@ -51,7 +50,7 @@ public class TimeBasedReplicationTest extends JSR166TestCase { @After public void checkThreadsShutdown() { - StatelessClientTest.checkThreadsShutdown(threads); + ChannelReplicationTest.checkThreadsShutdown(threads); } public void testIgnoreLateAction(BiConsumer, diff --git a/src/test/java/net/openhft/chronicle/map/TwoMapOnDifferentServersTest.java b/src/test/java/net/openhft/chronicle/map/TwoMapOnDifferentServersTest.java index 16a85d8fc..c6c5e8db3 100644 --- a/src/test/java/net/openhft/chronicle/map/TwoMapOnDifferentServersTest.java +++ b/src/test/java/net/openhft/chronicle/map/TwoMapOnDifferentServersTest.java @@ -19,7 +19,6 @@ package net.openhft.chronicle.map; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import java.io.Closeable; @@ -80,7 +79,7 @@ public class TwoMapOnDifferentServersTest { @After public void checkThreadsShutdown() { - StatelessClientTest.checkThreadsShutdown(threads); + ChannelReplicationTest.checkThreadsShutdown(threads); } @Test diff --git a/src/test/java/net/openhft/chronicle/map/example/ServersMapMain.java b/src/test/java/net/openhft/chronicle/map/example/ServersMapMain.java index 9d391bcb2..2bd934690 100755 --- a/src/test/java/net/openhft/chronicle/map/example/ServersMapMain.java +++ b/src/test/java/net/openhft/chronicle/map/example/ServersMapMain.java @@ -32,7 +32,6 @@ public class ServersMapMain { static final int port = Integer.getInteger("port", 8989); static final int entries = Integer.getInteger("entries", 100000); static final int runs = Integer.getInteger("runs", 5); - static final boolean stateless = Boolean.getBoolean("stateless"); public static void startServer() throws IOException { File file = File.createTempFile("testServersMapMain", ".deleteme"); @@ -51,23 +50,16 @@ public class ServersMapMain { public static void startRemoteClient(String hostname) throws IOException { final ChronicleMap map; - if (stateless) { - map = ChronicleMapBuilder - .of(byte[].class, byte[].class, new InetSocketAddress(hostname, port)) - .putReturnsNull(true) - .create(); - } else { - File file = File.createTempFile("testServersMapMain", ".deleteme"); - file.deleteOnExit(); - TcpTransportAndNetworkConfig tcpConfig = - TcpTransportAndNetworkConfig.of(port, new InetSocketAddress(hostname, port)); + File file = File.createTempFile("testServersMapMain", ".deleteme"); + file.deleteOnExit(); + TcpTransportAndNetworkConfig tcpConfig = + TcpTransportAndNetworkConfig.of(port, new InetSocketAddress(hostname, port)); - map = ChronicleMapBuilder - .of(byte[].class, byte[].class) - .putReturnsNull(true) - .replication((byte) 1, tcpConfig) - .createPersistedTo(file); - } + map = ChronicleMapBuilder + .of(byte[].class, byte[].class) + .putReturnsNull(true) + .replication((byte) 1, tcpConfig) + .createPersistedTo(file); ByteBuffer key = ByteBuffer.allocate(8); ByteBuffer value = ByteBuffer.allocate(32); double lastAveragePut = Double.POSITIVE_INFINITY, lastAverageGet = Double.POSITIVE_INFINITY; diff --git a/src/test/java/net/openhft/chronicle/map/example/StringsMapMain.java b/src/test/java/net/openhft/chronicle/map/example/StringsMapMain.java index 6143ef6c6..8f573e3e3 100755 --- a/src/test/java/net/openhft/chronicle/map/example/StringsMapMain.java +++ b/src/test/java/net/openhft/chronicle/map/example/StringsMapMain.java @@ -31,7 +31,6 @@ public class StringsMapMain { static final int port = Integer.getInteger("port", 8998); static final int entries = Integer.getInteger("entries", 100000); static final int runs = Integer.getInteger("runs", 5); - static final boolean stateless = Boolean.getBoolean("stateless"); public static void startServer() throws IOException { File file = File.createTempFile("testServersMapMain", ".deleteme"); @@ -52,23 +51,16 @@ public class StringsMapMain { public static void startRemoteClient(String hostname) throws IOException { final ChronicleMap map; - if (stateless) { - map = ChronicleMapBuilder - .of(CharSequence.class, CharSequence.class, new InetSocketAddress(hostname, port)) - .putReturnsNull(true) - .create(); - } else { - File file = File.createTempFile("testServersMapMain", ".deleteme"); - file.deleteOnExit(); - TcpTransportAndNetworkConfig tcpConfig = - TcpTransportAndNetworkConfig.of(port, new InetSocketAddress(hostname, port)); + File file = File.createTempFile("testServersMapMain", ".deleteme"); + file.deleteOnExit(); + TcpTransportAndNetworkConfig tcpConfig = + TcpTransportAndNetworkConfig.of(port, new InetSocketAddress(hostname, port)); - map = ChronicleMapBuilder - .of(CharSequence.class, CharSequence.class) - .putReturnsNull(true) - .replication((byte) 1, tcpConfig) - .createPersistedTo(file); - } + map = ChronicleMapBuilder + .of(CharSequence.class, CharSequence.class) + .putReturnsNull(true) + .replication((byte) 1, tcpConfig) + .createPersistedTo(file); StringBuilder key = new StringBuilder(); StringBuilder value = new StringBuilder(); StringBuilder value2 = new StringBuilder(); @@ -83,12 +75,7 @@ public class StringsMapMain { long t1 = System.nanoTime(); map.put(key, value); long t2 = System.nanoTime(); - if (stateless) { - value.setLength(0); - value.append(map.get(key)); - } else { - map.getUsing(key, value); - } + map.getUsing(key, value); long t3 = System.nanoTime(); puts += t2 - t1; gets += t3 - t2; diff --git a/src/test/java/net/openhft/chronicle/map/jsr166/map/StatelessChronicleMapTest.java b/src/test/java/net/openhft/chronicle/map/jsr166/map/StatelessChronicleMapTest.java deleted file mode 100755 index 08f4d0af6..000000000 --- a/src/test/java/net/openhft/chronicle/map/jsr166/map/StatelessChronicleMapTest.java +++ /dev/null @@ -1,975 +0,0 @@ -/* - * Copyright (C) 2015 higherfrequencytrading.com - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package net.openhft.chronicle.map.jsr166.map; - -import net.openhft.chronicle.hash.Data; -import net.openhft.chronicle.hash.function.SerializableFunction; -import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; -import net.openhft.chronicle.map.*; -import net.openhft.chronicle.map.jsr166.JSR166TestCase; -import org.jetbrains.annotations.NotNull; -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - -import java.io.Closeable; -import java.io.File; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; -import java.util.*; -import java.util.function.Consumer; -import java.util.function.Predicate; - -import static net.openhft.chronicle.map.StatelessClientTest.localClient; -import static org.junit.Assert.*; - -/* - * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain, as explained at - * http://creativecommons.org/publicdomain/zero/1.0/ - * Other contributors include Andrew Wright, Jeffrey Hayes, - * Pat Fisher, Mike Judd. - */ -@Ignore -public class StatelessChronicleMapTest extends JSR166TestCase { - - public static final int SIZE = 1024; - - static class SingleCloseMap implements ChronicleMap { - private final Closeable[] closeables; - private final ChronicleMap d; - - @Override - public String toString() { - return d.toString(); - } - - public SingleCloseMap(ChronicleMap statelessMap, Closeable... closeables) { - this.closeables = closeables; - this.d = statelessMap; - } - - @Override - public File file() { - return null; - } - - @Override - public void close() { - for (Closeable c : closeables) { - try { - c.close(); - } catch (Exception e) { - e.printStackTrace(); - // eat the exception - } - } - } - - @Override - public boolean isOpen() { - return d.isOpen(); - } - - @Override - public long longSize() { - return d.longSize(); - } - - @Override - public int size() { - return d.size(); - } - - @Override - public boolean isEmpty() { - return d.isEmpty(); - } - - @Override - public boolean containsKey(Object key) { - return d.containsKey(key); - } - - @Override - public boolean containsValue(Object value) { - return d.containsValue(value); - } - - @NotNull - @Override - public net.openhft.chronicle.core.io.Closeable acquireContext(@NotNull K key, @NotNull V usingValue) { - return d.acquireContext(key, usingValue); - } - - @NotNull - @Override - public ExternalMapQueryContext queryContext(K key) { - return d.queryContext(key); - } - - @NotNull - @Override - public ExternalMapQueryContext queryContext(Data key) { - return d.queryContext(key); - } - - @Override - public MapSegmentContext segmentContext(int segmentIndex) { - return d.segmentContext(segmentIndex); - } - - @Override - public int segments() { - return d.segments(); - } - - @Override - public V get(Object key) { - return d.get(key); - } - - @Override - public V put(K key, V value) { - return d.put(key, value); - } - - @Override - public V remove(Object key) { - return d.remove(key); - } - - @Override - public void putAll(java.util.Map m) { - d.putAll(m); - } - - @Override - public void clear() { - d.clear(); - } - - @NotNull - @Override - public Set keySet() { - return d.keySet(); - } - - @NotNull - @Override - public Collection values() { - return d.values(); - } - - @NotNull - @Override - public Set> entrySet() { - return d.entrySet(); - } - - @Override - public V getUsing(K key, V usingValue) { - return d.getUsing(key, usingValue); - } - - @Override - public V acquireUsing(@NotNull K key, V usingValue) { - return d.acquireUsing(key, usingValue); - } - - @Override - public R getMapped(K key, @NotNull SerializableFunction function) { - return d.getMapped(key, function); - } - - @Override - public V putMapped(K key, @NotNull UnaryOperator unaryOperator) { - return d.putMapped(key, unaryOperator); - } - - @Override - public void getAll(File toFile) throws IOException { - d.getAll(toFile); - } - - @Override - public void putAll(File fromFile) throws IOException { - d.putAll(fromFile); - } - - @Override - public V newValueInstance() { - throw new UnsupportedOperationException(); - } - - @Override - public K newKeyInstance() { - throw new UnsupportedOperationException(); - } - - @Override - public Class keyClass() { - return d.keyClass(); - } - - @Override - public boolean forEachEntryWhile(Predicate> predicate) { - return d.forEachEntryWhile(predicate); - } - - @Override - public void forEachEntry(Consumer> action) { - d.forEachEntry(action); - } - - @Override - public Class valueClass() { - return d.valueClass(); - } - - @Override - public V putIfAbsent(K key, V value) { - return d.putIfAbsent(key, value); - } - - @Override - public boolean remove(Object key, Object value) { - return d.remove(key, value); - } - - @Override - public boolean replace(K key, V oldValue, V newValue) { - return d.replace(key, oldValue, newValue); - } - - @Override - public V replace(K key, V value) { - return d.replace(key, value); - } - } - - static ChronicleMap newShmIntString(int port) throws IOException { - - final ChronicleMap serverMap = - ChronicleMapBuilder.of(Integer.class, String.class) - .averageValueSize(1) - .entries(SIZE) - .replication((byte) 1, TcpTransportAndNetworkConfig.of(port)) - .create(); - - final ChronicleMap statelessMap = localClient(port); - - return new SingleCloseMap(statelessMap, statelessMap, serverMap); - } - - static ChronicleMap newStrStrMap(int port) throws - IOException { - - final ChronicleMap serverMap = ChronicleMapBuilder - .of(CharSequence.class, CharSequence.class) - .entries(SIZE) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(port)).create(); - - final ChronicleMap statelessMap = localClient(port); - - return new SingleCloseMap<>(statelessMap, statelessMap, serverMap); - } - - static ChronicleMap newByteArrayMap(int port) throws IOException { - - final ChronicleMap serverMap = ChronicleMapBuilder - .of(byte[].class, byte[].class) - .putReturnsNull(true) - .entries(SIZE) - .replication((byte) 2, TcpTransportAndNetworkConfig.of(port)) - .create(); - - final ChronicleMap statelessMap = ChronicleMapBuilder - .of(byte[].class, byte[].class, new InetSocketAddress("localhost", port)) - .putReturnsNull(true) - .create(); - - return new SingleCloseMap<>(statelessMap, statelessMap, serverMap); - } - - Set threads; - - @Before - public void sampleThreads() { - threads = Thread.getAllStackTraces().keySet(); - } - - @After - public void checkThreadsShutdown() { - StatelessClientTest.checkThreadsShutdown(threads); - } - - /** - * Returns a new map from Integers 1-5 to Strings "A"-"E". - * - * @param port - */ - private ChronicleMap map5(final int port) throws IOException { - ChronicleMap map = newShmIntString(port); - assertTrue(map.isEmpty()); - map.put(one, "A"); - map.put(two, "B"); - map.put(three, "C"); - map.put(four, "D"); - map.put(five, "E"); - assertFalse(map.isEmpty()); - assertEquals(5, map.size()); - return map; - } - - static int s_port = 11050; - - @Test(timeout = 30000) - @Ignore - public void testByteArrayPerf() throws IOException { - ByteBuffer key = ByteBuffer.allocate(8); - ByteBuffer value = ByteBuffer.allocate(50); - int runs = 100000; - try (ChronicleMap map = newByteArrayMap(s_port++)) { - for (int t = 0; t < 5; t++) { - { - long start = System.nanoTime(); - for (int i = 0; i < runs; i++) { - key.putLong(0, i); - value.putLong(0, i); - map.put(key.array(), value.array()); - } - long time = System.nanoTime() - start; - System.out.printf("%d: Took %.1f us on average to put %n", t, time / 1e3 / runs); - } - { - long start = System.nanoTime(); - for (int i = 0; i < runs; i++) { - key.putLong(0, i); - byte[] b = map.get(key.array()); - } - long time = System.nanoTime() - start; - System.out.printf("%d: Took %.1f us on average to get %n", t, time / 1e3 / runs); - } - } - } - } - - /** - * clear removes all pairs - */ - @Test(timeout = 10000) - public void testClear() throws IOException { - try (ChronicleMap map = map5(s_port++)) { - map.clear(); - assertEquals(0, map.size()); - } - } - - /** - * contains returns true for contained value - */ - @Test(timeout = 10000) - public void testContains() throws IOException { - try (ChronicleMap map = map5(s_port++)) { - assertTrue(map.containsValue("A")); - assertFalse(map.containsValue("Z")); - } - } - - /** - * containsKey returns true for contained key - */ - @Test(timeout = 10000) - public void testContainsKey() throws IOException { - try (ChronicleMap map = map5(s_port++)) { - assertTrue(map.containsKey(one)); - assertFalse(map.containsKey(zero)); - } - } - - /** - * containsValue returns true for held values - */ - @Test(timeout = 10000) - public void testContainsValue() throws IOException { - try (ChronicleMap map = map5(s_port++)) { - assertTrue(map.containsValue("A")); - assertFalse(map.containsValue("Z")); - } - } - - /** - * get returns the correct element at the given key, or null if not present - */ - @Test(timeout = 10000) - public void testGet() throws IOException { - try (ChronicleMap map = map5(s_port++)) { - assertEquals("A", (String) map.get(one)); - try (ChronicleMap empty = newStrStrMap(8078)) { - assertNull(map.get(notPresent)); - } - } - } - - /** - * isEmpty is true of empty map and false for non-empty - */ - @Test(timeout = 10000) - public void testIsEmpty() throws IOException { - try (ChronicleMap empty = newShmIntString(s_port++)) { - try (ChronicleMap map = map5(s_port++)) { - if (!empty.isEmpty()) { - System.out.print("not empty " + empty); - } - assertTrue(empty.isEmpty()); - assertFalse(map.isEmpty()); - } - } - } - - /** - * keySet returns a Set containing all the keys - */ - @Test(timeout = 10000) - public void testKeySet() throws IOException { - try (ChronicleMap map = map5(s_port++)) { - Set s = map.keySet(); - assertEquals(5, s.size()); - assertTrue(s.contains(one)); - assertTrue(s.contains(two)); - assertTrue(s.contains(three)); - assertTrue(s.contains(four)); - assertTrue(s.contains(five)); - } - } - - /** - * keySet.toArray returns contains all keys - */ - @Test(timeout = 10000) - public void testKeySetToArray() throws IOException { - try (ChronicleMap map = map5(s_port++)) { - Set s = map.keySet(); - Object[] ar = s.toArray(); - assertTrue(s.containsAll(Arrays.asList(ar))); - assertEquals(5, ar.length); - ar[0] = m10; - assertFalse(s.containsAll(Arrays.asList(ar))); - } - } - - /** - * Values.toArray contains all values - */ - @Test(timeout = 10000) - public void testValuesToArray() throws IOException { - try (ChronicleMap map = map5(s_port++)) { - Collection v = map.values(); - Object[] ar = v.toArray(); - ArrayList s = new ArrayList(Arrays.asList(ar)); - assertEquals(5, ar.length); - assertTrue(s.contains("A")); - assertTrue(s.contains("B")); - assertTrue(s.contains("C")); - assertTrue(s.contains("D")); - assertTrue(s.contains("E")); - } - } - - /** - * entrySet.toArray contains all entries - */ - @Test(timeout = 5000) - public void testEntrySetToArray() throws IOException { - try (ChronicleMap map = map5(s_port++)) { - Set s = map.entrySet(); - Object[] ar = s.toArray(); - assertEquals(5, ar.length); - for (int i = 0; i < 5; ++i) { - assertTrue(map.containsKey(((java.util.Map.Entry) (ar[i])).getKey())); - assertTrue(map.containsValue(((java.util.Map.Entry) (ar[i])).getValue())); - } - } - } - - /** - * values collection contains all values - */ - @Test(timeout = 5000) - public void testValues() throws IOException { - try (ChronicleMap map = map5(s_port++)) { - Collection s = map.values(); - assertEquals(5, s.size()); - assertTrue(s.contains("A")); - assertTrue(s.contains("B")); - assertTrue(s.contains("C")); - assertTrue(s.contains("D")); - assertTrue(s.contains("E")); - } - } - - /** - * entrySet contains all pairs - */ - @Test(timeout = 10000) - public void testEntrySet() throws IOException { - try (ChronicleMap map = map5(s_port++)) { - Set s = map.entrySet(); - assertEquals(5, s.size()); - Iterator it = s.iterator(); - while (it.hasNext()) { - java.util.Map.Entry e = (java.util.Map.Entry) it.next(); - assertTrue( - (e.getKey().equals(one) && e.getValue().equals("A")) || - (e.getKey().equals(two) && e.getValue().equals("B")) || - (e.getKey().equals(three) && e.getValue().equals("C")) || - (e.getKey().equals(four) && e.getValue().equals("D")) || - (e.getKey().equals(five) && e.getValue().equals("E")) - ); - } - } - } - - /** - * putAll adds all key-value pairs from the given map - */ - @Test(timeout = 5000) - public void testPutAll() throws IOException { - int port = s_port++; - try (ChronicleMap empty = newShmIntString(port)) { - try (ChronicleMap map = map5(port)) { - empty.putAll(map); - assertEquals(5, empty.size()); - assertTrue(empty.containsKey(one)); - assertTrue(empty.containsKey(two)); - assertTrue(empty.containsKey(three)); - assertTrue(empty.containsKey(four)); - assertTrue(empty.containsKey(five)); - } - } - } - - /** - * putIfAbsent works when the given key is not present - */ - @Test(timeout = 5000) - public void testPutIfAbsent() throws IOException { - try (ChronicleMap map = map5(s_port++)) { - map.putIfAbsent(six, "Z"); - assertTrue(map.containsKey(six)); - } - } - - /** - * putIfAbsent does not add the pair if the key is already present - */ - @Test(timeout = 5000) - public void testPutIfAbsent2() throws IOException { - try (ChronicleMap map = map5(s_port++)) { - assertEquals("A", map.putIfAbsent(one, "Z")); - } - } - - /** - * replace fails when the given key is not present - */ - @Test(timeout = 5000) - public void testReplace() throws IOException { - try (ChronicleMap map = map5(s_port++)) { - assertNull(map.replace(six, "Z")); - assertFalse(map.containsKey(six)); - } - } - - /** - * replace succeeds if the key is already present - */ - @Test(timeout = 5000) - public void testReplace2() throws - IOException { - try (ChronicleMap map = map5(s_port++)) { - assertNotNull(map.replace(one, "Z")); - assertEquals("Z", map.get(one)); - } - } - - /** - * replace value fails when the given key not mapped to expected value - */ - @Test(timeout = 5000) - public void testReplaceValue() throws IOException { - try (ChronicleMap map = map5(s_port++)) { - assertEquals("A", map.get(one)); - assertFalse(map.replace(one, "Z", "Z")); - assertEquals("A", map.get(one)); - } - } - - /** - * replace value succeeds when the given key mapped to expected value - */ - @Test(timeout = 5000) - public void testReplaceValue2() throws IOException { - try (ChronicleMap map = map5(s_port++)) { - assertEquals("A", map.get(one)); - assertTrue(map.replace(one, "A", "Z")); - assertEquals("Z", map.get(one)); - } - } - - /** - * remove removes the correct key-value pair from the map - */ - @Test(timeout = 5000) - public void testRemove() throws IOException { - try (ChronicleMap map = map5(s_port++)) { - map.remove(five); - assertEquals(4, map.size()); - assertFalse(map.containsKey(five)); - } - } - - /** - * remove(key,value) removes only if pair present - */ - @Test(timeout = 5000) - public void testRemove2 - () throws IOException { - /* try( ChronicleMap map = map5(8076)) { - map.remove(five, "E"); - assertEquals(4, map.size()); - assertFalse(map.containsKey(five)); - map.remove(four, "A"); - assertEquals(4, map.size()); - assertTrue(map.containsKey(four)); - */ - } - - /** - * size returns the correct values - */ - @Test(timeout = 5000) - public void testSize() throws IOException { - try (ChronicleMap map = map5(s_port++)) { - try (ChronicleMap empty = newShmIntString(s_port++)) { - assertEquals(0, empty.size()); - assertEquals(5, map.size()); - } - } - } - - /** - * size returns the correct values - */ - @Test(timeout = 15000) - public void testSize2() throws IOException { - try (ChronicleMap map = map5(s_port++)) { - try (ChronicleMap empty = newShmIntString(s_port++)) { - assertEquals(0, empty.size()); - assertEquals(5, map.size()); - } - } - } - - /** - * size returns the correct values - */ - @Test(timeout = 5000) - public void testSize3() throws IOException { - try (ChronicleMap map = map5(s_port++)) { - try (ChronicleMap empty = newShmIntString(s_port++)) { - assertEquals(0, empty.size()); - assertEquals(5, map.size()); - } - } - } - - /** - * toString contains toString of elements - */ - @Test(timeout = 5000) - public void testToString() throws IOException { - try (ChronicleMap map = map5(s_port++)) { - String s = map.toString(); - for (int i = 1; i <= 5; ++i) { - assertTrue(s.contains(String.valueOf(i))); - } - } - } - - /** - * get(null) throws NPE - */ - @Test(timeout = 5000) - public void testGet_NullPointerException() throws IOException { - - try (ChronicleMap c = newShmIntString(s_port++)) { - c.get(null); - shouldThrow(); - } catch (NullPointerException success) { - } catch (IllegalArgumentException success) { - } - } - - /** - * containsKey(null) throws NPE - */ - @Test(timeout = 5000) - public void testContainsKey_NullPointerException() throws IOException { - try (ChronicleMap c = newShmIntString(s_port++)) { - c.containsKey(null); - shouldThrow(); - } catch (NullPointerException success) { - } catch (IllegalArgumentException success) { - } - } - - /** - * put(null,x) throws NPE - */ - @Test(timeout = 5000) - public void testPut1_NullPointerException() throws IOException { - try (ChronicleMap c = newShmIntString(s_port++)) { - c.put(null, "whatever"); - shouldThrow(); - } catch (NullPointerException success) { - } - } - - /** - * put(x, null) throws NPE - */ - @Test(timeout = 5000) - public void testPut2_NullPointerException() throws IOException { - try (ChronicleMap c = newShmIntString(s_port++)) { - c.put(notPresent, null); - shouldThrow(); - } catch (NullPointerException success) { - } - } - - /** - * putIfAbsent(null, x) throws NPE - */ - @Test(timeout = 5000) - public void testPutIfAbsent1_NullPointerException() throws IOException { - try (ChronicleMap c = newShmIntString(s_port++)) { - c.putIfAbsent(null, "whatever"); - shouldThrow(); - } catch (NullPointerException success) { - } - } - - /** - * replace(null, x) throws NPE - */ - @Test(timeout = 10000) - public void testReplace_NullPointerException() throws IOException { - try (ChronicleMap c = newShmIntString(s_port++)) { - c.replace(null, "whatever"); - shouldThrow(); - } catch (NullPointerException success) { - } - } - - /** - * replace(null, x, y) throws NPE - */ - @Test(timeout = 10000) - public void testReplaceValue_NullPointerException() throws IOException { - try (ChronicleMap c = newShmIntString(s_port++)) { - c.replace(null, "A", "whatever"); - shouldThrow(); - } catch (NullPointerException success) { - } - } - - /** - * putIfAbsent(x, null) throws NPE - */ - @Test(timeout = 10000) - public void testPutIfAbsent2_NullPointerException() throws IOException { - try (ChronicleMap c = newShmIntString(s_port++)) { - c.putIfAbsent(notPresent, null); - shouldThrow(); - } catch (NullPointerException success) { - } - } - - /** - * replace(x, null) throws NPE - */ - @Test(timeout = 5000) - public void testReplace2_NullPointerException() throws IOException { - try (ChronicleMap c = newShmIntString(s_port++)) { - c.replace(notPresent, null); - shouldThrow(); - } catch (NullPointerException success) { - } - } - - /** - * replace(x, null, y) throws NPE - */ - @Test(timeout = 5000) - public void testReplaceValue2_NullPointerException() throws IOException { - try (ChronicleMap c = newShmIntString(s_port++)) { - c.replace(notPresent, null, "A"); - shouldThrow(); - } catch (NullPointerException success) { - } - } - - /** - * replace(x, y, null) throws NPE - */ - @Test(timeout = 5000) - public void testReplaceValue3_NullPointerException() throws IOException { - try (ChronicleMap c = newShmIntString(s_port++)) { - c.replace(notPresent, "A", null); - shouldThrow(); - } catch (NullPointerException success) { - } - } - - /** - * remove(null) throws NPE - */ - @Test(timeout = 10000) - public void testRemove1_NullPointerException() throws IOException { - try (ChronicleMap c = newStrStrMap(s_port++)) { - c.put("sadsdf", "asdads"); - c.remove(null); - shouldThrow(); - } catch (NullPointerException success) { - } - } - - /** - * remove(null, x) throws NPE - */ - @Test(timeout = 5000) - public void testRemove2_NullPointerException - () throws IOException { - try (ChronicleMap c = newStrStrMap(s_port++)) { - c.put("sadsdf", "asdads"); - c.remove(null, "whatever"); - shouldThrow(); - } catch (NullPointerException success) { - } - } - - /** - * remove(x, null) returns false - */ - @Test(timeout = 5000) - public void testRemove3() throws IOException { - - try (ChronicleMap c = newStrStrMap(s_port++)) { - c.put("sadsdf", "asdads"); - assertFalse(c.remove("sadsdf", null)); - } - } - - // classes for testing Comparable fallbacks - static class BI implements Comparable { - private final int value; - - BI(int value) { - this.value = value; - } - - public int compareTo(BI other) { - return Integer.compare(value, other.value); - } - - public boolean equals(Object x) { - return (x instanceof BI) && ((BI) x).value == value; - } - - public int hashCode() { - return 42; - } - } - - static class CI extends BI { - CI(int value) { - super(value); - } - } - - static class DI extends BI { - DI(int value) { - super(value); - } - } - - static class BS implements Comparable { - private final String value; - - BS(String value) { - this.value = value; - } - - public int compareTo(BS other) { - return value.compareTo(other.value); - } - - public boolean equals(Object x) { - return (x instanceof BS) && value.equals(((BS) x).value); - } - - public int hashCode() { - return 42; - } - } - - static class LexicographicList> extends ArrayList - implements Comparable> { - private static final long serialVersionUID = 0; - static long total; - static long n; - - LexicographicList(Collection c) { - super(c); - } - - LexicographicList(E e) { - super(Collections.singleton(e)); - } - - public int compareTo(LexicographicList other) { - long start = System.currentTimeMillis(); - int common = Math.min(size(), other.size()); - int r = 0; - for (int i = 0; i < common; i++) { - if ((r = get(i).compareTo(other.get(i))) != 0) - break; - } - if (r == 0) - r = Integer.compare(size(), other.size()); - total += System.currentTimeMillis() - start; - n++; - return r; - } - } - -} -