diff --git a/src/main/java/net/openhft/chronicle/hash/replication/ReplicationHub.java b/src/main/java/net/openhft/chronicle/hash/replication/ReplicationHub.java index 81d1b1a7d..2240a5da5 100644 --- a/src/main/java/net/openhft/chronicle/hash/replication/ReplicationHub.java +++ b/src/main/java/net/openhft/chronicle/hash/replication/ReplicationHub.java @@ -28,10 +28,10 @@ import java.util.Arrays; /** * This class holds all configurations of * multicontainer replication, which is usable, when you want to replicate several {@linkplain - * ChronicleHash ChronicleHashes} ({@linkplain ChronicleMap maps}, {@linkplain ChronicleSet sets}, etc.) - * between same servers. {@code ReplicationHub} allows to share TCP/UDP connection, sockets, buffers, worker - * threads for that, considerably reducing resources usage and increasing cumulative (for all replicated - * containers) replication throughput. See + * ChronicleHash ChronicleHashes} ({@linkplain ChronicleMap maps}, {@linkplain ChronicleSet sets}, + * etc.) between same servers. {@code ReplicationHub} allows to share TCP/UDP connection, sockets, + * buffers, worker threads for that, considerably reducing resources usage and increasing cumulative + * (for all replicated containers) replication throughput. See * the corresponding section in ChronicleMap manual for more information. * *
Create instances of this class using this pattern:
{@code
@@ -61,38 +61,24 @@ public final class ReplicationHub extends AbstractReplication {
return new Builder();
}
- private final int maxEntrySize;
private final ReplicationChannel[] channels;
private ReplicationHub(byte localIdentifier, Builder builder) {
super(localIdentifier, builder);
- maxEntrySize = builder.maxEntrySize;
+
channels = new ReplicationChannel[builder.maxNumberOfChannels];
}
@Override
public String toString() {
return "ReplicationHub{" + super.toString() +
- ", maxEntrySize=" + maxEntrySize +
", channels=" + Arrays.toString(channels) + '}';
}
- /**
- * Returns the maximum {@linkplain ChronicleHashBuilder#entrySize(int) entry size} of {@link
- * ChronicleHash}es, replicated by this {@code ReplicationHub}, could have. {@code RuntimeException} is
- * thrown on attempt to replicate with this {@code ReplicationHub} a {@code ChronicleHash} with larger
- * entry size.
- *
- * @return the maximum entry size
- * @see Builder#maxEntrySize(int)
- */
- public int maxEntrySize() {
- return maxEntrySize;
- }
/**
- * Returns the maximum number of channels could be {@linkplain #createChannel(int) created} for this
- * {@code ReplicationHub}.
+ * Returns the maximum number of channels could be {@linkplain #createChannel(int) created} for
+ * this {@code ReplicationHub}.
*
* @return the maximum number of channels
* @see Builder#maxNumberOfChannels()
@@ -103,19 +89,20 @@ public final class ReplicationHub extends AbstractReplication {
}
/**
- * Creates a new {@link ReplicationChannel} in this {@code ReplicationHub} with the given identifier.
- * Identifier shouldn't be lesser than zero and greater or equal to {@code maxNumberOfChannels() - 1}. On
- * a {@code ReplicationHub} instance, {@code ReplicationChannel} could be created only once for each
- * possible {@code channelId} value.
+ * Creates a new {@link ReplicationChannel} in this {@code ReplicationHub} with the given
+ * identifier. Identifier shouldn't be lesser than zero and greater or equal to {@code
+ * maxNumberOfChannels() - 1}. On a {@code ReplicationHub} instance, {@code ReplicationChannel}
+ * could be created only once for each possible {@code channelId} value.
*
- * @param channelId the identifier of the channel. Should be equal for replicated containers on different
- * nodes (servers)
- * @return a new {@code ReplicationChannel} instance, in fact just incapsulating the given {@code
- * channelId} for this {@code ReplicationHub}
- * @throws IllegalArgumentException if the specified {@code channelId} is out of
[0, {@link
- * #maxNumberOfChannels()}) range
- * @throws IllegalStateException if {@code ReplicationChannel} with the specified {@code channelId} has
- * already been acquired on this {@code ReplicationHub}
+ * @param channelId the identifier of the channel. Should be equal for replicated containers on
+ * different nodes (servers)
+ * @return a new {@code ReplicationChannel} instance, in fact just incapsulating the given
+ * {@code channelId} for this {@code ReplicationHub}
+ * @throws IllegalArgumentException if the specified {@code channelId} is out of
[0,
+ * {@link #maxNumberOfChannels()}) range
+ * @throws IllegalStateException if {@code ReplicationChannel} with the specified {@code
+ * channelId} has already been acquired on this {@code
+ * ReplicationHub}
* @see ReplicationChannel
*/
public synchronized ReplicationChannel createChannel(int channelId) {
@@ -136,37 +123,20 @@ public final class ReplicationHub extends AbstractReplication {
* Builder of {@link ReplicationHub}s.
*/
public static final class Builder extends AbstractReplication.Builder {
- private int maxEntrySize = 1024;
+
private int maxNumberOfChannels = 128;
private Builder() {
}
/**
- * Configures the maximum {@linkplain ChronicleHashBuilder#entrySize(int) entry size} of {@link
- * ChronicleHash}es, replicated via {@code ReplicationHub}s, created by this builder.
- *
- * Default value is {@code 1024}.
- *
- * @param maxEntrySize {@link ReplicationHub#maxEntrySize()} of {@link ReplicationHub}s, created by
- * this builder
- * @return this builder object back, for chaining
- * @see ReplicationHub#maxEntrySize()
- */
- @NotNull
- public Builder maxEntrySize(int maxEntrySize) {
- this.maxEntrySize = maxEntrySize * 64;
- return this;
- }
-
- /**
- * Configures the maximum number of channels could be {@linkplain #createChannel(int)} created for
- * {@code ReplicationHub}s, created by this builder.
+ * Configures the maximum number of channels could be {@linkplain #createChannel(int)}
+ * created for {@code ReplicationHub}s, created by this builder.
*
*
Default value is {@code 128}.
*
- * @param maxNumberOfChannels {@link ReplicationHub#maxNumberOfChannels()} of {@link ReplicationHub}s,
- * created by this builder
+ * @param maxNumberOfChannels {@link ReplicationHub#maxNumberOfChannels()} of {@link
+ * ReplicationHub}s, created by this builder
* @return this builder object back, for chaining
* @see ReplicationHub#maxNumberOfChannels()
*/
diff --git a/src/main/java/net/openhft/chronicle/map/ChannelProvider.java b/src/main/java/net/openhft/chronicle/map/ChannelProvider.java
index e24bf5890..2b877a3a8 100644
--- a/src/main/java/net/openhft/chronicle/map/ChannelProvider.java
+++ b/src/main/java/net/openhft/chronicle/map/ChannelProvider.java
@@ -77,7 +77,7 @@ final class ChannelProvider implements Closeable {
new UdpReplicator(
channelProvider.asReplica,
channelProvider.asEntryExternalizable,
- udpConfig, hub.maxEntrySize());
+ udpConfig);
channelProvider.add(udpReplicator);
if (tcpConfig == null)
LOG.warn(Replicators.ONLY_UDP_WARN_MESSAGE);
@@ -258,7 +258,7 @@ final class ChannelProvider implements Closeable {
};
private final ReplicationHub hub;
- private final int maxEntrySize;
+
private final ReadWriteLock channelDataLock = new ReentrantReadWriteLock();
@@ -283,7 +283,7 @@ final class ChannelProvider implements Closeable {
private ChannelProvider(ReplicationHub hub) {
localIdentifier = hub.identifier();
this.hub = hub;
- maxEntrySize = hub.maxEntrySize();
+
chronicleChannels = new Replica[hub.maxNumberOfChannels()];
channelEntryExternalizables = new EntryExternalizable[hub.maxNumberOfChannels()];
chronicleChannelList = new ArrayList();
@@ -304,9 +304,6 @@ final class ChannelProvider implements Closeable {
add((short) 0, systemMessageQueue.asReplica, systemMessageQueue.asEntryExternalizable);
}
- public int maxEntrySize() {
- return maxEntrySize;
- }
/**
* creates a bit set based on a number of bits
diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java
index 4426d3718..2431f1e3a 100755
--- a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java
+++ b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java
@@ -70,24 +70,18 @@ import static net.openhft.lang.model.DataValueGenerator.firstPrimitiveFieldType;
*
* ChronicleMap map1 = builder.create();
* ChronicleMap map2 = builder.create();}
- * i. e. created {@code ChronicleMap} instances don't depend on the builder.
- * - *
{@code ChronicleMapBuilder} is mutable, see a note in {@link ChronicleHashBuilder} interface - * documentation. - *
- *
Later in this documentation, "ChronicleMap" means "ChronicleMaps, created by {@code - * ChronicleMapBuilder}", unless specified different, because theoretically someone might provide - * {@code ChronicleMap} implementations with completely different properties. - *
- *
{@code ChronicleMap} ("ChronicleMaps, created by {@code ChronicleMapBuilder}") currently - * doesn't support resizing. That is why you should always configure {@linkplain - * #entries(long) number of entries} you are going to insert into the created map at most. - * See {@link #entries(long)} method documentation for more information on this. - *
- *
{@code ChronicleMap} allocates memory by equally sized chunks. This size is called {@linkplain - * #entrySize(int) entry size}, you are strongly recommended to configure it to achieve least memory - * consumption and best speed. See {@link #entrySize(int)} method documentation for more information - * on this. + * i. e. created {@code ChronicleMap} instances don't depend on the builder.
{@code + * ChronicleMapBuilder} is mutable, see a note in {@link ChronicleHashBuilder} interface + * documentation.
Later in this documentation, "ChronicleMap" means "ChronicleMaps, created + * by {@code ChronicleMapBuilder}", unless specified different, because theoretically someone might + * provide {@code ChronicleMap} implementations with completely different properties.
{@code + * ChronicleMap} ("ChronicleMaps, created by {@code ChronicleMapBuilder}") currently doesn't support + * resizing. That is why you should always configure {@linkplain #entries(long) number of + * entries} you are going to insert into the created map at most. See {@link #entries(long)} + * method documentation for more information on this.
{@code ChronicleMap} allocates memory
+ * by equally sized chunks. This size is called {@linkplain #entrySize(int) entry size}, you are
+ * strongly recommended to configure it to achieve least memory consumption and best speed. See
+ * {@link #entrySize(int)} method documentation for more information on this.
*
* @param
- * Example: if keys in your map(s) are English words in {@link String} form, keys size 10
+ * {@inheritDoc} Example: if keys in your map(s) are English words in {@link String}
+ * form, keys size 10
* (a bit more than average English word length) would be a good choice:
+ * {@inheritDoc}
* For example, if your keys are Git commit hashes:
- * If values are of boxed primitive type or {@link Byteable} subclass, i. e. if value size is
- * known statically, it is automatically accounted and shouldn't be specified by user.
- *
- * If value size varies moderately, specify the size higher than average, but lower than the
- * maximum possible, to minimize average memory overuse. If value size varies in a wide range,
- * it's better to use {@linkplain #entrySize(int) entry size} in "chunk" mode and configure it
- * directly.
+ * #constantValueSizeBySample(Object)} method instead of this one. If values are of boxed
+ * primitive type or {@link Byteable} subclass, i. e. if value size is known statically, it is
+ * automatically accounted and shouldn't be specified by user. If value size varies
+ * moderately, specify the size higher than average, but lower than the maximum possible, to
+ * minimize average memory overuse. If value size varies in a wide range, it's better to use
+ * {@linkplain #entrySize(int) entry size} in "chunk" mode and configure it directly.
*
* @param valueSize number of bytes, taken by serialized form of values
* @return this builder back
@@ -311,13 +300,11 @@ public final class ChronicleMapBuilder
- * If values are of boxed primitive type or {@link Byteable} subclass, i. e. if value size is
- * known statically, it is automatically accounted and this method shouldn't be called.
- *
- * If value size varies, method {@link #valueSize(int)} or {@link #entrySize(int)} should be
- * called instead of this one.
+ * take the same number of bytes in serialized form, as this sample object. If values are
+ * of boxed primitive type or {@link Byteable} subclass, i. e. if value size is known
+ * statically, it is automatically accounted and this method shouldn't be called. If
+ * value size varies, method {@link #valueSize(int)} or {@link #entrySize(int)} should be called
+ * instead of this one.
*
* @param sampleValue the sample value
* @return this builder back
@@ -342,18 +329,14 @@ public final class ChronicleMapBuilder
- * In fully default case you can expect entry size to be about 256 bytes. But it is strongly
- * recommended always to configure {@linkplain #keySize(int) key size} and {@linkplain
- * #valueSize(int) value size}, if they couldn't be derived statically.
- *
- * If entry size is not configured explicitly by calling this method, it is computed based on
+ * {@inheritDoc} In fully default case you can expect entry size to be about 256 bytes.
+ * But it is strongly recommended always to configure {@linkplain #keySize(int) key size} and
+ * {@linkplain #valueSize(int) value size}, if they couldn't be derived statically. If
+ * entry size is not configured explicitly by calling this method, it is computed based on
* {@linkplain #metaDataBytes(int) meta data bytes}, plus {@linkplain #keySize(int) key size},
* plus {@linkplain #valueSize(int) value size}, plus a few bytes required by implementations,
- * with respect to {@linkplain #entryAndValueAlignment(Alignment) alignment}.
- *
- * Note that the actual entrySize will be aligned by the configured {@linkplain
+ * with respect to {@linkplain #entryAndValueAlignment(Alignment) alignment}. Note that
+ * the actual entrySize will be aligned by the configured {@linkplain
* #entryAndValueAlignment(Alignment) entry and value alignment}. I. e. if you set entry size to
* 30, and entry alignment is set to {@link Alignment#OF_4_BYTES}, the actual entry size will be
* 32 (30 aligned to 4 bytes).
@@ -439,22 +422,17 @@ public final class ChronicleMapBuilder
- * Useful when values of the map are updated intensively, particularly fields with volatile
- * access, because it doesn't work well if the value crosses cache lines. Also, on some
- * (nowadays rare) architectures any misaligned memory access is more expensive than aligned.
- *
- * Note that {@linkplain #entrySize(int) entry size} will be aligned according to this
- * alignment. I. e. if you set {@code entrySize(20)} and {@link Alignment#OF_8_BYTES}, actual
- * entry size will be 24 (20 aligned to 8 bytes).
- *
- * If values couldn't reference off-heap memory (i. e. it is not {@link Byteable} or "data
- * value generated"), alignment configuration makes no sense and forbidden.
- *
- * Default is {@link Alignment#NO_ALIGNMENT} if values couldn't reference off-heap memory,
- * otherwise chosen heuristically (configure explicitly for being sure and to compare
- * performance in your case).
+ * memory of values within entries in ChronicleMaps, created by this builder. Useful when
+ * values of the map are updated intensively, particularly fields with volatile access, because
+ * it doesn't work well if the value crosses cache lines. Also, on some (nowadays rare)
+ * architectures any misaligned memory access is more expensive than aligned. Note that
+ * {@linkplain #entrySize(int) entry size} will be aligned according to this alignment. I. e. if
+ * you set {@code entrySize(20)} and {@link Alignment#OF_8_BYTES}, actual entry size will be 24
+ * (20 aligned to 8 bytes). If values couldn't reference off-heap memory (i. e. it is not
+ * {@link Byteable} or "data value generated"), alignment configuration makes no sense and
+ * forbidden. Default is {@link Alignment#NO_ALIGNMENT} if values couldn't reference
+ * off-heap memory, otherwise chosen heuristically (configure explicitly for being sure and to
+ * compare performance in your case).
*
* @param alignment the new alignment of the maps constructed by this builder
* @return this {@code ChronicleMapOnHeapUpdatableBuilder} back
@@ -660,16 +638,13 @@ public final class ChronicleMapBuilder
- * {@link Map#put(Object, Object) Map.put()} returns the previous value, functionality which
- * is rarely used but fairly cheap for {@link HashMap}. In the case, for an off heap collection,
- * it has to create a new object and deserialize the data from off-heap memory. It's expensive
- * for something you probably don't use.
- *
- * By default, of cause, {@code ChronicleMap} conforms the general {@code Map} contract and
- * returns the previous mapped value on {@code put()} calls.
+ * mapped values on {@link ChronicleMap#put(Object, Object) ChornicleMap.put(key, value)} calls.
+ * {@link Map#put(Object, Object) Map.put()} returns the previous value, functionality
+ * which is rarely used but fairly cheap for {@link HashMap}. In the case, for an off heap
+ * collection, it has to create a new object and deserialize the data from off-heap memory. It's
+ * expensive for something you probably don't use. By default, of cause, {@code
+ * ChronicleMap} conforms the general {@code Map} contract and returns the previous mapped value
+ * on {@code put()} calls.
*
* @param putReturnsNull {@code true} if you want {@link ChronicleMap#put(Object, Object)
* ChronicleMap.put()} to not return the value that was replaced but
@@ -688,15 +663,12 @@ public final class ChronicleMapBuilder
+ * mapped value on {@link ChronicleMap#remove(Object) ChronicleMap.remove(key)} calls.
* {@link Map#remove(Object) Map.remove()} returns the previous value, functionality which is
* rarely used but fairly cheap for {@link HashMap}. In the case, for an off heap collection, it
* has to create a new object and deserialize the data from off-heap memory. It's expensive for
- * something you probably don't use.
- *
- * By default, of cause, {@code ChronicleMap} conforms the general {@code Map} contract and
- * returns the mapped value on {@code remove()} calls.
+ * something you probably don't use. By default, of cause, {@code ChronicleMap} conforms
+ * the general {@code Map} contract and returns the mapped value on {@code remove()} calls.
*
* @param removeReturnsNull {@code true} if you want {@link ChronicleMap#remove(Object)
* ChronicleMap.remove()} to not return the value of the removed entry
@@ -797,8 +769,7 @@ public final class ChronicleMapBuilder
+ * {@inheritDoc}
* Example:
- * This serializer is used to serialize both keys and values, if they both require this:
+ * This serializer is used to serialize both keys and values, if they both require this:
* loosely typed, nullable, and custom {@linkplain #keyMarshaller(BytesMarshaller) key} and
* {@linkplain #valueMarshaller(BytesMarshaller) value} marshallers are not configured.
*/
@@ -875,14 +845,11 @@ public final class ChronicleMapBuilder
+ * section about serialization in ChronicleMap manual for more information.
* Configuring marshalling this way results to a little bit more compact in-memory layout of
* the map, comparing to a single interface configuration: {@link #valueMarshaller(
- *BytesMarshaller)}.
- *
- * Passing {@link BytesInterop} instead of plain {@link BytesWriter} is, of cause, possible,
- * but currently pointless for values.
+ *BytesMarshaller)}. Passing {@link BytesInterop} instead of plain {@link BytesWriter}
+ * is, of cause, possible, but currently pointless for values.
*
* @param valueWriter the new value object → {@link Bytes} writer (interop) strategy
* @param valueReader the new {@link Bytes} → value object reader strategy
@@ -900,12 +867,11 @@ public final class ChronicleMapBuilder
- * Default value size marshaller is so-called {@linkplain SizeMarshallers#stopBit() stop bit
- * encoding marshalling}, unless {@link #constantValueSizeBySample(Object)} or the builder
- * statically knows the value size is constant -- {@link SizeMarshallers#constant(long)} or
- * equivalents are used by default in these cases.
+ * created by this builder. Default value size marshaller is so-called {@linkplain
+ * SizeMarshallers#stopBit() stop bit encoding marshalling}, unless {@link
+ * #constantValueSizeBySample(Object)} or the builder statically knows the value size is
+ * constant -- {@link SizeMarshallers#constant(long)} or equivalents are used by default in
+ * these cases.
*
* @param valueSizeMarshaller the new marshaller, used to serialize actual value sizes to
* off-heap memory
@@ -922,8 +888,7 @@ public final class ChronicleMapBuilder
+ * {@link DeserializationFactoryConfigurableBytesReader}, in maps, created by this builder.
* Default value deserialization factory is {@link NewInstanceObjectFactory}, which creates a
* new value instance using {@link Class#newInstance()} default constructor. You could provide
* an {@link AllocateInstanceObjectFactory}, which uses {@code Unsafe.allocateInstance(Class)}
@@ -964,11 +929,9 @@ public final class ChronicleMapBuilder
- * This configuration overrides any previous {@link #defaultValueProvider(
- *DefaultValueProvider)} and {@link #prepareDefaultValueBytes(PrepareValueBytes)}
- * configurations to this builder.
+ * acquireUsing()} method, if the key is absent in the map, created by this builder. This
+ * configuration overrides any previous {@link #defaultValueProvider(DefaultValueProvider)} and
+ * {@link #prepareDefaultValueBytes(PrepareValueBytes)} configurations to this builder.
*
* @param defaultValue the default value to be put to the map for absent keys during {@code
* acquireUsing()} calls
@@ -987,9 +950,8 @@ public final class ChronicleMapBuilder
- * This configuration overrides any previous {@link #defaultValue(Object)} and {@link
+ * acquireUsing()} calls, if the key is absent in the map, created by this builder. This
+ * configuration overrides any previous {@link #defaultValue(Object)} and {@link
* #prepareDefaultValueBytes(PrepareValueBytes)} configurations to this builder.
*
* @param defaultValueProvider the strategy to obtain a default value by the absent key
@@ -1009,16 +971,12 @@ public final class ChronicleMapBuilder
- * This method of value initialization on {@code acquireUsing()} calls is allowed only if
- * value size is constant. Otherwise you should use either {@link #defaultValue(Object)} or
- * {@link #defaultValueProvider(DefaultValueProvider)} methods.
- *
+ * information. This method of value initialization on {@code acquireUsing()} calls is
+ * allowed only if value size is constant. Otherwise you should use either {@link
+ * #defaultValue(Object)} or {@link #defaultValueProvider(DefaultValueProvider)} methods.
* This configuration overrides any previous {@link #defaultValue(Object)} and {@link
- * #defaultValueProvider(DefaultValueProvider)} configurations to this builder.
- *
- * The default preparation callback zeroes out the value bytes.
+ * #defaultValueProvider(DefaultValueProvider)} configurations to this builder. The
+ * default preparation callback zeroes out the value bytes.
*
* @param prepareValueBytes what to do with the value bytes before assigning them into the
* {@link Byteable} value or deserializing the value from, to return
@@ -1283,13 +1241,7 @@ public final class ChronicleMapBuilder{@code
* ChronicleMap{@code
* Map{@code Map
- *