diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashLookupSearch.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashLookupSearch.java index cc2495f9c..47ddf7295 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashLookupSearch.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashLookupSearch.java @@ -19,6 +19,7 @@ package net.openhft.chronicle.hash.impl.stage.entry; import net.openhft.chronicle.hash.impl.CompactOffHeapLinearHashTable; import net.openhft.chronicle.hash.impl.VanillaChronicleHashHolder; import net.openhft.chronicle.hash.impl.stage.query.KeySearch; +import net.openhft.chronicle.map.impl.stage.entry.MapEntryStages; import net.openhft.sg.Stage; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; @@ -32,6 +33,7 @@ public abstract class HashLookupSearch { @StageRef public VanillaChronicleHashHolder hh; @StageRef HashLookupPos hlp; @StageRef KeySearch ks; + @StageRef MapEntryStages e; @Stage("SearchKey") long searchKey = UNSET_KEY; @Stage("SearchKey") public long searchStartPos; @@ -78,17 +80,22 @@ public abstract class HashLookupSearch { hlp.setHashLookupPos(hl().remove(addr(), hlp.hashLookupPos)); } - public void putNewVolatile(long value) { + public void putNewVolatile(long entryPos) { // Correctness check + make putNewVolatile() dependant on keySearch, this, in turn, // is needed for hlp.hashLookupPos re-initialization after nextTier(). // Not an assert statement, because ks.searchStatePresent() should run regardless assertions // enabled or not. + boolean keySearchReInit = !ks.keySearchInit(); if (ks.searchStatePresent()) throw new AssertionError(); + if (keySearchReInit) { + // if key search was re-init, entry was re-init too during the search + e.readExistingEntry(entryPos); + } - hl().checkValueForPut(value); + hl().checkValueForPut(entryPos); long currentEntry = hl().readEntry(addr(), hlp.hashLookupPos); - hl().writeEntryVolatile(addr(), hlp.hashLookupPos, currentEntry, searchKey, value); + hl().writeEntryVolatile(addr(), hlp.hashLookupPos, currentEntry, searchKey, entryPos); } public boolean checkSlotContainsExpectedKeyAndValue(long value) { diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/query/KeySearch.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/query/KeySearch.java index f56651785..ec73bed4d 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/query/KeySearch.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/query/KeySearch.java @@ -51,7 +51,7 @@ public abstract class KeySearch { @Stage("KeySearch") protected SearchState searchState = null; - abstract boolean keySearchInit(); + public abstract boolean keySearchInit(); @Stage("KeySearch") public void setSearchState(SearchState newSearchState) { diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapAbsent.java b/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapAbsent.java index 74142319f..90f5b307f 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapAbsent.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapAbsent.java @@ -22,11 +22,9 @@ import net.openhft.chronicle.hash.impl.stage.entry.SegmentStages; import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; import net.openhft.chronicle.hash.impl.stage.query.HashQuery.EntryPresence; import net.openhft.chronicle.hash.impl.stage.query.KeySearch; -import net.openhft.chronicle.map.MapAbsentEntry; import net.openhft.chronicle.map.impl.VanillaChronicleMapHolder; import net.openhft.chronicle.map.impl.stage.entry.MapEntryStages; import net.openhft.chronicle.set.DummyValueData; -import net.openhft.chronicle.set.SetAbsentEntry; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; import org.jetbrains.annotations.NotNull; @@ -89,6 +87,7 @@ public abstract class MapAbsent implements Absent { public void doInsert() { if (mh.set() == null) throw new IllegalStateException("Called SetAbsentEntry.doInsert() from Map context"); + //noinspection unchecked doInsert((Data) DummyValueData.INSTANCE); } }