From 9b1d3f63933c38becf5c5f603722782a0f6de6bd Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Thu, 7 May 2020 11:33:10 +0100 Subject: [PATCH 01/67] Add a RandomAccessFile which doesn't resource leak on a GC, https://github.com/OpenHFT/Chronicle-Core/issues/108 --- .../chronicle/hash/impl/util/CanonicalRandomAccessFiles.java | 3 ++- src/test/java/net/openhft/chronicle/set/Builder.java | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/openhft/chronicle/hash/impl/util/CanonicalRandomAccessFiles.java b/src/main/java/net/openhft/chronicle/hash/impl/util/CanonicalRandomAccessFiles.java index 311815e04..02d2ce273 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/util/CanonicalRandomAccessFiles.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/util/CanonicalRandomAccessFiles.java @@ -16,6 +16,7 @@ package net.openhft.chronicle.hash.impl.util; +import net.openhft.chronicle.core.CleaningRandomAccessFile; import net.openhft.chronicle.core.Jvm; import java.io.File; @@ -36,7 +37,7 @@ public final class CanonicalRandomAccessFiles { return canonicalRafs.compute(file, (f, ref) -> { if (ref == null) { try { - return new RafReference(new RandomAccessFile(f, "rw")); + return new RafReference(new CleaningRandomAccessFile(f, "rw")); } catch (FileNotFoundException e) { throw Jvm.rethrow(e); } diff --git a/src/test/java/net/openhft/chronicle/set/Builder.java b/src/test/java/net/openhft/chronicle/set/Builder.java index bed10ca9e..2edde079c 100644 --- a/src/test/java/net/openhft/chronicle/set/Builder.java +++ b/src/test/java/net/openhft/chronicle/set/Builder.java @@ -44,8 +44,9 @@ public class Builder { This will only work if the user is an admin on windows. */ file.setWritable(true);//just in case relative path was used. - RandomAccessFile raf = new RandomAccessFile(file, "rw"); - raf.close();//allows closing the file access on windows. forcing to close access. Only works for admin-access. + try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) { + //allows closing the file access on windows. forcing to close access. Only works for admin-access. + } } //file.delete(); //isnt guaranteed on windows. From 528e09bd0c9ccaea04d757e9b0582fd3f4e87e85 Mon Sep 17 00:00:00 2001 From: Jerry Shea Date: Thu, 14 May 2020 08:29:27 +1000 Subject: [PATCH 02/67] doco: Engine -> Datagrid --- docs/CM_FAQs.adoc | 2 +- docs/CM_Features.adoc | 2 +- docs/CM_Updates.adoc | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/CM_FAQs.adoc b/docs/CM_FAQs.adoc index b8b1dd225..0029907d8 100755 --- a/docs/CM_FAQs.adoc +++ b/docs/CM_FAQs.adoc @@ -24,7 +24,7 @@ Also, is there a reason these `1000` `gets` have be done serially in one thread? ===== Answer -The stateless client has been replaced with Chronicle Engine. The stateless client is not supported in ChronicleMap 3.x. For more information, please refer to Chronicle Engine FAQ's. +The stateless client has been replaced with Chronicle Datagrid. The stateless client is not supported in ChronicleMap 3.x. For more information, please refer to Chronicle Datagrid FAQ's. For `get()s`, parallelizing will reduce costs. For `put()s`, if you have concurrency requirements, that is, multi-key lock before updating all of them, it should be in one thread. diff --git a/docs/CM_Features.adoc b/docs/CM_Features.adoc index fd8b0d2ac..7a556a2cf 100755 --- a/docs/CM_Features.adoc +++ b/docs/CM_Features.adoc @@ -129,7 +129,7 @@ Please contact us at mailto:sales@chronicle.software[sales@chronicle.software] i NOTE: For access to commercially available features please contact mailto:sales@chronicle.software[sales@chronicle.software]. == Peer projects - - https://github.com/OpenHFT/Chronicle-Engine[Chronicle Engine]. Reactive processing framework + - Chronicle Datagrid. Reactive processing framework supporting Chronicle Map as a backend. - http://vanillajava.blogspot.com/2015/09/chronicle-journal-customizable-data.html[Chronicle Journal]. Another diff --git a/docs/CM_Updates.adoc b/docs/CM_Updates.adoc index 1bfbda862..67922413b 100755 --- a/docs/CM_Updates.adoc +++ b/docs/CM_Updates.adoc @@ -18,9 +18,9 @@ Changes between Chronicle Map 3 and the previous Chronicle Map version are detai - "Listeners" mechanism fully reworked; see <>. This has a number of important consequences, most notable is that it is now possible to define "eventual-consistency" replication strategy, different from "last write wins"; any state-based CRDT. - - "Stateless clients" functionality (remote calls) is moved to https://github.com/OpenHFT/Chronicle-Engine[Chronicle Engine]. + - "Stateless clients" functionality (remote calls) is moved to Chronicle Datagrid. - - Replication is performed using https://github.com/OpenHFT/Chronicle-Engine[Chronicle Engine]. + - Replication is performed using Chronicle Datagrid. - Earlier versions of Chronicle Map had hard creation-time limits on the number of entries storable in a Chronicle Map. If the size exceeded this limit, an exception was thrown. + In Chronicle Map 3, this limitation is removed. The number of entries still has to be configured when the Chronicle Map is created, Exceeding this configured limit is possible, but discouraged. + From 911258b0662b1fdb87d94509deab0a298baffc4a Mon Sep 17 00:00:00 2001 From: Rob Austin Date: Thu, 21 May 2020 11:55:15 +0100 Subject: [PATCH 03/67] fixed #219 --- .../chronicle/map/OldDeletedEntriesCleanupThread.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupThread.java b/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupThread.java index 3a6253b7d..fd5ac567a 100644 --- a/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupThread.java +++ b/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupThread.java @@ -120,7 +120,14 @@ class OldDeletedEntriesCleanupThread extends Thread return; while (!shutdown) { - int nextSegmentIndex = cleanupSegment(); + int nextSegmentIndex; + try { + nextSegmentIndex = cleanupSegment(); + } catch (Exception e) { + if (shutdown) + break; + throw e; + } if (nextSegmentIndex == -1) return; if (nextSegmentIndex == 0) { From 2bdb39b6f74a511ed097298ab6d2b7903c497362 Mon Sep 17 00:00:00 2001 From: The Alchemist Date: Thu, 21 May 2020 13:22:32 -0400 Subject: [PATCH 04/67] minor typo fix --- spec/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/README.md b/spec/README.md index 596f5cc40..e0dbe4305 100644 --- a/spec/README.md +++ b/spec/README.md @@ -27,7 +27,7 @@ as an implementation bug. - To provide the ability for Chronicle Map adopters, database developers and researchers to study - the Chronicle Map design and possibly draw their own conclusions about it's behaviour, guarantees + the Chronicle Map design and possibly draw their own conclusions about its behaviour, guarantees and efficiency. The reference implementation is quite complex so it's hard to understand how it works by solely reading the code, especially for people who don't know Java. From 9438b1ea5bd53f922ae2a2fa320b130bf3fbeafe Mon Sep 17 00:00:00 2001 From: Dmitry Pisklov Date: Tue, 26 May 2020 22:15:33 +0100 Subject: [PATCH 05/67] implement AbstractCloseable - OpenHFT/Chronicle-Core#116 --- .../net/openhft/chronicle/hash/HashSegmentContext.java | 5 +++++ .../chronicle/hash/impl/VanillaChronicleHash.java | 9 ++++----- .../chronicle/map/OldDeletedEntriesCleanupThread.java | 5 +++++ .../chronicle/map/impl/stage/query/AcquireHandle.java | 5 +++-- src/main/java/net/openhft/chronicle/set/SetFromMap.java | 5 +++++ .../openhft/chronicle/map/ReplicationCheckingMap.java | 5 +++++ 6 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/openhft/chronicle/hash/HashSegmentContext.java b/src/main/java/net/openhft/chronicle/hash/HashSegmentContext.java index fa3fb1280..8fbdfe8b6 100644 --- a/src/main/java/net/openhft/chronicle/hash/HashSegmentContext.java +++ b/src/main/java/net/openhft/chronicle/hash/HashSegmentContext.java @@ -57,4 +57,9 @@ public interface HashSegmentContext> extends HashConte * Returns the number of present entries in this segment. */ long size(); + + @Override + default boolean isClosed() { + throw new UnsupportedOperationException(); + } } diff --git a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java index 1d613653b..ad8756bbe 100755 --- a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java @@ -22,6 +22,7 @@ import net.openhft.chronicle.bytes.MappedBytesStoreFactory; import net.openhft.chronicle.bytes.NativeBytesStore; import net.openhft.chronicle.core.Maths; import net.openhft.chronicle.core.OS; +import net.openhft.chronicle.core.io.AbstractCloseable; import net.openhft.chronicle.hash.*; import net.openhft.chronicle.hash.impl.util.BuildVersion; import net.openhft.chronicle.hash.impl.util.Cleaner; @@ -38,7 +39,6 @@ import net.openhft.chronicle.map.ChronicleMapBuilder; import net.openhft.chronicle.values.Values; import net.openhft.chronicle.wire.Marshallable; import net.openhft.chronicle.wire.WireIn; -import net.openhft.chronicle.wire.WireInternal; import net.openhft.chronicle.wire.WireOut; import org.jetbrains.annotations.NotNull; @@ -65,9 +65,8 @@ import static net.openhft.chronicle.hash.impl.CompactOffHeapLinearHashTable.*; import static net.openhft.chronicle.map.ChronicleHashCorruptionImpl.format; import static net.openhft.chronicle.map.ChronicleHashCorruptionImpl.report; -public abstract class VanillaChronicleHash, SC extends HashSegmentContext, - ECQ extends ExternalHashQueryContext> +public abstract class VanillaChronicleHash, SC extends HashSegmentContext, ECQ extends ExternalHashQueryContext> + extends AbstractCloseable implements ChronicleHash, Marshallable { public static final long TIER_COUNTERS_AREA_SIZE = 64; @@ -660,7 +659,7 @@ public abstract class VanillaChronicleHash implements Closeable { +public class AcquireHandle extends AbstractCloseable { @StageRef CheckOnEachPublicOperation checkOnEachPublicOperation; @@ -33,7 +34,7 @@ public class AcquireHandle implements Closeable { UsingReturnValue usingReturn; @Override - public void close() { + protected void performClose() { checkOnEachPublicOperation.checkOnEachPublicOperation(); q.replaceValue(q.entry(), q.wrapValueAsData(usingReturn.returnValue())); q.close(); diff --git a/src/main/java/net/openhft/chronicle/set/SetFromMap.java b/src/main/java/net/openhft/chronicle/set/SetFromMap.java index c31204622..fb1c049d4 100644 --- a/src/main/java/net/openhft/chronicle/set/SetFromMap.java +++ b/src/main/java/net/openhft/chronicle/set/SetFromMap.java @@ -203,6 +203,11 @@ class SetFromMap extends AbstractSet implements ChronicleSet { m.close(); } + @Override + public boolean isClosed() { + return m.isClosed(); + } + @Override public boolean isOpen() { return m.isOpen(); diff --git a/src/test/java/net/openhft/chronicle/map/ReplicationCheckingMap.java b/src/test/java/net/openhft/chronicle/map/ReplicationCheckingMap.java index 910662f8d..f7902816d 100644 --- a/src/test/java/net/openhft/chronicle/map/ReplicationCheckingMap.java +++ b/src/test/java/net/openhft/chronicle/map/ReplicationCheckingMap.java @@ -331,6 +331,11 @@ public class ReplicationCheckingMap implements ChronicleMap { map2.close(); } + @Override + public boolean isClosed() { + return false; + } + @Override public boolean isOpen() { throw new UnsupportedOperationException(); From 21b2676a3c73b5d82ea2d538aada604f349c6e88 Mon Sep 17 00:00:00 2001 From: Dmitry Pisklov Date: Thu, 28 May 2020 16:37:52 +0100 Subject: [PATCH 06/67] Small fixes --- .../hash/impl/util/ThrowablesTest.java | 1 + .../map/AbstractMarshallableKeyValueTest.java | 3 ++- .../net/openhft/lang/values/DoubleArray.java | 12 ++++------ .../openhft/lang/values/DoubleArrayTest.java | 23 ------------------- 4 files changed, 7 insertions(+), 32 deletions(-) diff --git a/src/test/java/net/openhft/chronicle/hash/impl/util/ThrowablesTest.java b/src/test/java/net/openhft/chronicle/hash/impl/util/ThrowablesTest.java index 8e238a7d2..9826d1fc2 100644 --- a/src/test/java/net/openhft/chronicle/hash/impl/util/ThrowablesTest.java +++ b/src/test/java/net/openhft/chronicle/hash/impl/util/ThrowablesTest.java @@ -48,6 +48,7 @@ public class ThrowablesTest { Throwables.propagateNotWrapping(null, IOException.class); } + @SuppressWarnings("RedundantThrows") @Test(expected = NullPointerException.class) public void testPropagateNotWrappingNullWrappingType() throws Throwable { Throwables.propagateNotWrapping(new IOException(), null); diff --git a/src/test/java/net/openhft/chronicle/map/AbstractMarshallableKeyValueTest.java b/src/test/java/net/openhft/chronicle/map/AbstractMarshallableKeyValueTest.java index d22d6731b..3abfdd30b 100644 --- a/src/test/java/net/openhft/chronicle/map/AbstractMarshallableKeyValueTest.java +++ b/src/test/java/net/openhft/chronicle/map/AbstractMarshallableKeyValueTest.java @@ -20,6 +20,7 @@ import net.openhft.chronicle.wire.SelfDescribingMarshallable; import org.junit.Test; import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; public final class AbstractMarshallableKeyValueTest { @@ -31,7 +32,7 @@ public final class AbstractMarshallableKeyValueTest { map.put(new Key(), new Value()); - assertThat(map.get(new Key()).number, is(new Value().number)); + assertEquals(new Value().number, map.get(new Key()).number); } private static final class Key extends SelfDescribingMarshallable { diff --git a/src/test/java/net/openhft/lang/values/DoubleArray.java b/src/test/java/net/openhft/lang/values/DoubleArray.java index d080f305d..be85dcbd5 100755 --- a/src/test/java/net/openhft/lang/values/DoubleArray.java +++ b/src/test/java/net/openhft/lang/values/DoubleArray.java @@ -22,14 +22,10 @@ import net.openhft.chronicle.bytes.DynamicallySized; import net.openhft.chronicle.bytes.NativeBytesStore; import net.openhft.chronicle.values.Copyable; -/** - * Created by peter.lawrey on 23/04/2015. - */ public class DoubleArray implements Byteable, Copyable, DynamicallySized { - static boolean HACK = true; - private static int CAPACITY = 0; // assume a 32-bit size. - private static int LENGTH = CAPACITY + 4; // assume a 32-bit size. - private static int BASE = LENGTH + 4; + private final static int CAPACITY = 0; // assume a 32-bit size. + private final static int LENGTH = CAPACITY + 4; // assume a 32-bit size. + private final static int BASE = LENGTH + 4; private final int capacity; private BytesStore bs; @@ -64,7 +60,7 @@ public class DoubleArray implements Byteable, Copyable, Dynamically } public int length() { - return HACK && bs == null ? 6 * 8 : bs.readInt(LENGTH + offset); + return bs == null ? 6 * 8 : bs.readInt(LENGTH + offset); } public int capacity() { diff --git a/src/test/java/net/openhft/lang/values/DoubleArrayTest.java b/src/test/java/net/openhft/lang/values/DoubleArrayTest.java index 2c91b0e35..6c54051aa 100755 --- a/src/test/java/net/openhft/lang/values/DoubleArrayTest.java +++ b/src/test/java/net/openhft/lang/values/DoubleArrayTest.java @@ -85,27 +85,4 @@ public class DoubleArrayTest { System.out.println(proxyMap.get(2)); proxyMap.close(); } - - @Test - @Ignore("TODO What is HACK???") - public void addToAMap2() { - DoubleArray.HACK = false; - DoubleArray a = new DoubleArray(10); - a.setData(new double[]{1, 2, 3, 4, 5}); - - DoubleArray b = new DoubleArray(10); - b.setData(new double[]{5, 6, 7, 8, 9}); - - ChronicleMap proxyMap = ChronicleMapBuilder - .of(Integer.class, DoubleArray.class) - .averageValueSize(6 * 8) - .create(); - proxyMap.put(1, a); - proxyMap.put(2, b); - - System.out.println(proxyMap.get(1)); - System.out.println(proxyMap.get(2)); - proxyMap.close(); - DoubleArray.HACK = true; - } } \ No newline at end of file From d7c318986bafe00dd5d743e9be0fd8e7c5be741b Mon Sep 17 00:00:00 2001 From: Dmitry Pisklov Date: Thu, 28 May 2020 16:54:28 +0100 Subject: [PATCH 07/67] fix longSize() implementation for closed map --- .../openhft/chronicle/map/VanillaChronicleMap.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java index 1c33ded38..23dda6548 100755 --- a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java @@ -131,7 +131,7 @@ public class VanillaChronicleMap alignment = wireIn.read(() -> "alignment").int32(); worstAlignment = wireIn.read(() -> "worstAlignment").int32(); - maxBloatFactor = wireIn.read(() -> "maxBloatFactor").float64(); + maxBloatFactor = wireIn.read(() -> "maxBloatFactor").float64(); } @Override @@ -203,12 +203,13 @@ public class VanillaChronicleMap @Override public final long longSize() { long result = 0L; - try (IterationContext c = iterationContext()) { - for (int segmentIndex = 0; segmentIndex < segments(); segmentIndex++) { - c.initSegmentIndex(segmentIndex); - result += c.size(); + if (!isClosed()) + try (IterationContext c = iterationContext()) { + for (int segmentIndex = 0; segmentIndex < segments(); segmentIndex++) { + c.initSegmentIndex(segmentIndex); + result += c.size(); + } } - } return result; } From b0ef26bb582b7511fe71173ee74df080f043d5de Mon Sep 17 00:00:00 2001 From: Dmitry Pisklov Date: Thu, 28 May 2020 17:06:58 +0100 Subject: [PATCH 08/67] fix longSize() implementation for closed map --- .../java/net/openhft/chronicle/map/VanillaChronicleMap.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java index 23dda6548..a49f79934 100755 --- a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java @@ -203,7 +203,7 @@ public class VanillaChronicleMap @Override public final long longSize() { long result = 0L; - if (!isClosed()) + if (!isClosed() && this.cxt != null) try (IterationContext c = iterationContext()) { for (int segmentIndex = 0; segmentIndex < segments(); segmentIndex++) { c.initSegmentIndex(segmentIndex); From fb3b953b9d24451a1e7541831e0f63f2c5f38e3b Mon Sep 17 00:00:00 2001 From: Dmitry Pisklov Date: Thu, 28 May 2020 20:01:51 +0100 Subject: [PATCH 09/67] fix longSize() implementation - fix the test --- .../chronicle/hash/impl/VanillaChronicleHash.java | 7 ++++++- .../net/openhft/chronicle/map/MapCloseTest.java | 13 +++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java index ad8756bbe..a42226f62 100755 --- a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java @@ -679,7 +679,12 @@ public abstract class VanillaChronicleHash, SC extends @Override public boolean isOpen() { - return !resources.closed(); + return !isClosed(); + } + + @Override + public boolean isClosed() { + return super.isClosed() || resources.closed(); } public final void checkKey(Object key) { diff --git a/src/test/java/net/openhft/chronicle/map/MapCloseTest.java b/src/test/java/net/openhft/chronicle/map/MapCloseTest.java index b99e6e957..767044fb8 100644 --- a/src/test/java/net/openhft/chronicle/map/MapCloseTest.java +++ b/src/test/java/net/openhft/chronicle/map/MapCloseTest.java @@ -18,13 +18,14 @@ package net.openhft.chronicle.map; import net.openhft.chronicle.hash.ChronicleHashClosedException; import net.openhft.chronicle.hash.impl.stage.hash.ChainingInterface; -import org.junit.Assert; import org.junit.Test; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Semaphore; import static net.openhft.chronicle.hash.impl.BigSegmentHeader.LOCK_TIMEOUT_SECONDS; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; public class MapCloseTest { @@ -58,7 +59,7 @@ public class MapCloseTest { }); } - @Test(expected = ChronicleHashClosedException.class) + @Test public void testSizeAfterCloseThrowsChronicleHashClosedException() throws InterruptedException { ChronicleMap map = @@ -66,7 +67,7 @@ public class MapCloseTest { Thread t = new Thread(() -> map.close()); t.start(); t.join(); - map.size(); + assertEquals(0, map.size()); } @Test(expected = RuntimeException.class) @@ -117,14 +118,14 @@ public class MapCloseTest { t1.start(); t2.start(); latch.await(); - Assert.assertEquals(2, map.allContexts().size()); + assertEquals(2, map.allContexts().size()); semaphore.release(2); t1.join(); t2.join(); map.get(1); - Assert.assertEquals(1, map.allContexts().size()); + assertEquals(1, map.allContexts().size()); ChainingInterface cxt = map.allContexts().get(0).get().get(); - Assert.assertTrue(cxt == map.queryContext(1)); + assertSame(cxt, map.queryContext(1)); } } From e56fb15f9506d9d2b46bd3f64683f41915b8e91c Mon Sep 17 00:00:00 2001 From: Rob Austin Date: Fri, 29 May 2020 13:26:43 +0100 Subject: [PATCH 10/67] fixed java.lang.NullPointerException at net.openhft.chronicle.hash.impl.VanillaChronicleHash.isClosed(VanillaChronicleHash.java:687) at net.openhft.chronicle.map.VanillaChronicleMap.longSize(VanillaChronicleMap.java:206) at net.openhft.chronicle.map.AbstractChronicleMap.mapEquals(AbstractChronicleMap.java:183) at net.openhft.chronicle.map.VanillaChronicleMap.equals(VanillaChronicleMap.java:321) at java.util.WeakHashMap.eq(WeakHashMap.java:287) at java.util.WeakHashMap.put(WeakHashMap.java:454) at java.util.Collections$SynchronizedMap.put(Collections.java:2590) at net.openhft.chronicle.core.io.AbstractCloseable.(AbstractCloseable.java:46) at net.openhft.chronicle.hash.impl.VanillaChronicleHash.(VanillaChronicleHash.java:156) --- .../chronicle/hash/impl/VanillaChronicleHash.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java index a42226f62..dd01ed81e 100755 --- a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java @@ -74,10 +74,9 @@ public abstract class VanillaChronicleHash, SC extends // --- Start of instance fields --- /** - * Global mutable state lock doesn't yet need read-write levels and waits; - * Used the same locking strategy as in segment locks - * (VanillaReadWriteUpdateWithWaitsLockingStrategy) in order to simplify Chronicle Map - * specification (having only one kind of locks to specify and implement). + * Global mutable state lock doesn't yet need read-write levels and waits; Used the same locking strategy as in segment locks + * (VanillaReadWriteUpdateWithWaitsLockingStrategy) in order to simplify Chronicle Map specification (having only one kind of locks to specify and + * implement). */ static final LockingStrategy globalMutableStateLockingStrategy = VanillaReadWriteUpdateWithWaitsLockingStrategy.instance(); @@ -684,7 +683,8 @@ public abstract class VanillaChronicleHash, SC extends @Override public boolean isClosed() { - return super.isClosed() || resources.closed(); + ChronicleHashResources resources = this.resources; + return super.isClosed() || (resources != null && resources.closed()); } public final void checkKey(Object key) { @@ -1055,8 +1055,8 @@ public abstract class VanillaChronicleHash, SC extends } /** - * {@link ChronicleHashCloseOnExitHook} needs to use {@code VanillaChronicleHash}es as - * WeakHashMap keys, but with identity comparison, not Map's equals() and hashCode(). + * {@link ChronicleHashCloseOnExitHook} needs to use {@code VanillaChronicleHash}es as WeakHashMap keys, but with identity comparison, not Map's + * equals() and hashCode(). */ public class Identity { public VanillaChronicleHash hash() { From b471a97a0d79b8743a4aea305aa001474127e1b1 Mon Sep 17 00:00:00 2001 From: Rob Austin Date: Fri, 29 May 2020 15:06:20 +0100 Subject: [PATCH 11/67] added default is closed --- .../openhft/chronicle/core/io/Closeable.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/main/java/net/openhft/chronicle/core/io/Closeable.java diff --git a/src/main/java/net/openhft/chronicle/core/io/Closeable.java b/src/main/java/net/openhft/chronicle/core/io/Closeable.java new file mode 100644 index 000000000..91b10ab38 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/core/io/Closeable.java @@ -0,0 +1,47 @@ +package net.openhft.chronicle.core.io; + +import net.openhft.chronicle.core.Jvm; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.util.Collection; + +public interface Closeable extends java.io.Closeable, QueryCloseable { + + static void closeQuietly(@NotNull Object... closeables) { + closeQuietly((Object) closeables); + } + + static void closeQuietly(@Nullable Object o) { + if (o instanceof Collection) { + ((Collection) o).forEach(Closeable::closeQuietly); + } else if (o instanceof Object[]) { + for (Object o2 : (Object[]) o) { + closeQuietly(o2); + } + } else if (o instanceof java.io.Closeable) { + try { + ((java.io.Closeable) o).close(); + } catch (IOException | IllegalStateException e) { + Jvm.debug().on(Closeable.class, e); + } + } + } + + /** + * Doesn't throw a checked exception. + */ + @Override + void close(); + + @Deprecated + default void notifyClosing() { + // take an action before everything else closes. + } + + @Override + default boolean isClosed() { + throw new UnsupportedOperationException("todo"); + } +} From f042add96b056cf6ebf90e07b592332ddde5ea41 Mon Sep 17 00:00:00 2001 From: Rob Austin Date: Fri, 29 May 2020 16:40:58 +0100 Subject: [PATCH 12/67] create MapClosable which replaces the default isClosed() method that was removed from chronicle closable --- .../openhft/chronicle/hash/ChronicleHash.java | 99 ++++++++----------- .../chronicle/hash/HashSegmentContext.java | 9 +- .../map/OldDeletedEntriesCleanupThread.java | 11 +-- .../chronicle/map/VanillaChronicleMap.java | 10 +- .../map/impl/QueryContextInterface.java | 4 +- .../map/impl/stage/query/AcquireHandle.java | 4 +- 6 files changed, 57 insertions(+), 80 deletions(-) diff --git a/src/main/java/net/openhft/chronicle/hash/ChronicleHash.java b/src/main/java/net/openhft/chronicle/hash/ChronicleHash.java index 17faf9aa9..ecf893395 100644 --- a/src/main/java/net/openhft/chronicle/hash/ChronicleHash.java +++ b/src/main/java/net/openhft/chronicle/hash/ChronicleHash.java @@ -17,8 +17,8 @@ package net.openhft.chronicle.hash; import net.openhft.chronicle.bytes.BytesStore; -import net.openhft.chronicle.core.io.Closeable; import net.openhft.chronicle.map.ChronicleMap; +import net.openhft.chronicle.map.MapClosable; import net.openhft.chronicle.map.MapMethods; import net.openhft.chronicle.map.MapQueryContext; import net.openhft.chronicle.set.ChronicleSet; @@ -35,43 +35,37 @@ import java.util.function.Predicate; * Common base interface for {@link ChronicleMap} and {@link ChronicleSet}. */ public interface ChronicleHash, SC extends HashSegmentContext, - EQC extends ExternalHashQueryContext> extends Closeable { + EQC extends ExternalHashQueryContext> extends MapClosable { /** - * Returns the file this hash container mapped to, i. e. when it is created by - * {@link ChronicleHashBuilder#create()} call, or {@code null} if it is purely in-memory, - * i. e. if it is created by {@link ChronicleHashBuilder#create()} call. + * Returns the file this hash container mapped to, i. e. when it is created by {@link ChronicleHashBuilder#create()} call, or {@code null} if it + * is purely in-memory, i. e. if it is created by {@link ChronicleHashBuilder#create()} call. * - * @return the file this {@link ChronicleMap} or {@link ChronicleSet} is mapped to, - * or {@code null} if it is not mapped to any file + * @return the file this {@link ChronicleMap} or {@link ChronicleSet} is mapped to, or {@code null} if it is not mapped to any file * @see ChronicleHashBuilder#createPersistedTo(File) */ File file(); /** - * Returns the name of this {@code ChronicleHash}, configured by {@link - * ChronicleHashBuilder#name(String)}, or {@code null}, if not configured. + * Returns the name of this {@code ChronicleHash}, configured by {@link ChronicleHashBuilder#name(String)}, or {@code null}, if not configured. * * @return the name of this this {@link ChronicleMap} or {@link ChronicleSet} */ String name(); /** - * Returns a {@code String}, useful for identifying this {@code ChronicleHash} in debugging, - * logging, and error reporting. {@link #toString()} of concrete {@code ChronicleHash} - * subinterfaces, {@link ChronicleMap} and {@link ChronicleSet}, has to follow {@link - * Map#toString()} and {@link Set#toString()} contracts respectively, making it not always - * useful (or even impossible to use, if this {@code ChronicleHash} contains a lot of entries) - * for the purposes listed above. + * Returns a {@code String}, useful for identifying this {@code ChronicleHash} in debugging, logging, and error reporting. {@link #toString()} of + * concrete {@code ChronicleHash} subinterfaces, {@link ChronicleMap} and {@link ChronicleSet}, has to follow {@link Map#toString()} and {@link + * Set#toString()} contracts respectively, making it not always useful (or even impossible to use, if this {@code ChronicleHash} contains a lot of + * entries) for the purposes listed above. *

