HCOLL-378 #36 Fix bugs in recovery

This commit is contained in:
leventov
2016-01-06 00:39:36 +03:00
parent ebee1d36c3
commit 6ee78ba926
7 changed files with 129 additions and 12 deletions
@@ -149,7 +149,7 @@ public abstract class VanillaChronicleHash<K,
public transient List<TierBulkData> tierBulkOffsets;
public transient long headerSize;
transient long segmentHeadersOffset;
public transient long segmentHeadersOffset;
transient long segmentsOffset;
public transient CompactOffHeapLinearHashTable hashLookup;
@@ -416,7 +416,10 @@ public abstract class VanillaChronicleHash<K,
public final void createMappedStoreAndSegments(BytesStore bytesStore) throws IOException {
initBytesStoreAndHeadersViews(bytesStore);
initOffsetsAndBulks();
}
private void initOffsetsAndBulks() {
segmentHeadersOffset = segmentHeadersOffset();
long segmentHeadersSize = actualSegments * segmentHeaderSize;
@@ -472,7 +475,7 @@ public abstract class VanillaChronicleHash<K,
resetGlobalMutableStateLock(file);
recoverAllocatedExtraTierBulks(file, allocatedExtraTierBulks);
recoverSegmentHeadersOffset(file, segmentHeadersOffset);
initBulks();
initOffsetsAndBulks();
}
private void resetGlobalMutableStateLock(File file) {
@@ -34,7 +34,6 @@ public abstract class SegmentsRecovery implements IterationContext {
@StageRef SegmentStages s;
@StageRef TierRecovery tierRecovery;
@StageRef LogHolder lh;
@StageRef HashSegmentIteration iteration;
@Override
public void recoverSegments() {
@@ -19,8 +19,6 @@ package net.openhft.chronicle.hash.impl.stage.iter;
import net.openhft.chronicle.bytes.BytesUtil;
import net.openhft.chronicle.hash.ChronicleHashRecoveryFailedException;
import net.openhft.chronicle.hash.Data;
import net.openhft.chronicle.hash.ExternalHashQueryContext;
import net.openhft.chronicle.hash.HashEntry;
import net.openhft.chronicle.hash.impl.CompactOffHeapLinearHashTable;
import net.openhft.chronicle.hash.impl.VanillaChronicleHash;
import net.openhft.chronicle.hash.impl.stage.entry.SegmentStages;
@@ -134,11 +132,13 @@ public class TierRecovery {
Data key = (Data) e.key();
try (ExternalMapQueryContext<?, ?, ?> c = m.queryContext(key)) {
MapEntry<?, ?> entry2 = c.entry();
Data<?> key2 = entry2.key();
Data<?> key2 = ((MapEntry) c).key();
if (key2.bytes().address(key2.offset()) != key.bytes().address(key.offset())) {
lh.LOG.error("entries with duplicate key {} in segment {}: " +
"with values {} and {}, removing the latter",
key, c.segmentIndex(), entry2.value(), e.value());
key, c.segmentIndex(),
entry2 != null ? ((MapEntry) c).value() : "<deleted>",
!e.entryDeleted() ? e.value() : "<deleted>");
if (hashLookup.remove(currentTierBaseAddr, hlPos) != hlPos) {
hlPos = hashLookup.stepBack(hlPos);
steps--;
@@ -266,4 +266,8 @@ public abstract class MapEntryStages<K, V> extends HashEntryStages<K>
initEntrySizeInChunks(allocatedChunks.allocatedChunks);
}
}
public boolean entryDeleted() {
return false;
}
}
@@ -69,6 +69,7 @@ public abstract class ReplicatedMapEntryStages<K, V> extends MapEntryStages<K, V
return replicationBytesOffset + 9L;
}
@Override
public boolean entryDeleted() {
return s.segmentBS.readBoolean(entryDeletedOffset());
}
@@ -72,7 +72,7 @@ public class ReplicatedTierRecovery extends TierRecovery {
ReplicatedChronicleMap<?, ?, ?>.ModificationIterator[] its =
m.acquireAllModificationIterators();
ReusableBitSet freeList = s.freeList;
for (long pos = 0;;) {
for (long pos = 0; pos < m.actualChunksPerSegmentTier;) {
long nextPos = freeList.nextSetBit(pos);
if (nextPos > pos) {
for (ReplicatedChronicleMap<?, ?, ?>.ModificationIterator it : its) {
@@ -88,11 +88,10 @@ public class ReplicatedTierRecovery extends TierRecovery {
}
pos = nextPos + e.entrySizeInChunks;
} else {
if (pos < m.actualChunksPerSegmentTier) {
for (ReplicatedChronicleMap<?, ?, ?>.ModificationIterator it : its) {
it.clearRange0(s.tierIndex, pos, m.actualChunksPerSegmentTier);
}
for (ReplicatedChronicleMap<?, ?, ?>.ModificationIterator it : its) {
it.clearRange0(s.tierIndex, pos, m.actualChunksPerSegmentTier);
}
break;
}
}
}