mirror of
https://github.com/OpenHFT/Chronicle-Map.git
synced 2021-09-13 01:26:12 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -53,6 +53,7 @@ class ClientWiredStatelessChronicleMap<K, V> extends MapStatelessClient<K, V, Ev
|
||||
|
||||
|
||||
public static final Consumer<ValueOut> VOID_PARAMETERS = out -> out.marshallable(AbstactStatelessClient.EMPTY);
|
||||
private final Class vClass;
|
||||
|
||||
protected Class<K> kClass;
|
||||
|
||||
@@ -73,6 +74,8 @@ class ClientWiredStatelessChronicleMap<K, V> extends MapStatelessClient<K, V, Ev
|
||||
this.putReturnsNull = config.putReturnsNull();
|
||||
this.removeReturnsNull = config.removeReturnsNull();
|
||||
this.kClass = kClass;
|
||||
this.vClass = vClass;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -252,7 +255,7 @@ class ClientWiredStatelessChronicleMap<K, V> extends MapStatelessClient<K, V, Ev
|
||||
}
|
||||
|
||||
public V get(Object key) {
|
||||
return proxyReturnObject(vClass, get, (K) key);
|
||||
return (V)proxyReturnObject(vClass, get, (K) key);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -275,7 +278,7 @@ class ClientWiredStatelessChronicleMap<K, V> extends MapStatelessClient<K, V, Ev
|
||||
public V remove(Object key) {
|
||||
if (key == null)
|
||||
throw keyNotNullNPE();
|
||||
return proxyReturnObject(vClass, removeReturnsNull ? removeWithoutAcc : remove, key);
|
||||
return (V)proxyReturnObject(vClass, removeReturnsNull ? removeWithoutAcc : remove, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -329,7 +332,6 @@ class ClientWiredStatelessChronicleMap<K, V> extends MapStatelessClient<K, V, Ev
|
||||
public Set<Map.Entry<K, V>> entrySet() {
|
||||
|
||||
|
||||
|
||||
long cid = proxyReturnWireConsumer(entrySet, (WireIn wireIn) -> {
|
||||
final long[] cidRef = new long[1];
|
||||
final StringBuilder type = Wires.acquireStringBuilder();
|
||||
@@ -343,7 +345,7 @@ class ClientWiredStatelessChronicleMap<K, V> extends MapStatelessClient<K, V, Ev
|
||||
cidRef[0] = cid0;
|
||||
|
||||
});
|
||||
return cidRef[0];
|
||||
return cidRef[0];
|
||||
});
|
||||
|
||||
return new ClientWiredStatelessChronicleEntrySet<K, V>(channelName, hub, cid, vClass);
|
||||
@@ -451,7 +453,5 @@ class ClientWiredStatelessChronicleMap<K, V> extends MapStatelessClient<K, V, Ev
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -2,21 +2,20 @@ package net.openhft.chronicle.map;
|
||||
|
||||
import net.openhft.chronicle.engine.client.ClientWiredStatelessTcpConnectionHub;
|
||||
import net.openhft.chronicle.engine.client.ParameterizeWireKey;
|
||||
import net.openhft.chronicle.wire.*;
|
||||
import net.openhft.chronicle.wire.Wire;
|
||||
import net.openhft.chronicle.wire.WireKey;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static net.openhft.chronicle.engine.client.ClientWiredStatelessTcpConnectionHub.CoreFields.reply;
|
||||
|
||||
/**
|
||||
* Created by Rob Austin
|
||||
*/
|
||||
public abstract class MapStatelessClient<K, V, E extends ParameterizeWireKey> extends
|
||||
AbstactStatelessClient<E> {
|
||||
public abstract class MapStatelessClient<K, V, E extends ParameterizeWireKey>
|
||||
extends AbstactStatelessClient<E> {
|
||||
|
||||
protected Class<V> vClass;
|
||||
private Class<V> vClass;
|
||||
|
||||
/**
|
||||
* @param channelName
|
||||
@@ -29,97 +28,10 @@ public abstract class MapStatelessClient<K, V, E extends ParameterizeWireKey> ex
|
||||
@NotNull String type,
|
||||
long cid, @NotNull final Class vClass) {
|
||||
super(channelName, hub, type, cid);
|
||||
|
||||
this.vClass = vClass;
|
||||
}
|
||||
|
||||
protected Object readValue(WireKey argName, long tid, long startTime, final V usingValue) {
|
||||
assert !hub.outBytesLock().isHeldByCurrentThread();
|
||||
long timeoutTime = startTime + hub.timeoutMs;
|
||||
|
||||
hub.inBytesLock().lock();
|
||||
try {
|
||||
|
||||
final Wire wireIn = hub.proxyReply(timeoutTime, tid);
|
||||
checkIsData(wireIn);
|
||||
|
||||
|
||||
return readV(argName, wireIn, usingValue);
|
||||
|
||||
} finally {
|
||||
hub.inBytesLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private Object readV(WireKey argName, Wire wireIn, V usingValue) {
|
||||
return readObject(argName, wireIn, usingValue, vClass);
|
||||
}
|
||||
|
||||
protected <E> E readObject(WireKey argName, Wire wireIn, E usingValue, Class<E> clazz) {
|
||||
|
||||
final ValueIn valueIn = wireIn.read(argName);
|
||||
if (valueIn.isNull())
|
||||
return null;
|
||||
|
||||
if (StringBuilder.class.isAssignableFrom(clazz)) {
|
||||
valueIn.text((StringBuilder) usingValue);
|
||||
return usingValue;
|
||||
} else if (Marshallable.class.isAssignableFrom(clazz)) {
|
||||
|
||||
|
||||
final E v;
|
||||
if (usingValue == null)
|
||||
try {
|
||||
v = clazz.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
else
|
||||
v = usingValue;
|
||||
|
||||
|
||||
valueIn.marshallable((Marshallable) v);
|
||||
return v;
|
||||
|
||||
} else if (String.class.isAssignableFrom(clazz)) {
|
||||
//noinspection unchecked
|
||||
return (E) valueIn.text();
|
||||
|
||||
} else if (Long.class.isAssignableFrom(clazz)) {
|
||||
//noinspection unchecked
|
||||
return (E) (Long) valueIn.int64();
|
||||
} else if (Double.class.isAssignableFrom(clazz)) {
|
||||
//noinspection unchecked
|
||||
return (E) (Double) valueIn.float64();
|
||||
|
||||
} else if (Integer.class.isAssignableFrom(clazz)) {
|
||||
//noinspection unchecked
|
||||
return (E) (Integer) valueIn.int32();
|
||||
|
||||
} else if (Float.class.isAssignableFrom(clazz)) {
|
||||
//noinspection unchecked
|
||||
return (E) (Float) valueIn.float32();
|
||||
|
||||
} else if (Short.class.isAssignableFrom(clazz)) {
|
||||
//noinspection unchecked
|
||||
return (E) (Short) valueIn.int16();
|
||||
|
||||
} else if (Character.class.isAssignableFrom(clazz)) {
|
||||
//noinspection unchecked
|
||||
final String text = valueIn.text();
|
||||
if (text == null || text.length() == 0)
|
||||
return null;
|
||||
return (E) (Character) text.charAt(0);
|
||||
|
||||
} else if (Byte.class.isAssignableFrom(clazz)) {
|
||||
//noinspection unchecked
|
||||
return (E) (Byte) valueIn.int8();
|
||||
|
||||
|
||||
} else {
|
||||
throw new IllegalStateException("unsupported type");
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected <R> R proxyReturnTypedObject(
|
||||
@NotNull final E eventId,
|
||||
@@ -141,7 +53,8 @@ public abstract class MapStatelessClient<K, V, E extends ParameterizeWireKey> ex
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected <R> R proxyReturnObject(Class<R> rClass, @NotNull final E eventId, Object field) {
|
||||
protected <R> R proxyReturnObject(@NotNull final Class<R> rClass,
|
||||
@NotNull final E eventId, Object field) {
|
||||
|
||||
final long startTime = System.currentTimeMillis();
|
||||
final long tid = sendEvent(startTime, eventId, out -> writeField(out, field));
|
||||
@@ -159,7 +72,26 @@ public abstract class MapStatelessClient<K, V, E extends ParameterizeWireKey> ex
|
||||
protected abstract boolean eventReturnsNull(@NotNull E methodName);
|
||||
|
||||
|
||||
protected V readValue(WireKey argName, long tid, long startTime, final V usingValue) {
|
||||
assert !hub.outBytesLock().isHeldByCurrentThread();
|
||||
long timeoutTime = startTime + hub.timeoutMs;
|
||||
|
||||
hub.inBytesLock().lock();
|
||||
try {
|
||||
|
||||
final Wire wireIn = hub.proxyReply(timeoutTime, tid);
|
||||
checkIsData(wireIn);
|
||||
|
||||
|
||||
return readV(argName, wireIn, usingValue);
|
||||
|
||||
} finally {
|
||||
hub.inBytesLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private V readV(WireKey argName, Wire wireIn, V usingValue) {
|
||||
return readObject(argName, wireIn, usingValue, vClass);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
package net.openhft.chronicle.map;
|
||||
|
||||
import net.openhft.chronicle.hash.ChronicleHashInstanceBuilder;
|
||||
import net.openhft.chronicle.hash.replication.ReplicationHub;
|
||||
import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
import static net.openhft.chronicle.map.ChronicleMapBuilder.of;
|
||||
|
||||
/**
|
||||
* Created by Rob Austin
|
||||
*/
|
||||
public class MapWireConnectionHub<K, V> {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MapWireHandler.class);
|
||||
public static final int MAP_SERVICE = 3;
|
||||
private final byte localIdentifier;
|
||||
|
||||
protected ChronicleMap<String, Integer> channelNameToId;
|
||||
private Supplier<ChronicleHashInstanceBuilder<ChronicleMap<K, V>>> mapFactory;
|
||||
private final Map<Integer, Replica> channelMap;
|
||||
private final ReplicationHub hub;
|
||||
|
||||
private final ArrayList<BytesChronicleMap> bytesChronicleMaps = new ArrayList<>();
|
||||
|
||||
|
||||
public MapWireConnectionHub(
|
||||
@NotNull final Supplier<ChronicleHashInstanceBuilder<ChronicleMap<K, V>>> mapFactory,
|
||||
@NotNull final Supplier<ChronicleHashInstanceBuilder<ChronicleMap<String, Integer>>>
|
||||
channelNameToIdFactory,
|
||||
byte localIdentifier,
|
||||
int serverPort) throws IOException {
|
||||
|
||||
|
||||
this.mapFactory = mapFactory;
|
||||
this.localIdentifier = localIdentifier;
|
||||
|
||||
final TcpTransportAndNetworkConfig tcpConfig = TcpTransportAndNetworkConfig
|
||||
.of(serverPort)
|
||||
.heartBeatInterval(1, SECONDS);
|
||||
|
||||
hub = ReplicationHub.builder().tcpTransportAndNetwork(tcpConfig).createWithId(localIdentifier);
|
||||
|
||||
// this is how you add maps after the custer is created
|
||||
of(byte[].class, byte[].class)
|
||||
.instance().replicatedViaChannel(hub.createChannel((short) 1)).create();
|
||||
|
||||
channelNameToId = (ChronicleMap) channelNameToIdFactory.get()
|
||||
.replicatedViaChannel(hub.createChannel(MAP_SERVICE)).create();
|
||||
|
||||
ChannelProvider provider = ChannelProvider.getProvider(hub);
|
||||
channelMap = provider.chronicleChannelMap();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the next free channel id
|
||||
*/
|
||||
short getNextFreeChannel() {
|
||||
|
||||
// todo this is a horrible hack, it slow and not processor safe, but was added to get
|
||||
// todo something working for now.
|
||||
|
||||
int max = 3;
|
||||
for (Integer channel : channelNameToId.values()) {
|
||||
max = Math.max(max, channel);
|
||||
}
|
||||
|
||||
return (short) (max + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the channel id for a name, or creates a new one if this name is not yet assosiated to a
|
||||
* channel
|
||||
*
|
||||
* @param fromName the name of the channel
|
||||
* @return the id associated with this name
|
||||
*/
|
||||
BytesChronicleMap acquireMap(@NotNull final String fromName) throws IOException {
|
||||
|
||||
// todo this is a horrible hack, it slow and NOT processor safe, but was added to get
|
||||
// todo something working for now.
|
||||
|
||||
final Integer channelId = channelNameToId.get(fromName);
|
||||
|
||||
if (channelId != null)
|
||||
return bytesMap(channelId);
|
||||
|
||||
final int nextFreeChannel = getNextFreeChannel();
|
||||
try {
|
||||
|
||||
mapFactory.get().replicatedViaChannel(hub.createChannel(nextFreeChannel)).create();
|
||||
channelNameToId.put(fromName, nextFreeChannel);
|
||||
|
||||
return bytesMap(nextFreeChannel);
|
||||
} catch (IOException e) {
|
||||
// todo send this error back to the user
|
||||
LOG.error("", e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* this is used to push the data straight into the entry in memory
|
||||
*
|
||||
* @param channelId the ID of the map
|
||||
* @return a BytesChronicleMap used to update the memory which holds the chronicle map
|
||||
*/
|
||||
@Nullable
|
||||
BytesChronicleMap bytesMap(int channelId) {
|
||||
|
||||
final BytesChronicleMap bytesChronicleMap = (channelId < bytesChronicleMaps.size())
|
||||
? bytesChronicleMaps.get(channelId)
|
||||
: null;
|
||||
|
||||
if (bytesChronicleMap != null)
|
||||
return bytesChronicleMap;
|
||||
|
||||
// grow the array
|
||||
for (int i = bytesChronicleMaps.size(); i <= channelId; i++) {
|
||||
bytesChronicleMaps.add(null);
|
||||
}
|
||||
|
||||
final ReplicatedChronicleMap delegate = map(channelId);
|
||||
final BytesChronicleMap element = new BytesChronicleMap(delegate);
|
||||
bytesChronicleMaps.set(channelId, element);
|
||||
return element;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the map for this channel id
|
||||
*
|
||||
* @param channelId the ID of the map
|
||||
* @return the chronicle map with this {@code channelId}
|
||||
*/
|
||||
@NotNull
|
||||
private ReplicatedChronicleMap map(int channelId) {
|
||||
|
||||
// todo this cast is a bit of a hack, improve later
|
||||
final ReplicatedChronicleMap map =
|
||||
(ReplicatedChronicleMap) channelMap.get(channelId);
|
||||
|
||||
if (map != null)
|
||||
return map;
|
||||
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package net.openhft.chronicle.map;
|
||||
|
||||
import net.openhft.chronicle.bytes.Bytes;
|
||||
import net.openhft.chronicle.engine.client.ClientWiredStatelessTcpConnectionHub.CoreFields;
|
||||
import net.openhft.chronicle.wire.TextWire;
|
||||
import net.openhft.chronicle.wire.ValueOut;
|
||||
import net.openhft.chronicle.wire.Wire;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Rob Austin
|
||||
*/
|
||||
public class MapWireConnectionHubByName<K, V> implements Map<K, V> {
|
||||
|
||||
private final Class<K> kClass;
|
||||
private final Class<V> vClass;
|
||||
private final MapWireConnectionHub mapWireConnectionHub;
|
||||
|
||||
|
||||
Bytes<ByteBuffer> buffer = Bytes.elasticByteBuffer();
|
||||
|
||||
private final Map<byte[], byte[]> map;
|
||||
|
||||
|
||||
Class<? extends Wire> wireType = TextWire.class;
|
||||
|
||||
public MapWireConnectionHubByName(String name,
|
||||
Class<V> vClass,
|
||||
Class<K> kClass,
|
||||
MapWireConnectionHub mapWireConnectionHub) throws IOException {
|
||||
this.mapWireConnectionHub = mapWireConnectionHub;
|
||||
final BytesChronicleMap b = this.mapWireConnectionHub.acquireMap(name);
|
||||
this.map = (Map) b.delegate;
|
||||
this.vClass = vClass;
|
||||
this.kClass = kClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
Wire toWire() {
|
||||
buffer.clear();
|
||||
if (TextWire.class.isAssignableFrom(wireType)) {
|
||||
return new TextWire(buffer);
|
||||
} else throw new UnsupportedOperationException("todo");
|
||||
}
|
||||
|
||||
|
||||
Wire toWire(byte[] bytes) {
|
||||
|
||||
Bytes<byte[]> wrap = Bytes.wrap(bytes);
|
||||
|
||||
if (TextWire.class.isAssignableFrom(wireType)) {
|
||||
return new TextWire(wrap);
|
||||
} else throw new UnsupportedOperationException("todo");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
return map.containsKey(bytes(key));
|
||||
}
|
||||
|
||||
private byte[] bytes(Object key) {
|
||||
ValueOut valueOut = toWire().getValueOut();
|
||||
AbstactStatelessClient.writeField(key, valueOut);
|
||||
buffer.flip();
|
||||
byte[] bytes = new byte[(int) buffer.limit()];
|
||||
buffer.read(bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(Object value) {
|
||||
return map.containsValue(bytes(value));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(Object key) {
|
||||
byte[] bytes = map.get(bytes(key));
|
||||
|
||||
if (bytes == null)
|
||||
return null;
|
||||
|
||||
final Wire wire = toWire(bytes);
|
||||
return AbstactStatelessClient.<V>readObject(CoreFields.reply, wire, null, vClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V put(K key, V value) {
|
||||
final Wire wire = toWire(map.put(bytes(key), bytes(value)));
|
||||
return AbstactStatelessClient.<V>readObject(CoreFields.reply, wire, null, vClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V remove(Object key) {
|
||||
final Wire wire = toWire(map.remove(bytes(key)));
|
||||
return AbstactStatelessClient.<V>readObject(CoreFields.reply, wire, null, vClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(Map<? extends K, ? extends V> m) {
|
||||
throw new UnsupportedOperationException("todo");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
map.clear();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
throw new UnsupportedOperationException("todo");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<V> values() {
|
||||
throw new UnsupportedOperationException("todo");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<Entry<K, V>> entrySet() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,9 +25,7 @@ package net.openhft.chronicle.map;
|
||||
import net.openhft.chronicle.bytes.Bytes;
|
||||
import net.openhft.chronicle.engine.client.ClientWiredStatelessTcpConnectionHub;
|
||||
import net.openhft.chronicle.engine.client.ParameterizeWireKey;
|
||||
import net.openhft.chronicle.hash.ChronicleHashInstanceBuilder;
|
||||
import net.openhft.chronicle.hash.impl.util.BuildVersion;
|
||||
import net.openhft.chronicle.hash.replication.ReplicationHub;
|
||||
import net.openhft.chronicle.map.ClientWiredStatelessChronicleEntrySet.EntrySetEventId;
|
||||
import net.openhft.chronicle.network.WireHandler;
|
||||
import net.openhft.chronicle.network.event.EventGroup;
|
||||
@@ -35,19 +33,16 @@ import net.openhft.chronicle.network.event.WireHandlers;
|
||||
import net.openhft.chronicle.wire.*;
|
||||
import net.openhft.lang.io.DirectStore;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StreamCorruptedException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static net.openhft.chronicle.engine.client.ClientWiredStatelessTcpConnectionHub.CoreFields;
|
||||
import static net.openhft.chronicle.engine.client.ClientWiredStatelessTcpConnectionHub.CoreFields.csp;
|
||||
@@ -64,20 +59,19 @@ import static net.openhft.chronicle.wire.Wires.acquireStringBuilder;
|
||||
public class MapWireHandler<K, V> implements WireHandler, Consumer<WireHandlers> {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MapWireHandler.class);
|
||||
public static final int MAP_SERVICE = 3;
|
||||
|
||||
public static final int SIZE_OF_SIZE = ClientWiredStatelessTcpConnectionHub.SIZE_OF_SIZE;
|
||||
private final Map<Long, Runnable> incompleteWork = new HashMap<>();
|
||||
private final ArrayList<BytesChronicleMap> bytesChronicleMaps = new ArrayList<>();
|
||||
|
||||
@NotNull
|
||||
private final Supplier<ChronicleHashInstanceBuilder<ChronicleMap<K, V>>> mapFactory;
|
||||
private final Map<Long, CharSequence> cidToCsp;
|
||||
@NotNull
|
||||
private final MapWireConnectionHub mapWireConnectionHub;
|
||||
private final Map<CharSequence, Long> cspToCid = new HashMap<>();
|
||||
|
||||
|
||||
private Wire inWire = null;
|
||||
private Wire outWire = null;
|
||||
|
||||
|
||||
private void setCspTextFromCid(long cid) {
|
||||
cspText.setLength(0);
|
||||
cspText.append(cidToCsp.get(cid));
|
||||
@@ -88,17 +82,13 @@ public class MapWireHandler<K, V> implements WireHandler, Consumer<WireHandlers>
|
||||
@Override
|
||||
public void accept(WireIn wireIn) {
|
||||
|
||||
StringBuilder key = Wires.acquireStringBuilder();
|
||||
final StringBuilder key = Wires.acquireStringBuilder();
|
||||
final ValueIn read = wireIn.read(key);
|
||||
|
||||
|
||||
if (csp.contentEquals(key)) {
|
||||
if (csp.contentEquals(key))
|
||||
read.text(cspText);
|
||||
} else {
|
||||
if (CoreFields.cid.contentEquals(key)) {
|
||||
setCspTextFromCid(read.int64());
|
||||
}
|
||||
}
|
||||
else if (CoreFields.cid.contentEquals(key))
|
||||
setCspTextFromCid(read.int64());
|
||||
|
||||
final int slash = cspText.lastIndexOf("/");
|
||||
final int hash = cspText.lastIndexOf("#");
|
||||
@@ -107,13 +97,15 @@ public class MapWireHandler<K, V> implements WireHandler, Consumer<WireHandlers>
|
||||
hash != -1 && hash < (cspText.length() - 1)) {
|
||||
final String channelStr = cspText.substring(slash + 1, hash);
|
||||
try {
|
||||
channelId = MapWireHandler.this.acquireChannelId(channelStr);
|
||||
bytesChronicleMap = mapWireConnectionHub.acquireMap(channelStr);
|
||||
|
||||
} catch (IOException e) {
|
||||
// todo send to user
|
||||
LOG.error("", e);
|
||||
}
|
||||
|
||||
} else
|
||||
channelId = 0;
|
||||
bytesChronicleMap = null;
|
||||
|
||||
tid = inWire.read(CoreFields.tid).int64();
|
||||
|
||||
@@ -122,44 +114,16 @@ public class MapWireHandler<K, V> implements WireHandler, Consumer<WireHandlers>
|
||||
|
||||
|
||||
private WireHandlers publishLater;
|
||||
private byte localIdentifier;
|
||||
|
||||
private int channelId;
|
||||
private Map<Integer, Replica> channels;
|
||||
private ReplicationHub hub;
|
||||
private BytesChronicleMap bytesChronicleMap;
|
||||
|
||||
private ChronicleMap<String, Integer> channelNameToId;
|
||||
|
||||
public MapWireHandler(
|
||||
@NotNull final Supplier<ChronicleHashInstanceBuilder<ChronicleMap<K, V>>> mapFactory,
|
||||
@NotNull final Supplier<ChronicleHashInstanceBuilder<ChronicleMap<String, Integer>>>
|
||||
channelNameToIdFactory,
|
||||
@NotNull final ReplicationHub hub, byte localIdentifier,
|
||||
@NotNull final Map<Integer, Replica> channels,
|
||||
@NotNull final Map<Long, CharSequence> cidToCsp) {
|
||||
this(mapFactory, channelNameToIdFactory, hub, cidToCsp);
|
||||
this.channels = channels;
|
||||
this.localIdentifier = localIdentifier;
|
||||
@NotNull final Map<Long, CharSequence> cidToCsp,
|
||||
@NotNull final MapWireConnectionHub mapWireConnectionHub) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
public MapWireHandler(
|
||||
@NotNull final Supplier<ChronicleHashInstanceBuilder<ChronicleMap<K, V>>> mapFactory,
|
||||
@NotNull final Supplier<ChronicleHashInstanceBuilder<ChronicleMap<String, Integer>>>
|
||||
channelNameToIdFactory,
|
||||
@NotNull final ReplicationHub hub,
|
||||
@NotNull final Map<Long, CharSequence> cidToCsp) {
|
||||
|
||||
this.mapFactory = mapFactory;
|
||||
this.hub = hub;
|
||||
this.cidToCsp = cidToCsp;
|
||||
|
||||
try {
|
||||
channelNameToId = (ChronicleMap) channelNameToIdFactory.get()
|
||||
.replicatedViaChannel(hub.createChannel(MAP_SERVICE)).create();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.mapWireConnectionHub = mapWireConnectionHub;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -168,8 +132,6 @@ public class MapWireHandler<K, V> implements WireHandler, Consumer<WireHandlers>
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void process(@NotNull final Wire in, @NotNull final Wire out) throws StreamCorruptedException {
|
||||
try {
|
||||
@@ -182,55 +144,6 @@ public class MapWireHandler<K, V> implements WireHandler, Consumer<WireHandlers>
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the next free channel id
|
||||
*/
|
||||
short getNextFreeChannel() {
|
||||
|
||||
// todo this is a horrible hack, it slow and not processor safe, but was added to get
|
||||
// todo something working for now.
|
||||
|
||||
int max = 3;
|
||||
for (Integer channel : channelNameToId.values()) {
|
||||
max = Math.max(max, channel);
|
||||
}
|
||||
|
||||
return (short) (max + 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gets the channel id for a name, or creates a new one if this name is not yet assosiated to a
|
||||
* channel
|
||||
*
|
||||
* @param fromName the name of the channel
|
||||
* @return the id assosiated with this name
|
||||
*/
|
||||
int acquireChannelId(@NotNull final String fromName) throws IOException {
|
||||
|
||||
// todo this is a horrible hack, it slow and NOT processor safe, but was added to get
|
||||
// todo something working for now.
|
||||
|
||||
final Integer channelId = channelNameToId.get(fromName);
|
||||
|
||||
if (channelId != null)
|
||||
return channelId;
|
||||
|
||||
final int nextFreeChannel = getNextFreeChannel();
|
||||
try {
|
||||
|
||||
mapFactory.get().replicatedViaChannel(hub.createChannel(nextFreeChannel)).create();
|
||||
channelNameToId.put(fromName, nextFreeChannel);
|
||||
|
||||
return nextFreeChannel;
|
||||
} catch (IOException e) {
|
||||
// todo send this error back to the user
|
||||
LOG.error("", e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
final StringBuilder cspText = new StringBuilder();
|
||||
public long tid;
|
||||
private final AtomicLong cid = new AtomicLong();
|
||||
@@ -440,7 +353,6 @@ public class MapWireHandler<K, V> implements WireHandler, Consumer<WireHandlers>
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (replace.contentEquals(eventName)) {
|
||||
|
||||
|
||||
@@ -537,11 +449,6 @@ public class MapWireHandler<K, V> implements WireHandler, Consumer<WireHandlers>
|
||||
};
|
||||
|
||||
|
||||
private void putAll(long tid) {
|
||||
|
||||
// todo
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameReturnValue")
|
||||
private void writeValueFromBytes(final Function<BytesChronicleMap, byte[]> f) {
|
||||
|
||||
@@ -564,7 +471,7 @@ public class MapWireHandler<K, V> implements WireHandler, Consumer<WireHandlers>
|
||||
|
||||
@NotNull
|
||||
private CharSequence persistedDataVersion() {
|
||||
final BytesChronicleMap bytesChronicleMap = bytesMap(channelId);
|
||||
|
||||
if (bytesChronicleMap == null)
|
||||
return "";
|
||||
return bytesChronicleMap.delegate.persistedDataVersion();
|
||||
@@ -612,52 +519,6 @@ public class MapWireHandler<K, V> implements WireHandler, Consumer<WireHandlers>
|
||||
return text.getBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the map for this channel id
|
||||
*
|
||||
* @param channelId the ID of the map
|
||||
* @return the chronicle map with this {@code channelId}
|
||||
*/
|
||||
@NotNull
|
||||
private ReplicatedChronicleMap map(int channelId) {
|
||||
|
||||
// todo this cast is a bit of a hack, improve later
|
||||
final ReplicatedChronicleMap map =
|
||||
(ReplicatedChronicleMap) channels.get(channelId);
|
||||
|
||||
if (map != null)
|
||||
return map;
|
||||
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
/**
|
||||
* this is used to push the data straight into the entry in memory
|
||||
*
|
||||
* @param channelId the ID of the map
|
||||
* @return a BytesChronicleMap used to update the memory which holds the chronicle map
|
||||
*/
|
||||
@Nullable
|
||||
private BytesChronicleMap bytesMap(int channelId) {
|
||||
|
||||
final BytesChronicleMap bytesChronicleMap = (channelId < bytesChronicleMaps.size())
|
||||
? bytesChronicleMaps.get(channelId)
|
||||
: null;
|
||||
|
||||
if (bytesChronicleMap != null)
|
||||
return bytesChronicleMap;
|
||||
|
||||
// grow the array
|
||||
for (int i = bytesChronicleMaps.size(); i <= channelId; i++) {
|
||||
bytesChronicleMaps.add(null);
|
||||
}
|
||||
|
||||
final ReplicatedChronicleMap delegate = map(channelId);
|
||||
final BytesChronicleMap element = new BytesChronicleMap(delegate);
|
||||
bytesChronicleMaps.set(channelId, element);
|
||||
return element;
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameReturnValue")
|
||||
private void writeValue(final Function<Map<byte[], byte[]>, byte[]> f) {
|
||||
@@ -688,23 +549,23 @@ public class MapWireHandler<K, V> implements WireHandler, Consumer<WireHandlers>
|
||||
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("SameReturnValue")
|
||||
private void write(@NotNull Consumer<BytesChronicleMap> c) {
|
||||
void write(@NotNull Consumer<BytesChronicleMap> c) {
|
||||
|
||||
final BytesChronicleMap bytesMap = bytesMap(channelId);
|
||||
|
||||
if (bytesMap == null) {
|
||||
LOG.error("no map for channelId=" + channelId + " can be found.");
|
||||
if (bytesChronicleMap == null) {
|
||||
LOG.error("no map for channel.");
|
||||
return;
|
||||
}
|
||||
|
||||
bytesMap.output = null;
|
||||
bytesChronicleMap.output = null;
|
||||
|
||||
outWire.writeDocument(false, out -> {
|
||||
long position = 0;
|
||||
try {
|
||||
position = outWire.bytes().position();
|
||||
c.accept(bytesMap);
|
||||
c.accept(bytesChronicleMap);
|
||||
} catch (Exception e) {
|
||||
// bytes.reset();
|
||||
// the idea of wire is that is platform independent,
|
||||
@@ -714,9 +575,9 @@ public class MapWireHandler<K, V> implements WireHandler, Consumer<WireHandlers>
|
||||
final WireOut o = out.write(reply)
|
||||
.type(e.getClass().getSimpleName());
|
||||
|
||||
if (e.getMessage() != null) {
|
||||
if (e.getMessage() != null)
|
||||
o.writeValue().text(e.getMessage());
|
||||
}
|
||||
|
||||
LOG.error("", e);
|
||||
}
|
||||
});
|
||||
@@ -729,17 +590,16 @@ public class MapWireHandler<K, V> implements WireHandler, Consumer<WireHandlers>
|
||||
private void writeVoid(@NotNull Consumer<BytesChronicleMap> process) {
|
||||
|
||||
// skip 4 bytes where we will write the size
|
||||
final BytesChronicleMap bytesMap = bytesMap(channelId);
|
||||
|
||||
if (bytesMap == null) {
|
||||
LOG.error("no map for channelId=" + channelId + " can be found.");
|
||||
if (bytesChronicleMap == null) {
|
||||
LOG.error("no map for channelId.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
outWire.bytes().mark();
|
||||
process.accept(bytesMap);
|
||||
process.accept(bytesChronicleMap);
|
||||
|
||||
} catch (Exception e) {
|
||||
outWire.writeDocument(false, out -> {
|
||||
@@ -758,10 +618,6 @@ public class MapWireHandler<K, V> implements WireHandler, Consumer<WireHandlers>
|
||||
}
|
||||
|
||||
|
||||
public void localIdentifier(byte localIdentifier) {
|
||||
this.localIdentifier = localIdentifier;
|
||||
}
|
||||
|
||||
enum Params implements WireKey {
|
||||
key,
|
||||
value,
|
||||
|
||||
Reference in New Issue
Block a user