Merge remote-tracking branch 'origin/master'

This commit is contained in:
Rob Austin
2014-12-11 10:40:10 +00:00
24 changed files with 510 additions and 310 deletions
+7 -1
View File
@@ -168,7 +168,7 @@ and define the snapshot version in your pom.xml, for example:
<dependency>
<groupId>net.openhft</groupId>
<artifactId>chronicle-map</artifactId>
<version>1.0.1-SNAPSHOT</version>
<version><!--replace with the latest version--></version>
</dependency>
```
@@ -599,6 +599,9 @@ entries are no where near the max entry size.
## Serialization
![Serialization](http://openhft.net/wp-content/uploads/2014/09/Serialization_01.jpg)
Chronicle Map stores your data into off heap memory, so when you give it a Key or Value, it will
serialise these objects into bytes.
@@ -1117,6 +1120,9 @@ click [here](https://github.com/OpenHFT/Chronicle-Map#sharing-data-between-two-o
### How to speed up the Chronicle Map Stateless Client
![Chronicle Map](http://openhft.net/wp-content/uploads/2014/09/State-Transition_1-thread_02.jpg)
![Chronicle Map](http://openhft.net/wp-content/uploads/2014/09/State-Transition_2-thread_03.jpg)
By default when you make a method call to a `ChronicleMap` stateless client,
your method call is wrapped into an event which is sent over tcp and processed by the server,
your stateless client will block until an acknowledgement has been received from the server that
+4 -6
View File
@@ -17,20 +17,18 @@
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>net.openhft</groupId>
<artifactId>java-parent-pom</artifactId>
<version>1.1.2</version>
<relativePath/>
<relativePath />
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>chronicle-map</artifactId>
<version>2.0.12b-SNAPSHOT</version>
<version>2.0.14b-SNAPSHOT</version>
<name>OpenHFT/Chronicle-Map</name>
<description>Chronicle-Map</description>
@@ -48,7 +46,7 @@
<dependency>
<groupId>net.openhft</groupId>
<artifactId>lang</artifactId>
<version>6.4.16-SNAPSHOT</version>
<version>6.4.17-SNAPSHOT</version>
</dependency>
<dependency>
@@ -77,7 +77,7 @@ public final class TcpTransportAndNetworkConfig implements Serializable {
return new TcpTransportAndNetworkConfig(
serverPort, unmodifiableSet(s),
DEFAULT_PACKET_SIZE,
false, // autoReconnectedUponDroppedConnection
true, // autoReconnectedUponDroppedConnection
ThrottlingConfig.noThrottling(),
DEFAULT_HEART_BEAT_INTERVAL,
DEFAULT_HEART_BEAT_INTERVAL_UNIT);
@@ -143,6 +143,7 @@ abstract class AbstractChronicleMapBuilder<K, V,
private SingleChronicleHashReplication singleHashReplication = null;
private InetSocketAddress[] pushToAddresses;
public boolean bootstrapOnlyLocalEntries = false;
private boolean disableOversizedEntries = false;
AbstractChronicleMapBuilder(Class<K> keyClass, Class<V> valueClass) {
keyBuilder = new SerializationBuilder<K>(keyClass, SerializationBuilder.Role.KEY);
@@ -933,7 +934,7 @@ abstract class AbstractChronicleMapBuilder<K, V,
keyBuilder.objectSerializer(acquireObjectSerializer(JDKObjectSerializer.INSTANCE));
valueBuilder.objectSerializer(acquireObjectSerializer(JDKObjectSerializer.INSTANCE));
long maxSize = (long) entrySize(replicated) * figureBufferAllocationFactor();
long maxSize = (long) entrySize(replicated) * Math.min(maxEntryOversizeFactor(), figureBufferAllocationFactor());
keyBuilder.maxSize(maxSize);
valueBuilder.maxSize(maxSize);
@@ -984,8 +985,7 @@ abstract class AbstractChronicleMapBuilder<K, V,
private int figureBufferAllocationFactor() {
// if expected map size is about 1000, seems rather wasteful to allocate
// key and value serialization buffers each x64 of expected entry size..
return (int) Math.min(Math.max(4L, entries() >> 10),
VanillaChronicleMap.MAX_ENTRY_OVERSIZE_FACTOR);
return (int) Math.max(4L, entries() >> 10);
}
@Override
@@ -1003,5 +1003,15 @@ abstract class AbstractChronicleMapBuilder<K, V,
public String name() {
return this.name;
}
@Override
public ChronicleMapBuilderI<K, V> disableOversizedEntries() {
this.disableOversizedEntries = true;
return this;
}
public int maxEntryOversizeFactor() {
return disableOversizedEntries ? 1 : VanillaChronicleMap.MAX_ENTRY_OVERSIZE_FACTOR;
}
}
@@ -197,17 +197,17 @@ public interface ChronicleMap<K, V> extends ConcurrentMap<K, V>, ChronicleHash {
* @param <R> return type.
* @return the result of the function, or null if there is no entry for the key.
*/
<R> R mapForKey(K key, @NotNull Function<? super V, R> function);
<R> R getMapped(K key, @NotNull Function<? super V, R> function);
/**
* Apply a mutator to the value for a key and return a result. A write lock is assumed. <p> If
* Apply a unaryOperator to the value for a key and return a result. A write lock is assumed. <p> If
* there is no entry for this key null will be returned
*
* @param key to apply the mapping to
* @param mutator to alter the value and calculate a result
* @param unaryOperator to alter the value and calculate a result
* @return the result of the function.
*/
V putWith(K key, @NotNull Mutator<V> mutator);
V putMapped(K key, @NotNull UnaryOperator<V> unaryOperator);
/**
* exports all the entries to a {@link java.io.File} storing them in JSON format, an attempt is
@@ -247,5 +247,14 @@ public interface ChronicleMap<K, V> extends ConcurrentMap<K, V>, ChronicleHash {
*/
void putAll(File fromFile) throws IOException;
/**
* @return a new empty instance based on the Value type
*/
V newValueInstance();
/**
* @return a new empty instance based on the Key type
*/
K newKeyInstance();
}
@@ -69,26 +69,8 @@ public final class ChronicleMapBuilder<K, V> implements ChronicleMapBuilderI<K,
return new ChronicleMapBuilder<K, V>(builder);
}
// todo - work in progress this will be changed me not today, so don't refactor this !
public static <T> T newInstance(Class<T> interfaceClass, boolean isKey) {
if (interfaceClass.isEnum())
return isKey ? DataValueClasses.newDirectReference(interfaceClass) : DataValueClasses
.newDirectInstance(interfaceClass);
else if (!offHeapReference(interfaceClass) && !interfaceClass.isInterface() &&
!builtInType(interfaceClass)) {
// if (())
// interfaceClass = DataValueClasses.directClassFor(interfaceClass);
return DataValueClasses.newInstance(interfaceClass);
}
return DataValueClasses.newDirectInstance(interfaceClass);
}
static boolean builtInType(Class clazz) {
return clazz.getClassLoader() == Class.class.getClassLoader();
}
@@ -97,7 +79,7 @@ public final class ChronicleMapBuilder<K, V> implements ChronicleMapBuilderI<K,
this.delegate = delegate;
}
private static boolean offHeapReference(Class valueClass) {
static boolean offHeapReference(Class valueClass) {
return Byteable.class.isAssignableFrom(valueClass);
}
@@ -540,14 +522,8 @@ public final class ChronicleMapBuilder<K, V> implements ChronicleMapBuilderI<K,
return this;
}
public ChronicleMapBuilderI<K, V> checkSerializedValues() {
// throw new UnsupportedOperationException("Not implemented");
return this;
}
public ChronicleMapBuilder<K, V> disableOversizedEntries(boolean disableOversizedEntries) {
// throw an exception rather than use oversized entries to test the size is as expected.
// throw new UnsupportedOperationException("Not implemented");
public ChronicleMapBuilder<K, V> disableOversizedEntries() {
delegate.disableOversizedEntries();
return this;
}
}
@@ -315,4 +315,5 @@ public interface ChronicleMapBuilderI<K, V> extends Serializable {
String name();
ChronicleMapBuilderI<K, V> disableOversizedEntries();
}
@@ -718,7 +718,7 @@ final class ReplicatedChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? supe
throw defaultValueOrPrepareBytesShouldBeSpecified();
}
putValue(pos, offset, entry, valueSizePos, entryEndAddr,
copies, localSegmentState, metaElemWriter, elemWriter, elem,
localSegmentState, metaElemWriter, elemWriter, elem,
metaElemWriter.size(elemWriter, elem), hashLookup);
pos = localSegmentState.pos;
@@ -47,7 +47,8 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
import static java.nio.ByteBuffer.allocateDirect;
import static net.openhft.chronicle.map.AbstractChannelReplicator.*;
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.*;
/**
@@ -68,8 +69,8 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clon
private volatile ByteBuffer outBuffer;
private volatile ByteBufferBytes outBytes;
private ByteBuffer inBuffer;
private ByteBufferBytes inBytes;
private volatile ByteBuffer inBuffer;
private volatile ByteBufferBytes inBytes;
@NotNull
private final ReaderWithSize<K> keyReaderWithSize;
@@ -123,7 +124,7 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clon
PUT_ALL_WITHOUT_ACC,
HASH_CODE,
MAP_FOR_KEY,
UPDATE_FOR_KEY
PUT_MAPPED
}
@@ -177,6 +178,16 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clon
throw new UnsupportedOperationException();
}
@Override
public V newValueInstance() {
return VanillaChronicleMap.newInstance(vClass, false);
}
@Override
public K newKeyInstance() {
return VanillaChronicleMap.newInstance(kClass, true);
}
private ExecutorService lazyExecutorService() {
if (executorService == null) {
synchronized (this) {
@@ -225,16 +236,14 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clon
}
/**
* 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.
* 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)
* @see net.openhft.chronicle.map.StatelessChronicleMap#lazyConnect(long, java.net.InetSocketAddress)
*/
private synchronized void attemptConnect(final InetSocketAddress remoteAddress) {
@@ -263,9 +272,8 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clon
}
/**
* 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
* 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
@@ -331,13 +339,14 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clon
* @return a unique transactionId
*/
private long nextUniqueTransaction(long time) {
long old = transactionID.getAndSet(time);
if (old == time)
return transactionID.incrementAndGet();
else
return 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")
@@ -382,10 +391,9 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clon
}
/**
* 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
* 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
@@ -481,7 +489,7 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clon
}
@Nullable
public <R> R mapForKey(@Nullable K key, @NotNull Function<? super V, R> function) {
public <R> R getMapped(@Nullable K key, @NotNull Function<? super V, R> function) {
if (key == null)
throw keyNotNullNPE();
return fetchObject(MAP_FOR_KEY, key, function);
@@ -490,10 +498,10 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clon
@Nullable
@Override
public V putWith(@Nullable K key, @NotNull Mutator<V> mutator) {
public V putMapped(@Nullable K key, @NotNull UnaryOperator<V> unaryOperator) {
if (key == null)
throw keyNotNullNPE();
return fetchObject(UPDATE_FOR_KEY, key, mutator);
return fetchObject(PUT_MAPPED, key, unaryOperator);
}
@@ -814,8 +822,8 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clon
// skips for the transaction id
outBytes.skip(SIZE_OF_TRANSACTION_ID);
outBytes.skip(SIZE_OF_TIME_SHIFT);
outBytes.writeByte(identifier);
outBytes.writeInt(0);
return sizeLocation;
}
@@ -997,13 +1005,15 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clon
receive(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();
assert transactionId0 != 0;
// check the transaction id is reasonable
assert String.valueOf(transactionId0).startsWith("14");
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) {
@@ -1130,7 +1140,6 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clon
outBytes.writeInt(size0);
assert transactionId != 0;
outBytes.writeLong(transactionId);
outBytes.writeUnsignedShort((int) (transactionId - startTime));
outBytes.position(pos);
}
@@ -64,6 +64,7 @@ interface Work {
*/
final class TcpReplicator extends AbstractChannelReplicator implements Closeable {
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 Logger LOG = LoggerFactory.getLogger(TcpReplicator.class.getName());
@@ -413,8 +414,8 @@ final class TcpReplicator extends AbstractChannelReplicator implements Closeable
// so these nodes will establish the connection when they come back up,
// hence under these circumstances, polling a dropped node to attempt to reconnect is no-longer
// required as the remote node will establish the connection its self on startup.
if (replicationConfig.autoReconnectedUponDroppedConnection())
attached.connector.connect();
attached.connector.connect();
throw e;
}
@@ -592,7 +593,11 @@ final class TcpReplicator extends AbstractChannelReplicator implements Closeable
final long approxTime) throws IOException {
final SocketChannel socketChannel = (SocketChannel) key.channel();
final Attached attached = (Attached) key.attachment();
if (attached == null) throw new NullPointerException("No attached");
if (attached == null) {
LOG.info("Closing connection " + socketChannel + ", nothing attached");
socketChannel.close();
return;
}
TcpSocketChannelEntryWriter entryWriter = attached.entryWriter;
if (entryWriter == null) throw new NullPointerException("No entryWriter");
if (entryWriter.isWorkIncomplete()) {
@@ -1332,10 +1337,10 @@ class StatelessServerConnector<K, V> {
long transactionId = reader.readLong();
// the time stamp and the transaction are usually the same, or out by the shift
int timestampShift = reader.readUnsignedShort();
long timestamp = transactionId - timestampShift;
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
@@ -1413,8 +1418,8 @@ class StatelessServerConnector<K, V> {
case MAP_FOR_KEY:
return mapForKey(reader, writer, sizeLocation);
case UPDATE_FOR_KEY:
return updateForKey(reader, writer, sizeLocation);
case PUT_MAPPED:
return putMapped(reader, writer, sizeLocation);
default:
throw new IllegalStateException("unsupported event=" + event);
@@ -1426,7 +1431,7 @@ class StatelessServerConnector<K, V> {
final K key = keyReaderWithSize.read(reader, null);
final Function<V, ?> function = (Function<V, ?>) reader.readObject();
try {
Object result = map.mapForKey(key, function);
Object result = map.getMapped(key, function);
writer.writeObject(result);
} catch (Throwable e) {
LOG.info("", e);
@@ -1438,11 +1443,11 @@ class StatelessServerConnector<K, V> {
}
@Nullable
public Work updateForKey(@NotNull ByteBufferBytes reader, @NotNull Bytes writer, long sizeLocation) {
public Work putMapped(@NotNull ByteBufferBytes reader, @NotNull Bytes writer, long sizeLocation) {
final K key = keyReaderWithSize.read(reader, null);
final Mutator<V> mutator = (Mutator<V>) reader.readObject();
final UnaryOperator<V> unaryOperator = (UnaryOperator<V>) reader.readObject();
try {
Object result = map.putWith(key, mutator);
Object result = map.putMapped(key, unaryOperator);
writer.writeObject(result);
} catch (Throwable e) {
LOG.info("", e);
@@ -11,7 +11,7 @@ import java.io.Serializable;
*/
public interface Mutator<T> extends Serializable {
public interface UnaryOperator<T> extends Serializable {
/**
* Applies this mutator to the given mutable argument.
*
@@ -36,14 +36,13 @@ import net.openhft.lang.collection.DirectBitSet;
import net.openhft.lang.collection.SingleThreadedDirectBitSet;
import net.openhft.lang.io.*;
import net.openhft.lang.io.serialization.JDKObjectSerializer;
import net.openhft.lang.io.serialization.impl.VanillaBytesMarshallerFactory;
import net.openhft.lang.io.serialization.ObjectSerializer;
import net.openhft.lang.model.DataValueClasses;
import net.openhft.lang.threadlocal.Provider;
import net.openhft.lang.threadlocal.StatefulCopyable;
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.*;
import java.lang.reflect.Array;
@@ -51,6 +50,9 @@ import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import static java.lang.Class.forName;
import static java.lang.Long.numberOfTrailingZeros;
@@ -58,6 +60,8 @@ import static java.lang.Math.max;
import static java.lang.Thread.currentThread;
import static java.nio.ByteBuffer.allocateDirect;
import static net.openhft.chronicle.map.Asserts.assertNotNull;
import static net.openhft.chronicle.map.ChronicleMapBuilder.builtInType;
import static net.openhft.chronicle.map.ChronicleMapBuilder.offHeapReference;
import static net.openhft.lang.MemoryUnit.*;
class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
@@ -65,11 +69,10 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
implements ChronicleMap<K, V>, Serializable, ReadValue<V>, InstanceOrBytesToInstance,
GetValueInterops<V, VI, MVI> {
private static final Logger LOG = LoggerFactory.getLogger(VanillaChronicleMap.class);
// private static final Logger LOG = LoggerFactory.getLogger(VanillaChronicleMap.class);
/**
* Because DirectBitSet implementations couldn't find more than 64 continuous clear or set
* bits.
* Because DirectBitSet implementations couldn't find more than 64 continuous clear or set bits.
*/
static final int MAX_ENTRY_OVERSIZE_FACTOR = 64;
private static final long serialVersionUID = 2L;
@@ -105,6 +108,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
private final HashSplitting hashSplitting;
final boolean isNativeValueClass;
final MultiMapFactory multiMapFactory;
final int maxEntryOversizeFactor;
transient Provider<BytesReader<K>> keyReaderProvider;
transient Provider<KI> keyInteropProvider;
transient Provider<BytesReader<V>> valueReaderProvider;
@@ -113,7 +117,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
// non-final for close() and because it is initialized out of constructor
transient BytesStore ms;
transient long headerSize;
private transient Set<Map.Entry<K, V>> entrySet;
transient Set<Map.Entry<K, V>> entrySet;
public VanillaChronicleMap(AbstractChronicleMapBuilder<K, V, ?> builder) throws IOException {
@@ -156,6 +160,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
this.eventListener = builder.eventListener();
this.bytesEventListener = builder.bytesEventListener();
this.segmentHeaderSize = builder.segmentHeaderSize();
this.maxEntryOversizeFactor = builder.maxEntryOversizeFactor();
hashSplitting = HashSplitting.Splitting.forSegments(actualSegments);
initTransients();
@@ -551,7 +556,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
}
@Override
public <R> R mapForKey(K key, @NotNull Function<? super V, R> function) {
public <R> R getMapped(K key, @NotNull Function<? super V, R> function) {
try (ReadContext<K, V> entry = lookupUsing(key, null,
false, false, LockType.READ_LOCK)) {
return entry.present() ? function.apply(entry.value()) : null;
@@ -559,45 +564,58 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
}
@Override
public V putWith(K key, @NotNull Mutator<V> mutator) {
public V putMapped(K key, @NotNull UnaryOperator<V> unaryOperator) {
return (vClass.equals(CharSequence.class) || vClass.equals(StringBuilder.class))
? putMappedSB(key, unaryOperator)
: putMapped0(key, unaryOperator);
}
final V using = (vClass.equals(CharSequence.class)) ? (V) new StringBuilder() : null;
V putMappedSB(K key, @NotNull UnaryOperator<V> unaryOperator) {
try (WriteContext<K, V> entry = lookupUsing(key, using,
false, false, LockType.WRITE_LOCK)) {
StringBuilder usingSB = new StringBuilder("\uFFFF");
try (WriteContext<K, V> entry = lookupUsing(key, (V) usingSB,
false, true, LockType.WRITE_LOCK)) {
if (CharSequence.class.isAssignableFrom(vClass)) {
CharSequence value = (CharSequence) entry.value();
if (entry.value() == null || value.length() == 0)
return null;
usingSB = (StringBuilder) entry.value();
if (usingSB.length() == 1 && usingSB.charAt(0) == '\uFFFF')
return null;
V result = unaryOperator.update((V) usingSB);
if (usingSB != result) {
usingSB.setLength(0);
usingSB.append((CharSequence) result);
}
return result;
}
}
V putMapped0(K key, @NotNull UnaryOperator<V> unaryOperator) {
try (WriteContext<K, V> entry = lookupUsing(key, null,
false, true, LockType.WRITE_LOCK)) {
if (entry.value() == null)
return null;
V result = mutator.update(entry.value());
if (entry.value() instanceof StringBuilder) {
((StringBuilder) using).setLength(0);
((StringBuilder) using).append((CharSequence) result);
} else
((MutableLockedEntry) entry).value(result);
V result = unaryOperator.update(entry.value());
((MutableLockedEntry) entry).value(result);
return result;
}
}
@Override
public synchronized void getAll(File toFile) throws IOException {
final XStream xstream = new XStream(new JettisonMappedXmlDriver());
xstream.setMode(XStream.NO_REFERENCES);
xstream.alias("chronicle-entries", VanillaChronicleMap.EntrySet.class);
// ideally we will use java serialization if we can
lazyXStreamConverter().registerConverter(xstream);
try (FileOutputStream out = new FileOutputStream(toFile)) {
OutputStream outputStream = new FileOutputStream(toFile);
if (toFile.getName().toLowerCase().endsWith(".gz"))
outputStream = new GZIPOutputStream(outputStream);
try (OutputStream out = outputStream) {
xstream.toXML(entrySet(), out);
}
}
@@ -611,11 +629,44 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
// ideally we will use java serialization if we can
lazyXStreamConverter().registerConverter(xstream);
try (FileInputStream out = new FileInputStream(fromFile)) {
InputStream inputStream = new FileInputStream(fromFile);
if (fromFile.getName().toLowerCase().endsWith(".gz"))
inputStream = new GZIPInputStream(inputStream);
try (InputStream out = inputStream) {
xstream.fromXML(out);
}
}
@Override
public V newValueInstance() {
return newInstance(vClass, false);
}
@Override
public K newKeyInstance() {
return newInstance(kClass, true);
}
static <T> T newInstance(Class<T> interfaceClass, boolean isKey) {
if (interfaceClass.isEnum())
return isKey ? DataValueClasses.newDirectReference(interfaceClass)
: DataValueClasses.newDirectInstance(interfaceClass);
else if (!offHeapReference(interfaceClass) && !interfaceClass.isInterface() &&
!builtInType(interfaceClass)) {
// if (())
// interfaceClass = DataValueClasses.directClassFor(interfaceClass);
return DataValueClasses.newInstance(interfaceClass);
}
return DataValueClasses.newDirectInstance(interfaceClass);
}
private XStreamConverter xStreamConverter;
/**
@@ -1007,9 +1058,9 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
}
/**
* removes ( if there exists ) an entry from the map, if the {@param key} and {@param
* expectedValue} match that of a maps.entry. If the {@param expectedValue} equals null then (
* if there exists ) an entry whose key equals {@param key} this is removed.
* removes ( if there exists ) an entry from the map, if the {@param key} and {@param expectedValue} match that of a
* maps.entry. If the {@param expectedValue} equals null then ( if there exists ) an entry whose key equals {@param
* key} this is removed.
*
* @param k the key of the entry to remove
* @param expectedValue null if not required
@@ -1141,8 +1192,8 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
* replace the value in a map, only if the existing entry equals {@param expectedValue}
*
* @param key the key into the map
* @param expectedValue the expected existing value in the map ( could be null when we don't
* wish to do this check )
* @param expectedValue the expected existing value in the map ( could be null when we don't wish to do this check
* )
* @param newValue the new value you wish to store in the map
* @return the value that was replaced
*/
@@ -1427,7 +1478,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
*/
static final long LOCK_OFFSET = 0L; // 64-bit
static final long SIZE_OFFSET = LOCK_OFFSET + 8L; // 32-bit
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
final NativeBytes segmentHeader;
final NativeBytes bytes;
final long entriesOffset;
@@ -1468,11 +1519,11 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
private MultiMap createMultiMap(long start) {
final NativeBytes multiMapBytes =
new NativeBytes(new VanillaBytesMarshallerFactory(), start,
new NativeBytes((ObjectSerializer) null, start,
start = start + sizeOfMultiMap(), null);
final NativeBytes sizeOfMultiMapBitSetBytes =
new NativeBytes(new VanillaBytesMarshallerFactory(), start,
new NativeBytes((ObjectSerializer) null, start,
start + sizeOfMultiMapBitSet(), null);
// multiMapBytes.load();
return multiMapFactory.create(multiMapBytes, sizeOfMultiMapBitSetBytes);
@@ -1516,7 +1567,16 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
public final ReadLocked<K, KI, MKI, V, VI, MVI> readLock(
@Nullable SegmentState segmentState) {
while (true) {
final boolean success = segmentHeader.tryRWReadLock(LOCK_OFFSET, lockTimeOutNS);
// final boolean success = segmentHeader.tryRWReadLock(LOCK_OFFSET, lockTimeOutNS);
final boolean success = segmentHeader.tryRWWriteLock(LOCK_OFFSET, lockTimeOutNS);
/*
boolean success = false;
try {
success = lock.readLock().tryLock(lockTimeOutNS, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
*/
if (success) {
if (segmentState != null) {
return segmentState.readLocked(this);
@@ -1542,6 +1602,14 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
startWriteLock = System.nanoTime();
while (true) {
final boolean success = segmentHeader.tryRWWriteLock(LOCK_OFFSET, lockTimeOutNS);
/*
boolean success = false;
try {
success = lock.writeLock().tryLock(lockTimeOutNS, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
*/
if (success) {
if (segmentState != null) {
if (isNativeValueClass) {
@@ -1567,7 +1635,9 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
@Override
public final void readUnlock() {
try {
segmentHeader.unlockRWReadLock(LOCK_OFFSET);
// segmentHeader.unlockRWReadLock(LOCK_OFFSET);
segmentHeader.unlockRWWriteLock(LOCK_OFFSET);
// lock.readLock().unlock();
} catch (IllegalMonitorStateException e) {
errorListener.errorOnUnlock(e);
}
@@ -1577,6 +1647,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
public final void writeUnlock() {
try {
segmentHeader.unlockRWWriteLock(LOCK_OFFSET);
// lock.writeLock().unlock();
} catch (IllegalMonitorStateException e) {
errorListener.errorOnUnlock(e);
}
@@ -1873,7 +1944,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
}
// putValue may relocate entry and change offset
putValue(pos, offset, entry, valueSizePos, entryEndAddr, copies, segmentState,
putValue(pos, offset, entry, valueSizePos, entryEndAddr, segmentState,
metaValueInterop, valueInterop, value, valueSize, searchedHashLookup);
// put callbacks
@@ -1897,9 +1968,9 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
}
/**
* Returns value size, writes the entry (key, value, sizes) to the entry, after this method
* call entry positioned after value bytes written (i. e. at the end of entry), sets entry
* position (in segment) and value size position in the given segmentState
* Returns value size, writes the entry (key, value, sizes) to the entry, after this method call entry
* positioned after value bytes written (i. e. at the end of entry), sets entry position (in segment) and value
* size position in the given segmentState
*/
final <KB, KBI, MKBI extends MetaBytesInterop<KB, ? super KBI>, E, EW>
long putEntry(SegmentState segmentState,
@@ -1942,9 +2013,9 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
//TODO refactor/optimize
private long alloc(int blocks) {
if (blocks > MAX_ENTRY_OVERSIZE_FACTOR)
if (blocks > maxEntryOversizeFactor)
throw new IllegalArgumentException("Entry is too large: requires " + blocks +
" entry size chucks, " + MAX_ENTRY_OVERSIZE_FACTOR + " is maximum.");
" entry size chucks, " + maxEntryOversizeFactor + " is maximum.");
long ret = freeList.setNextNContinuousClearBits(nextPosToSearchFrom, blocks);
if (ret == DirectBitSet.NOT_FOUND || ret + blocks > entriesPerSegment) {
if (ret + blocks > entriesPerSegment)
@@ -2023,10 +2094,9 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
}
/**
* - if expectedValue is not null, returns Boolean.TRUE (removed) or Boolean.FALSE (entry
* not found), regardless the expectedValue object is Bytes instance (RPC call) or the value
* instance - if expectedValue is null: - if resultUnused is false, null or removed value is
* returned - if resultUnused is true, null is always returned
* - if expectedValue is not null, returns Boolean.TRUE (removed) or Boolean.FALSE (entry not found), regardless
* the expectedValue object is Bytes instance (RPC call) or the value instance - if expectedValue is null: - if
* resultUnused is false, null or removed value is returned - if resultUnused is true, null is always returned
*/
<KB, KBI, MKBI extends MetaBytesInterop<KB, ? super KBI>,
RV, VB extends RV, VBI, MVBI extends MetaBytesInterop<? super VB, ? super VBI>>
@@ -2170,9 +2240,8 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
}
/**
* Replaces the specified value for the key with the given value. {@code newValue} is set
* only if the existing value corresponding to the specified key is equal to {@code
* expectedValue} or {@code expectedValue == null}.
* Replaces the specified value for the key with the given value. {@code newValue} is set only if the existing
* value corresponding to the specified key is equal to {@code expectedValue} or {@code expectedValue == null}.
*
* @param hash2 a hash code related to the {@code keyBytes}
* @return the replaced value or {@code null} if the value was not replaced
@@ -2252,7 +2321,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
MVBI metaValueInterop = getNewValueInterops.getMetaValueInterop(
copies, valueInterop, newValue);
long newValueSize = metaValueInterop.size(valueInterop, newValue);
putValue(pos, offset, entry, valueSizePos, entryEndAddr, copies, segmentState,
putValue(pos, offset, entry, valueSizePos, entryEndAddr, segmentState,
metaValueInterop, valueInterop, newValue, newValueSize, searchedHashLookup);
// put callbacks
@@ -2270,21 +2339,19 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
}
/**
* Replaces value in existing entry. May cause entry relocation, because there may be not
* enough space for new value in location already allocated for this entry.
* Replaces value in existing entry. May cause entry relocation, because there may be not enough space for new
* value in location already allocated for this entry.
*
* @param pos index of the first block occupied by the entry
* @param offset relative offset of the entry in Segment bytes (before, i. e.
* including metaData)
* @param offset relative offset of the entry in Segment bytes (before, i. e. including metaData)
* @param entry relative pointer in Segment bytes
* @param valueSizePos relative position of value size in entry
* @param entryEndAddr absolute address of the entry end
* @return relative offset of the entry in Segment bytes after putting value (that may cause
* entry relocation)
* @return relative offset of the entry in Segment bytes after putting value (that may cause entry relocation)
*/
final <E, EW> long putValue(
long pos, long offset, MultiStoreBytes entry, long valueSizePos, long entryEndAddr,
ThreadLocalCopies copies, SegmentState segmentState,
SegmentState segmentState,
MetaBytesWriter<E, ? super EW> metaElemWriter, EW elemWriter, E newElem,
long newElemSize,
MultiMap searchedHashLookup) {
@@ -2299,10 +2366,10 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
int oldSizeInBlocks = inBlocks(oldEntrySize);
int newSizeInBlocks = inBlocks(newEntryEndAddr - entryStartAddr);
if (newSizeInBlocks > oldSizeInBlocks) {
if (newSizeInBlocks > MAX_ENTRY_OVERSIZE_FACTOR) {
if (newSizeInBlocks > maxEntryOversizeFactor) {
throw new IllegalArgumentException("Value too large: " +
"entry takes " + newSizeInBlocks + " blocks, " +
MAX_ENTRY_OVERSIZE_FACTOR + " is maximum.");
maxEntryOversizeFactor + " is maximum.");
}
if (realloc(pos, oldSizeInBlocks, newSizeInBlocks))
break newValueDoesNotFit;
@@ -2631,7 +2698,6 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
private K key;
private V value;
boolean present;
MutableLockedEntry(SegmentState segmentState) {
this.segmentState = segmentState;
@@ -2650,7 +2716,6 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
}
void value(V value) {
this.present = value != null;
this.value = value;
}
@@ -2676,7 +2741,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super KI>,
* @return if the value is not null
*/
public boolean present() {
return present;
return value() != null;
}
}
@@ -2,6 +2,7 @@ package net.openhft.chronicle.map;
import net.openhft.lang.io.serialization.impl.*;
import net.openhft.lang.values.*;
import org.junit.Ignore;
import org.junit.Test;
import java.nio.ByteBuffer;
@@ -18,8 +19,8 @@ import static org.junit.Assert.*;
public class CHMUseCasesTest {
/**
* String is not as efficient as CharSequence as a key or value but easier to use The key can
* only be on heap and variable length serialised.
* String is not as efficient as CharSequence as a key or value but easier to use The key can only be on heap and
* variable length serialised.
*/
@Test
public void testStringStringMap() throws ExecutionException, InterruptedException {
@@ -32,19 +33,18 @@ public class CHMUseCasesTest {
try (ChronicleMap<String, String> map = chmb.create()) {
*/
try (ChronicleMap<String, String> map = ChronicleMapBuilder
.of(String.class, String.class)
.checkSerializedValues() // for testing purposes only
.of(String.class, String.class) // for testing purposes only
.create()) {
map.put("Hello", "World");
assertEquals("World", map.get("Hello"));
assertEquals("New World", map.mapForKey("Hello", new Function<String, String>() {
assertEquals("New World", map.getMapped("Hello", new Function<String, String>() {
@Override
public String apply(String s) {
return "New " + s;
}
}));
assertEquals(null, map.mapForKey("No key", new Function<String, String>() {
assertEquals(null, map.getMapped("No key", new Function<String, String>() {
@Override
public String apply(String s) {
return "New " + s;
@@ -67,32 +67,29 @@ public class CHMUseCasesTest {
try (ChronicleMap<String, String> map = chmb.create()) {
*/
try (ChronicleMap<String, String> map = ChronicleMapBuilder
.of(String.class, String.class)
.checkSerializedValues() // for testing purposes only
.of(String.class, String.class) // for testing purposes only
.create()) {
map.put("Hello", "World");
map.putWith("Hello", new Mutator<String>() {
map.putMapped("Hello", new UnaryOperator<String>() {
@Override
public String update(String s) {
return "New " + s;
}
});
}
}
/**
* CharSequence is more efficient when object creation is avoided. The key can only be on heap
* and variable length serialised.
* CharSequence is more efficient when object creation is avoided. The key can only be on heap and variable length
* serialised.
*/
@Test
public void testCharSequenceCharSequenceMap() throws ExecutionException, InterruptedException {
try (ChronicleMap<CharSequence, CharSequence> map = ChronicleMapBuilder
.of(CharSequence.class, CharSequence.class)
.checkSerializedValues() // for testing purposes only
.of(CharSequence.class, CharSequence.class) // for testing purposes only
.defaultValue("")
.create()) {
map.put("Hello", "World");
StringBuilder key = new StringBuilder();
@@ -109,14 +106,14 @@ public class CHMUseCasesTest {
assertNull(map.getUsing(key, value));
assertEquals("New World", map.mapForKey("Hello", new
assertEquals("New World", map.getMapped("Hello", new
Function<CharSequence, CharSequence>() {
@Override
public CharSequence apply(CharSequence s) {
return "New " + s;
}
}));
assertEquals(null, map.mapForKey("No key", new
assertEquals(null, map.getMapped("No key", new
Function<CharSequence, CharSequence>() {
@Override
public CharSequence apply(CharSequence s) {
@@ -124,8 +121,8 @@ public class CHMUseCasesTest {
}
}));
assertEquals("New World !!", map.putWith("Hello", new
Mutator<CharSequence>() {
assertEquals("New World !!", map.putMapped("Hello", new
UnaryOperator<CharSequence>() {
@Override
public CharSequence update(CharSequence s) {
((StringBuilder) s).append(" !!");
@@ -135,8 +132,8 @@ public class CHMUseCasesTest {
assertEquals("New World !!", map.get("Hello").toString());
assertEquals(null, map.putWith("no-key", new
Mutator<CharSequence>() {
assertEquals("New !!", map.putMapped("no-key", new
UnaryOperator<CharSequence>() {
@Override
public CharSequence update(CharSequence s) {
((StringBuilder) s).append("!!");
@@ -153,13 +150,12 @@ public class CHMUseCasesTest {
@Test
public void testStringValueStringValueMap() {
try (ChronicleMap<StringValue, StringValue> map = ChronicleMapBuilder
.of(StringValue.class, StringValue.class)
.checkSerializedValues() // for testing purposes only
.of(StringValue.class, StringValue.class) // for testing purposes only
.create()) {
StringValue key1 = ChronicleMapBuilder.newInstance(StringValue.class, true);
StringValue key2 = ChronicleMapBuilder.newInstance(StringValue.class, true);
StringValue value1 = ChronicleMapBuilder.newInstance(StringValue.class, false);
StringValue value2 = ChronicleMapBuilder.newInstance(StringValue.class, false);
StringValue key1 = map.newKeyInstance();
StringValue key2 = map.newKeyInstance();
StringValue value1 = map.newValueInstance();
StringValue value2 = map.newValueInstance();
key1.setValue(new StringBuilder("1"));
value1.setValue("11");
@@ -246,7 +242,7 @@ public class CHMUseCasesTest {
try (ChronicleMap<Integer, Integer> map = ChronicleMapBuilder
.of(Integer.class, Integer.class)
.entrySize(8)
.disableOversizedEntries(true) // disabled for testing purposes only.
.disableOversizedEntries() // disabled for testing purposes only.
.create()) {
Integer key1;
Integer key2;
@@ -268,13 +264,13 @@ public class CHMUseCasesTest {
assertEquals(null, map.get(3));
assertEquals(null, map.get(4));
assertEquals((Integer) 110, map.mapForKey(1, new Function<Integer, Integer>() {
assertEquals((Integer) 110, map.getMapped(1, new Function<Integer, Integer>() {
@Override
public Integer apply(Integer s) {
return 10 * s;
}
}));
assertEquals(null, map.mapForKey(-1, new Function<Integer, Integer>() {
assertEquals(null, map.getMapped(-1, new Function<Integer, Integer>() {
@Override
public Integer apply(Integer s) {
return 10 * s;
@@ -282,7 +278,7 @@ public class CHMUseCasesTest {
}));
try {
map.putWith(1, new Mutator<Integer>() {
map.putMapped(1, new UnaryOperator<Integer>() {
@Override
public Integer update(Integer s) {
return s + 1;
@@ -300,7 +296,7 @@ public class CHMUseCasesTest {
try (ChronicleMap<Long, Long> map = ChronicleMapBuilder
.of(Long.class, Long.class)
.entrySize(16)
.disableOversizedEntries(true) // disabled for testing purposes only.
.disableOversizedEntries() // disabled for testing purposes only.
.create()) {
map.put(1L, 11L);
assertEquals((Long) 11L, map.get(1L));
@@ -311,13 +307,13 @@ public class CHMUseCasesTest {
assertEquals(null, map.get(3L));
assertEquals(null, map.get(4L));
assertEquals((Long) 110L, map.mapForKey(1L, new Function<Long, Long>() {
assertEquals((Long) 110L, map.getMapped(1L, new Function<Long, Long>() {
@Override
public Long apply(Long s) {
return 10 * s;
}
}));
assertEquals(null, map.mapForKey(-1L, new Function<Long, Long>() {
assertEquals(null, map.getMapped(-1L, new Function<Long, Long>() {
@Override
public Long apply(Long s) {
return 10 * s;
@@ -325,7 +321,7 @@ public class CHMUseCasesTest {
}));
try {
map.putWith(1L, new Mutator<Long>() {
map.putMapped(1L, new UnaryOperator<Long>() {
@Override
public Long update(Long s) {
return s + 1;
@@ -342,7 +338,7 @@ public class CHMUseCasesTest {
public void testDoubleDoubleMap() throws ExecutionException, InterruptedException {
try (ChronicleMap<Double, Double> map = ChronicleMapBuilder
.of(Double.class, Double.class)
.disableOversizedEntries(true) // disabled for testing purposes only.
.disableOversizedEntries() // disabled for testing purposes only.
.entrySize(16)
.create()) {
map.put(1.0, 11.0);
@@ -354,13 +350,13 @@ public class CHMUseCasesTest {
assertEquals(null, map.get(3.0));
assertEquals(null, map.get(4.0));
assertEquals((Double) 110.0, map.mapForKey(1.0, new Function<Double, Double>() {
assertEquals((Double) 110.0, map.getMapped(1.0, new Function<Double, Double>() {
@Override
public Double apply(Double s) {
return 10 * s;
}
}));
assertEquals(null, map.mapForKey(-1.0, new Function<Double, Double>() {
assertEquals(null, map.getMapped(-1.0, new Function<Double, Double>() {
@Override
public Double apply(Double s) {
return 10 * s;
@@ -368,7 +364,7 @@ public class CHMUseCasesTest {
}));
try {
map.putWith(1.0, new Mutator<Double>() {
map.putMapped(1.0, new UnaryOperator<Double>() {
@Override
public Double update(Double s) {
return s + 1;
@@ -386,7 +382,7 @@ public class CHMUseCasesTest {
public void testByteArrayByteArrayMap() throws ExecutionException, InterruptedException {
try (ChronicleMap<byte[], byte[]> map = ChronicleMapBuilder
.of(byte[].class, byte[].class)
.disableOversizedEntries(true) // disabled for testing purposes only.
.disableOversizedEntries() // disabled for testing purposes only.
.entrySize(12)
.create()) {
byte[] key1 = {1, 1, 1, 1};
@@ -401,20 +397,20 @@ public class CHMUseCasesTest {
map.put(key1, value1);
assertTrue(Arrays.equals(new byte[]{11, 11}, map.mapForKey(key1, new Function<byte[], byte[]>() {
assertTrue(Arrays.equals(new byte[]{11, 11}, map.getMapped(key1, new Function<byte[], byte[]>() {
@Override
public byte[] apply(byte[] s) {
return Arrays.copyOf(s, 2);
}
})));
assertEquals(null, map.mapForKey(key2, new Function<byte[], byte[]>() {
assertEquals(null, map.getMapped(key2, new Function<byte[], byte[]>() {
@Override
public byte[] apply(byte[] s) {
return Arrays.copyOf(s, 2);
}
}));
assertTrue(Arrays.equals(new byte[]{12, 10}, map.putWith(key1, new Mutator<byte[]>() {
assertTrue(Arrays.equals(new byte[]{12, 10}, map.putMapped(key1, new UnaryOperator<byte[]>() {
@Override
public byte[] update(byte[] s) {
s[0]++;
@@ -434,10 +430,11 @@ public class CHMUseCasesTest {
public void testByteBufferByteBufferMap() throws ExecutionException, InterruptedException {
try (ChronicleMap<ByteBuffer, ByteBuffer> map = ChronicleMapBuilder
.of(ByteBuffer.class, ByteBuffer.class)
.valueMarshaller(ByteBufferMarshaller.INSTANCE)
.keyMarshaller(ByteBufferMarshaller.INSTANCE)
.disableOversizedEntries(true) // disabled for testing purposes only.
.entrySize(20)
.valueMarshaller(ByteBufferMarshaller.INSTANCE)
.disableOversizedEntries() // disabled for testing purposes only.
// TODO does this have to be 14 bytes?
.entrySize(14)
.create()) {
ByteBuffer key1 = ByteBuffer.wrap(new byte[]{1, 1, 1, 1});
ByteBuffer key2 = ByteBuffer.wrap(new byte[]{2, 2, 2, 2});
@@ -458,10 +455,10 @@ public class CHMUseCasesTest {
};
map.put(key1, value1);
assertBBEquals(ByteBuffer.wrap(new byte[]{11, 11}), map.mapForKey(key1, function));
assertEquals(null, map.mapForKey(key2, function));
assertBBEquals(ByteBuffer.wrap(new byte[]{11, 11}), map.getMapped(key1, function));
assertEquals(null, map.getMapped(key2, function));
assertBBEquals(ByteBuffer.wrap(new byte[]{12, 10}), map.putWith(key1, new Mutator<ByteBuffer>() {
assertBBEquals(ByteBuffer.wrap(new byte[]{12, 10}), map.putMapped(key1, new UnaryOperator<ByteBuffer>() {
@Override
public ByteBuffer update(ByteBuffer s) {
s.put(0, (byte) (s.get(0) + 1));
@@ -510,7 +507,6 @@ public class CHMUseCasesTest {
try (WriteContext wc = map.acquireUsingLocked(key1, valueB)) {
assertBBEquals(value1, valueB);
appendMode(valueB);
valueB.putShort((short) 12345);
@@ -522,7 +518,7 @@ public class CHMUseCasesTest {
ByteBuffer bb1 = ByteBuffer.allocate(8);
bb1.put(value1);
bb1.putShort((short)12345);
bb1.putShort((short) 12345);
bb1.flip();
assertBBEquals(bb1, valueA);
}
@@ -543,7 +539,7 @@ public class CHMUseCasesTest {
.of(ByteBuffer.class, ByteBuffer.class)
.valueMarshaller(ByteBufferMarshaller.INSTANCE) // we should not have to to this !
.keyMarshaller(ByteBufferMarshaller.INSTANCE) // we should not have to to this !
.disableOversizedEntries(true) // disabled for testing purposes only.
.disableOversizedEntries() // disabled for testing purposes only.
.entrySize(12)
.create()) {
ByteBuffer key1 = ByteBuffer.wrap(new byte[]{1, 1, 1, 1});
@@ -568,10 +564,10 @@ public class CHMUseCasesTest {
return slice;
}
};
assertBBEquals(ByteBuffer.wrap(new byte[]{11, 11}), map.mapForKey(key1, function));
assertEquals(null, map.mapForKey(key2, function));
assertBBEquals(ByteBuffer.wrap(new byte[]{11, 11}), map.getMapped(key1, function));
assertEquals(null, map.getMapped(key2, function));
assertBBEquals(ByteBuffer.wrap(new byte[]{12, 10}), map.putWith(key1, new Mutator<ByteBuffer>() {
assertBBEquals(ByteBuffer.wrap(new byte[]{12, 10}), map.putMapped(key1, new UnaryOperator<ByteBuffer>() {
@Override
public ByteBuffer update(ByteBuffer s) {
s.put(0, (byte) (s.get(0) + 1));
@@ -595,13 +591,18 @@ public class CHMUseCasesTest {
public void testIntValueIntValueMap() {
try (ChronicleMap<IntValue, IntValue> map = ChronicleMapBuilder
.of(IntValue.class, IntValue.class)
.disableOversizedEntries(true) // disabled for testing purposes only.
.disableOversizedEntries() // disabled for testing purposes only.
.entrySize(8)
.create()) {
IntValue key1 = ChronicleMapBuilder.newInstance(IntValue.class, false);
IntValue key2 = ChronicleMapBuilder.newInstance(IntValue.class, false);
IntValue value1 = ChronicleMapBuilder.newInstance(IntValue.class, false);
IntValue value2 = ChronicleMapBuilder.newInstance(IntValue.class, false);
IntValue key1 = map.newKeyInstance();
IntValue key2 = map.newKeyInstance();
IntValue value1 = map.newValueInstance();
IntValue value2 = map.newValueInstance();
key1.setValue(1);
value1.setValue(11);
@@ -670,6 +671,26 @@ public class CHMUseCasesTest {
}
}
@Test
@Ignore("Generated code creates a field too large ie. it ignores the @Range")
public void testUnsignedIntValueUnsignedIntValueMapEntrySize() {
// TODO once this is working, merge the next test.
try (ChronicleMap<UnsignedIntValue, UnsignedIntValue> map = ChronicleMapBuilder
.of(UnsignedIntValue.class, UnsignedIntValue.class)
.disableOversizedEntries() // disabled for testing purposes only.
.entrySize(8)
.create()) {
UnsignedIntValue key1 = map.newKeyInstance();
UnsignedIntValue value1 = map.newValueInstance();
key1.setValue(1);
value1.setValue(11);
map.put(key1, value1);
assertEquals(value1, map.get(key1));
}
}
/**
* For unsigned int -> unsigned int entries, the key can be on heap or off heap.
*/
@@ -677,13 +698,14 @@ public class CHMUseCasesTest {
public void testUnsignedIntValueUnsignedIntValueMap() {
try (ChronicleMap<UnsignedIntValue, UnsignedIntValue> map = ChronicleMapBuilder
.of(UnsignedIntValue.class, UnsignedIntValue.class)
.disableOversizedEntries(true) // disabled for testing purposes only.
.entrySize(8)
.create()) {
UnsignedIntValue key1 = ChronicleMapBuilder.newInstance(UnsignedIntValue.class, true);
UnsignedIntValue key2 = ChronicleMapBuilder.newInstance(UnsignedIntValue.class, true);
UnsignedIntValue value1 = ChronicleMapBuilder.newInstance(UnsignedIntValue.class, false);
UnsignedIntValue value2 = ChronicleMapBuilder.newInstance(UnsignedIntValue.class, false);
UnsignedIntValue key1 = map.newKeyInstance();
UnsignedIntValue key2 = map.newKeyInstance();
UnsignedIntValue value1 = map.newValueInstance();
UnsignedIntValue value2 = map.newValueInstance();
key1.setValue(1);
value1.setValue(11);
@@ -759,13 +781,13 @@ public class CHMUseCasesTest {
public void testIntValueShortValueMap() {
try (ChronicleMap<IntValue, ShortValue> map = ChronicleMapBuilder
.of(IntValue.class, ShortValue.class)
.disableOversizedEntries(true) // disabled for testing purposes only.
.disableOversizedEntries() // disabled for testing purposes only.
.entrySize(6)
.create()) {
IntValue key1 = ChronicleMapBuilder.newInstance(IntValue.class, false);
IntValue key2 = ChronicleMapBuilder.newInstance(IntValue.class, false);
ShortValue value1 = ChronicleMapBuilder.newInstance(ShortValue.class, false);
ShortValue value2 = ChronicleMapBuilder.newInstance(ShortValue.class, false);
IntValue key1 = map.newKeyInstance();
IntValue key2 = map.newKeyInstance();
ShortValue value1 = map.newValueInstance();
ShortValue value2 = map.newValueInstance();
key1.setValue(1);
value1.setValue((short) 11);
@@ -842,12 +864,13 @@ public class CHMUseCasesTest {
try (ChronicleMap<IntValue, UnsignedShortValue> map = ChronicleMapBuilder
.of(IntValue.class, UnsignedShortValue.class)
.entrySize(6)
.disableOversizedEntries(true) // disabled for testing purposes only.
.disableOversizedEntries() // disabled for testing purposes only.
.create()) {
IntValue key1 = ChronicleMapBuilder.newInstance(IntValue.class, false);
IntValue key2 = ChronicleMapBuilder.newInstance(IntValue.class, false);
UnsignedShortValue value1 = ChronicleMapBuilder.newInstance(UnsignedShortValue.class, false);
UnsignedShortValue value2 = ChronicleMapBuilder.newInstance(UnsignedShortValue.class, false);
IntValue key1 = map.newKeyInstance();
IntValue key2 = map.newKeyInstance();
UnsignedShortValue value1 = map.newValueInstance();
UnsignedShortValue value2 = map.newValueInstance();
key1.setValue(1);
value1.setValue(11);
@@ -923,13 +946,14 @@ public class CHMUseCasesTest {
public void testIntValueCharValueMap() {
try (ChronicleMap<IntValue, CharValue> map = ChronicleMapBuilder
.of(IntValue.class, CharValue.class)
.disableOversizedEntries(true) // disabled for testing purposes only.
.disableOversizedEntries() // disabled for testing purposes only.
.entrySize(6)
.create()) {
IntValue key1 = ChronicleMapBuilder.newInstance(IntValue.class, false);
IntValue key2 = ChronicleMapBuilder.newInstance(IntValue.class, false);
CharValue value1 = ChronicleMapBuilder.newInstance(CharValue.class, false);
CharValue value2 = ChronicleMapBuilder.newInstance(CharValue.class, false);
IntValue key1 = map.newKeyInstance();
IntValue key2 = map.newKeyInstance();
CharValue value1 = map.newValueInstance();
CharValue value2 = map.newValueInstance();
key1.setValue(1);
value1.setValue((char) 11);
@@ -1006,12 +1030,16 @@ public class CHMUseCasesTest {
try (ChronicleMap<IntValue, UnsignedByteValue> map = ChronicleMapBuilder
.of(IntValue.class, UnsignedByteValue.class)
.entrySize(5)
.disableOversizedEntries(true) // disabled for testing purposes only.
.disableOversizedEntries() // disabled for testing purposes only.
.create()) {
IntValue key1 = ChronicleMapBuilder.newInstance(IntValue.class, false);
IntValue key2 = ChronicleMapBuilder.newInstance(IntValue.class, false);
UnsignedByteValue value1 = ChronicleMapBuilder.newInstance(UnsignedByteValue.class, false);
UnsignedByteValue value2 = ChronicleMapBuilder.newInstance(UnsignedByteValue.class, false);
IntValue key1 = map.newKeyInstance();
IntValue key2 = map.newKeyInstance();
UnsignedByteValue value1 = map.newValueInstance();
UnsignedByteValue value2 = map.newValueInstance();
key1.setValue(1);
value1.setValue(11);
@@ -1087,13 +1115,17 @@ public class CHMUseCasesTest {
public void testIntValueBooleanValueMap() {
try (ChronicleMap<IntValue, BooleanValue> map = ChronicleMapBuilder
.of(IntValue.class, BooleanValue.class)
.disableOversizedEntries(true) // disabled for testing purposes only.
.disableOversizedEntries() // disabled for testing purposes only.
.entrySize(5)
.create()) {
IntValue key1 = ChronicleMapBuilder.newInstance(IntValue.class, false);
IntValue key2 = ChronicleMapBuilder.newInstance(IntValue.class, false);
BooleanValue value1 = ChronicleMapBuilder.newInstance(BooleanValue.class, false);
BooleanValue value2 = ChronicleMapBuilder.newInstance(BooleanValue.class, false);
IntValue key1 = map.newKeyInstance();
IntValue key2 = map.newKeyInstance();
BooleanValue value1 = map.newValueInstance();
BooleanValue value2 = map.newValueInstance();
key1.setValue(1);
value1.setValue(true);
@@ -1170,12 +1202,14 @@ public class CHMUseCasesTest {
try (ChronicleMap<FloatValue, FloatValue> map = ChronicleMapBuilder
.of(FloatValue.class, FloatValue.class)
.entrySize(8)
.disableOversizedEntries(true) // disabled for testing purposes only.
.disableOversizedEntries() // disabled for testing purposes only.
.create()) {
FloatValue key1 = ChronicleMapBuilder.newInstance(FloatValue.class, false);
FloatValue key2 = ChronicleMapBuilder.newInstance(FloatValue.class, false);
FloatValue value1 = ChronicleMapBuilder.newInstance(FloatValue.class, false);
FloatValue value2 = ChronicleMapBuilder.newInstance(FloatValue.class, false);
FloatValue key1 = map.newKeyInstance();
FloatValue key2 = map.newKeyInstance();
FloatValue value1 = map.newValueInstance();
FloatValue value2 = map.newValueInstance();
key1.setValue(1);
value1.setValue(11);
@@ -1254,10 +1288,10 @@ public class CHMUseCasesTest {
.entrySize(16)
.create()) {
DoubleValue key1 = ChronicleMapBuilder.newInstance(DoubleValue.class, false);
DoubleValue key2 = ChronicleMapBuilder.newInstance(DoubleValue.class, false);
DoubleValue value1 = ChronicleMapBuilder.newInstance(DoubleValue.class, false);
DoubleValue value2 = ChronicleMapBuilder.newInstance(DoubleValue.class, false);
DoubleValue key1 = map.newKeyInstance();
DoubleValue key2 = map.newKeyInstance();
DoubleValue value1 = map.newValueInstance();
DoubleValue value2 = map.newValueInstance();
key1.setValue(1);
@@ -1337,12 +1371,14 @@ public class CHMUseCasesTest {
try (ChronicleMap<LongValue, LongValue> map = ChronicleMapBuilder
.of(LongValue.class, LongValue.class)
.entrySize(16)
.disableOversizedEntries(true) // disabled for testing purposes only.
.disableOversizedEntries() // disabled for testing purposes only.
.create()) {
LongValue key1 = ChronicleMapBuilder.newInstance(LongValue.class, false);
LongValue key2 = ChronicleMapBuilder.newInstance(LongValue.class, false);
LongValue value1 = ChronicleMapBuilder.newInstance(LongValue.class, false);
LongValue value2 = ChronicleMapBuilder.newInstance(LongValue.class, false);
LongValue key1 = map.newKeyInstance();
LongValue key2 = map.newKeyInstance();
LongValue value1 = map.newValueInstance();
LongValue value2 = map.newValueInstance();
key1.setValue(1);
@@ -27,7 +27,7 @@ package net.openhft.chronicle.map;
/*import junit.framework.Test;
import junit.framework.TestSuite;*/
import net.openhft.chronicle.map.jrs166.JSR166TestCase;
import net.openhft.chronicle.map.jsr166.JSR166TestCase;
import java.util.concurrent.ConcurrentMap;
@@ -26,36 +26,39 @@ import org.junit.Test;
import java.beans.XMLEncoder;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.*;
/**
* Created by peter on 06/12/14.
*/
public class LargeEntriesTest {
static final int ENTRIES = 640;
static final int ENTRY_SIZE = 1024;
@Test
@Ignore
public void testLargeStrings() throws ExecutionException, InterruptedException {
public void testLargeStrings() throws ExecutionException, InterruptedException, IOException {
final int ENTRIES = 250;
final int ENTRY_SIZE = 100 * 1024;
File file = File.createTempFile("largeEntries", ".deleteme");
file.deleteOnExit();
final ChronicleMap<String, String> map = ChronicleMapBuilder
.of(String.class, String.class)
.valueMarshaller(SnappyStringMarshaller.INSTANCE)
.actualSegments(1) // to force an error.
.entries(ENTRIES * 2)
.entrySize(ENTRY_SIZE / 4)
.entries(ENTRIES)
.entrySize(ENTRY_SIZE / 6)
.putReturnsNull(true)
.create();
.createPersistedTo(file);
{
int threads = 2; //Runtime.getRuntime().availableProcessors();
warmUpCompression(ENTRY_SIZE);
int threads = 4; //Runtime.getRuntime().availableProcessors();
ExecutorService es = Executors.newFixedThreadPool(threads);
final int block = ENTRIES / threads;
for (int i = 0; i < 3; i++) {
@@ -63,11 +66,10 @@ public class LargeEntriesTest {
List<Future<?>> futureList = new ArrayList<>();
for (int t = 0; t < threads; t++) {
final int finalT = t;
final int finalI = i;
futureList.add(es.submit(new Runnable() {
@Override
public void run() {
exerciseLargeStrings(map, finalI, finalT * block, finalT * block + block, ENTRY_SIZE);
exerciseLargeStrings(map, finalT * block, finalT * block + block, ENTRY_SIZE);
}
}));
}
@@ -84,7 +86,70 @@ public class LargeEntriesTest {
}
}
void exerciseLargeStrings(ChronicleMap<String, String> map, int run, int start, int finish, int entrySize) {
private void warmUpCompression(int entrySize) {
String value = generateValue(entrySize);
DirectBytes bytes = DirectStore.allocate(entrySize / 6).bytes();
for (int i = 0; i < 5; i++) {
// warmup to compression.
bytes.clear();
SnappyStringMarshaller.INSTANCE.write(bytes, value);
bytes.flip();
SnappyStringMarshaller.INSTANCE.read(bytes);
}
bytes.release();
}
@Test
@Ignore
public void testLargeStringsPerf() throws ExecutionException, InterruptedException, IOException {
doLargeEntryPerf(10000, 100 * 1024);
doLargeEntryPerf(100000, 10 * 1024);
doLargeEntryPerf(10000, 100 * 1024);
doLargeEntryPerf(3000, 1024 * 1024);
}
private void doLargeEntryPerf(int ENTRIES, final int ENTRY_SIZE) throws IOException, InterruptedException, ExecutionException {
System.out.printf("Testing %,d entries of %,d KB%n", ENTRIES, ENTRY_SIZE);
File file = File.createTempFile("largeEntries", ".deleteme");
file.deleteOnExit();
final ChronicleMap<String, String> map = ChronicleMapBuilder
.of(String.class, String.class)
.valueMarshaller(SnappyStringMarshaller.INSTANCE)
.entries(ENTRIES * 2)
.entrySize(ENTRY_SIZE / 6)
.putReturnsNull(true)
.createPersistedTo(file);
{
warmUpCompression(ENTRY_SIZE);
int threads = Runtime.getRuntime().availableProcessors();
ExecutorService es = Executors.newFixedThreadPool(threads);
final int block = ENTRIES / threads;
for (int i = 0; i < 3; i++) {
long start = System.currentTimeMillis();
List<Future<?>> futureList = new ArrayList<>();
for (int t = 0; t < threads; t++) {
final int finalT = t;
futureList.add(es.submit(new Runnable() {
@Override
public void run() {
exerciseLargeStrings(map, finalT * block, finalT * block + block, ENTRY_SIZE);
}
}));
}
for (Future<?> future : futureList) {
future.get();
}
long time = System.currentTimeMillis() - start;
long operations = 3;
System.out.printf("Put/Get rate was %.1f MB/s%n", operations * ENTRIES * ENTRY_SIZE / 1e6 / (time / 1e3));
}
es.shutdown();
if (es.isTerminated())
map.close();
}
}
void exerciseLargeStrings(ChronicleMap<String, String> map, int start, int finish, int entrySize) {
/*
final Thread thisThread = Thread.currentThread();
Thread monitor = new Thread(new Runnable() {
@@ -107,28 +172,15 @@ public class LargeEntriesTest {
});
monitor.start();
*/
ByteArrayOutputStream baos = new ByteArrayOutputStream();
XMLEncoder xml = new XMLEncoder(baos);
Map<String, String> map2 = new HashMap<>();
Random rand = new Random(1);
for (int i = 0; i < entrySize / 80; i++)
map2.put("key-" + i, "value-" + rand.nextInt(1000));
xml.writeObject(map2);
xml.close();
String value = baos.toString().substring(0, entrySize);
// warmup to compression.
if (run == 0) {
DirectBytes bytes = DirectStore.allocate(entrySize).bytes();
SnappyStringMarshaller.INSTANCE.write(bytes, value);
bytes.flip();
SnappyStringMarshaller.INSTANCE.read(bytes);
bytes.release();
}
String value = generateValue(entrySize);
for (int i = start; i < finish; i++) {
String key = "key-" + i;
String object;
map.put(key, value);
String object = map.get(key);
object = map.get(key);
assertTrue(key, map.containsKey(key));
assertNotNull(key, object);
assertEquals(key, entrySize, object.length());
@@ -138,10 +190,23 @@ public class LargeEntriesTest {
for (int i = start; i < finish; i++) {
// System.out.println(i);
String key = "key-" + i;
String object = map.get(key);
assertNotNull(key, object);
assertEquals(key, entrySize, object.length());
}
}
private String generateValue(int entrySize) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
XMLEncoder xml = new XMLEncoder(baos);
Map<String, String> map2 = new HashMap<>();
Random rand = new Random(1);
for (int i = 0; i < entrySize / 80; i++)
map2.put("key-" + i, "value-" + rand.nextInt(1000));
xml.writeObject(map2);
xml.close();
return baos.toString().substring(0, entrySize);
}
}
@@ -18,7 +18,7 @@
package net.openhft.chronicle.map;
import net.openhft.chronicle.map.jrs166.JSR166TestCase;
import net.openhft.chronicle.map.jsr166.JSR166TestCase;
import org.junit.Test;
import java.io.IOException;
@@ -218,13 +218,13 @@ public class ReplicationCheckingMap<K, V> implements ChronicleMap<K, V> {
}
@Override
public <R> R mapForKey(K key, @NotNull Function<? super V, R> function) {
return map1.mapForKey(key, function);
public <R> R getMapped(K key, @NotNull Function<? super V, R> function) {
return map1.getMapped(key, function);
}
@Override
public V putWith(K key, @NotNull Mutator<V> mutator) {
return map1.putWith(key, mutator);
public V putMapped(K key, @NotNull UnaryOperator<V> unaryOperator) {
return map1.putMapped(key, unaryOperator);
}
@Override
@@ -237,6 +237,16 @@ public class ReplicationCheckingMap<K, V> implements ChronicleMap<K, V> {
throw new UnsupportedOperationException();
}
@Override
public V newValueInstance() {
throw new UnsupportedOperationException();
}
@Override
public K newKeyInstance() {
throw new UnsupportedOperationException();
}
@Override
public V acquireUsing(@NotNull K key, V usingValue) {
return map1.acquireUsing(key, usingValue);
@@ -41,7 +41,7 @@ import static org.junit.Assert.assertTrue;
public class StatelessClientTest {
public static final int SIZE = 2500;
static int s_port = 9050;
static int s_port = 9070;
enum ToString implements Function<Object, String> {
INSTANCE;
@@ -114,7 +114,7 @@ public class StatelessClientTest {
.class, StringBuilder.class)
.putReturnsNull(true)
.statelessClient(new InetSocketAddress("localhost", port)).create()) {
String actual = statelessMap.mapForKey(10, ToString.INSTANCE);
String actual = statelessMap.getMapped(10, ToString.INSTANCE);
assertEquals("Hello World", actual);
}
@@ -134,7 +134,7 @@ public class StatelessClientTest {
try (ChronicleMap<Integer, StringBuilder> statelessMap = ChronicleMapBuilder.of(Integer
.class, StringBuilder.class)
.statelessClient(new InetSocketAddress("localhost", port)).create()) {
String actual = statelessMap.mapForKey(11, ToString.INSTANCE);
String actual = statelessMap.getMapped(11, ToString.INSTANCE);
assertEquals(null, actual);
}
@@ -19,7 +19,7 @@
package net.openhft.chronicle.map;
import net.openhft.chronicle.hash.replication.TimeProvider;
import net.openhft.chronicle.map.jrs166.JSR166TestCase;
import net.openhft.chronicle.map.jsr166.JSR166TestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -16,7 +16,7 @@
* limitations under the License.
*/
package net.openhft.chronicle.map.jrs166;
package net.openhft.chronicle.map.jsr166;
import junit.framework.AssertionFailedError;
import org.junit.After;
@@ -16,11 +16,11 @@
* limitations under the License.
*/
package net.openhft.chronicle.map.jrs166.map;
package net.openhft.chronicle.map.jsr166.map;
import net.openhft.chronicle.map.ChronicleMap;
import net.openhft.chronicle.map.ChronicleMapBuilder;
import net.openhft.chronicle.map.jrs166.JSR166TestCase;
import net.openhft.chronicle.map.jsr166.JSR166TestCase;
import org.junit.Test;
import java.io.IOException;
@@ -16,7 +16,7 @@
* limitations under the License.
*/
package net.openhft.chronicle.map.jrs166.map;
package net.openhft.chronicle.map.jsr166.map;
/*
* Written by Doug Lea with assistance from members of JCP JSR-166
@@ -16,7 +16,7 @@
* limitations under the License.
*/
package net.openhft.chronicle.map.jrs166.map;
package net.openhft.chronicle.map.jsr166.map;
import net.openhft.chronicle.map.ChronicleMap;
import net.openhft.chronicle.map.ChronicleMapBuilder;
@@ -16,11 +16,11 @@
* limitations under the License.
*/
package net.openhft.chronicle.map.jrs166.map;
package net.openhft.chronicle.map.jsr166.map;
import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig;
import net.openhft.chronicle.map.*;
import net.openhft.chronicle.map.jrs166.JSR166TestCase;
import net.openhft.chronicle.map.jsr166.JSR166TestCase;
import org.jetbrains.annotations.NotNull;
import org.junit.After;
import org.junit.Before;
@@ -170,13 +170,13 @@ public class StatelessChronicleMapTest extends JSR166TestCase {
}
@Override
public <R> R mapForKey(K key, @NotNull Function<? super V, R> function) {
return d.mapForKey(key, function);
public <R> R getMapped(K key, @NotNull Function<? super V, R> function) {
return d.getMapped(key, function);
}
@Override
public V putWith(K key, @NotNull Mutator<V> mutator) {
return d.putWith(key, mutator);
public V putMapped(K key, @NotNull UnaryOperator<V> unaryOperator) {
return d.putMapped(key, unaryOperator);
}
@Override
@@ -189,6 +189,16 @@ public class StatelessChronicleMapTest extends JSR166TestCase {
d.putAll(fromFile);
}
@Override
public V newValueInstance() {
throw new UnsupportedOperationException();
}
@Override
public K newKeyInstance() {
throw new UnsupportedOperationException();
}
@Override
public V putIfAbsent(K key, V value) {
return d.putIfAbsent(key, value);