From 2b6c87156208336593187b74c773ad2c1c55ff9e Mon Sep 17 00:00:00 2001 From: leventov Date: Wed, 5 Aug 2015 02:57:12 +0300 Subject: [PATCH] Reduce ChronicleMapBuilder API surface, hide private API in a class --- pom.xml | 19 ++--- .../chronicle/hash/ChronicleHashBuilder.java | 5 ++ .../hash/ChronicleHashBuilderPrivateAPI.java | 38 ++++++++++ .../hash/impl/VanillaChronicleHash.java | 27 ++++--- .../chronicle/map/ChronicleMapBuilder.java | 70 ++++++------------- .../map/ChronicleMapBuilderPrivateAPI.java | 69 ++++++++++++++++++ .../chronicle/set/ChronicleSetBuilder.java | 10 +++ 7 files changed, 168 insertions(+), 70 deletions(-) create mode 100644 src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilderPrivateAPI.java create mode 100644 src/main/java/net/openhft/chronicle/map/ChronicleMapBuilderPrivateAPI.java diff --git a/pom.xml b/pom.xml index 345c72ce4..905948cf6 100755 --- a/pom.xml +++ b/pom.xml @@ -228,18 +228,19 @@ net.openhft.chronicle.hash.serialization.internal:net.openhft.xstream:net.openhft.xstream.*:net.openhft.chronicle.hash.impl:net.openhft.chronicle.map.impl:net.openhft.chronicle.hash.hashing - net/openhft/chronicle/map/VanillaChronicleMap.java - net/openhft/chronicle/map/ReplicatedChronicleMap.java - net/openhft/chronicle/map/Replica.java - net/openhft/chronicle/map/ServiceDescriptor.java - net/openhft/chronicle/hash/Segment.java - net/openhft/chronicle/map/MapEventListener.java - net/openhft/chronicle/map/MapEntryCallback.java + net/openhft/chronicle/hash/ChronicleHashBuilderPrivateAPI.java net/openhft/chronicle/hash/KeyContext.java - net/openhft/chronicle/map/MapKeyContext.java + net/openhft/chronicle/hash/Segment.java net/openhft/chronicle/hash/locks/LockingStrategy.java - net/openhft/chronicle/map/TcpReplicator.java net/openhft/chronicle/map/ConstantValueProvider.java + net/openhft/chronicle/map/MapEntryCallback.java + net/openhft/chronicle/map/MapEventListener.java + net/openhft/chronicle/map/MapKeyContext.java + net/openhft/chronicle/map/VanillaChronicleMap.java + net/openhft/chronicle/map/Replica.java + net/openhft/chronicle/map/ReplicatedChronicleMap.java + net/openhft/chronicle/map/ServiceDescriptor.java + net/openhft/chronicle/map/TcpReplicator.java false -Xdoclint:none diff --git a/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilder.java b/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilder.java index c52501226..fc06ae828 100755 --- a/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilder.java +++ b/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilder.java @@ -505,4 +505,9 @@ public interface ChronicleHashBuilder, * @see ChronicleHashInstanceBuilder#persistedTo(File) */ H createPersistedTo(File file) throws IOException; + + /** + * @deprecated don't use private API in the client code + */ + ChronicleHashBuilderPrivateAPI privateAPI(); } diff --git a/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilderPrivateAPI.java b/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilderPrivateAPI.java new file mode 100644 index 000000000..eac41a5a3 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilderPrivateAPI.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2015 higherfrequencytrading.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package net.openhft.chronicle.hash; + +import net.openhft.chronicle.hash.serialization.internal.SerializationBuilder; + +public interface ChronicleHashBuilderPrivateAPI { + + SerializationBuilder keyBuilder(); + + int segmentEntrySpaceInnerOffset(boolean replicated); + + long chunkSize(boolean replicated); + + int maxChunksPerEntry(boolean replicated); + + long entriesPerSegment(boolean replicated); + + long actualChunksPerSegment(boolean replicated); + + int segmentHeaderSize(boolean replicated); + + int actualSegments(boolean replicated); +} 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 604c935ab..ed9b58e00 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java @@ -16,10 +16,7 @@ package net.openhft.chronicle.hash.impl; -import net.openhft.chronicle.hash.ChronicleHash; -import net.openhft.chronicle.hash.ExternalHashQueryContext; -import net.openhft.chronicle.hash.HashEntry; -import net.openhft.chronicle.hash.HashSegmentContext; +import net.openhft.chronicle.hash.*; import net.openhft.chronicle.hash.impl.util.BuildVersion; import net.openhft.chronicle.hash.serialization.BytesReader; import net.openhft.chronicle.hash.serialization.SizeMarshaller; @@ -112,14 +109,16 @@ public abstract class VanillaChronicleHash builder, boolean replicated) { // Version dataFileVersion = BuildVersion.version(); + @SuppressWarnings("deprecation") + ChronicleHashBuilderPrivateAPI privateAPI = builder.privateAPI(); + // Data model - SerializationBuilder keyBuilder = builder.keyBuilder(); + SerializationBuilder keyBuilder = privateAPI.keyBuilder(); kClass = keyBuilder.eClass; keySizeMarshaller = keyBuilder.sizeMarshaller(); originalKeyReader = keyBuilder.reader(); @@ -127,17 +126,17 @@ public abstract class VanillaChronicleHash) keyBuilder.metaInteropProvider(); - actualSegments = builder.actualSegments(replicated); + actualSegments = privateAPI.actualSegments(replicated); hashSplitting = HashSplitting.Splitting.forSegments(actualSegments); - entriesPerSegment = builder.entriesPerSegment(replicated); + entriesPerSegment = privateAPI.entriesPerSegment(replicated); - chunkSize = builder.chunkSize(replicated); - maxChunksPerEntry = builder.maxChunksPerEntry(replicated); - actualChunksPerSegment = builder.actualChunksPerSegment(replicated); + chunkSize = privateAPI.chunkSize(replicated); + maxChunksPerEntry = privateAPI.maxChunksPerEntry(replicated); + actualChunksPerSegment = privateAPI.actualChunksPerSegment(replicated); // Precomputed offsets and sizes for fast Context init - segmentHeaderSize = builder.segmentHeaderSize(replicated); + segmentHeaderSize = privateAPI.segmentHeaderSize(replicated); segmentHashLookupValueBits = valueBits(actualChunksPerSegment); segmentHashLookupKeyBits = keyBits(entriesPerSegment, segmentHashLookupValueBits); @@ -152,7 +151,7 @@ public abstract class VanillaChronicleHash implements private static final boolean strictStateChecks = Boolean.getBoolean("chronicle.strictStateChecks"); + private ChronicleMapBuilderPrivateAPI privateAPI = new ChronicleMapBuilderPrivateAPI<>(this); + SerializationBuilder keyBuilder; SerializationBuilder valueBuilder; @@ -196,7 +199,8 @@ public final class ChronicleMapBuilder implements } public static ChronicleMapStatelessClientBuilder of( - @NotNull Class keyClass, @NotNull Class valueClass, InetSocketAddress socketAddress) { + @NotNull Class keyClass, @NotNull Class valueClass, + InetSocketAddress socketAddress) { return ChronicleMapStatelessClientBuilder.of(socketAddress); } @@ -236,12 +240,21 @@ public final class ChronicleMapBuilder implements (ChronicleMapBuilder) super.clone(); result.keyBuilder = keyBuilder.clone(); result.valueBuilder = valueBuilder.clone(); + result.privateAPI = new ChronicleMapBuilderPrivateAPI<>(result); return result; } catch (CloneNotSupportedException e) { throw new AssertionError(e); } } + /** + * @deprecated don't use private API in the client code + */ + @Override + public ChronicleHashBuilderPrivateAPI privateAPI() { + return privateAPI; + } + /** * {@inheritDoc} * @@ -484,11 +497,7 @@ public final class ChronicleMapBuilder implements return this; } - /** - * @deprecated part of private API, shouldn't be used in the client code - */ - @Deprecated - public SerializationBuilder keyBuilder() { + SerializationBuilder keyBuilder() { return keyBuilder; } @@ -547,11 +556,7 @@ public final class ChronicleMapBuilder implements return new EntrySizeInfo(size, worstAlignment); } - /** - * @deprecated part of private API, shouldn't be used in the client code - */ - @Deprecated - public int segmentEntrySpaceInnerOffset(boolean replicated) { + int segmentEntrySpaceInnerOffset(boolean replicated) { // This is needed, if chunkSize = constant entry size is not aligned, for entry alignment // to be always the same, we should _misalign_ the first chunk. if (!constantlySizedEntries()) @@ -607,11 +612,7 @@ public final class ChronicleMapBuilder implements return greatestCommonDivisor(b, a % b); } - /** - * @deprecated part of private API, shouldn't be used in the client code - */ - @Deprecated - public long chunkSize(boolean replicated) { + long chunkSize(boolean replicated) { if (actualChunkSize > 0) return actualChunkSize; double averageEntrySize = entrySizeInfo(replicated).averageEntrySize; @@ -632,7 +633,6 @@ public final class ChronicleMapBuilder implements double averageChunksPerEntry(boolean replicated) { if (constantlySizedEntries()) return 1.0; - @SuppressWarnings("deprecation") long chunkSize = chunkSize(replicated); // assuming we always has worst internal fragmentation. This affects total segment // entry space which is allocated lazily on Linux (main target platform) @@ -653,14 +653,9 @@ public final class ChronicleMapBuilder implements return this; } - /** - * @deprecated part of private API, shouldn't be used in the client code - */ - @Deprecated - public int maxChunksPerEntry(boolean replicated) { + int maxChunksPerEntry(boolean replicated) { if (constantlySizedEntries()) return 1; - @SuppressWarnings("deprecation") long actualChunksPerSegment = actualChunksPerSegment(replicated); int result = (int) Math.min(actualChunksPerSegment, (long) Integer.MAX_VALUE); if (this.maxChunksPerEntry > 0) @@ -739,16 +734,11 @@ public final class ChronicleMapBuilder implements return this; } - /** - * @deprecated part of private API, shouldn't be used in the client code - */ - @Deprecated - public long entriesPerSegment(boolean replicated) { + long entriesPerSegment(boolean replicated) { long entriesPerSegment; if (this.entriesPerSegment > 0L) { entriesPerSegment = this.entriesPerSegment; } else { - @SuppressWarnings("deprecation") int actualSegments = actualSegments(replicated); long totalEntries = totalEntriesIfPoorDistribution(actualSegments); entriesPerSegment = divideUpper(totalEntries, actualSegments); @@ -799,11 +789,7 @@ public final class ChronicleMapBuilder implements } } - /** - * @deprecated part of private API, shouldn't be used in the client code - */ - @Deprecated - public long actualChunksPerSegment(boolean replicated) { + long actualChunksPerSegment(boolean replicated) { if (actualChunksPerSegment > 0) return actualChunksPerSegment; return chunksPerSegment(entriesPerSegment(replicated), replicated); @@ -850,7 +836,7 @@ public final class ChronicleMapBuilder implements return (int) Math.min(Maths.nextPower2(entries() / 32, 1), estimateSegmentsBasedOnSize()); } - //TODO reivew because this heuristic doesn't seem to perform well + //TODO review because this heuristic doesn't seem to perform well private int estimateSegmentsBasedOnSize() { // the idea is that if values are huge, operations on them (and simply ser/deser) // could take long time, so we want more segment to minimize probablity that @@ -892,11 +878,7 @@ public final class ChronicleMapBuilder implements return this; } - /** - * @deprecated part of private API, shouldn't be used in the client code - */ - @Deprecated - public int actualSegments(boolean replicated) { + int actualSegments(boolean replicated) { if (actualSegments > 0) return actualSegments; if (entriesPerSegment > 0) { @@ -984,12 +966,7 @@ public final class ChronicleMapBuilder implements return segments <= maxSegments ? segments : -segments; } - /** - * @deprecated part of private API, shouldn't be used in the client code - */ - @Deprecated - public int segmentHeaderSize(boolean replicated) { - @SuppressWarnings("deprecation") + int segmentHeaderSize(boolean replicated) { int segments = actualSegments(replicated); // reduce false sharing unless we have a lot of segments. return segments <= 16 * 1024 ? 64 : 32; @@ -1589,7 +1566,6 @@ public final class ChronicleMapBuilder implements if (builder.constantSizeMarshaller()) return round(ceil(averageSize)); - @SuppressWarnings("deprecation") int maxChunksPerEntry = maxChunksPerEntry(replicated); // if maxChunksPerEntry is Integer.MAX_VALUE, we, of cause, // are not going to allocate such big buffers diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilderPrivateAPI.java b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilderPrivateAPI.java new file mode 100644 index 000000000..ac9f82c1a --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilderPrivateAPI.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2015 higherfrequencytrading.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package net.openhft.chronicle.map; + +import net.openhft.chronicle.hash.ChronicleHashBuilderPrivateAPI; +import net.openhft.chronicle.hash.serialization.internal.SerializationBuilder; + +class ChronicleMapBuilderPrivateAPI implements ChronicleHashBuilderPrivateAPI { + + private ChronicleMapBuilder b; + + public ChronicleMapBuilderPrivateAPI(ChronicleMapBuilder b) { + this.b = b; + } + + @Override + public SerializationBuilder keyBuilder() { + return b.keyBuilder(); + } + + @Override + public int segmentEntrySpaceInnerOffset(boolean replicated) { + return b.segmentEntrySpaceInnerOffset(replicated); + } + + @Override + public long chunkSize(boolean replicated) { + return b.chunkSize(replicated); + } + + @Override + public int maxChunksPerEntry(boolean replicated) { + return b.maxChunksPerEntry(replicated); + } + + @Override + public long entriesPerSegment(boolean replicated) { + return b.entriesPerSegment(replicated); + } + + @Override + public long actualChunksPerSegment(boolean replicated) { + return b.actualChunksPerSegment(replicated); + } + + @Override + public int segmentHeaderSize(boolean replicated) { + return b.segmentHeaderSize(replicated); + } + + @Override + public int actualSegments(boolean replicated) { + return b.actualSegments(replicated); + } +} diff --git a/src/main/java/net/openhft/chronicle/set/ChronicleSetBuilder.java b/src/main/java/net/openhft/chronicle/set/ChronicleSetBuilder.java index 9d2066526..4632fe981 100755 --- a/src/main/java/net/openhft/chronicle/set/ChronicleSetBuilder.java +++ b/src/main/java/net/openhft/chronicle/set/ChronicleSetBuilder.java @@ -17,6 +17,7 @@ package net.openhft.chronicle.set; import net.openhft.chronicle.hash.ChronicleHashBuilder; +import net.openhft.chronicle.hash.ChronicleHashBuilderPrivateAPI; import net.openhft.chronicle.hash.ChronicleHashInstanceBuilder; import net.openhft.chronicle.hash.replication.SingleChronicleHashReplication; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; @@ -288,5 +289,14 @@ public final class ChronicleSetBuilder ChronicleMap map = chronicleMapBuilder.createPersistedTo(file); return new SetFromMap<>(map); } + + /** + * @deprecated don't use private API in the client code + */ + @Deprecated + @Override + public ChronicleHashBuilderPrivateAPI privateAPI() { + return chronicleMapBuilder.privateAPI(); + } }