diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableReaderWriter.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableReaderWriter.java index e45b38fe9..36c44ab3a 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableReaderWriter.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableReaderWriter.java @@ -18,8 +18,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class BytesMarshallableReaderWriter - extends InstanceCreatingMarshaller - implements SizedReader, SizedWriter { + extends CachingCreatingMarshaller { public BytesMarshallableReaderWriter(Class vClass) { super(vClass); } @@ -39,17 +38,7 @@ public class BytesMarshallableReaderWriter } @Override - public long size(@NotNull V toWrite) { - Bytes bytes = Wires.acquireBytes(); - toWrite.writeMarshallable(bytes); - return bytes.readRemaining(); - } - - @Override - public void write(Bytes out, long size, @NotNull V toWrite) { - VanillaBytes vanillaBytes = VANILLA_BYTES_TL.get(); - vanillaBytes.bytesStore(out, out.readPosition(), out.readRemaining()); - vanillaBytes.writeLimit(out.writePosition() + size); - toWrite.writeMarshallable(vanillaBytes); + protected void writeToWire(Wire wire, @NotNull V toWrite) { + toWrite.writeMarshallable(wire.bytes()); } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/CachingCreatingMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/CachingCreatingMarshaller.java new file mode 100644 index 000000000..f74c0b998 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/CachingCreatingMarshaller.java @@ -0,0 +1,46 @@ +package net.openhft.chronicle.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.hash.serialization.SizedWriter; +import net.openhft.chronicle.wire.*; +import org.jetbrains.annotations.NotNull; + +public abstract class CachingCreatingMarshaller + extends InstanceCreatingMarshaller + implements SizedReader, SizedWriter { + + static final ThreadLocal WIRE_TL = ThreadLocal.withInitial( + () -> WireType.BINARY_LIGHT.apply(Bytes.allocateElasticOnHeap(128))); + static final ThreadLocal LAST_TL = new ThreadLocal<>(); + + public CachingCreatingMarshaller(Class vClass) { + super(vClass); + } + + @Override + public long size(@NotNull V toWrite) { + Wire wire = WIRE_TL.get(); + wire.bytes().clear(); + writeToWire(wire, toWrite); + LAST_TL.set(toWrite); + return wire.bytes().readRemaining(); + } + + protected abstract void writeToWire(Wire wire, @NotNull V toWrite); + + @Override + public void write(Bytes out, long size, @NotNull V toWrite) { + if (LAST_TL.get() == toWrite) { + Wire wire = WIRE_TL.get(); + if (wire.bytes().readRemaining() == size) { + out.write(wire.bytes()); + wire.bytes().clear(); + LAST_TL.set(null); + return; + } + } + BinaryWire wire = Wires.binaryWireForWrite(out, out.writePosition(), size); + writeToWire(wire, toWrite); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/MarshallableReaderWriter.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/MarshallableReaderWriter.java index 77f063228..d633ebab7 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/MarshallableReaderWriter.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/MarshallableReaderWriter.java @@ -15,8 +15,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class MarshallableReaderWriter - extends InstanceCreatingMarshaller - implements SizedReader, SizedWriter { + extends CachingCreatingMarshaller { public MarshallableReaderWriter(Class vClass) { super(vClass); } @@ -32,15 +31,7 @@ public class MarshallableReaderWriter } @Override - public long size(@NotNull V toWrite) { - Wire wire = Wires.acquireBinaryWire(); - toWrite.writeMarshallable(wire); - return wire.bytes().readRemaining(); - } - - @Override - public void write(Bytes out, long size, @NotNull V toWrite) { - BinaryWire wire = Wires.binaryWireForWrite(out, out.writePosition(), size); + protected void writeToWire(Wire wire, @NotNull V toWrite) { toWrite.writeMarshallable(wire); } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/TypedMarshallableReaderWriter.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/TypedMarshallableReaderWriter.java new file mode 100644 index 000000000..e9f375b6c --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/TypedMarshallableReaderWriter.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016-2019 Chronicle Software Ltd + */ + +package net.openhft.chronicle.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.hash.serialization.SizedWriter; +import net.openhft.chronicle.wire.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class TypedMarshallableReaderWriter + extends CachingCreatingMarshaller { + + public TypedMarshallableReaderWriter(Class vClass) { + super(vClass); + } + + @NotNull + @Override + public V read(Bytes in, long size, @Nullable V using) { + BinaryWire wire = Wires.binaryWireForRead(in, in.readPosition(), size); + return (V) wire.getValueIn().object(using, tClass()); + } + protected void writeToWire(Wire wire, @NotNull V toWrite) { + wire.getValueOut().object(toWrite); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java index 70b9f0016..044113c45 100755 --- a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java +++ b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java @@ -35,6 +35,7 @@ import net.openhft.chronicle.hash.serialization.*; import net.openhft.chronicle.hash.serialization.impl.BytesMarshallableReaderWriter; import net.openhft.chronicle.hash.serialization.impl.MarshallableReaderWriter; import net.openhft.chronicle.hash.serialization.impl.SerializationBuilder; +import net.openhft.chronicle.hash.serialization.impl.TypedMarshallableReaderWriter; import net.openhft.chronicle.map.replication.MapRemoteOperations; import net.openhft.chronicle.set.ChronicleSetBuilder; import net.openhft.chronicle.values.ValueModel; @@ -49,6 +50,7 @@ import org.slf4j.LoggerFactory; import java.io.*; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; @@ -136,7 +138,7 @@ import static net.openhft.chronicle.map.VanillaChronicleMap.alignAddr; */ public final class ChronicleMapBuilder implements ChronicleHashBuilder, - ChronicleMapBuilder> { + ChronicleMapBuilder> { private static final int UNDEFINED_ALIGNMENT_CONFIG = -1; private static final int NO_ALIGNMENT = 1; @@ -265,7 +267,10 @@ public final class ChronicleMapBuilder implements } else if (Marshallable.class.isAssignableFrom(valueClass)) { //noinspection unchecked builder.averageValueSize(1024) - .valueMarshaller(new MarshallableReaderWriter<>((Class) valueClass)); + .valueMarshaller( + valueClass.isMemberClass() && Modifier.isFinal(valueClass.getModifiers()) + ? new MarshallableReaderWriter<>((Class) valueClass) + : new TypedMarshallableReaderWriter<>((Class) valueClass)); } return builder; } @@ -274,14 +279,6 @@ public final class ChronicleMapBuilder implements return Character.toLowerCase(name.charAt(0)) + name.substring(1); } - private boolean isKeySizeKnown() { - return keyBuilder.sizeIsStaticallyKnown; - } - - private boolean isValueSizeKnown() { - return valueBuilder.sizeIsStaticallyKnown; - } - private static void checkSegments(final long segments) { if (segments <= 0) { throw new IllegalArgumentException("segments should be positive, " + segments + " given"); @@ -359,7 +356,7 @@ public final class ChronicleMapBuilder implements } private static void writeNotComplete(@NotNull final FileChannel fileChannel, - @NotNull final ByteBuffer headerBuffer, + @NotNull final ByteBuffer headerBuffer, final int headerSize) throws IOException { //noinspection PointlessBitwiseExpression headerBuffer.putInt(SIZE_WORD_OFFSET, NOT_COMPLETE | DATA | headerSize); @@ -462,11 +459,63 @@ public final class ChronicleMapBuilder implements return storedChecksum == checkSum; } + private static boolean isDefined(final double config) { + return !isNaN(config); + } + + private static long toLong(final double v) { + long l = round(v); + if (l != v) + throw new IllegalArgumentException("Integer argument expected, given " + v); + return l; + } + + private static long roundUp(final double v) { + return round(Math.ceil(v)); + } + + private static long roundDown(final double v) { + return (long) v; + } + + /** + * When Chronicle Maps are created using {@link #createPersistedTo(File)} or + * {@link #recoverPersistedTo(File, boolean)} or {@link + * #createOrRecoverPersistedTo(File, boolean)} methods, file lock on the Chronicle Map's file is + * acquired, that shouldn't be done from concurrent threads within the same JVM process. So + * creation of Chronicle Maps persisted to the same File should be synchronized across JVM's + * threads. Simple way would be to synchronize on some static (lock) object, but would serialize + * all Chronicle Maps creations (persisted to any files), ConcurrentHashMap#compute() gives more + * scalability. ConcurrentHashMap is used effectively for lock striping only, because the + * entries are not even landing the map, because compute() always returns null. + */ + private static void fileLockedIO(@NotNull final File file, + @NotNull final FileChannel fileChannel, + @NotNull final FileIOAction fileIOAction) { + FILE_LOCKING_CONTROL.compute(file, (k, v) -> { + try { + try (FileLock ignored = fileChannel.lock()) { + fileIOAction.fileIOAction(); + } + return null; + } catch (IOException e) { + throw Jvm.rethrow(e); + } + }); + } + + private boolean isKeySizeKnown() { + return keyBuilder.sizeIsStaticallyKnown; + } + + private boolean isValueSizeKnown() { + return valueBuilder.sizeIsStaticallyKnown; + } + @Override public ChronicleMapBuilder clone() { try { - @SuppressWarnings("unchecked") - final ChronicleMapBuilder result = (ChronicleMapBuilder) super.clone(); + @SuppressWarnings("unchecked") final ChronicleMapBuilder result = (ChronicleMapBuilder) super.clone(); result.keyBuilder = keyBuilder.clone(); result.valueBuilder = valueBuilder.clone(); result.privateAPI = new ChronicleMapBuilderPrivateAPI<>(result); @@ -649,7 +698,7 @@ public final class ChronicleMapBuilder implements public ChronicleMapBuilder averageValue(@NotNull final V averageValue) { final Class valueClass = averageValue.getClass(); if (BytesMarshallable.class.isAssignableFrom(valueClass) && - valueBuilder.tClass.isInterface()) { + (valueBuilder.tClass.isInterface() && valueBuilder.tClass != Marshallable.class)) { if (Serializable.class.isAssignableFrom(valueClass)) LOG.warn("BytesMarshallable " + valueClass + " will be serialized as Serializable as the value class is an interface"); else @@ -1568,7 +1617,7 @@ public final class ChronicleMapBuilder implements } @Override - public ChronicleMap recoverPersistedTo(@NotNull final File file, final boolean sameBuilderConfigAndLibraryVersion) throws IOException { + public ChronicleMap recoverPersistedTo(@NotNull final File file, final boolean sameBuilderConfigAndLibraryVersion) throws IOException { return recoverPersistedTo(file, sameBuilderConfigAndLibraryVersion, DEFAULT_CHRONICLE_MAP_CORRUPTION_LISTENER); } @@ -1576,7 +1625,7 @@ public final class ChronicleMapBuilder implements @Override public ChronicleMap recoverPersistedTo(@NotNull final File file, final boolean sameBuilderConfigAndLibraryVersion, - @Nullable final ChronicleHashCorruption.Listener corruptionListener) throws IOException { + @Nullable final ChronicleHashCorruption.Listener corruptionListener) throws IOException { return clone().createWithFile(file, true, sameBuilderConfigAndLibraryVersion, corruptionListener); } @@ -1791,7 +1840,7 @@ public final class ChronicleMapBuilder implements @NotNull final ChronicleHashResources resources, final boolean recover, final boolean overrideBuilderConfig, - @Nullable final ChronicleHashCorruption.Listener corruptionListener) throws IOException { + @Nullable final ChronicleHashCorruption.Listener corruptionListener) throws IOException { final ChronicleHashCorruptionImpl corruption = recover ? new ChronicleHashCorruptionImpl() : null; try { int headerSize = waitUntilReady(raf, file, recover); @@ -1967,49 +2016,4 @@ public final class ChronicleMapBuilder implements } } - private static boolean isDefined(final double config) { - return !isNaN(config); - } - - private static long toLong(final double v) { - long l = round(v); - if (l != v) - throw new IllegalArgumentException("Integer argument expected, given " + v); - return l; - } - - private static long roundUp(final double v) { - return round(Math.ceil(v)); - } - - private static long roundDown(final double v) { - return (long) v; - } - - /** - * When Chronicle Maps are created using {@link #createPersistedTo(File)} or - * {@link #recoverPersistedTo(File, boolean)} or {@link - * #createOrRecoverPersistedTo(File, boolean)} methods, file lock on the Chronicle Map's file is - * acquired, that shouldn't be done from concurrent threads within the same JVM process. So - * creation of Chronicle Maps persisted to the same File should be synchronized across JVM's - * threads. Simple way would be to synchronize on some static (lock) object, but would serialize - * all Chronicle Maps creations (persisted to any files), ConcurrentHashMap#compute() gives more - * scalability. ConcurrentHashMap is used effectively for lock striping only, because the - * entries are not even landing the map, because compute() always returns null. - */ - private static void fileLockedIO(@NotNull final File file, - @NotNull final FileChannel fileChannel, - @NotNull final FileIOAction fileIOAction) { - FILE_LOCKING_CONTROL.compute(file, (k, v) -> { - try { - try (FileLock ignored = fileChannel.lock()) { - fileIOAction.fileIOAction(); - } - return null; - } catch (IOException e) { - throw Jvm.rethrow(e); - } - }); - } - } \ No newline at end of file diff --git a/src/test/java/net/openhft/chronicle/map/AbstractMarshallableKeyValueTest.java b/src/test/java/net/openhft/chronicle/map/AbstractMarshallableKeyValueTest.java index d22d6731b..c85dce301 100644 --- a/src/test/java/net/openhft/chronicle/map/AbstractMarshallableKeyValueTest.java +++ b/src/test/java/net/openhft/chronicle/map/AbstractMarshallableKeyValueTest.java @@ -16,6 +16,8 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.hash.serialization.impl.TypedMarshallableReaderWriter; +import net.openhft.chronicle.wire.Marshallable; import net.openhft.chronicle.wire.SelfDescribingMarshallable; import org.junit.Test; @@ -34,6 +36,19 @@ public final class AbstractMarshallableKeyValueTest { assertThat(map.get(new Key()).number, is(new Value().number)); } + @Test + public void shouldAcceptAbstractMarshallableComponents2() throws Exception { + final ChronicleMap map = ChronicleMapBuilder.of(Key.class, Marshallable.class).entries(10) + .averageKey(new Key()).averageValue(new Value()) + .valueMarshaller(new TypedMarshallableReaderWriter<>(Marshallable.class)) + .create(); + + map.put(new Key(), new Value()); + + Value value = (Value) map.get(new Key()); + assertThat(value.number, is(new Value().number)); + } + private static final class Key extends SelfDescribingMarshallable { private String k = "key"; } diff --git a/src/test/java/net/openhft/chronicle/map/ReplicatedChronicleMapTest.java b/src/test/java/net/openhft/chronicle/map/ReplicatedChronicleMapTest.java index f76590b90..38900e723 100644 --- a/src/test/java/net/openhft/chronicle/map/ReplicatedChronicleMapTest.java +++ b/src/test/java/net/openhft/chronicle/map/ReplicatedChronicleMapTest.java @@ -468,7 +468,7 @@ public class ReplicatedChronicleMapTest extends JSR166TestCase { ChronicleMap c = newShmIntString(); c.get(null); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException|IllegalArgumentException success) { } } @@ -481,7 +481,7 @@ public class ReplicatedChronicleMapTest extends JSR166TestCase { ChronicleMap c = newShmIntString(); c.containsKey(null); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException|IllegalArgumentException success) { } } @@ -494,7 +494,7 @@ public class ReplicatedChronicleMapTest extends JSR166TestCase { ChronicleMap c = newShmIntString(); c.put(null, "whatever"); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException|IllegalArgumentException success) { } } @@ -507,7 +507,7 @@ public class ReplicatedChronicleMapTest extends JSR166TestCase { ChronicleMap c = newShmIntString(); c.put(JSR166TestCase.notPresent, null); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException|IllegalArgumentException success) { } } @@ -520,7 +520,7 @@ public class ReplicatedChronicleMapTest extends JSR166TestCase { ChronicleMap c = newShmIntString(); c.putIfAbsent(null, "whatever"); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException|IllegalArgumentException success) { } } @@ -568,7 +568,7 @@ public class ReplicatedChronicleMapTest extends JSR166TestCase { ChronicleMap c = newShmIntString(); c.replace(null, "whatever"); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException|IllegalArgumentException success) { } } @@ -581,7 +581,7 @@ public class ReplicatedChronicleMapTest extends JSR166TestCase { ChronicleMap c = newShmIntString(); c.replace(null, "A", "whatever"); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException|IllegalArgumentException success) { } } @@ -593,7 +593,7 @@ public class ReplicatedChronicleMapTest extends JSR166TestCase { ChronicleMap c = newShmIntString(5); c.containsValue(null); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException|IllegalArgumentException success) { } }*/ @@ -606,7 +606,7 @@ public class ReplicatedChronicleMapTest extends JSR166TestCase { ChronicleMap c = newShmIntString(5); c.contains(null); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException|IllegalArgumentException success) { } } */ @@ -620,7 +620,7 @@ public class ReplicatedChronicleMapTest extends JSR166TestCase { ChronicleMap c = newShmIntString(); c.putIfAbsent(JSR166TestCase.notPresent, null); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException|IllegalArgumentException success) { } } @@ -633,7 +633,7 @@ public class ReplicatedChronicleMapTest extends JSR166TestCase { ChronicleMap c = newShmIntString(); c.replace(JSR166TestCase.notPresent, null); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException|IllegalArgumentException success) { } } @@ -646,7 +646,7 @@ public class ReplicatedChronicleMapTest extends JSR166TestCase { ChronicleMap c = newShmIntString(); c.replace(JSR166TestCase.notPresent, null, "A"); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException|IllegalArgumentException success) { } } @@ -659,7 +659,7 @@ public class ReplicatedChronicleMapTest extends JSR166TestCase { ChronicleMap c = newShmIntString(); c.replace(JSR166TestCase.notPresent, "A", null); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException|IllegalArgumentException success) { } } @@ -673,7 +673,7 @@ public class ReplicatedChronicleMapTest extends JSR166TestCase { c.put("sadsdf", "asdads"); c.remove(null); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException|IllegalArgumentException success) { } } @@ -687,7 +687,7 @@ public class ReplicatedChronicleMapTest extends JSR166TestCase { c.put("sadsdf", "asdads"); c.remove(null, "whatever"); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException|IllegalArgumentException success) { } } diff --git a/src/test/java/net/openhft/chronicle/map/SerializableTest.java b/src/test/java/net/openhft/chronicle/map/SerializableTest.java index 969dbe92b..64ce71c69 100755 --- a/src/test/java/net/openhft/chronicle/map/SerializableTest.java +++ b/src/test/java/net/openhft/chronicle/map/SerializableTest.java @@ -1,6 +1,7 @@ package net.openhft.chronicle.map; import net.openhft.chronicle.wire.BytesInBinaryMarshallable; +import net.openhft.chronicle.wire.Marshallable; import net.openhft.chronicle.wire.SelfDescribingMarshallable; import org.junit.Test; @@ -94,6 +95,26 @@ public class SerializableTest { assertEquals(expected, actual); } + @Test + public void test2d() { + ChronicleMap map = ChronicleMapBuilder.simpleMapOf(Integer.class, Marshallable.class) + .name("bar") + .averageValueSize(1024) + .entries(10) + .create(); + + String expected = IntStream.range(0, 4096) + .mapToObj(i -> i % 50 == 0 ? String.format("\n%04d", i) : "" + i % 10) + .collect(Collectors.joining("")); + + Bar2 value = new Bar2(expected); + map.put(1, value); + Bar2 bar2 = (Bar2) map.get(1); + String actual = bar2.x; + + assertEquals(expected, actual); + } + public static class Foo implements Serializable { public String x; diff --git a/src/test/java/net/openhft/chronicle/map/jsr166/map/ChronicleMapTest.java b/src/test/java/net/openhft/chronicle/map/jsr166/map/ChronicleMapTest.java index e721e60ba..71b045503 100644 --- a/src/test/java/net/openhft/chronicle/map/jsr166/map/ChronicleMapTest.java +++ b/src/test/java/net/openhft/chronicle/map/jsr166/map/ChronicleMapTest.java @@ -420,7 +420,7 @@ public class ChronicleMapTest extends JSR166TestCase { try (ChronicleMap c = newShmIntString(8076)) { c.get(null); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException | IllegalArgumentException success) { } } @@ -432,7 +432,7 @@ public class ChronicleMapTest extends JSR166TestCase { try (ChronicleMap c = newShmIntString(8076)) { c.containsKey(null); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException | IllegalArgumentException success) { } } @@ -444,7 +444,7 @@ public class ChronicleMapTest extends JSR166TestCase { try (ChronicleMap c = newShmIntString(8076)) { c.put(null, "whatever"); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException | IllegalArgumentException success) { } } @@ -457,7 +457,7 @@ public class ChronicleMapTest extends JSR166TestCase { try (ChronicleMap c = newShmIntString(8076)) { c.put(notPresent, null); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException | IllegalArgumentException success) { } } @@ -470,7 +470,7 @@ public class ChronicleMapTest extends JSR166TestCase { try (ChronicleMap c = newShmIntString(8076)) { c.putIfAbsent(null, "whatever"); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException | IllegalArgumentException success) { } } @@ -483,7 +483,7 @@ public class ChronicleMapTest extends JSR166TestCase { try (ChronicleMap c = newShmIntString(8076)) { c.replace(null, "whatever"); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException | IllegalArgumentException success) { } } @@ -496,7 +496,7 @@ public class ChronicleMapTest extends JSR166TestCase { try (ChronicleMap c = newShmIntString(8076)) { c.replace(null, "A", "whatever"); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException | IllegalArgumentException success) { } } @@ -508,7 +508,7 @@ public class ChronicleMapTest extends JSR166TestCase { try (ChronicleMap c = newShmIntString(8076)) { c.putIfAbsent(notPresent, null); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException | IllegalArgumentException success) { } } @@ -520,7 +520,7 @@ public class ChronicleMapTest extends JSR166TestCase { try (ChronicleMap c = newShmIntString(8076)) { c.replace(notPresent, null); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException | IllegalArgumentException success) { } } @@ -528,12 +528,11 @@ public class ChronicleMapTest extends JSR166TestCase { * replace(x, null, y) throws NPE */ @Test(timeout = 5000) - public void testReplaceValue2_NullPointerException - () throws IOException { + public void testReplaceValue2_NullPointerException() throws IOException { try (ChronicleMap c = newShmIntString(8076)) { c.replace(notPresent, null, "A"); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException | IllegalArgumentException success) { } } @@ -545,7 +544,7 @@ public class ChronicleMapTest extends JSR166TestCase { try (ChronicleMap c = newShmIntString(8076)) { c.replace(notPresent, "A", null); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException | IllegalArgumentException success) { } } @@ -558,7 +557,7 @@ public class ChronicleMapTest extends JSR166TestCase { c.put("sadsdf", "asdads"); c.remove(null); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException | IllegalArgumentException success) { } } @@ -572,7 +571,7 @@ public class ChronicleMapTest extends JSR166TestCase { c.put("sadsdf", "asdads"); c.remove(null, "whatever"); shouldThrow(); - } catch (NullPointerException success) { + } catch (NullPointerException | IllegalArgumentException success) { } } @@ -588,6 +587,37 @@ public class ChronicleMapTest extends JSR166TestCase { } } + @Test + public void testPercentageComplete() { + + try (ChronicleMap map = ChronicleMap + .of(Integer.class, Integer.class) + .entries(1600) + .actualSegments(3) + .maxBloatFactor(2) + .create()) { + + long remainingAutoResizes = 0; + short percentageFreeSpace = 0; + try { + for (int i = 0; ; i++) { + + map.put(i, 0); + remainingAutoResizes = map.remainingAutoResizes(); + percentageFreeSpace = map.percentageFreeSpace(); + + } + } catch (IllegalStateException e) { + if (e.getMessage().contains("Attempt to allocate")) { + Assert.assertEquals(0, (int) remainingAutoResizes); + Assert.assertTrue(percentageFreeSpace < 6); + return; + } + Assert.fail(); + } + } + } + // classes for testing Comparable fallbacks static class BI implements Comparable { private final int value; @@ -671,36 +701,5 @@ public class ChronicleMapTest extends JSR166TestCase { } } - @Test - public void testPercentageComplete() { - - try (ChronicleMap map = ChronicleMap - .of(Integer.class, Integer.class) - .entries(1600) - .actualSegments(3) - .maxBloatFactor(2) - .create()) { - - long remainingAutoResizes = 0; - short percentageFreeSpace = 0; - try { - for (int i = 0; ; i++) { - - map.put(i, 0); - remainingAutoResizes = map.remainingAutoResizes(); - percentageFreeSpace = map.percentageFreeSpace(); - - } - } catch (IllegalStateException e) { - if (e.getMessage().contains("Attempt to allocate")) { - Assert.assertEquals(0, (int) remainingAutoResizes); - Assert.assertTrue(percentageFreeSpace < 6); - return; - } - Assert.fail(); - } - } - } - }