mirror of
https://github.com/OpenHFT/Chronicle-Map.git
synced 2021-09-13 01:26:12 +00:00
HCOLL-167 added a working version of StatelessChronicleMapTest but requires refactoring,
This commit is contained in:
@@ -8,7 +8,7 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
public class StatelessBuilder {
|
||||
|
||||
private long timeoutMs = TimeUnit.SECONDS.toMillis(5);
|
||||
private long timeoutMs = TimeUnit.SECONDS.toMillis(1);
|
||||
|
||||
private InetSocketAddress remoteAddress;
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clos
|
||||
private static final Logger LOG = LoggerFactory.getLogger(StatelessChronicleMap.class);
|
||||
|
||||
private final SocketChannel clientChannel;
|
||||
public static final ByteBuffer STATELESS_CLIENT_IDENTIFER = ByteBuffer.wrap(new byte[]{-127});
|
||||
private final CloseablesManager closeables = new CloseablesManager();
|
||||
public static final byte STATELESS_CLIENT_IDENTIFER = (byte) -127;
|
||||
private CloseablesManager closeables;
|
||||
private final StatelessBuilder builder;
|
||||
|
||||
static enum EventId {
|
||||
@@ -48,7 +48,8 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clos
|
||||
REPLACE,
|
||||
REPLACE_WITH_OLD_AND_NEW_VALUE,
|
||||
PUT_IF_ABSENT,
|
||||
REMOVE_WITH_VALUE
|
||||
REMOVE_WITH_VALUE,
|
||||
TO_STRING
|
||||
}
|
||||
|
||||
private final AtomicLong transactionID = new AtomicLong();
|
||||
@@ -65,8 +66,16 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clos
|
||||
IOException exception = null;
|
||||
SocketChannel clientChannel0 = null;
|
||||
|
||||
for (int i = 1; i < 5; i++) {
|
||||
long timeoutAt = System.currentTimeMillis() + builder.timeoutMs();
|
||||
for (; ; ) {
|
||||
|
||||
if (System.currentTimeMillis() > timeoutAt) {
|
||||
clientChannel0.close();
|
||||
close();
|
||||
throw new RuntimeException("unable to connect to remote server");
|
||||
}
|
||||
|
||||
closeables = new CloseablesManager();
|
||||
clientChannel0 = AbstractChannelReplicator.openSocketChannel(closeables);
|
||||
|
||||
try {
|
||||
@@ -75,8 +84,10 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clos
|
||||
exception = null;
|
||||
break;
|
||||
} catch (IOException e) {
|
||||
closeables.closeQuietly();
|
||||
Thread.yield();
|
||||
|
||||
clientChannel0.close();
|
||||
close();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -84,6 +95,8 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clos
|
||||
if (exception != null)
|
||||
throw exception;
|
||||
|
||||
if (clientChannel0 == null)
|
||||
throw new IOException("unable to connect to remote server");
|
||||
|
||||
return clientChannel0;
|
||||
}
|
||||
@@ -91,11 +104,22 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clos
|
||||
|
||||
private void doHandShaking(final SocketChannel clientChannel) throws IOException {
|
||||
|
||||
while (STATELESS_CLIENT_IDENTIFER.remaining() > 0) {
|
||||
clientChannel.write(STATELESS_CLIENT_IDENTIFER);
|
||||
out.clear();
|
||||
out.writeByte(STATELESS_CLIENT_IDENTIFER);
|
||||
|
||||
|
||||
ByteBuffer buffer = out.buffer().slice();
|
||||
buffer.position(0);
|
||||
buffer.limit(1);
|
||||
while (buffer.hasRemaining()) {
|
||||
clientChannel.write(buffer);
|
||||
}
|
||||
|
||||
|
||||
in.buffer().clear();
|
||||
in.clear();
|
||||
out.buffer().clear();
|
||||
out.clear();
|
||||
|
||||
while (in.buffer().position() <= 0) {
|
||||
clientChannel.read(in.buffer());
|
||||
@@ -115,6 +139,7 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clos
|
||||
|
||||
public void close() {
|
||||
closeables.closeQuietly();
|
||||
clearBuffers();
|
||||
}
|
||||
|
||||
|
||||
@@ -191,6 +216,15 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clos
|
||||
}
|
||||
|
||||
|
||||
public synchronized String toString() {
|
||||
long sizeLocation = writeEvent(TO_STRING);
|
||||
|
||||
// get the data back from the server
|
||||
return blockingFetch(sizeLocation).readObject(String.class);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public synchronized boolean isEmpty() {
|
||||
long sizeLocation = writeEvent(IS_EMPTY);
|
||||
|
||||
@@ -258,6 +292,11 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clos
|
||||
|
||||
}
|
||||
|
||||
private void compact() {
|
||||
in.buffer().compact();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public synchronized V remove(Object key) {
|
||||
long sizeLocation = writeEvent(REMOVE);
|
||||
@@ -422,18 +461,28 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clos
|
||||
try {
|
||||
return blockingFetchThrowable(sizeLocation, this.builder.timeoutMs());
|
||||
} catch (IOException e) {
|
||||
closeables.closeQuietly();
|
||||
close();
|
||||
throw new IORuntimeException(e);
|
||||
} catch (Exception e) {
|
||||
closeables.closeQuietly();
|
||||
close();
|
||||
throw e;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void clearBuffers() {
|
||||
out.clear();
|
||||
out.buffer().clear();
|
||||
in.clear();
|
||||
in.buffer().clear();
|
||||
}
|
||||
|
||||
|
||||
private Bytes blockingFetchThrowable(long sizeLocation, long timeOutMs) throws IOException {
|
||||
|
||||
// free up space in the buffer
|
||||
// compact();
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
long transactionId = nextUniqueTransaction(startTime);
|
||||
long timeoutTime = startTime + timeOutMs;
|
||||
@@ -453,18 +502,25 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clos
|
||||
in.clear();
|
||||
in.buffer().clear();
|
||||
|
||||
/* in.buffer().limit(in.buffer().capacity());
|
||||
in.limit(in.buffer().position());
|
||||
*/
|
||||
// read size
|
||||
while (in.buffer().position() < 2) {
|
||||
clientChannel.read(in.buffer());
|
||||
checkTimeout(timeoutTime);
|
||||
}
|
||||
|
||||
in.limit(in.buffer().position());
|
||||
int size = in.readUnsignedShort();
|
||||
|
||||
LOG.info("size=" + size);
|
||||
|
||||
while (in.buffer().position() < size) {
|
||||
clientChannel.read(in.buffer());
|
||||
checkTimeout(timeoutTime);
|
||||
}
|
||||
in.limit(in.buffer().position());
|
||||
|
||||
boolean isException = in.readBoolean();
|
||||
|
||||
|
||||
@@ -60,7 +60,6 @@ class TcpReplicator extends AbstractChannelReplicator implements Closeable {
|
||||
private final int maxEntrySizeBytes;
|
||||
private final Replica.EntryExternalizable externalizable;
|
||||
private final TcpReplicationConfig replicationConfig;
|
||||
|
||||
private final StatelessServerConnector statelessServerConnector;
|
||||
|
||||
private long selectorTimeout;
|
||||
@@ -201,6 +200,7 @@ class TcpReplicator extends AbstractChannelReplicator implements Closeable {
|
||||
* @param approxTime the approximate time in milliseconds
|
||||
*/
|
||||
void heartBeatMonitor(long approxTime) {
|
||||
|
||||
for (int i = activeKeys.nextSetBit(0); i >= 0; i = activeKeys.nextSetBit(i + 1)) {
|
||||
try {
|
||||
final SelectionKey key = selectionKeysStore[i];
|
||||
@@ -208,6 +208,11 @@ class TcpReplicator extends AbstractChannelReplicator implements Closeable {
|
||||
activeKeys.clear(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
final Attached attachment = (Attached) key.attachment();
|
||||
if (!attachment.hasRemoteHeartbeatInterval)
|
||||
continue;
|
||||
|
||||
try {
|
||||
sendHeartbeatIfRequired(approxTime, key);
|
||||
} catch (Exception e) {
|
||||
@@ -442,6 +447,7 @@ class TcpReplicator extends AbstractChannelReplicator implements Closeable {
|
||||
|
||||
if (remoteIdentifier == STATELESS_CLIENT) {
|
||||
attached.handShakingComplete = true;
|
||||
attached.hasRemoteHeartbeatInterval = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -530,13 +536,14 @@ class TcpReplicator extends AbstractChannelReplicator implements Closeable {
|
||||
final SocketChannel socketChannel = (SocketChannel) key.channel();
|
||||
final Attached attached = (Attached) key.attachment();
|
||||
|
||||
if (attached.entryWriter.hasIncompletWork()) {
|
||||
if (attached.entryWriter.isWorkIncomplete()) {
|
||||
|
||||
boolean completed = attached.entryWriter.doWork();
|
||||
|
||||
if (completed)
|
||||
attached.entryWriter.workCompleted();
|
||||
|
||||
attached.hasRemoteHeartbeatInterval = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -567,7 +574,7 @@ class TcpReplicator extends AbstractChannelReplicator implements Closeable {
|
||||
final SocketChannel socketChannel = (SocketChannel) key.channel();
|
||||
final Attached attached = (Attached) key.attachment();
|
||||
|
||||
if (attached.entryWriter.hasIncompletWork())
|
||||
if (attached.entryWriter.isWorkIncomplete())
|
||||
return;
|
||||
|
||||
try {
|
||||
@@ -820,8 +827,6 @@ class TcpReplicator extends AbstractChannelReplicator implements Closeable {
|
||||
remoteHeartbeatInterval = heartBeatIntervalMillis;
|
||||
hasRemoteHeartbeatInterval = false;
|
||||
remoteModificationIterator = null;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -856,7 +861,7 @@ class TcpReplicator extends AbstractChannelReplicator implements Closeable {
|
||||
entryCallback = new EntryCallback(externalizable, in);
|
||||
}
|
||||
|
||||
public boolean hasIncompletWork() {
|
||||
public boolean isWorkIncomplete() {
|
||||
return uncompletedWork != null;
|
||||
}
|
||||
|
||||
@@ -1068,14 +1073,8 @@ class TcpReplicator extends AbstractChannelReplicator implements Closeable {
|
||||
|
||||
// state is used for both heartbeat and stateless
|
||||
state = out.readByte();
|
||||
|
||||
|
||||
sizeInBytes = out.readUnsignedShort();
|
||||
|
||||
if (state == 0 && sizeInBytes != 0) {
|
||||
int i = 1;
|
||||
}
|
||||
|
||||
// this is the :
|
||||
// -- heartbeat if its 0
|
||||
// -- stateful update if its 1
|
||||
@@ -1211,6 +1210,8 @@ class StatelessServerConnector<K, V> {
|
||||
|
||||
final StatelessChronicleMap.EventId event = StatelessChronicleMap.EventId.values()[eventId];
|
||||
|
||||
System.out.println("got remote event to StatelessChronicleMap");
|
||||
|
||||
switch (event) {
|
||||
|
||||
case LONG_SIZE:
|
||||
@@ -1261,6 +1262,9 @@ class StatelessServerConnector<K, V> {
|
||||
case SIZE:
|
||||
return size(in, out);
|
||||
|
||||
case TO_STRING:
|
||||
return toString(in, out);
|
||||
|
||||
default:
|
||||
throw new IllegalStateException("unsupported event=" + event);
|
||||
|
||||
@@ -1268,8 +1272,18 @@ class StatelessServerConnector<K, V> {
|
||||
|
||||
}
|
||||
|
||||
|
||||
private Work removeWithValue(Bytes in, Bytes out) {
|
||||
boolean result = map.remove(readKey(in), readValue(in));
|
||||
|
||||
K key = readKey(in);
|
||||
V readValue = readValue(in);
|
||||
long sizeLocation = reflectTransactionId(in, out);
|
||||
boolean result;
|
||||
try {
|
||||
result = map.remove(key, readValue);
|
||||
} catch (RuntimeException e) {
|
||||
return sendException(out, sizeLocation, e);
|
||||
}
|
||||
out.writeBoolean(result);
|
||||
return null;
|
||||
}
|
||||
@@ -1279,15 +1293,14 @@ class StatelessServerConnector<K, V> {
|
||||
final K key = readKey(in);
|
||||
V oldValue = readValue(in);
|
||||
V newValue = readValue(in);
|
||||
|
||||
boolean replaced;
|
||||
long sizeLocation = reflectTransactionId(in, out);
|
||||
try {
|
||||
map.replace(key, oldValue, newValue);
|
||||
replaced = map.replace(key, oldValue, newValue);
|
||||
} catch (RuntimeException e) {
|
||||
writeException(e, out);
|
||||
writeSizeAndFlags(sizeLocation, true, out);
|
||||
return null;
|
||||
return sendException(out, sizeLocation, e);
|
||||
}
|
||||
out.writeBoolean(replaced);
|
||||
writeSizeAndFlags(sizeLocation, false, out);
|
||||
return null;
|
||||
}
|
||||
@@ -1295,21 +1308,53 @@ class StatelessServerConnector<K, V> {
|
||||
|
||||
private Work longSize(Bytes in, Bytes out) {
|
||||
long sizeLocation = reflectTransactionId(in, out);
|
||||
out.writeLong(map.longSize());
|
||||
try {
|
||||
out.writeLong(map.longSize());
|
||||
} catch (RuntimeException e) {
|
||||
return sendException(out, sizeLocation, e);
|
||||
}
|
||||
writeSizeAndFlags(sizeLocation, false, out);
|
||||
return null;
|
||||
}
|
||||
|
||||
private Work size(Bytes in, Bytes out) {
|
||||
long sizeLocation = reflectTransactionId(in, out);
|
||||
out.writeInt(map.size());
|
||||
try {
|
||||
out.writeInt(map.size());
|
||||
} catch (RuntimeException e) {
|
||||
return sendException(out, sizeLocation, e);
|
||||
}
|
||||
writeSizeAndFlags(sizeLocation, false, out);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private Work toString(Bytes in, Bytes out) {
|
||||
long sizeLocation = reflectTransactionId(in, out);
|
||||
try {
|
||||
out.writeObject(map.toString());
|
||||
} catch (RuntimeException e) {
|
||||
return sendException(out, sizeLocation, e);
|
||||
}
|
||||
writeSizeAndFlags(sizeLocation, false, out);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private Work sendException(Bytes out, long sizeLocation, RuntimeException e) {
|
||||
writeException(e, out);
|
||||
writeSizeAndFlags(sizeLocation, true, out);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private Work isEmpty(Bytes in, Bytes out) {
|
||||
long sizeLocation = reflectTransactionId(in, out);
|
||||
out.writeBoolean(map.isEmpty());
|
||||
try {
|
||||
out.writeBoolean(map.isEmpty());
|
||||
} catch (RuntimeException e) {
|
||||
return sendException(out, sizeLocation, e);
|
||||
}
|
||||
writeSizeAndFlags(sizeLocation, false, out);
|
||||
return null;
|
||||
}
|
||||
@@ -1317,7 +1362,11 @@ class StatelessServerConnector<K, V> {
|
||||
private Work containsKey(Bytes in, Bytes out) {
|
||||
K k = readKey(in);
|
||||
long sizeLocation = reflectTransactionId(in, out);
|
||||
out.writeBoolean(map.containsKey(k));
|
||||
try {
|
||||
out.writeBoolean(map.containsKey(k));
|
||||
} catch (RuntimeException e) {
|
||||
return sendException(out, sizeLocation, e);
|
||||
}
|
||||
writeSizeAndFlags(sizeLocation, false, out);
|
||||
return null;
|
||||
}
|
||||
@@ -1325,7 +1374,11 @@ class StatelessServerConnector<K, V> {
|
||||
private Work containsValue(Bytes in, Bytes out) {
|
||||
V v = readValue(in);
|
||||
long sizeLocation = reflectTransactionId(in, out);
|
||||
out.writeBoolean(map.containsValue(v));
|
||||
try {
|
||||
out.writeBoolean(map.containsValue(v));
|
||||
} catch (RuntimeException e) {
|
||||
return sendException(out, sizeLocation, e);
|
||||
}
|
||||
writeSizeAndFlags(sizeLocation, false, out);
|
||||
return null;
|
||||
}
|
||||
@@ -1336,9 +1389,7 @@ class StatelessServerConnector<K, V> {
|
||||
try {
|
||||
writeValue(map.get(k), out);
|
||||
} catch (RuntimeException e) {
|
||||
writeException(e, out);
|
||||
writeSizeAndFlags(sizeLocation, true, out);
|
||||
return null;
|
||||
return sendException(out, sizeLocation, e);
|
||||
}
|
||||
writeSizeAndFlags(sizeLocation, false, out);
|
||||
return null;
|
||||
@@ -1349,30 +1400,54 @@ class StatelessServerConnector<K, V> {
|
||||
K k = readKey(in);
|
||||
V v = readValue(in);
|
||||
long sizeLocation = reflectTransactionId(in, out);
|
||||
writeValue(map.put(k, v), out);
|
||||
try {
|
||||
writeValue(map.put(k, v), out);
|
||||
} catch (RuntimeException e) {
|
||||
return sendException(out, sizeLocation, e);
|
||||
}
|
||||
writeSizeAndFlags(sizeLocation, false, out);
|
||||
return null;
|
||||
}
|
||||
|
||||
private Work remove(Bytes in, Bytes out) {
|
||||
final V value = map.remove(readKey(in));
|
||||
K key = readKey(in);
|
||||
long sizeLocation = reflectTransactionId(in, out);
|
||||
writeValue(value, out);
|
||||
|
||||
try {
|
||||
writeValue(map.remove(key), out);
|
||||
} catch (RuntimeException e) {
|
||||
return sendException(out, sizeLocation, e);
|
||||
}
|
||||
|
||||
writeSizeAndFlags(sizeLocation, false, out);
|
||||
return null;
|
||||
|
||||
|
||||
}
|
||||
|
||||
private Work putAll(Bytes in, Bytes out) {
|
||||
map.putAll(readEntries(in));
|
||||
Map<K, V> m = readEntries(in);
|
||||
|
||||
long sizeLocation = reflectTransactionId(in, out);
|
||||
try {
|
||||
map.putAll(m);
|
||||
} catch (RuntimeException e) {
|
||||
return sendException(out, sizeLocation, e);
|
||||
}
|
||||
|
||||
writeSizeAndFlags(sizeLocation, false, out);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private Work clear(Bytes in, Bytes out) {
|
||||
map.clear();
|
||||
|
||||
long sizeLocation = reflectTransactionId(in, out);
|
||||
try {
|
||||
map.clear();
|
||||
} catch (RuntimeException e) {
|
||||
return sendException(out, sizeLocation, e);
|
||||
}
|
||||
writeSizeAndFlags(sizeLocation, false, out);
|
||||
return null;
|
||||
}
|
||||
@@ -1409,7 +1484,14 @@ class StatelessServerConnector<K, V> {
|
||||
|
||||
private Work values(Bytes in, Bytes out) {
|
||||
long sizeLocation = reflectTransactionId(in, out);
|
||||
final Collection<V> values = map.values();
|
||||
final Collection<V> values;
|
||||
try {
|
||||
values = map.values();
|
||||
} catch (RuntimeException e) {
|
||||
return sendException(out, sizeLocation, e);
|
||||
}
|
||||
|
||||
|
||||
out.writeStopBit(values.size());
|
||||
for (final V value : values) {
|
||||
writeValue(value, out);
|
||||
@@ -1421,7 +1503,13 @@ class StatelessServerConnector<K, V> {
|
||||
private Work entrySet(Bytes in, Bytes out) {
|
||||
long sizeLocation = reflectTransactionId(in, out);
|
||||
|
||||
final Set<Map.Entry<K, V>> entries = map.entrySet();
|
||||
final Set<Map.Entry<K, V>> entries;
|
||||
try {
|
||||
|
||||
entries = map.entrySet();
|
||||
} catch (RuntimeException e) {
|
||||
return sendException(out, sizeLocation, e);
|
||||
}
|
||||
out.writeStopBit(entries.size());
|
||||
for (Map.Entry<K, V> e : entries) {
|
||||
writeKey(e.getKey(), out);
|
||||
@@ -1434,7 +1522,15 @@ class StatelessServerConnector<K, V> {
|
||||
K key = readKey(in);
|
||||
V v = readValue(in);
|
||||
long sizeLocation = reflectTransactionId(in, out);
|
||||
writeValue(map.putIfAbsent(key, v), out);
|
||||
V value;
|
||||
|
||||
try {
|
||||
value = map.putIfAbsent(key, v);
|
||||
} catch (RuntimeException e) {
|
||||
return sendException(out, sizeLocation, e);
|
||||
}
|
||||
|
||||
writeValue(value, out);
|
||||
writeSizeAndFlags(sizeLocation, false, out);
|
||||
return null;
|
||||
}
|
||||
@@ -1443,9 +1539,14 @@ class StatelessServerConnector<K, V> {
|
||||
private Work replace(Bytes in, Bytes out) {
|
||||
K k = readKey(in);
|
||||
V v = readValue(in);
|
||||
|
||||
V replaced;
|
||||
long sizeLocation = reflectTransactionId(in, out);
|
||||
map.replace(k, v);
|
||||
try {
|
||||
replaced = map.replace(k, v);
|
||||
} catch (RuntimeException e) {
|
||||
return sendException(out, sizeLocation, e);
|
||||
}
|
||||
writeValue(replaced, out);
|
||||
writeSizeAndFlags(sizeLocation, false, out);
|
||||
return null;
|
||||
}
|
||||
@@ -1455,6 +1556,7 @@ class StatelessServerConnector<K, V> {
|
||||
*
|
||||
* @param key the key of the map
|
||||
*/
|
||||
|
||||
private void writeKey(K key, Bytes out) {
|
||||
keyValueSerializer.writeKey(key, out);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user