Fixed several replication bugs; Value -> Data; extracted ReplicableEntry as a superclass of HashReplicableEntry

This commit is contained in:
leventov
2015-06-15 21:34:45 +03:00
parent f1da352a5d
commit bf20bc98c3
55 changed files with 6708 additions and 6379 deletions
@@ -21,20 +21,20 @@ package net.openhft.chronicle.hash;
import net.openhft.chronicle.algo.hashing.LongHashFunction;
/**
* Defines reasonable defaults for {@code Value}'s {@code equals()}, {@code hashCode()} and
* {@code toString()}. They should be default implementations in the {@code Value} interface itself,
* Defines reasonable defaults for {@code Data}'s {@code equals()}, {@code hashCode()} and
* {@code toString()}. They should be default implementations in the {@code Data} interface itself,
* but Java 8 doesn't allow to override {@code Object}'s methods by default implementations
* in interfaces.
*/
public abstract class AbstractValue<V, T> implements Value<V, T> {
public abstract class AbstractData<V, T> implements Data<V, T> {
/**
* Constructor for use by subclasses.
*/
protected AbstractValue() {}
protected AbstractData() {}
/**
* Computes value's hash code by applying a hash function to {@code Value}'s <i>bytes</i>
* Computes value's hash code by applying a hash function to {@code Data}'s <i>bytes</i>
* representation.
*/
@Override
@@ -43,17 +43,17 @@ public abstract class AbstractValue<V, T> implements Value<V, T> {
}
/**
* Compares {@code Value}s' <i>bytes</i> representations.
* Compares {@code Data}s' <i>bytes</i> representations.
*/
@Override
public boolean equals(Object obj) {
return obj != null &&
obj instanceof Value &&
Value.bytesEquivalent(this, (Value<?, ?>) obj);
obj instanceof Data &&
Data.bytesEquivalent(this, (Data<?, ?>) obj);
}
/**
* Delegates to {@code Value}'s <i>object</i> {@code toString()}.
* Delegates to {@code Data}'s <i>object</i> {@code toString()}.
*/
@Override
public String toString() {
@@ -19,14 +19,11 @@
package net.openhft.chronicle.hash;
import net.openhft.chronicle.map.ChronicleMap;
import net.openhft.chronicle.map.ExternalMapQueryContext;
import net.openhft.chronicle.map.MapEntry;
import net.openhft.chronicle.set.ChronicleSet;
import org.jetbrains.annotations.NotNull;
import java.io.Closeable;
import java.io.File;
import java.io.Serializable;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -63,7 +60,7 @@ public interface ChronicleHash<K, C extends KeyContext<K>, EQC extends ExternalH
@NotNull
EQC queryContext(K key);
@NotNull EQC queryContext(Value<K, ?> key);
@NotNull EQC queryContext(Data<K, ?> key);
/**
* Checks the given predicate on each entry in this {@code ChronicleHash} until all entries
@@ -36,7 +36,7 @@ import org.jetbrains.annotations.Nullable;
* @param <V> type of the accessed objects
* @param <T> type of the handle for bytes access
*/
public interface Value<V, T> {
public interface Data<V, T> {
/**
* Returns access to the value's bytes.
@@ -92,7 +92,7 @@ public interface Value<V, T> {
* Returns "cached" object, generally not eligible for using outside some context, or a block,
* synchronized with locks, or lambda, etc.
*
* If the {@code Value} is object wrapper -- this method just returns this object.
* If the {@code Data} is object wrapper -- this method just returns this object.
*/
V get();
@@ -102,7 +102,7 @@ public interface Value<V, T> {
*/
V getUsing(@Nullable V usingInstance);
static <T1, T2> boolean bytesEquivalent(Value<?, T1> v1, Value<?, T2> v2) {
static <T1, T2> boolean bytesEquivalent(Data<?, T1> v1, Data<?, T2> v2) {
if (v1.size() != v2.size())
return false;
return Access.equivalent(v1.access(), v1.handle(), v1.offset(),
@@ -25,5 +25,5 @@ public interface HashAbsentEntry<K> {
* Returns the key is going to be inserted into the {@code ChronicleHash}.
*/
@NotNull
Value<K, ?> absentKey();
Data<K, ?> absentKey();
}
@@ -19,7 +19,6 @@
package net.openhft.chronicle.hash;
import net.openhft.chronicle.map.MapEntry;
import net.openhft.chronicle.map.MapEntryOperations;
import net.openhft.chronicle.set.SetEntry;
import org.jetbrains.annotations.NotNull;
@@ -41,7 +40,8 @@ public interface HashEntry<K> {
/**
* Returns the entry key.
*/
@NotNull Value<K, ?> key();
@NotNull
Data<K, ?> key();
/**
* Removes the entry from the {@code ChronicleHash}.
@@ -1,11 +1,8 @@
package net.openhft.chronicle.hash;
import net.openhft.chronicle.hash.locks.IllegalInterProcessLockStateException;
import net.openhft.chronicle.hash.locks.InterProcessLock;
import net.openhft.chronicle.hash.locks.InterProcessReadWriteUpdateLock;
import net.openhft.chronicle.map.MapMethods;
import net.openhft.chronicle.map.MapQueryContext;
import net.openhft.chronicle.map.ReturnValue;
/**
* Context of {@link ChronicleHash} operations with <i>individual keys</i>.
@@ -94,9 +91,9 @@ import net.openhft.chronicle.map.ReturnValue;
public interface HashQueryContext<K> extends HashContext<K>, InterProcessReadWriteUpdateLock {
/**
* Returns the queried key as a {@code Value}.
* Returns the queried key as a {@code Data}.
*/
Value<K, ?> queriedKey();
Data<K, ?> queriedKey();
/**
* Returns the entry context, if the entry with the queried key is <i>present</i>
@@ -19,15 +19,14 @@
package net.openhft.chronicle.hash.impl;
import net.openhft.chronicle.bytes.ReadAccess;
import net.openhft.chronicle.hash.AbstractValue;
import net.openhft.chronicle.hash.Value;
import net.openhft.chronicle.hash.AbstractData;
import net.openhft.lang.io.DirectBytes;
import net.openhft.lang.io.DirectStore;
import net.openhft.lang.io.serialization.JDKObjectSerializer;
import static net.openhft.chronicle.hash.impl.JavaLangBytesAccessors.uncheckedBytesAccessor;
public abstract class CopyingInstanceValue<I, T> extends AbstractValue<I, T> {
public abstract class CopyingInstanceData<I, T> extends AbstractData<I, T> {
public static DirectBytes getBuffer(DirectBytes b, long capacity) {
if (b != null) {
@@ -0,0 +1,8 @@
package net.openhft.chronicle.hash.impl.value.instance;
import net.openhft.chronicle.hash.Data;
public interface KeyInitableData<K, T> extends Data<K, T> {
void initKey(K key);
}
@@ -1,8 +0,0 @@
package net.openhft.chronicle.hash.impl.value.instance;
import net.openhft.chronicle.hash.Value;
public interface KeyInitableValue<K, T> extends Value<K, T> {
void initKey(K key);
}
@@ -50,7 +50,7 @@ public final class DefaultEventualConsistencyStrategy {
* @return if the remote operation should be accepted or discarded
*/
public static AcceptanceDecision decideOnRemoteModification(
HashReplicableEntry<?> entry, RemoteOperationContext<?> context) {
ReplicableEntry entry, RemoteOperationContext<?> context) {
long remoteTimestamp = context.remoteTimestamp();
long originTimestamp = entry.originTimestamp();
boolean shouldAccept = remoteTimestamp > originTimestamp ||
@@ -20,9 +20,6 @@ package net.openhft.chronicle.hash.replication;
import net.openhft.chronicle.hash.HashEntry;
public interface HashReplicableEntry<K> extends HashEntry<K> {
byte originIdentifier();
long originTimestamp();
public interface HashReplicableEntry<K> extends HashEntry<K>,ReplicableEntry {
}
@@ -0,0 +1,7 @@
package net.openhft.chronicle.hash.replication;
public interface ReplicableEntry {
byte originIdentifier();
long originTimestamp();
}
@@ -19,7 +19,7 @@
package net.openhft.chronicle.map;
import net.openhft.chronicle.core.util.CloseablesManager;
import net.openhft.chronicle.hash.replication.HashReplicableEntry;
import net.openhft.chronicle.hash.replication.ReplicableEntry;
import net.openhft.chronicle.hash.replication.ThrottlingConfig;
import net.openhft.lang.io.ByteBufferBytes;
import net.openhft.lang.io.Bytes;
@@ -478,7 +478,7 @@ abstract class AbstractChannelReplicator implements Closeable {
}
@Override
public boolean shouldBeIgnored(final HashReplicableEntry<?> entry, final int chronicleId) {
public boolean shouldBeIgnored(final ReplicableEntry entry, final int chronicleId) {
return !externalizable.identifierCheck(entry, chronicleId);
}
@@ -18,10 +18,7 @@
package net.openhft.chronicle.map;
import net.openhft.chronicle.hash.replication.HashReplicableEntry;
import net.openhft.chronicle.hash.replication.ReplicationHub;
import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig;
import net.openhft.chronicle.hash.replication.UdpTransportConfig;
import net.openhft.chronicle.hash.replication.*;
import net.openhft.lang.collection.DirectBitSet;
import net.openhft.lang.collection.SingleThreadedDirectBitSet;
import net.openhft.lang.io.ByteBufferBytes;
@@ -101,7 +98,7 @@ public final class ChannelProvider implements Closeable {
}
@Override
public boolean identifierCheck(@NotNull HashReplicableEntry<?> entry, int chronicleChannel) {
public boolean identifierCheck(@NotNull ReplicableEntry entry, int chronicleChannel) {
channelDataLock.readLock().lock();
try {
@@ -504,7 +501,7 @@ public final class ChannelProvider implements Closeable {
}
@Override
public boolean identifierCheck(@NotNull HashReplicableEntry<?> entry, int chronicleId) {
public boolean identifierCheck(@NotNull ReplicableEntry entry, int chronicleId) {
return true;
}
@@ -108,7 +108,7 @@ public final class ChronicleMapBuilder<K, V> implements
ChronicleHashBuilderImpl<K, ChronicleMap<K, V>, ChronicleMapBuilder<K, V>>,
MapBuilder<ChronicleMapBuilder<K, V>>, Serializable {
static final byte UDP_REPLICATION_MODIFICATION_ITERATOR_ID = (byte) 128;
static final byte UDP_REPLICATION_MODIFICATION_ITERATOR_ID = (byte) 127;
private static final int DEFAULT_KEY_OR_VALUE_SIZE = 120;
private static final long DEFAULT_ENTRIES = 1 << 20;
private static final int MAX_SEGMENTS = (1 << 30);
@@ -1,11 +1,8 @@
package net.openhft.chronicle.map;
import net.openhft.chronicle.hash.Value;
import net.openhft.chronicle.hash.Data;
import net.openhft.chronicle.hash.function.SerializableFunction;
import net.openhft.lang.Jvm;
import org.jetbrains.annotations.NotNull;
import org.xerial.snappy.SnappyInputStream;
import org.xerial.snappy.SnappyOutputStream;
import java.io.File;
import java.io.IOException;
@@ -14,8 +11,6 @@ import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
/**
* Created by daniel on 22/04/15.
@@ -188,7 +183,7 @@ public class FilePerKeyChronicleMap implements ChronicleMap<String, String> {
@NotNull
@Override
public ExternalMapQueryContext<String, String, ?> queryContext(Value<String, ?> key) {
public ExternalMapQueryContext<String, String, ?> queryContext(Data<String, ?> key) {
throw new UnsupportedOperationException();
}
@@ -18,8 +18,8 @@
package net.openhft.chronicle.map;
import net.openhft.chronicle.hash.Data;
import net.openhft.chronicle.hash.HashAbsentEntry;
import net.openhft.chronicle.hash.Value;
import org.jetbrains.annotations.NotNull;
/**
@@ -42,14 +42,14 @@ public interface MapAbsentEntry<K, V> extends HashAbsentEntry<K> {
* value}.
*
* <p>This method is the default implementation for {@link MapEntryOperations#insert(
* MapAbsentEntry, Value)}, which might be customized over the default.
* MapAbsentEntry, Data)}, which might be customized over the default.
*
* @param value the value to insert into the map along with {@link #absentKey() the key}
* @throws IllegalStateException if some locking/state conditions required to perform insertion
* operation are not met
* @see MapEntryOperations#insert(MapAbsentEntry, Value)
* @see MapEntryOperations#insert(MapAbsentEntry, Data)
*/
void doInsert(Value<V, ?> value);
void doInsert(Data<V, ?> value);
/**
* Returns the <i>default</i> (or <i>nil</i>) value, that should be inserted into the map in
@@ -62,5 +62,6 @@ public interface MapAbsentEntry<K, V> extends HashAbsentEntry<K> {
* @return the default value to be inserted into the map
* @see MapEntryOperations#defaultValue(MapAbsentEntry)
*/
@NotNull Value<V, ?> defaultValue();
@NotNull
Data<V, ?> defaultValue();
}
@@ -19,7 +19,7 @@
package net.openhft.chronicle.map;
import net.openhft.chronicle.hash.HashContext;
import net.openhft.chronicle.hash.Value;
import net.openhft.chronicle.hash.Data;
/**
* Context, in which {@link MapEntry MapEntries} are accessed.
@@ -43,14 +43,14 @@ public interface MapContext<K, V, R> extends HashContext<K>, MapEntryOperations<
ChronicleMap<K, V> map();
/**
* Wraps the given value as a {@code Value}. Useful when you need to pass a value
* to some method accepting {@code Value}, for example, {@link MapEntryOperations#replaceValue(
* MapEntry, Value)}, without allocating new objects (i. e. garbage) and {@code ThreadLocals}.
* Wraps the given value as a {@code Data}. Useful when you need to pass a value
* to some method accepting {@code Data}, for example, {@link MapEntryOperations#replaceValue(
* MapEntry, Data)}, without allocating new objects (i. e. garbage) and {@code ThreadLocals}.
*
* <p>The returned {@code Value} object shouldn't outlive this {@code MapContext}.
* <p>The returned {@code Data} object shouldn't outlive this {@code MapContext}.
*
* @param value the value object to wrap
* @return the value as {@code Value}
* @return the value as {@code Data}
*/
Value<V, ?> wrapValueAsValue(V value);
Data<V, ?> wrapValueAsValue(V value);
}
@@ -18,8 +18,8 @@
package net.openhft.chronicle.map;
import net.openhft.chronicle.hash.Data;
import net.openhft.chronicle.hash.HashEntry;
import net.openhft.chronicle.hash.Value;
import org.jetbrains.annotations.NotNull;
/**
@@ -37,20 +37,21 @@ public interface MapEntry<K, V> extends HashEntry<K> {
/**
* Returns the entry value.
*/
@NotNull Value<V, ?> value();
@NotNull
Data<V, ?> value();
/**
* Replaces the entry's value with the given {@code newValue}.
*
* <p>This method is the default implementation for {@link MapEntryOperations#replaceValue(
* MapEntry, Value)}, which might be customized over the default.
* MapEntry, Data)}, which might be customized over the default.
*
* @param newValue the value to be put into the map instead of the {@linkplain #value() current
* value}
* @throws IllegalStateException if some locking/state conditions required to perform replace
* operation are not met
*/
void doReplaceValue(Value<V, ?> newValue);
void doReplaceValue(Data<V, ?> newValue);
/**
* Removes the entry from the map.
@@ -18,7 +18,7 @@
package net.openhft.chronicle.map;
import net.openhft.chronicle.hash.Value;
import net.openhft.chronicle.hash.Data;
import org.jetbrains.annotations.NotNull;
/**
@@ -56,7 +56,7 @@ public interface MapEntryOperations<K, V, R> {
* @throws IllegalStateException if some locking/state conditions required to perform replace
* operation are not met
*/
default R replaceValue(@NotNull MapEntry<K, V> entry, Value<V, ?> newValue) {
default R replaceValue(@NotNull MapEntry<K, V> entry, Data<V, ?> newValue) {
entry.doReplaceValue(newValue);
return null;
}
@@ -70,7 +70,7 @@ public interface MapEntryOperations<K, V, R> {
* @throws IllegalStateException if some locking/state conditions required to perform insertion
* operation are not met
*/
default R insert(@NotNull MapAbsentEntry<K, V> absentEntry, Value<V, ?> value) {
default R insert(@NotNull MapAbsentEntry<K, V> absentEntry, Data<V, ?> value) {
absentEntry.doInsert(value);
return null;
}
@@ -82,7 +82,7 @@ public interface MapEntryOperations<K, V, R> {
*
* @implNote simply delegates to {@link MapAbsentEntry#defaultValue()}.
*/
default Value<V, ?> defaultValue(@NotNull MapAbsentEntry<K, V> absentEntry) {
default Data<V, ?> defaultValue(@NotNull MapAbsentEntry<K, V> absentEntry) {
return absentEntry.defaultValue();
}
}
@@ -18,11 +18,11 @@
package net.openhft.chronicle.map;
import net.openhft.chronicle.hash.Value;
import net.openhft.chronicle.hash.Data;
import java.util.function.BiFunction;
import static net.openhft.chronicle.hash.Value.bytesEquivalent;
import static net.openhft.chronicle.hash.Data.bytesEquivalent;
import static net.openhft.chronicle.map.MapMethodsSupport.returnCurrentValueIfPresent;
import static net.openhft.chronicle.map.MapMethodsSupport.tryReturnCurrentValueIfPresent;
@@ -43,7 +43,7 @@ public interface MapMethods<K, V, R> {
returnCurrentValueIfPresent(q, returnValue);
}
default void put(MapQueryContext<K, V, R> q, Value<V, ?> value, ReturnValue<V> returnValue) {
default void put(MapQueryContext<K, V, R> q, Data<V, ?> value, ReturnValue<V> returnValue) {
// We cannot read the previous value under read lock, because then we will need
// to release the read lock -> acquire write lock, the value might be updated in
// between, that will break ConcurrentMap.put() atomicity guarantee. So, we acquire
@@ -59,7 +59,7 @@ public interface MapMethods<K, V, R> {
}
default void putIfAbsent(MapQueryContext<K, V, R> q,
Value<V, ?> value, ReturnValue<V> returnValue) {
Data<V, ?> value, ReturnValue<V> returnValue) {
if (tryReturnCurrentValueIfPresent(q, returnValue))
return;
// Key is absent
@@ -90,7 +90,7 @@ public interface MapMethods<K, V, R> {
}
}
default boolean remove(MapQueryContext<K, V, R> q, Value<V, ?> value) {
default boolean remove(MapQueryContext<K, V, R> q, Data<V, ?> value) {
// remove(key, value) should find the entry & remove most of the time,
// so don't try to check key presence and value equivalence under read lock first,
// as in putIfAbsent()/acquireUsing(), start with update lock:
@@ -105,7 +105,7 @@ public interface MapMethods<K, V, R> {
}
default void replace(MapQueryContext<K, V, R> q,
Value<V, ?> value, ReturnValue<V> returnValue) {
Data<V, ?> value, ReturnValue<V> returnValue) {
// replace(key, value) should find the key & put the value most of the time,
// so don't try to check key presence under read lock first,
// as in putIfAbsent()/acquireUsing(), start with update lock:
@@ -118,7 +118,7 @@ public interface MapMethods<K, V, R> {
}
default boolean replace(MapQueryContext<K, V, R> q,
Value<V, ?> oldValue, Value<V, ?> newValue) {
Data<V, ?> oldValue, Data<V, ?> newValue) {
// replace(key, old, new) should find the entry & put new value most of the time,
// so don't try to check key presence and value equivalence under read lock first,
// as in putIfAbsent()/acquireUsing(), start with update lock:
@@ -140,23 +140,23 @@ public interface MapMethods<K, V, R> {
V oldValue = entry != null ? entry.value().get() : null;
V newValue = remappingFunction.apply(q.queriedKey().get(), oldValue);
if (newValue != null) {
Value<V, ?> newValueValue = q.wrapValueAsValue(newValue);
Data<V, ?> newValueData = q.wrapValueAsValue(newValue);
if (entry != null) {
q.replaceValue(entry, newValueValue);
q.replaceValue(entry, newValueData);
} else {
q.insert(q.absentEntry(), newValueValue);
q.insert(q.absentEntry(), newValueData);
}
returnValue.returnValue(newValueValue);
returnValue.returnValue(newValueData);
} else if (entry != null) {
q.remove(entry);
}
}
default void merge(MapQueryContext<K, V, R> q, Value<V, ?> value,
default void merge(MapQueryContext<K, V, R> q, Data<V, ?> value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction,
ReturnValue<V> returnValue) {
q.updateLock().lock();
Value<V, ?> newValueValue;
Data<V, ?> newValueData;
MapEntry<K, V> entry = q.entry();
if (entry != null) {
V oldValue = entry.value().get();
@@ -165,12 +165,12 @@ public interface MapMethods<K, V, R> {
q.remove(entry);
return;
}
newValueValue = q.wrapValueAsValue(newValue);
q.replaceValue(entry, newValueValue);
newValueData = q.wrapValueAsValue(newValue);
q.replaceValue(entry, newValueData);
} else {
newValueValue = value;
q.insert(q.absentEntry(), newValueValue);
newValueData = value;
q.insert(q.absentEntry(), newValueData);
}
returnValue.returnValue(newValueValue);
returnValue.returnValue(newValueData);
}
}
@@ -18,7 +18,7 @@
package net.openhft.chronicle.map;
import net.openhft.chronicle.hash.replication.HashReplicableEntry;
import net.openhft.chronicle.hash.replication.ReplicableEntry;
import net.openhft.lang.io.Bytes;
import org.jetbrains.annotations.NotNull;
@@ -144,7 +144,7 @@ public interface Replica extends Closeable {
* @param chronicleId is the channel id used to identify the canonical map or queue
* @return the size of the entry
*/
boolean identifierCheck(@NotNull HashReplicableEntry<?> entry, int chronicleId);
boolean identifierCheck(@NotNull ReplicableEntry entry, int chronicleId);
/**
@@ -213,7 +213,7 @@ public interface Replica extends Closeable {
* @param chronicleId only assigned when clustering
* @return {@code true} if this entry should be ignored
*/
public abstract boolean shouldBeIgnored(final HashReplicableEntry<?> entry, final int chronicleId);
public abstract boolean shouldBeIgnored(final ReplicableEntry entry, final int chronicleId);
}
@@ -20,9 +20,8 @@ package net.openhft.chronicle.map;
import net.openhft.chronicle.hash.KeyContext;
import net.openhft.chronicle.hash.replication.AbstractReplication;
import net.openhft.chronicle.hash.replication.HashReplicableEntry;
import net.openhft.chronicle.hash.replication.ReplicableEntry;
import net.openhft.chronicle.hash.replication.TimeProvider;
import net.openhft.chronicle.hash.serialization.BytesReader;
import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop;
import net.openhft.chronicle.map.impl.*;
import net.openhft.chronicle.map.replication.MapRemoteOperations;
@@ -31,7 +30,6 @@ import net.openhft.lang.Maths;
import net.openhft.lang.collection.ATSDirectBitSet;
import net.openhft.lang.collection.SingleThreadedDirectBitSet;
import net.openhft.lang.io.Bytes;
import net.openhft.lang.threadlocal.ThreadLocalCopies;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -293,7 +291,7 @@ public class ReplicatedChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? sup
}
@Override
public boolean identifierCheck(@NotNull HashReplicableEntry<?> entry, int chronicleId) {
public boolean identifierCheck(@NotNull ReplicableEntry entry, int chronicleId) {
return entry.originIdentifier() == localIdentifier;
}
@@ -337,13 +335,11 @@ public class ReplicatedChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? sup
public void writeExternalEntry(@NotNull Bytes entry,
@NotNull Bytes destination,
int chronicleId) {
final long initialLimit = entry.limit();
final long keySize = keySizeMarshaller.readSize(entry);
final long keyPosition = entry.position();
entry.skip(keySize);
final long keyLimit = entry.position();
final long timeStamp = entry.readLong();
final byte identifier = entry.readByte();
@@ -366,13 +362,14 @@ public class ReplicatedChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? sup
valueSizeMarshaller.writeSize(destination, valueSize);
destination.writeStopBit(timeStamp);
if (identifier == 0)
throw new IllegalStateException("Identifier can't be 0");
destination.writeByte(identifier);
destination.writeBoolean(isDeleted);
// write the key
entry.position(keyPosition);
entry.limit(keyLimit);
destination.write(entry, entry.position(), entry.remaining());
destination.write(entry, entry.position(), keySize);
boolean debugEnabled = LOG.isDebugEnabled();
String message = null;
@@ -390,14 +387,12 @@ public class ReplicatedChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? sup
if (isDeleted)
return;
entry.limit(initialLimit);
entry.position(valuePosition);
// skipping the alignment, as alignment wont work when we send the data over the wire.
alignment.alignPositionAddr(entry);
// writes the value
entry.limit(entry.position() + valueSize);
destination.write(entry, entry.position(), entry.remaining());
destination.write(entry, entry.position(), valueSize);
if (debugEnabled) {
LOG.debug(message + "value=" + entry.toString().trim() + ")");
@@ -515,11 +510,13 @@ public class ReplicatedChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? sup
}
void raiseChange(long segmentIndex, long pos) {
LOG.debug("raise change: id {}, segment {}, pos {}", localIdentifier, segmentIndex, pos);
changesForUpdates.set(combine(segmentIndex, pos));
modificationNotifier.onChange();
}
void dropChange(long segmentIndex, long pos) {
LOG.debug("drop change: id {}, segment {}, pos {}", localIdentifier, segmentIndex, pos);
changesForUpdates.clear(combine(segmentIndex, pos));
}
@@ -568,7 +565,7 @@ public class ReplicatedChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? sup
entryCallback.onBeforeEntry();
final long segmentPos = position & posMask;
context.initEntry(segmentPos);
context.readExistingEntry(segmentPos);
// if the entry should be ignored, we'll move the next entry
if (entryCallback.shouldBeIgnored(context, chronicleId)) {
@@ -589,7 +586,7 @@ public class ReplicatedChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? sup
return success;
}
// if the position was already cleared by another thread
// while we were trying to obtain segment lock (for example, in onRelocation()),
// while we were trying to obtain segment lock (for example, in relocation()),
// go to pick up next (next iteration in while (true) loop)
}
}
@@ -604,7 +601,9 @@ public class ReplicatedChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? sup
for (int i = 0; i < actualSegments; i++) {
final int segmentIndex = i;
c.initTheSegmentIndex(segmentIndex);
c.forEachRemoving(entry -> {
c.forEachReplicableEntry(entry -> {
LOG.debug("Bootstrap entry: id {}, key {}, value {}", localIdentifier,
c.key(), c.value());
MapReplicableEntry re = (MapReplicableEntry) entry;
assert re.originTimestamp() > 0L;
if (re.originIdentifier() >= fromTimeStamp &&
@@ -612,7 +611,6 @@ public class ReplicatedChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? sup
re.originIdentifier() == localIdentifier)) {
raiseChange(segmentIndex, c.pos());
}
return true;
});
}
}
@@ -18,9 +18,9 @@
package net.openhft.chronicle.map;
import net.openhft.chronicle.hash.Value;
import net.openhft.chronicle.hash.Data;
import org.jetbrains.annotations.NotNull;
public interface ReturnValue<V> {
void returnValue(@NotNull Value<V, ?> value);
void returnValue(@NotNull Data<V, ?> value);
}
@@ -20,7 +20,7 @@ package net.openhft.chronicle.map;
import net.openhft.chronicle.bytes.IORuntimeException;
import net.openhft.chronicle.core.util.CloseablesManager;
import net.openhft.chronicle.hash.Value;
import net.openhft.chronicle.hash.Data;
import net.openhft.chronicle.hash.function.SerializableFunction;
import net.openhft.chronicle.hash.impl.util.BuildVersion;
import net.openhft.chronicle.hash.serialization.BytesReader;
@@ -555,7 +555,7 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable, Clon
@NotNull
@Override
public ExternalMapQueryContext<K, V, ?> queryContext(Value<K, ?> key) {
public ExternalMapQueryContext<K, V, ?> queryContext(Data<K, ?> key) {
throw new UnsupportedOperationException("Contexts are not supported by stateless clients");
}
@@ -697,8 +697,11 @@ public final class TcpReplicator<K, V> extends AbstractChannelReplicator impleme
// now we're finished we can get on with reading the entries
attached.remoteModificationIterator.dirtyEntries(attached.remoteBootstrapTimestamp);
reader.entriesFromBuffer(attached, key);
attached.handShakingComplete = true;
try {
reader.entriesFromBuffer(attached, key);
} finally {
attached.handShakingComplete = true;
}
}
}
@@ -19,7 +19,7 @@
package net.openhft.chronicle.map;
import net.openhft.chronicle.hash.KeyContext;
import net.openhft.chronicle.hash.Value;
import net.openhft.chronicle.hash.Data;
import net.openhft.chronicle.hash.impl.VanillaChronicleHash;
import net.openhft.chronicle.hash.serialization.BytesReader;
import net.openhft.chronicle.hash.serialization.SizeMarshaller;
@@ -367,7 +367,7 @@ public class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, ? super
@Override
@NotNull
public QueryContextInterface<K, V, R> queryContext(Value<K, ?> key) {
public QueryContextInterface<K, V, R> queryContext(Data<K, ?> key) {
QueryContextInterface<K, V, R> q = mapContext();
q.initInputKey(key);
return q;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,6 +1,6 @@
package net.openhft.chronicle.map.impl;
import net.openhft.chronicle.hash.Value;
import net.openhft.chronicle.hash.Data;
import net.openhft.chronicle.map.impl.ret.InstanceReturnValue;
import org.jetbrains.annotations.NotNull;
@@ -19,7 +19,7 @@ public final class NullReturnValue implements InstanceReturnValue {
}
@Override
public void returnValue(@NotNull Value value) {
public void returnValue(@NotNull Data value) {
// ignore
}
}
@@ -1,24 +1,24 @@
package net.openhft.chronicle.map.impl;
import net.openhft.chronicle.hash.Value;
import net.openhft.chronicle.hash.impl.value.instance.KeyInitableValue;
import net.openhft.chronicle.hash.Data;
import net.openhft.chronicle.hash.impl.value.instance.KeyInitableData;
import net.openhft.chronicle.map.ExternalMapQueryContext;
import net.openhft.chronicle.map.MapKeyContext;
import net.openhft.chronicle.map.impl.ret.InstanceReturnValue;
import net.openhft.chronicle.map.impl.ret.UsableReturnValue;
import net.openhft.chronicle.map.impl.value.instance.ValueInitableValue;
import net.openhft.chronicle.map.impl.value.instance.ValueInitableData;
public interface QueryContextInterface<K, V, R> extends ExternalMapQueryContext<K, V, R> {
void initInputKey(Value<K, ?> inputKey);
void initInputKey(Data<K, ?> inputKey);
KeyInitableValue<K, ?> inputKeyInstanceValue();
KeyInitableData<K, ?> inputKeyInstanceValue();
InstanceReturnValue<V> defaultReturnValue();
UsableReturnValue<V> usingReturnValue();
ValueInitableValue<V, ?> inputValueInstanceValue();
ValueInitableData<V, ?> inputValueInstanceValue();
MapKeyContext<K, V> deprecatedMapKeyContext();
@@ -28,7 +28,5 @@ public interface QueryContextInterface<K, V, R> extends ExternalMapQueryContext<
boolean theSegmentIndexInit();
void initEntry(long pos);
void clear();
}
@@ -0,0 +1,8 @@
package net.openhft.chronicle.map.impl.value.instance;
import net.openhft.chronicle.hash.Data;
public interface ValueInitableData<V, T> extends Data<V, T> {
void initValue(V value);
}
@@ -1,8 +0,0 @@
package net.openhft.chronicle.map.impl.value.instance;
import net.openhft.chronicle.hash.Value;
public interface ValueInitableValue<V, T> extends Value<V, T> {
void initValue(V value);
}
@@ -19,8 +19,8 @@
package net.openhft.chronicle.map.replication;
import net.openhft.chronicle.hash.AcceptanceDecision;
import net.openhft.chronicle.hash.Value;
import net.openhft.chronicle.hash.replication.HashReplicableEntry;
import net.openhft.chronicle.hash.Data;
import net.openhft.chronicle.hash.replication.ReplicableEntry;
import net.openhft.chronicle.map.MapAbsentEntry;
import static net.openhft.chronicle.hash.AcceptanceDecision.ACCEPT;
@@ -41,15 +41,17 @@ public interface MapRemoteOperations<K, V, R> {
} else {
MapAbsentEntry<K, V> absentEntry = q.absentEntry();
assert absentEntry != null;
if (absentEntry instanceof HashReplicableEntry) {
return decideOnRemoteModification((HashReplicableEntry<?>) absentEntry, q);
if (absentEntry instanceof ReplicableEntry) {
AcceptanceDecision decision =
decideOnRemoteModification((ReplicableEntry) absentEntry, q);
return decision;
} else {
return ACCEPT;
}
}
}
default AcceptanceDecision put(MapRemoteQueryContext<K, V, R> q, Value<V, ?> newValue) {
default AcceptanceDecision put(MapRemoteQueryContext<K, V, R> q, Data<V, ?> newValue) {
MapReplicableEntry<K, V> entry = q.entry();
if (entry != null) {
if (decideOnRemoteModification(entry, q) == ACCEPT) {
@@ -61,8 +63,8 @@ public interface MapRemoteOperations<K, V, R> {
} else {
MapAbsentEntry<K, V> absentEntry = q.absentEntry();
assert absentEntry != null;
if (!(absentEntry instanceof HashReplicableEntry) ||
decideOnRemoteModification((HashReplicableEntry<?>) absentEntry, q) == ACCEPT) {
if (!(absentEntry instanceof ReplicableEntry) ||
decideOnRemoteModification((ReplicableEntry) absentEntry, q) == ACCEPT) {
q.insert(absentEntry, newValue);
return ACCEPT;
} else {
@@ -18,8 +18,8 @@
package net.openhft.chronicle.set;
import net.openhft.chronicle.hash.Data;
import net.openhft.chronicle.hash.KeyContext;
import net.openhft.chronicle.hash.Value;
import net.openhft.chronicle.hash.serialization.internal.DummyValue;
import net.openhft.chronicle.map.ChronicleMap;
import org.jetbrains.annotations.NotNull;
@@ -142,7 +142,7 @@ class SetFromMap<E> extends AbstractSet<E>
@NotNull
@Override
public ExternalSetQueryContext<E, ?> queryContext(Value<E, ?> key) {
public ExternalSetQueryContext<E, ?> queryContext(Data<E, ?> key) {
//TODO
throw new UnsupportedOperationException();
}
@@ -1,7 +1,7 @@
package net.openhft.chronicle.set.replication;
import net.openhft.chronicle.hash.AcceptanceDecision;
import net.openhft.chronicle.hash.replication.HashReplicableEntry;
import net.openhft.chronicle.hash.replication.ReplicableEntry;
import net.openhft.chronicle.set.SetAbsentEntry;
import static net.openhft.chronicle.hash.AcceptanceDecision.ACCEPT;
@@ -22,8 +22,8 @@ public interface SetRemoteOperations<K, R> {
} else {
SetAbsentEntry<K> absentEntry = q.absentEntry();
assert absentEntry != null;
if (absentEntry instanceof HashReplicableEntry) {
return decideOnRemoteModification((HashReplicableEntry<?>) absentEntry, q);
if (absentEntry instanceof ReplicableEntry) {
return decideOnRemoteModification((ReplicableEntry) absentEntry, q);
} else {
return ACCEPT;
}
@@ -41,8 +41,8 @@ public interface SetRemoteOperations<K, R> {
} else {
SetAbsentEntry<K> absentEntry = q.absentEntry();
assert absentEntry != null;
if (!(absentEntry instanceof HashReplicableEntry) ||
decideOnRemoteModification((HashReplicableEntry<?>) absentEntry, q) == ACCEPT) {
if (!(absentEntry instanceof ReplicableEntry) ||
decideOnRemoteModification((ReplicableEntry) absentEntry, q) == ACCEPT) {
q.insert(absentEntry);
return ACCEPT;
} else {