use of org.apache.geode.internal.cache.versions.RegionVersionVector in project geode by apache.
the class DiskInitFile method cmnClearRegion.
public void cmnClearRegion(long drId, ConcurrentHashMap<DiskStoreID, RegionVersionHolder<DiskStoreID>> memberToVersion) {
DiskRegionView drv = getDiskRegionById(drId);
if (drv.getClearRVV() == null) {
this.ifLiveRecordCount++;
}
// otherwise previous clear is cancelled so don't change liveRecordCount
this.ifTotalRecordCount++;
DiskStoreID ownerId = parent.getDiskStoreID();
// Create a fake RVV for clear purposes. We only need to memberToVersion information
RegionVersionHolder<DiskStoreID> ownerExceptions = memberToVersion.remove(ownerId);
long ownerVersion = ownerExceptions == null ? 0 : ownerExceptions.getVersion();
RegionVersionVector rvv = new DiskRegionVersionVector(ownerId, memberToVersion, ownerVersion, new ConcurrentHashMap(), 0L, false, ownerExceptions);
drv.setClearRVV(rvv);
}
use of org.apache.geode.internal.cache.versions.RegionVersionVector in project geode by apache.
the class Oplog method basicModify.
/**
* A helper function which identifies whether to modify the entry in the current oplog or to make
* the switch to the next oplog. This function enables us to reuse the byte buffer which got
* created for an oplog which no longer permits us to use itself. It will also take acre of
* compaction if required
*
* @param entry DiskEntry object representing the current Entry
*/
private void basicModify(DiskRegionView dr, DiskEntry entry, ValueWrapper value, byte userBits, boolean async, boolean calledByCompactor) throws IOException, InterruptedException {
DiskId id = entry.getDiskId();
boolean useNextOplog = false;
long startPosForSynchOp = -1L;
int adjustment = 0;
Oplog emptyOplog = null;
if (DiskStoreImpl.KRF_DEBUG) {
// wait for cache close to create krf
System.out.println("basicModify KRF_DEBUG");
Thread.sleep(1000);
}
synchronized (this.lock) {
// synchronized (this.crf) {
if (getOplogSet().getChild() != this) {
useNextOplog = true;
} else {
initOpState(OPLOG_MOD_ENTRY_1ID, dr, entry, value, userBits, false);
adjustment = getOpStateSize();
assert adjustment > 0;
long temp = (this.crf.currSize + adjustment);
if (temp > getMaxCrfSize() && !isFirstRecord()) {
switchOpLog(dr, adjustment, entry);
// we can't reuse it since it contains variable length data
useNextOplog = true;
} else {
if (this.lockedForKRFcreate) {
CacheClosedException cce = new CacheClosedException("The disk store is closed.");
dr.getCancelCriterion().checkCancelInProgress(cce);
throw cce;
}
this.firstRecord = false;
long oldOplogId;
// do the io while holding lock so that switch can set doneAppending
// Write the data to the opLog for the synch mode
startPosForSynchOp = writeOpLogBytes(this.crf, async, true);
this.crf.currSize = temp;
startPosForSynchOp += getOpStateValueOffset();
if (logger.isTraceEnabled(LogMarker.PERSIST_WRITES)) {
VersionTag tag = null;
if (entry.getVersionStamp() != null) {
tag = entry.getVersionStamp().asVersionTag();
}
logger.trace(LogMarker.PERSIST_WRITES, "basicModify: id=<{}> key=<{}> valueOffset={} userBits={} valueLen={} valueBytes=<{}> drId={} versionStamp={} oplog#{}", abs(id.getKeyId()), entry.getKey(), startPosForSynchOp, userBits, value.getLength(), value.getBytesAsString(), dr.getId(), tag, getOplogId());
}
if (EntryBits.isNeedsValue(userBits)) {
id.setValueLength(value.getLength());
} else {
id.setValueLength(0);
}
id.setUserBits(userBits);
if (logger.isTraceEnabled()) {
logger.trace("Oplog::basicModify:Released ByteBuffer with data for Disk ID = {}", id);
}
synchronized (id) {
// Need to do this while synced on id
// now that we compact forward to most recent oplog.
// @todo darrel: The sync logic in the disk code is so complex
// a really doubt is is correct.
// I think we need to do a fresh rewrite of it.
oldOplogId = id.setOplogId(getOplogId());
if (EntryBits.isAnyInvalid(userBits) || EntryBits.isTombstone(userBits)) {
id.setOffsetInOplog(-1);
} else {
id.setOffsetInOplog(startPosForSynchOp);
}
}
// Set the oplog size change for stats
this.dirHolder.incrementTotalOplogSize(adjustment);
this.incTotalCount();
EntryLogger.logPersistPut(dr.getName(), entry.getKey(), dr.getDiskStoreID());
if (oldOplogId != getOplogId()) {
Oplog oldOplog = getOplogSet().getChild(oldOplogId);
if (oldOplog != null) {
oldOplog.rmLive(dr, entry);
emptyOplog = oldOplog;
}
addLive(dr, entry);
// Note if this mod was done to oldOplog then this entry is already
// in
// the linked list. All we needed to do in this case is call
// incTotalCount
} else {
getOrCreateDRI(dr).update(entry);
}
// Update the region version vector for the disk store.
// This needs to be done under lock so that we don't switch oplogs
// unit the version vector accurately represents what is in this oplog
RegionVersionVector rvv = dr.getRegionVersionVector();
if (rvv != null && entry.getVersionStamp() != null) {
rvv.recordVersion(entry.getVersionStamp().getMemberID(), entry.getVersionStamp().getRegionVersion());
}
}
clearOpState();
}
// }
}
if (useNextOplog) {
if (LocalRegion.ISSUE_CALLBACKS_TO_CACHE_OBSERVER) {
CacheObserverHolder.getInstance().afterSwitchingOplog();
}
Assert.assertTrue(getOplogSet().getChild() != this);
getOplogSet().getChild().basicModify(dr, entry, value, userBits, async, calledByCompactor);
} else {
if (LocalRegion.ISSUE_CALLBACKS_TO_CACHE_OBSERVER) {
CacheObserverHolder.getInstance().afterSettingOplogOffSet(startPosForSynchOp);
}
if (emptyOplog != null && (!emptyOplog.isCompacting() || emptyOplog.calledByCompactorThread())) {
if (calledByCompactor && emptyOplog.hasNoLiveValues()) {
// Since compactor will only append to crf no need to flush drf.
// Before we have the compactor delete an oplog it has emptied out
// we want to have it flush anything it has written to the current
// oplog.
// Note that since sync writes may be done to the same oplog we are
// doing
// async writes to any sync writes will cause a flush to be done
// immediately.
flushAll(true);
}
emptyOplog.handleNoLiveValues();
}
}
}
use of org.apache.geode.internal.cache.versions.RegionVersionVector in project geode by apache.
the class LocalRegion method createVersionVector.
/** initializes a new version vector for this region */
void createVersionVector() {
this.versionVector = RegionVersionVector.create(getVersionMember(), this);
if (this.dataPolicy.withPersistence()) {
// copy the versions that we have recovered from disk into
// the version vector.
RegionVersionVector diskVector = this.diskRegion.getRegionVersionVector();
this.versionVector.recordVersions(diskVector.getCloneForTransmission());
} else if (!this.dataPolicy.withStorage()) {
// version vectors are currently only necessary in empty regions for
// tracking canonical member IDs
this.versionVector.turnOffRecordingForEmptyRegion();
}
if (this.serverRegionProxy != null) {
this.versionVector.setIsClientVector();
}
this.cache.getDistributionManager().addMembershipListener(this.versionVector);
}
use of org.apache.geode.internal.cache.versions.RegionVersionVector in project geode by apache.
the class Oplog method basicCreate.
/**
* A helper function which identifies whether to create the entry in the current oplog or to make
* the switch to the next oplog. This function enables us to reuse the byte buffer which got
* created for an oplog which no longer permits us to use itself
*
* @param entry DiskEntry object representing the current Entry
*/
private void basicCreate(DiskRegion dr, DiskEntry entry, ValueWrapper value, byte userBits, boolean async) throws IOException, InterruptedException {
DiskId id = entry.getDiskId();
boolean useNextOplog = false;
long startPosForSynchOp = -1;
if (DiskStoreImpl.KRF_DEBUG) {
// wait for cache close to create krf
System.out.println("basicCreate KRF_DEBUG");
Thread.sleep(1000);
}
synchronized (this.lock) {
// TODO soplog perf analysis shows this as a
// contention point
// synchronized (this.crf) {
initOpState(OPLOG_NEW_ENTRY_0ID, dr, entry, value, userBits, false);
// Check if the current data in ByteBuffer will cause a
// potential increase in the size greater than the max allowed
long temp = (getOpStateSize() + this.crf.currSize);
if (!this.wroteNewEntryBase) {
temp += OPLOG_NEW_ENTRY_BASE_REC_SIZE;
}
if (this != getOplogSet().getChild()) {
useNextOplog = true;
} else if (temp > getMaxCrfSize() && !isFirstRecord()) {
switchOpLog(dr, getOpStateSize(), entry);
useNextOplog = true;
} else {
if (this.lockedForKRFcreate) {
CacheClosedException cce = new CacheClosedException("The disk store is closed.");
dr.getCancelCriterion().checkCancelInProgress(cce);
throw cce;
}
this.firstRecord = false;
writeNewEntryBaseRecord(async);
// Now we can finally call newOplogEntryId.
// We need to make sure the create records
// are written in the same order as they are created.
// This allows us to not encode the oplogEntryId explicitly in the
// record
long createOplogEntryId = getOplogSet().newOplogEntryId();
id.setKeyId(createOplogEntryId);
// startPosForSynchOp = this.crf.currSize;
// Allow it to be added to the OpLOg so increase the
// size of currenstartPosForSynchOpt oplog
int dataLength = getOpStateSize();
// It is necessary that we set the
// Oplog ID here without releasing the lock on object as we are
// writing to the file after releasing the lock. This can cause
// a situation where the
// switching thread has added Oplog for compaction while the previous
// thread has still not started writing. Thus compactor can
// miss an entry as the oplog Id was not set till then.
// This is because a compactor thread will iterate over the entries &
// use only those which have OplogID equal to that of Oplog being
// compacted without taking any lock. A lock is taken only if the
// entry is a potential candidate.
// Further the compactor may delete the file as a compactor thread does
// not require to take any shared/exclusive lock at DiskStoreImpl
// or Oplog level.
// It is also assumed that compactor thread will take a lock on both
// entry as well as DiskID while compacting. In case of synch
// mode we can
// safely set OplogID without taking lock on DiskId. But
// for asynch mode
// we have to take additional precaution as the asynch
// writer of previous
// oplog can interfere with the current oplog.
id.setOplogId(getOplogId());
// do the io while holding lock so that switch can set doneAppending
// Write the data to the opLog for the synch mode
startPosForSynchOp = writeOpLogBytes(this.crf, async, true);
// if (this.crf.currSize != startPosForSynchOp) {
// assert false;
// }
this.crf.currSize = temp;
if (EntryBits.isNeedsValue(userBits)) {
id.setValueLength(value.getLength());
} else {
id.setValueLength(0);
}
id.setUserBits(userBits);
if (logger.isTraceEnabled()) {
logger.trace("Oplog::basicCreate:Release dByteBuffer with data for Disk ID = {}", id);
}
// As such for any put or get operation , a synch is taken
// on the Entry object in the DiskEntry's Helper functions.
// Compactor thread will also take a lock on entry object. Therefore
// we do not require a lock on DiskID, as concurrent access for
// value will not occur.
startPosForSynchOp += getOpStateValueOffset();
if (logger.isTraceEnabled(LogMarker.PERSIST_WRITES)) {
VersionTag tag = null;
if (entry.getVersionStamp() != null) {
tag = entry.getVersionStamp().asVersionTag();
}
logger.trace(LogMarker.PERSIST_WRITES, "basicCreate: id=<{}> key=<{}> valueOffset={} userBits={} valueLen={} valueBytes={} drId={} versionTag={} oplog#{}", abs(id.getKeyId()), entry.getKey(), startPosForSynchOp, userBits, (value != null ? value.getLength() : 0), value.getBytesAsString(), dr.getId(), tag, getOplogId());
}
id.setOffsetInOplog(startPosForSynchOp);
addLive(dr, entry);
// Size of the current oplog being increased
// due to 'create' operation. Set the change in stats.
this.dirHolder.incrementTotalOplogSize(dataLength);
incTotalCount();
// Update the region version vector for the disk store.
// This needs to be done under lock so that we don't switch oplogs
// unit the version vector accurately represents what is in this oplog
RegionVersionVector rvv = dr.getRegionVersionVector();
if (rvv != null && entry.getVersionStamp() != null) {
rvv.recordVersion(entry.getVersionStamp().getMemberID(), entry.getVersionStamp().getRegionVersion());
}
EntryLogger.logPersistPut(dr.getName(), entry.getKey(), dr.getDiskStoreID());
}
clearOpState();
// }
}
if (useNextOplog) {
if (LocalRegion.ISSUE_CALLBACKS_TO_CACHE_OBSERVER) {
CacheObserverHolder.getInstance().afterSwitchingOplog();
}
Assert.assertTrue(this != getOplogSet().getChild());
getOplogSet().getChild().basicCreate(dr, entry, value, userBits, async);
} else {
if (LocalRegion.ISSUE_CALLBACKS_TO_CACHE_OBSERVER) {
CacheObserverHolder.getInstance().afterSettingOplogOffSet(startPosForSynchOp);
}
}
}
use of org.apache.geode.internal.cache.versions.RegionVersionVector in project geode by apache.
the class Oplog method okToSkipRegion.
/**
* Returns true if the drId region has been destroyed or if oplogKeyId preceeds the last clear
* done on the drId region
*/
private OkToSkipResult okToSkipRegion(DiskRegionView drv, long oplogKeyId, VersionTag tag) {
long lastClearKeyId = drv.getClearOplogEntryId();
if (lastClearKeyId != DiskStoreImpl.INVALID_ID) {
if (logger.isTraceEnabled(LogMarker.PERSIST_RECOVERY)) {
logger.trace(LogMarker.PERSIST_RECOVERY, "lastClearKeyId={} oplogKeyId={}", lastClearKeyId, oplogKeyId);
}
if (lastClearKeyId >= 0) {
if (oplogKeyId <= lastClearKeyId) {
if (logger.isTraceEnabled(LogMarker.PERSIST_RECOVERY)) {
logger.trace(LogMarker.PERSIST_RECOVERY, "okToSkip because oplogKeyId={} <= lastClearKeyId={} for drId={}", oplogKeyId, lastClearKeyId, drv.getId());
}
// @todo add some wraparound logic
return OkToSkipResult.SKIP_RECORD;
}
} else {
// treat it like an unsigned value (-1 == MAX_UNSIGNED)
if (oplogKeyId > 0 || oplogKeyId <= lastClearKeyId) {
// if it is < lastClearKeyId
if (logger.isTraceEnabled(LogMarker.PERSIST_RECOVERY)) {
logger.trace(LogMarker.PERSIST_RECOVERY, "okToSkip because oplogKeyId={} <= lastClearKeyId={} for drId={}", oplogKeyId, lastClearKeyId, drv.getId());
}
return OkToSkipResult.SKIP_RECORD;
}
}
}
RegionVersionVector clearRVV = drv.getClearRVV();
if (clearRVV != null) {
if (logger.isTraceEnabled(LogMarker.PERSIST_RECOVERY)) {
logger.trace(LogMarker.PERSIST_RECOVERY, "clearRVV={} tag={}", clearRVV, tag);
}
if (clearRVV.contains(tag.getMemberID(), tag.getRegionVersion())) {
if (logger.isTraceEnabled(LogMarker.PERSIST_RECOVERY)) {
logger.trace(LogMarker.PERSIST_RECOVERY, "okToSkip because tag={} <= clearRVV={} for drId={}", tag, clearRVV, drv.getId());
}
// because later modifies may use the oplog key id.
return OkToSkipResult.SKIP_VALUE;
}
}
return OkToSkipResult.DONT_SKIP;
}
Aggregations