mirror of
https://github.com/OpenHFT/Chronicle-Map.git
synced 2021-09-13 01:26:12 +00:00
Fixed a bug in MapEntryStages.putValueDeletedEntry() -- the slot in hashLookup is empty, should be filled, not just the value updated
This commit is contained in:
@@ -36,7 +36,6 @@ import net.openhft.chronicle.map.impl.stage.data.bytes.InputFirstValueBytesData;
|
||||
import net.openhft.chronicle.map.impl.stage.data.bytes.InputSecondValueBytesData;
|
||||
import net.openhft.chronicle.map.impl.stage.data.instance.InputValueInstanceData;
|
||||
import net.openhft.chronicle.map.impl.stage.data.instance.WrappedValueInstanceData;
|
||||
import net.openhft.chronicle.map.impl.stage.entry.MapEntryStages;
|
||||
import net.openhft.chronicle.map.impl.stage.input.MapInputBytesValues;
|
||||
import net.openhft.chronicle.map.impl.stage.map.MapEntryOperationsDelegation;
|
||||
import net.openhft.chronicle.map.impl.stage.map.ValueBytesInterop;
|
||||
@@ -66,7 +65,7 @@ import net.openhft.sg.Staged;
|
||||
QueryCheckOnEachPublicOperation.class,
|
||||
SearchAllocatedChunks.class,
|
||||
|
||||
MapEntryStages.class,
|
||||
QueryMapEntryStages.class,
|
||||
MapEntryOperationsDelegation.class,
|
||||
WrappedValueInstanceValueHolder.class,
|
||||
MapQuery.class,
|
||||
|
||||
@@ -33,10 +33,11 @@ import org.jetbrains.annotations.NotNull;
|
||||
public abstract class MapEntryStages<K, V> extends HashEntryStages<K>
|
||||
implements MapEntry<K, V> {
|
||||
|
||||
@StageRef VanillaChronicleMapHolder<?, ?, ?, ?, ?, ?, ?> mh;
|
||||
@StageRef AllocatedChunks allocatedChunks;
|
||||
@StageRef public VanillaChronicleMapHolder<?, ?, ?, ?, ?, ?, ?> mh;
|
||||
@StageRef public AllocatedChunks allocatedChunks;
|
||||
@StageRef HashLookup hashLookup;
|
||||
|
||||
|
||||
long countValueSizeOffset() {
|
||||
return keyEnd();
|
||||
}
|
||||
@@ -106,51 +107,8 @@ public abstract class MapEntryStages<K, V> extends HashEntryStages<K>
|
||||
}
|
||||
|
||||
public void putValueDeletedEntry(Data<V> newValue) {
|
||||
assert s.innerUpdateLock.isHeldByCurrentThread();
|
||||
|
||||
int newSizeInChunks;
|
||||
long entryStartOffset = keySizeOffset;
|
||||
long newSizeOfEverythingBeforeValue = -1;
|
||||
boolean newValueSizeIsDifferent = newValue.size() != valueSize;
|
||||
if (newValueSizeIsDifferent) {
|
||||
newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue);
|
||||
long newValueOffset = mh.m().alignment.alignAddr(
|
||||
entryStartOffset + newSizeOfEverythingBeforeValue);
|
||||
long newEntrySize = newValueOffset + newValue.size() - entryStartOffset;
|
||||
newSizeInChunks = mh.m().inChunks(newEntrySize);
|
||||
} else {
|
||||
newSizeInChunks = entrySizeInChunks;
|
||||
}
|
||||
if (pos + newSizeInChunks < s.freeList.size() &&
|
||||
s.freeList.allClear(pos, pos + newSizeInChunks)) {
|
||||
s.freeList.set(pos, pos + newSizeInChunks);
|
||||
s.innerWriteLock.lock();
|
||||
allocatedChunks.incrementSegmentEntriesIfNeeded();
|
||||
if (newValueSizeIsDifferent) {
|
||||
initValue(newValue);
|
||||
} else {
|
||||
writeValue(newValue);
|
||||
}
|
||||
} else {
|
||||
if (newValueSizeIsDifferent) {
|
||||
assert newSizeOfEverythingBeforeValue >= 0;
|
||||
} else {
|
||||
newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue);
|
||||
}
|
||||
long entrySize = innerEntrySize(newSizeOfEverythingBeforeValue, newValue.size());
|
||||
if (newValueSizeIsDifferent) {
|
||||
allocatedChunks.initEntryAndKeyCopying(entrySize, valueSizeOffset - entryStartOffset);
|
||||
initValue(newValue);
|
||||
} else {
|
||||
long oldValueSizeOffset = valueSizeOffset;
|
||||
long oldValueSize = valueSize;
|
||||
long oldValueOffset = valueOffset;
|
||||
allocatedChunks.initEntryAndKeyCopying(entrySize, valueOffset - entryStartOffset);
|
||||
initValueWithoutSize(newValue, oldValueSizeOffset, oldValueSize, oldValueOffset);
|
||||
}
|
||||
freeExtraAllocatedChunks();
|
||||
}
|
||||
hashLookup.putValueVolatile(hlp.hashLookupPos, pos);
|
||||
throw new AssertionError("putValueDeletedEntry() might be called only from " +
|
||||
"non-Replicated Map query context");
|
||||
}
|
||||
|
||||
public void writeValueAndPutPos(Data<V> value) {
|
||||
|
||||
@@ -158,9 +158,4 @@ public abstract class ReplicatedMapEntryStages<K, V, T> extends MapEntryStages<K
|
||||
long sizeOfEverythingBeforeValue(long keySize, long valueSize) {
|
||||
return super.sizeOfEverythingBeforeValue(keySize, valueSize) + ADDITIONAL_ENTRY_BYTES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putValueDeletedEntry(Data<V> newValue) {
|
||||
throw new AssertionError("Replicated Map doesn't remove entries truly, yet");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2015 higherfrequencytrading.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.openhft.chronicle.map.impl.stage.query;
|
||||
|
||||
import net.openhft.chronicle.hash.Data;
|
||||
import net.openhft.chronicle.hash.impl.stage.query.HashLookupSearch;
|
||||
import net.openhft.chronicle.map.impl.stage.entry.MapEntryStages;
|
||||
import net.openhft.sg.StageRef;
|
||||
import net.openhft.sg.Staged;
|
||||
|
||||
@Staged
|
||||
public abstract class QueryMapEntryStages<K, V> extends MapEntryStages<K, V> {
|
||||
|
||||
@StageRef HashLookupSearch hls;
|
||||
|
||||
@Override
|
||||
public void putValueDeletedEntry(Data<V> newValue) {
|
||||
assert s.innerUpdateLock.isHeldByCurrentThread();
|
||||
|
||||
int newSizeInChunks;
|
||||
long entryStartOffset = keySizeOffset;
|
||||
long newSizeOfEverythingBeforeValue = -1;
|
||||
boolean newValueSizeIsDifferent = newValue.size() != valueSize;
|
||||
if (newValueSizeIsDifferent) {
|
||||
newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue);
|
||||
long newValueOffset = mh.m().alignment.alignAddr(
|
||||
entryStartOffset + newSizeOfEverythingBeforeValue);
|
||||
long newEntrySize = newValueOffset + newValue.size() - entryStartOffset;
|
||||
newSizeInChunks = mh.m().inChunks(newEntrySize);
|
||||
} else {
|
||||
newSizeInChunks = entrySizeInChunks;
|
||||
}
|
||||
if (pos + newSizeInChunks < s.freeList.size() &&
|
||||
s.freeList.allClear(pos, pos + newSizeInChunks)) {
|
||||
s.freeList.set(pos, pos + newSizeInChunks);
|
||||
s.innerWriteLock.lock();
|
||||
allocatedChunks.incrementSegmentEntriesIfNeeded();
|
||||
if (newValueSizeIsDifferent) {
|
||||
initValue(newValue);
|
||||
} else {
|
||||
writeValue(newValue);
|
||||
}
|
||||
} else {
|
||||
if (newValueSizeIsDifferent) {
|
||||
assert newSizeOfEverythingBeforeValue >= 0;
|
||||
} else {
|
||||
newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue);
|
||||
}
|
||||
long entrySize = innerEntrySize(newSizeOfEverythingBeforeValue, newValue.size());
|
||||
if (newValueSizeIsDifferent) {
|
||||
allocatedChunks.initEntryAndKeyCopying(entrySize, valueSizeOffset - entryStartOffset);
|
||||
initValue(newValue);
|
||||
} else {
|
||||
long oldValueSizeOffset = valueSizeOffset;
|
||||
long oldValueSize = valueSize;
|
||||
long oldValueOffset = valueOffset;
|
||||
allocatedChunks.initEntryAndKeyCopying(entrySize, valueOffset - entryStartOffset);
|
||||
initValueWithoutSize(newValue, oldValueSizeOffset, oldValueSize, oldValueOffset);
|
||||
}
|
||||
freeExtraAllocatedChunks();
|
||||
}
|
||||
hls.putNewVolatile(pos);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user