mirror of
https://github.com/OpenHFT/Chronicle-Map.git
synced 2021-09-13 01:26:12 +00:00
Merge branch 'master' of github.com:OpenHFT/Chronicle-Map
Conflicts: src/main/java/net/openhft/chronicle/set/ChronicleSetBuilder.java
This commit is contained in:
@@ -46,7 +46,7 @@ Click here to get the [Latest Version Number](http://search.maven.org/#search%7C
|
||||
* [Identifier](https://github.com/OpenHFT/Chronicle-Map#identifier)
|
||||
* [Port](https://github.com/OpenHFT/Chronicle-Map#port)
|
||||
* [Heart Beat Interval](https://github.com/OpenHFT/Chronicle-Map#heart-beat-interval)
|
||||
* [Clustering](https://github.com/OpenHFT/Chronicle-Map#cluster)
|
||||
* [Channels and the Channel Provider](https://github.com/OpenHFT/Chronicle-Map#channels-and-channelprovider)
|
||||
|
||||
#### Miscellaneous
|
||||
|
||||
@@ -63,7 +63,6 @@ Click here to get the [Latest Version Number](http://search.maven.org/#search%7C
|
||||
* [Replicating data between process on different servers with UDP] (https://github.com/OpenHFT/Chronicle-Map/blob/master/README.md#example--replicating-data-between-process-on-different-servers-using-udp)
|
||||
* [Creating a Chronicle Set and adding data to it](https://github.com/OpenHFT/Chronicle-Map/blob/master/README.md#example--creating-a-chronicle-set-and-adding-data-to-it)
|
||||
|
||||
|
||||
#### Performance Topics
|
||||
|
||||
* [Chronicle Map with Large Data ](https://github.com/OpenHFT/Chronicle-Map#chronicle-map-with-large-data)
|
||||
@@ -71,12 +70,10 @@ Click here to get the [Latest Version Number](http://search.maven.org/#search%7C
|
||||
* [Better to use small keys](https://github.com/OpenHFT/Chronicle-Map#better-to-use-small-keys)
|
||||
* [ConcurrentHashMap v ChronicleMap](https://github.com/OpenHFT/Chronicle-Map#concurrenthashmap-v-chroniclemap)
|
||||
|
||||
|
||||
### Overview
|
||||
Chronicle Map implements the `java.util.concurrent.ConcurrentMap`, however unlike the standard
|
||||
java map, ChronicleMap is able to share your entries accross processes:
|
||||
|
||||
|
||||

|
||||
|
||||
## When to use
|
||||
@@ -512,7 +509,7 @@ A heartbeat will only be send if no data is transmitted, if the maps are constan
|
||||
no heartbeat message is sent. If a map does not receive either data of a heartbeat the connection
|
||||
is dropped and re-established.
|
||||
|
||||
# Cluster
|
||||
# Channels and ChannelProvider
|
||||
|
||||
Chronicle Map TCP Replication lets you distribute a single Chronicle Map, to a number of servers
|
||||
across your network. Replication is point to point and the data transfer is bidirectional, so in the
|
||||
@@ -520,37 +517,42 @@ example of just two servers, they only have to be connected via a single tcp soc
|
||||
the data is transferred both ways. Which is great, however what if you wanted to replicate more than
|
||||
just one chronicle map, what if you were going to replicate two chronicle maps across your network,
|
||||
unfortunately with just TCP replication you would have to have two tcp socket connections, which is
|
||||
not ideal. This is why we created Chronicle Clustering. Clustering lets you replicate numerous
|
||||
not ideal. This is why we created Chronicle Channels. Channels let you replicate numerous
|
||||
Chronicle Maps via a single point to point socket connection.
|
||||
|
||||
Clustering is similar to TCP replication, where each map has to be given a unique identifier, but
|
||||
when using Chronicle Clustering its the cluster that is given the unique identifier not the map.
|
||||
Chronicle Channels are similar to TCP replication, where each map has to be given a unique identifier, but
|
||||
when using Chronicle Channels its the channels that are given the unique identifier not the map.
|
||||
|
||||
``` java
|
||||
ReplicatingClusterBuilder clusterBuilder = new ReplicatingClusterBuilder((byte) 2, 1024);
|
||||
byte identifier = 2;
|
||||
int maxEntrySize = 1024;
|
||||
ChannelProvider replicator = new ChannelProviderBuilder(identifier, maxEntrySize)
|
||||
.create();
|
||||
```
|
||||
|
||||
In this example above the cluster is given the identifier of 2
|
||||
In this example above the channel is given the identifier of 2
|
||||
|
||||
In addition to specifying the identifier we also have to set the maximum entry size, this sets
|
||||
the size of the memory buffers within the cluster. This has to be set manually, with clusters you
|
||||
are able to attach additional maps to a cluster once its up and running, so the maximum size of each
|
||||
the size of the memory buffers within the ChannelProvider. This has to be set manually, with channels you
|
||||
are able to attach additional maps to a ChannelProvider once its up and running, so the maximum size of each
|
||||
entry in the map can not be known in advance and we don’t currently support automatic resizing
|
||||
of buffers.
|
||||
|
||||
Once you have created the cluster you should attach your tcpConfig
|
||||
Once you have created the ChannelProvider you should attach your tcp configuration
|
||||
``` java
|
||||
TcpReplicationConfig tcpConfig = TcpReplicationConfig.of(8087).heartBeatInterval(1, SECONDS);
|
||||
clusterBuilder.tcpReplication(tcpConfig);
|
||||
ReplicatingCluster cluster = clusterBuilder.create();
|
||||
byte identifier = 2;
|
||||
int maxEntrySize =1024;
|
||||
ChannelProvider replicator = new ChannelProviderBuilder(identifier, 1024)
|
||||
.tcpReplication(tcpConfig)
|
||||
.create();;
|
||||
```
|
||||
|
||||
Attaching cluster replication to the map:
|
||||
Attaching ChannelProvider replication to the map:
|
||||
|
||||
``` java
|
||||
ChronicleMap<Integer, CharSequence> map = ChronicleMapBuilder.of(Integer.class, CharSequence.class)
|
||||
.entries(1000)
|
||||
.addReplicator(cluster.channelReplicator((short) 1))
|
||||
.channel(replicator.createChannel((short) 1))
|
||||
.create(file);
|
||||
```
|
||||
|
||||
@@ -567,11 +569,11 @@ If you inadvertently got the chronicle channels around the wrong way, then chron
|
||||
to replicate the wrong maps data. The chronicle channels don't have to be in order but they must be
|
||||
unique for each map you have.
|
||||
|
||||
Once you have created the cluster you may wish to hold onto the reference so that you can call close
|
||||
once you have finished, this will close everything in the cluster
|
||||
Once you have created the ChannelProvider you may wish to hold onto the reference so that you can call close
|
||||
once you have finished, this will close everything in the ChannelProvider
|
||||
|
||||
``` java
|
||||
cluster.close();
|
||||
replicator.close();
|
||||
```
|
||||
|
||||
#### Known Issues
|
||||
|
||||
@@ -189,9 +189,7 @@ public interface ChronicleHashBuilder<K, C, B extends ChronicleHashBuilder<K, C,
|
||||
|
||||
B metaDataBytes(int metaDataBytes);
|
||||
|
||||
B addReplicator(Replicator replicator);
|
||||
|
||||
B setReplicators(Replicator... replicators);
|
||||
B replicators(byte identifier, Replicator... replicators);
|
||||
|
||||
B timeProvider(TimeProvider timeProvider);
|
||||
|
||||
|
||||
+9
-9
@@ -45,8 +45,8 @@ import static net.openhft.chronicle.map.Replica.ModificationNotifier.NOP;
|
||||
/**
|
||||
* @author Rob Austin.
|
||||
*/
|
||||
public final class ReplicatingCluster implements Closeable {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ReplicatingCluster.class.getName());
|
||||
public final class ChannelProvider implements Closeable {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ChannelProvider.class.getName());
|
||||
|
||||
private static final byte BOOTSTRAP_MESSAGE = 'B';
|
||||
final EntryExternalizable asEntryExternalizable = new EntryExternalizable() {
|
||||
@@ -152,7 +152,7 @@ public final class ReplicatingCluster implements Closeable {
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
ReplicatingCluster.this.close();
|
||||
ChannelProvider.this.close();
|
||||
}
|
||||
};
|
||||
private final int maxEntrySize;
|
||||
@@ -169,7 +169,7 @@ public final class ReplicatingCluster implements Closeable {
|
||||
private final Set<AbstractChannelReplicator> replicators =
|
||||
new CopyOnWriteArraySet<AbstractChannelReplicator>();
|
||||
|
||||
ReplicatingCluster(ReplicatingClusterBuilder builder) {
|
||||
ChannelProvider(ChannelProviderBuilder builder) {
|
||||
localIdentifier = builder.identifier;
|
||||
maxEntrySize = builder.maxEntrySize;
|
||||
chronicleChannels = new Replica[builder.maxNumberOfChronicles];
|
||||
@@ -206,12 +206,12 @@ public final class ReplicatingCluster implements Closeable {
|
||||
/**
|
||||
* Returns a replicator, dedicated to the specified channel. Channel is basically just a number, that
|
||||
* should correspond on different servers for instances of the same replicated map. Only one replicator
|
||||
* per channel could be obtained from a single {@code ReplicatingCluster}. The returned replicator could
|
||||
* per channel could be obtained from a single {@code ReplicatingChannel}. The returned replicator could
|
||||
* be applied to a map at most once.
|
||||
*
|
||||
* @return a replicator, dedicated to the specified channel
|
||||
*/
|
||||
public Replicator channelReplicator(short channel) {
|
||||
public ChronicleChannel createChannel(short channel) {
|
||||
return new ChronicleChannel(channel);
|
||||
}
|
||||
|
||||
@@ -393,14 +393,14 @@ public final class ReplicatingCluster implements Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
private class ChronicleChannel extends Replicator implements Closeable {
|
||||
public class ChronicleChannel extends Replicator implements Closeable {
|
||||
|
||||
private final short chronicleChannel;
|
||||
|
||||
private ChronicleChannel(short chronicleChannel) {
|
||||
this.chronicleChannel = chronicleChannel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte identifier() {
|
||||
return localIdentifier;
|
||||
}
|
||||
@@ -409,7 +409,7 @@ public final class ReplicatingCluster implements Closeable {
|
||||
protected Closeable applyTo(ChronicleMapBuilder builder,
|
||||
Replica map, EntryExternalizable entryExternalizable) {
|
||||
if (builder.entrySize() > maxEntrySize) {
|
||||
throw new IllegalArgumentException("During ReplicatingClusterBuilder setup, " +
|
||||
throw new IllegalArgumentException("During ReplicatingChannelBuilder setup, " +
|
||||
"maxEntrySize=" + maxEntrySize + " was specified, but map with " +
|
||||
"entrySize=" + builder.entrySize() + " is attempted to apply" +
|
||||
"to the replicator");
|
||||
+28
-20
@@ -21,40 +21,48 @@ import java.io.IOException;
|
||||
/**
|
||||
* @author Rob Austin.
|
||||
*/
|
||||
public final class ReplicatingClusterBuilder {
|
||||
public final class ChannelProviderBuilder {
|
||||
|
||||
final byte identifier;
|
||||
final int maxEntrySize;
|
||||
byte identifier;
|
||||
int maxEntrySize = 1024;
|
||||
int maxNumberOfChronicles = 128;
|
||||
private UdpReplicationConfig udpReplicationConfig = null;
|
||||
private TcpReplicationConfig tcpReplicationConfig = null;
|
||||
|
||||
ReplicatingClusterBuilder(byte identifier, final int maxEntrySize) {
|
||||
this.identifier = identifier;
|
||||
|
||||
|
||||
public int maxEntrySize() {
|
||||
return maxEntrySize;
|
||||
}
|
||||
|
||||
public ChannelProviderBuilder maxEntrySize(int maxEntrySize) {
|
||||
this.maxEntrySize = maxEntrySize;
|
||||
if (identifier <= 0) {
|
||||
throw new IllegalArgumentException("Identifier must be positive, identifier=" +
|
||||
identifier);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ChannelProviderBuilder replicators(byte identifier, Config... configs) {
|
||||
this.identifier = identifier;
|
||||
|
||||
|
||||
for (Config config : configs) {
|
||||
|
||||
if (config instanceof TcpReplicationConfig) {
|
||||
this.tcpReplicationConfig = (TcpReplicationConfig) config;
|
||||
} else if (config instanceof UdpReplicationConfig) {
|
||||
this.udpReplicationConfig = (UdpReplicationConfig) config;
|
||||
} else
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
public ReplicatingClusterBuilder udpReplication(UdpReplicationConfig replicationConfig) {
|
||||
this.udpReplicationConfig = replicationConfig;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReplicatingClusterBuilder tcpReplication(TcpReplicationConfig replicationConfig) {
|
||||
this.tcpReplicationConfig = replicationConfig;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReplicatingClusterBuilder maxNumberOfChronicles(int maxNumberOfChronicles) {
|
||||
public ChannelProviderBuilder maxNumberOfChronicles(int maxNumberOfChronicles) {
|
||||
this.maxNumberOfChronicles = maxNumberOfChronicles;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReplicatingCluster create() throws IOException {
|
||||
final ReplicatingCluster replicatingCluster = new ReplicatingCluster(this);
|
||||
public ChannelProvider create() throws IOException {
|
||||
final ChannelProvider replicatingCluster = new ChannelProvider(this);
|
||||
if (tcpReplicationConfig != null) {
|
||||
final TcpReplicator tcpReplicator = new TcpReplicator(
|
||||
replicatingCluster.asReplica,
|
||||
@@ -27,9 +27,12 @@ import net.openhft.chronicle.map.serialization.MetaProvider;
|
||||
import net.openhft.chronicle.map.threadlocal.Provider;
|
||||
import net.openhft.chronicle.map.threadlocal.ThreadLocalCopies;
|
||||
import net.openhft.lang.Maths;
|
||||
import net.openhft.lang.io.*;
|
||||
import net.openhft.lang.io.ByteBufferBytes;
|
||||
import net.openhft.lang.io.Bytes;
|
||||
import net.openhft.lang.io.BytesStore;
|
||||
import net.openhft.lang.io.DirectStore;
|
||||
import net.openhft.lang.io.serialization.*;
|
||||
import net.openhft.lang.io.serialization.impl.*;
|
||||
import net.openhft.lang.io.serialization.impl.VanillaBytesMarshallerFactory;
|
||||
import net.openhft.lang.model.Byteable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
@@ -44,8 +47,8 @@ import java.util.concurrent.TimeUnit;
|
||||
import static net.openhft.chronicle.map.Objects.builderEquals;
|
||||
|
||||
/**
|
||||
* {@code ChronicleMapBuilder} manages the whole set of {@link ChronicleMap} configurations, could
|
||||
* be used as a classic builder and/or factory. This means that in addition to the standard builder
|
||||
* {@code ChronicleMapBuilder} manages the whole set of {@link ChronicleMap} configurations, could be used as
|
||||
* a classic builder and/or factory. This means that in addition to the standard builder
|
||||
* usage pattern: <pre>{@code
|
||||
* ChronicleMap<Key, Value> map = ChronicleMapBuilder
|
||||
* .of(Key.class, Value.class)
|
||||
@@ -63,25 +66,22 @@ import static net.openhft.chronicle.map.Objects.builderEquals;
|
||||
*
|
||||
* <p>Use static {@link #of(Class, Class)} method to obtain a {@code ChronicleMapBuilder} instance.
|
||||
*
|
||||
* <p>{@code ChronicleMapBuilder} is mutable. Configuration methods mutate the builder and
|
||||
* return <i>the builder itself</i> back to support chaining pattern, rather than the builder copies
|
||||
* with the corresponding configuration changed. To make an independent configuration,
|
||||
* {@linkplain #clone} the builder.
|
||||
* <p>{@code ChronicleMapBuilder} is mutable. Configuration methods mutate the builder and return <i>the
|
||||
* builder itself</i> back to support chaining pattern, rather than the builder copies with the corresponding
|
||||
* configuration changed. To make an independent configuration, {@linkplain #clone} the builder.
|
||||
*
|
||||
* <p>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.
|
||||
* <p>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.
|
||||
*
|
||||
* <p>{@code ChronicleMap} ("ChronicleMaps, created by {@code ChronicleMapBuilder}") currently
|
||||
* doesn't support resizing. That is why you should <i>always</i> configure {@linkplain
|
||||
* #entries(long) number of entries} you are going to insert into the created map <i>at most</i>.
|
||||
* See {@link #entries(long)} method documentation for more information on this.
|
||||
* <p>{@code ChronicleMap} ("ChronicleMaps, created by {@code ChronicleMapBuilder}") currently doesn't support
|
||||
* resizing. That is why you should <i>always</i> configure {@linkplain #entries(long) number of entries} you
|
||||
* are going to insert into the created map <i>at most</i>. See {@link #entries(long)} method documentation
|
||||
* for more information on this.
|
||||
*
|
||||
* <p>{@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.
|
||||
* <p>{@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 <K> key type of the maps, produced by this builder
|
||||
* @param <V> value type of the maps, produced by this builder
|
||||
@@ -94,11 +94,12 @@ public class ChronicleMapBuilder<K, V> implements Cloneable,
|
||||
|
||||
public static final short UDP_REPLICATION_MODIFICATION_ITERATOR_ID = 128;
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ChronicleMapBuilder.class.getName());
|
||||
|
||||
SerializationBuilder<K> keyBuilder;
|
||||
SerializationBuilder<V> valueBuilder;
|
||||
Replicator firstReplicator;
|
||||
Map<Class<? extends Replicator>, Replicator> replicators = new HashMap<Class<? extends Replicator>, Replicator>();
|
||||
boolean forceReplicatedImpl = false;
|
||||
|
||||
private Map<Class<? extends Replicator>, Replicator> replicators = new HashMap<Class<? extends Replicator>, Replicator>();
|
||||
|
||||
// used when configuring the number of segments.
|
||||
private int minSegments = -1;
|
||||
private int actualSegments = -1;
|
||||
@@ -126,6 +127,7 @@ public class ChronicleMapBuilder<K, V> implements Cloneable,
|
||||
MapEventListeners.nop();
|
||||
private V defaultValue = null;
|
||||
private DefaultValueProvider<K, V> defaultValueProvider = null;
|
||||
private byte identifier = -1;
|
||||
|
||||
ChronicleMapBuilder(Class<K> keyClass, Class<V> valueClass) {
|
||||
keyBuilder = new SerializationBuilder<K>(keyClass, SerializationBuilder.Role.KEY);
|
||||
@@ -156,6 +158,7 @@ public class ChronicleMapBuilder<K, V> implements Cloneable,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ChronicleMapBuilder<K, V> minSegments(int minSegments) {
|
||||
this.minSegments = minSegments;
|
||||
@@ -185,9 +188,9 @@ public class ChronicleMapBuilder<K, V> implements Cloneable,
|
||||
* .keySize(10)
|
||||
* // shouldn't specify valueSize(), because it is statically known
|
||||
* .create();}</pre>
|
||||
* (Note that 10 is chosen as key size in bytes despite strings in Java are UTF-16 encoded
|
||||
* (and each character takes 2 bytes on-heap), because default off-heap {@link String} encoding
|
||||
* is UTF-8 in {@code ChronicleMap}.)
|
||||
* (Note that 10 is chosen as key size in bytes despite strings in Java are UTF-16 encoded (and each
|
||||
* character takes 2 bytes on-heap), because default off-heap {@link String} encoding is UTF-8 in {@code
|
||||
* ChronicleMap}.)
|
||||
*
|
||||
* @see #constantKeySizeBySample(Object)
|
||||
* @see #valueSize(int)
|
||||
@@ -224,17 +227,16 @@ public class ChronicleMapBuilder<K, V> implements Cloneable,
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the optimal number of bytes, taken by serialized form of values, put into maps,
|
||||
* created by this builder. If value size is always the same, call
|
||||
* {@link #constantValueSizeBySample(Object)} method instead of this one.
|
||||
* Configures the optimal number of bytes, taken by serialized form of values, put into maps, created by
|
||||
* this builder. If value size is always the same, call {@link #constantValueSizeBySample(Object)} method
|
||||
* instead of this one.
|
||||
*
|
||||
* <p>If value is a 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.
|
||||
* <p>If value is a 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.
|
||||
*
|
||||
* <p>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.
|
||||
* <p>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 {@code ChronicleMapBuilder} back
|
||||
@@ -249,15 +251,15 @@ public class ChronicleMapBuilder<K, V> implements Cloneable,
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the constant number of bytes, taken by serialized form of values, put into maps,
|
||||
* created by this builder. This is done by providing the {@code sampleValue}, all values should
|
||||
* take the same number of bytes in serialized form, as this sample object.
|
||||
* Configures the constant number of bytes, taken by serialized form of values, put into maps, created by
|
||||
* this builder. This is done by providing the {@code sampleValue}, all values should take the same number
|
||||
* of bytes in serialized form, as this sample object.
|
||||
*
|
||||
* <p>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.
|
||||
* <p>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.
|
||||
*
|
||||
* <p>If value size varies, method {@link #valueSize(int)} or {@link #entrySize(int)} should be
|
||||
* called instead of this one.
|
||||
* <p>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
|
||||
@@ -286,18 +288,18 @@ public class ChronicleMapBuilder<K, V> implements Cloneable,
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>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.
|
||||
* recommended always to configure {@linkplain #keySize(int) key size} and {@linkplain #valueSize(int)
|
||||
* value size}, if they couldn't be derived statically.
|
||||
*
|
||||
* <p>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}.
|
||||
* <p>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}.
|
||||
*
|
||||
* <p>Note that the actual entrySize will be aligned to 4 (default {@linkplain
|
||||
* #entryAndValueAlignment(Alignment) entry alignment}). I. e. if you set entry size to 30,
|
||||
* the actual entry size will be 32 (30 aligned to 4 bytes). If you don't want entry size
|
||||
* to be aligned, set {@code entryAndValueAlignment(Alignment.NO_ALIGNMENT)}.
|
||||
* #entryAndValueAlignment(Alignment) entry alignment}). I. e. if you set entry size to 30, the actual
|
||||
* entry size will be 32 (30 aligned to 4 bytes). If you don't want entry size to be aligned, set {@code
|
||||
* entryAndValueAlignment(Alignment.NO_ALIGNMENT)}.
|
||||
*
|
||||
* @see #entryAndValueAlignment(Alignment)
|
||||
* @see #entries(long)
|
||||
@@ -317,7 +319,7 @@ public class ChronicleMapBuilder<K, V> implements Cloneable,
|
||||
int keySize = keySize();
|
||||
size += keyBuilder.sizeMarshaller().sizeEncodingSize(keySize);
|
||||
size += keySize;
|
||||
if (replicatedImpl())
|
||||
if (useReplication())
|
||||
size += ReplicatedChronicleMap.ADDITIONAL_ENTRY_BYTES;
|
||||
int valueSize = valueSize();
|
||||
size += valueBuilder.sizeMarshaller().sizeEncodingSize(valueSize);
|
||||
@@ -339,16 +341,16 @@ public class ChronicleMapBuilder<K, V> implements Cloneable,
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures alignment strategy of address in memory of entries and independently of address
|
||||
* in memory of values within entries in ChronicleMaps, created by this builder.
|
||||
* Configures alignment strategy of address in memory of entries and independently of address in memory of
|
||||
* values within entries in ChronicleMaps, created by this builder.
|
||||
*
|
||||
* <p>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.
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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).
|
||||
* <p>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).
|
||||
*
|
||||
* <p>Default is {@link Alignment#OF_4_BYTES}.
|
||||
*
|
||||
@@ -406,7 +408,6 @@ public class ChronicleMapBuilder<K, V> implements Cloneable,
|
||||
return (int) Maths.nextPower2(Math.max((entries >> 30) + 1, minSegments()), 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronicleMapBuilder<K, V> lockTimeOut(long lockTimeOut, TimeUnit unit) {
|
||||
this.lockTimeOut = lockTimeOut;
|
||||
lockTimeOutUnit = unit;
|
||||
@@ -428,20 +429,20 @@ public class ChronicleMapBuilder<K, V> implements Cloneable,
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures if the maps created by this builder should return {@code null} instead of previous
|
||||
* mapped values on {@link ChronicleMap#put(Object, Object) ChornicleMap.put(key, value)} calls.
|
||||
* Configures if the maps created by this builder should return {@code null} instead of previous mapped
|
||||
* values on {@link ChronicleMap#put(Object, Object) ChornicleMap.put(key, value)} calls.
|
||||
*
|
||||
* <p>{@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.
|
||||
* <p>{@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.
|
||||
*
|
||||
* <p>By default, of cause, {@code ChronicleMap} conforms the general {@code Map} contract
|
||||
* and returns the previous mapped value on {@code put()} calls.
|
||||
* <p>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 instead return {@code null}
|
||||
* ChronicleMap.put()} to not return the value that was replaced but instead return
|
||||
* {@code null}
|
||||
* @return an instance of the map builder back
|
||||
* @see #removeReturnsNull(boolean)
|
||||
*/
|
||||
@@ -455,17 +456,17 @@ public class ChronicleMapBuilder<K, V> implements Cloneable,
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures if the maps created by this builder should return {@code null} instead of
|
||||
* the last mapped value on {@link ChronicleMap#remove(Object) ChronicleMap.remove(key)} calls.
|
||||
* Configures if the maps created by this builder should return {@code null} instead of the last mapped
|
||||
* value on {@link ChronicleMap#remove(Object) ChronicleMap.remove(key)} calls.
|
||||
*
|
||||
* <p>{@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.
|
||||
* <p>{@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.
|
||||
*
|
||||
* @param removeReturnsNull {@code true} if you want {@link ChronicleMap#remove(Object)
|
||||
* ChronicleMap.remove()} to not return the value of the removed entry
|
||||
* but instead return {@code null}
|
||||
* ChronicleMap.remove()} to not return the value of the removed entry but
|
||||
* instead return {@code null}
|
||||
* @return an instance of the map builder back
|
||||
* @see #putReturnsNull(boolean)
|
||||
*/
|
||||
@@ -496,6 +497,7 @@ public class ChronicleMapBuilder<K, V> implements Cloneable,
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
int metaDataBytes() {
|
||||
return metaDataBytes;
|
||||
}
|
||||
@@ -549,32 +551,23 @@ public class ChronicleMapBuilder<K, V> implements Cloneable,
|
||||
return toString().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronicleMapBuilder<K, V> addReplicator(Replicator replicator) {
|
||||
if (firstReplicator == null) {
|
||||
firstReplicator = replicator;
|
||||
replicators.put(replicator.getClass(), replicator);
|
||||
} else {
|
||||
if (replicator.identifier() != firstReplicator.identifier()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Identifiers of all replicators of the map should be the same");
|
||||
}
|
||||
if (replicators.containsKey(replicator.getClass())) {
|
||||
throw new IllegalArgumentException("Replicator of " + replicator.getClass() +
|
||||
" class has already to the map");
|
||||
}
|
||||
replicators.put(replicator.getClass(), replicator);
|
||||
public ChronicleMapBuilder<K, V> replicators(byte identifier, Replicator... replicators) {
|
||||
|
||||
this.identifier = identifier;
|
||||
this.replicators.clear();
|
||||
for (Replicator replicator : replicators) {
|
||||
this.replicators.put(replicator.getClass(), replicator);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronicleMapBuilder<K, V> setReplicators(Replicator... replicators) {
|
||||
firstReplicator = null;
|
||||
|
||||
public ChronicleMapBuilder<K, V> channel(ChannelProvider.ChronicleChannel chronicleChannel) {
|
||||
this.identifier = chronicleChannel.identifier();
|
||||
this.replicators.clear();
|
||||
for (Replicator replicator : replicators) {
|
||||
addReplicator(replicator);
|
||||
}
|
||||
replicators.put(chronicleChannel.getClass(), chronicleChannel);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -613,13 +606,6 @@ public class ChronicleMapBuilder<K, V> implements Cloneable,
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* For testing
|
||||
*/
|
||||
ChronicleMapBuilder<K, V> forceReplicatedImpl() {
|
||||
this.forceReplicatedImpl = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronicleMapBuilder<K, V> keyMarshaller(@NotNull BytesMarshaller<K> keyMarshaller) {
|
||||
@@ -662,19 +648,18 @@ public class ChronicleMapBuilder<K, V> implements Cloneable,
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the value to be put for each key queried in {@link ChronicleMap#get get()} and
|
||||
* {@link ChronicleMap#getUsing(Object, Object) getUsing()} methods, if the key is absent
|
||||
* in the map. Then this default value is returned from query method.
|
||||
* Specifies the value to be put for each key queried in {@link ChronicleMap#get get()} and {@link
|
||||
* ChronicleMap#getUsing(Object, Object) getUsing()} methods, if the key is absent in the map. Then this
|
||||
* default value is returned from query method.
|
||||
*
|
||||
* <p>Setting default value to {@code null} is interpreted as map shouldn't put any default
|
||||
* value for absent keys. This is by default.
|
||||
* <p>Setting default value to {@code null} is interpreted as map shouldn't put any default value for
|
||||
* absent keys. This is by default.
|
||||
*
|
||||
* <p>This configuration overrides any previous
|
||||
* {@link #defaultValueProvider(DefaultValueProvider)} configuration to this
|
||||
* {@code ChronicleMapBuilder}.
|
||||
* <p>This configuration overrides any previous {@link #defaultValueProvider(DefaultValueProvider)}
|
||||
* configuration to this {@code ChronicleMapBuilder}.
|
||||
*
|
||||
* @param defaultValue the default value to be put to the map for absent keys during
|
||||
* {@code get()} and {@code getUsing()} calls and returned from these calls
|
||||
* @param defaultValue the default value to be put to the map for absent keys during {@code get()} and
|
||||
* {@code getUsing()} calls and returned from these calls
|
||||
* @return this builder object back
|
||||
*/
|
||||
public ChronicleMapBuilder<K, V> defaultValue(V defaultValue) {
|
||||
@@ -684,13 +669,13 @@ public class ChronicleMapBuilder<K, V> implements Cloneable,
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the function to obtain a value for the key during {@link ChronicleMap#get get()}
|
||||
* and {@link ChronicleMap#getUsing(Object, Object) getUsing()} calls, if the key is absent
|
||||
* in the map. If the obtained value is non-null, it is put for the key in the map and then
|
||||
* returned from current {@code get()} or {@code getUsing()} call.
|
||||
* Specifies the function to obtain a value for the key during {@link ChronicleMap#get get()} and {@link
|
||||
* ChronicleMap#getUsing(Object, Object) getUsing()} calls, if the key is absent in the map. If the
|
||||
* obtained value is non-null, it is put for the key in the map and then returned from current {@code
|
||||
* get()} or {@code getUsing()} call.
|
||||
*
|
||||
* <p>This configuration overrides any previous {@link #defaultValue(Object)} configuration
|
||||
* to this {@code ChronicleMapBuilder}.
|
||||
* <p>This configuration overrides any previous {@link #defaultValue(Object)} configuration to this {@code
|
||||
* ChronicleMapBuilder}.
|
||||
*
|
||||
* @param defaultValueProvider the strategy to obtain a default value by the absent key
|
||||
* @return this builder object back
|
||||
@@ -778,7 +763,7 @@ public class ChronicleMapBuilder<K, V> implements Cloneable,
|
||||
|
||||
private VanillaChronicleMap<K, ?, ?, V, ?, ?> newMap() throws IOException {
|
||||
preMapConstruction();
|
||||
if (!replicatedImpl()) {
|
||||
if (!useReplication()) {
|
||||
return new VanillaChronicleMap<K, Object, MetaBytesInterop<K, Object>,
|
||||
V, Object, MetaBytesWriter<V, Object>>(this);
|
||||
} else {
|
||||
@@ -787,8 +772,8 @@ public class ChronicleMapBuilder<K, V> implements Cloneable,
|
||||
}
|
||||
}
|
||||
|
||||
private boolean replicatedImpl() {
|
||||
return firstReplicator != null || forceReplicatedImpl;
|
||||
private boolean useReplication() {
|
||||
return identifier != -1;
|
||||
}
|
||||
|
||||
private void preMapConstruction() {
|
||||
@@ -833,5 +818,9 @@ public class ChronicleMapBuilder<K, V> implements Cloneable,
|
||||
return (int) Math.min(Math.max(2L, entries() >> 10),
|
||||
VanillaChronicleMap.MAX_ENTRY_OVERSIZE_FACTOR);
|
||||
}
|
||||
|
||||
public byte identifier() {
|
||||
return identifier;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package net.openhft.chronicle.map;
|
||||
|
||||
/**
|
||||
* @author Rob Austin.
|
||||
*/
|
||||
public interface Config {
|
||||
}
|
||||
@@ -212,7 +212,7 @@ public class NodeDiscovery {
|
||||
return ChronicleMapBuilder.of(Integer.class,
|
||||
CharSequence.class)
|
||||
.entries(20000L)
|
||||
.addReplicator(tcp(identifier, tcpConfig)).create();
|
||||
.replicators(identifier, tcp(tcpConfig)).create();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -55,14 +55,11 @@ public interface Replica extends Closeable {
|
||||
ModificationNotifier modificationNotifier);
|
||||
|
||||
/**
|
||||
* Returns the timestamp of the last change from the specified remote node, already replicated
|
||||
* to this Replica.
|
||||
* <p/>
|
||||
* <p>Used in conjunction with replication, to back fill data from a remote node. This node
|
||||
* Returns the timestamp of the last change from the specified remote node, already replicated to this
|
||||
* Replica. <p/> <p>Used in conjunction with replication, to back fill data from a remote node. This node
|
||||
* may have missed updates while it was not been running or connected via TCP.
|
||||
*
|
||||
* @param remoteIdentifier the identifier of the remote node to check last replicated update
|
||||
* time from
|
||||
* @param remoteIdentifier the identifier of the remote node to check last replicated update time from
|
||||
* @return a timestamp of the last modification to an entry, or 0 if there are no entries.
|
||||
* @see #identifier()
|
||||
*/
|
||||
@@ -102,7 +99,7 @@ public interface Replica extends Closeable {
|
||||
* A non-blocking call that provides the entry that has changed to {@code callback.onEntry()}.
|
||||
*
|
||||
* @param callback a callback which will be called when a new entry becomes available.
|
||||
* @param chronicleId only assigned when clustering
|
||||
* @param chronicleId only assigned when using chronicle channels
|
||||
* @return {@code true} if the entry was accepted by the {@code callback.onEntry()} method, {@code
|
||||
* false} if the entry was not accepted or was not available
|
||||
*/
|
||||
@@ -111,10 +108,8 @@ public interface Replica extends Closeable {
|
||||
/**
|
||||
* Dirties all entries with a modification time equal to {@code fromTimeStamp} or newer. It means all
|
||||
* these entries will be considered as "new" by this ModificationIterator and iterated once again no
|
||||
* matter if they have already been.
|
||||
* <p/>
|
||||
* <p>This functionality is used to publish recently modified entries to a new remote node as it
|
||||
* connects.
|
||||
* matter if they have already been. <p/> <p>This functionality is used to publish recently modified
|
||||
* entries to a new remote node as it connects.
|
||||
*
|
||||
* @param fromTimeStamp the timestamp from which all entries should be dirty
|
||||
*/
|
||||
@@ -133,7 +128,7 @@ public interface Replica extends Closeable {
|
||||
* @param entry the byte location of the entry to be stored
|
||||
* @param destination a buffer the entry will be written to, the segment may reject this operation and
|
||||
* add zeroBytes, if the identifier in the entry did not match the maps local
|
||||
* @param chronicleId used in cluster into identify the canonical map or queue
|
||||
* @param chronicleId is the channel id used to identify the canonical map or queue
|
||||
*/
|
||||
void writeExternalEntry(@NotNull Bytes entry, @NotNull Bytes destination, int chronicleId);
|
||||
|
||||
@@ -180,20 +175,20 @@ public interface Replica extends Closeable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implemented typically by a replicator, This interface provides the event, which will get
|
||||
* called whenever a put() or remove() has occurred to the map
|
||||
* Implemented typically by a replicator, This interface provides the event, which will get called
|
||||
* whenever a put() or remove() has occurred to the map
|
||||
*/
|
||||
abstract class EntryCallback {
|
||||
|
||||
/**
|
||||
* Called whenever a put() or remove() has occurred to a replicating map.
|
||||
*
|
||||
* @param entry the entry you will receive, this does not have to be locked,
|
||||
* as locking is already provided from the caller.
|
||||
* @param entry the entry you will receive, this does not have to be locked, as locking is
|
||||
* already provided from the caller.
|
||||
* @param chronicleId only assigned when clustering
|
||||
* @return {@code false} if this entry should be ignored because the identifier
|
||||
* of the source node is not from one of our changes, WARNING even though we check
|
||||
* the identifier in the ModificationIterator the entry may have been updated.
|
||||
* @return {@code false} if this entry should be ignored because the identifier of the source node is
|
||||
* not from one of our changes, WARNING even though we check the identifier in the
|
||||
* ModificationIterator the entry may have been updated.
|
||||
*/
|
||||
public abstract boolean onEntry(final Bytes entry, final int chronicleId);
|
||||
|
||||
|
||||
@@ -18,16 +18,16 @@ package net.openhft.chronicle.map;
|
||||
|
||||
|
||||
import net.openhft.chronicle.TimeProvider;
|
||||
import net.openhft.chronicle.map.serialization.BytesReader;
|
||||
import net.openhft.chronicle.map.serialization.MetaBytesInterop;
|
||||
import net.openhft.chronicle.map.serialization.MetaBytesWriter;
|
||||
import net.openhft.chronicle.map.threadlocal.ThreadLocalCopies;
|
||||
import net.openhft.lang.Maths;
|
||||
import net.openhft.lang.collection.ATSDirectBitSet;
|
||||
import net.openhft.lang.io.Bytes;
|
||||
import net.openhft.lang.io.MultiStoreBytes;
|
||||
import net.openhft.lang.io.NativeBytes;
|
||||
import net.openhft.chronicle.map.serialization.BytesReader;
|
||||
import net.openhft.chronicle.map.serialization.MetaBytesInterop;
|
||||
import net.openhft.chronicle.map.serialization.MetaBytesWriter;
|
||||
import net.openhft.lang.model.Byteable;
|
||||
import net.openhft.chronicle.map.threadlocal.ThreadLocalCopies;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -100,8 +100,13 @@ class ReplicatedChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
throws IOException {
|
||||
super(builder);
|
||||
this.timeProvider = builder.timeProvider();
|
||||
Replicator firstReplicator = builder.firstReplicator;
|
||||
this.localIdentifier = firstReplicator != null ? firstReplicator.identifier() : 1;
|
||||
|
||||
this.localIdentifier = builder.identifier();
|
||||
|
||||
if (localIdentifier==-1){
|
||||
throw new IllegalStateException("localIdentifier should not be -1");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private int assignedModIterBitSetSizeInBytes() {
|
||||
@@ -882,15 +887,15 @@ class ReplicatedChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts entry. If {@code value} implements {@link Byteable} interface and
|
||||
* {@code usingValue} is {@code true}, the value is backed with the bytes of this entry.
|
||||
* Puts entry. If {@code value} implements {@link Byteable} interface and {@code usingValue} is {@code
|
||||
* true}, the value is backed with the bytes of this entry.
|
||||
*
|
||||
* @param hash2 a hash of the {@code keyBytes}. Caller was searching for the key in the
|
||||
* {@code searchedHashLookup} using this hash.
|
||||
* @param value the value to put
|
||||
* @param usingValue {@code true} if the value should be backed with the bytes of the entry,
|
||||
* if it implements {@link Byteable} interface,
|
||||
* {@code false} if it should put itself
|
||||
* if it implements {@link Byteable} interface, {@code false} if it should
|
||||
* put itself
|
||||
* @param identifier the identifier of the outer CHM node
|
||||
* @param timestamp the timestamp when the entry was put <s>(this could be later if it was a
|
||||
* remote put)</s> this method is called only from usual put or acquire
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @see Replicators
|
||||
* @see ChronicleMapBuilder#addReplicator(Replicator)
|
||||
* @see ChronicleMapBuilder#replicator(byte, Replicator)
|
||||
*/
|
||||
public abstract class Replicator {
|
||||
|
||||
@@ -31,14 +31,6 @@ public abstract class Replicator {
|
||||
protected Replicator() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this node identifier within the replication topology.
|
||||
*
|
||||
* @return the unique identifier among nodes
|
||||
* @see Replica#identifier()
|
||||
*/
|
||||
public abstract byte identifier();
|
||||
|
||||
/**
|
||||
* Applies the replicator to the map instance and returns a Closeable token to manage resources,
|
||||
* associated with the replication.
|
||||
|
||||
@@ -25,13 +25,8 @@ public final class Replicators {
|
||||
private Replicators() {
|
||||
}
|
||||
|
||||
public static Replicator tcp(final byte identifier,
|
||||
final TcpReplicationConfig replicationConfig) {
|
||||
public static Replicator tcp(final TcpReplicationConfig replicationConfig) {
|
||||
return new Replicator() {
|
||||
@Override
|
||||
public byte identifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Closeable applyTo(ChronicleMapBuilder builder,
|
||||
@@ -43,13 +38,9 @@ public final class Replicators {
|
||||
};
|
||||
}
|
||||
|
||||
public static Replicator udp(final byte identifier,
|
||||
final UdpReplicationConfig replicationConfig) {
|
||||
public static Replicator udp(
|
||||
final UdpReplicationConfig replicationConfig) {
|
||||
return new Replicator() {
|
||||
@Override
|
||||
public byte identifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Closeable applyTo(ChronicleMapBuilder builder,
|
||||
|
||||
@@ -29,7 +29,7 @@ import static java.util.Collections.unmodifiableSet;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
|
||||
public class TcpReplicationConfig {
|
||||
public class TcpReplicationConfig implements Config {
|
||||
|
||||
private static final int DEFAULT_PACKET_SIZE = 1024 * 8;
|
||||
private static final long DEFAULT_HEART_BEAT_INTERVAL = 20;
|
||||
|
||||
@@ -23,7 +23,7 @@ import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
|
||||
|
||||
public abstract class UdpReplicationConfig {
|
||||
public abstract class UdpReplicationConfig implements Config {
|
||||
|
||||
/**
|
||||
* Package-private constructor forbids subclassing from outside of the package
|
||||
@@ -37,7 +37,6 @@ public abstract class UdpReplicationConfig {
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
|
||||
|
||||
return create(address, port, null, ThrottlingConfig.noThrottling());
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ public class ChronicleSetBuilder<E>
|
||||
ChronicleSetBuilder(Class<E> keyClass) {
|
||||
chronicleMapBuilder = ChronicleMapBuilder.of(keyClass, DummyValue.class)
|
||||
.entryAndValueAlignment(Alignment.NO_ALIGNMENT)
|
||||
.valueMarshallerAndFactory(DummyValueMarshaller.INSTANCE, NullObjectFactory.of());
|
||||
.valueMarshallerAndFactory(DummyValueMarshaller.INSTANCE,
|
||||
NullObjectFactory.<DummyValue>of());
|
||||
}
|
||||
|
||||
public static <K> ChronicleSetBuilder<K> of(Class<K> keyClass) {
|
||||
@@ -85,7 +86,8 @@ public class ChronicleSetBuilder<E>
|
||||
* .entries(50000)
|
||||
* .keySize(10)
|
||||
* .create();}</pre>
|
||||
* (Note that 10 is chosen as key size in bytes despite strings in Java are UTF-16 encoded
|
||||
*
|
||||
* <p>(Note that 10 is chosen as key size in bytes despite strings in Java are UTF-16 encoded
|
||||
* (and each character takes 2 bytes on-heap), because default off-heap {@link String} encoding
|
||||
* is UTF-8 in {@code ChronicleSet}.)
|
||||
*
|
||||
@@ -121,9 +123,9 @@ public class ChronicleSetBuilder<E>
|
||||
* strongly recommended always to configure {@linkplain #keySize(int) key size},
|
||||
* if they couldn't be derived statically.
|
||||
*
|
||||
* <p>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 a few bytes required by implementations.
|
||||
* <p>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 a few bytes required by implementations.
|
||||
*/
|
||||
@Override
|
||||
public ChronicleSetBuilder<E> entrySize(int entrySize) {
|
||||
@@ -161,6 +163,12 @@ public class ChronicleSetBuilder<E>
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronicleSetBuilder<E> replicators(byte identifier, Replicator... replicators) {
|
||||
chronicleMapBuilder.replicators(identifier, replicators);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return " ChronicleSetBuilder{" +
|
||||
@@ -181,15 +189,11 @@ public class ChronicleSetBuilder<E>
|
||||
return toString().hashCode();
|
||||
}
|
||||
|
||||
public ChronicleSetBuilder<E> addReplicator(Replicator replicator) {
|
||||
chronicleMapBuilder.addReplicator(replicator);
|
||||
public ChronicleSetBuilder<E> replicators(byte identifier, Replicator replicator) {
|
||||
chronicleMapBuilder.replicators(identifier, replicator);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ChronicleSetBuilder<E> setReplicators(Replicator... replicators) {
|
||||
chronicleMapBuilder.setReplicators(replicators);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronicleSetBuilder<E> timeProvider(TimeProvider timeProvider) {
|
||||
|
||||
@@ -73,7 +73,7 @@ public class Builder {
|
||||
.heartBeatInterval(1L, SECONDS);
|
||||
return ChronicleMapBuilder.of(kClass, vClass)
|
||||
.entries(20000L)
|
||||
.addReplicator(tcp(identifier, tcpConfig));
|
||||
.replicators(identifier, tcp( tcpConfig));
|
||||
}
|
||||
|
||||
|
||||
|
||||
+15
-11
@@ -17,7 +17,10 @@
|
||||
package net.openhft.chronicle.map;
|
||||
|
||||
|
||||
import org.junit.*;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
@@ -32,7 +35,7 @@ import static org.junit.Assert.assertTrue;
|
||||
*
|
||||
* @author Rob Austin.
|
||||
*/
|
||||
public class ClusterReplicationTest {
|
||||
public class ChannelReplicationTest {
|
||||
|
||||
private ChronicleMap<Integer, CharSequence> map1a;
|
||||
private ChronicleMap<Integer, CharSequence> map2a;
|
||||
@@ -40,8 +43,8 @@ public class ClusterReplicationTest {
|
||||
private ChronicleMap<Integer, CharSequence> map1b;
|
||||
private ChronicleMap<Integer, CharSequence> map2b;
|
||||
|
||||
private ReplicatingCluster clusterB;
|
||||
private ReplicatingCluster clusterA;
|
||||
private ChannelProvider channelProviderA;
|
||||
private ChannelProvider channelProviderB;
|
||||
|
||||
|
||||
@Before
|
||||
@@ -52,12 +55,13 @@ public class ClusterReplicationTest {
|
||||
.of(8086, new InetSocketAddress("localhost", 8087))
|
||||
.heartBeatInterval(1, SECONDS);
|
||||
|
||||
clusterA = new ReplicatingClusterBuilder((byte) 1, 1024).tcpReplication(tcpConfig)
|
||||
channelProviderA = new ChannelProviderBuilder()
|
||||
.replicators((byte) 1, tcpConfig)
|
||||
.create();
|
||||
|
||||
map1a = ChronicleMapBuilder.of(Integer.class, CharSequence.class)
|
||||
.entries(1000)
|
||||
.addReplicator(clusterA.channelReplicator((short) 1))
|
||||
.channel(channelProviderA.createChannel((short) 1))
|
||||
.create(getPersistenceFile());
|
||||
}
|
||||
|
||||
@@ -65,12 +69,12 @@ public class ClusterReplicationTest {
|
||||
TcpReplicationConfig tcpConfig =
|
||||
TcpReplicationConfig.of(8087).heartBeatInterval(1, SECONDS);
|
||||
|
||||
clusterB = new ReplicatingClusterBuilder((byte) 2, 1024).tcpReplication(tcpConfig)
|
||||
channelProviderB = new ChannelProviderBuilder().replicators((byte) 2, tcpConfig)
|
||||
.create();
|
||||
|
||||
map1b = ChronicleMapBuilder.of(Integer.class, CharSequence.class)
|
||||
.entries(1000)
|
||||
.addReplicator(clusterB.channelReplicator((short) 1))
|
||||
.channel(channelProviderB.createChannel((short) 1))
|
||||
.create(getPersistenceFile());
|
||||
}
|
||||
}
|
||||
@@ -78,7 +82,7 @@ public class ClusterReplicationTest {
|
||||
@After
|
||||
public void tearDown() throws InterruptedException {
|
||||
|
||||
for (final Closeable closeable : new Closeable[]{clusterA, clusterB}) {
|
||||
for (final Closeable closeable : new Closeable[]{channelProviderA, channelProviderB}) {
|
||||
try {
|
||||
closeable.close();
|
||||
} catch (IOException e) {
|
||||
@@ -93,13 +97,13 @@ public class ClusterReplicationTest {
|
||||
|
||||
map2b = ChronicleMapBuilder.of(Integer.class, CharSequence.class)
|
||||
.entries(1000)
|
||||
.addReplicator(clusterB.channelReplicator((short) 2))
|
||||
.channel(channelProviderB.createChannel((short) 2))
|
||||
.create(getPersistenceFile());
|
||||
|
||||
|
||||
map2a = ChronicleMapBuilder.of(Integer.class, CharSequence.class)
|
||||
.entries(1000)
|
||||
.addReplicator(clusterA.channelReplicator((short) 2))
|
||||
.channel(channelProviderA.createChannel((short) 2))
|
||||
.create(getPersistenceFile());
|
||||
|
||||
map2a.put(1, "EXAMPLE-2");
|
||||
+18
-18
@@ -17,7 +17,10 @@
|
||||
package net.openhft.chronicle.map;
|
||||
|
||||
|
||||
import org.junit.*;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
@@ -32,7 +35,7 @@ import static org.junit.Assert.assertTrue;
|
||||
*
|
||||
* @author Rob Austin.
|
||||
*/
|
||||
public class PostClusterMapCreationTest {
|
||||
public class PostChannelCreationTest {
|
||||
|
||||
private ChronicleMap<Integer, CharSequence> map1a;
|
||||
private ChronicleMap<Integer, CharSequence> map2a;
|
||||
@@ -40,11 +43,8 @@ public class PostClusterMapCreationTest {
|
||||
private ChronicleMap<Integer, CharSequence> map1b;
|
||||
private ChronicleMap<Integer, CharSequence> map2b;
|
||||
|
||||
private ReplicatingCluster clusterB;
|
||||
private ReplicatingCluster clusterA;
|
||||
|
||||
private ReplicatingClusterBuilder replicatingClusterBuilder1;
|
||||
|
||||
private ChannelProvider channelProviderA;
|
||||
private ChannelProvider channelProviderB;
|
||||
|
||||
public static File getPersistenceFile() {
|
||||
String TMP = System.getProperty("java.io.tmpdir");
|
||||
@@ -59,43 +59,43 @@ public class PostClusterMapCreationTest {
|
||||
public void setup() throws IOException {
|
||||
|
||||
{
|
||||
final TcpReplicationConfig tcpReplicationConfig = TcpReplicationConfig
|
||||
final TcpReplicationConfig tcpConfig = TcpReplicationConfig
|
||||
.of(8086, new InetSocketAddress("localhost", 8087))
|
||||
.heartBeatInterval(1, SECONDS);
|
||||
|
||||
clusterA = new ReplicatingClusterBuilder((byte) 1, 1024)
|
||||
.tcpReplication(tcpReplicationConfig).create();
|
||||
channelProviderA = new ChannelProviderBuilder()
|
||||
.replicators((byte) 1, tcpConfig).create();
|
||||
|
||||
// this is how you add maps after the custer is created
|
||||
map1a = ChronicleMapBuilder.of(Integer.class, CharSequence.class)
|
||||
.entries(1000)
|
||||
.addReplicator(clusterA.channelReplicator((short) 1))
|
||||
.channel(channelProviderA.createChannel((short) 1))
|
||||
.create(getPersistenceFile());
|
||||
|
||||
map2a = ChronicleMapBuilder.of(Integer.class, CharSequence.class)
|
||||
.entries(1000)
|
||||
.addReplicator(clusterA.channelReplicator((short) 2))
|
||||
.channel(channelProviderA.createChannel((short) 2))
|
||||
.create(getPersistenceFile());
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
final TcpReplicationConfig tcpReplicationConfig = TcpReplicationConfig
|
||||
final TcpReplicationConfig tcpConfig = TcpReplicationConfig
|
||||
.of(8087, new InetSocketAddress("localhost", 8086))
|
||||
.heartBeatInterval(1, SECONDS);
|
||||
|
||||
clusterB = new ReplicatingClusterBuilder((byte) 2, 1024)
|
||||
.tcpReplication(tcpReplicationConfig).create();
|
||||
channelProviderB = new ChannelProviderBuilder()
|
||||
.replicators((byte) 2, tcpConfig).create();
|
||||
|
||||
// this is how you add maps after the custer is created
|
||||
map1b = ChronicleMapBuilder.of(Integer.class, CharSequence.class)
|
||||
.entries(1000)
|
||||
.addReplicator(clusterB.channelReplicator((short) 1))
|
||||
.channel(channelProviderB.createChannel((short) 1))
|
||||
.create(getPersistenceFile());
|
||||
|
||||
map2b = ChronicleMapBuilder.of(Integer.class, CharSequence.class)
|
||||
.entries(1000)
|
||||
.addReplicator(clusterB.channelReplicator((short) 2))
|
||||
.channel(channelProviderB.createChannel((short) 2))
|
||||
.create(getPersistenceFile());
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ public class PostClusterMapCreationTest {
|
||||
@After
|
||||
public void tearDown() throws InterruptedException {
|
||||
|
||||
for (final Closeable closeable : new Closeable[]{clusterA, clusterB}) {
|
||||
for (final Closeable closeable : new Closeable[]{channelProviderA, channelProviderB}) {
|
||||
try {
|
||||
closeable.close();
|
||||
} catch (IOException e) {
|
||||
@@ -18,8 +18,6 @@ package net.openhft.chronicle.map;
|
||||
|
||||
import net.openhft.chronicle.map.jrs166.JSR166TestCase;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -44,48 +42,51 @@ public class ReplicatedChronicleMapTest extends JSR166TestCase {
|
||||
}
|
||||
|
||||
ChronicleMap<Integer, CharSequence> newShmIntString(int size) throws IOException {
|
||||
ChronicleMapBuilder.of(Integer.class, CharSequence.class)
|
||||
.entries(size).replicators((byte) 1);
|
||||
return ChronicleMapBuilder.of(Integer.class, CharSequence.class)
|
||||
.entries(size)
|
||||
.forceReplicatedImpl()
|
||||
.create(getPersistenceFile());
|
||||
|
||||
}
|
||||
|
||||
ChronicleMap<ArrayList, CharSequence> newShmListBoolean(int size) throws IOException {
|
||||
ChronicleMapBuilder.of(ArrayList.class, CharSequence.class)
|
||||
.entries(size).replicators((byte) 1);
|
||||
return ChronicleMapBuilder.of(ArrayList.class, CharSequence.class)
|
||||
.entries(size)
|
||||
.forceReplicatedImpl()
|
||||
.create(getPersistenceFile());
|
||||
|
||||
}
|
||||
|
||||
|
||||
ChronicleMap<ArrayList, CharSequence> newShmListBoolean() throws IOException {
|
||||
ChronicleMapBuilder.of(ArrayList.class, CharSequence.class).replicators((byte) 1);
|
||||
return ChronicleMapBuilder.of(ArrayList.class, CharSequence.class)
|
||||
.forceReplicatedImpl()
|
||||
.create(getPersistenceFile());
|
||||
|
||||
}
|
||||
|
||||
ChronicleMap<CharSequence, CharSequence> newShmStringString(int size) throws IOException {
|
||||
ChronicleMapBuilder.of(CharSequence.class, CharSequence.class)
|
||||
.entries(size).replicators((byte) 1);
|
||||
return ChronicleMapBuilder.of(CharSequence.class, CharSequence.class)
|
||||
.entries(size)
|
||||
.forceReplicatedImpl()
|
||||
.create(getPersistenceFile());
|
||||
|
||||
}
|
||||
|
||||
|
||||
ChronicleMap<Integer, CharSequence> newShmIntString() throws IOException {
|
||||
ChronicleMapBuilder.of(Integer.class, CharSequence.class).replicators((byte) 1);
|
||||
return ChronicleMapBuilder.of(Integer.class, CharSequence.class)
|
||||
.forceReplicatedImpl()
|
||||
.create(getPersistenceFile());
|
||||
|
||||
}
|
||||
|
||||
ChronicleMap<BI, Boolean> newShmBiBoolean() throws IOException {
|
||||
return ChronicleMapBuilder.of(BI.class, Boolean.class)
|
||||
.forceReplicatedImpl().create(getPersistenceFile());
|
||||
ChronicleMapBuilder.of(BI.class, Boolean.class).replicators((byte) 1);
|
||||
return ChronicleMapBuilder.of(BI.class, Boolean.class).create(getPersistenceFile());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -41,9 +41,8 @@ public class SingleMapClusterTest {
|
||||
|
||||
private ChronicleMap<Integer, CharSequence> map1b;
|
||||
|
||||
private ReplicatingCluster clusterB;
|
||||
private ReplicatingCluster clusterA;
|
||||
|
||||
private ChannelProvider channelProviderA;
|
||||
private ChannelProvider channelProviderB;
|
||||
|
||||
public static File getPersistenceFile() {
|
||||
String TMP = System.getProperty("java.io.tmpdir");
|
||||
@@ -61,12 +60,12 @@ public class SingleMapClusterTest {
|
||||
.of(8086, new InetSocketAddress("localhost", 8087))
|
||||
.heartBeatInterval(1, SECONDS);
|
||||
|
||||
clusterA = new ReplicatingClusterBuilder((byte) 1, 1024)
|
||||
.tcpReplication(tcpReplicationConfig).create();
|
||||
channelProviderA = new ChannelProviderBuilder()
|
||||
.replicators((byte) 1, tcpReplicationConfig).create();
|
||||
// this is how you add maps after the custer is created
|
||||
map1a = ChronicleMapBuilder.of(Integer.class, CharSequence.class)
|
||||
.entries(1000)
|
||||
.addReplicator(clusterA.channelReplicator((short) 1))
|
||||
.channel(channelProviderA.createChannel((short) 1))
|
||||
.create(getPersistenceFile());
|
||||
}
|
||||
|
||||
@@ -76,11 +75,12 @@ public class SingleMapClusterTest {
|
||||
.of(8087, new InetSocketAddress("localhost", 8086))
|
||||
.heartBeatInterval(1, SECONDS);
|
||||
|
||||
clusterB = new ReplicatingClusterBuilder((byte) 2, 1024)
|
||||
.tcpReplication(tcpReplicationConfig).create();
|
||||
channelProviderB = new ChannelProviderBuilder()
|
||||
.replicators((byte) 2, tcpReplicationConfig).create();
|
||||
|
||||
// this is how you add maps after the custer is created
|
||||
map1b = ChronicleMapBuilder.of(Integer.class, CharSequence.class)
|
||||
.addReplicator(clusterB.channelReplicator((short) 1))
|
||||
.channel(channelProviderB.createChannel((short) 1))
|
||||
.entries(1000)
|
||||
.create(getPersistenceFile());
|
||||
}
|
||||
@@ -89,7 +89,7 @@ public class SingleMapClusterTest {
|
||||
@After
|
||||
public void tearDown() throws InterruptedException {
|
||||
|
||||
for (final Closeable closeable : new Closeable[]{clusterA, clusterB}) {
|
||||
for (final Closeable closeable : new Closeable[]{channelProviderA, channelProviderB}) {
|
||||
try {
|
||||
closeable.close();
|
||||
} catch (IOException e) {
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ public class TCPSocketReplicationTest3wayPutReturnsNull {
|
||||
|
||||
.entries(1000)
|
||||
.putReturnsNull(true)
|
||||
.addReplicator(Replicators.tcp(identifier, tcpConfig))
|
||||
.replicators(identifier, Replicators.tcp(tcpConfig))
|
||||
.create(Builder.getPersistenceFile());
|
||||
}
|
||||
|
||||
|
||||
@@ -48,9 +48,10 @@ public class TimeBasedReplicationTests extends JSR166TestCase {
|
||||
|
||||
final TimeProvider timeProvider = Mockito.mock(TimeProvider.class);
|
||||
|
||||
ChronicleMapBuilder.of(CharSequence.class, CharSequence.class)
|
||||
.entries(10).replicators((byte) 1);
|
||||
ChronicleMap map = ChronicleMapBuilder.of(CharSequence.class, CharSequence.class)
|
||||
.entries(10)
|
||||
.forceReplicatedImpl()
|
||||
.replicators((byte) 1)
|
||||
.timeProvider(timeProvider)
|
||||
.create(getPersistenceFile());
|
||||
|
||||
@@ -78,10 +79,10 @@ public class TimeBasedReplicationTests extends JSR166TestCase {
|
||||
public void testIgnoreALatePutIfAbsent() throws IOException {
|
||||
|
||||
final TimeProvider timeProvider = Mockito.mock(TimeProvider.class);
|
||||
ChronicleMapBuilder.of(CharSequence.class, CharSequence.class)
|
||||
.entries(10).replicators((byte) 1);
|
||||
ChronicleMap map = ChronicleMapBuilder.of(CharSequence.class, CharSequence.class)
|
||||
.entries(10)
|
||||
.forceReplicatedImpl()
|
||||
.entries(10)
|
||||
.replicators((byte) 1)
|
||||
.timeProvider(timeProvider)
|
||||
.create(getPersistenceFile());
|
||||
|
||||
@@ -110,10 +111,10 @@ public class TimeBasedReplicationTests extends JSR166TestCase {
|
||||
public void testIgnoreALateReplace() throws IOException {
|
||||
|
||||
final TimeProvider timeProvider = Mockito.mock(TimeProvider.class);
|
||||
ChronicleMapBuilder.of(CharSequence.class, CharSequence.class)
|
||||
.entries(10).replicators((byte) 1);
|
||||
ChronicleMap map = ChronicleMapBuilder.of(CharSequence.class, CharSequence.class)
|
||||
.entries(10)
|
||||
.forceReplicatedImpl()
|
||||
.entries(10)
|
||||
.replicators((byte) 1)
|
||||
.timeProvider(timeProvider)
|
||||
.create(getPersistenceFile());
|
||||
|
||||
@@ -145,10 +146,10 @@ public class TimeBasedReplicationTests extends JSR166TestCase {
|
||||
public void testIgnoreALateReplaceWithValue() throws IOException {
|
||||
|
||||
final TimeProvider timeProvider = Mockito.mock(TimeProvider.class);
|
||||
ChronicleMapBuilder.of(CharSequence.class, CharSequence.class)
|
||||
.entries(10).replicators((byte) 1);
|
||||
ChronicleMap map = ChronicleMapBuilder.of(CharSequence.class, CharSequence.class)
|
||||
.entries(10)
|
||||
.forceReplicatedImpl()
|
||||
.entries(10)
|
||||
.replicators((byte) 1)
|
||||
.timeProvider(timeProvider)
|
||||
.create(getPersistenceFile());
|
||||
|
||||
@@ -177,9 +178,9 @@ public class TimeBasedReplicationTests extends JSR166TestCase {
|
||||
public void testIgnoreALateRemoveWithValue() throws IOException {
|
||||
|
||||
final TimeProvider timeProvider = Mockito.mock(TimeProvider.class);
|
||||
ChronicleMapBuilder.of(CharSequence.class, CharSequence.class).replicators((byte) 1);
|
||||
ChronicleMap map = ChronicleMapBuilder.of(CharSequence.class, CharSequence.class)
|
||||
|
||||
.forceReplicatedImpl()
|
||||
.replicators((byte) 1)
|
||||
.timeProvider(timeProvider)
|
||||
.create(getPersistenceFile());
|
||||
|
||||
@@ -207,9 +208,9 @@ public class TimeBasedReplicationTests extends JSR166TestCase {
|
||||
public void testIgnoreALateRemove() throws IOException {
|
||||
|
||||
final TimeProvider timeProvider = Mockito.mock(TimeProvider.class);
|
||||
ChronicleMapBuilder.of(CharSequence.class, CharSequence.class).replicators((byte) 1);
|
||||
ChronicleMap map = ChronicleMapBuilder.of(CharSequence.class, CharSequence.class)
|
||||
|
||||
.forceReplicatedImpl()
|
||||
.replicators((byte) 1)
|
||||
.timeProvider(timeProvider)
|
||||
.create(getPersistenceFile());
|
||||
|
||||
@@ -237,10 +238,9 @@ public class TimeBasedReplicationTests extends JSR166TestCase {
|
||||
public void testIgnoreWithRemoteRemove() throws IOException {
|
||||
|
||||
final TimeProvider timeProvider = Mockito.mock(TimeProvider.class);
|
||||
ChronicleMapBuilder.of(CharSequence.class, CharSequence.class).replicators((byte) 1);
|
||||
ReplicatedChronicleMap map = (ReplicatedChronicleMap) ChronicleMapBuilder.of(CharSequence.class, CharSequence.class)
|
||||
|
||||
.forceReplicatedImpl()
|
||||
.entries(10)
|
||||
.replicators((byte) 1)
|
||||
.timeProvider(timeProvider)
|
||||
.create(getPersistenceFile());
|
||||
|
||||
@@ -269,10 +269,9 @@ public class TimeBasedReplicationTests extends JSR166TestCase {
|
||||
|
||||
|
||||
final TimeProvider timeProvider = Mockito.mock(TimeProvider.class);
|
||||
ChronicleMapBuilder.of(CharSequence.class, CharSequence.class).replicators((byte) 1);
|
||||
ReplicatedChronicleMap map = (ReplicatedChronicleMap) ChronicleMapBuilder.of(CharSequence.class, CharSequence.class)
|
||||
|
||||
.forceReplicatedImpl()
|
||||
.entries(10)
|
||||
.replicators((byte) 1)
|
||||
.timeProvider(timeProvider)
|
||||
.create(getPersistenceFile());
|
||||
|
||||
@@ -303,7 +302,7 @@ public class TimeBasedReplicationTests extends JSR166TestCase {
|
||||
final TimeProvider timeProvider = Mockito.mock(TimeProvider.class);
|
||||
ReplicatedChronicleMap map = (ReplicatedChronicleMap) ChronicleMapBuilder.of(CharSequence.class, CharSequence.class)
|
||||
.entries(10)
|
||||
.forceReplicatedImpl()
|
||||
.replicators((byte) 1)
|
||||
.entries(10)
|
||||
.timeProvider(timeProvider)
|
||||
.create(getPersistenceFile());
|
||||
@@ -331,9 +330,10 @@ public class TimeBasedReplicationTests extends JSR166TestCase {
|
||||
public void testPutRemovePut() throws IOException {
|
||||
|
||||
final TimeProvider timeProvider = Mockito.mock(TimeProvider.class);
|
||||
ChronicleMapBuilder.of(CharSequence.class, CharSequence.class)
|
||||
.entries(10).replicators((byte) 1);
|
||||
ChronicleMap map = ChronicleMapBuilder.of(CharSequence.class, CharSequence.class)
|
||||
.entries(10)
|
||||
.forceReplicatedImpl()
|
||||
.entries(10)
|
||||
.timeProvider(timeProvider)
|
||||
.create(getPersistenceFile());
|
||||
|
||||
@@ -51,12 +51,12 @@ public class TwoMapOnDifferentServers {
|
||||
File persistenceFile = getPersistenceFile();
|
||||
map1 = ChronicleMapBuilder.of(Integer.class, CharSequence.class)
|
||||
.entries(20000)
|
||||
.addReplicator(tcp((byte) 1, tcpReplicationConfig))
|
||||
.replicators((byte) 1, tcp(tcpReplicationConfig))
|
||||
.create(persistenceFile);
|
||||
|
||||
map2 = ChronicleMapBuilder.of(Integer.class, CharSequence.class)
|
||||
.entries(20000)
|
||||
.addReplicator(tcp((byte) 2,
|
||||
.replicators((byte) 2, tcp(
|
||||
TcpReplicationConfig.of(8077).heartBeatInterval(1, SECONDS)))
|
||||
.create(persistenceFile);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public class UDPSocketReplicationTest {
|
||||
|
||||
return ChronicleMapBuilder.of(Integer.class, CharSequence.class)
|
||||
.entries(1000)
|
||||
.addReplicator(udp((byte) identifier, udpConfig))
|
||||
.replicators((byte) identifier, udp(udpConfig))
|
||||
.create(Builder.getPersistenceFile());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.openhft.chronicle.map.fromdocs;
|
||||
|
||||
import net.openhft.chronicle.map.ChronicleMapBuilder;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Created by peter on 28/02/14.
|
||||
*/
|
||||
public class GettingStartedTest {
|
||||
|
||||
@Test
|
||||
public void testTheCodeInGuide() throws IOException {
|
||||
String tmpdir = System.getProperty("java.io.tmpdir");
|
||||
Map<String, String> map = ChronicleMapBuilder.of(String.class, String.class)
|
||||
|
||||
.create(new File(tmpdir + "/shared.map"));
|
||||
map.put("some.json", "missing");
|
||||
map.get("some.json");
|
||||
|
||||
map.put("Hello", "World");
|
||||
String hi = map.get("Hello");
|
||||
map.put("Long String", "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789");
|
||||
String json = "{\"menu\": {\n" +
|
||||
" \"id\": \"file\",\n" +
|
||||
" \"value\": \"File\",\n" +
|
||||
" \"popup\": {\n" +
|
||||
" \"menuitem\": [\n" +
|
||||
" {\"value\": \"New\", \"onclick\": \"CreateNew()\"},\n" +
|
||||
" {\"value\": \"Open\", \"onclick\": \"OpenDoc()\"},\n" +
|
||||
" {\"value\": \"Close\", \"onclick\": \"CloseDoc()\"}\n" +
|
||||
" ]\n" +
|
||||
" }\n" +
|
||||
"}}";
|
||||
map.put("some.json", json);
|
||||
|
||||
String s2 = map.get("some.json");
|
||||
assertEquals(json, s2);
|
||||
|
||||
((Closeable) map).close();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ public class SetForTCPSocketReplicationTest3way {
|
||||
final int serverPort,
|
||||
final InetSocketAddress... endpoints) throws IOException {
|
||||
return (T) ChronicleSetBuilder.of(Integer.class)
|
||||
.addReplicator(tcp(identifier, of(serverPort, endpoints).
|
||||
.replicators(identifier, tcp(of(serverPort, endpoints).
|
||||
heartBeatInterval(1L, SECONDS))).create(getPersistenceFile());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user