Reduce ChronicleMapBuilder API surface, hide private API in a class

This commit is contained in:
leventov
2015-08-05 02:57:12 +03:00
parent 8afd90c528
commit 2b6c871562
7 changed files with 168 additions and 70 deletions
@@ -505,4 +505,9 @@ public interface ChronicleHashBuilder<K, H extends ChronicleHash<K, ?, ?, ?>,
* @see ChronicleHashInstanceBuilder#persistedTo(File)
*/
H createPersistedTo(File file) throws IOException;
/**
* @deprecated don't use private API in the client code
*/
ChronicleHashBuilderPrivateAPI<K> privateAPI();
}
@@ -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 <http://www.gnu.org/licenses/>.
*/
package net.openhft.chronicle.hash;
import net.openhft.chronicle.hash.serialization.internal.SerializationBuilder;
public interface ChronicleHashBuilderPrivateAPI<K> {
SerializationBuilder<K> 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);
}
@@ -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<K, KI, MKI extends MetaBytesInterop<K
transient long segmentsOffset;
public transient CompactOffHeapLinearHashTable hashLookup;
@SuppressWarnings("deprecation")
public VanillaChronicleHash(ChronicleMapBuilder<K, ?> builder, boolean replicated) {
// Version
dataFileVersion = BuildVersion.version();
@SuppressWarnings("deprecation")
ChronicleHashBuilderPrivateAPI<K> privateAPI = builder.privateAPI();
// Data model
SerializationBuilder<K> keyBuilder = builder.keyBuilder();
SerializationBuilder<K> keyBuilder = privateAPI.keyBuilder();
kClass = keyBuilder.eClass;
keySizeMarshaller = keyBuilder.sizeMarshaller();
originalKeyReader = keyBuilder.reader();
@@ -127,17 +126,17 @@ public abstract class VanillaChronicleHash<K, KI, MKI extends MetaBytesInterop<K
originalMetaKeyInterop = (MKI) keyBuilder.metaInterop();
metaKeyInteropProvider = (MetaProvider<K, KI, MKI>) 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<K, KI, MKI extends MetaBytesInterop<K
segmentFreeListOuterSize = CACHE_LINES.align(segmentFreeListInnerSize, BYTES);
segmentEntrySpaceInnerSize = chunkSize * actualChunksPerSegment;
segmentEntrySpaceInnerOffset = builder.segmentEntrySpaceInnerOffset(replicated);
segmentEntrySpaceInnerOffset = privateAPI.segmentEntrySpaceInnerOffset(replicated);
segmentEntrySpaceOuterSize = CACHE_LINES.align(
segmentEntrySpaceInnerOffset + segmentEntrySpaceInnerSize, BYTES);
@@ -17,6 +17,7 @@
package net.openhft.chronicle.map;
import net.openhft.chronicle.hash.ChronicleHashBuilder;
import net.openhft.chronicle.hash.ChronicleHashBuilderPrivateAPI;
import net.openhft.chronicle.hash.ChronicleHashInstanceBuilder;
import net.openhft.chronicle.hash.replication.*;
import net.openhft.chronicle.hash.serialization.*;
@@ -129,6 +130,8 @@ public final class ChronicleMapBuilder<K, V> implements
private static final boolean strictStateChecks =
Boolean.getBoolean("chronicle.strictStateChecks");
private ChronicleMapBuilderPrivateAPI<K> privateAPI = new ChronicleMapBuilderPrivateAPI<>(this);
SerializationBuilder<K> keyBuilder;
SerializationBuilder<V> valueBuilder;
@@ -196,7 +199,8 @@ public final class ChronicleMapBuilder<K, V> implements
}
public static <K, V> ChronicleMapStatelessClientBuilder<K, V> of(
@NotNull Class<K> keyClass, @NotNull Class<V> valueClass, InetSocketAddress socketAddress) {
@NotNull Class<K> keyClass, @NotNull Class<V> valueClass,
InetSocketAddress socketAddress) {
return ChronicleMapStatelessClientBuilder.of(socketAddress);
}
@@ -236,12 +240,21 @@ public final class ChronicleMapBuilder<K, V> implements
(ChronicleMapBuilder<K, V>) 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<K> privateAPI() {
return privateAPI;
}
/**
* {@inheritDoc}
*
@@ -484,11 +497,7 @@ public final class ChronicleMapBuilder<K, V> implements
return this;
}
/**
* @deprecated part of private API, shouldn't be used in the client code
*/
@Deprecated
public SerializationBuilder<K> keyBuilder() {
SerializationBuilder<K> keyBuilder() {
return keyBuilder;
}
@@ -547,11 +556,7 @@ public final class ChronicleMapBuilder<K, V> 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<K, V> 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<K, V> 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<K, V> 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<K, V> 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<K, V> 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<K, V> 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<K, V> 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<K, V> 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<K, V> 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
@@ -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 <http://www.gnu.org/licenses/>.
*/
package net.openhft.chronicle.map;
import net.openhft.chronicle.hash.ChronicleHashBuilderPrivateAPI;
import net.openhft.chronicle.hash.serialization.internal.SerializationBuilder;
class ChronicleMapBuilderPrivateAPI<K> implements ChronicleHashBuilderPrivateAPI<K> {
private ChronicleMapBuilder<K, ?> b;
public ChronicleMapBuilderPrivateAPI(ChronicleMapBuilder<K, ?> b) {
this.b = b;
}
@Override
public SerializationBuilder<K> 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);
}
}
@@ -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<K>
ChronicleMap<K, DummyValue> map = chronicleMapBuilder.createPersistedTo(file);
return new SetFromMap<>(map);
}
/**
* @deprecated don't use private API in the client code
*/
@Deprecated
@Override
public ChronicleHashBuilderPrivateAPI<K> privateAPI() {
return chronicleMapBuilder.privateAPI();
}
}