Refactor VanillaChronicleHash.allocateTier() method

This commit is contained in:
leventov
2016-02-10 22:59:38 +07:00
parent 9ba667d93a
commit 6b030ab44e
2 changed files with 38 additions and 30 deletions
@@ -728,14 +728,13 @@ public abstract class VanillaChronicleHash<K,
globalMutableStateAddress() + GLOBAL_MUTABLE_STATE_LOCK_OFFSET);
}
public long allocateTier(int forSegmentIndex, int tier) {
LOG.debug("Allocate tier for segment # {}, tier {}", forSegmentIndex, tier);
public long allocateTier() {
globalMutableStateLock();
try {
long tiersInUse = globalMutableState.getExtraTiersInUse();
if (tiersInUse == maxExtraTiers) {
throw new IllegalStateException("Attempt to allocate " + (maxExtraTiers + 1) +
"th extra segment tier, " + maxExtraTiers + " is maximum.\n" +
if (tiersInUse >= maxExtraTiers) {
throw new IllegalStateException("Attempt to allocate #" + (tiersInUse + 1) +
" extra segment tier, " + maxExtraTiers + " is maximum.\n" +
"Possible reasons include:\n" +
" - you have forgotten to configure (or configured wrong) " +
"builder.entries() number\n" +
@@ -744,30 +743,31 @@ public abstract class VanillaChronicleHash<K,
" - keys, inserted into the ChronicleHash, are distributed suspiciously " +
"bad. This might be a DOS attack");
}
while (true) {
long firstFreeTierIndex = globalMutableState.getFirstFreeTierIndex();
if (firstFreeTierIndex > 0) {
globalMutableState.setExtraTiersInUse(tiersInUse + 1);
BytesStore allocatedTierBytes = tierBytesStore(firstFreeTierIndex);
long allocatedTierOffset = tierBytesOffset(firstFreeTierIndex);
long tierBaseAddr = allocatedTierBytes.address(0) + allocatedTierOffset;
long tierCountersAreaAddr = tierBaseAddr + tierHashLookupOuterSize;
long nextFreeTierIndex = TierCountersArea.nextTierIndex(tierCountersAreaAddr);
// now, when this tier will be a part of the map, the next tier designates
// the next tier in the data store, should be 0
TierCountersArea.nextTierIndex(tierCountersAreaAddr, 0);
TierCountersArea.segmentIndex(tierCountersAreaAddr, forSegmentIndex);
TierCountersArea.tier(tierCountersAreaAddr, tier);
globalMutableState.setFirstFreeTierIndex(nextFreeTierIndex);
return firstFreeTierIndex;
} else {
try {
allocateTierBulk();
} catch (IOException e) {
throw new RuntimeException(e);
}
long firstFreeTierIndex = globalMutableState.getFirstFreeTierIndex();
if (firstFreeTierIndex < 0) {
throw new RuntimeException("unexpected firstFreeTierIndex value " +
firstFreeTierIndex);
}
if (firstFreeTierIndex == 0) {
try {
allocateTierBulk();
} catch (IOException e) {
throw new RuntimeException(e);
}
firstFreeTierIndex = globalMutableState.getFirstFreeTierIndex();
if (firstFreeTierIndex <= 0) {
throw new RuntimeException("unexpected firstFreeTierIndex value " +
firstFreeTierIndex);
}
}
globalMutableState.setExtraTiersInUse(tiersInUse + 1);
BytesStore allocatedTierBytes = tierBytesStore(firstFreeTierIndex);
long allocatedTierOffset = tierBytesOffset(firstFreeTierIndex);
long tierBaseAddr = allocatedTierBytes.address(0) + allocatedTierOffset;
long tierCountersAreaAddr = tierBaseAddr + tierHashLookupOuterSize;
long nextFreeTierIndex = TierCountersArea.nextTierIndex(tierCountersAreaAddr);
globalMutableState.setFirstFreeTierIndex(nextFreeTierIndex);
return firstFreeTierIndex;
} finally {
globalMutableStateUnlock();
}
@@ -27,6 +27,7 @@ import net.openhft.chronicle.hash.SegmentLock;
import net.openhft.chronicle.hash.impl.*;
import net.openhft.chronicle.hash.impl.stage.hash.Chaining;
import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation;
import net.openhft.chronicle.hash.impl.stage.hash.LogHolder;
import net.openhft.chronicle.hash.impl.stage.query.KeySearch;
import net.openhft.chronicle.hash.locks.InterProcessLock;
import net.openhft.chronicle.map.impl.IterationContext;
@@ -46,6 +47,7 @@ import static net.openhft.chronicle.hash.impl.VanillaChronicleHash.TIER_COUNTERS
@Staged
public abstract class SegmentStages implements SegmentLock, LocksInterface {
@StageRef LogHolder log;
@StageRef Chaining chaining;
@StageRef public VanillaChronicleHashHolder<?> hh;
@StageRef public CheckOnEachPublicOperation checkOnEachPublicOperation;
@@ -558,11 +560,17 @@ public abstract class SegmentStages implements SegmentLock, LocksInterface {
VanillaChronicleHash<?, ?, ?, ?> h = hh.h();
long nextTierIndex = nextTierIndex();
if (nextTierIndex == 0) {
nextTierIndex = h.allocateTier(segmentIndex, tier + 1);
log.LOG.debug("Allocate tier for segment # {}, tier {}", segmentIndex, tier + 1);
nextTierIndex = h.allocateTier();
nextTierIndex(nextTierIndex);
long currentTierIndex = tierIndex;
long prevTierIndex = tierIndex;
initSegmentTier(tier + 1, nextTierIndex);
prevTierIndex(currentTierIndex);
TierCountersArea.segmentIndex(tierCountersAreaAddr(), segmentIndex);
TierCountersArea.tier(tierCountersAreaAddr(), tier);
nextTierIndex(0);
prevTierIndex(prevTierIndex);
} else {
initSegmentTier(tier + 1, nextTierIndex);
}