mirror of
https://github.com/OpenHFT/Chronicle-Map.git
synced 2021-09-13 01:26:12 +00:00
Add dataStoreSize field to Chronicle Map's global mutable state
This commit is contained in:
@@ -18,6 +18,8 @@ package net.openhft.chronicle.hash;
|
||||
|
||||
import net.openhft.chronicle.bytes.Byteable;
|
||||
import net.openhft.chronicle.values.Group;
|
||||
import net.openhft.chronicle.values.Range;
|
||||
import net.openhft.chronicle.values.Values;
|
||||
|
||||
/**
|
||||
* <h1>This interface is a private API, don't use in client code</h1>
|
||||
@@ -28,17 +30,27 @@ public interface VanillaGlobalMutableState extends Byteable {
|
||||
|
||||
@Group(1)
|
||||
int getAllocatedExtraTierBulks();
|
||||
void setAllocatedExtraTierBulks(int allocatedExtraTierBulks);
|
||||
void setAllocatedExtraTierBulks(@Range(min = 0, max = 16777215) int allocatedExtraTierBulks);
|
||||
|
||||
@Group(2)
|
||||
long getFirstFreeTierIndex();
|
||||
void setFirstFreeTierIndex(long firstFreeTierIndex);
|
||||
void setFirstFreeTierIndex(@Range(min = 0, max = 1099511627775L) long firstFreeTierIndex);
|
||||
|
||||
@Group(3)
|
||||
long getExtraTiersInUse();
|
||||
void setExtraTiersInUse(long extraTiersInUse);
|
||||
void setExtraTiersInUse(@Range(min = 0, max = 1099511627775L) long extraTiersInUse);
|
||||
|
||||
@Group(4)
|
||||
long getSegmentHeadersOffset();
|
||||
void setSegmentHeadersOffset(long segmentHeadersOffset);
|
||||
void setSegmentHeadersOffset(@Range(min = 0, max = 4294967295L) long segmentHeadersOffset);
|
||||
|
||||
@Group(5)
|
||||
long getDataStoreSize();
|
||||
void setDataStoreSize(@Range(min = 0, max = Long.MAX_VALUE) long dataStoreSize);
|
||||
long addDataStoreSize(long addition);
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.setProperty("chronicle.values.dumpCode", "true");
|
||||
Values.nativeClassFor(VanillaGlobalMutableState.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package net.openhft.chronicle.hash.impl;
|
||||
|
||||
import net.openhft.chronicle.algo.MemoryUnit;
|
||||
import net.openhft.chronicle.algo.locks.*;
|
||||
import net.openhft.chronicle.bytes.BytesStore;
|
||||
import net.openhft.chronicle.bytes.MappedBytesStoreFactory;
|
||||
@@ -434,6 +435,7 @@ public abstract class VanillaChronicleHash<K,
|
||||
zeroOutNewlyMappedChronicleMapBytes();
|
||||
// write the segment headers offset after zeroing out
|
||||
globalMutableState.setSegmentHeadersOffset(segmentHeadersOffset);
|
||||
globalMutableState.setDataStoreSize(sizeInBytesWithoutTiers());
|
||||
} else {
|
||||
initBulks();
|
||||
}
|
||||
@@ -481,24 +483,32 @@ public abstract class VanillaChronicleHash<K,
|
||||
}
|
||||
|
||||
public final void createMappedStoreAndSegments() throws IOException {
|
||||
// TODO this method had been moved -- not clear where
|
||||
//OS.warnOnWindows(sizeInBytesWithoutTiers());
|
||||
long mapSize = expectedFileSize();
|
||||
createMappedStoreAndSegments(map(mapSize, 0));
|
||||
createMappedStoreAndSegments(map(dataStoreSize(), 0));
|
||||
}
|
||||
|
||||
public final void basicRecover() throws IOException {
|
||||
long segmentHeadersOffset = computeSegmentHeadersOffset();
|
||||
long segmentHeadersOffset = globalMutableState().getSegmentHeadersOffset();
|
||||
if (segmentHeadersOffset <= 0 || segmentHeadersOffset % 4096 != 0 ||
|
||||
segmentHeadersOffset > GIGABYTES.toBytes(1)) {
|
||||
segmentHeadersOffset = computeSegmentHeadersOffset();
|
||||
}
|
||||
long sizeInBytesWithoutTiers = computeSizeInBytesWithoutTiers(segmentHeadersOffset);
|
||||
long sizeBeyondSegments = Math.max(raf.length() - sizeInBytesWithoutTiers, 0);
|
||||
int allocatedExtraTierBulks = (int) (sizeBeyondSegments / tierBulkSizeInBytes);
|
||||
long mapSize = pageAlign(sizeInBytesWithoutTiers +
|
||||
allocatedExtraTierBulks * tierBulkSizeInBytes);
|
||||
initBytesStoreAndHeadersViews(map(mapSize, 0));
|
||||
long dataStoreSize = globalMutableState().getDataStoreSize();
|
||||
int allocatedExtraTierBulks = globalMutableState().getAllocatedExtraTierBulks();
|
||||
if (dataStoreSize < sizeInBytesWithoutTiers ||
|
||||
((dataStoreSize - sizeInBytesWithoutTiers) % tierBulkSizeInBytes != 0)) {
|
||||
dataStoreSize = sizeInBytesWithoutTiers + allocatedExtraTierBulks * tierBulkSizeInBytes;
|
||||
} else {
|
||||
allocatedExtraTierBulks =
|
||||
(int) ((dataStoreSize - sizeInBytesWithoutTiers) / tierBulkSizeInBytes);
|
||||
}
|
||||
initBytesStoreAndHeadersViews(map(dataStoreSize, 0));
|
||||
|
||||
resetGlobalMutableStateLock();
|
||||
recoverAllocatedExtraTierBulks(allocatedExtraTierBulks);
|
||||
recoverSegmentHeadersOffset(segmentHeadersOffset);
|
||||
recoverDataStoreSize(dataStoreSize);
|
||||
initOffsetsAndBulks();
|
||||
}
|
||||
|
||||
@@ -530,6 +540,14 @@ public abstract class VanillaChronicleHash<K,
|
||||
}
|
||||
}
|
||||
|
||||
private void recoverDataStoreSize(long dataStoreSize) {
|
||||
if (globalMutableState.getDataStoreSize() != dataStoreSize) {
|
||||
LOG.error("data store size of map at {} corrupted. stored: {}, should be: {}",
|
||||
file, globalMutableState.getDataStoreSize(), dataStoreSize);
|
||||
globalMutableState.setDataStoreSize(dataStoreSize);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean persisted() {
|
||||
return file != null;
|
||||
}
|
||||
@@ -609,11 +627,11 @@ public abstract class VanillaChronicleHash<K,
|
||||
return segmentHeadersOffset + actualSegments * (segmentHeaderSize + tierSize);
|
||||
}
|
||||
|
||||
public final long expectedFileSize() {
|
||||
public final long dataStoreSize() {
|
||||
long sizeInBytesWithoutTiers = sizeInBytesWithoutTiers();
|
||||
int allocatedExtraTierBulks = !createdOrInMemory ?
|
||||
globalMutableState.getAllocatedExtraTierBulks() : 0;
|
||||
return pageAlign(sizeInBytesWithoutTiers + allocatedExtraTierBulks * tierBulkSizeInBytes);
|
||||
return sizeInBytesWithoutTiers + allocatedExtraTierBulks * tierBulkSizeInBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -800,6 +818,7 @@ public abstract class VanillaChronicleHash<K,
|
||||
// after we are sure the new bulk is initialized, update the global mutable state
|
||||
globalMutableState.setAllocatedExtraTierBulks(allocatedExtraTierBulks + 1);
|
||||
globalMutableState.setFirstFreeTierIndex(firstTierIndex);
|
||||
globalMutableState.addDataStoreSize(tierBulkSizeInBytes);
|
||||
}
|
||||
|
||||
public void msync() throws IOException {
|
||||
@@ -930,6 +949,7 @@ public abstract class VanillaChronicleHash<K,
|
||||
* @see net.openhft.chronicle.bytes.MappedFile#acquireByteStore(long, MappedBytesStoreFactory)
|
||||
*/
|
||||
private NativeBytesStore map(long mapSize, long mappingOffsetInFile) throws IOException {
|
||||
mapSize = pageAlign(mapSize);
|
||||
long minFileSize = mappingOffsetInFile + mapSize;
|
||||
FileChannel fileChannel = raf.getChannel();
|
||||
if (fileChannel.size() < minFileSize) {
|
||||
|
||||
@@ -1593,11 +1593,11 @@ public final class ChronicleMapBuilder<K, V> implements
|
||||
VanillaChronicleMap<K, V, ?> map = wire.getValueIn().typedMarshallable();
|
||||
assert map != null;
|
||||
map.initBeforeMapping(file, raf, headerBuffer.limit(), recover);
|
||||
long expectedFileLength = map.expectedFileSize();
|
||||
if (!recover && expectedFileLength != file.length()) {
|
||||
long dataStoreSize = map.globalMutableState().getDataStoreSize();
|
||||
if (!recover && dataStoreSize > file.length()) {
|
||||
throw new IOException("The file " + file + " the map is serialized from " +
|
||||
"has unexpected length " + file.length() + ", probably corrupted. " +
|
||||
"Expected length is " + expectedFileLength);
|
||||
"Data store size is " + dataStoreSize);
|
||||
}
|
||||
map.initTransientsFromBuilder(this);
|
||||
if (!recover) {
|
||||
@@ -1683,11 +1683,6 @@ public final class ChronicleMapBuilder<K, V> implements
|
||||
|
||||
try {
|
||||
VanillaChronicleMap<K, V, ?> map = newMap();
|
||||
// TODO this method had been moved
|
||||
// if(OS.warnOnWindows(map.sizeInBytesWithoutTiers())){
|
||||
// throw new IllegalStateException("Windows cannot support this configuration");
|
||||
// }
|
||||
|
||||
BytesStore bytesStore =
|
||||
lazyNativeBytesStoreWithFixedCapacity(map.sizeInBytesWithoutTiers());
|
||||
map.createMappedStoreAndSegments(bytesStore);
|
||||
|
||||
@@ -17,21 +17,30 @@
|
||||
package net.openhft.chronicle.map;
|
||||
|
||||
import net.openhft.chronicle.hash.VanillaGlobalMutableState;
|
||||
import net.openhft.chronicle.values.Array;
|
||||
import net.openhft.chronicle.values.Group;
|
||||
import net.openhft.chronicle.values.*;
|
||||
|
||||
interface ReplicatedGlobalMutableState extends VanillaGlobalMutableState {
|
||||
|
||||
@Group(5)
|
||||
int getCurrentCleanupSegmentIndex();
|
||||
void setCurrentCleanupSegmentIndex(int currentCleanupSegmentIndex);
|
||||
|
||||
@Group(6)
|
||||
int getCurrentCleanupSegmentIndex();
|
||||
void setCurrentCleanupSegmentIndex(
|
||||
@Range(min = 0, max = Integer.MAX_VALUE) int currentCleanupSegmentIndex);
|
||||
|
||||
@Group(7)
|
||||
@Align(offset = 1)
|
||||
int getModificationIteratorsCount();
|
||||
int addModificationIteratorsCount(@Range(min = 0, max = 128) int addition);
|
||||
|
||||
@Group(8)
|
||||
// Align to prohibit array filling the highest bit of the previous 2-byte block, that
|
||||
// complicates generated code for all fields, defined in this interface.
|
||||
@Align(offset = 2)
|
||||
@Array(length = 128)
|
||||
boolean getModificationIteratorInitAt(int index);
|
||||
void setModificationIteratorInitAt(int index, boolean init);
|
||||
|
||||
@Group(7)
|
||||
int getModificationIteratorsCount();
|
||||
int addModificationIteratorsCount(int addition);
|
||||
public static void main(String[] args) {
|
||||
System.setProperty("chronicle.values.dumpCode", "true");
|
||||
Values.nativeClassFor(ReplicatedGlobalMutableState.class);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user