entry = q.entry();
+ * if (entry != null)
+ * q.remove(entry);
* }}
*
* You want to try to acquire some lock heuristically, in order to improve total {@code
@@ -46,14 +51,14 @@ import net.openhft.chronicle.map.MapMethods;
* // For acquireUsing(), it is assumed to be very probable, that the entry is already
* // present in the map, so we will perform the whole acquireUsing() without exclusive locking
* if (q.readLock().tryLock()) {
- * MapEntry, V> entry = q.entry();
+ * MapEntry entry = q.entry();
* if (entry != null) {
* // Entry is present, return
* returnValue.returnValue(entry.value());
* return;
* }
* // Key is absent
- * // Need to unlock, to lock to update lock later. Direct updrage is forbidden.
+ * // Need to unlock, to lock to update lock later. Direct upgrade is forbidden.
* q.readLock().unlock();
* }
* // We are here, either if we:
@@ -63,7 +68,7 @@ import net.openhft.chronicle.map.MapMethods;
* // 2) Seen the entry is absent under the read lock. This means we need to insert
* // the default value into the map. that requires update-level access as well
* q.updateLock().lock();
- * MapEntry, V> entry = q.entry();
+ * MapEntry entry = q.entry();
* if (entry != null) {
* // Entry is present, return
* returnValue.returnValue(entry.value());
@@ -74,7 +79,7 @@ import net.openhft.chronicle.map.MapMethods;
* returnValue.returnValue(q.entry().value());
* }}
* If the default {@link InterProcessLock#lock()} policy of trying to acquire the
- * lock for some time, and then throw {@code RuntimeException}, or need custom timeout:
+ * lock for some time, and then throw {@code RuntimeException}, or need a custom timeout:
* {@code
* try (ExternalHashQueryContext q = hash.queryContext(key)) {
* if (q.writeLock().tryLock(5, TimeUnit.SECONDS)) {
@@ -84,9 +89,53 @@ import net.openhft.chronicle.map.MapMethods;
* }
* }}
*
+ *
+ * {@code HashQueryContext} defines the common pattern for working with {@code ChronicleHash}
+ * contexts: it has a pair of methods, {@link #entry()} and {@link #absentEntry()}, at any moment
+ * one of them returns an (absent) entry context object, another - {@code null}, depending on the
+ * presence of the {@linkplain #queriedKey() queried key} in the {@code ChronicleHash}. Thus,
+ * block of code that uses {@code HashQueryContext} usually has an if-else statement,
+ * with "then" branch for dealing with the present entry, {@code else} branch for dealing with
+ * the absent entry, or vise-versa. For example:
{@code
+ * interface Point {
+ * double getX();
+ * void setX(double x);
+ * double addX(double xAdd);
+ *
+ * double getY();
+ * void setY(double y);
+ * double addY(double yAdd);
+ * }
+ *
+ * Point movePoint(ChronicleMap map, K key, double xMove, double yMove,
+ * Point using) {
+ * // Moves existing point by [xMove, yMove], if absent - assumes the default point is [0, 0].
+ * // Returns the resulting point
+ * try (ExternalMapQueryContext q = map.queryContext(key)) {
+ * Point offHeapPoint;
+ * q.updateLock().lock();
+ * MapEntry entry = q.entry();
+ * if (entry != null) {
+ * // Key is present
+ * offHeapPoint = entry.value().getUsing(using);
+ * } else {
+ * // Key is absent
+ * q.insert(q.absentEntry(), q.defaultValue(q.absentEntry()));
+ * offHeapPoint = q.entry().value().getUsing(using);
+ * }
+ * offHeapPoint.addX(xMove);
+ * offHeapPoint.addY(yMove);
+ * return offHeapPoint;
+ * }
+ * }}
+ *
+ * {@code HashQueryContext} is the base interface defining the structure, but it has no methods
+ * to anything "interesting" with {@code entry()} or {@code absentEntry()}. Use {@link
+ * MapQueryContext} or {@link SetQueryContext} interfaces, which provide access to {@link
+ * MapEntryOperations} and {@link SetEntryOperations} respectively.
*
* @param the hash key type
- * @see ChronicleHash#queryContext(Object)
+ * @see ChronicleHash#queryContext(Object)
*/
public interface HashQueryContext extends HashContext, InterProcessReadWriteUpdateLock {
diff --git a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java
index bdd938afe..e2f488c33 100644
--- a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java
+++ b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java
@@ -16,7 +16,6 @@
package net.openhft.chronicle.hash.impl;
-import net.openhft.chronicle.core.OS;
import net.openhft.chronicle.hash.ChronicleHash;
import net.openhft.chronicle.hash.ExternalHashQueryContext;
import net.openhft.chronicle.hash.KeyContext;
diff --git a/src/main/java/net/openhft/chronicle/hash/AcceptanceDecision.java b/src/main/java/net/openhft/chronicle/hash/replication/AcceptanceDecision.java
similarity index 72%
rename from src/main/java/net/openhft/chronicle/hash/AcceptanceDecision.java
rename to src/main/java/net/openhft/chronicle/hash/replication/AcceptanceDecision.java
index f3c7a9f37..bc122e550 100644
--- a/src/main/java/net/openhft/chronicle/hash/AcceptanceDecision.java
+++ b/src/main/java/net/openhft/chronicle/hash/replication/AcceptanceDecision.java
@@ -16,25 +16,21 @@
* limitations under the License.
*/
-package net.openhft.chronicle.hash;
+package net.openhft.chronicle.hash.replication;
+import net.openhft.chronicle.hash.ChronicleHash;
+import net.openhft.chronicle.hash.replication.DefaultEventualConsistencyStrategy;
import net.openhft.chronicle.map.replication.MapRemoteOperations;
import net.openhft.chronicle.set.replication.SetRemoteOperations;
/**
* Decision, if {@link MapRemoteOperations remote modification operation} should be accepted
- * or discarded.
- * *
- * @see MapRemoteOperations
- * @see SetRemoteOperations
+ * or discarded. Used in {@link DefaultEventualConsistencyStrategy}.
*/
public enum AcceptanceDecision {
/**
* Acceptance decision -- the remote modification operation is applied to the local
- * {@link ChronicleHash} state. This decision should also been returned, when the actual
- * state modification is not needed (for example, remote {@code remove entry} operation, while
- * the entry is not present in the ChronicleHash locally), but the operation is generally
- * considered acceptable.
+ * {@link ChronicleHash} state.
*/
ACCEPT,
diff --git a/src/main/java/net/openhft/chronicle/hash/replication/DefaultEventualConsistencyStrategy.java b/src/main/java/net/openhft/chronicle/hash/replication/DefaultEventualConsistencyStrategy.java
index 94d3b7747..b33cd0e64 100644
--- a/src/main/java/net/openhft/chronicle/hash/replication/DefaultEventualConsistencyStrategy.java
+++ b/src/main/java/net/openhft/chronicle/hash/replication/DefaultEventualConsistencyStrategy.java
@@ -18,14 +18,13 @@
package net.openhft.chronicle.hash.replication;
-import net.openhft.chronicle.hash.AcceptanceDecision;
import net.openhft.chronicle.hash.ChronicleHash;
import net.openhft.chronicle.hash.ChronicleHashBuilder;
import net.openhft.chronicle.map.replication.MapRemoteOperations;
import net.openhft.chronicle.set.replication.SetRemoteOperations;
-import static net.openhft.chronicle.hash.AcceptanceDecision.ACCEPT;
-import static net.openhft.chronicle.hash.AcceptanceDecision.DISCARD;
+import static net.openhft.chronicle.hash.replication.AcceptanceDecision.ACCEPT;
+import static net.openhft.chronicle.hash.replication.AcceptanceDecision.DISCARD;
/**
* Specifies the default eventual consistency strategy for {@link ChronicleHashBuilder#replication(
diff --git a/src/main/java/net/openhft/chronicle/hash/replication/HashReplicableEntry.java b/src/main/java/net/openhft/chronicle/hash/replication/HashReplicableEntry.java
index b23d8dc5a..f2395eb6b 100644
--- a/src/main/java/net/openhft/chronicle/hash/replication/HashReplicableEntry.java
+++ b/src/main/java/net/openhft/chronicle/hash/replication/HashReplicableEntry.java
@@ -20,6 +20,6 @@ package net.openhft.chronicle.hash.replication;
import net.openhft.chronicle.hash.HashEntry;
-public interface HashReplicableEntry extends HashEntry,ReplicableEntry {
+public interface HashReplicableEntry extends HashEntry, ReplicableEntry {
}
diff --git a/src/main/java/net/openhft/chronicle/hash/replication/ReplicableEntry.java b/src/main/java/net/openhft/chronicle/hash/replication/ReplicableEntry.java
index 43eb977a2..46d795aec 100644
--- a/src/main/java/net/openhft/chronicle/hash/replication/ReplicableEntry.java
+++ b/src/main/java/net/openhft/chronicle/hash/replication/ReplicableEntry.java
@@ -1,7 +1,72 @@
package net.openhft.chronicle.hash.replication;
+import net.openhft.chronicle.hash.ChronicleHash;
+import net.openhft.chronicle.hash.ChronicleHashBuilder;
+import net.openhft.chronicle.hash.HashAbsentEntry;
+import net.openhft.chronicle.hash.HashEntry;
+import net.openhft.chronicle.map.ChronicleMap;
+import net.openhft.chronicle.map.Replica;
+import net.openhft.chronicle.map.replication.MapRemoteOperations;
+import net.openhft.chronicle.set.replication.SetRemoteOperations;
+
+/**
+ * Abstracts an in replicated {@link ChronicleHash}. A {@link HashAbsentEntry} might be a {@code
+ * ReplicableEntry} as well as {@link HashEntry}.
+ */
public interface ReplicableEntry {
+ /**
+ * The identifier, associated with this entry. Originally, and by default, this identifier means
+ * the identifier of the {@code ChronicleHash} node on which this entry was updated last.
+ *
+ * When the entry is replicated, this identifier comes to remote nodes as {@link
+ * HashRemoteQueryContext#remoteIdentifier()}.
+ *
+ *
On {@code ChronicleHash} local operations with entries, like {@link ChronicleMap#put(
+ * Object, Object)}, this identifier is overwritten to the own {@code ChronicleHash} {@link
+ * Replica#identifier()}. On remote operations, proxied through {@link MapRemoteOperations} or
+ * {@link SetRemoteOperations}, you are free to overwrite this identifier to any value, using
+ * {@link #updateOrigin(byte, long)} method.
+ *
+ * @return the identifier, associated with this entry
+ */
byte originIdentifier();
+ /**
+ * The timestamp, associated with this entry. Originally, and by default, this timestamp means
+ * the time of the last.
+ *
+ *
When the entry is replicated, this timestamp comes to remote nodes as {@link
+ * HashRemoteQueryContext#remoteTimestamp()}.
+ *
+ *
On {@code ChronicleHash} local operations with entries, like {@link ChronicleMap#put(
+ * Object, Object)}, this timestamp is overwritten using {@linkplain
+ * ChronicleHashBuilder#timeProvider(TimeProvider) the configured time provider}. On remote
+ * operations, proxied through {@link MapRemoteOperations} or {@link SetRemoteOperations},
+ * you are free to overwrite this timestamp by any value, using {@link #updateOrigin(byte, long)
+ * } method.
+ *
+ * @return the timestamp, associated with this entry
+ * @see TimeProvider
+ */
long originTimestamp();
+
+ /**
+ * Overwrite the entry's associated identifier and timestamp. After this call {@link
+ * #originIdentifier()} returns the given {@code newIdentifier} and {@link #originTimestamp()}
+ * returns the given {@code newTimestamp} respectively.
+ *
+ * @param newIdentifier the new identifier for the entry
+ * @param newTimestamp the new timestamp for the entry
+ */
+ void updateOrigin(byte newIdentifier, long newTimestamp);
+
+ /**
+ * Suppress the entry, if it was scheduled to be replicated over to remote Chronicle nodes.
+ */
+ void dropChanged();
+
+ /**
+ * Propagate the entry, schedule it to be replicated over to remote Chronicle nodes.
+ */
+ void raiseChanged();
}
diff --git a/src/main/java/net/openhft/chronicle/map/ChannelFactory.java b/src/main/java/net/openhft/chronicle/map/ChannelFactory.java
deleted file mode 100644
index 5f326f4fd..000000000
--- a/src/main/java/net/openhft/chronicle/map/ChannelFactory.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2014 Higher Frequency Trading
- *
- * http://www.higherfrequencytrading.com
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.openhft.chronicle.map;
-
-/**
- * Created by Rob Austin
- */
-public interface ChannelFactory {
- void createChannel(short channelID);
-}
diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java
index 65ed0c321..998886298 100755
--- a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java
+++ b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java
@@ -28,6 +28,7 @@ import net.openhft.chronicle.hash.replication.*;
import net.openhft.chronicle.hash.serialization.*;
import net.openhft.chronicle.hash.serialization.internal.MetaBytesWriter;
import net.openhft.chronicle.hash.serialization.internal.MetaProvider;
+import net.openhft.chronicle.map.replication.MapRemoteOperations;
import net.openhft.chronicle.set.ChronicleSetBuilder;
import net.openhft.lang.Maths;
import net.openhft.lang.io.Bytes;
@@ -168,6 +169,7 @@ public final class ChronicleMapBuilder implements
MapMethods methods = DefaultSpi.mapMethods();
MapEntryOperations entryOperations = mapEntryOperations();
+ MapRemoteOperations remoteOperations = mapRemoteOperations();
ChronicleMapBuilder(Class keyClass, Class valueClass) {
keyBuilder = new SerializationBuilder<>(keyClass, SerializationBuilder.Role.KEY);
@@ -1495,8 +1497,8 @@ public final class ChronicleMapBuilder implements
}
/**
- * Inject your SPI code around basic {@code ChronicleMap}'s operations with present entries:
- * removing entries and replacing the entries' value.
+ * Inject your SPI code around basic {@code ChronicleMap}'s operations with entries:
+ * removing entries, replacing the entries' value and inserting the new entry.
*
* This affects behaviour of ordinary map.put(), map.remove(), etc. calls, as well as removes
* and replacing values during iterations, remote map calls and
@@ -1520,5 +1522,12 @@ public final class ChronicleMapBuilder implements
this.methods = mapMethods;
return this;
}
+
+ public ChronicleMapBuilder remoteOperations(
+ MapRemoteOperations remoteOperations) {
+ Objects.requireNonNull(remoteOperations);
+ this.remoteOperations = remoteOperations;
+ return this;
+ }
}
diff --git a/src/main/java/net/openhft/chronicle/map/MapContext.java b/src/main/java/net/openhft/chronicle/map/MapContext.java
index c59af1c82..da1710fca 100644
--- a/src/main/java/net/openhft/chronicle/map/MapContext.java
+++ b/src/main/java/net/openhft/chronicle/map/MapContext.java
@@ -22,11 +22,14 @@ import net.openhft.chronicle.hash.HashContext;
import net.openhft.chronicle.hash.Data;
/**
- * Context, in which {@link MapEntry MapEntries} are accessed.
+ * Context, in which {@link MapEntry MapEntries} are accessed. {@code MapContext} allows to access
+ * {@link MapEntryOperations}, configured for the accessed {@link ChronicleMap} via {@link
+ * ChronicleMapBuilder#entryOperations(MapEntryOperations)}. {@code MapContext} implements {@code
+ * MapEntryOperations} by delegation to the configured {@code entryOperations}.
*
* @param the map key type
* @param the map value type
- * @param the return type of {@link MapEntryOperations} specialized for the queried map
+ * @param the return type of {@link MapEntryOperations} specified for the queried map
*/
public interface MapContext extends HashContext, MapEntryOperations {
/**
diff --git a/src/main/java/net/openhft/chronicle/map/MapEntryOperations.java b/src/main/java/net/openhft/chronicle/map/MapEntryOperations.java
index 3eeffaba6..cd94e4706 100644
--- a/src/main/java/net/openhft/chronicle/map/MapEntryOperations.java
+++ b/src/main/java/net/openhft/chronicle/map/MapEntryOperations.java
@@ -19,17 +19,85 @@
package net.openhft.chronicle.map;
import net.openhft.chronicle.hash.Data;
+import net.openhft.chronicle.map.replication.MapRemoteOperations;
import org.jetbrains.annotations.NotNull;
/**
* SPI interface for customizing "low-level" modification operations on {@link ChronicleMap}
- * entries. All {@code ChronicleMap} modifications operate via and instance of this interface:
+ * entries. All {@code ChronicleMap} modifications operate via an instance of this interface:
*
- * - Ordinary query operations: {@code map.put()}, {@code map.compute()}. In fact, the
+ * - Ordinary query operations: {@code map.put()}, {@code map.compute()}, {@code map.remove()}
+ *
+ * - Operations with entry during iterations on the map, or the key/value/entry views,
+ * like {@code iterator.remove()}.
+ * - Remote map operation calls and Replicated {@code ChronicleMap} reconciliation operations:
+ * see {@link MapRemoteOperations}.
*
*
+ * By default {@link #remove}, {@link #insert} and {@link #replaceValue} return {@code null},
+ * but subclasses could return something more sensible, to be used in higher-level SPI interfaces,
+ * namely {@link MapMethods} and {@link MapRemoteOperations}. For example, in bidirectional map
+ * implementation (i. e. a map that preserves the uniqueness of its values as well as that of
+ * its keys), that includes two {@code ChronicleMaps}, the {@code MapEntryOperations}' methods return
+ * type could be used to indicate if we were successful to lock both maps before performing
+ * the update:
{@code
+ * enum DualLockSuccess {SUCCESS, FAIL}
+ *
+ * class BiMapEntryOperations implements MapEntryOperations {
+ * ChronicleMap reverse;
+ *
+ * public void setReverse(ChronicleMap reverse) {
+ * this.reverse = reverse;
+ * }
+ *
+ * @Override
+ * public DualLockSuccess remove(@NotNull MapEntry entry) {
+ * try (ExternalMapQueryContext rq = reverse.queryContext(entry.value())) {
+ * if (!rq.updateLock().tryLock()) {
+ * if (entry.context() instanceof MapQueryContext)
+ * return FAIL;
+ * throw new IllegalStateException("Concurrent modifications to reverse map " +
+ * "during remove during iteration");
+ * }
+ * MapEntry reverseEntry = rq.entry();
+ * if (reverseEntry != null) {
+ * entry.doRemove();
+ * reverseEntry.doRemove();
+ * return SUCCESS;
+ * } else {
+ * throw new IllegalStateException(entry.key() + " maps to " + entry.value() +
+ * ", but in the reverse map this value is absent");
+ * }
+ * }
+ * }
+ *
+ * // ... other methods
+ * }
+ *
+ * class BiMapMethods implements MapMethods {
+ * @Override
+ * public void remove(MapQueryContext q, ReturnValue returnValue) {
+ * while (true) {
+ * q.updateLock().lock();
+ * try {
+ * MapEntry entry = q.entry();
+ * if (entry != null) {
+ * returnValue.returnValue(entry.value());
+ * if (q.remove(entry) == SUCCESS)
+ * return;
+ * }
+ * } finally {
+ * q.readLock().unlock();
+ * }
+ * }
+ * }
+ *
+ * // ... other methods
+ * }}
+ *
* @param the map key type
* @param the map value type
+ * @param methods return type, used for communication between lower- and higher-level SPI
* @see ChronicleMapBuilder#entryOperations(MapEntryOperations)
*/
public interface MapEntryOperations {
@@ -43,6 +111,7 @@ public interface MapEntryOperations {
* @param entry the entry to remove
* @throws IllegalStateException if some locking/state conditions required to perform remove
* operation are not met
+ * @throws RuntimeException if removal was unconditionally unsuccessful due to any reason
*/
default R remove(@NotNull MapEntry entry) {
entry.doRemove();
@@ -52,9 +121,14 @@ public interface MapEntryOperations {
/**
* Replaces the given entry's value with the new one.
*
+ * @implNote default implementation calls {@link MapEntry#doReplaceValue(Data)
+ * entry.doReplaceValue(newValue)} and returns {@code null}.
+ *
* @param entry the entry to replace the value in
* @throws IllegalStateException if some locking/state conditions required to perform replace
* operation are not met
+ * @throws RuntimeException if value replacement was unconditionally unsuccessful due
+ * to any reason
*/
default R replaceValue(@NotNull MapEntry entry, Data newValue) {
entry.doReplaceValue(newValue);
@@ -64,11 +138,13 @@ public interface MapEntryOperations {
/**
* Inserts the new entry into the map, of {@link MapAbsentEntry#absentKey() the key} from
* the given insertion context (absentEntry) and the given {@code value}.
- * Returns {@code true} if the insertion was successful, {@code false} if it was discarded
- * for any reason.
+ *
+ * @implNote default implementation calls {@link MapAbsentEntry#doInsert(Data)
+ * absentEntry.doInsert(value)} and returns {@code null}.
*
* @throws IllegalStateException if some locking/state conditions required to perform insertion
* operation are not met
+ * @throws RuntimeException if insertion was unconditionally unsuccessful due to any reason
*/
default R insert(@NotNull MapAbsentEntry absentEntry, Data value) {
absentEntry.doInsert(value);
diff --git a/src/main/java/net/openhft/chronicle/map/MapMethods.java b/src/main/java/net/openhft/chronicle/map/MapMethods.java
index a6ef293d1..85f6bf114 100644
--- a/src/main/java/net/openhft/chronicle/map/MapMethods.java
+++ b/src/main/java/net/openhft/chronicle/map/MapMethods.java
@@ -21,6 +21,7 @@ package net.openhft.chronicle.map;
import net.openhft.chronicle.hash.Data;
import java.util.function.BiFunction;
+import java.util.function.Function;
import static net.openhft.chronicle.hash.Data.bytesEquivalent;
import static net.openhft.chronicle.map.MapMethodsSupport.returnCurrentValueIfPresent;
@@ -28,6 +29,8 @@ import static net.openhft.chronicle.map.MapMethodsSupport.tryReturnCurrentValueI
/**
* SPI interface for customizing behaviour of the specific Map's methods with individual keys.
+ *
+ * @see ChronicleMapBuilder#mapMethods(MapMethods)
*/
public interface MapMethods {
@@ -38,11 +41,34 @@ public interface MapMethods {
/**
* Backing {@link ChronicleMap#get}, {@link ChronicleMap#getUsing} and
* {@link ChronicleMap#getOrDefault} methods.
+ *
+ * @implNote the default implementation is equivalent to {@code
+ * MapEntry, V> entry = q.entry();
+ * if (entry != null)
+ * returnValue.returnValue(entry.value());
+ * }
*/
default void get(MapQueryContext q, ReturnValue returnValue) {
returnCurrentValueIfPresent(q, returnValue);
}
+ /**
+ * Backing {@link ChronicleMap#put(Object, Object)} method.
+ *
+ * @implNote the default implementation is equivalent to {@code
+ * // 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
+ * // update lock from the start:
+ * q.updateLock().lock();
+ * MapEntry entry = q.entry();
+ * if (entry != null) {
+ * returnValue.returnValue(entry.value());
+ * q.replaceValue(entry, value);
+ * } else {
+ * q.insert(q.absentEntry(), value);
+ * }}
+ */
default void put(MapQueryContext q, Data value, ReturnValue 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
@@ -58,6 +84,29 @@ public interface MapMethods {
}
}
+ /**
+ * Backing {@link ChronicleMap#putIfAbsent(Object, Object)} method.
+ *
+ * @implNote the default implementation is equivalent to {@code
+ * if (q.readLock().tryLock()) {
+ * MapEntry, V> entry = q.entry();
+ * if (entry != null) {
+ * returnValue.returnValue(entry.value());
+ * return;
+ * }
+ * // Key is absent
+ * q.readLock().unlock();
+ * }
+ * q.updateLock().lock();
+ * MapEntry, V> entry = q.entry();
+ * if (entry != null) {
+ * returnValue.returnValue(entry.value());
+ * return;
+ * }
+ * // Key is absent
+ * q.insert(q.absentEntry(), value);
+ * }
+ */
default void putIfAbsent(MapQueryContext q,
Data value, ReturnValue returnValue) {
if (tryReturnCurrentValueIfPresent(q, returnValue))
@@ -66,6 +115,33 @@ public interface MapMethods {
q.insert(q.absentEntry(), value);
}
+ /**
+ * Backing {@link ChronicleMap#acquireUsing(Object, Object)} method.
+ *
+ * @implNote the default implementation is equivalent to {@code
+ * if (q.readLock().tryLock()) {
+ * MapEntry, V> entry = q.entry();
+ * if (entry != null) {
+ * returnValue.returnValue(entry.value());
+ * return;
+ * }
+ * // Key is absent
+ * q.readLock().unlock();
+ * }
+ * q.updateLock().lock();
+ * MapEntry, V> entry = q.entry();
+ * if (entry != null) {
+ * returnValue.returnValue(entry.value());
+ * return;
+ * }
+ * // Key is absent
+ * q.insert(q.absentEntry(), q.defaultValue(q.absentEntry()));
+ * // Meaningful to return the default as newly-inserted, not the default entry itself.
+ * // map.acquireUsing() is most useful for data-value generated values, for which it makes
+ * // big difference -- what bytes to refer. Consider map.acquireUsing(...).incrementValue();
+ * returnValue.returnValue(q.entry().value());
+ * }
+ */
default void acquireUsing(MapQueryContext q, ReturnValue returnValue) {
if (tryReturnCurrentValueIfPresent(q, returnValue))
return;
@@ -73,10 +149,60 @@ public interface MapMethods {
q.insert(q.absentEntry(), q.defaultValue(q.absentEntry()));
// meaningful to return the default as newly-inserted, not the default entry itself.
// map.acquireUsing() is most useful for data-value generated values, for which it makes
- // big difference -- what bytes to refer. map.acquireUsing().incrementValue();
+ // big difference -- what bytes to refer. consider map.acquireUsing(...).incrementValue();
+ // The same reasoning is applied in all same occurrences in this class file
returnValue.returnValue(q.entry().value());
}
+ /**
+ * Backing {@link ChronicleMap#computeIfAbsent(Object, Function)} method.
+ *
+ * @implNote the default implementation is equivalent to {@code
+ * if (q.readLock().tryLock()) {
+ * MapEntry, V> entry = q.entry();
+ * if (entry != null) {
+ * returnValue.returnValue(entry.value());
+ * return;
+ * }
+ * // Key is absent
+ * q.readLock().unlock();
+ * }
+ * q.updateLock().lock();
+ * MapEntry, V> entry = q.entry();
+ * if (entry != null) {
+ * returnValue.returnValue(entry.value());
+ * return;
+ * }
+ * // Key is absent
+ * q.insert(q.absentEntry(), q.wrapValueAsValue(mappingFunction.apply(q.queriedKey().get())));
+ * returnValue.returnValue(q.entry().value());
+ * }
+ */
+ default void computeIfAbsent(MapQueryContext q,
+ Function super K, ? extends V> mappingFunction,
+ ReturnValue returnValue) {
+ if (tryReturnCurrentValueIfPresent(q, returnValue))
+ return;
+ // Key is absent
+ q.insert(q.absentEntry(), q.wrapValueAsValue(mappingFunction.apply(q.queriedKey().get())));
+ returnValue.returnValue(q.entry().value());
+ }
+
+ /**
+ * Backing {@link ChronicleMap#remove(Object)} method.
+ *
+ * @implNote the default implementation is equivalent to {@code
+ * // 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.remove() atomicity guarantee. So, we acquire
+ * // update lock from the start:
+ * q.updateLock().lock();
+ * MapEntry entry = q.entry();
+ * if (entry != null) {
+ * returnValue.returnValue(entry.value());
+ * q.remove(entry);
+ * }}
+ */
default void remove(MapQueryContext q, ReturnValue 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
@@ -90,6 +216,24 @@ public interface MapMethods {
}
}
+ /**
+ * Backing {@link ChronicleMap#remove(Object, Object)} method.
+ *
+ * @implNote the default implementation is equivalent to {@code
+ * // 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:
+ * q.updateLock().lock();
+ * MapEntry entry = q.entry();
+ * if (entry != null && Data.bytesEquivalent(entry.value(), value)) {
+ * q.remove(entry);
+ * return true;
+ * } else {
+ * return false;
+ * }}
+ *
+ * @return if the entry was removed
+ */
default boolean remove(MapQueryContext q, Data 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,
@@ -104,6 +248,20 @@ public interface MapMethods {
}
}
+ /**
+ * Backing {@link ChronicleMap#replace(Object, Object)} method.
+ *
+ * @implNote the default implementation is equivalent to {@code
+ * // 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:
+ * q.updateLock().lock();
+ * MapEntry entry = q.entry();
+ * if (entry != null) {
+ * returnValue.returnValue(entry.value());
+ * q.replaceValue(entry, value);
+ * }}
+ */
default void replace(MapQueryContext q,
Data value, ReturnValue returnValue) {
// replace(key, value) should find the key & put the value most of the time,
@@ -117,6 +275,24 @@ public interface MapMethods {
}
}
+ /**
+ * Backing {@link ChronicleMap#replace(Object, Object, Object)} method.
+ *
+ * @implNote the default implementation is equivalent to {@code
+ * // 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:
+ * q.updateLock().lock();
+ * MapEntry entry = q.entry();
+ * if (entry != null && Data.bytesEquivalent(((MapEntry) entry).value(), oldValue)) {
+ * q.replaceValue(entry, newValue);
+ * return true;
+ * } else {
+ * return false;
+ * }}
+ *
+ * @return if the entry was replaced
+ */
default boolean replace(MapQueryContext q,
Data oldValue, Data newValue) {
// replace(key, old, new) should find the entry & put new value most of the time,
@@ -132,9 +308,30 @@ public interface MapMethods {
}
}
+ /**
+ * Backing {@link ChronicleMap#compute(Object, BiFunction)} method.
+ *
+ * @implNote the default implementation is equivalent to {@code
+ * q.updateLock().lock();
+ * MapEntry entry = q.entry();
+ * V oldValue = entry != null ? entry.value().get() : null;
+ * V newValue = remappingFunction.apply(q.queriedKey().get(), oldValue);
+ * if (newValue != null) {
+ * Data newValueData = q.wrapValueAsValue(newValue);
+ * if (entry != null) {
+ * q.replaceValue(entry, newValueData);
+ * } else {
+ * q.insert(q.absentEntry(), newValueData);
+ * entry = q.entry();
+ * }
+ * returnValue.returnValue(entry.value());
+ * } else if (entry != null) {
+ * q.remove(entry);
+ * }}
+ */
default void compute(MapQueryContext q,
- BiFunction super K, ? super V, ? extends V> remappingFunction,
- ReturnValue returnValue) {
+ BiFunction super K, ? super V, ? extends V> remappingFunction,
+ ReturnValue returnValue) {
q.updateLock().lock();
MapEntry entry = q.entry();
V oldValue = entry != null ? entry.value().get() : null;
@@ -145,16 +342,76 @@ public interface MapMethods {
q.replaceValue(entry, newValueData);
} else {
q.insert(q.absentEntry(), newValueData);
+ entry = q.entry();
+ assert entry != null;
}
- returnValue.returnValue(newValueData);
+ returnValue.returnValue(entry.value());
} else if (entry != null) {
q.remove(entry);
}
}
+ /**
+ * Backing {@link ChronicleMap#computeIfPresent(Object, BiFunction)} method.
+ *
+ * @implNote the default implementation is equivalent to {@code
+ * q.updateLock().lock();
+ * MapEntry entry = q.entry();
+ * if (entry != null) {
+ * V oldValue = entry.value().get();
+ * V newValue = remappingFunction.apply(q.queriedKey().get(), oldValue);
+ * if (newValue != null ) {
+ * q.replaceValue(entry, q.wrapValueAsValue(newValue));
+ * returnValue.returnValue(q.entry().value());
+ * } else {
+ * q.remove(entry);
+ * }
+ * }}
+ */
+ default void computeIfPresent(MapQueryContext q,
+ BiFunction super K, ? super V, ? extends V> remappingFunction,
+ ReturnValue returnValue) {
+ q.updateLock().lock();
+ MapEntry entry = q.entry();
+ if (entry != null) {
+ V oldValue = entry.value().get();
+ V newValue = remappingFunction.apply(q.queriedKey().get(), oldValue);
+ if (newValue != null ) {
+ q.replaceValue(entry, q.wrapValueAsValue(newValue));
+ returnValue.returnValue(q.entry().value());
+ } else {
+ q.remove(entry);
+ }
+ }
+ }
+
+ /**
+ * Backing {@link ChronicleMap#merge(Object, Object, BiFunction)} method.
+ *
+ * @implNote the default implementation is equivalent to {@code
+ * q.updateLock().lock();
+ * Data newValueData;
+ * MapEntry entry = q.entry();
+ * if (entry != null) {
+ * V oldValue = entry.value().get();
+ * V newValue = remappingFunction.apply(oldValue, value.get());
+ * if (newValue == null) {
+ * q.remove(entry);
+ * return;
+ * }
+ * newValueData = q.wrapValueAsValue(newValue);
+ * q.replaceValue(entry, newValueData);
+ * } else {
+ * newValueData = value;
+ * q.insert(q.absentEntry(), newValueData);
+ * entry = q.entry();
+ * }
+ * returnValue.returnValue(entry.value());
+ * }
+ */
default void merge(MapQueryContext q, Data value,
- BiFunction super V, ? super V, ? extends V> remappingFunction,
- ReturnValue returnValue) {
+ BiFunction super V, ? super V, ? extends V> remappingFunction,
+ ReturnValue returnValue) {
q.updateLock().lock();
Data newValueData;
MapEntry entry = q.entry();
@@ -170,7 +427,9 @@ public interface MapMethods {
} else {
newValueData = value;
q.insert(q.absentEntry(), newValueData);
+ entry = q.entry();
+ assert entry != null;
}
- returnValue.returnValue(newValueData);
+ returnValue.returnValue(entry.value());
}
}
diff --git a/src/main/java/net/openhft/chronicle/map/MapQueryContext.java b/src/main/java/net/openhft/chronicle/map/MapQueryContext.java
index 5c8a6bc67..05c534330 100644
--- a/src/main/java/net/openhft/chronicle/map/MapQueryContext.java
+++ b/src/main/java/net/openhft/chronicle/map/MapQueryContext.java
@@ -24,8 +24,10 @@ import org.jetbrains.annotations.Nullable;
/**
* The context of {@link ChronicleMap} operations with individual keys
- * (most: {@code get()}, {@code put()}, etc., opposed to bulk operations). This is the main
- * context type of {@link MapMethods} and {@link MapRemoteOperations}.
+ * (like during {@code get()}, {@code put()}, etc., opposed to bulk operations).
+ * This is the main context type of {@link MapMethods} and {@link MapRemoteOperations}.
+ *
+ *
*
* @param the map key type
* @param the map value type
diff --git a/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java b/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java
index 2eeb5dc2d..3f1e76416 100644
--- a/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java
+++ b/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java
@@ -102,9 +102,7 @@ public class ReplicatedChronicleMap remoteOperations =
- DefaultSpi.mapRemoteOperations();
+ public transient MapRemoteOperations remoteOperations;
transient CompiledReplicatedMapQueryContext remoteOpContext;
transient CompiledReplicatedMapIterationContext remoteItContext;
@@ -113,6 +111,7 @@ public class ReplicatedChronicleMap) builder.remoteOperations;
this.localIdentifier = replication.identifier();
this.bootstrapOnlyLocalEntries = replication.bootstrapOnlyLocalEntries();
@@ -290,6 +289,19 @@ public class ReplicatedChronicleMap 0L;
+ next = modIterSet.nextSetBit(next + 1L)) {
+ try {
+ ModificationIterator modificationIterator = modificationIterators.get((int) next);
+ if (modificationIterator.dropChange(segmentIndex, oldPos))
+ modificationIterator.raiseChange(segmentIndex, newPos);
+ } catch (Exception e) {
+ LOG.error("", e);
+ }
+ }
+ }
+
@Override
public boolean identifierCheck(@NotNull ReplicableEntry entry, int chronicleId) {
return entry.originIdentifier() == localIdentifier;
@@ -515,9 +527,9 @@ public class ReplicatedChronicleMap mappingFunction) {
+ try (QueryContextInterface q = queryContext(key)) {
+ methods.computeIfAbsent(q, mappingFunction, q.defaultReturnValue());
+ return q.defaultReturnValue().returnValue();
+ }
+ }
+
+ @Override
+ public V computeIfPresent(K key,
+ BiFunction super K, ? super V, ? extends V> remappingFunction) {
+ try (QueryContextInterface q = queryContext(key)) {
+ methods.computeIfPresent(q, remappingFunction, q.defaultReturnValue());
+ return q.defaultReturnValue().returnValue();
+ }
+ }
}
diff --git a/src/main/java/net/openhft/chronicle/map/impl/CompiledReplicatedMapIterationContext.java b/src/main/java/net/openhft/chronicle/map/impl/CompiledReplicatedMapIterationContext.java
index 5563c4ca3..9f1415f55 100644
--- a/src/main/java/net/openhft/chronicle/map/impl/CompiledReplicatedMapIterationContext.java
+++ b/src/main/java/net/openhft/chronicle/map/impl/CompiledReplicatedMapIterationContext.java
@@ -49,22 +49,21 @@ import java.util.function.Predicate;
public class CompiledReplicatedMapIterationContext, V, VI, MVI extends MetaBytesInterop, R, T> implements AutoCloseable , HashEntry , InterProcessReadWriteUpdateLock , RemoteOperationContext , ReplicableEntry , MapContext , MapEntry , IterationContextInterface , ReplicatedChronicleMapHolder , ReplicatedIterationContextInterface , MapReplicableEntry {
public void close() {
+ CompiledReplicatedMapIterationContext.this.closePos();
CompiledReplicatedMapIterationContext.this.wrappedValueInstanceValue.closeValue();
CompiledReplicatedMapIterationContext.this.closeReplicationUpdate();
- CompiledReplicatedMapIterationContext.this.closeUsed();
- CompiledReplicatedMapIterationContext.this.closePos();
- CompiledReplicatedMapIterationContext.this.closeKeyOffset();
- CompiledReplicatedMapIterationContext.this.closeAllocatedChunks();
CompiledReplicatedMapIterationContext.this.wrappedValueInstanceValue.closeNext();
+ CompiledReplicatedMapIterationContext.this.closeKeyOffset();
CompiledReplicatedMapIterationContext.this.closeEntryRemovedOnThisIteration();
- CompiledReplicatedMapIterationContext.this.closeTheSegmentIndex();
- CompiledReplicatedMapIterationContext.this.closeKeySize();
CompiledReplicatedMapIterationContext.this.closeHashLookupPos();
- CompiledReplicatedMapIterationContext.this.closeReplicatedChronicleMapHolderImplContextAtIndexInChainDependants();
- CompiledReplicatedMapIterationContext.this.innerWriteLock.closeWriteLockForbiddenUpgradeDependants();
+ CompiledReplicatedMapIterationContext.this.closeUsed();
+ CompiledReplicatedMapIterationContext.this.closeKeySize();
+ CompiledReplicatedMapIterationContext.this.closeTheSegmentIndex();
+ CompiledReplicatedMapIterationContext.this.closeAllocatedChunks();
CompiledReplicatedMapIterationContext.this.closeReplicatedMapSegmentIterationCheckEntryNotRemovedOnThisIterationDependants();
- CompiledReplicatedMapIterationContext.this.closeValueBytesInteropValueMetaInteropDependants();
CompiledReplicatedMapIterationContext.this.closeOwnerThreadHolderCheckAccessingFromOwnerThreadDependants();
+ CompiledReplicatedMapIterationContext.this.closeValueBytesInteropValueMetaInteropDependants();
+ CompiledReplicatedMapIterationContext.this.closeReplicatedChronicleMapHolderImplContextAtIndexInChainDependants();
}
public void incrementModCountGuarded() {
@@ -91,24 +90,24 @@ public class CompiledReplicatedMapIterationContext)(entryBytesAccessor.access(entryBytes)));
+ this.entryKey = new EntryKeyBytesData();
this.wrappedValueInstanceValue = new WrappedValueInstanceData();
- this.innerReadLock = new ReadLock();
+ this.innerWriteLock = new WriteLock();
+ this.owner = Thread.currentThread();
this.copies = ThreadLocalCopies.get();
this.valueInterop = CompiledReplicatedMapIterationContext.this.m().valueInteropProvider.get(CompiledReplicatedMapIterationContext.this.copies, CompiledReplicatedMapIterationContext.this.m().originalValueInterop);
this.valueReader = CompiledReplicatedMapIterationContext.this.m().valueReaderProvider.get(CompiledReplicatedMapIterationContext.this.copies, CompiledReplicatedMapIterationContext.this.m().originalValueReader);
this.keyInterop = CompiledReplicatedMapIterationContext.this.h().keyInteropProvider.get(CompiledReplicatedMapIterationContext.this.copies, CompiledReplicatedMapIterationContext.this.h().originalKeyInterop);
this.keyReader = CompiledReplicatedMapIterationContext.this.h().keyReaderProvider.get(CompiledReplicatedMapIterationContext.this.copies, CompiledReplicatedMapIterationContext.this.h().originalKeyReader);
this.innerUpdateLock = new UpdateLock();
- this.owner = Thread.currentThread();
this.deprecatedMapKeyContextOnIteration = new DeprecatedMapKeyContextOnIteration();
- this.entryBytes = CompiledReplicatedMapIterationContext.this.h().ms.bytes();
- this.entryBytesAccessor = JavaLangBytesAccessors.uncheckedBytesAccessor(entryBytes);
- this.entryBytesAccessHandle = ((T)(entryBytesAccessor.handle(entryBytes)));
- this.entryBytesAccess = ((Access)(entryBytesAccessor.access(entryBytes)));
- this.entryKey = new EntryKeyBytesData();
- this.innerWriteLock = new WriteLock();
- this.dummyValue = new DummyValueZeroData();
this.entryValue = new EntryValueBytesData();
+ this.dummyValue = new DummyValueZeroData();
+ this.innerReadLock = new ReadLock();
}
public CompiledReplicatedMapIterationContext(CompiledReplicatedMapIterationContext c) {
@@ -116,30 +115,72 @@ public class CompiledReplicatedMapIterationContext)(c.m));
+ this.entryBytes = CompiledReplicatedMapIterationContext.this.h().ms.bytes();
+ this.entryBytesAccessor = JavaLangBytesAccessors.uncheckedBytesAccessor(entryBytes);
+ this.entryBytesAccessHandle = ((T)(entryBytesAccessor.handle(entryBytes)));
+ this.entryBytesAccess = ((Access)(entryBytesAccessor.access(entryBytes)));
+ this.entryKey = new EntryKeyBytesData();
this.wrappedValueInstanceValue = new WrappedValueInstanceData();
- this.innerReadLock = new ReadLock();
+ this.innerWriteLock = new WriteLock();
+ this.owner = Thread.currentThread();
this.copies = ThreadLocalCopies.get();
this.valueInterop = CompiledReplicatedMapIterationContext.this.m().valueInteropProvider.get(CompiledReplicatedMapIterationContext.this.copies, CompiledReplicatedMapIterationContext.this.m().originalValueInterop);
this.valueReader = CompiledReplicatedMapIterationContext.this.m().valueReaderProvider.get(CompiledReplicatedMapIterationContext.this.copies, CompiledReplicatedMapIterationContext.this.m().originalValueReader);
this.keyInterop = CompiledReplicatedMapIterationContext.this.h().keyInteropProvider.get(CompiledReplicatedMapIterationContext.this.copies, CompiledReplicatedMapIterationContext.this.h().originalKeyInterop);
this.keyReader = CompiledReplicatedMapIterationContext.this.h().keyReaderProvider.get(CompiledReplicatedMapIterationContext.this.copies, CompiledReplicatedMapIterationContext.this.h().originalKeyReader);
this.innerUpdateLock = new UpdateLock();
- this.owner = Thread.currentThread();
this.deprecatedMapKeyContextOnIteration = new DeprecatedMapKeyContextOnIteration();
- this.entryBytes = CompiledReplicatedMapIterationContext.this.h().ms.bytes();
- this.entryBytesAccessor = JavaLangBytesAccessors.uncheckedBytesAccessor(entryBytes);
- this.entryBytesAccessHandle = ((T)(entryBytesAccessor.handle(entryBytes)));
- this.entryBytesAccess = ((Access)(entryBytesAccessor.access(entryBytes)));
- this.entryKey = new EntryKeyBytesData();
- this.innerWriteLock = new WriteLock();
- this.dummyValue = new DummyValueZeroData();
this.entryValue = new EntryValueBytesData();
+ this.dummyValue = new DummyValueZeroData();
+ this.innerReadLock = new ReadLock();
}
public class DeprecatedMapKeyContextOnIteration implements MapKeyContext {
+ @NotNull
+ private UnsupportedOperationException unsupportedLocks() {
+ return new UnsupportedOperationException("Lock operations are not supported (and not needed!) during iteration");
+ }
+
+ @NotNull
@Override
- public void close() {
- throw new UnsupportedOperationException("close() is not supported during iteration");
+ public InterProcessLock writeLock() {
+ throw unsupportedLocks();
+ }
+
+ @NotNull
+ @Override
+ public InterProcessLock updateLock() {
+ throw unsupportedLocks();
+ }
+
+ @NotNull
+ @Override
+ public InterProcessLock readLock() {
+ throw unsupportedLocks();
+ }
+
+ @Override
+ public V get() {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ return CompiledReplicatedMapIterationContext.this.value().get();
+ }
+
+ @Override
+ public boolean valueEqualTo(V value) {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ return Data.bytesEquivalent(CompiledReplicatedMapIterationContext.this.entryValue, CompiledReplicatedMapIterationContext.this.context().wrapValueAsValue(value));
+ }
+
+ @Override
+ public boolean containsKey() {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ return true;
+ }
+
+ @Override
+ public V getUsing(V usingValue) {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ return CompiledReplicatedMapIterationContext.this.value().getUsing(usingValue);
}
@NotNull
@@ -156,12 +197,6 @@ public class CompiledReplicatedMapIterationContext {
@Override
- public long size() {
- return CompiledReplicatedMapIterationContext.this.m().valueSizeMarshaller.minEncodableSize();
- }
-
- @Override
- public long offset() {
- return 0;
+ public V get() {
+ throw new UnsupportedOperationException();
}
@Override
@@ -259,8 +253,8 @@ public class CompiledReplicatedMapIterationContext {
- @Override
- public T handle() {
- CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
- return CompiledReplicatedMapIterationContext.this.entryBytesAccessHandle;
- }
-
@Override
public ReadAccess access() {
CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
return CompiledReplicatedMapIterationContext.this.entryBytesAccess;
}
+ @Override
+ public T handle() {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ return CompiledReplicatedMapIterationContext.this.entryBytesAccessHandle;
+ }
+
@Override
public long size() {
CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
@@ -297,12 +296,6 @@ public class CompiledReplicatedMapIterationContext {
@@ -709,37 +708,9 @@ public class CompiledReplicatedMapIterationContextT contextAtIndexInChain(int index) {
+ return ((T)(contextChain.get(index)));
}
- public void checkAccessingFromOwnerThread() {
- if ((owner) != (Thread.currentThread())) {
- throw new ConcurrentModificationException("Context shouldn\'t be accessed from multiple threads");
- }
- }
-
- public void closeOwnerThreadHolderCheckAccessingFromOwnerThreadDependants() {
- CompiledReplicatedMapIterationContext.this.closeInterationCheckOnEachPublicOperationCheckOnEachPublicOperationDependants();
+ public void closeReplicatedChronicleMapHolderImplContextAtIndexInChainDependants() {
+ CompiledReplicatedMapIterationContext.this.closeSegmentStagesTryFindInitLocksOfThisSegmentDependants();
}
public MVI valueMetaInterop(V value) {
@@ -1122,109 +1107,16 @@ public class CompiledReplicatedMapIterationContext wrapValueAsValue(V value) {
- CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
- WrappedValueInstanceData wrapped = CompiledReplicatedMapIterationContext.this.wrappedValueInstanceValue;
- wrapped = wrapped.getUnusedWrappedValueGuarded();
- wrapped.initValue(value);
- return wrapped;
- }
-
- @Override
- public R replaceValue(@NotNull
- MapEntry entry, Data newValue) {
- CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
- return CompiledReplicatedMapIterationContext.this.m().entryOperations.replaceValue(entry, newValue);
- }
-
- @Override
- public R remove(@NotNull
- MapEntry entry) {
- CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
- return CompiledReplicatedMapIterationContext.this.m().entryOperations.remove(entry);
- }
-
- @NotNull
- @Override
- public Data value() {
- CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
- return CompiledReplicatedMapIterationContext.this.entryValue;
- }
-
- @Override
- public Data defaultValue(@NotNull
- MapAbsentEntry absentEntry) {
- CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
- return CompiledReplicatedMapIterationContext.this.m().entryOperations.defaultValue(absentEntry);
- }
-
- @NotNull
- @Override
- public Data key() {
- CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
- return CompiledReplicatedMapIterationContext.this.entryKey;
- }
-
- @NotNull
- @Override
- public InterProcessLock updateLock() {
- CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
- return CompiledReplicatedMapIterationContext.this.innerUpdateLock;
- }
-
- @NotNull
- @Override
- public InterProcessLock readLock() {
- CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
- return CompiledReplicatedMapIterationContext.this.innerReadLock;
- }
-
- @Override
- public R insert(@NotNull
- MapAbsentEntry absentEntry, Data value) {
- CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
- return CompiledReplicatedMapIterationContext.this.m().entryOperations.insert(absentEntry, value);
+ public MapContext context() {
+ return CompiledReplicatedMapIterationContext.this;
}
public long entryBytesAccessOffset(long offset) {
return entryBytesAccessor.offset(entryBytes, offset);
}
- public void incrementSegmentEntriesIfNeeded() {
- }
-
@Override
public ReplicatedChronicleMap m() {
return m;
@@ -1235,22 +1127,6 @@ public class CompiledReplicatedMapIterationContextT contextAtIndexInChain(int index) {
- return ((T)(contextChain.get(index)));
- }
-
- public void closeReplicatedChronicleMapHolderImplContextAtIndexInChainDependants() {
- CompiledReplicatedMapIterationContext.this.closeSegmentStagesTryFindInitLocksOfThisSegmentDependants();
- }
-
- private long _MapEntryStages_sizeOfEverythingBeforeValue(long keySize, long valueSize) {
- return (((CompiledReplicatedMapIterationContext.this.m().metaDataBytes) + (CompiledReplicatedMapIterationContext.this.m().keySizeMarshaller.sizeEncodingSize(keySize))) + keySize) + (CompiledReplicatedMapIterationContext.this.m().valueSizeMarshaller.sizeEncodingSize(valueSize));
- }
-
- long sizeOfEverythingBeforeValue(long keySize, long valueSize) {
- return (_MapEntryStages_sizeOfEverythingBeforeValue(keySize, valueSize)) + (ReplicatedChronicleMap.ADDITIONAL_ENTRY_BYTES);
- }
-
public long innerEntrySize(long sizeOfEverythingBeforeValue, long valueSize) {
if (CompiledReplicatedMapIterationContext.this.m().constantlySizedEntry) {
return CompiledReplicatedMapIterationContext.this.m().alignment.alignAddr((sizeOfEverythingBeforeValue + valueSize));
@@ -1261,9 +1137,8 @@ public class CompiledReplicatedMapIterationContext absentEntry, Data value) {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ return CompiledReplicatedMapIterationContext.this.m().entryOperations.insert(absentEntry, value);
+ }
+
@NotNull
@Override
- public MapContext context() {
- return CompiledReplicatedMapIterationContext.this;
+ public InterProcessLock readLock() {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ return CompiledReplicatedMapIterationContext.this.innerReadLock;
}
- public long hashLookupPos = -1;
-
- public boolean hashLookupPosInit() {
- return (this.hashLookupPos) >= 0;
+ @Override
+ public Data defaultValue(@NotNull
+ MapAbsentEntry absentEntry) {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ return CompiledReplicatedMapIterationContext.this.m().entryOperations.defaultValue(absentEntry);
}
- public void initHashLookupPos(long hashLookupPos) {
- this.hashLookupPos = hashLookupPos;
+ @NotNull
+ @Override
+ public Data key() {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ return CompiledReplicatedMapIterationContext.this.entryKey;
}
- public long hashLookupPos() {
- assert this.hashLookupPosInit() : "HashLookupPos should be init";
- return this.hashLookupPos;
+ @NotNull
+ @Override
+ public InterProcessLock writeLock() {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ return CompiledReplicatedMapIterationContext.this.innerWriteLock;
}
- public void closeHashLookupPos() {
- if (!(this.hashLookupPosInit()))
+ @Override
+ public Data wrapValueAsValue(V value) {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ WrappedValueInstanceData wrapped = CompiledReplicatedMapIterationContext.this.wrappedValueInstanceValue;
+ wrapped = wrapped.getUnusedWrappedValueGuarded();
+ wrapped.initValue(value);
+ return wrapped;
+ }
+
+ @Override
+ public R remove(@NotNull
+ MapEntry entry) {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ return CompiledReplicatedMapIterationContext.this.m().entryOperations.remove(entry);
+ }
+
+ @Override
+ public R replaceValue(@NotNull
+ MapEntry entry, Data newValue) {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ return CompiledReplicatedMapIterationContext.this.m().entryOperations.replaceValue(entry, newValue);
+ }
+
+ @NotNull
+ @Override
+ public InterProcessLock updateLock() {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ return CompiledReplicatedMapIterationContext.this.innerUpdateLock;
+ }
+
+ @NotNull
+ @Override
+ public Data value() {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ return CompiledReplicatedMapIterationContext.this.entryValue;
+ }
+
+ public int allocatedChunks = 0;
+
+ public boolean allocatedChunksInit() {
+ return (this.allocatedChunks) != 0;
+ }
+
+ public void initAllocatedChunks(int allocatedChunks) {
+ this.allocatedChunks = allocatedChunks;
+ }
+
+ public int allocatedChunks() {
+ assert this.allocatedChunksInit() : "AllocatedChunks should be init";
+ return this.allocatedChunks;
+ }
+
+ public void closeAllocatedChunks() {
+ if (!(this.allocatedChunksInit()))
return ;
- this.hashLookupPos = -1;
- }
-
- public long keySize = -1;
-
- public boolean keySizeInit() {
- return (this.keySize) >= 0;
- }
-
- public void initKeySize(long keySize) {
- this.keySize = keySize;
- this.closeKeySizeDependants();
- }
-
- public long keySize() {
- assert this.keySizeInit() : "KeySize should be init";
- return this.keySize;
- }
-
- public void closeKeySize() {
- if (!(this.keySizeInit()))
- return ;
-
- this.closeKeySizeDependants();
- this.keySize = -1;
- }
-
- public void closeKeySizeDependants() {
- CompiledReplicatedMapIterationContext.this.entryKey.closeEntryKeyBytesDataSizeDependants();
- CompiledReplicatedMapIterationContext.this.closeReplicatedMapEntryStagesKeyEndDependants();
+ this.allocatedChunks = 0;
}
public int segmentIndex = -1;
@@ -1369,178 +1331,59 @@ public class CompiledReplicatedMapIterationContext 0;
}
- private void initSegHeader() {
- segmentHeaderAddress = (CompiledReplicatedMapIterationContext.this.h().ms.address()) + (CompiledReplicatedMapIterationContext.this.h().segmentHeaderOffset(segmentIndex()));
- segmentHeader = BigSegmentHeader.INSTANCE;
- this.closeSegHeaderDependants();
+ void initSegment() {
+ VanillaChronicleHash, ?, ?, ?, ?> h = CompiledReplicatedMapIterationContext.this.h();
+ long hashLookupOffset = h.segmentOffset(segmentIndex());
+ long freeListOffset = hashLookupOffset + (h.segmentHashLookupOuterSize);
+ freeListBytes.storePositionAndSize(h.ms, freeListOffset, h.segmentFreeListInnerSize);
+ freeList.reuse(freeListBytes);
+ entrySpaceOffset = (freeListOffset + (h.segmentFreeListOuterSize)) + (h.segmentEntrySpaceInnerOffset);
+ this.closeSegmentDependants();
}
- public long segmentHeaderAddress() {
- if (!(this.segHeaderInit()))
- this.initSegHeader();
+ public long entrySpaceOffset() {
+ if (!(this.segmentInit()))
+ this.initSegment();
- return this.segmentHeaderAddress;
+ return this.entrySpaceOffset;
}
- public SegmentHeader segmentHeader() {
- if (!(this.segHeaderInit()))
- this.initSegHeader();
+ public SingleThreadedDirectBitSet freeList() {
+ if (!(this.segmentInit()))
+ this.initSegment();
- return this.segmentHeader;
+ return this.freeList;
}
- public void closeSegHeader() {
- if (!(this.segHeaderInit()))
+ void closeSegment() {
+ if (!(this.segmentInit()))
return ;
- this.closeSegHeaderDependants();
- this.segmentHeader = null;
+ this.closeSegmentDependants();
+ entrySpaceOffset = 0;
}
- public void closeSegHeaderDependants() {
- CompiledReplicatedMapIterationContext.this.closeSegmentStagesTryFindInitLocksOfThisSegmentDependants();
- CompiledReplicatedMapIterationContext.this.closeLocks();
- CompiledReplicatedMapIterationContext.this.innerWriteLock.closeWriteLockLockDependants();
+ public void closeSegmentDependants() {
+ CompiledReplicatedMapIterationContext.this.closeEntryOffset();
}
- public void deleted(long deleted) {
- segmentHeader().deleted(segmentHeaderAddress(), deleted);
- }
-
- public long deleted() {
- return segmentHeader().deleted(segmentHeaderAddress());
- }
-
- public long entries() {
- return segmentHeader().size(segmentHeaderAddress());
- }
-
- public long size() {
- return (entries()) - (deleted());
- }
-
- boolean tryFindInitLocksOfThisSegment(Object thisContext, int index) {
- CompiledReplicatedMapIterationContext c = CompiledReplicatedMapIterationContext.this.contextAtIndexInChain(index);
- if ((((c.segmentHeader()) != null) && ((c.segmentHeaderAddress()) == (segmentHeaderAddress()))) && ((c.rootContextOnThisSegment()) != null)) {
- throw new IllegalStateException("Nested context not implemented yet");
- } else {
- return false;
- }
- }
-
- public void closeSegmentStagesTryFindInitLocksOfThisSegmentDependants() {
- CompiledReplicatedMapIterationContext.this.closeLocks();
- }
-
- int totalReadLockCount;
-
- int totalUpdateLockCount;
-
- int totalWriteLockCount;
-
- public int latestSameThreadSegmentModCount;
-
- public int contextModCount;
-
- CompiledReplicatedMapIterationContext nextNode;
-
- public boolean concurrentSameThreadContexts;
-
- LocalLockState localLockState;
-
- public CompiledReplicatedMapIterationContext rootContextOnThisSegment = null;
-
- public boolean locksInit() {
- return (this.rootContextOnThisSegment) != null;
- }
-
- void initLocks() {
- localLockState = LocalLockState.UNLOCKED;
- int indexOfThisContext = CompiledReplicatedMapIterationContext.this.indexInContextChain;
- for (int i = indexOfThisContext - 1 ; i >= 0 ; i--) {
- if (tryFindInitLocksOfThisSegment(this, i))
- return ;
-
- }
- for (int i = indexOfThisContext + 1, size = CompiledReplicatedMapIterationContext.this.contextChain.size() ; i < size ; i++) {
- if (tryFindInitLocksOfThisSegment(this, i))
- return ;
-
- }
- rootContextOnThisSegment = this;
- concurrentSameThreadContexts = false;
- latestSameThreadSegmentModCount = 0;
- contextModCount = 0;
- nextNode = null;
- totalReadLockCount = 0;
- totalUpdateLockCount = 0;
- totalWriteLockCount = 0;
- this.closeLocksDependants();
- }
-
- public LocalLockState localLockState() {
- if (!(this.locksInit()))
- this.initLocks();
-
- return this.localLockState;
- }
-
- public CompiledReplicatedMapIterationContext rootContextOnThisSegment() {
- if (!(this.locksInit()))
- this.initLocks();
-
- return this.rootContextOnThisSegment;
- }
-
- void closeLocks() {
- if (!(this.locksInit()))
- return ;
-
- this.closeLocksDependants();
- if ((rootContextOnThisSegment) == this) {
- closeRootLocks();
- } else {
- closeNestedLocks();
- }
- localLockState = null;
- rootContextOnThisSegment = null;
- }
-
- public void closeLocksDependants() {
- CompiledReplicatedMapIterationContext.this.innerWriteLock.closeWriteLockLockDependants();
- }
-
- public void entries(long size) {
- segmentHeader().size(segmentHeaderAddress(), size);
- }
-
- long nextPosToSearchFrom() {
- return segmentHeader().nextPosToSearchFrom(segmentHeaderAddress());
- }
-
- public void nextPosToSearchFrom(long nextPosToSearchFrom) {
- segmentHeader().nextPosToSearchFrom(segmentHeaderAddress(), nextPosToSearchFrom);
- }
-
- public void updateNextPosToSearchFrom(long allocated, int chunks) {
- long nextPosToSearchFrom = allocated + chunks;
- if (nextPosToSearchFrom >= (CompiledReplicatedMapIterationContext.this.h().actualChunksPerSegment))
- nextPosToSearchFrom = 0L;
-
- nextPosToSearchFrom(nextPosToSearchFrom);
+ public void moveChange(long oldPos, long newPos) {
+ CompiledReplicatedMapIterationContext.this.m().moveChange(CompiledReplicatedMapIterationContext.this.segmentIndex(), oldPos, newPos);
}
int hashLookupEntrySize;
@@ -1635,25 +1478,8 @@ public class CompiledReplicatedMapIterationContext>> (keyBits())) & (valueMask());
- }
-
- public long maskUnsetKey(long key) {
- return (key &= keyMask()) != (UNSET_KEY) ? key : keyMask();
+ public long step(long pos) {
+ return (pos += hashLookupEntrySize()) <= (capacityMask2()) ? pos : 0L;
}
public void clearHashLookup() {
@@ -1664,37 +1490,69 @@ public class CompiledReplicatedMapIterationContext= 0 ? pos : capacityMask2();
+ }
+
+ public long readEntry(long pos) {
+ return NativeBytes.UNSAFE.getLong(((address()) + pos));
+ }
+
public void putValueVolatile(long pos, long value) {
checkValueForPut(value);
long currentEntry = readEntry(pos);
writeEntryVolatile(pos, currentEntry, key(currentEntry), value);
}
+ public long value(long entry) {
+ return (entry >>> (keyBits())) & (valueMask());
+ }
+
+ public long maskUnsetKey(long key) {
+ return (key &= keyMask()) != (UNSET_KEY) ? key : keyMask();
+ }
+
void writeEntry(long pos, long prevEntry, long anotherEntry) {
long entry = (prevEntry & (~(entryMask()))) | (anotherEntry & (entryMask()));
NativeBytes.UNSAFE.putLong(((address()) + pos), entry);
}
- public long stepBack(long pos) {
- return (pos -= hashLookupEntrySize()) >= 0 ? pos : capacityMask2();
+ void clearEntry(long pos, long prevEntry) {
+ long entry = prevEntry & (~(entryMask()));
+ NativeBytes.UNSAFE.putLong(((address()) + pos), entry);
}
- public long step(long pos) {
- return (pos += hashLookupEntrySize()) <= (capacityMask2()) ? pos : 0L;
+ void forEach(EntryConsumer action) {
+ for (long pos = 0L ; pos <= (capacityMask2()) ; pos += hashLookupEntrySize()) {
+ long entry = readEntry(pos);
+ if (!(empty(entry)))
+ action.accept(key(entry), value(entry));
+
+ }
+ }
+
+ String hashLookupToString() {
+ final StringBuilder sb = new StringBuilder("{");
+ forEach((long key,long value) -> sb.append(key).append('=').append(value).append(','));
+ sb.append('}');
+ return sb.toString();
}
long indexToPos(long index) {
@@ -1705,10 +1563,6 @@ public class CompiledReplicatedMapIterationContext= (CompiledReplicatedMapIterationContext.this.h().actualChunksPerSegment))
+ nextPosToSearchFrom = 0L;
+
+ nextPosToSearchFrom(nextPosToSearchFrom);
+ }
+
+ public long deleted() {
+ return segmentHeader().deleted(segmentHeaderAddress());
+ }
+
+ public long size() {
+ return (entries()) - (deleted());
+ }
+
+ boolean tryFindInitLocksOfThisSegment(Object thisContext, int index) {
+ CompiledReplicatedMapIterationContext c = CompiledReplicatedMapIterationContext.this.contextAtIndexInChain(index);
+ if ((((c.segmentHeader()) != null) && ((c.segmentHeaderAddress()) == (segmentHeaderAddress()))) && ((c.rootContextOnThisSegment()) != null)) {
+ throw new IllegalStateException("Nested context not implemented yet");
+ } else {
+ return false;
}
}
- String hashLookupToString() {
- final StringBuilder sb = new StringBuilder("{");
- forEach((long key,long value) -> sb.append(key).append('=').append(value).append(','));
- sb.append('}');
- return sb.toString();
+ public void closeSegmentStagesTryFindInitLocksOfThisSegmentDependants() {
+ CompiledReplicatedMapIterationContext.this.closeLocks();
}
- long entrySpaceOffset = 0;
-
- MultiStoreBytes freeListBytes = new MultiStoreBytes();
-
- public SingleThreadedDirectBitSet freeList = new SingleThreadedDirectBitSet();
-
- boolean segmentInit() {
- return (entrySpaceOffset) > 0;
+ public void entries(long size) {
+ segmentHeader().size(segmentHeaderAddress(), size);
}
- void initSegment() {
- VanillaChronicleHash, ?, ?, ?, ?> h = CompiledReplicatedMapIterationContext.this.h();
- long hashLookupOffset = h.segmentOffset(segmentIndex());
- long freeListOffset = hashLookupOffset + (h.segmentHashLookupOuterSize);
- freeListBytes.storePositionAndSize(h.ms, freeListOffset, h.segmentFreeListInnerSize);
- freeList.reuse(freeListBytes);
- entrySpaceOffset = (freeListOffset + (h.segmentFreeListOuterSize)) + (h.segmentEntrySpaceInnerOffset);
- this.closeSegmentDependants();
- }
-
- public long entrySpaceOffset() {
- if (!(this.segmentInit()))
- this.initSegment();
-
- return this.entrySpaceOffset;
- }
-
- public SingleThreadedDirectBitSet freeList() {
- if (!(this.segmentInit()))
- this.initSegment();
-
- return this.freeList;
- }
-
- void closeSegment() {
- if (!(this.segmentInit()))
- return ;
-
- this.closeSegmentDependants();
- entrySpaceOffset = 0;
- }
-
- public void closeSegmentDependants() {
- CompiledReplicatedMapIterationContext.this.closeEntryOffset();
- }
-
- public void clearSegment() {
- CompiledReplicatedMapIterationContext.this.innerWriteLock.lock();
- CompiledReplicatedMapIterationContext.this.clearHashLookup();
- freeList().clear();
- nextPosToSearchFrom(0L);
- entries(0L);
- }
-
- public void clear() {
- clearSegment();
+ long nextPosToSearchFrom() {
+ return segmentHeader().nextPosToSearchFrom(segmentHeaderAddress());
}
public void free(long fromPos, int chunks) {
@@ -1842,6 +1713,162 @@ public class CompiledReplicatedMapIterationContext= 0 ; i--) {
+ if (tryFindInitLocksOfThisSegment(this, i))
+ return ;
+
+ }
+ for (int i = indexOfThisContext + 1, size = CompiledReplicatedMapIterationContext.this.contextChain.size() ; i < size ; i++) {
+ if (tryFindInitLocksOfThisSegment(this, i))
+ return ;
+
+ }
+ rootContextOnThisSegment = this;
+ concurrentSameThreadContexts = false;
+ latestSameThreadSegmentModCount = 0;
+ contextModCount = 0;
+ nextNode = null;
+ totalReadLockCount = 0;
+ totalUpdateLockCount = 0;
+ totalWriteLockCount = 0;
+ }
+
+ public LocalLockState localLockState() {
+ if (!(this.locksInit()))
+ this.initLocks();
+
+ return this.localLockState;
+ }
+
+ public CompiledReplicatedMapIterationContext rootContextOnThisSegment() {
+ if (!(this.locksInit()))
+ this.initLocks();
+
+ return this.rootContextOnThisSegment;
+ }
+
+ void closeLocks() {
+ if (!(this.locksInit()))
+ return ;
+
+ if ((rootContextOnThisSegment) == this) {
+ closeRootLocks();
+ } else {
+ closeNestedLocks();
+ }
+ localLockState = null;
+ rootContextOnThisSegment = null;
+ }
+
+ public void clearSegment() {
+ CompiledReplicatedMapIterationContext.this.innerWriteLock.lock();
+ CompiledReplicatedMapIterationContext.this.clearHashLookup();
+ freeList().clear();
+ nextPosToSearchFrom(0L);
+ entries(0L);
+ }
+
+ public void clear() {
+ clearSegment();
+ }
+
+ public void deleted(long deleted) {
+ segmentHeader().deleted(segmentHeaderAddress(), deleted);
+ }
+
+ public long keySize = -1;
+
+ public boolean keySizeInit() {
+ return (this.keySize) >= 0;
+ }
+
+ public void initKeySize(long keySize) {
+ this.keySize = keySize;
+ this.closeKeySizeDependants();
+ }
+
+ public long keySize() {
+ assert this.keySizeInit() : "KeySize should be init";
+ return this.keySize;
+ }
+
+ public void closeKeySize() {
+ if (!(this.keySizeInit()))
+ return ;
+
+ this.closeKeySizeDependants();
+ this.keySize = -1;
+ }
+
+ public void closeKeySizeDependants() {
+ CompiledReplicatedMapIterationContext.this.entryKey.closeEntryKeyBytesDataSizeDependants();
+ CompiledReplicatedMapIterationContext.this.closeReplicatedMapEntryStagesKeyEndDependants();
+ }
+
+ boolean used;
+
+ public boolean usedInit() {
+ return used;
+ }
+
+ public void initUsed(boolean used) {
+ this.used = used;
+ }
+
+ void closeUsed() {
+ if (!(this.usedInit()))
+ return ;
+
+ used = false;
+ }
+
+ public long hashLookupPos = -1;
+
+ public boolean hashLookupPosInit() {
+ return (this.hashLookupPos) >= 0;
+ }
+
+ public void initHashLookupPos(long hashLookupPos) {
+ this.hashLookupPos = hashLookupPos;
+ }
+
+ public long hashLookupPos() {
+ assert this.hashLookupPosInit() : "HashLookupPos should be init";
+ return this.hashLookupPos;
+ }
+
+ public void closeHashLookupPos() {
+ if (!(this.hashLookupPosInit()))
+ return ;
+
+ this.hashLookupPos = -1;
+ }
+
public boolean entryRemovedOnThisIteration = false;
boolean entryRemovedOnThisIterationInit() {
@@ -1859,28 +1886,6 @@ public class CompiledReplicatedMapIterationContext= 0;
+ }
+
+ void initReplicationState() {
+ replicationBytesOffset = keyEnd();
+ }
+
+ public long replicationBytesOffset() {
+ if (!(this.replicationStateInit()))
+ this.initReplicationState();
+
+ return this.replicationBytesOffset;
+ }
+
+ public void closeReplicationState() {
+ if (!(this.replicationStateInit()))
+ return ;
+
+ this.replicationBytesOffset = -1;
+ }
+
+ private long identifierOffset() {
+ return (replicationBytesOffset()) + 8L;
+ }
+
+ byte identifier() {
+ return entryBytesAccess.readByte(entryBytesAccessHandle, identifierOffset());
+ }
+
+ @Override
+ public byte originIdentifier() {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ return identifier();
+ }
+
+ private long timestampOffset() {
+ return replicationBytesOffset();
+ }
+
+ public long timestamp() {
+ return entryBytesAccess.readLong(entryBytesAccessHandle, timestampOffset());
+ }
+
+ @Override
+ public long originTimestamp() {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ return timestamp();
+ }
+
+ void updateReplicationState(long timestamp, byte identifier) {
+ entryBytes.position(replicationBytesOffset());
+ entryBytes.writeLong(timestamp);
+ entryBytes.writeByte(identifier);
+ }
+
+ public void updatedReplicationStateOnAbsentEntry() {
+ if (!(CompiledReplicatedMapIterationContext.this.replicationUpdateInit())) {
+ CompiledReplicatedMapIterationContext.this.innerWriteLock.lock();
+ updateReplicationState(CompiledReplicatedMapIterationContext.this.m().timeProvider.currentTime(), CompiledReplicatedMapIterationContext.this.m().identifier());
+ }
+ }
+
+ public void updatedReplicationStateOnPresentEntry() {
+ if (!(CompiledReplicatedMapIterationContext.this.replicationUpdateInit())) {
+ CompiledReplicatedMapIterationContext.this.innerWriteLock.lock();
+ long timestamp;
+ if ((identifier()) != (CompiledReplicatedMapIterationContext.this.m().identifier())) {
+ timestamp = Math.max(((timestamp()) + 1), CompiledReplicatedMapIterationContext.this.m().timeProvider.currentTime());
+ } else {
+ timestamp = CompiledReplicatedMapIterationContext.this.m().timeProvider.currentTime();
+ }
+ updateReplicationState(timestamp, CompiledReplicatedMapIterationContext.this.m().identifier());
+ }
+ }
+
+ @Override
+ public void updateOrigin(byte newIdentifier, long newTimestamp) {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ CompiledReplicatedMapIterationContext.this.innerWriteLock.lock();
+ updateReplicationState(newTimestamp, newIdentifier);
+ }
+
+ private long entryDeletedOffset() {
+ return (replicationBytesOffset()) + 9L;
+ }
+
+ public boolean entryDeleted() {
+ return entryBytesAccess.readBoolean(entryBytesAccessHandle, entryDeletedOffset());
+ }
+
+ private boolean _MapSegmentIteration_entryIsPresent() {
+ return true;
+ }
+
+ public boolean entryIsPresent() {
+ return !(CompiledReplicatedMapIterationContext.this.entryDeleted());
+ }
+
+ public void writeEntryDeleted() {
+ entryBytesAccess.writeBoolean(entryBytesAccessHandle, entryDeletedOffset(), true);
+ }
+
+ public void writeEntryPresent() {
+ entryBytesAccess.writeBoolean(entryBytesAccessHandle, entryDeletedOffset(), false);
}
private long _MapEntryStages_countValueSizeOffset() {
@@ -2019,22 +2133,6 @@ public class CompiledReplicatedMapIterationContext value) {
- value.writeTo(entryBytesAccess, entryBytesAccessHandle, entryBytesAccessOffset(valueOffset()));
- }
-
- public void initValue(Data, ?> value) {
- entryBytes.position(valueSizeOffset());
- initValSize(value.size());
- writeValue(value);
- }
-
- public void initValueWithoutSize(Data, ?> value, long oldValueSizeOffset, long oldValueSize, long oldValueOffset) {
- assert oldValueSize == (value.size());
- initValSizeEqualToOld(oldValueSizeOffset, oldValueSize, oldValueOffset);
- writeValue(value);
- }
-
private long _HashEntryStages_entryEnd() {
return keyEnd();
}
@@ -2047,114 +2145,74 @@ public class CompiledReplicatedMapIterationContext= 0;
+ public void writeValue(Data, ?> value) {
+ value.writeTo(entryBytesAccess, entryBytesAccessHandle, entryBytesAccessOffset(valueOffset()));
}
- void initReplicationState() {
- replicationBytesOffset = keyEnd();
- this.closeReplicationStateDependants();
+ public void initValueWithoutSize(Data, ?> value, long oldValueSizeOffset, long oldValueSize, long oldValueOffset) {
+ assert oldValueSize == (value.size());
+ initValSizeEqualToOld(oldValueSizeOffset, oldValueSize, oldValueOffset);
+ writeValue(value);
}
- public long replicationBytesOffset() {
- if (!(this.replicationStateInit()))
- this.initReplicationState();
-
- return this.replicationBytesOffset;
+ public void initValue(Data, ?> value) {
+ entryBytes.position(valueSizeOffset());
+ initValSize(value.size());
+ writeValue(value);
}
- public void closeReplicationState() {
- if (!(this.replicationStateInit()))
+ public long innerRemoteTimestamp;
+
+ public byte innerRemoteIdentifier = ((byte)(0));
+
+ public boolean replicationUpdateInit() {
+ return (this.innerRemoteIdentifier) != ((byte)(0));
+ }
+
+ public void initReplicationUpdate(long timestamp, byte identifier) {
+ innerRemoteTimestamp = timestamp;
+ if (identifier == 0)
+ throw new IllegalStateException("identifier can\'t be 0");
+
+ innerRemoteIdentifier = identifier;
+ }
+
+ public byte innerRemoteIdentifier() {
+ assert this.replicationUpdateInit() : "ReplicationUpdate should be init";
+ return this.innerRemoteIdentifier;
+ }
+
+ public long innerRemoteTimestamp() {
+ assert this.replicationUpdateInit() : "ReplicationUpdate should be init";
+ return this.innerRemoteTimestamp;
+ }
+
+ public void closeReplicationUpdate() {
+ if (!(this.replicationUpdateInit()))
return ;
- this.closeReplicationStateDependants();
- this.replicationBytesOffset = -1;
+ this.innerRemoteIdentifier = ((byte)(0));
}
- public void closeReplicationStateDependants() {
- CompiledReplicatedMapIterationContext.this.closeReplicatedMapEntryStagesTimestampOffsetDependants();
- CompiledReplicatedMapIterationContext.this.closeReplicatedMapEntryStagesUpdateReplicationStateDependants();
- CompiledReplicatedMapIterationContext.this.closeReplicatedMapEntryStagesIdentifierOffsetDependants();
+ @Override
+ public byte remoteIdentifier() {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ return innerRemoteIdentifier();
}
- private long entryDeletedOffset() {
- return (replicationBytesOffset()) + 9L;
- }
-
- public boolean entryDeleted() {
- return entryBytesAccess.readBoolean(entryBytesAccessHandle, entryDeletedOffset());
- }
-
- private boolean _MapSegmentIteration_entryIsPresent() {
+ private boolean testTimeStampInSensibleRange() {
+ if ((CompiledReplicatedMapIterationContext.this.m().timeProvider) == (TimeProvider.SYSTEM)) {
+ long currentTime = TimeProvider.SYSTEM.currentTime();
+ assert (Math.abs((currentTime - (timestamp())))) <= 100000000 : "unrealistic timestamp: " + (timestamp());
+ assert (Math.abs((currentTime - (CompiledReplicatedMapIterationContext.this.innerRemoteTimestamp())))) <= 100000000 : "unrealistic innerRemoteTimestamp: " + (CompiledReplicatedMapIterationContext.this.innerRemoteTimestamp());
+ }
return true;
}
- public boolean entryIsPresent() {
- return !(CompiledReplicatedMapIterationContext.this.entryDeleted());
- }
-
- public void writeEntryDeleted() {
- entryBytesAccess.writeBoolean(entryBytesAccessHandle, entryDeletedOffset(), true);
- }
-
- public void writeEntryPresent() {
- entryBytesAccess.writeBoolean(entryBytesAccessHandle, entryDeletedOffset(), false);
- }
-
- private long timestampOffset() {
- return replicationBytesOffset();
- }
-
- public void closeReplicatedMapEntryStagesTimestampOffsetDependants() {
- CompiledReplicatedMapIterationContext.this.closeReplicatedMapEntryStagesTimestampDependants();
- }
-
- public long timestamp() {
- return entryBytesAccess.readLong(entryBytesAccessHandle, timestampOffset());
- }
-
- public void closeReplicatedMapEntryStagesTimestampDependants() {
- CompiledReplicatedMapIterationContext.this.closeUpdatedReplicationState();
- }
-
@Override
- public long originTimestamp() {
+ public long remoteTimestamp() {
CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
- return timestamp();
- }
-
- void updateReplicationState(long timestamp, byte identifier) {
- entryBytes.position(replicationBytesOffset());
- entryBytes.writeLong(timestamp);
- entryBytes.writeByte(identifier);
- }
-
- public void closeReplicatedMapEntryStagesUpdateReplicationStateDependants() {
- CompiledReplicatedMapIterationContext.this.closeUpdatedReplicationState();
- }
-
- private long identifierOffset() {
- return (replicationBytesOffset()) + 8L;
- }
-
- public void closeReplicatedMapEntryStagesIdentifierOffsetDependants() {
- CompiledReplicatedMapIterationContext.this.closeReplicatedMapEntryStagesIdentifierDependants();
- }
-
- byte identifier() {
- return entryBytesAccess.readByte(entryBytesAccessHandle, identifierOffset());
- }
-
- public void closeReplicatedMapEntryStagesIdentifierDependants() {
- CompiledReplicatedMapIterationContext.this.closeUpdatedReplicationState();
- }
-
- @Override
- public byte originIdentifier() {
- CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
- return identifier();
+ return innerRemoteTimestamp();
}
public long pos = -1;
@@ -2189,16 +2247,11 @@ public class CompiledReplicatedMapIterationContext newValue) {
- return ((valueSizeOffset()) + (CompiledReplicatedMapIterationContext.this.m().valueSizeMarshaller.sizeEncodingSize(newValue.size()))) - (keySizeOffset());
- }
-
- public void copyExistingEntry(long newPos, long bytesToCopy) {
- long oldKeySizeOffset = keySizeOffset();
- long oldKeyOffset = keyOffset();
- initPos(newPos);
- initKeyOffset(((keySizeOffset()) + (oldKeyOffset - oldKeySizeOffset)));
- Access.copy(entryBytesAccess, entryBytesAccessHandle, entryBytesAccessOffset(oldKeySizeOffset), entryBytesAccess, entryBytesAccessHandle, entryBytesAccessOffset(keySizeOffset()), bytesToCopy);
- }
-
- public void initEntryAndKeyCopying(long entrySize, long bytesToCopy) {
- initAllocatedChunks(CompiledReplicatedMapIterationContext.this.h().inChunks(entrySize));
- CompiledReplicatedMapIterationContext.this.copyExistingEntry(CompiledReplicatedMapIterationContext.this.alloc(allocatedChunks()), bytesToCopy);
- incrementSegmentEntriesIfNeeded();
- }
-
long entrySize() {
return (entryEnd()) - (keySizeOffset());
}
@@ -2286,33 +2321,28 @@ public class CompiledReplicatedMapIterationContext value) {
- initValue(value);
- freeExtraAllocatedChunks();
- CompiledReplicatedMapIterationContext.this.putValueVolatile(CompiledReplicatedMapIterationContext.this.hashLookupPos(), pos());
- }
-
public void innerRemoveEntryExceptHashLookupUpdate() {
CompiledReplicatedMapIterationContext.this.free(pos(), entrySizeInChunks());
CompiledReplicatedMapIterationContext.this.entries(((CompiledReplicatedMapIterationContext.this.entries()) - 1L));
CompiledReplicatedMapIterationContext.this.incrementModCountGuarded();
}
- public void writeNewEntry(long pos, Data, ?> key) {
- initPos(pos);
- initKeySize(key.size());
- entryBytes.position(keySizeOffset());
- CompiledReplicatedMapIterationContext.this.h().keySizeMarshaller.writeSize(entryBytes, keySize());
- initKeyOffset(entryBytes.position());
- key.writeTo(entryBytesAccessor, entryBytes, keyOffset());
+ public void copyExistingEntry(long newPos, long bytesToCopy) {
+ long oldKeySizeOffset = keySizeOffset();
+ long oldKeyOffset = keyOffset();
+ initPos(newPos);
+ initKeyOffset(((keySizeOffset()) + (oldKeyOffset - oldKeySizeOffset)));
+ Access.copy(entryBytesAccess, entryBytesAccessHandle, entryBytesAccessOffset(oldKeySizeOffset), entryBytesAccess, entryBytesAccessHandle, entryBytesAccessOffset(keySizeOffset()), bytesToCopy);
+ }
+
+ public void initEntryAndKeyCopying(long entrySize, long bytesToCopy) {
+ initAllocatedChunks(CompiledReplicatedMapIterationContext.this.h().inChunks(entrySize));
+ CompiledReplicatedMapIterationContext.this.copyExistingEntry(CompiledReplicatedMapIterationContext.this.alloc(allocatedChunks()), bytesToCopy);
+ incrementSegmentEntriesIfNeeded();
+ }
+
+ public long newSizeOfEverythingBeforeValue(Data newValue) {
+ return ((valueSizeOffset()) + (CompiledReplicatedMapIterationContext.this.m().valueSizeMarshaller.sizeEncodingSize(newValue.size()))) - (keySizeOffset());
}
public void readExistingEntry(long pos) {
@@ -2389,101 +2419,20 @@ public class CompiledReplicatedMapIterationContext newValue, long newSizeOfEverythingBeforeValue) {
- CompiledReplicatedMapIterationContext.this.free(pos(), entrySizeInChunks());
- long entrySize = innerEntrySize(newSizeOfEverythingBeforeValue, newValue.size());
- CompiledReplicatedMapIterationContext.this.initEntryAndKeyCopying(entrySize, ((valueSizeOffset()) - (keySizeOffset())));
- writeValueAndPutPos(newValue);
+ public void writeNewEntry(long pos, Data, ?> key) {
+ initPos(pos);
+ initKeySize(key.size());
+ entryBytes.position(keySizeOffset());
+ CompiledReplicatedMapIterationContext.this.h().keySizeMarshaller.writeSize(entryBytes, keySize());
+ initKeyOffset(entryBytes.position());
+ key.writeTo(entryBytesAccessor, entryBytes, keyOffset());
}
- protected void relocation(Data newValue, long newSizeOfEverythingBeforeValue) {
- CompiledReplicatedMapIterationContext.this.dropChange();
- _MapEntryStages_relocation(newValue, newSizeOfEverythingBeforeValue);
- }
-
- public void innerDefaultReplaceValue(Data newValue) {
- assert CompiledReplicatedMapIterationContext.this.innerUpdateLock.isHeldByCurrentThread();
- boolean newValueSizeIsDifferent = (newValue.size()) != (this.valueSize());
- if (newValueSizeIsDifferent) {
- long newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue);
- long entryStartOffset = keySizeOffset();
- VanillaChronicleMap, ?, ?, ?, ?, ?, ?> m = CompiledReplicatedMapIterationContext.this.m();
- long newValueOffset = m.alignment.alignAddr((entryStartOffset + newSizeOfEverythingBeforeValue));
- long newEntrySize = (newValueOffset + (newValue.size())) - entryStartOffset;
- int newSizeInChunks = m.inChunks(newEntrySize);
- newValueDoesNotFit : if (newSizeInChunks > (entrySizeInChunks())) {
- if (newSizeInChunks > (m.maxChunksPerEntry)) {
- throw new IllegalArgumentException(((((("Value too large: " + "entry takes ") + newSizeInChunks) + " chunks, ") + (m.maxChunksPerEntry)) + " is maximum."));
- }
- if (CompiledReplicatedMapIterationContext.this.freeList().allClear(((pos()) + (entrySizeInChunks())), ((pos()) + newSizeInChunks))) {
- CompiledReplicatedMapIterationContext.this.freeList().set(((pos()) + (entrySizeInChunks())), ((pos()) + newSizeInChunks));
- break newValueDoesNotFit;
- }
- relocation(newValue, newSizeOfEverythingBeforeValue);
- return ;
- } else if (newSizeInChunks < (entrySizeInChunks())) {
- CompiledReplicatedMapIterationContext.this.freeList().clear(((pos()) + newSizeInChunks), ((pos()) + (entrySizeInChunks())));
- }
+ public final void freeExtraAllocatedChunks() {
+ if (((!(CompiledReplicatedMapIterationContext.this.m().constantlySizedEntry)) && (CompiledReplicatedMapIterationContext.this.m().couldNotDetermineAlignmentBeforeAllocation)) && ((entrySizeInChunks()) < (CompiledReplicatedMapIterationContext.this.allocatedChunks()))) {
+ CompiledReplicatedMapIterationContext.this.free(((pos()) + (entrySizeInChunks())), ((CompiledReplicatedMapIterationContext.this.allocatedChunks()) - (entrySizeInChunks())));
} else {
- }
- CompiledReplicatedMapIterationContext.this.innerWriteLock.lock();
- if (newValueSizeIsDifferent) {
- initValue(newValue);
- } else {
- writeValue(newValue);
- }
- CompiledReplicatedMapIterationContext.this.putValueVolatile(CompiledReplicatedMapIterationContext.this.hashLookupPos(), pos());
- }
-
- private void _MapSegmentIteration_doReplaceValue(Data newValue) {
- CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
- try {
- CompiledReplicatedMapIterationContext.this.innerDefaultReplaceValue(newValue);
- } finally {
- CompiledReplicatedMapIterationContext.this.innerWriteLock.unlock();
- }
- }
-
- @Override
- public void doReplaceValue(Data newValue) {
- CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
- try {
- CompiledReplicatedMapIterationContext.this.innerDefaultReplaceValue(newValue);
- CompiledReplicatedMapIterationContext.this.updateChange();
- CompiledReplicatedMapIterationContext.this.initUpdatedReplicationStateOnPresentEntry();
- } finally {
- CompiledReplicatedMapIterationContext.this.innerWriteLock.unlock();
- }
- }
-
- private void _MapSegmentIteration_doRemove() {
- CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
- initEntryRemovedOnThisIteration(true);
- CompiledReplicatedMapIterationContext.this.innerWriteLock.lock();
- try {
- if ((CompiledReplicatedMapIterationContext.this.remove(CompiledReplicatedMapIterationContext.this.hashLookupPos())) != (CompiledReplicatedMapIterationContext.this.hashLookupPos())) {
- CompiledReplicatedMapIterationContext.this.setHashLookupPosGuarded(CompiledReplicatedMapIterationContext.this.stepBack(CompiledReplicatedMapIterationContext.this.hashLookupPos()));
- }
- CompiledReplicatedMapIterationContext.this.innerRemoveEntryExceptHashLookupUpdate();
- } finally {
- CompiledReplicatedMapIterationContext.this.innerWriteLock.unlock();
- }
- }
-
- @Override
- public void doRemove() {
- CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
- initEntryRemovedOnThisIteration(true);
- try {
- if ((CompiledReplicatedMapIterationContext.this.valueSize()) > (CompiledReplicatedMapIterationContext.this.dummyValue.size()))
- CompiledReplicatedMapIterationContext.this.innerDefaultReplaceValue(CompiledReplicatedMapIterationContext.this.dummyValue);
-
- CompiledReplicatedMapIterationContext.this.initUpdatedReplicationStateOnPresentEntry();
- CompiledReplicatedMapIterationContext.this.writeEntryDeleted();
- CompiledReplicatedMapIterationContext.this.updateChange();
- CompiledReplicatedMapIterationContext.this.deleted(((CompiledReplicatedMapIterationContext.this.deleted()) + 1));
- } finally {
- CompiledReplicatedMapIterationContext.this.innerWriteLock.unlock();
+ initTheEntrySizeInChunks(CompiledReplicatedMapIterationContext.this.allocatedChunks());
}
}
@@ -2536,119 +2485,125 @@ public class CompiledReplicatedMapIterationContext value) {
+ initValue(value);
+ freeExtraAllocatedChunks();
+ CompiledReplicatedMapIterationContext.this.putValueVolatile(CompiledReplicatedMapIterationContext.this.hashLookupPos(), pos());
}
- public void initUsed(boolean used) {
- this.used = used;
+ private void _MapEntryStages_relocation(Data newValue, long newSizeOfEverythingBeforeValue) {
+ CompiledReplicatedMapIterationContext.this.free(pos(), entrySizeInChunks());
+ long entrySize = innerEntrySize(newSizeOfEverythingBeforeValue, newValue.size());
+ CompiledReplicatedMapIterationContext.this.initEntryAndKeyCopying(entrySize, ((valueSizeOffset()) - (keySizeOffset())));
+ writeValueAndPutPos(newValue);
}
- void closeUsed() {
- if (!(this.usedInit()))
- return ;
-
- used = false;
+ protected void relocation(Data newValue, long newSizeOfEverythingBeforeValue) {
+ long oldPos = pos();
+ _MapEntryStages_relocation(newValue, newSizeOfEverythingBeforeValue);
+ CompiledReplicatedMapIterationContext.this.moveChange(oldPos, pos());
}
- public long innerRemoteTimestamp;
-
- public byte innerRemoteIdentifier = ((byte)(0));
-
- public boolean replicationUpdateInit() {
- return (this.innerRemoteIdentifier) != ((byte)(0));
- }
-
- public void initReplicationUpdate(long timestamp, byte identifier) {
- innerRemoteTimestamp = timestamp;
- if (identifier == 0)
- throw new IllegalStateException("identifier can\'t be 0");
-
- innerRemoteIdentifier = identifier;
- this.closeReplicationUpdateDependants();
- }
-
- public byte innerRemoteIdentifier() {
- assert this.replicationUpdateInit() : "ReplicationUpdate should be init";
- return this.innerRemoteIdentifier;
- }
-
- public long innerRemoteTimestamp() {
- assert this.replicationUpdateInit() : "ReplicationUpdate should be init";
- return this.innerRemoteTimestamp;
- }
-
- public void closeReplicationUpdate() {
- if (!(this.replicationUpdateInit()))
- return ;
-
- this.closeReplicationUpdateDependants();
- this.innerRemoteIdentifier = ((byte)(0));
- }
-
- public void closeReplicationUpdateDependants() {
- CompiledReplicatedMapIterationContext.this.closeUpdatedReplicationState();
- }
-
- private boolean updatedReplicationState = false;
-
- public boolean updatedReplicationStateInit() {
- return (this.updatedReplicationState) != false;
- }
-
- public void initUpdatedReplicationStateOnAbsentEntry() {
- CompiledReplicatedMapIterationContext.this.innerWriteLock.lock();
- if (CompiledReplicatedMapIterationContext.this.replicationUpdateInit()) {
- updateReplicationState(CompiledReplicatedMapIterationContext.this.innerRemoteTimestamp(), CompiledReplicatedMapIterationContext.this.innerRemoteIdentifier());
- } else {
- updateReplicationState(CompiledReplicatedMapIterationContext.this.m().timeProvider.currentTime(), CompiledReplicatedMapIterationContext.this.m().identifier());
- }
- updatedReplicationState = true;
- }
-
- public void initUpdatedReplicationStateOnPresentEntry() {
- CompiledReplicatedMapIterationContext.this.innerWriteLock.lock();
- if (CompiledReplicatedMapIterationContext.this.replicationUpdateInit()) {
- updateReplicationState(CompiledReplicatedMapIterationContext.this.innerRemoteTimestamp(), CompiledReplicatedMapIterationContext.this.innerRemoteIdentifier());
- } else {
- long timestamp;
- if ((identifier()) != (CompiledReplicatedMapIterationContext.this.m().identifier())) {
- timestamp = Math.max(((timestamp()) + 1), CompiledReplicatedMapIterationContext.this.m().timeProvider.currentTime());
- } else {
- timestamp = CompiledReplicatedMapIterationContext.this.m().timeProvider.currentTime();
+ public void innerDefaultReplaceValue(Data newValue) {
+ assert CompiledReplicatedMapIterationContext.this.innerUpdateLock.isHeldByCurrentThread();
+ boolean newValueSizeIsDifferent = (newValue.size()) != (this.valueSize());
+ if (newValueSizeIsDifferent) {
+ long newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue);
+ long entryStartOffset = keySizeOffset();
+ VanillaChronicleMap, ?, ?, ?, ?, ?, ?> m = CompiledReplicatedMapIterationContext.this.m();
+ long newValueOffset = m.alignment.alignAddr((entryStartOffset + newSizeOfEverythingBeforeValue));
+ long newEntrySize = (newValueOffset + (newValue.size())) - entryStartOffset;
+ int newSizeInChunks = m.inChunks(newEntrySize);
+ newValueDoesNotFit : if (newSizeInChunks > (entrySizeInChunks())) {
+ if (newSizeInChunks > (m.maxChunksPerEntry)) {
+ throw new IllegalArgumentException(((((("Value too large: " + "entry takes ") + newSizeInChunks) + " chunks, ") + (m.maxChunksPerEntry)) + " is maximum."));
+ }
+ if (CompiledReplicatedMapIterationContext.this.freeList().allClear(((pos()) + (entrySizeInChunks())), ((pos()) + newSizeInChunks))) {
+ CompiledReplicatedMapIterationContext.this.freeList().set(((pos()) + (entrySizeInChunks())), ((pos()) + newSizeInChunks));
+ break newValueDoesNotFit;
+ }
+ relocation(newValue, newSizeOfEverythingBeforeValue);
+ return ;
+ } else if (newSizeInChunks < (entrySizeInChunks())) {
+ CompiledReplicatedMapIterationContext.this.freeList().clear(((pos()) + newSizeInChunks), ((pos()) + (entrySizeInChunks())));
}
- updateReplicationState(timestamp, CompiledReplicatedMapIterationContext.this.m().identifier());
+ } else {
}
- updatedReplicationState = true;
+ CompiledReplicatedMapIterationContext.this.innerWriteLock.lock();
+ if (newValueSizeIsDifferent) {
+ initValue(newValue);
+ } else {
+ writeValue(newValue);
+ }
+ CompiledReplicatedMapIterationContext.this.putValueVolatile(CompiledReplicatedMapIterationContext.this.hashLookupPos(), pos());
}
- public void closeUpdatedReplicationState() {
- if (!(this.updatedReplicationStateInit()))
- return ;
+ public void raiseChange() {
+ CompiledReplicatedMapIterationContext.this.m().raiseChange(CompiledReplicatedMapIterationContext.this.segmentIndex(), CompiledReplicatedMapIterationContext.this.pos());
+ }
- this.updatedReplicationState = false;
+ public void updateChange() {
+ if (!(replicationUpdateInit())) {
+ raiseChange();
+ }
+ }
+
+ private void _MapSegmentIteration_doRemove() {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ initEntryRemovedOnThisIteration(true);
+ CompiledReplicatedMapIterationContext.this.innerWriteLock.lock();
+ try {
+ if ((CompiledReplicatedMapIterationContext.this.remove(CompiledReplicatedMapIterationContext.this.hashLookupPos())) != (CompiledReplicatedMapIterationContext.this.hashLookupPos())) {
+ CompiledReplicatedMapIterationContext.this.setHashLookupPosGuarded(CompiledReplicatedMapIterationContext.this.stepBack(CompiledReplicatedMapIterationContext.this.hashLookupPos()));
+ }
+ CompiledReplicatedMapIterationContext.this.innerRemoveEntryExceptHashLookupUpdate();
+ } finally {
+ CompiledReplicatedMapIterationContext.this.innerWriteLock.unlock();
+ }
}
@Override
- public long remoteTimestamp() {
+ public void doRemove() {
CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
- return innerRemoteTimestamp();
+ initEntryRemovedOnThisIteration(true);
+ try {
+ if ((CompiledReplicatedMapIterationContext.this.valueSize()) > (CompiledReplicatedMapIterationContext.this.dummyValue.size()))
+ CompiledReplicatedMapIterationContext.this.innerDefaultReplaceValue(CompiledReplicatedMapIterationContext.this.dummyValue);
+
+ CompiledReplicatedMapIterationContext.this.updatedReplicationStateOnPresentEntry();
+ CompiledReplicatedMapIterationContext.this.writeEntryDeleted();
+ CompiledReplicatedMapIterationContext.this.updateChange();
+ CompiledReplicatedMapIterationContext.this.deleted(((CompiledReplicatedMapIterationContext.this.deleted()) + 1));
+ } finally {
+ CompiledReplicatedMapIterationContext.this.innerWriteLock.unlock();
+ }
+ }
+
+ private void _MapSegmentIteration_doReplaceValue(Data newValue) {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ try {
+ CompiledReplicatedMapIterationContext.this.innerDefaultReplaceValue(newValue);
+ } finally {
+ CompiledReplicatedMapIterationContext.this.innerWriteLock.unlock();
+ }
}
@Override
- public byte remoteIdentifier() {
+ public void doReplaceValue(Data newValue) {
CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
- return innerRemoteIdentifier();
+ try {
+ CompiledReplicatedMapIterationContext.this.innerDefaultReplaceValue(newValue);
+ CompiledReplicatedMapIterationContext.this.updateChange();
+ CompiledReplicatedMapIterationContext.this.updatedReplicationStateOnPresentEntry();
+ } finally {
+ CompiledReplicatedMapIterationContext.this.innerWriteLock.unlock();
+ }
}
- private boolean testTimeStampInSensibleRange() {
- if ((CompiledReplicatedMapIterationContext.this.m().timeProvider) == (TimeProvider.SYSTEM)) {
- long currentTime = TimeProvider.SYSTEM.currentTime();
- assert (Math.abs((currentTime - (timestamp())))) <= 100000000 : "unrealistic timestamp: " + (timestamp());
- assert (Math.abs((currentTime - (CompiledReplicatedMapIterationContext.this.innerRemoteTimestamp())))) <= 100000000 : "unrealistic innerRemoteTimestamp: " + (CompiledReplicatedMapIterationContext.this.innerRemoteTimestamp());
- }
- return true;
+ @Override
+ public void raiseChanged() {
+ CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation();
+ CompiledReplicatedMapIterationContext.this.innerUpdateLock.lock();
+ CompiledReplicatedMapIterationContext.this.raiseChange();
}
}
diff --git a/src/main/java/net/openhft/chronicle/map/impl/CompiledReplicatedMapQueryContext.java b/src/main/java/net/openhft/chronicle/map/impl/CompiledReplicatedMapQueryContext.java
index 08d393fb3..122953d30 100644
--- a/src/main/java/net/openhft/chronicle/map/impl/CompiledReplicatedMapQueryContext.java
+++ b/src/main/java/net/openhft/chronicle/map/impl/CompiledReplicatedMapQueryContext.java
@@ -45,29 +45,28 @@ import java.util.concurrent.TimeUnit;
public class CompiledReplicatedMapQueryContext, V, VI, MVI extends MetaBytesInterop, R, T> implements AutoCloseable , HashEntry , InterProcessReadWriteUpdateLock , RemoteOperationContext , ExternalMapQueryContext , MapAbsentEntry , MapContext , MapEntry , MapAbsentEntryHolder , QueryContextInterface