mirror of
https://github.com/OpenHFT/Chronicle-Map.git
synced 2021-09-13 01:26:12 +00:00
Fixed several replication bugs; Value -> Data; extracted ReplicableEntry as a superclass of HashReplicableEntry
This commit is contained in:
+9
-9
@@ -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
|
||||
|
||||
+3
-3
@@ -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>
|
||||
|
||||
+2
-3
@@ -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);
|
||||
}
|
||||
+1
-1
@@ -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
+1332
-1199
File diff suppressed because it is too large
Load Diff
+2257
-2152
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 {
|
||||
|
||||
Reference in New Issue
Block a user