From 3370aa7dba41b2f11bd71355f9a03e3c47cef38b Mon Sep 17 00:00:00 2001 From: leventov Date: Fri, 18 Sep 2015 18:14:40 +0300 Subject: [PATCH] Add ChronicleHashBuilder.allowSegmentTiering() config for regressions and EntryCountMapTest --- .../chronicle/hash/ChronicleHashBuilder.java | 19 +++++++++++++++++++ .../chronicle/map/ChronicleMapBuilder.java | 9 +++++++++ .../chronicle/set/ChronicleSetBuilder.java | 6 ++++++ .../chronicle/map/EntryCountMapTest.java | 1 + 4 files changed, 35 insertions(+) diff --git a/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilder.java b/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilder.java index 21daf2b7a..4b8b50b64 100755 --- a/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilder.java +++ b/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilder.java @@ -293,6 +293,25 @@ public interface ChronicleHashBuilder, */ B maxBloatFactor(double maxBloatFactor); + /** + * In addition to {@link #maxBloatFactor(double) maxBloatFactor(1.0)}, that does not + * guarantee that segments won't tier (due to bad hash distribution or natural variance), + * configuring {@code allowSegmentTiering(false)} makes Chronicle Hashes, created by this + * builder, to throw {@code IllegalStateException} immediately when some segment overflows. + * + *

Useful exactly for testing hash distribution and variance of segment filling. + * + *

Default is {@code true}, segments are allowed to tier. + * + *

When configured to {@code false}, {@link #maxBloatFactor(double)} configuration becomes + * irrelevant, because effectively no bloat is allowed. + * + * @param allowSegmentTiering if {@code true}, when a segment overflows a next tier + * is allocated to accommodate new entries + * @return this builder back + */ + B allowSegmentTiering(boolean allowSegmentTiering); + /** * Configures the actual maximum number entries, that could be inserted into any single segment * of the hash containers, created by this builder. Configuring both the actual number of diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java index 3f7ce96b9..86a473c08 100755 --- a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java +++ b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java @@ -158,6 +158,7 @@ public final class ChronicleMapBuilder implements private TimeUnit lockTimeOutUnit = TimeUnit.MILLISECONDS; private int metaDataBytes = 0; private double maxBloatFactor = 1.0; + private boolean allowSegmentTiering = true; private boolean putReturnsNull = false; private boolean removeReturnsNull = false; @@ -1033,7 +1034,15 @@ public final class ChronicleMapBuilder implements return this; } + @Override + public ChronicleMapBuilder allowSegmentTiering(boolean allowSegmentTiering) { + this.allowSegmentTiering = allowSegmentTiering; + return this; + } + long maxExtraTiers(boolean replicated) { + if (!allowSegmentTiering) + return 0; int actualSegments = actualSegments(replicated); // maxBloatFactor is scale, so we do (- 1.0) to compute _extra_ tiers return ((long) (maxBloatFactor - 1.0) * actualSegments) diff --git a/src/main/java/net/openhft/chronicle/set/ChronicleSetBuilder.java b/src/main/java/net/openhft/chronicle/set/ChronicleSetBuilder.java index 5d30b4d20..750e340dd 100755 --- a/src/main/java/net/openhft/chronicle/set/ChronicleSetBuilder.java +++ b/src/main/java/net/openhft/chronicle/set/ChronicleSetBuilder.java @@ -171,6 +171,12 @@ public final class ChronicleSetBuilder return this; } + @Override + public ChronicleSetBuilder allowSegmentTiering(boolean allowSegmentTiering) { + chronicleMapBuilder.allowSegmentTiering(allowSegmentTiering); + return this; + } + @Override public String toString() { return " ChronicleSetBuilder{" + diff --git a/src/test/java/net/openhft/chronicle/map/EntryCountMapTest.java b/src/test/java/net/openhft/chronicle/map/EntryCountMapTest.java index 3ed4c9fa3..b77565cfa 100644 --- a/src/test/java/net/openhft/chronicle/map/EntryCountMapTest.java +++ b/src/test/java/net/openhft/chronicle/map/EntryCountMapTest.java @@ -49,6 +49,7 @@ public class EntryCountMapTest { long entries, int segments, int keySize) throws IOException { ChronicleMapBuilder mapBuilder = ChronicleMapBuilder.of(CharSequence.class, LongValue.class) + .allowSegmentTiering(false) .entries(entries) .actualSegments(segments) .averageKeySize(keySize);