diff --git a/src/main/java/net/openhft/chronicle/hash/replication/AbstractReplication.java b/src/main/java/net/openhft/chronicle/hash/replication/AbstractReplication.java index b1be83962..4f72484dd 100644 --- a/src/main/java/net/openhft/chronicle/hash/replication/AbstractReplication.java +++ b/src/main/java/net/openhft/chronicle/hash/replication/AbstractReplication.java @@ -16,6 +16,7 @@ package net.openhft.chronicle.hash.replication; +import net.openhft.chronicle.map.EngineReplicationLangBytes; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -40,6 +41,7 @@ public abstract class AbstractReplication implements Serializable { @Nullable private final transient ConnectionListener connectionListener; + private final EngineReplicationLangBytesConsumer engineReplicationLangBytesConsumer; // package-private to forbid subclassing from outside of the package AbstractReplication(byte localIdentifier, Builder builder) { @@ -49,6 +51,7 @@ public abstract class AbstractReplication implements Serializable { remoteNodeValidator = builder.remoteNodeValidator; bootstrapOnlyLocalEntries = builder.bootstrapOnlyLocalEntries; connectionListener = builder.connectionListener; + engineReplicationLangBytesConsumer = builder.engineReplicationLangBytesConsumer(); } @Override @@ -69,6 +72,10 @@ public abstract class AbstractReplication implements Serializable { return tcpConfig; } + public EngineReplicationLangBytesConsumer engineReplicator() { + return engineReplicationLangBytesConsumer; + } + @Nullable public UdpTransportConfig udpTransport() { return udpConfig; @@ -105,10 +112,25 @@ public abstract class AbstractReplication implements Serializable { private boolean bootstrapOnlyLocalEntries = false; + private EngineReplicationLangBytesConsumer engineReplicationLangBytesConsumer; + // package-private to forbid subclassing from outside of the package Builder() { } + @NotNull + public B engineReplication(EngineReplicationLangBytesConsumer + engineReplicationLangBytesConsumer) { + this.engineReplicationLangBytesConsumer = engineReplicationLangBytesConsumer; + return (B) this; + } + + EngineReplicationLangBytesConsumer engineReplicationLangBytesConsumer() { + return engineReplicationLangBytesConsumer; + } + + + @NotNull public B tcpTransportAndNetwork(@Nullable TcpTransportAndNetworkConfig tcpConfig) { this.tcpConfig = tcpConfig; @@ -190,5 +212,6 @@ public abstract class AbstractReplication implements Serializable { return ", udpConfig=" + udpConfig + ", remoteNodeValidator=" + remoteNodeValidator; } + } } diff --git a/src/main/java/net/openhft/chronicle/hash/replication/EngineReplicationLangBytesConsumer.java b/src/main/java/net/openhft/chronicle/hash/replication/EngineReplicationLangBytesConsumer.java new file mode 100644 index 000000000..cd33b95c8 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/replication/EngineReplicationLangBytesConsumer.java @@ -0,0 +1,11 @@ +package net.openhft.chronicle.hash.replication; + +import net.openhft.chronicle.map.EngineReplicationLangBytes; + +/** + * Created by Rob Austin + */ +public interface EngineReplicationLangBytesConsumer { + + void set(EngineReplicationLangBytes engineReplicationLangBytes); +} diff --git a/src/main/java/net/openhft/chronicle/hash/replication/SingleChronicleHashReplication.java b/src/main/java/net/openhft/chronicle/hash/replication/SingleChronicleHashReplication.java index a4d869c2b..9d0668fd4 100644 --- a/src/main/java/net/openhft/chronicle/hash/replication/SingleChronicleHashReplication.java +++ b/src/main/java/net/openhft/chronicle/hash/replication/SingleChronicleHashReplication.java @@ -18,14 +18,14 @@ package net.openhft.chronicle.hash.replication; import org.jetbrains.annotations.NotNull; -public final class SingleChronicleHashReplication extends AbstractReplication { +public class SingleChronicleHashReplication extends AbstractReplication { @NotNull public static Builder builder() { return new Builder(); } - SingleChronicleHashReplication(byte localIdentifier, Builder builder) { + public SingleChronicleHashReplication(byte localIdentifier, Builder builder) { super(localIdentifier, builder); } @@ -34,7 +34,7 @@ public final class SingleChronicleHashReplication extends AbstractReplication { return "SingleChronicleHashReplication{" + super.toString() + "}"; } - public static final class Builder + public static class Builder extends AbstractReplication.Builder { private Builder() {} diff --git a/src/main/java/net/openhft/chronicle/map/ChannelProvider.java b/src/main/java/net/openhft/chronicle/map/ChannelProvider.java index 9ceeda2a3..d5f597fb7 100644 --- a/src/main/java/net/openhft/chronicle/map/ChannelProvider.java +++ b/src/main/java/net/openhft/chronicle/map/ChannelProvider.java @@ -18,6 +18,7 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.hash.replication.EngineReplicationLangBytesConsumer; import net.openhft.chronicle.hash.replication.ReplicationHub; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; import net.openhft.chronicle.hash.replication.UdpTransportConfig; @@ -58,9 +59,10 @@ final class ChannelProvider implements Closeable { if (channelProvider != null) return channelProvider; channelProvider = new ChannelProvider(hub); + + + TcpTransportAndNetworkConfig tcpConfig = hub.tcpTransportAndNetwork(); - - if (tcpConfig != null) { final TcpReplicator tcpReplicator = new TcpReplicator( @@ -158,11 +160,26 @@ final class ChannelProvider implements Closeable { private final byte localIdentifier; final Replica asReplica = new Replica() { + @Override + public void put(final Bytes key, final Bytes value, final byte remoteIdentifier, final long timestamp) { + throw new UnsupportedOperationException("todo"); + } + + @Override + public void remove(final Bytes key, final byte remoteIdentifier, final long timestamp) { + throw new UnsupportedOperationException("todo"); + } + @Override public byte identifier() { return localIdentifier; } + @Override + public EngineModificationIterator acquireEngineModificationIterator(final byte remoteIdentifier) { + throw new UnsupportedOperationException("todo"); + } + @Override public ModificationIterator acquireModificationIterator( final byte remoteIdentifier) { @@ -472,11 +489,26 @@ final class ChannelProvider implements Closeable { class SystemQueue { final Replica asReplica = new Replica() { + @Override + public void put(final Bytes key, final Bytes value, final byte remoteIdentifier, final long timestamp) { + throw new UnsupportedOperationException("todo"); + } + + @Override + public void remove(final Bytes key, final byte remoteIdentifier, final long timestamp) { + throw new UnsupportedOperationException("todo"); + } + @Override public byte identifier() { throw new UnsupportedOperationException(); } + @Override + public EngineModificationIterator acquireEngineModificationIterator(final byte remoteIdentifier) { + throw new UnsupportedOperationException("todo"); + } + @Override public ModificationIterator acquireModificationIterator( final byte remoteIdentifier) { diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java index a44519791..8c55f588d 100755 --- a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java +++ b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java @@ -99,7 +99,7 @@ import static net.openhft.lang.model.DataValueGenerator.firstPrimitiveFieldType; * @see ChronicleMap * @see ChronicleSetBuilder */ -public final class ChronicleMapBuilder implements Cloneable, +public class ChronicleMapBuilder implements Cloneable, ChronicleHashBuilder, ChronicleMapBuilder>, MapBuilder>, Serializable { @@ -1454,12 +1454,14 @@ public final class ChronicleMapBuilder implements Cloneable, throw new AssertionError("Only one non-null replication should be passed"); } ReplicatedChronicleMap result = (ReplicatedChronicleMap) map; - List replicators = new ArrayList<>(2); + List replicators = new ArrayList<>(3); if (singleHashReplication != null) { if (singleHashReplication.tcpTransportAndNetwork() != null) replicators.add(Replicators.tcp(singleHashReplication)); if (singleHashReplication.udpTransport() != null) replicators.add(Replicators.udp(singleHashReplication.udpTransport())); + if (singleHashReplication.engineReplicator() != null) + replicators.add(Replicators.engineReplicaton(singleHashReplication)); } else { ReplicationHub hub = channel.hub(); diff --git a/src/main/java/net/openhft/chronicle/map/Replica.java b/src/main/java/net/openhft/chronicle/map/Replica.java index 3a32b6d21..084556c90 100644 --- a/src/main/java/net/openhft/chronicle/map/Replica.java +++ b/src/main/java/net/openhft/chronicle/map/Replica.java @@ -27,7 +27,7 @@ import java.io.Closeable; /** * @author Rob Austin. */ -interface Replica extends Closeable { +interface Replica extends Closeable, EngineReplicationLangBytes { /** * Provides the unique Identifier associated with this map instance.

An identifier is used diff --git a/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java b/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java index 3d3e754ec..ab3675d17 100644 --- a/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java @@ -26,6 +26,10 @@ import net.openhft.chronicle.hash.serialization.internal.BytesBytesInterop; import net.openhft.chronicle.hash.serialization.internal.DelegatingMetaBytesInterop; import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; import net.openhft.chronicle.hash.serialization.internal.MetaBytesWriter; +import net.openhft.chronicle.map.MultiMap.EntryConsumer; +import net.openhft.chronicle.map.Replica.EntryExternalizable; +import net.openhft.chronicle.map.Replica.EntryResolver; +import net.openhft.chronicle.map.ReplicatedChronicleMap.ModificationIterator.EntryModifiableCallback; import net.openhft.lang.Maths; import net.openhft.lang.collection.ATSDirectBitSet; import net.openhft.lang.io.*; @@ -91,7 +95,7 @@ import static net.openhft.lang.io.NativeBytes.wrap; final class ReplicatedChronicleMap, V, VI, MVI extends MetaBytesInterop> extends VanillaChronicleMap - implements Replica, Replica.EntryExternalizable, Replica.EntryResolver, EngineReplicationLangBytes { + implements Replica, EntryExternalizable, EntryResolver, EngineReplicationLangBytes { // for file, jdbc and UDP replication public static final int RESERVED_MOD_ITER = 8; public static final int ADDITIONAL_ENTRY_BYTES = 10; @@ -276,7 +280,7 @@ final class ReplicatedChronicleMap buffer = new ThreadLocal() { @Override protected IByteBufferBytes initialValue() { - return ByteBufferBytes.wrap(ByteBuffer.allocate(1024)); + return ByteBufferBytes.wrap(ByteBuffer.allocateDirect(1024)); } }; @@ -365,7 +369,7 @@ final class ReplicatedChronicleMap Integer.MAX_VALUE) throw new IllegalStateException("entry is too large"); - IByteBufferBytes result = ByteBufferBytes.wrap(ByteBuffer.allocate((int) requiredSize)); + IByteBufferBytes result = ByteBufferBytes.wrap(ByteBuffer.allocateDirect((int) requiredSize)); buffer.set(result); return result; } @@ -407,9 +411,10 @@ final class ReplicatedChronicleMap 0 && source.remaining() > 0) { - source.writeByte(source.readByte()); + destination.writeByte(source.readByte()); } } @@ -498,8 +504,10 @@ final class ReplicatedChronicleMap