*

This method return a string of the form:

- * [ChronicleMap|ChronicleSet]{name={@link #name()}, file={@link #file()}, - * identityHashCode={@link System#identityHashCode System.identityHashCode(thisChronicleHash)}} + * [ChronicleMap|ChronicleSet]{name={@link #name()}, file={@link #file()}, identityHashCode={@link System#identityHashCode + * System.identityHashCode(thisChronicleHash)}} *

- * This form could be changed in any subsequent Chronicle Map library release (including patch - * release). The user code shouldn't depend on this form. + * This form could be changed in any subsequent Chronicle Map library release (including patch release). The user code shouldn't depend on this + * form. * - * @return a {@code String}, useful for identifying this {@code ChronicleHash} in debugging, - * logging, and error reporting + * @return a {@code String}, useful for identifying this {@code ChronicleHash} in debugging, logging, and error reporting */ String toIdentityString(); @@ -83,8 +77,8 @@ public interface ChronicleHash, SC extends HashSegment long longSize(); /** - * Returns the amount of off-heap memory (in bytes), allocated by this {@code ChronicleHash} or - * shared with with other ChronicleHashes, persisting to the same {@link #file()}. + * Returns the amount of off-heap memory (in bytes), allocated by this {@code ChronicleHash} or shared with with other ChronicleHashes, persisting + * to the same {@link #file()}. *

*

After {@link #close()} this method returns 0. * @@ -110,8 +104,7 @@ public interface ChronicleHash, SC extends HashSegment * }} *

*

See documentation to {@link HashQueryContext} interface and methods in {@link MapMethods} - * interface for examples of using contexts. Also see + * interface for examples of using contexts. Also see * Working with an entry within a context section in the Chronicle Map tutorial. * * @param key the queried key @@ -125,15 +118,12 @@ public interface ChronicleHash, SC extends HashSegment EQC queryContext(K key); /** - * Returns a context to perform arbitrary operations with the given key, provided in - * {@link Data} form. Equivalent to {@link #queryContext(Object)}, but accepts {@code Data} - * instead of object key. This method is useful, when you already have {@code Data}, calling - * this method instead of {@link #queryContext(Object)} might help to avoid unnecessary - * deserialization. + * Returns a context to perform arbitrary operations with the given key, provided in {@link Data} form. Equivalent to {@link + * #queryContext(Object)}, but accepts {@code Data} instead of object key. This method is useful, when you already have {@code Data}, calling this + * method instead of {@link #queryContext(Object)} might help to avoid unnecessary deserialization. *

*

See documentation to {@link HashQueryContext} interface and methods in {@link MapMethods} - * interface for examples of using contexts. Also see + * interface for examples of using contexts. Also see * Working with an entry within a context section in the Chronicle Map tutorial. * * @param key the queried key as {@code Data} @@ -143,9 +133,8 @@ public interface ChronicleHash, SC extends HashSegment EQC queryContext(Data key); /** - * Returns a context to perform arbitrary operations with the given key, provided in the - * serialized form. See {@link #queryContext(Object)} and {@link #queryContext(Data)} for more - * information on contexts semantics and usage patterns. + * Returns a context to perform arbitrary operations with the given key, provided in the serialized form. See {@link #queryContext(Object)} and + * {@link #queryContext(Data)} for more information on contexts semantics and usage patterns. * * @param keyBytes the bytes store with the key bytes to query * @param offset actual offset of the key bytes within the given BytesStore @@ -156,8 +145,7 @@ public interface ChronicleHash, SC extends HashSegment EQC queryContext(BytesStore keyBytes, long offset, long size); /** - * Returns a context of the segment with the given index. Segments are indexed from 0 to - * {@link #segments()}{@code - 1}. + * Returns a context of the segment with the given index. Segments are indexed from 0 to {@link #segments()}{@code - 1}. * * @see HashSegmentContext */ @@ -172,50 +160,43 @@ public interface ChronicleHash, SC extends HashSegment int segments(); /** - * Checks the given predicate on each entry in this {@code ChronicleHash} until all entries - * have been processed or the predicate returns {@code false} for some entry, or throws - * an {@code Exception}. Exceptions thrown by the predicate are relayed to the caller. + * Checks the given predicate on each entry in this {@code ChronicleHash} until all entries have been processed or the predicate returns {@code + * false} for some entry, or throws an {@code Exception}. Exceptions thrown by the predicate are relayed to the caller. *

*

The order in which the entries will be processed is unspecified. It might differ from - * the order of iteration via {@code Iterator} returned by any method of this - * {@code ChronicleHash} or it's collection view. + * the order of iteration via {@code Iterator} returned by any method of this {@code ChronicleHash} or it's collection view. *

*

If the {@code ChronicleHash} is empty, this method returns {@code true} immediately. * * @param predicate the predicate to be checked for each entry - * @return {@code true} if the predicate returned {@code true} for all entries of - * the {@code ChronicleHash}, {@code false} if it returned {@code false} for the entry + * @return {@code true} if the predicate returned {@code true} for all entries of the {@code ChronicleHash}, {@code false} if it returned {@code + * false} for the entry */ boolean forEachEntryWhile(Predicate predicate); /** - * Performs the given action for each entry in this {@code ChronicleHash} until all entries have - * been processed or the action throws an {@code Exception}. Exceptions thrown by the action are - * relayed to the caller. + * Performs the given action for each entry in this {@code ChronicleHash} until all entries have been processed or the action throws an {@code + * Exception}. Exceptions thrown by the action are relayed to the caller. *

*

The order in which the entries will be processed is unspecified. It might differ from - * the order of iteration via {@code Iterator} returned by any method of this - * {@code ChronicleHash} or it's collection view. + * the order of iteration via {@code Iterator} returned by any method of this {@code ChronicleHash} or it's collection view. * * @param action the action to be performed for each entry */ void forEachEntry(Consumer action); /** - * Releases the off-heap memory, used by this hash container and resources, used by replication, - * if any. However, if hash container (hence off-heap memory, used by it) is mapped to the file - * and there are other instances mapping the same data on the server across JVMs, the memory - * won't be actually freed on operating system level. I. e. this method call doesn't affect - * other {@link ChronicleMap} or {@link ChronicleSet} instances mapping the same data. + * Releases the off-heap memory, used by this hash container and resources, used by replication, if any. However, if hash container (hence + * off-heap memory, used by it) is mapped to the file and there are other instances mapping the same data on the server across JVMs, the memory + * won't be actually freed on operating system level. I. e. this method call doesn't affect other {@link ChronicleMap} or {@link ChronicleSet} + * instances mapping the same data. *

*

If you won't call this method, memory would be held at least until next garbage - * collection. This could be a problem if, for example, you target rare garbage collections, - * but load and drop {@code ChronicleHash}es regularly. + * collection. This could be a problem if, for example, you target rare garbage collections, but load and drop {@code ChronicleHash}es regularly. *

*

After this method call, all methods, querying the {@code ChronicleHash}'s entries, {@link - * #longSize()} and {@code size()}), throw {@link ChronicleHashClosedException}. {@link - * #isOpen()} returns {@code false}, {@code close()} itself returns immediately without effects - * (i. e. repetitive {@code close()}, even from concurrent threads, are safe). + * #longSize()} and {@code size()}), throw {@link ChronicleHashClosedException}. {@link #isOpen()} returns {@code false}, {@code close()} itself + * returns immediately without effects (i. e. repetitive {@code close()}, even from concurrent threads, are safe). */ @Override void close(); diff --git a/src/main/java/net/openhft/chronicle/hash/HashSegmentContext.java b/src/main/java/net/openhft/chronicle/hash/HashSegmentContext.java index fa3fb1280..8f135e02e 100644 --- a/src/main/java/net/openhft/chronicle/hash/HashSegmentContext.java +++ b/src/main/java/net/openhft/chronicle/hash/HashSegmentContext.java @@ -16,7 +16,7 @@ package net.openhft.chronicle.hash; -import net.openhft.chronicle.core.io.Closeable; +import net.openhft.chronicle.core.io.DefaultCloseable; import java.util.function.Consumer; import java.util.function.Predicate; @@ -28,12 +28,11 @@ import java.util.function.Predicate; * @param the entry type * @see ChronicleHash#segmentContext(int) */ -public interface HashSegmentContext> extends HashContext, Closeable { +public interface HashSegmentContext> extends HashContext, DefaultCloseable { /** - * Performs the given action for each present entry in this segment until all entries - * have been processed or the action throws an {@code Exception}. Exceptions thrown by the - * action are relayed to the caller. + * Performs the given action for each present entry in this segment until all entries have been processed or the action throws an {@code + * Exception}. Exceptions thrown by the action are relayed to the caller. * * @param action the action to be performed for each entry in this segment */ diff --git a/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupThread.java b/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupThread.java index fd5ac567a..4fbd8ef3a 100644 --- a/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupThread.java +++ b/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupThread.java @@ -16,7 +16,7 @@ package net.openhft.chronicle.map; -import net.openhft.chronicle.core.io.Closeable; +import net.openhft.chronicle.core.io.DefaultCloseable; import net.openhft.chronicle.hash.ChronicleHashBuilderPrivateAPI; import net.openhft.chronicle.hash.ReplicatedHashSegmentContext; import net.openhft.chronicle.hash.replication.ReplicableEntry; @@ -34,14 +34,13 @@ import static net.openhft.chronicle.hash.replication.TimeProvider.currentTime; import static net.openhft.chronicle.hash.replication.TimeProvider.systemTimeIntervalBetween; class OldDeletedEntriesCleanupThread extends Thread - implements Closeable, Predicate { + implements DefaultCloseable, Predicate { private static final Logger LOG = LoggerFactory.getLogger(OldDeletedEntriesCleanupThread.class); /** - * Don't store a strong ref to a map in order to avoid it's leaking, if the user forgets to - * close() map, from where this thread is shut down explicitly. Dereference map within - * a single method, {@link #cleanupSegment()}. The map has a chance to be collected by GC when - * this thread is sleeping after cleaning up a segment. + * Don't store a strong ref to a map in order to avoid it's leaking, if the user forgets to close() map, from where this thread is shut down + * explicitly. Dereference map within a single method, {@link #cleanupSegment()}. The map has a chance to be collected by GC when this thread is + * sleeping after cleaning up a segment. */ private final WeakReference> mapRef; /** diff --git a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java index 1c33ded38..243524f0b 100755 --- a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java @@ -22,7 +22,6 @@ import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.bytes.BytesStore; import net.openhft.chronicle.bytes.PointerBytesStore; import net.openhft.chronicle.core.Jvm; -import net.openhft.chronicle.core.io.Closeable; import net.openhft.chronicle.hash.ChronicleHashClosedException; import net.openhft.chronicle.hash.ChronicleHashCorruption; import net.openhft.chronicle.hash.Data; @@ -88,9 +87,8 @@ public class VanillaChronicleMap ///////////////////////////////////////////////// private transient String name; /** - * identityString is initialized lazily in {@link #toIdentityString()} rather than in - * {@link #initOwnTransients()} because it depends on {@link #file()} which is set after - * initOwnTransients(). + * identityString is initialized lazily in {@link #toIdentityString()} rather than in {@link #initOwnTransients()} because it depends on {@link + * #file()} which is set after initOwnTransients(). */ private transient String identityString; private transient boolean defaultEntryOperationsAndMethods; @@ -131,7 +129,7 @@ public class VanillaChronicleMap alignment = wireIn.read(() -> "alignment").int32(); worstAlignment = wireIn.read(() -> "worstAlignment").int32(); - maxBloatFactor = wireIn.read(() -> "maxBloatFactor").float64(); + maxBloatFactor = wireIn.read(() -> "maxBloatFactor").float64(); } @Override @@ -279,7 +277,7 @@ public class VanillaChronicleMap @NotNull @Override - public final Closeable acquireContext(K key, V usingValue) { + public final MapClosable acquireContext(K key, V usingValue) { QueryContextInterface q = queryContext(key); // TODO optimize to update lock in certain cases try { diff --git a/src/main/java/net/openhft/chronicle/map/impl/QueryContextInterface.java b/src/main/java/net/openhft/chronicle/map/impl/QueryContextInterface.java index a951067cd..9ab41ef8c 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/QueryContextInterface.java +++ b/src/main/java/net/openhft/chronicle/map/impl/QueryContextInterface.java @@ -17,10 +17,10 @@ package net.openhft.chronicle.map.impl; import net.openhft.chronicle.bytes.BytesStore; -import net.openhft.chronicle.core.io.Closeable; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.serialization.DataAccess; import net.openhft.chronicle.map.ExternalMapQueryContext; +import net.openhft.chronicle.map.MapClosable; import net.openhft.chronicle.map.impl.ret.InstanceReturnValue; import net.openhft.chronicle.map.impl.ret.UsableReturnValue; @@ -38,7 +38,7 @@ public interface QueryContextInterface extends ExternalMapQueryContext< DataAccess inputValueDataAccess(); - Closeable acquireHandle(); + MapClosable acquireHandle(); void initSegmentIndex(int segmentIndex); diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/query/AcquireHandle.java b/src/main/java/net/openhft/chronicle/map/impl/stage/query/AcquireHandle.java index f946b6a93..2fcec669b 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/query/AcquireHandle.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/query/AcquireHandle.java @@ -16,14 +16,14 @@ package net.openhft.chronicle.map.impl.stage.query; -import net.openhft.chronicle.core.io.Closeable; import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; +import net.openhft.chronicle.map.MapClosable; import net.openhft.chronicle.map.impl.stage.ret.UsingReturnValue; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; @Staged -public class AcquireHandle implements Closeable { +public class AcquireHandle implements MapClosable { @StageRef CheckOnEachPublicOperation checkOnEachPublicOperation; From e129a208f29ef70b56c9d75fb8034ad6fea6d1ed Mon Sep 17 00:00:00 2001 From: Rob Austin Date: Fri, 29 May 2020 16:44:38 +0100 Subject: [PATCH 13/67] added missing class --- .../java/net/openhft/chronicle/map/MapClosable.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/main/java/net/openhft/chronicle/map/MapClosable.java diff --git a/src/main/java/net/openhft/chronicle/map/MapClosable.java b/src/main/java/net/openhft/chronicle/map/MapClosable.java new file mode 100644 index 000000000..dfc5dc9c0 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/MapClosable.java @@ -0,0 +1,11 @@ +package net.openhft.chronicle.map; + +import net.openhft.chronicle.core.io.Closeable; + +public interface MapClosable extends Closeable { + + @Override + default boolean isClosed() { + throw new UnsupportedOperationException(); + } +} From b51207186af27c1f868f38475ce6120398ba777e Mon Sep 17 00:00:00 2001 From: Rob Austin Date: Fri, 29 May 2020 18:22:13 +0100 Subject: [PATCH 14/67] changed to MapClosable --- .../openhft/chronicle/hash/HashSegmentContext.java | 12 +++++------- .../map/OldDeletedEntriesCleanupThread.java | 3 +-- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/main/java/net/openhft/chronicle/hash/HashSegmentContext.java b/src/main/java/net/openhft/chronicle/hash/HashSegmentContext.java index 8f135e02e..425c32d92 100644 --- a/src/main/java/net/openhft/chronicle/hash/HashSegmentContext.java +++ b/src/main/java/net/openhft/chronicle/hash/HashSegmentContext.java @@ -16,7 +16,7 @@ package net.openhft.chronicle.hash; -import net.openhft.chronicle.core.io.DefaultCloseable; +import net.openhft.chronicle.map.MapClosable; import java.util.function.Consumer; import java.util.function.Predicate; @@ -28,7 +28,7 @@ import java.util.function.Predicate; * @param the entry type * @see ChronicleHash#segmentContext(int) */ -public interface HashSegmentContext> extends HashContext, DefaultCloseable { +public interface HashSegmentContext> extends HashContext, MapClosable { /** * Performs the given action for each present entry in this segment until all entries have been processed or the action throws an {@code @@ -39,16 +39,14 @@ public interface HashSegmentContext> extends HashConte void forEachSegmentEntry(Consumer action); /** - * Checks the given predicate on each present entry in this segment until all entries - * have been processed or the predicate returns {@code false} for some entry, or throws - * an {@code Exception}. Exceptions thrown by the predicate are relayed to the caller. + * Checks the given predicate on each present entry in this segment until all entries have been processed or the predicate returns {@code + * false} for some entry, or throws an {@code Exception}. Exceptions thrown by the predicate are relayed to the caller. *

*

If this segment is empty (i. e. {@link #size()} call returns 0), this method returns * {@code true} immediately. * * @param predicate the predicate to be checked for each entry in this segment - * @return {@code true} if the predicate returned {@code true} for all checked entries, - * {@code false} if it returned {@code false} for some entry + * @return {@code true} if the predicate returned {@code true} for all checked entries, {@code false} if it returned {@code false} for some entry */ boolean forEachSegmentEntryWhile(Predicate predicate); diff --git a/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupThread.java b/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupThread.java index 4fbd8ef3a..b6dbbcebf 100644 --- a/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupThread.java +++ b/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupThread.java @@ -16,7 +16,6 @@ package net.openhft.chronicle.map; -import net.openhft.chronicle.core.io.DefaultCloseable; import net.openhft.chronicle.hash.ChronicleHashBuilderPrivateAPI; import net.openhft.chronicle.hash.ReplicatedHashSegmentContext; import net.openhft.chronicle.hash.replication.ReplicableEntry; @@ -34,7 +33,7 @@ import static net.openhft.chronicle.hash.replication.TimeProvider.currentTime; import static net.openhft.chronicle.hash.replication.TimeProvider.systemTimeIntervalBetween; class OldDeletedEntriesCleanupThread extends Thread - implements DefaultCloseable, Predicate { + implements MapClosable, Predicate { private static final Logger LOG = LoggerFactory.getLogger(OldDeletedEntriesCleanupThread.class); /** From 59fc0e2342c1f0bec89bfe146a5959b4d4d87900 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Tue, 2 Jun 2020 17:18:50 +0100 Subject: [PATCH 15/67] release Map 2.19.30 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 614ed75e0..6051d7d4d 100755 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ 4.0.0 chronicle-map - 3.19.5-SNAPSHOT + 3.19.30-SNAPSHOT OpenHFT/Chronicle-Map Chronicle-Map bundle From c803b241d515ae054691d118d205635fbe490420 Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Tue, 2 Jun 2020 18:21:08 +0200 Subject: [PATCH 16/67] Updating to bom version 2.19.174 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6051d7d4d..584bd528a 100755 --- a/pom.xml +++ b/pom.xml @@ -30,7 +30,7 @@ net.openhft chronicle-bom - 2.19-SNAPSHOT + 2.19.174 pom import From 7cd4de10292ebe8ca32e7ca999e9abba9ffc2815 Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Tue, 2 Jun 2020 18:23:37 +0200 Subject: [PATCH 17/67] [maven-release-plugin] prepare release chronicle-map-3.19.30 --- pom.xml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 584bd528a..03ccb023e 100755 --- a/pom.xml +++ b/pom.xml @@ -1,17 +1,16 @@ - + net.openhft java-parent-pom 1.1.23 - + 4.0.0 chronicle-map - 3.19.30-SNAPSHOT + 3.19.30 OpenHFT/Chronicle-Map Chronicle-Map bundle @@ -446,7 +445,7 @@ scm:git:git@github.com:OpenHFT/Chronicle-Map.git scm:git:git@github.com:OpenHFT/Chronicle-Map.git scm:git:git@github.com:OpenHFT/Chronicle-Map.git - master + chronicle-map-3.19.30 From 32412ece60c7a2a6cd70e636f6a53cb70fcf0b07 Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Tue, 2 Jun 2020 18:23:45 +0200 Subject: [PATCH 18/67] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 03ccb023e..d04edc9f2 100755 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ 4.0.0 chronicle-map - 3.19.30 + 3.19.31-SNAPSHOT OpenHFT/Chronicle-Map Chronicle-Map bundle @@ -445,7 +445,7 @@ scm:git:git@github.com:OpenHFT/Chronicle-Map.git scm:git:git@github.com:OpenHFT/Chronicle-Map.git scm:git:git@github.com:OpenHFT/Chronicle-Map.git - chronicle-map-3.19.30 + master From 3f6e8a97d95a81261792af94b310f13f116d06ef Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Tue, 2 Jun 2020 18:25:32 +0200 Subject: [PATCH 19/67] Reverting back to bom version 2.19-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d04edc9f2..cbf18f837 100755 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ net.openhft chronicle-bom - 2.19.174 + 2.19-SNAPSHOT pom import From 43d6454884b69a67b9f61c423d8fd6d57314af28 Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Tue, 2 Jun 2020 22:39:27 +0200 Subject: [PATCH 20/67] Updating to bom version 2.19.176 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index cbf18f837..aad6382e8 100755 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ net.openhft chronicle-bom - 2.19-SNAPSHOT + 2.19.176 pom import From c41c5485a81f528bc07c672f83c7e416ae3a7d58 Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Tue, 2 Jun 2020 22:41:49 +0200 Subject: [PATCH 21/67] [maven-release-plugin] prepare release chronicle-map-3.19.31 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index aad6382e8..4adda4ce3 100755 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ 4.0.0 chronicle-map - 3.19.31-SNAPSHOT + 3.19.31 OpenHFT/Chronicle-Map Chronicle-Map bundle @@ -445,7 +445,7 @@ scm:git:git@github.com:OpenHFT/Chronicle-Map.git scm:git:git@github.com:OpenHFT/Chronicle-Map.git scm:git:git@github.com:OpenHFT/Chronicle-Map.git - master + chronicle-map-3.19.31 From 008ed0e56a52e84860c1cfe0cee2232d2530d563 Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Tue, 2 Jun 2020 22:41:57 +0200 Subject: [PATCH 22/67] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 4adda4ce3..5b84d3ac3 100755 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ 4.0.0 chronicle-map - 3.19.31 + 3.19.32-SNAPSHOT OpenHFT/Chronicle-Map Chronicle-Map bundle @@ -445,7 +445,7 @@ scm:git:git@github.com:OpenHFT/Chronicle-Map.git scm:git:git@github.com:OpenHFT/Chronicle-Map.git scm:git:git@github.com:OpenHFT/Chronicle-Map.git - chronicle-map-3.19.31 + master From 2abde62218e1864057b8582ca346f68f35e318c9 Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Tue, 2 Jun 2020 22:43:28 +0200 Subject: [PATCH 23/67] Reverting back to bom version 2.19-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5b84d3ac3..fb97e2b06 100755 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ net.openhft chronicle-bom - 2.19.176 + 2.19-SNAPSHOT pom import From f003e6c3f0b9bc6c9ce5a3c1bf4d4e07b594908d Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Tue, 2 Jun 2020 22:51:13 +0200 Subject: [PATCH 24/67] Reverting back to bom version 2.19-SNAPSHOT From cbcb83ede5d3a2646733ed5de9d556a2c8415b8b Mon Sep 17 00:00:00 2001 From: Dmitry Pisklov Date: Wed, 3 Jun 2020 20:58:54 +0100 Subject: [PATCH 25/67] Add stress test --- .../openhft/chronicle/map/perf/MapStress.java | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 src/test/java/net/openhft/chronicle/map/perf/MapStress.java diff --git a/src/test/java/net/openhft/chronicle/map/perf/MapStress.java b/src/test/java/net/openhft/chronicle/map/perf/MapStress.java new file mode 100644 index 000000000..8a68a19e8 --- /dev/null +++ b/src/test/java/net/openhft/chronicle/map/perf/MapStress.java @@ -0,0 +1,73 @@ +package net.openhft.chronicle.map.perf; + +import net.openhft.chronicle.map.ChronicleMap; + +import java.io.File; +import java.io.IOException; +import java.util.Random; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.stream.IntStream; + +public class MapStress { + private static final File file = new File("./StressTested.cm3"); + private static final int N_WRITE_THREADS = 100; + private static final int N_READ_THREADS = 20; + private ChronicleMap map = ChronicleMap.of(String.class, String.class).averageKeySize(50).averageValueSize(500).entries(100_000).createOrRecoverPersistedTo(file); + private ChronicleMap readerMap = ChronicleMap.of(String.class, String.class).averageKeySize(500).averageValueSize(500).entries(100_000).createOrRecoverPersistedTo(file); + + private ExecutorService executor = Executors.newFixedThreadPool(N_WRITE_THREADS + N_READ_THREADS); + private ThreadLocal randomTL = ThreadLocal.withInitial(Random::new); + + public MapStress() throws IOException { + } + + public void stress() throws ExecutionException, InterruptedException { + Future[] futures = new Future[N_WRITE_THREADS + N_READ_THREADS]; + for (int i = 0; i < N_WRITE_THREADS; i++) { + String id = i + " -> "; + futures[i] = executor.submit(() -> { + final long started = System.currentTimeMillis(); + long written = 0; + do { + IntStream.range(0, 10).forEach(x -> { + final int keyIdx = randomTL.get().nextInt(N_WRITE_THREADS); + map.put("valuekdljashjgffkljakljsdffhh" + keyIdx, "aksjdfhljkhadfjklahfjkladshfjklahdsljkfch aljiocufoipreyuvoiurywcoriucy8oiuxrauoi;dajfhadsih" + System.nanoTime() + System.currentTimeMillis()); + }); + written += 10; + + if (written % 100_000 == 0) + System.err.println(id + "Wrote " + written); + } while (System.currentTimeMillis() - started < 100_000); + }); + } + + for (int i = 0; i < N_READ_THREADS; i++) { + String id = i + " -> "; + futures[i + N_WRITE_THREADS] = executor.submit(() -> { + final long started = System.currentTimeMillis(); + long got = 0; + do { + final int keyIdx = randomTL.get().nextInt(N_WRITE_THREADS); + if (null != readerMap.get("valuekdljashjgffkljakljsdffhh" + keyIdx)) { + got++; + } + } while (System.currentTimeMillis() - started < 100_000); + System.err.println(id + "Read total: " + got); + }); + } + + for (Future f : futures) { + f.get(); + } + executor.shutdown(); + } + + public static void main(String[] args) throws Exception { +// if (file.exists()) +// file.delete(); + new MapStress().stress(); + } +} From 55c1c084e693c64da7b2159b65339cc595a24165 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Thu, 4 Jun 2020 13:05:19 +0100 Subject: [PATCH 26/67] Test for detecting a map which wasn't closed correctly shouldn't close the map correctly. --- .../chronicle/map/MemoryLeaksTest.java | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/test/java/net/openhft/chronicle/map/MemoryLeaksTest.java b/src/test/java/net/openhft/chronicle/map/MemoryLeaksTest.java index 26326d6d8..c75d87367 100755 --- a/src/test/java/net/openhft/chronicle/map/MemoryLeaksTest.java +++ b/src/test/java/net/openhft/chronicle/map/MemoryLeaksTest.java @@ -18,6 +18,7 @@ package net.openhft.chronicle.map; import com.google.common.collect.Lists; import net.openhft.chronicle.bytes.NoBytesStore; +import net.openhft.chronicle.core.Jvm; import net.openhft.chronicle.core.OS; import net.openhft.chronicle.core.values.IntValue; import net.openhft.chronicle.hash.impl.util.Cleaner; @@ -56,6 +57,7 @@ public class MemoryLeaksTest { private boolean persisted; private ChronicleMapBuilder builder; private boolean closeWithinContext; + public MemoryLeaksTest(String testType, boolean replicated, boolean persisted, boolean closeWithinContext) { this.persisted = persisted; this.closeWithinContext = closeWithinContext; @@ -109,33 +111,31 @@ public class MemoryLeaksTest { } long nativeMemoryUsedBeforeMap = nativeMemoryUsed(); int serializersBeforeMap = serializerCount.get(); - try (ChronicleMap map = getMap()) { - long expectedNativeMemory = nativeMemoryUsedBeforeMap + map.offHeapMemoryUsed(); - assertEquals(expectedNativeMemory, nativeMemoryUsed()); - tryCloseFromContext(map); - WeakReference> ref = new WeakReference<>(map); - Assert.assertNotNull(ref.get()); - // map = null; + // the purpose of the test is to find maps which are not closed properly. + ChronicleMap map = getMap(); + long expectedNativeMemory = nativeMemoryUsedBeforeMap + map.offHeapMemoryUsed(); + assertEquals(expectedNativeMemory, nativeMemoryUsed()); + tryCloseFromContext(map); + WeakReference> ref = new WeakReference<>(map); + Assert.assertNotNull(ref.get()); + map = null; - // Wait until Map is collected by GC - while (ref.get() != null) { - System.gc(); - byte[] garbage = new byte[10_000_000]; - Thread.yield(); - } - // Wait until Cleaner is called and memory is returned to the system - for (int i = 0; i < 6_000; i++) { - if (nativeMemoryUsedBeforeMap == nativeMemoryUsed() && // (*) - serializerCount.get() == serializersBeforeMap) { - break; - } - System.gc(); - byte[] garbage = new byte[10_000_000]; - Thread.sleep(10); - } - Assert.assertEquals(nativeMemoryUsedBeforeMap, nativeMemoryUsed()); - Assert.assertEquals(serializersBeforeMap, serializerCount.get()); + // Wait until Map is collected by GC + while (ref.get() != null) { + System.gc(); + Jvm.pause(100); } + // Wait until Cleaner is called and memory is returned to the system + for (int i = 0; i < 6_000; i++) { + if (nativeMemoryUsedBeforeMap == nativeMemoryUsed() && // (*) + serializerCount.get() == serializersBeforeMap) { + break; + } + System.gc(); + Jvm.pause(100); + } + Assert.assertEquals(nativeMemoryUsedBeforeMap, nativeMemoryUsed()); + Assert.assertEquals(serializersBeforeMap, serializerCount.get()); } private long nativeMemoryUsed() { From 28bc77edd6a912d3baae7b08dcd48e9c8e46f8a8 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Thu, 4 Jun 2020 13:09:14 +0100 Subject: [PATCH 27/67] Enable the memory leak test after fixing it. --- .../chronicle/map/MemoryLeaksTest.java | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/test/java/net/openhft/chronicle/map/MemoryLeaksTest.java b/src/test/java/net/openhft/chronicle/map/MemoryLeaksTest.java index c75d87367..8acb8136c 100755 --- a/src/test/java/net/openhft/chronicle/map/MemoryLeaksTest.java +++ b/src/test/java/net/openhft/chronicle/map/MemoryLeaksTest.java @@ -40,6 +40,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; @RunWith(Parameterized.class) public class MemoryLeaksTest { @@ -94,21 +95,21 @@ public class MemoryLeaksTest { @Before public void resetSerializerCount() { + System.err.println("This test is expect to print 'ChronicleMap ... is not closed manually, cleaned up from Cleaner'"); serializerCount.set(0); } @Test(timeout = 60_000) public void testChronicleMapCollectedAndDirectMemoryReleased() throws IOException, InterruptedException { - if (!OS.isWindows()) { - // This test is flaky in Linux and Mac OS apparently because some native memory from - // running previous/concurrent tests is released during this test, that infers with - // the (*) check below. The aim of this test is to check that native memory is not - // leaked and it is proven if it succeeds at least sometimes at least in some OSes. - // This tests is successful always in Windows and successful in Linux and OS X when run - // alone, rather than along all other Chronicle Map's tests. - return; - } + assertFalse(OS.isMacOSX()); + // This test is flaky in Linux and Mac OS apparently because some native memory from + // running previous/concurrent tests is released during this test, that infers with + // the (*) check below. The aim of this test is to check that native memory is not + // leaked and it is proven if it succeeds at least sometimes at least in some OSes. + // This tests is successful always in Windows and successful in Linux and OS X when run + // alone, rather than along all other Chronicle Map's tests. + long nativeMemoryUsedBeforeMap = nativeMemoryUsed(); int serializersBeforeMap = serializerCount.get(); // the purpose of the test is to find maps which are not closed properly. @@ -118,16 +119,14 @@ public class MemoryLeaksTest { tryCloseFromContext(map); WeakReference> ref = new WeakReference<>(map); Assert.assertNotNull(ref.get()); + //noinspection UnusedAssignment map = null; // Wait until Map is collected by GC - while (ref.get() != null) { - System.gc(); - Jvm.pause(100); - } // Wait until Cleaner is called and memory is returned to the system for (int i = 0; i < 6_000; i++) { - if (nativeMemoryUsedBeforeMap == nativeMemoryUsed() && // (*) + if (ref.get() == null && + nativeMemoryUsedBeforeMap == nativeMemoryUsed() && // (*) serializerCount.get() == serializersBeforeMap) { break; } From 8082914c44dd2206f5b1d89bceffa9897cde2bfa Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Thu, 4 Jun 2020 13:21:47 +0100 Subject: [PATCH 28/67] Enable the memory leak test after allowing to copy with native memory being freed in the background. --- .../openhft/chronicle/map/MemoryLeaksTest.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/test/java/net/openhft/chronicle/map/MemoryLeaksTest.java b/src/test/java/net/openhft/chronicle/map/MemoryLeaksTest.java index 8acb8136c..d13d0fa96 100755 --- a/src/test/java/net/openhft/chronicle/map/MemoryLeaksTest.java +++ b/src/test/java/net/openhft/chronicle/map/MemoryLeaksTest.java @@ -99,7 +99,7 @@ public class MemoryLeaksTest { serializerCount.set(0); } - @Test(timeout = 60_000) + @Test(timeout = 10_000) public void testChronicleMapCollectedAndDirectMemoryReleased() throws IOException, InterruptedException { assertFalse(OS.isMacOSX()); @@ -110,6 +110,9 @@ public class MemoryLeaksTest { // This tests is successful always in Windows and successful in Linux and OS X when run // alone, rather than along all other Chronicle Map's tests. + System.gc(); + Jvm.pause(100); + long nativeMemoryUsedBeforeMap = nativeMemoryUsed(); int serializersBeforeMap = serializerCount.get(); // the purpose of the test is to find maps which are not closed properly. @@ -124,16 +127,20 @@ public class MemoryLeaksTest { // Wait until Map is collected by GC // Wait until Cleaner is called and memory is returned to the system - for (int i = 0; i < 6_000; i++) { + for (int i = 1; i <= 10; i++) { if (ref.get() == null && - nativeMemoryUsedBeforeMap == nativeMemoryUsed() && // (*) + nativeMemoryUsedBeforeMap >= nativeMemoryUsed() && // (*) serializerCount.get() == serializersBeforeMap) { break; } System.gc(); - Jvm.pause(100); + Jvm.pause(i * 10); + System.out.println("ref.get()=" + (ref.get() == null)); + System.out.println(nativeMemoryUsedBeforeMap + " <=> " + nativeMemoryUsed()); + System.out.println(serializerCount.get() + " <=> " + serializersBeforeMap); } - Assert.assertEquals(nativeMemoryUsedBeforeMap, nativeMemoryUsed()); + if (nativeMemoryUsedBeforeMap < nativeMemoryUsed()) + Assert.assertEquals(nativeMemoryUsedBeforeMap, nativeMemoryUsed()); Assert.assertEquals(serializersBeforeMap, serializerCount.get()); } From 84a17e8cb3b09c480b88921248e704804a9cfb26 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Thu, 4 Jun 2020 15:06:22 +0100 Subject: [PATCH 29/67] Don't requires to be deleted on Windows. --- .../openhft/chronicle/map/ExitHookTest.java | 107 +++++++++--------- 1 file changed, 51 insertions(+), 56 deletions(-) diff --git a/src/test/java/net/openhft/chronicle/map/ExitHookTest.java b/src/test/java/net/openhft/chronicle/map/ExitHookTest.java index b5003cb8c..eed6bea0e 100644 --- a/src/test/java/net/openhft/chronicle/map/ExitHookTest.java +++ b/src/test/java/net/openhft/chronicle/map/ExitHookTest.java @@ -17,7 +17,6 @@ package net.openhft.chronicle.map; import com.google.common.base.Preconditions; -import net.bytebuddy.implementation.bytecode.Throw; import net.openhft.chronicle.core.OS; import org.junit.Rule; import org.junit.Test; @@ -36,7 +35,7 @@ import static org.junit.Assert.*; public class ExitHookTest { private static final int KEY = 1; - private static final int JVM_STARTUP_WAIT_TIME_MS = 15_000; + private static final int JVM_STARTUP_WAIT_TIME_MS = 5_000; private static final String PRE_SHUTDOWN_ACTION_EXECUTED = "PRE_SHUTDOWN_ACTION_EXECUTED"; private static final String USER_SHUTDOWN_HOOK_EXECUTED = "USER_SHUTDOWN_HOOK_EXECUTED"; @@ -44,64 +43,60 @@ public class ExitHookTest { public TemporaryFolder folder = new TemporaryFolder(); public static void main(String[] args) throws IOException, InterruptedException { + + System.out.println("Other process started, yo"); + File mapFile = new File(args[0]); + System.out.println("1"); + File shutdownActionConfirmationFile = new File(args[1]); + System.out.println("2"); + ChronicleMapBuilder mapBuilder = null; try { - System.out.println("Other process started, yo"); - File mapFile = new File(args[0]); - System.out.println("1"); - File shutdownActionConfirmationFile = new File(args[1]); - System.out.println("2"); - ChronicleMapBuilder mapBuilder = null; - try { - mapBuilder = createMapBuilder(); - } catch (Throwable e) { - e.printStackTrace(); - } - System.out.println("3"); - boolean skipCloseOnExitHook = false; - System.out.println("4"); - if (Boolean.parseBoolean(args[2])) { - skipCloseOnExitHook = true; - } - AtomicReference> mapReference = new AtomicReference<>(); - System.out.println("exit hook" + skipCloseOnExitHook); - if (skipCloseOnExitHook) { - mapBuilder.skipCloseOnExitHook(skipCloseOnExitHook); - Runtime.getRuntime().addShutdownHook(new Thread(() -> { - // In practice, do something with map before shutdown - like create a new map using data from this map. - mapReference.get().close(); - try { - System.out.println("Executing user defined shutdown hook"); - Preconditions.checkState(shutdownActionConfirmationFile.exists()); - Files.write(shutdownActionConfirmationFile.toPath(), - USER_SHUTDOWN_HOOK_EXECUTED.getBytes()); - } catch (Exception e) { - throw new RuntimeException(e); - } - })); - } else { - mapBuilder.setPreShutdownAction(() -> { - try { - System.out.println("Executing pre-shutdown action"); - Preconditions.checkState(shutdownActionConfirmationFile.exists()); - Files.write(shutdownActionConfirmationFile.toPath(), - PRE_SHUTDOWN_ACTION_EXECUTED.getBytes()); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - } - mapReference.set(mapBuilder.createPersistedTo(mapFile)); - try (ExternalMapQueryContext c = mapReference.get().queryContext(KEY)) { - c.writeLock().lock(); - Thread.sleep(30_000); - } - } catch (Exception e) { + mapBuilder = createMapBuilder(); + } catch (Throwable e) { e.printStackTrace(); } + System.out.println("3"); + boolean skipCloseOnExitHook = false; + System.out.println("4"); + if (Boolean.parseBoolean(args[2])) { + skipCloseOnExitHook = true; + } + AtomicReference> mapReference = new AtomicReference<>(); + System.out.println("exit hook" + skipCloseOnExitHook); + if (skipCloseOnExitHook) { + mapBuilder.skipCloseOnExitHook(skipCloseOnExitHook); + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + // In practice, do something with map before shutdown - like create a new map using data from this map. + mapReference.get().close(); + try { + System.out.println("Executing user defined shutdown hook"); + Preconditions.checkState(shutdownActionConfirmationFile.exists()); + Files.write(shutdownActionConfirmationFile.toPath(), + USER_SHUTDOWN_HOOK_EXECUTED.getBytes()); + } catch (Exception e) { + throw new RuntimeException(e); + } + })); + } else { + mapBuilder.setPreShutdownAction(() -> { + try { + System.out.println("Executing pre-shutdown action"); + Preconditions.checkState(shutdownActionConfirmationFile.exists()); + Files.write(shutdownActionConfirmationFile.toPath(), + PRE_SHUTDOWN_ACTION_EXECUTED.getBytes()); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + } + mapReference.set(mapBuilder.createPersistedTo(mapFile)); + try (ExternalMapQueryContext c = mapReference.get().queryContext(KEY)) { + c.writeLock().lock(); + Thread.sleep(30_000); + } } - private static ChronicleMapBuilder createMapBuilder() - throws IOException { + private static ChronicleMapBuilder createMapBuilder() { return ChronicleMapBuilder .of(Integer.class, Integer.class) .entries(1); @@ -203,7 +198,7 @@ public class ExitHookTest { System.out.println("Classpath: " + classpath); String className = ExitHookTest.class.getCanonicalName(); - String[] command = new String[] {javaBin, "-cp", classpath, className, + String[] command = new String[]{javaBin, "-cp", classpath, className, mapFile.getAbsolutePath(), outputFile.getAbsolutePath(), String.valueOf(skipCloseOnExitHook)}; ProcessBuilder builder = new ProcessBuilder(command); builder.inheritIO(); From 8ad372f4d1d60bffe4562fac9605c5d9b04664a2 Mon Sep 17 00:00:00 2001 From: Dmitry Pisklov Date: Thu, 4 Jun 2020 17:05:13 +0100 Subject: [PATCH 30/67] Update stress test with DTO --- .../openhft/chronicle/map/perf/MapStress.java | 106 ++++++++++++++++-- 1 file changed, 96 insertions(+), 10 deletions(-) diff --git a/src/test/java/net/openhft/chronicle/map/perf/MapStress.java b/src/test/java/net/openhft/chronicle/map/perf/MapStress.java index 8a68a19e8..ef2c4f0ae 100644 --- a/src/test/java/net/openhft/chronicle/map/perf/MapStress.java +++ b/src/test/java/net/openhft/chronicle/map/perf/MapStress.java @@ -4,19 +4,21 @@ import net.openhft.chronicle.map.ChronicleMap; import java.io.File; import java.io.IOException; +import java.io.Serializable; import java.util.Random; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.IntStream; public class MapStress { private static final File file = new File("./StressTested.cm3"); private static final int N_WRITE_THREADS = 100; private static final int N_READ_THREADS = 20; - private ChronicleMap map = ChronicleMap.of(String.class, String.class).averageKeySize(50).averageValueSize(500).entries(100_000).createOrRecoverPersistedTo(file); - private ChronicleMap readerMap = ChronicleMap.of(String.class, String.class).averageKeySize(500).averageValueSize(500).entries(100_000).createOrRecoverPersistedTo(file); + private ChronicleMap map = ChronicleMap.of(String.class, Security.class).averageKeySize(500).averageValueSize(500).entries(100_000).createOrRecoverPersistedTo(file); + private ChronicleMap readerMap = ChronicleMap.of(String.class, Security.class).averageKeySize(50).averageValueSize(500).entries(100_000).createOrRecoverPersistedTo(file); private ExecutorService executor = Executors.newFixedThreadPool(N_WRITE_THREADS + N_READ_THREADS); private ThreadLocal randomTL = ThreadLocal.withInitial(Random::new); @@ -25,6 +27,73 @@ public class MapStress { } public void stress() throws ExecutionException, InterruptedException { + Security[] secs = new Security[5]; + secs[0] = new Security(); + secs[0].region = "EMEA"; + secs[0].countryCode = "UK"; + secs[0].currency = "GBP"; + secs[0].industryGroup = "ASDFH"; + secs[0].issuer = "ASDF"; + secs[0].otc = "kajsdf"; + secs[0].securityTicker = "ASJDF"; + secs[0].securityType = "DFGH"; + secs[0].sector = "askdf"; + secs[0].securityUltimateUnderlyingTicker = "RTYU"; + secs[0].securityUnderlyingTicker = "WERT"; + + secs[1] = new Security(); + secs[1].region = "APAC"; + secs[1].countryCode = "CN"; + secs[1].currency = "CNY"; + secs[1].industryGroup = "&^*$"; + secs[1].issuer = "ASDF"; + secs[1].otc = "kajsdf"; + secs[1].securityTicker = "ASJDF"; + secs[1].securityType = "DFGH"; + secs[1].sector = "askdf"; + secs[1].securityUltimateUnderlyingTicker = "RTYU"; + secs[1].securityUnderlyingTicker = "WERT"; + + secs[2] = new Security(); + secs[2].region = "EMEA"; + secs[2].countryCode = "FR"; + secs[2].currency = "EUR"; + secs[2].industryGroup = "ASDFH"; + secs[2].issuer = "ASDF"; + secs[2].otc = "kajsdf"; + secs[2].securityTicker = "ASJDF"; + secs[2].securityType = "DFGH"; + secs[2].sector = "askdf"; + secs[2].securityUltimateUnderlyingTicker = "RTYU"; + secs[2].securityUnderlyingTicker = "TYUIO"; + + secs[3] = new Security(); + secs[3].region = "NAM"; + secs[3].countryCode = "US"; + secs[3].currency = "USD"; + secs[3].industryGroup = "ASDFH"; + secs[3].issuer = "ASDF"; + secs[3].otc = "kajsdf"; + secs[3].securityTicker = "ASJDF"; + secs[3].securityType = "DFGH"; + secs[3].sector = "askdf"; + secs[3].securityUltimateUnderlyingTicker = "RTYU"; + secs[3].securityUnderlyingTicker = "QEDFW"; + + secs[4] = new Security(); + secs[4].region = "LATAM"; + secs[4].countryCode = "PA"; + secs[4].currency = "REL"; + secs[4].industryGroup = "ASDFH"; + secs[4].issuer = "ASDF"; + secs[4].otc = "kajsdf"; + secs[4].securityTicker = "ASJDF"; + secs[4].securityType = "DFGH"; + secs[4].sector = "askdf"; + secs[4].securityUltimateUnderlyingTicker = "RTYU"; + secs[4].securityUnderlyingTicker = "RTYU"; + + Future[] futures = new Future[N_WRITE_THREADS + N_READ_THREADS]; for (int i = 0; i < N_WRITE_THREADS; i++) { String id = i + " -> "; @@ -32,13 +101,16 @@ public class MapStress { final long started = System.currentTimeMillis(); long written = 0; do { + long time = System.currentTimeMillis(); IntStream.range(0, 10).forEach(x -> { final int keyIdx = randomTL.get().nextInt(N_WRITE_THREADS); - map.put("valuekdljashjgffkljakljsdffhh" + keyIdx, "aksjdfhljkhadfjklahfjkladshfjklahdsljkfch aljiocufoipreyuvoiurywcoriucy8oiuxrauoi;dajfhadsih" + System.nanoTime() + System.currentTimeMillis()); + Security sec = secs[x%5]; + sec.calculationTimeMillis = time; + map.put("valuekdljashjgffkljakljsdffhh" + keyIdx, sec); }); written += 10; - if (written % 100_000 == 0) + if (written % 50_000 == 0) System.err.println(id + "Wrote " + written); } while (System.currentTimeMillis() - started < 100_000); }); @@ -48,14 +120,11 @@ public class MapStress { String id = i + " -> "; futures[i + N_WRITE_THREADS] = executor.submit(() -> { final long started = System.currentTimeMillis(); - long got = 0; + AtomicInteger got = new AtomicInteger(0); do { - final int keyIdx = randomTL.get().nextInt(N_WRITE_THREADS); - if (null != readerMap.get("valuekdljashjgffkljakljsdffhh" + keyIdx)) { - got++; - } + readerMap.values().forEach(s -> got.incrementAndGet()); } while (System.currentTimeMillis() - started < 100_000); - System.err.println(id + "Read total: " + got); + System.err.println(id + "Read total: " + got.get()); }); } @@ -70,4 +139,21 @@ public class MapStress { // file.delete(); new MapStress().stress(); } + + public static class Security implements Serializable { + + String securityTicker; + String securityType; + String currency; + String securityUnderlyingTicker; + String sector; + String industryGroup; + String countryCode; + String issuer; + String securityUltimateUnderlyingTicker; + String otc; + String region; + long calculationTimeMillis; + + } } From 558860a05154041edbace2931e31370488a55ec1 Mon Sep 17 00:00:00 2001 From: Dmitry Pisklov Date: Fri, 5 Jun 2020 12:48:45 +0100 Subject: [PATCH 31/67] Update stress test with size() and removes --- .../java/net/openhft/chronicle/map/perf/MapStress.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/test/java/net/openhft/chronicle/map/perf/MapStress.java b/src/test/java/net/openhft/chronicle/map/perf/MapStress.java index ef2c4f0ae..dc67677a9 100644 --- a/src/test/java/net/openhft/chronicle/map/perf/MapStress.java +++ b/src/test/java/net/openhft/chronicle/map/perf/MapStress.java @@ -102,15 +102,18 @@ public class MapStress { long written = 0; do { long time = System.currentTimeMillis(); + final Random random = randomTL.get(); IntStream.range(0, 10).forEach(x -> { - final int keyIdx = randomTL.get().nextInt(N_WRITE_THREADS); + final int keyIdx = random.nextInt(N_WRITE_THREADS * 100); Security sec = secs[x%5]; sec.calculationTimeMillis = time; map.put("valuekdljashjgffkljakljsdffhh" + keyIdx, sec); }); + int keyIdx = random.nextInt(N_WRITE_THREADS * 100); + map.remove("valuekdljashjgffkljakljsdffhh" + keyIdx); written += 10; - if (written % 50_000 == 0) + if (written % 1_000 == 0) System.err.println(id + "Wrote " + written); } while (System.currentTimeMillis() - started < 100_000); }); @@ -122,6 +125,9 @@ public class MapStress { final long started = System.currentTimeMillis(); AtomicInteger got = new AtomicInteger(0); do { + if (map.size() % 1000 == 0) { + System.err.print("."); + } readerMap.values().forEach(s -> got.incrementAndGet()); } while (System.currentTimeMillis() - started < 100_000); System.err.println(id + "Read total: " + got.get()); From 12e286f9ec539eb8ca397d745c685a3bd9b68a12 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Thu, 11 Jun 2020 19:51:48 +0100 Subject: [PATCH 32/67] Standardize how ReferenceCounted resources are managed and traced, https://github.com/OpenHFT/Chronicle-Core/issues/121 --- pom.xml | 2 +- .../chronicle/map/ReplicatedChronicleMap.java | 8 +++--- .../map/impl/stage/data/ZeroBytesStore.java | 28 +++++++++++++------ .../portfolio/PortfolioValueTest.java | 7 +++-- .../chronicle/map/BasicReplicationTest.java | 7 +++-- .../map/ChronicleMapSanityCheckTest.java | 7 +++-- .../chronicle/map/ChronicleMapTest.java | 9 +++--- .../chronicle/map/EntryCountMapTest.java | 5 ++-- .../chronicle/map/LargeEntriesTest.java | 6 ++-- .../openhft/chronicle/map/RecoverTest.java | 4 ++- .../chronicle/map/TrickyContextCasesTest.java | 19 +++++++------ .../map/example/LotsOfEntriesMain.java | 4 ++- .../openhft/chronicle/map/perf/MapStress.java | 4 ++- .../set/Issue24ChronicleSetTest.java | 4 ++- system.properties | 4 +++ 15 files changed, 79 insertions(+), 39 deletions(-) create mode 100644 system.properties diff --git a/pom.xml b/pom.xml index fb97e2b06..046fbedb0 100755 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ 4.0.0 chronicle-map - 3.19.32-SNAPSHOT + 3.19.40-SNAPSHOT OpenHFT/Chronicle-Map Chronicle-Map bundle diff --git a/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java b/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java index c1cec0737..a551cdc16 100644 --- a/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java @@ -524,11 +524,11 @@ public class ReplicatedChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap { throw new UnsupportedOperationException("Cannot get the address of nothing"); } + @Override public int peekUnsignedByte(long offset) { return 0; @@ -155,24 +157,34 @@ public enum ZeroBytesStore implements BytesStore { return true; } + @Override - public void reserve() throws IllegalStateException { + public void reserve(ReferenceOwner id) throws IllegalStateException { } @Override - public void release() throws IllegalStateException { + public boolean tryReserve(ReferenceOwner id) throws IllegalStateException { + return false; } @Override - public long refCount() { + public boolean reservedBy(ReferenceOwner owner) { + return true; + } + + @Override + public void release(ReferenceOwner id) throws IllegalStateException { + } + + @Override + public void releaseLast(ReferenceOwner id) throws IllegalStateException { + } + + @Override + public int refCount() { return 0; } - @Override - public boolean tryReserve() { - throw new UnsupportedOperationException("todo"); - } - @Override public ZeroBytesStore writeByte(long l, byte b) { throw new UnsupportedOperationException(); diff --git a/src/test/java/examples/portfolio/PortfolioValueTest.java b/src/test/java/examples/portfolio/PortfolioValueTest.java index 3beba449e..64b8c59bd 100644 --- a/src/test/java/examples/portfolio/PortfolioValueTest.java +++ b/src/test/java/examples/portfolio/PortfolioValueTest.java @@ -20,6 +20,7 @@ import net.openhft.chronicle.core.values.LongValue; import net.openhft.chronicle.map.ChronicleMap; import net.openhft.chronicle.map.ChronicleMapBuilder; import net.openhft.chronicle.map.MapSegmentContext; +import net.openhft.chronicle.threads.NamedThreadFactory; import net.openhft.chronicle.values.Values; import org.apache.commons.lang3.mutable.MutableDouble; import org.junit.Test; @@ -42,7 +43,8 @@ public class PortfolioValueTest { private static void computeValueUsingIterator(final ChronicleMap cache) throws ExecutionException, InterruptedException { long startTime = System.currentTimeMillis(); - ExecutorService executor = Executors.newFixedThreadPool(nThreads); + ExecutorService executor = Executors.newFixedThreadPool(nThreads, + new NamedThreadFactory("test")); @SuppressWarnings("unchecked") Future[] futures = new Future[nThreads]; long batchSize = (useIterator ? cache.segments() : nAssets) / nThreads; @@ -118,7 +120,8 @@ public class PortfolioValueTest { private void createData(final ChronicleMap cache) throws ExecutionException, InterruptedException { long startTime = System.currentTimeMillis(); - ExecutorService executor = Executors.newFixedThreadPool(nThreads); + ExecutorService executor = Executors.newFixedThreadPool(nThreads, + new NamedThreadFactory("test")); Future[] futures = new Future[nThreads]; long batchSize = nAssets / nThreads; diff --git a/src/test/java/net/openhft/chronicle/map/BasicReplicationTest.java b/src/test/java/net/openhft/chronicle/map/BasicReplicationTest.java index 9dc28723b..a22a4bc0b 100644 --- a/src/test/java/net/openhft/chronicle/map/BasicReplicationTest.java +++ b/src/test/java/net/openhft/chronicle/map/BasicReplicationTest.java @@ -18,6 +18,7 @@ package net.openhft.chronicle.map; import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.hash.replication.ReplicableEntry; +import net.openhft.chronicle.threads.NamedThreadFactory; import org.hamcrest.CoreMatchers; import org.junit.Test; @@ -65,7 +66,8 @@ public class BasicReplicationTest { processorThree.addDestinationMap(mapThree.acquireModificationIterator(asByte(1)), mapThree, mapOne); processorThree.addDestinationMap(mapThree.acquireModificationIterator(asByte(2)), mapThree, mapTwo); - final ExecutorService executorService = Executors.newFixedThreadPool(3); + final ExecutorService executorService = Executors.newFixedThreadPool(3, + new NamedThreadFactory("test")); executorService.submit(processorOne::processPendingChangesLoop); executorService.submit(processorTwo::processPendingChangesLoop); executorService.submit(processorThree::processPendingChangesLoop); @@ -175,7 +177,8 @@ public class BasicReplicationTest { private final ReplicatedChronicleMap sourceMap; private final ReplicatedChronicleMap destinationMap; private final Bytes buffer = Bytes.elasticByteBuffer(4096); - private final ExecutorService delayedExecutor = Executors.newSingleThreadExecutor(); + private final ExecutorService delayedExecutor = Executors.newSingleThreadExecutor( + new NamedThreadFactory("delayed")); private final AtomicInteger messagesInflight = new AtomicInteger(0); private final ArrayList keys = new ArrayList<>(); diff --git a/src/test/java/net/openhft/chronicle/map/ChronicleMapSanityCheckTest.java b/src/test/java/net/openhft/chronicle/map/ChronicleMapSanityCheckTest.java index 28c02ef66..8a12f33f1 100644 --- a/src/test/java/net/openhft/chronicle/map/ChronicleMapSanityCheckTest.java +++ b/src/test/java/net/openhft/chronicle/map/ChronicleMapSanityCheckTest.java @@ -17,6 +17,7 @@ package net.openhft.chronicle.map; import net.openhft.chronicle.core.Jvm; +import net.openhft.chronicle.threads.NamedThreadFactory; import org.junit.Test; import java.io.File; @@ -47,10 +48,12 @@ public class ChronicleMapSanityCheckTest { file.getAbsolutePath().toString()); ScheduledExecutorService producerExecutor = - Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors() - 1); + Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors() - 1, + new NamedThreadFactory("producer")); ScheduledExecutorService consumerExecutor = - Executors.newSingleThreadScheduledExecutor(); + Executors.newSingleThreadScheduledExecutor( + new NamedThreadFactory("consumer")); int N = 1000; diff --git a/src/test/java/net/openhft/chronicle/map/ChronicleMapTest.java b/src/test/java/net/openhft/chronicle/map/ChronicleMapTest.java index f6f3d4034..792964e22 100755 --- a/src/test/java/net/openhft/chronicle/map/ChronicleMapTest.java +++ b/src/test/java/net/openhft/chronicle/map/ChronicleMapTest.java @@ -23,6 +23,7 @@ import net.openhft.chronicle.bytes.BytesStore; import net.openhft.chronicle.core.values.IntValue; import net.openhft.chronicle.core.values.LongValue; import net.openhft.chronicle.set.Builder; +import net.openhft.chronicle.threads.NamedThreadFactory; import net.openhft.chronicle.values.Values; import org.junit.Ignore; import org.junit.Test; @@ -917,7 +918,7 @@ public class ChronicleMapTest { // int runs = Integer.getInteger("runs", 10); int procs = 1; // Runtime.getRuntime().availableProcessors(); int threads = procs * 3; - ExecutorService es = Executors.newFixedThreadPool(procs); + ExecutorService es = Executors.newFixedThreadPool(procs, new NamedThreadFactory("test")); for (int runs : new int[]{1, /*10, 250, 500, 1000, 2500*/}) { for (int entrySize : new int[]{240, 256}) { int valuePadding = entrySize - 16; @@ -1009,7 +1010,7 @@ public class ChronicleMapTest { int procs = Runtime.getRuntime().availableProcessors(); if (procs > 8) procs--; int threads = procs * 3; - ExecutorService es = Executors.newFixedThreadPool(procs); + ExecutorService es = Executors.newFixedThreadPool(procs, new NamedThreadFactory("test")); for (int runs : new int[]{1, 2, 5, 10, 25, 50, 100, 500, 1000, 2500}) { final long entries = runs * 1000 * 1000L; @@ -1106,7 +1107,7 @@ public class ChronicleMapTest { // int runs = Integer.getInteger("runs", 10); int procs = Runtime.getRuntime().availableProcessors(); int threads = procs * 3; // runs > 100 ? procs / 2 : procs; - ExecutorService es = Executors.newFixedThreadPool(procs); + ExecutorService es = Executors.newFixedThreadPool(procs, new NamedThreadFactory("test")); for (int runs : new int[]{10, 50, 100, 250, 500, 1000, 2500}) { // JAVA 8 produces more garbage than previous versions for internal work. // System.gc(); @@ -1185,7 +1186,7 @@ public class ChronicleMapTest { for (int j = 0; j < count; j++) { final ConcurrentMap map = new ConcurrentHashMap((int) (entries * 5 / 4), 1.0f, 1024); long start = System.currentTimeMillis(); - ExecutorService es = Executors.newFixedThreadPool(procs); + ExecutorService es = Executors.newFixedThreadPool(procs, new NamedThreadFactory("test")); for (int i = 0; i < threads; i++) { final int t = i; es.submit(new Runnable() { diff --git a/src/test/java/net/openhft/chronicle/map/EntryCountMapTest.java b/src/test/java/net/openhft/chronicle/map/EntryCountMapTest.java index 698dc5246..9f4c4236b 100644 --- a/src/test/java/net/openhft/chronicle/map/EntryCountMapTest.java +++ b/src/test/java/net/openhft/chronicle/map/EntryCountMapTest.java @@ -17,6 +17,7 @@ package net.openhft.chronicle.map; import net.openhft.chronicle.core.values.LongValue; +import net.openhft.chronicle.threads.NamedThreadFactory; import org.junit.Ignore; import org.junit.Test; @@ -116,7 +117,7 @@ public class EntryCountMapTest { public void testSmall() throws IOException, ExecutionException, InterruptedException { System.out.print("testSmall seeds"); int procs = Runtime.getRuntime().availableProcessors(); - ExecutorService es = Executors.newFixedThreadPool(procs); + ExecutorService es = Executors.newFixedThreadPool(procs, new NamedThreadFactory("test")); for (int t = 0; t < ecmTests; t++) { List> futures = new ArrayList<>(); { @@ -160,7 +161,7 @@ public class EntryCountMapTest { public void testMedium() throws IOException, ExecutionException, InterruptedException { System.out.print("testMedium seeds"); int procs = Runtime.getRuntime().availableProcessors(); - ExecutorService es = Executors.newFixedThreadPool(procs); + ExecutorService es = Executors.newFixedThreadPool(procs, new NamedThreadFactory("test")); for (int t = 0; t < ecmTests; t++) { // regression test. List> futures = new ArrayList<>(); diff --git a/src/test/java/net/openhft/chronicle/map/LargeEntriesTest.java b/src/test/java/net/openhft/chronicle/map/LargeEntriesTest.java index c3fb73ee4..fc5b9fe61 100755 --- a/src/test/java/net/openhft/chronicle/map/LargeEntriesTest.java +++ b/src/test/java/net/openhft/chronicle/map/LargeEntriesTest.java @@ -16,6 +16,7 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.threads.NamedThreadFactory; import org.junit.Ignore; import org.junit.Test; @@ -51,7 +52,7 @@ public class LargeEntriesTest { .createPersistedTo(file)) { warmUpCompression(ENTRY_SIZE); int threads = 4; //Runtime.getRuntime().availableProcessors(); - ExecutorService es = Executors.newFixedThreadPool(threads); + ExecutorService es = Executors.newFixedThreadPool(threads, new NamedThreadFactory("test")); final int block = ENTRIES / threads; for (int i = 0; i < 3; i++) { long start = System.currentTimeMillis(); @@ -119,7 +120,8 @@ public class LargeEntriesTest { { // warmUpCompression(ENTRY_SIZE); int threads = Runtime.getRuntime().availableProcessors(); - ExecutorService es = Executors.newFixedThreadPool(threads); + ExecutorService es = Executors.newFixedThreadPool(threads, + new NamedThreadFactory("test")); final int block = ENTRIES / threads; for (int i = 0; i < 3; i++) { long start = System.currentTimeMillis(); diff --git a/src/test/java/net/openhft/chronicle/map/RecoverTest.java b/src/test/java/net/openhft/chronicle/map/RecoverTest.java index abf39dece..f6c986d41 100644 --- a/src/test/java/net/openhft/chronicle/map/RecoverTest.java +++ b/src/test/java/net/openhft/chronicle/map/RecoverTest.java @@ -20,6 +20,7 @@ import net.openhft.chronicle.core.values.LongValue; import net.openhft.chronicle.hash.ChecksumEntry; import net.openhft.chronicle.hash.ChronicleHashBuilderPrivateAPI; import net.openhft.chronicle.hash.ChronicleHashCorruption; +import net.openhft.chronicle.threads.NamedThreadFactory; import net.openhft.chronicle.values.Values; import org.junit.Assert; import org.junit.Ignore; @@ -69,7 +70,8 @@ public class RecoverTest { // acquires read lock successfully assertNull(map.get(0)); - ExecutorService executorService = Executors.newSingleThreadExecutor(); + ExecutorService executorService = Executors.newSingleThreadExecutor( + new NamedThreadFactory("recoverTest")); executorService.submit(() -> { ExternalMapQueryContext c = map.queryContext(0); diff --git a/src/test/java/net/openhft/chronicle/map/TrickyContextCasesTest.java b/src/test/java/net/openhft/chronicle/map/TrickyContextCasesTest.java index f194c6a5d..82210538d 100644 --- a/src/test/java/net/openhft/chronicle/map/TrickyContextCasesTest.java +++ b/src/test/java/net/openhft/chronicle/map/TrickyContextCasesTest.java @@ -17,6 +17,7 @@ package net.openhft.chronicle.map; import net.openhft.chronicle.core.values.IntValue; +import net.openhft.chronicle.threads.NamedThreadFactory; import net.openhft.chronicle.values.Values; import org.junit.Test; @@ -65,14 +66,16 @@ public class TrickyContextCasesTest { try (ExternalMapQueryContext q = map.queryContext(1)) { MapEntry entry = q.entry(); // acquires read lock implicitly assertNotNull(entry); - Executors.newFixedThreadPool(1).submit(() -> { - // this call should try to acquire write lock, that should lead to dead lock - // but if not... - // relocates the entry for the key 1 after the entry for 2, under update lock - map.put(1, new byte[]{1, 2, 3, 4, 5}); - // puts the entry for 3 at the place of the entry for the key 1, under update lock - map.put(3, new byte[]{3}); - }).get(); + Executors.newFixedThreadPool(1, + new NamedThreadFactory("test")) + .submit(() -> { + // this call should try to acquire write lock, that should lead to dead lock + // but if not... + // relocates the entry for the key 1 after the entry for 2, under update lock + map.put(1, new byte[]{1, 2, 3, 4, 5}); + // puts the entry for 3 at the place of the entry for the key 1, under update lock + map.put(3, new byte[]{3}); + }).get(); // prints [3] System.out.println(Arrays.toString(entry.value().get())); } diff --git a/src/test/java/net/openhft/chronicle/map/example/LotsOfEntriesMain.java b/src/test/java/net/openhft/chronicle/map/example/LotsOfEntriesMain.java index 4d57453d1..a33bb60ca 100755 --- a/src/test/java/net/openhft/chronicle/map/example/LotsOfEntriesMain.java +++ b/src/test/java/net/openhft/chronicle/map/example/LotsOfEntriesMain.java @@ -18,6 +18,7 @@ package net.openhft.chronicle.map.example; import net.openhft.chronicle.map.ChronicleMap; import net.openhft.chronicle.map.ChronicleMapBuilder; +import net.openhft.chronicle.threads.NamedThreadFactory; import net.openhft.chronicle.values.Array; import net.openhft.chronicle.values.Values; @@ -59,7 +60,8 @@ public class LotsOfEntriesMain { .averageKeySize((Math.log(1.024) - Math.log(0.024)) * 24 + 2) .createPersistedTo(file); int threads = Runtime.getRuntime().availableProcessors(); - ExecutorService es = Executors.newFixedThreadPool(threads); + ExecutorService es = Executors.newFixedThreadPool(threads, + new NamedThreadFactory("test")); long block = (entries + threads - 1) / threads; final long start = System.nanoTime(); diff --git a/src/test/java/net/openhft/chronicle/map/perf/MapStress.java b/src/test/java/net/openhft/chronicle/map/perf/MapStress.java index dc67677a9..12543389d 100644 --- a/src/test/java/net/openhft/chronicle/map/perf/MapStress.java +++ b/src/test/java/net/openhft/chronicle/map/perf/MapStress.java @@ -1,6 +1,7 @@ package net.openhft.chronicle.map.perf; import net.openhft.chronicle.map.ChronicleMap; +import net.openhft.chronicle.threads.NamedThreadFactory; import java.io.File; import java.io.IOException; @@ -20,7 +21,8 @@ public class MapStress { private ChronicleMap map = ChronicleMap.of(String.class, Security.class).averageKeySize(500).averageValueSize(500).entries(100_000).createOrRecoverPersistedTo(file); private ChronicleMap readerMap = ChronicleMap.of(String.class, Security.class).averageKeySize(50).averageValueSize(500).entries(100_000).createOrRecoverPersistedTo(file); - private ExecutorService executor = Executors.newFixedThreadPool(N_WRITE_THREADS + N_READ_THREADS); + private ExecutorService executor = Executors.newFixedThreadPool(N_WRITE_THREADS + N_READ_THREADS, + new NamedThreadFactory("mapStress")); private ThreadLocal randomTL = ThreadLocal.withInitial(Random::new); public MapStress() throws IOException { diff --git a/src/test/java/net/openhft/chronicle/set/Issue24ChronicleSetTest.java b/src/test/java/net/openhft/chronicle/set/Issue24ChronicleSetTest.java index eb8a1b2e3..48b76c5f6 100644 --- a/src/test/java/net/openhft/chronicle/set/Issue24ChronicleSetTest.java +++ b/src/test/java/net/openhft/chronicle/set/Issue24ChronicleSetTest.java @@ -18,6 +18,7 @@ package net.openhft.chronicle.set; import net.openhft.chronicle.hash.ChronicleHash; import net.openhft.chronicle.hash.ChronicleHashBuilder; +import net.openhft.chronicle.threads.NamedThreadFactory; import org.junit.Test; import java.io.File; @@ -55,7 +56,8 @@ public class Issue24ChronicleSetTest { @Test public void issue24ChronicleSetTest() throws IOException { ChronicleSet set = initSet(String.class, 1_000_000, 30); - ExecutorService executor = Executors.newFixedThreadPool(5); + ExecutorService executor = Executors.newFixedThreadPool(5, + new NamedThreadFactory("test")); for (int i = 0; i < 10; i++) { Runnable worker = new WorkerThread(set); executor.execute(worker); diff --git a/system.properties b/system.properties new file mode 100644 index 000000000..677f6b473 --- /dev/null +++ b/system.properties @@ -0,0 +1,4 @@ +# Tracing if resources are closed/released correctly. +jvm.resource.tracing=true +# for profiling +jvm.safepoint.enabled=false \ No newline at end of file From fcd3c4d2eb7a2fd2042797b48b916321d73b3204 Mon Sep 17 00:00:00 2001 From: Jerry Shea Date: Mon, 15 Jun 2020 08:56:21 +1000 Subject: [PATCH 33/67] clean up: com.intellij:annotations -> org.jetbrains:annotations --- pom.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 046fbedb0..653b9fec0 100755 --- a/pom.xml +++ b/pom.xml @@ -70,9 +70,8 @@ - com.intellij + org.jetbrains annotations - 12.0 From 4a5983b27436cc750990ddddcda82c05e1fe91a6 Mon Sep 17 00:00:00 2001 From: Jerry Shea Date: Mon, 15 Jun 2020 09:19:34 +1000 Subject: [PATCH 34/67] Don't com.intellij:annotations -> org.jetbrains:annotations #222 --- pom.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 653b9fec0..d96a1520a 100755 --- a/pom.xml +++ b/pom.xml @@ -70,8 +70,10 @@ - org.jetbrains + + com.intellij annotations + 12.0 From a278b5930026c44164a73587db36fd29b2ba4f04 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Mon, 15 Jun 2020 12:48:56 +0100 Subject: [PATCH 35/67] Added CleaningThreadLocal and CleaningThread to clean thread local resources on exit, https://github.com/OpenHFT/Chronicle-Core/issues/122 --- .../java/net/openhft/chronicle/map/perf/MapStress.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/test/java/net/openhft/chronicle/map/perf/MapStress.java b/src/test/java/net/openhft/chronicle/map/perf/MapStress.java index 12543389d..7ad0a06a5 100644 --- a/src/test/java/net/openhft/chronicle/map/perf/MapStress.java +++ b/src/test/java/net/openhft/chronicle/map/perf/MapStress.java @@ -7,10 +7,7 @@ import java.io.File; import java.io.IOException; import java.io.Serializable; import java.util.Random; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; +import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.IntStream; @@ -23,7 +20,6 @@ public class MapStress { private ExecutorService executor = Executors.newFixedThreadPool(N_WRITE_THREADS + N_READ_THREADS, new NamedThreadFactory("mapStress")); - private ThreadLocal randomTL = ThreadLocal.withInitial(Random::new); public MapStress() throws IOException { } @@ -104,7 +100,7 @@ public class MapStress { long written = 0; do { long time = System.currentTimeMillis(); - final Random random = randomTL.get(); + final Random random = ThreadLocalRandom.current(); IntStream.range(0, 10).forEach(x -> { final int keyIdx = random.nextInt(N_WRITE_THREADS * 100); Security sec = secs[x%5]; From 0c5a5c89098fe8fe3a5547e6d3da0b1ca1b266aa Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Mon, 15 Jun 2020 16:17:07 +0100 Subject: [PATCH 36/67] Add `throwExceptionIfClosed();` to most public methods for classes implementing Closeable, https://github.com/OpenHFT/Chronicle-Core/issues/116 --- .../hash/impl/VanillaChronicleHash.java | 29 +++++++++++++++++- .../impl/stage/iter/HashSegmentIteration.java | 8 +++++ .../impl/stage/iter/SegmentsRecovery.java | 1 + .../map/OldDeletedEntriesCleanupThread.java | 2 ++ .../chronicle/map/ReplicatedChronicleMap.java | 30 ++++++++++++++++++- .../chronicle/map/VanillaChronicleMap.java | 29 ++++++++++++++++++ .../impl/stage/iter/MapSegmentIteration.java | 2 ++ .../iter/ReplicatedMapSegmentIteration.java | 11 +++++++ .../net/openhft/chronicle/set/SetFromMap.java | 24 +++++++++++++++ 9 files changed, 134 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java index 1d613653b..5ec3561c0 100755 --- a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java @@ -38,7 +38,6 @@ import net.openhft.chronicle.map.ChronicleMapBuilder; import net.openhft.chronicle.values.Values; import net.openhft.chronicle.wire.Marshallable; import net.openhft.chronicle.wire.WireIn; -import net.openhft.chronicle.wire.WireInternal; import net.openhft.chronicle.wire.WireOut; import org.jetbrains.annotations.NotNull; @@ -233,11 +232,13 @@ public abstract class VanillaChronicleHash "dataFileVersion").text(dataFileVersion); wireOut.write(() -> "keyClass").typeLiteral(keyClass); @@ -338,6 +340,7 @@ public abstract class VanillaChronicleHash 0; } @Override public long offHeapMemoryUsed() { + throwExceptionIfClosed(); return resources.totalMemory(); } public long allocateTier() { + throwExceptionIfClosed(); globalMutableStateLock(); try { long tiersInUse = globalMutableState.getExtraTiersInUse(); @@ -837,6 +855,7 @@ public abstract class VanillaChronicleHash> allContexts() { + throwExceptionIfClosed(); return Collections.unmodifiableList(resources.contexts()); } @@ -1056,6 +1082,7 @@ public abstract class VanillaChronicleHash> } public long tierEntriesForIteration() { + throwExceptionIfClosed(); return s.tierEntries(); } @@ -67,6 +68,7 @@ public abstract class HashSegmentIteration> public abstract boolean hashLookupEntryInit(); public void initHashLookupEntry(long entry) { + throwExceptionIfClosed(); hashLookupEntry = entry; } @@ -74,6 +76,7 @@ public abstract class HashSegmentIteration> @Override public boolean forEachSegmentEntryWhile(Predicate predicate) { + throwExceptionIfClosed(); checkOnEachPublicOperation.checkOnEachPublicOperation(); s.innerUpdateLock.lock(); return innerForEachSegmentEntryWhile(predicate); @@ -174,10 +177,12 @@ public abstract class HashSegmentIteration> } public void hookAfterEachIteration() { + throwExceptionIfClosed(); } @Override public void forEachSegmentEntry(Consumer action) { + throwExceptionIfClosed(); forEachSegmentEntryWhile(e -> { action.accept(e); return true; @@ -185,6 +190,7 @@ public abstract class HashSegmentIteration> } public void checkEntryNotRemovedOnThisIteration() { + throwExceptionIfClosed(); if (entryRemovedOnThisIterationInit()) { throw new IllegalStateException( hh.h().toIdentityString() + ": Entry was already removed on this iteration"); @@ -193,6 +199,7 @@ public abstract class HashSegmentIteration> @Override public void doRemove() { + throwExceptionIfClosed(); checkOnEachPublicOperation.checkOnEachPublicOperation(); s.innerWriteLock.lock(); try { @@ -204,6 +211,7 @@ public abstract class HashSegmentIteration> } public void iterationRemove() { + throwExceptionIfClosed(); // this condition mean -- some other entry taken place of the removed one if (hh.h().hashLookup.remove(s.tierBaseAddr, hlp.hashLookupPos) != hlp.hashLookupPos) { // if so, should make step back, to compensate step forward on the next iteration, diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/iter/SegmentsRecovery.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/iter/SegmentsRecovery.java index b8ce94f24..920ea52a7 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/iter/SegmentsRecovery.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/iter/SegmentsRecovery.java @@ -44,6 +44,7 @@ public abstract class SegmentsRecovery implements IterationContext { public void recoverSegments( ChronicleHashCorruption.Listener corruptionListener, ChronicleHashCorruptionImpl corruption) { + throwExceptionIfClosed(); VanillaChronicleHash h = hh.h(); for (int segmentIndex = 0; segmentIndex < h.actualSegments; segmentIndex++) { s.initSegmentIndex(segmentIndex); diff --git a/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupThread.java b/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupThread.java index b6dbbcebf..6c2fbb4b9 100644 --- a/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupThread.java +++ b/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupThread.java @@ -114,6 +114,7 @@ class OldDeletedEntriesCleanupThread extends Thread @Override public void run() { + throwExceptionIfClosed(); if (System.currentTimeMillis() - startTime < 1_000) return; @@ -175,6 +176,7 @@ class OldDeletedEntriesCleanupThread extends Thread @Override public boolean test(ReplicableEntry e) { + throwExceptionIfClosed(); if (shutdown) return false; if (e instanceof MapAbsentEntry) { diff --git a/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java b/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java index a551cdc16..16fce38eb 100644 --- a/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java @@ -154,6 +154,7 @@ public class ReplicatedChronicleMap extends VanillaChronicleMap "tierModIterBitSetSizeInBits").int64(tierModIterBitSetSizeInBits); @@ -171,11 +172,13 @@ public class ReplicatedChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap raise change for all changeCount.incrementAndGet(); raiseChangeForAllExcept(tierIndex, pos, (byte) -1); } public void raiseChangeFor(long tierIndex, long pos, byte remoteIdentifier) { + throwExceptionIfClosed(); acquireModificationIterator(remoteIdentifier).raiseChange0(tierIndex, pos); } public void raiseChangeForAllExcept(long tierIndex, long pos, byte remoteIdentifier) { + throwExceptionIfClosed(); updateModificationIteratorsArray(); if (tierIndex <= actualSegments) { long segmentIndex = tierIndex - 1; @@ -373,6 +389,7 @@ public class ReplicatedChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap keys) { + throwExceptionIfClosed(); if (payload != null) writePayload(payload, destination); if (entry != null) @@ -571,6 +593,7 @@ public class ReplicatedChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap c = iterationContext()) { // iterate over all the segments and mark bit in the modification iterator // that correspond to entries with an older timestamp @@ -934,6 +961,7 @@ public class ReplicatedChronicleMap extends VanillaChronicleMap @Override public void writeMarshallable(@NotNull WireOut wireOut) { + ; super.writeMarshallable(wireOut); wireOut.write(() -> "valueClass").typeLiteral(valueClass); @@ -161,6 +162,7 @@ public class VanillaChronicleMap @Override public void initTransients() { + throwExceptionIfClosed(); super.initTransients(); initOwnTransients(); } @@ -168,6 +170,7 @@ public class VanillaChronicleMap public void recover( ChronicleHashResources resources, ChronicleHashCorruption.Listener corruptionListener, ChronicleHashCorruptionImpl corruption) throws IOException { + throwExceptionIfClosed(); basicRecover(resources, corruptionListener, corruption); try (IterationContext iterationContext = iterationContext()) { iterationContext.recoverSegments(corruptionListener, corruption); @@ -212,21 +215,25 @@ public class VanillaChronicleMap @Override public Class keyClass() { + throwExceptionIfClosed(); return (Class) keyClass; } @Override public Type keyType() { + throwExceptionIfClosed(); return keyClass; } @Override public Class valueClass() { + throwExceptionIfClosed(); return (Class) valueClass; } @Override public Type valueType() { + throwExceptionIfClosed(); return valueClass; } @@ -240,11 +247,13 @@ public class VanillaChronicleMap @Override public int remainingAutoResizes() { + throwExceptionIfClosed(); return (int) (maxTiers() - tiersUsed()); } @Override public short percentageFreeSpace() { + throwExceptionIfClosed(); double totalUsed = 0; double totalSize = 0; @@ -310,11 +319,13 @@ public class VanillaChronicleMap @Override public int hashCode() { + throwExceptionIfClosed(); return mapHashCode(); } @Override public boolean equals(Object obj) { + throwExceptionIfClosed(); return mapEquals(obj); } @@ -330,6 +341,7 @@ public class VanillaChronicleMap @Override public String toIdentityString() { + throwExceptionIfClosed(); if (identityString == null) identityString = makeIdentityString(); return identityString; @@ -347,6 +359,7 @@ public class VanillaChronicleMap @Override public void clear() { + throwExceptionIfClosed(); forEachEntry(c -> c.context().remove(c)); } @@ -357,6 +370,7 @@ public class VanillaChronicleMap } public void alignReadPosition(Bytes entry) { + throwExceptionIfClosed(); long positionAddr = entry.addressForRead(entry.readPosition()); long skip = alignAddr(positionAddr, alignment) - positionAddr; if (skip > 0) @@ -520,6 +534,7 @@ public class VanillaChronicleMap @Override public V get(Object key) { + throwExceptionIfClosed(); return defaultEntryOperationsAndMethods ? optimizedGet(key, null) : defaultGet(key); } @@ -693,6 +708,7 @@ public class VanillaChronicleMap @Override public V getUsing(K key, V usingValue) { + throwExceptionIfClosed(); return defaultEntryOperationsAndMethods ? optimizedGet(key, usingValue) : defaultGetUsing(key, usingValue); } @@ -707,6 +723,7 @@ public class VanillaChronicleMap @Override public V acquireUsing(K key, V usingValue) { + throwExceptionIfClosed(); try (QueryContextInterface q = queryContext(key)) { return acquireUsingBody(q, usingValue); } @@ -720,6 +737,7 @@ public class VanillaChronicleMap @Override public V putIfAbsent(K key, V value) { + throwExceptionIfClosed(); checkValue(value); try (QueryContextInterface q = queryContext(key)) { methods.putIfAbsent(q, q.inputValueDataAccess().getData(value), q.defaultReturnValue()); @@ -729,6 +747,7 @@ public class VanillaChronicleMap @Override public boolean remove(Object key, Object value) { + throwExceptionIfClosed(); if (value == null) return false; // ConcurrentHashMap compatibility V v = checkValue(value); @@ -739,6 +758,7 @@ public class VanillaChronicleMap @Override public boolean replace(K key, V oldValue, V newValue) { + throwExceptionIfClosed(); checkValue(oldValue); checkValue(newValue); try (QueryContextInterface q = queryContext(key)) { @@ -749,6 +769,7 @@ public class VanillaChronicleMap @Override public V replace(K key, V value) { + throwExceptionIfClosed(); checkValue(value); try (QueryContextInterface q = queryContext(key)) { methods.replace(q, q.inputValueDataAccess().getData(value), q.defaultReturnValue()); @@ -758,6 +779,7 @@ public class VanillaChronicleMap @Override public boolean containsKey(Object key) { + throwExceptionIfClosed(); try (QueryContextInterface q = queryContext(key)) { return methods.containsKey(q); } @@ -765,6 +787,7 @@ public class VanillaChronicleMap @Override public V put(K key, V value) { + throwExceptionIfClosed(); checkValue(value); try (QueryContextInterface q = queryContext(key)) { Data valueData = q.inputValueDataAccess().getData(value); @@ -777,6 +800,7 @@ public class VanillaChronicleMap @Override public V remove(Object key) { + throwExceptionIfClosed(); try (QueryContextInterface q = queryContext(key)) { InstanceReturnValue returnValue = removeReturnsNull ? NullReturnValue.get() : q.defaultReturnValue(); @@ -788,6 +812,7 @@ public class VanillaChronicleMap @Override public V merge(K key, V value, BiFunction remappingFunction) { + throwExceptionIfClosed(); try (QueryContextInterface q = queryContext(key)) { methods.merge(q, q.inputValueDataAccess().getData(value), remappingFunction, q.defaultReturnValue()); @@ -797,6 +822,7 @@ public class VanillaChronicleMap @Override public V compute(K key, BiFunction remappingFunction) { + throwExceptionIfClosed(); try (QueryContextInterface q = queryContext(key)) { methods.compute(q, remappingFunction, q.defaultReturnValue()); return q.defaultReturnValue().returnValue(); @@ -805,6 +831,7 @@ public class VanillaChronicleMap @Override public V computeIfAbsent(K key, Function mappingFunction) { + throwExceptionIfClosed(); try (QueryContextInterface q = queryContext(key)) { methods.computeIfAbsent(q, mappingFunction, q.defaultReturnValue()); return q.defaultReturnValue().returnValue(); @@ -814,6 +841,7 @@ public class VanillaChronicleMap @Override public V computeIfPresent(K key, BiFunction remappingFunction) { + throwExceptionIfClosed(); try (QueryContextInterface q = queryContext(key)) { methods.computeIfPresent(q, remappingFunction, q.defaultReturnValue()); return q.defaultReturnValue().returnValue(); @@ -821,6 +849,7 @@ public class VanillaChronicleMap } public void verifyTierCountersAreaData() { + throwExceptionIfClosed(); for (int i = 0; i < actualSegments; i++) { try (MapSegmentContext c = segmentContext(i)) { Method verifyTierCountersAreaData = diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/iter/MapSegmentIteration.java b/src/main/java/net/openhft/chronicle/map/impl/stage/iter/MapSegmentIteration.java index 4532c782b..72540a242 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/iter/MapSegmentIteration.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/iter/MapSegmentIteration.java @@ -40,11 +40,13 @@ public abstract class MapSegmentIteration extends HashSegmentIteration< @Override public void hookAfterEachIteration() { + throwExceptionIfClosed(); wrappedValueInstanceDataHolder.closeValue(); } @Override public void doReplaceValue(Data newValue) { + throwExceptionIfClosed(); checkOnEachPublicOperation.checkOnEachPublicOperation(); try { entry.innerDefaultReplaceValue(newValue); diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/iter/ReplicatedMapSegmentIteration.java b/src/main/java/net/openhft/chronicle/map/impl/stage/iter/ReplicatedMapSegmentIteration.java index 46b1a8c55..d4c5c5f1a 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/iter/ReplicatedMapSegmentIteration.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/iter/ReplicatedMapSegmentIteration.java @@ -60,21 +60,25 @@ public abstract class ReplicatedMapSegmentIteration extends MapSegmentI @Override public boolean shouldTestEntry() { + throwExceptionIfClosed(); return entriesToTest == ALL || !e.entryDeleted(); } @Override public Object entryForIteration() { + throwExceptionIfClosed(); return !e.entryDeleted() ? entryDelegating : absentEntryDelegating; } @Override public long tierEntriesForIteration() { + throwExceptionIfClosed(); return entriesToTest == ALL ? s.tierEntries() : s.tierEntries() - s.tierDeleted(); } @Override public void doReplaceValue(Data newValue) { + throwExceptionIfClosed(); checkOnEachPublicOperation.checkOnEachPublicOperation(); try { entry.innerDefaultReplaceValue(newValue); @@ -87,6 +91,7 @@ public abstract class ReplicatedMapSegmentIteration extends MapSegmentI @Override public boolean forEachSegmentEntryWhile(Predicate> predicate) { + throwExceptionIfClosed(); checkOnEachPublicOperation.checkOnEachPublicOperation(); initEntriesToTest(PRESENT); s.innerUpdateLock.lock(); @@ -96,6 +101,7 @@ public abstract class ReplicatedMapSegmentIteration extends MapSegmentI @Override public boolean forEachSegmentReplicableEntryWhile( Predicate predicate) { + throwExceptionIfClosed(); checkOnEachPublicOperation.checkOnEachPublicOperation(); initEntriesToTest(ALL); s.innerUpdateLock.lock(); @@ -104,6 +110,7 @@ public abstract class ReplicatedMapSegmentIteration extends MapSegmentI @Override public void forEachSegmentReplicableEntry(Consumer action) { + throwExceptionIfClosed(); forEachSegmentReplicableEntryWhile(e -> { action.accept(e); return true; @@ -112,6 +119,7 @@ public abstract class ReplicatedMapSegmentIteration extends MapSegmentI @Override public void doRemove() { + throwExceptionIfClosed(); checkOnEachPublicOperation.checkOnEachPublicOperation(); try { if (e.valueSize > dummyValue.size()) @@ -128,6 +136,7 @@ public abstract class ReplicatedMapSegmentIteration extends MapSegmentI @Override public void doRemoveCompletely() { + throwExceptionIfClosed(); boolean wasDeleted = e.entryDeleted(); super.doRemove(); ru.dropChange(); @@ -136,6 +145,7 @@ public abstract class ReplicatedMapSegmentIteration extends MapSegmentI } public void doInsert(Data value) { + throwExceptionIfClosed(); checkOnEachPublicOperation.checkOnEachPublicOperation(); if (e.entryDeleted()) { try { @@ -155,6 +165,7 @@ public abstract class ReplicatedMapSegmentIteration extends MapSegmentI } public void doInsert() { + throwExceptionIfClosed(); if (mh.set() == null) throw new IllegalStateException(mh.h().toIdentityString() + ": Called SetAbsentEntry.doInsert() from Map context"); diff --git a/src/main/java/net/openhft/chronicle/set/SetFromMap.java b/src/main/java/net/openhft/chronicle/set/SetFromMap.java index c31204622..2e5bf508d 100644 --- a/src/main/java/net/openhft/chronicle/set/SetFromMap.java +++ b/src/main/java/net/openhft/chronicle/set/SetFromMap.java @@ -51,34 +51,42 @@ class SetFromMap extends AbstractSet implements ChronicleSet { } public void clear() { + throwExceptionIfClosed(); m.clear(); } public int size() { + throwExceptionIfClosed(); return m.size(); } public boolean isEmpty() { + throwExceptionIfClosed(); return m.isEmpty(); } public boolean contains(Object o) { + throwExceptionIfClosed(); return m.containsKey(o); } public boolean remove(Object o) { + throwExceptionIfClosed(); return m.remove(o, DUMMY_VALUE); } public boolean add(E e) { + throwExceptionIfClosed(); return m.putIfAbsent(e, DUMMY_VALUE) == null; } public Iterator iterator() { + throwExceptionIfClosed(); return s.iterator(); } public Object[] toArray() { + throwExceptionIfClosed(); return s.toArray(); } @@ -92,6 +100,7 @@ class SetFromMap extends AbstractSet implements ChronicleSet { @Override public String toIdentityString() { + throwExceptionIfClosed(); return "ChronicleSet{" + "name=" + name() + ", file=" + file() + @@ -100,43 +109,52 @@ class SetFromMap extends AbstractSet implements ChronicleSet { } public int hashCode() { + throwExceptionIfClosed(); return s.hashCode(); } public boolean equals(Object o) { + throwExceptionIfClosed(); return o == this || s.equals(o); } public boolean containsAll(Collection c) { + throwExceptionIfClosed(); return s.containsAll(c); } public boolean removeAll(Collection c) { + throwExceptionIfClosed(); return s.removeAll(c); } public boolean retainAll(Collection c) { + throwExceptionIfClosed(); return s.retainAll(c); } // addAll is the only inherited implementation @Override public long longSize() { + throwExceptionIfClosed(); return m.longSize(); } @Override public long offHeapMemoryUsed() { + throwExceptionIfClosed(); return m.offHeapMemoryUsed(); } @Override public Class keyClass() { + throwExceptionIfClosed(); return m.keyClass(); } @Override public Type keyType() { + throwExceptionIfClosed(); return m.keyType(); } @@ -171,6 +189,7 @@ class SetFromMap extends AbstractSet implements ChronicleSet { @Override public int segments() { + throwExceptionIfClosed(); return m.segments(); } @@ -178,23 +197,27 @@ class SetFromMap extends AbstractSet implements ChronicleSet { @Override public boolean forEachEntryWhile(Predicate> predicate) { + throwExceptionIfClosed(); Objects.requireNonNull(predicate); return m.forEachEntryWhile(e -> predicate.test(((SetEntry) e))); } @Override public void forEachEntry(Consumer> action) { + throwExceptionIfClosed(); Objects.requireNonNull(action); m.forEachEntry(e -> action.accept(((SetEntry) e))); } @Override public File file() { + throwExceptionIfClosed(); return m.file(); } @Override public String name() { + throwExceptionIfClosed(); return m.name(); } @@ -205,6 +228,7 @@ class SetFromMap extends AbstractSet implements ChronicleSet { @Override public boolean isOpen() { + throwExceptionIfClosed(); return m.isOpen(); } } From b167ec59eb6b53b8e0952349e074b35a760ec25d Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Tue, 16 Jun 2020 06:23:34 +0100 Subject: [PATCH 37/67] Add `throwExceptionIfClosed();` to most public methods for classes implementing Closeable, https://github.com/OpenHFT/Chronicle-Core/issues/116 --- src/main/java/net/openhft/chronicle/map/MapClosable.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/openhft/chronicle/map/MapClosable.java b/src/main/java/net/openhft/chronicle/map/MapClosable.java index dfc5dc9c0..d775ea379 100644 --- a/src/main/java/net/openhft/chronicle/map/MapClosable.java +++ b/src/main/java/net/openhft/chronicle/map/MapClosable.java @@ -6,6 +6,7 @@ public interface MapClosable extends Closeable { @Override default boolean isClosed() { - throw new UnsupportedOperationException(); + // if we don't know, pretend it is not. + return false; } } From 8dfc91b1eb2331118e41e8b56bd1cedb11fc525f Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Thu, 18 Jun 2020 13:17:58 +0100 Subject: [PATCH 38/67] Cody tidy and optimise the tracing code. --- docs/CM_FAQs.adoc | 3 - docs/CM_Replication.adoc | 1 - .../hash/impl/VanillaChronicleHash.java | 78 +++++++++++------ .../impl/stage/iter/HashSegmentIteration.java | 24 ++++-- .../impl/stage/iter/SegmentsRecovery.java | 3 +- .../chronicle/map/ChronicleMapBuilder.java | 3 +- .../map/OldDeletedEntriesCleanupThread.java | 6 +- .../chronicle/map/ReplicatedChronicleMap.java | 81 +++++++++++------- .../chronicle/map/VanillaChronicleMap.java | 83 ++++++++++++------- .../map/impl/stage/data/ZeroBytesStore.java | 6 +- .../impl/stage/iter/MapSegmentIteration.java | 6 +- .../iter/ReplicatedMapSegmentIteration.java | 33 +++++--- .../net/openhft/chronicle/set/SetFromMap.java | 72 ++++++++++------ .../openhft/chronicle/map/perf/MapStress.java | 3 +- .../chronicle/map/watcher/MapFileManager.java | 3 +- 15 files changed, 260 insertions(+), 145 deletions(-) diff --git a/docs/CM_FAQs.adoc b/docs/CM_FAQs.adoc index 0029907d8..c890c8e3c 100755 --- a/docs/CM_FAQs.adoc +++ b/docs/CM_FAQs.adoc @@ -40,13 +40,11 @@ Does Chronicle Map work by using Memory Mapped Files? ===== Answer Yes; Chronicle Map uses memory mapped files see https://en.wikipedia.org/wiki/Memory-mapped_file. This works the same way on both Linux and Windows. - == Is there a difference in performance between Linux and Windows systems? ===== Question Is there a difference in performance between Linux and Windows systems? - ===== Answer The same code is run on both Windows and Linux. However, we encourage all our clients to use Linux, as it has improved handling of memory mapped files over Windows. @@ -80,6 +78,5 @@ For Chronicle Map, it is somewhat more complicated because Chronicle Map reads a It follows that if you have quite a few maps, especially large maps, and your page cache is not large enough to hold all of these maps, then a read, or write, to a random entry may cause a cache miss. This in turn would cause a disk read or write. If you were going to install high-speed SSDs, Chronicle recommends that you use them to store the Chronicle maps and leave the slower cheap disks for the Chronicle queues. In addition, you should avoid using network attached storage, as this usually offers worst performance than local disks. - ''' <<../ReadMe.adoc#,Back to ReadMe>> diff --git a/docs/CM_Replication.adoc b/docs/CM_Replication.adoc index f96fbc350..a41c44058 100755 --- a/docs/CM_Replication.adoc +++ b/docs/CM_Replication.adoc @@ -164,7 +164,6 @@ try (ReplicatedMap clusterOnHost1 = createCluster(CLUSTER_YAML, 1); } .... - This example is available in the repository https://github.com/ChronicleEnterprise/Chronicle-Map-Enterprise-Demo/blob/master/Example1/src/main/java/software/chronicle/enterprise/map/ThreeWayMapReplicationExampleMain.java[here] == Replication event logging diff --git a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java index 5ec3561c0..ebbfd9a63 100755 --- a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java @@ -239,7 +239,8 @@ public abstract class VanillaChronicleHash 0; + + return globalMutableState.getAllocatedExtraTierBulks() > 0; } @Override public long offHeapMemoryUsed() { throwExceptionIfClosed(); - return resources.totalMemory(); + + return resources.totalMemory(); } public long allocateTier() { throwExceptionIfClosed(); - globalMutableStateLock(); + + globalMutableStateLock(); try { long tiersInUse = globalMutableState.getExtraTiersInUse(); if (tiersInUse >= maxExtraTiers) { @@ -856,7 +873,8 @@ public abstract class VanillaChronicleHash> allContexts() { throwExceptionIfClosed(); - return Collections.unmodifiableList(resources.contexts()); + + return Collections.unmodifiableList(resources.contexts()); } public static class TierBulkData { @@ -1083,7 +1108,8 @@ public abstract class VanillaChronicleHash> public long tierEntriesForIteration() { throwExceptionIfClosed(); - return s.tierEntries(); + + return s.tierEntries(); } abstract boolean entryRemovedOnThisIterationInit(); @@ -69,7 +70,8 @@ public abstract class HashSegmentIteration> public void initHashLookupEntry(long entry) { throwExceptionIfClosed(); - hashLookupEntry = entry; + + hashLookupEntry = entry; } abstract void closeHashLookupEntry(); @@ -77,7 +79,8 @@ public abstract class HashSegmentIteration> @Override public boolean forEachSegmentEntryWhile(Predicate predicate) { throwExceptionIfClosed(); - checkOnEachPublicOperation.checkOnEachPublicOperation(); + + checkOnEachPublicOperation.checkOnEachPublicOperation(); s.innerUpdateLock.lock(); return innerForEachSegmentEntryWhile(predicate); } @@ -178,12 +181,14 @@ public abstract class HashSegmentIteration> public void hookAfterEachIteration() { throwExceptionIfClosed(); - } + + } @Override public void forEachSegmentEntry(Consumer action) { throwExceptionIfClosed(); - forEachSegmentEntryWhile(e -> { + + forEachSegmentEntryWhile(e -> { action.accept(e); return true; }); @@ -191,7 +196,8 @@ public abstract class HashSegmentIteration> public void checkEntryNotRemovedOnThisIteration() { throwExceptionIfClosed(); - if (entryRemovedOnThisIterationInit()) { + + if (entryRemovedOnThisIterationInit()) { throw new IllegalStateException( hh.h().toIdentityString() + ": Entry was already removed on this iteration"); } @@ -200,7 +206,8 @@ public abstract class HashSegmentIteration> @Override public void doRemove() { throwExceptionIfClosed(); - checkOnEachPublicOperation.checkOnEachPublicOperation(); + + checkOnEachPublicOperation.checkOnEachPublicOperation(); s.innerWriteLock.lock(); try { iterationRemove(); @@ -212,7 +219,8 @@ public abstract class HashSegmentIteration> public void iterationRemove() { throwExceptionIfClosed(); - // this condition mean -- some other entry taken place of the removed one + + // this condition mean -- some other entry taken place of the removed one if (hh.h().hashLookup.remove(s.tierBaseAddr, hlp.hashLookupPos) != hlp.hashLookupPos) { // if so, should make step back, to compensate step forward on the next iteration, // to consume the shifted entry diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/iter/SegmentsRecovery.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/iter/SegmentsRecovery.java index 920ea52a7..a987cf71c 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/iter/SegmentsRecovery.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/iter/SegmentsRecovery.java @@ -45,7 +45,8 @@ public abstract class SegmentsRecovery implements IterationContext { ChronicleHashCorruption.Listener corruptionListener, ChronicleHashCorruptionImpl corruption) { throwExceptionIfClosed(); - VanillaChronicleHash h = hh.h(); + + VanillaChronicleHash h = hh.h(); for (int segmentIndex = 0; segmentIndex < h.actualSegments; segmentIndex++) { s.initSegmentIndex(segmentIndex); resetSegmentLock(corruptionListener, corruption); diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java index e7e7d81b8..7596127cc 100755 --- a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java +++ b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java @@ -330,8 +330,7 @@ public final class ChronicleMapBuilder implements return valueBuilder.sizeIsStaticallyKnown; } - - private static void checkSegments(long segments) { +private static void checkSegments(long segments) { if (segments <= 0) { throw new IllegalArgumentException("segments should be positive, " + segments + " given"); diff --git a/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupThread.java b/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupThread.java index 6c2fbb4b9..af47f9976 100644 --- a/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupThread.java +++ b/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupThread.java @@ -115,7 +115,8 @@ class OldDeletedEntriesCleanupThread extends Thread @Override public void run() { throwExceptionIfClosed(); - if (System.currentTimeMillis() - startTime < 1_000) + + if (System.currentTimeMillis() - startTime < 1_000) return; while (!shutdown) { @@ -177,7 +178,8 @@ class OldDeletedEntriesCleanupThread extends Thread @Override public boolean test(ReplicableEntry e) { throwExceptionIfClosed(); - if (shutdown) + + if (shutdown) return false; if (e instanceof MapAbsentEntry) { long deleteTimeout = systemTimeIntervalBetween( diff --git a/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java b/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java index 16fce38eb..cc004d1c6 100644 --- a/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java @@ -173,13 +173,15 @@ public class ReplicatedChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap raise change for all + + // -1 is invalid remoteIdentifier => raise change for all changeCount.incrementAndGet(); raiseChangeForAllExcept(tierIndex, pos, (byte) -1); } public void raiseChangeFor(long tierIndex, long pos, byte remoteIdentifier) { throwExceptionIfClosed(); - acquireModificationIterator(remoteIdentifier).raiseChange0(tierIndex, pos); + + acquireModificationIterator(remoteIdentifier).raiseChange0(tierIndex, pos); } public void raiseChangeForAllExcept(long tierIndex, long pos, byte remoteIdentifier) { throwExceptionIfClosed(); - updateModificationIteratorsArray(); + + updateModificationIteratorsArray(); if (tierIndex <= actualSegments) { long segmentIndex = tierIndex - 1; long offsetToTierBitSet = segmentIndex * tierModIterBitSetOuterSize; @@ -390,7 +403,8 @@ public class ReplicatedChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap keys) { throwExceptionIfClosed(); - if (payload != null) + + if (payload != null) writePayload(payload, destination); if (entry != null) writeExternalEntry0(entry, destination, keys); @@ -594,7 +613,8 @@ public class ReplicatedChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap * Once a change occurs to a map, map replication requires that these changes are picked up * by another thread, this class provides an iterator like interface to poll for such changes. @@ -705,7 +723,8 @@ public class ReplicatedChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap extends VanillaChronicleMap c = iterationContext()) { + + try (CompiledReplicatedMapIterationContext c = iterationContext()) { // iterate over all the segments and mark bit in the modification iterator // that correspond to entries with an older timestamp boolean debugEnabled = LOG.isDebugEnabled(); @@ -962,7 +984,8 @@ public class ReplicatedChronicleMap extends VanillaChronicleMap @Override public void initTransients() { throwExceptionIfClosed(); - super.initTransients(); + + super.initTransients(); initOwnTransients(); } @@ -171,7 +172,8 @@ public class VanillaChronicleMap ChronicleHashResources resources, ChronicleHashCorruption.Listener corruptionListener, ChronicleHashCorruptionImpl corruption) throws IOException { throwExceptionIfClosed(); - basicRecover(resources, corruptionListener, corruption); + + basicRecover(resources, corruptionListener, corruption); try (IterationContext iterationContext = iterationContext()) { iterationContext.recoverSegments(corruptionListener, corruption); } @@ -216,25 +218,29 @@ public class VanillaChronicleMap @Override public Class keyClass() { throwExceptionIfClosed(); - return (Class) keyClass; + + return (Class) keyClass; } @Override public Type keyType() { throwExceptionIfClosed(); - return keyClass; + + return keyClass; } @Override public Class valueClass() { throwExceptionIfClosed(); - return (Class) valueClass; + + return (Class) valueClass; } @Override public Type valueType() { throwExceptionIfClosed(); - return valueClass; + + return valueClass; } private long tiersUsed() { @@ -248,14 +254,15 @@ public class VanillaChronicleMap @Override public int remainingAutoResizes() { throwExceptionIfClosed(); - return (int) (maxTiers() - tiersUsed()); + + return (int) (maxTiers() - tiersUsed()); } @Override public short percentageFreeSpace() { throwExceptionIfClosed(); - double totalUsed = 0; + double totalUsed = 0; double totalSize = 0; try (IterationContext c = iterationContext()) { @@ -320,13 +327,15 @@ public class VanillaChronicleMap @Override public int hashCode() { throwExceptionIfClosed(); - return mapHashCode(); + + return mapHashCode(); } @Override public boolean equals(Object obj) { throwExceptionIfClosed(); - return mapEquals(obj); + + return mapEquals(obj); } @Override @@ -342,7 +351,8 @@ public class VanillaChronicleMap @Override public String toIdentityString() { throwExceptionIfClosed(); - if (identityString == null) + + if (identityString == null) identityString = makeIdentityString(); return identityString; } @@ -360,7 +370,8 @@ public class VanillaChronicleMap @Override public void clear() { throwExceptionIfClosed(); - forEachEntry(c -> c.context().remove(c)); + + forEachEntry(c -> c.context().remove(c)); } public final long readValueSize(Bytes entry) { @@ -371,7 +382,8 @@ public class VanillaChronicleMap public void alignReadPosition(Bytes entry) { throwExceptionIfClosed(); - long positionAddr = entry.addressForRead(entry.readPosition()); + + long positionAddr = entry.addressForRead(entry.readPosition()); long skip = alignAddr(positionAddr, alignment) - positionAddr; if (skip > 0) entry.readSkip(skip); @@ -535,7 +547,8 @@ public class VanillaChronicleMap @Override public V get(Object key) { throwExceptionIfClosed(); - return defaultEntryOperationsAndMethods ? optimizedGet(key, null) : defaultGet(key); + + return defaultEntryOperationsAndMethods ? optimizedGet(key, null) : defaultGet(key); } final V defaultGet(Object key) { @@ -709,7 +722,8 @@ public class VanillaChronicleMap @Override public V getUsing(K key, V usingValue) { throwExceptionIfClosed(); - return defaultEntryOperationsAndMethods ? optimizedGet(key, usingValue) : + + return defaultEntryOperationsAndMethods ? optimizedGet(key, usingValue) : defaultGetUsing(key, usingValue); } @@ -724,7 +738,8 @@ public class VanillaChronicleMap @Override public V acquireUsing(K key, V usingValue) { throwExceptionIfClosed(); - try (QueryContextInterface q = queryContext(key)) { + + try (QueryContextInterface q = queryContext(key)) { return acquireUsingBody(q, usingValue); } } @@ -738,7 +753,8 @@ public class VanillaChronicleMap @Override public V putIfAbsent(K key, V value) { throwExceptionIfClosed(); - checkValue(value); + + checkValue(value); try (QueryContextInterface q = queryContext(key)) { methods.putIfAbsent(q, q.inputValueDataAccess().getData(value), q.defaultReturnValue()); return q.defaultReturnValue().returnValue(); @@ -748,7 +764,8 @@ public class VanillaChronicleMap @Override public boolean remove(Object key, Object value) { throwExceptionIfClosed(); - if (value == null) + + if (value == null) return false; // ConcurrentHashMap compatibility V v = checkValue(value); try (QueryContextInterface q = queryContext(key)) { @@ -759,7 +776,8 @@ public class VanillaChronicleMap @Override public boolean replace(K key, V oldValue, V newValue) { throwExceptionIfClosed(); - checkValue(oldValue); + + checkValue(oldValue); checkValue(newValue); try (QueryContextInterface q = queryContext(key)) { return methods.replace( @@ -770,7 +788,8 @@ public class VanillaChronicleMap @Override public V replace(K key, V value) { throwExceptionIfClosed(); - checkValue(value); + + checkValue(value); try (QueryContextInterface q = queryContext(key)) { methods.replace(q, q.inputValueDataAccess().getData(value), q.defaultReturnValue()); return q.defaultReturnValue().returnValue(); @@ -780,7 +799,8 @@ public class VanillaChronicleMap @Override public boolean containsKey(Object key) { throwExceptionIfClosed(); - try (QueryContextInterface q = queryContext(key)) { + + try (QueryContextInterface q = queryContext(key)) { return methods.containsKey(q); } } @@ -788,7 +808,8 @@ public class VanillaChronicleMap @Override public V put(K key, V value) { throwExceptionIfClosed(); - checkValue(value); + + checkValue(value); try (QueryContextInterface q = queryContext(key)) { Data valueData = q.inputValueDataAccess().getData(value); InstanceReturnValue returnValue = @@ -801,7 +822,8 @@ public class VanillaChronicleMap @Override public V remove(Object key) { throwExceptionIfClosed(); - try (QueryContextInterface q = queryContext(key)) { + + try (QueryContextInterface q = queryContext(key)) { InstanceReturnValue returnValue = removeReturnsNull ? NullReturnValue.get() : q.defaultReturnValue(); methods.remove(q, returnValue); @@ -813,7 +835,8 @@ public class VanillaChronicleMap public V merge(K key, V value, BiFunction remappingFunction) { throwExceptionIfClosed(); - try (QueryContextInterface q = queryContext(key)) { + + try (QueryContextInterface q = queryContext(key)) { methods.merge(q, q.inputValueDataAccess().getData(value), remappingFunction, q.defaultReturnValue()); return q.defaultReturnValue().returnValue(); @@ -823,7 +846,8 @@ public class VanillaChronicleMap @Override public V compute(K key, BiFunction remappingFunction) { throwExceptionIfClosed(); - try (QueryContextInterface q = queryContext(key)) { + + try (QueryContextInterface q = queryContext(key)) { methods.compute(q, remappingFunction, q.defaultReturnValue()); return q.defaultReturnValue().returnValue(); } @@ -832,7 +856,8 @@ public class VanillaChronicleMap @Override public V computeIfAbsent(K key, Function mappingFunction) { throwExceptionIfClosed(); - try (QueryContextInterface q = queryContext(key)) { + + try (QueryContextInterface q = queryContext(key)) { methods.computeIfAbsent(q, mappingFunction, q.defaultReturnValue()); return q.defaultReturnValue().returnValue(); } @@ -842,7 +867,8 @@ public class VanillaChronicleMap public V computeIfPresent(K key, BiFunction remappingFunction) { throwExceptionIfClosed(); - try (QueryContextInterface q = queryContext(key)) { + + try (QueryContextInterface q = queryContext(key)) { methods.computeIfPresent(q, remappingFunction, q.defaultReturnValue()); return q.defaultReturnValue().returnValue(); } @@ -850,7 +876,8 @@ public class VanillaChronicleMap public void verifyTierCountersAreaData() { throwExceptionIfClosed(); - for (int i = 0; i < actualSegments; i++) { + + for (int i = 0; i < actualSegments; i++) { try (MapSegmentContext c = segmentContext(i)) { Method verifyTierCountersAreaData = c.getClass().getMethod("verifyTierCountersAreaData"); diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/data/ZeroBytesStore.java b/src/main/java/net/openhft/chronicle/map/impl/stage/data/ZeroBytesStore.java index 966606fd3..655b3a8b5 100755 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/data/ZeroBytesStore.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/data/ZeroBytesStore.java @@ -38,8 +38,7 @@ public enum ZeroBytesStore implements BytesStore { throw new UnsupportedOperationException("Cannot get the address of nothing"); } - - @Override +@Override public int peekUnsignedByte(long offset) { return 0; } @@ -157,8 +156,7 @@ public enum ZeroBytesStore implements BytesStore { return true; } - - @Override +@Override public void reserve(ReferenceOwner id) throws IllegalStateException { } diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/iter/MapSegmentIteration.java b/src/main/java/net/openhft/chronicle/map/impl/stage/iter/MapSegmentIteration.java index 72540a242..fab7faa66 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/iter/MapSegmentIteration.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/iter/MapSegmentIteration.java @@ -41,13 +41,15 @@ public abstract class MapSegmentIteration extends HashSegmentIteration< @Override public void hookAfterEachIteration() { throwExceptionIfClosed(); - wrappedValueInstanceDataHolder.closeValue(); + + wrappedValueInstanceDataHolder.closeValue(); } @Override public void doReplaceValue(Data newValue) { throwExceptionIfClosed(); - checkOnEachPublicOperation.checkOnEachPublicOperation(); + + checkOnEachPublicOperation.checkOnEachPublicOperation(); try { entry.innerDefaultReplaceValue(newValue); } finally { diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/iter/ReplicatedMapSegmentIteration.java b/src/main/java/net/openhft/chronicle/map/impl/stage/iter/ReplicatedMapSegmentIteration.java index d4c5c5f1a..584a1748a 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/iter/ReplicatedMapSegmentIteration.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/iter/ReplicatedMapSegmentIteration.java @@ -61,25 +61,29 @@ public abstract class ReplicatedMapSegmentIteration extends MapSegmentI @Override public boolean shouldTestEntry() { throwExceptionIfClosed(); - return entriesToTest == ALL || !e.entryDeleted(); + + return entriesToTest == ALL || !e.entryDeleted(); } @Override public Object entryForIteration() { throwExceptionIfClosed(); - return !e.entryDeleted() ? entryDelegating : absentEntryDelegating; + + return !e.entryDeleted() ? entryDelegating : absentEntryDelegating; } @Override public long tierEntriesForIteration() { throwExceptionIfClosed(); - return entriesToTest == ALL ? s.tierEntries() : s.tierEntries() - s.tierDeleted(); + + return entriesToTest == ALL ? s.tierEntries() : s.tierEntries() - s.tierDeleted(); } @Override public void doReplaceValue(Data newValue) { throwExceptionIfClosed(); - checkOnEachPublicOperation.checkOnEachPublicOperation(); + + checkOnEachPublicOperation.checkOnEachPublicOperation(); try { entry.innerDefaultReplaceValue(newValue); e.updatedReplicationStateOnPresentEntry(); @@ -92,7 +96,8 @@ public abstract class ReplicatedMapSegmentIteration extends MapSegmentI @Override public boolean forEachSegmentEntryWhile(Predicate> predicate) { throwExceptionIfClosed(); - checkOnEachPublicOperation.checkOnEachPublicOperation(); + + checkOnEachPublicOperation.checkOnEachPublicOperation(); initEntriesToTest(PRESENT); s.innerUpdateLock.lock(); return innerForEachSegmentEntryWhile(predicate); @@ -102,7 +107,8 @@ public abstract class ReplicatedMapSegmentIteration extends MapSegmentI public boolean forEachSegmentReplicableEntryWhile( Predicate predicate) { throwExceptionIfClosed(); - checkOnEachPublicOperation.checkOnEachPublicOperation(); + + checkOnEachPublicOperation.checkOnEachPublicOperation(); initEntriesToTest(ALL); s.innerUpdateLock.lock(); return innerForEachSegmentEntryWhile(predicate); @@ -111,7 +117,8 @@ public abstract class ReplicatedMapSegmentIteration extends MapSegmentI @Override public void forEachSegmentReplicableEntry(Consumer action) { throwExceptionIfClosed(); - forEachSegmentReplicableEntryWhile(e -> { + + forEachSegmentReplicableEntryWhile(e -> { action.accept(e); return true; }); @@ -120,7 +127,8 @@ public abstract class ReplicatedMapSegmentIteration extends MapSegmentI @Override public void doRemove() { throwExceptionIfClosed(); - checkOnEachPublicOperation.checkOnEachPublicOperation(); + + checkOnEachPublicOperation.checkOnEachPublicOperation(); try { if (e.valueSize > dummyValue.size()) e.innerDefaultReplaceValue(dummyValue); @@ -137,7 +145,8 @@ public abstract class ReplicatedMapSegmentIteration extends MapSegmentI @Override public void doRemoveCompletely() { throwExceptionIfClosed(); - boolean wasDeleted = e.entryDeleted(); + + boolean wasDeleted = e.entryDeleted(); super.doRemove(); ru.dropChange(); if (wasDeleted) @@ -146,7 +155,8 @@ public abstract class ReplicatedMapSegmentIteration extends MapSegmentI public void doInsert(Data value) { throwExceptionIfClosed(); - checkOnEachPublicOperation.checkOnEachPublicOperation(); + + checkOnEachPublicOperation.checkOnEachPublicOperation(); if (e.entryDeleted()) { try { s.tierDeleted(s.tierDeleted() - 1); @@ -166,7 +176,8 @@ public abstract class ReplicatedMapSegmentIteration extends MapSegmentI public void doInsert() { throwExceptionIfClosed(); - if (mh.set() == null) + + if (mh.set() == null) throw new IllegalStateException(mh.h().toIdentityString() + ": Called SetAbsentEntry.doInsert() from Map context"); doInsert((Data) DummyValueData.INSTANCE); diff --git a/src/main/java/net/openhft/chronicle/set/SetFromMap.java b/src/main/java/net/openhft/chronicle/set/SetFromMap.java index 2e5bf508d..edadc8f7a 100644 --- a/src/main/java/net/openhft/chronicle/set/SetFromMap.java +++ b/src/main/java/net/openhft/chronicle/set/SetFromMap.java @@ -52,42 +52,50 @@ class SetFromMap extends AbstractSet implements ChronicleSet { public void clear() { throwExceptionIfClosed(); - m.clear(); + + m.clear(); } public int size() { throwExceptionIfClosed(); - return m.size(); + + return m.size(); } public boolean isEmpty() { throwExceptionIfClosed(); - return m.isEmpty(); + + return m.isEmpty(); } public boolean contains(Object o) { throwExceptionIfClosed(); - return m.containsKey(o); + + return m.containsKey(o); } public boolean remove(Object o) { throwExceptionIfClosed(); - return m.remove(o, DUMMY_VALUE); + + return m.remove(o, DUMMY_VALUE); } public boolean add(E e) { throwExceptionIfClosed(); - return m.putIfAbsent(e, DUMMY_VALUE) == null; + + return m.putIfAbsent(e, DUMMY_VALUE) == null; } public Iterator iterator() { throwExceptionIfClosed(); - return s.iterator(); + + return s.iterator(); } public Object[] toArray() { throwExceptionIfClosed(); - return s.toArray(); + + return s.toArray(); } public T[] toArray(T[] a) { @@ -101,7 +109,8 @@ class SetFromMap extends AbstractSet implements ChronicleSet { @Override public String toIdentityString() { throwExceptionIfClosed(); - return "ChronicleSet{" + + + return "ChronicleSet{" + "name=" + name() + ", file=" + file() + ", identityHashCode=" + System.identityHashCode(this) + @@ -110,52 +119,61 @@ class SetFromMap extends AbstractSet implements ChronicleSet { public int hashCode() { throwExceptionIfClosed(); - return s.hashCode(); + + return s.hashCode(); } public boolean equals(Object o) { throwExceptionIfClosed(); - return o == this || s.equals(o); + + return o == this || s.equals(o); } public boolean containsAll(Collection c) { throwExceptionIfClosed(); - return s.containsAll(c); + + return s.containsAll(c); } public boolean removeAll(Collection c) { throwExceptionIfClosed(); - return s.removeAll(c); + + return s.removeAll(c); } public boolean retainAll(Collection c) { throwExceptionIfClosed(); - return s.retainAll(c); + + return s.retainAll(c); } // addAll is the only inherited implementation @Override public long longSize() { throwExceptionIfClosed(); - return m.longSize(); + + return m.longSize(); } @Override public long offHeapMemoryUsed() { throwExceptionIfClosed(); - return m.offHeapMemoryUsed(); + + return m.offHeapMemoryUsed(); } @Override public Class keyClass() { throwExceptionIfClosed(); - return m.keyClass(); + + return m.keyClass(); } @Override public Type keyType() { throwExceptionIfClosed(); - return m.keyType(); + + return m.keyType(); } // TODO test queryContext methods @@ -190,7 +208,8 @@ class SetFromMap extends AbstractSet implements ChronicleSet { @Override public int segments() { throwExceptionIfClosed(); - return m.segments(); + + return m.segments(); } // TODO test forEach methods @@ -198,27 +217,31 @@ class SetFromMap extends AbstractSet implements ChronicleSet { @Override public boolean forEachEntryWhile(Predicate> predicate) { throwExceptionIfClosed(); - Objects.requireNonNull(predicate); + + Objects.requireNonNull(predicate); return m.forEachEntryWhile(e -> predicate.test(((SetEntry) e))); } @Override public void forEachEntry(Consumer> action) { throwExceptionIfClosed(); - Objects.requireNonNull(action); + + Objects.requireNonNull(action); m.forEachEntry(e -> action.accept(((SetEntry) e))); } @Override public File file() { throwExceptionIfClosed(); - return m.file(); + + return m.file(); } @Override public String name() { throwExceptionIfClosed(); - return m.name(); + + return m.name(); } @Override @@ -229,6 +252,7 @@ class SetFromMap extends AbstractSet implements ChronicleSet { @Override public boolean isOpen() { throwExceptionIfClosed(); - return m.isOpen(); + + return m.isOpen(); } } diff --git a/src/test/java/net/openhft/chronicle/map/perf/MapStress.java b/src/test/java/net/openhft/chronicle/map/perf/MapStress.java index 7ad0a06a5..55e478d3b 100644 --- a/src/test/java/net/openhft/chronicle/map/perf/MapStress.java +++ b/src/test/java/net/openhft/chronicle/map/perf/MapStress.java @@ -91,8 +91,7 @@ public class MapStress { secs[4].securityUltimateUnderlyingTicker = "RTYU"; secs[4].securityUnderlyingTicker = "RTYU"; - - Future[] futures = new Future[N_WRITE_THREADS + N_READ_THREADS]; +Future[] futures = new Future[N_WRITE_THREADS + N_READ_THREADS]; for (int i = 0; i < N_WRITE_THREADS; i++) { String id = i + " -> "; futures[i] = executor.submit(() -> { diff --git a/src/test/java/net/openhft/chronicle/map/watcher/MapFileManager.java b/src/test/java/net/openhft/chronicle/map/watcher/MapFileManager.java index 63fc2c33c..766b03fd3 100755 --- a/src/test/java/net/openhft/chronicle/map/watcher/MapFileManager.java +++ b/src/test/java/net/openhft/chronicle/map/watcher/MapFileManager.java @@ -104,8 +104,7 @@ public class MapFileManager extends JMXFileManager implements MapFileManagerMBea map.createMappedStoreAndSegments( new PersistedChronicleHashResources(file)); - - keyClass = map.keyType(); +keyClass = map.keyType(); valueClass = map.valueType(); size = map.longSize(); name = map.name(); From 2d7e3b0ba3a024e74c2f82307af25708c42dd59a Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Thu, 18 Jun 2020 13:35:55 +0100 Subject: [PATCH 39/67] Code tidy --- .../java/net/openhft/chronicle/map/VanillaChronicleMap.java | 3 +-- src/test/java/net/openhft/chronicle/map/AutoResizeTest.java | 6 ++---- .../java/net/openhft/chronicle/map/BloatFactorTest.java | 3 +-- .../openhft/chronicle/map/example/StringArrayExample.java | 3 +-- .../openhft/chronicle/map/jsr166/map/ChronicleMapTest.java | 3 +-- 5 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java index ae46b387c..15198548e 100755 --- a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java @@ -284,8 +284,7 @@ public class VanillaChronicleMap totalUsed += freeList0.cardinality(); totalSize += freeList.logicalSize(); } - - } + } } return (short) (100 - (int) (100 * totalUsed / totalSize)); diff --git a/src/test/java/net/openhft/chronicle/map/AutoResizeTest.java b/src/test/java/net/openhft/chronicle/map/AutoResizeTest.java index 4ca677ffe..657fac2ec 100644 --- a/src/test/java/net/openhft/chronicle/map/AutoResizeTest.java +++ b/src/test/java/net/openhft/chronicle/map/AutoResizeTest.java @@ -43,8 +43,7 @@ public class AutoResizeTest { Assert.assertNotEquals(0.0, map.remainingAutoResizes()); System.out.println(actual); } - - } + } @Test public void testAutoResizeNotZeroUponRestart2() throws IOException { @@ -59,7 +58,6 @@ public class AutoResizeTest { Assert.assertNotEquals(0.0, actual); System.out.println(actual); } - - } + } } diff --git a/src/test/java/net/openhft/chronicle/map/BloatFactorTest.java b/src/test/java/net/openhft/chronicle/map/BloatFactorTest.java index 2b434e01b..3013eae01 100644 --- a/src/test/java/net/openhft/chronicle/map/BloatFactorTest.java +++ b/src/test/java/net/openhft/chronicle/map/BloatFactorTest.java @@ -42,7 +42,6 @@ public class BloatFactorTest { Assert.assertEquals(EXPECTED_MAX_BLOAT_FACTOR, maxBloatFactor,0.0); } - - } + } } diff --git a/src/test/java/net/openhft/chronicle/map/example/StringArrayExample.java b/src/test/java/net/openhft/chronicle/map/example/StringArrayExample.java index 3f027bbb2..c495af995 100644 --- a/src/test/java/net/openhft/chronicle/map/example/StringArrayExample.java +++ b/src/test/java/net/openhft/chronicle/map/example/StringArrayExample.java @@ -52,8 +52,7 @@ public class StringArrayExample { // to string all the values System.out.println(map.getUsing(1, charSequenceArray).toString()); } - - } + } private CharSequenceArray setToHello(final Integer integer, final CharSequenceArray charSequenceArray) { charSequenceArray.getCharSequenceWrapperAt(1).setCharSequence("hello"); 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 8ce65c4ba..e721e60ba 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 @@ -699,8 +699,7 @@ public class ChronicleMapTest extends JSR166TestCase { } Assert.fail(); } - - } + } } } From 37396d5c946af29ba31f5cd07200992a5c002e22 Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Thu, 18 Jun 2020 20:14:07 +0200 Subject: [PATCH 40/67] Updating to bom version 2.19.214 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d96a1520a..662887617 100755 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ net.openhft chronicle-bom - 2.19-SNAPSHOT + 2.19.214 pom import From ae0e70816811f8ae19aae793f533fcc5968ad823 Mon Sep 17 00:00:00 2001 From: rob Date: Thu, 18 Jun 2020 19:23:48 +0100 Subject: [PATCH 41/67] updated to net.openhft chronicle-bom 2.19-SNAPSHOT pom import --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 662887617..d96a1520a 100755 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ net.openhft chronicle-bom - 2.19.214 + 2.19-SNAPSHOT pom import From 2f99be8457338d0f58dc865984fb183d993745f9 Mon Sep 17 00:00:00 2001 From: rob Date: Thu, 18 Jun 2020 19:36:07 +0100 Subject: [PATCH 42/67] updated t net.openhft chronicle-bom 2.19.214 pom import --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d96a1520a..662887617 100755 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ net.openhft chronicle-bom - 2.19-SNAPSHOT + 2.19.214 pom import From 5bd8b4e2b6742c4f3e4031957452952cf4da3b7f Mon Sep 17 00:00:00 2001 From: rob Date: Thu, 18 Jun 2020 20:00:13 +0100 Subject: [PATCH 43/67] updated to net.openhft chronicle-bom 2.19-SNAPSHOT pom import --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 662887617..d96a1520a 100755 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ net.openhft chronicle-bom - 2.19.214 + 2.19-SNAPSHOT pom import From de77812087452ed9366a90ba481d58bf804aef8b Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Thu, 18 Jun 2020 21:05:05 +0200 Subject: [PATCH 44/67] Updating to bom version 2.19.214 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d96a1520a..662887617 100755 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ net.openhft chronicle-bom - 2.19-SNAPSHOT + 2.19.214 pom import From 9bc37f830bf3edda4dd4c05772db6f0bec0e71bc Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Fri, 19 Jun 2020 08:53:51 +0100 Subject: [PATCH 45/67] releaseLast() not release() --- .../java/net/openhft/chronicle/map/watcher/MapFileManager.java | 2 +- src/test/java/net/openhft/lang/values/DoubleArrayTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/net/openhft/chronicle/map/watcher/MapFileManager.java b/src/test/java/net/openhft/chronicle/map/watcher/MapFileManager.java index 766b03fd3..f05e9b21e 100755 --- a/src/test/java/net/openhft/chronicle/map/watcher/MapFileManager.java +++ b/src/test/java/net/openhft/chronicle/map/watcher/MapFileManager.java @@ -115,7 +115,7 @@ keyClass = map.keyType(); Jvm.warn().on(getClass(), "Unable to update", e); header = e.toString(); } finally { - mf.release(); + mf.releaseLast(); assert mf.refCount() == 0; } } diff --git a/src/test/java/net/openhft/lang/values/DoubleArrayTest.java b/src/test/java/net/openhft/lang/values/DoubleArrayTest.java index 2c91b0e35..e0438bf4c 100755 --- a/src/test/java/net/openhft/lang/values/DoubleArrayTest.java +++ b/src/test/java/net/openhft/lang/values/DoubleArrayTest.java @@ -62,7 +62,7 @@ public class DoubleArrayTest { // expected } // free the memory. - da.bytesStore().release(); + da.bytesStore().releaseLast(); } @Test From ca66a9729a726a993f813d8b718fae155381ee76 Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Fri, 19 Jun 2020 10:29:24 +0200 Subject: [PATCH 46/67] Updating to bom version 2.19.214 From 3c8beda7f308724a62e8679ef004b90d3529f621 Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Fri, 19 Jun 2020 10:38:46 +0200 Subject: [PATCH 47/67] Updating to bom version 2.19.214 From 9caa7a28f295f669fe0e6fed86f9b6e270a8983c Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Fri, 19 Jun 2020 10:41:10 +0200 Subject: [PATCH 48/67] [maven-release-plugin] prepare release chronicle-map-3.19.40 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 662887617..ef3e4379f 100755 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ 4.0.0 chronicle-map - 3.19.40-SNAPSHOT + 3.19.40 OpenHFT/Chronicle-Map Chronicle-Map bundle @@ -446,7 +446,7 @@ scm:git:git@github.com:OpenHFT/Chronicle-Map.git scm:git:git@github.com:OpenHFT/Chronicle-Map.git scm:git:git@github.com:OpenHFT/Chronicle-Map.git - master + chronicle-map-3.19.40 From 42909207a7154ca9b6b238f3fdddc1b17d70a929 Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Fri, 19 Jun 2020 10:41:19 +0200 Subject: [PATCH 49/67] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ef3e4379f..fa69fddc7 100755 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ 4.0.0 chronicle-map - 3.19.40 + 3.19.41-SNAPSHOT OpenHFT/Chronicle-Map Chronicle-Map bundle @@ -446,7 +446,7 @@ scm:git:git@github.com:OpenHFT/Chronicle-Map.git scm:git:git@github.com:OpenHFT/Chronicle-Map.git scm:git:git@github.com:OpenHFT/Chronicle-Map.git - chronicle-map-3.19.40 + master From 01f6c3d4cb31b205239e48ce8138aed2e3932c93 Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Fri, 19 Jun 2020 10:42:45 +0200 Subject: [PATCH 50/67] Reverting back to bom version 2.19-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fa69fddc7..cf74f6e65 100755 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ net.openhft chronicle-bom - 2.19.214 + 2.19-SNAPSHOT pom import From 96287ff5af1a24cec243317563596f56a8ab8077 Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Fri, 19 Jun 2020 10:42:57 +0200 Subject: [PATCH 51/67] Reverting back to bom version 2.19-SNAPSHOT From bc5453d29244481696cb6847d22bdef2a85c3557 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Fri, 19 Jun 2020 10:30:28 +0100 Subject: [PATCH 52/67] Add Jvm.nanoPause to tight loops --- .../net/openhft/chronicle/hash/replication/TimeProvider.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/net/openhft/chronicle/hash/replication/TimeProvider.java b/src/main/java/net/openhft/chronicle/hash/replication/TimeProvider.java index e18c524e7..0b10254bf 100644 --- a/src/main/java/net/openhft/chronicle/hash/replication/TimeProvider.java +++ b/src/main/java/net/openhft/chronicle/hash/replication/TimeProvider.java @@ -16,6 +16,7 @@ package net.openhft.chronicle.hash.replication; +import net.openhft.chronicle.core.Jvm; import net.openhft.chronicle.hash.ChronicleHash; import net.openhft.chronicle.hash.ChronicleHashBuilderPrivateAPI; @@ -61,6 +62,7 @@ public final class TimeProvider { return lastTime; if (lastTimeHolder.compareAndSet(lastTime, now)) return now; + Jvm.nanoPause(); } } From e4bf64d04b086e300e8fd303aec92ea72c1b6676 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Tue, 23 Jun 2020 10:04:40 +0100 Subject: [PATCH 53/67] Add readLimitToCapacity(); to optimise this use case --- .../openhft/chronicle/hash/impl/stage/entry/SegmentStages.java | 2 +- .../java/net/openhft/chronicle/map/VanillaChronicleMap.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/SegmentStages.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/SegmentStages.java index c6150ec00..b7c36137e 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/SegmentStages.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/SegmentStages.java @@ -659,7 +659,7 @@ public abstract class SegmentStages implements SegmentLock, LocksInterface { @Stage("Segment") public Bytes segmentBytesForRead() { - segmentBytes.readLimit(segmentBytes.capacity()); + segmentBytes.readLimitToCapacity(); return segmentBytes; } diff --git a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java index 15198548e..dfeee5247 100755 --- a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java @@ -702,7 +702,7 @@ public class VanillaChronicleMap } long keySizeOffset = entrySpaceOffset + (entryPos * chunkSize); - bs.readLimit(bs.capacity()); + bs.readLimitToCapacity(); bs.readPosition(keySizeOffset); long keySize = keySizeMarshaller.readSize(bs); long keyOffset = bs.readPosition(); From 901f332ceb7c115881106d9234fa01be43a8fafc Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Wed, 1 Jul 2020 08:35:19 +0100 Subject: [PATCH 54/67] Make checking thread safety an option which off by default --- system.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/system.properties b/system.properties index 677f6b473..9f316b79c 100644 --- a/system.properties +++ b/system.properties @@ -1,4 +1,5 @@ # Tracing if resources are closed/released correctly. jvm.resource.tracing=true +check.thread.safety=true # for profiling jvm.safepoint.enabled=false \ No newline at end of file From bfb87539ef824f61ccabe21e544d4f85092a1a18 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Thu, 2 Jul 2020 08:49:14 +0100 Subject: [PATCH 55/67] Standardize the top of pom.xml files. --- pom.xml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index cf74f6e65..b41573d09 100755 --- a/pom.xml +++ b/pom.xml @@ -1,14 +1,16 @@ - + + + 4.0.0 net.openhft java-parent-pom 1.1.23 - + - 4.0.0 chronicle-map 3.19.41-SNAPSHOT OpenHFT/Chronicle-Map From 1a428eeda0c26f2a6f63f45b75aea512244a1a1b Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Fri, 3 Jul 2020 09:58:36 +0200 Subject: [PATCH 56/67] Updating to bom version 2.19.311 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b41573d09..02bdef3ab 100755 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ net.openhft chronicle-bom - 2.19-SNAPSHOT + 2.19.311 pom import From edee53c11a55658386c1e2ffe37707f5bbd02f8e Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Fri, 3 Jul 2020 10:01:01 +0200 Subject: [PATCH 57/67] [maven-release-plugin] prepare release chronicle-map-3.19.41 --- pom.xml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 02bdef3ab..adbeea933 100755 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,5 @@ - + 4.0.0 @@ -8,11 +7,11 @@ net.openhft java-parent-pom 1.1.23 - + chronicle-map - 3.19.41-SNAPSHOT + 3.19.41 OpenHFT/Chronicle-Map Chronicle-Map bundle @@ -448,7 +447,7 @@ scm:git:git@github.com:OpenHFT/Chronicle-Map.git scm:git:git@github.com:OpenHFT/Chronicle-Map.git scm:git:git@github.com:OpenHFT/Chronicle-Map.git - master + chronicle-map-3.19.41 From 563fff79ac97e243746b3bbbcb6b5bbe1ee4cc0c Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Fri, 3 Jul 2020 10:01:11 +0200 Subject: [PATCH 58/67] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index adbeea933..7a886b061 100755 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ chronicle-map - 3.19.41 + 3.19.42-SNAPSHOT OpenHFT/Chronicle-Map Chronicle-Map bundle @@ -447,7 +447,7 @@ scm:git:git@github.com:OpenHFT/Chronicle-Map.git scm:git:git@github.com:OpenHFT/Chronicle-Map.git scm:git:git@github.com:OpenHFT/Chronicle-Map.git - chronicle-map-3.19.41 + master From 664edbecbd59fc251627ba06e22303a28fd99aae Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Fri, 3 Jul 2020 10:02:34 +0200 Subject: [PATCH 59/67] Reverting back to bom version 2.19-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7a886b061..7b30adf94 100755 --- a/pom.xml +++ b/pom.xml @@ -30,7 +30,7 @@ net.openhft chronicle-bom - 2.19.311 + 2.19-SNAPSHOT pom import From b2de7f39a89e02b5c08f857986efdb6cc6253ac0 Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Fri, 3 Jul 2020 10:09:28 +0200 Subject: [PATCH 60/67] Reverting back to bom version 2.19-SNAPSHOT From 2beba65c43dd33a384d043961d553ed16ead2943 Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Fri, 3 Jul 2020 13:26:07 +0200 Subject: [PATCH 61/67] Updating to bom version 2.19.320 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7b30adf94..928828c44 100755 --- a/pom.xml +++ b/pom.xml @@ -30,7 +30,7 @@ net.openhft chronicle-bom - 2.19-SNAPSHOT + 2.19.320 pom import From d5544dfae3976c1d0ae49e70c53306cc28b0e211 Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Fri, 3 Jul 2020 13:28:32 +0200 Subject: [PATCH 62/67] [maven-release-plugin] prepare release chronicle-map-3.19.42 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 928828c44..cb06b8ee6 100755 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ chronicle-map - 3.19.42-SNAPSHOT + 3.19.42 OpenHFT/Chronicle-Map Chronicle-Map bundle @@ -447,7 +447,7 @@ scm:git:git@github.com:OpenHFT/Chronicle-Map.git scm:git:git@github.com:OpenHFT/Chronicle-Map.git scm:git:git@github.com:OpenHFT/Chronicle-Map.git - master + chronicle-map-3.19.42 From 4d623eaa7636260a9ac0db425ad770e52a2a7a43 Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Fri, 3 Jul 2020 13:28:41 +0200 Subject: [PATCH 63/67] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index cb06b8ee6..1e7d538e2 100755 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ chronicle-map - 3.19.42 + 3.19.43-SNAPSHOT OpenHFT/Chronicle-Map Chronicle-Map bundle @@ -447,7 +447,7 @@ scm:git:git@github.com:OpenHFT/Chronicle-Map.git scm:git:git@github.com:OpenHFT/Chronicle-Map.git scm:git:git@github.com:OpenHFT/Chronicle-Map.git - chronicle-map-3.19.42 + master From 1a1910449d0092f335287be91b70cf3ecd41793e Mon Sep 17 00:00:00 2001 From: teamcity_hft Date: Fri, 3 Jul 2020 13:30:15 +0200 Subject: [PATCH 64/67] Reverting back to bom version 2.19-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1e7d538e2..32e32c35c 100755 --- a/pom.xml +++ b/pom.xml @@ -30,7 +30,7 @@ net.openhft chronicle-bom - 2.19.320 + 2.19-SNAPSHOT pom import From bb7ed518396bff5327e281ab06b26eaea03d10e7 Mon Sep 17 00:00:00 2001 From: Rob Austin Date: Fri, 3 Jul 2020 15:28:27 +0100 Subject: [PATCH 65/67] added chronicle-enterprise-snapshots Snapshot Repository https://nexus.chronicle.software/content/repositories/snapshots true chronicle-enterprise-release https://nexus.chronicle.software/content/repositories/releases true --- pom.xml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/pom.xml b/pom.xml index cf74f6e65..057bb5d6f 100755 --- a/pom.xml +++ b/pom.xml @@ -227,6 +227,28 @@ + + + chronicle-enterprise-snapshots + Snapshot Repository + + https://nexus.chronicle.software/content/repositories/snapshots + + + true + + + + chronicle-enterprise-release + + https://nexus.chronicle.software/content/repositories/releases + + + true + + + + From b7ad1a8214110aac3130af203fec98253ca545f9 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Fri, 3 Jul 2020 17:35:00 +0100 Subject: [PATCH 66/67] Stop the test killing all processes when run in Java 11, https://github.com/OpenHFT/Chronicle-Core/issues/128 --- .../openhft/chronicle/map/ExitHookTest.java | 21 +++++-------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/src/test/java/net/openhft/chronicle/map/ExitHookTest.java b/src/test/java/net/openhft/chronicle/map/ExitHookTest.java index eed6bea0e..8480d5682 100644 --- a/src/test/java/net/openhft/chronicle/map/ExitHookTest.java +++ b/src/test/java/net/openhft/chronicle/map/ExitHookTest.java @@ -17,6 +17,7 @@ package net.openhft.chronicle.map; import com.google.common.base.Preconditions; +import net.openhft.chronicle.core.Jvm; import net.openhft.chronicle.core.OS; import org.junit.Rule; import org.junit.Test; @@ -24,7 +25,6 @@ import org.junit.rules.TemporaryFolder; import java.io.File; import java.io.IOException; -import java.lang.reflect.Field; import java.nio.file.Files; import java.util.Iterator; import java.util.concurrent.atomic.AtomicReference; @@ -35,7 +35,7 @@ import static org.junit.Assert.*; public class ExitHookTest { private static final int KEY = 1; - private static final int JVM_STARTUP_WAIT_TIME_MS = 5_000; + private static final int JVM_STARTUP_WAIT_TIME_MS = 2_000; private static final String PRE_SHUTDOWN_ACTION_EXECUTED = "PRE_SHUTDOWN_ACTION_EXECUTED"; private static final String USER_SHUTDOWN_HOOK_EXECUTED = "USER_SHUTDOWN_HOOK_EXECUTED"; @@ -92,7 +92,7 @@ public class ExitHookTest { mapReference.set(mapBuilder.createPersistedTo(mapFile)); try (ExternalMapQueryContext c = mapReference.get().queryContext(KEY)) { c.writeLock().lock(); - Thread.sleep(30_000); + Thread.sleep(8_000); } } @@ -104,19 +104,8 @@ public class ExitHookTest { // http://stackoverflow.com/a/33171840/648955 public static long getPidOfProcess(Process p) { - long pid = -1; - - try { - if (p.getClass().getName().equals("java.lang.UNIXProcess")) { - Field f = p.getClass().getDeclaredField("pid"); - f.setAccessible(true); - pid = f.getLong(p); - f.setAccessible(false); - } - } catch (Exception e) { - pid = -1; - } - return pid; + Number pid = Jvm.getValue(p, "pid"); + return pid.longValue(); } @Test From 67b612c2568b82917bb090cac5046a34462e9d24 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Mon, 6 Jul 2020 15:40:53 +0100 Subject: [PATCH 67/67] Merge to repositories groups --- pom.xml | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/pom.xml b/pom.xml index 65e1a07d8..a0d6c6685 100755 --- a/pom.xml +++ b/pom.xml @@ -228,30 +228,7 @@ - - - chronicle-enterprise-snapshots - Snapshot Repository - - https://nexus.chronicle.software/content/repositories/snapshots - - - true - - - - chronicle-enterprise-release - - https://nexus.chronicle.software/content/repositories/releases - - - true - - - - - src/main/resources @@ -441,6 +418,26 @@ + + chronicle-enterprise-snapshots + Snapshot Repository + + https://nexus.chronicle.software/content/repositories/snapshots + + + true + + + + chronicle-enterprise-release + + https://nexus.chronicle.software/content/repositories/releases + + + true + + + central Central Repository