use of org.apache.geode.internal.offheap.annotations.Released in project geode by apache.
the class InvalidateMessage method operateOnPartitionedRegion.
/**
* This method is called upon receipt and make the desired changes to the PartitionedRegion Note:
* It is very important that this message does NOT cause any deadlocks as the sender will wait
* indefinitely for the acknowledgement
*
* @throws EntryExistsException
* @throws DataLocationException
*/
@Override
protected boolean operateOnPartitionedRegion(DistributionManager dm, PartitionedRegion r, long startTime) throws EntryExistsException, DataLocationException {
InternalDistributedMember eventSender = originalSender;
if (eventSender == null) {
eventSender = getSender();
}
final Object key = getKey();
@Released final EntryEventImpl event = EntryEventImpl.create(r, getOperation(), key, null, /* newValue */
getCallbackArg(), false, /* originRemote - false to force distribution in buckets */
eventSender, true, /* generateCallbacks */
false);
try {
if (this.versionTag != null) {
this.versionTag.replaceNullIDs(getSender());
event.setVersionTag(this.versionTag);
}
if (this.bridgeContext != null) {
event.setContext(this.bridgeContext);
}
// Assert.assertTrue(eventId != null); bug #47235: region invalidation doesn't send event ids
event.setEventId(eventId);
event.setPossibleDuplicate(this.posDup);
PartitionedRegionDataStore ds = r.getDataStore();
boolean sendReply = true;
// boolean failed = false;
event.setInvokePRCallbacks(!notificationOnly);
if (!notificationOnly) {
Assert.assertTrue(ds != null, "This process should have storage for an item in " + this.toString());
try {
Integer bucket = Integer.valueOf(PartitionedRegionHelper.getHashKey(event));
event.setCausedByMessage(this);
r.getDataView().invalidateOnRemote(event, true, /* invokeCallbacks */
false);
this.versionTag = event.getVersionTag();
if (logger.isTraceEnabled(LogMarker.DM)) {
logger.trace(LogMarker.DM, "{} invalidateLocally in bucket: {}, key: {}", getClass().getName(), bucket, key);
}
} catch (DataLocationException e) {
((ForceReattemptException) e).checkKey(event.getKey());
throw e;
} catch (EntryNotFoundException eee) {
// failed = true;
if (logger.isDebugEnabled()) {
logger.debug("{}: operateOnRegion caught EntryNotFoundException {}", getClass().getName(), eee.getMessage(), eee);
}
sendReply(getSender(), getProcessorId(), dm, new ReplyException(eee), r, startTime);
// this prevents us from acking later
sendReply = false;
} catch (PrimaryBucketException pbe) {
sendReply(getSender(), getProcessorId(), dm, new ReplyException(pbe), r, startTime);
return false;
}
} else {
event.setRegion(r);
event.setOriginRemote(true);
if (this.versionTag != null) {
this.versionTag.replaceNullIDs(getSender());
event.setVersionTag(this.versionTag);
}
if (this.filterInfo != null) {
event.setLocalFilterInfo(this.filterInfo.getFilterInfo(dm.getDistributionManagerId()));
}
r.invokeInvalidateCallbacks(EnumListenerEvent.AFTER_INVALIDATE, event, r.isInitialized());
}
return sendReply;
} finally {
event.release();
}
}
use of org.apache.geode.internal.offheap.annotations.Released in project geode by apache.
the class AbstractRegionMap method txApplyInvalidate.
public void txApplyInvalidate(Object key, Object newValue, boolean didDestroy, TransactionId txId, TXRmtEvent txEvent, boolean localOp, EventID eventId, Object aCallbackArgument, List<EntryEventImpl> pendingCallbacks, FilterRoutingInfo filterRoutingInfo, ClientProxyMembershipID bridgeContext, TXEntryState txEntryState, VersionTag versionTag, long tailKey) {
// boolean didInvalidate = false;
final LocalRegion owner = _getOwner();
@Released EntryEventImpl cbEvent = null;
boolean forceNewEntry = !owner.isInitialized() && owner.isAllEvents();
final boolean hasRemoteOrigin = !((TXId) txId).getMemberId().equals(owner.getMyId());
DiskRegion dr = owner.getDiskRegion();
// Fix for Bug #44431. We do NOT want to update the region and wait
// later for index INIT as region.clear() can cause inconsistency if
// happened in parallel as it also does index INIT.
IndexManager oqlIndexManager = owner.getIndexManager();
if (oqlIndexManager != null) {
oqlIndexManager.waitForIndexInit();
}
try {
if (forceNewEntry) {
boolean opCompleted = false;
RegionEntry newRe = getEntryFactory().createEntry(owner, key, Token.REMOVED_PHASE1);
synchronized (newRe) {
try {
RegionEntry oldRe = putEntryIfAbsent(key, newRe);
while (!opCompleted && oldRe != null) {
synchronized (oldRe) {
if (oldRe.isRemovedPhase2()) {
owner.getCachePerfStats().incRetries();
_getMap().remove(key, oldRe);
oldRe = putEntryIfAbsent(key, newRe);
} else {
opCompleted = true;
final boolean oldWasTombstone = oldRe.isTombstone();
final int oldSize = owner.calculateRegionEntryValueSize(oldRe);
// OFFHEAP eei
Object oldValue = oldRe.getValueInVM(owner);
// Create an entry event only if the calling context is
// a receipt of a TXCommitMessage AND there are callbacks
// installed
// for this region
boolean invokeCallbacks = shouldCreateCBEvent(owner, owner.isInitialized());
boolean cbEventInPending = false;
cbEvent = createCBEvent(owner, localOp ? Operation.LOCAL_INVALIDATE : Operation.INVALIDATE, key, newValue, txId, txEvent, eventId, aCallbackArgument, filterRoutingInfo, bridgeContext, txEntryState, versionTag, tailKey);
try {
cbEvent.setRegionEntry(oldRe);
cbEvent.setOldValue(oldValue);
if (logger.isDebugEnabled()) {
logger.debug("txApplyInvalidate cbEvent={}", cbEvent);
}
txRemoveOldIndexEntry(Operation.INVALIDATE, oldRe);
if (didDestroy) {
oldRe.txDidDestroy(owner.cacheTimeMillis());
}
if (txEvent != null) {
txEvent.addInvalidate(owner, oldRe, oldRe.getKey(), newValue, aCallbackArgument);
}
oldRe.setValueResultOfSearch(false);
processAndGenerateTXVersionTag(owner, cbEvent, oldRe, txEntryState);
boolean clearOccured = false;
try {
oldRe.setValue(owner, oldRe.prepareValueForCache(owner, newValue, true));
EntryLogger.logTXInvalidate(_getOwnerObject(), key);
owner.updateSizeOnPut(key, oldSize, 0);
if (oldWasTombstone) {
owner.unscheduleTombstone(oldRe);
}
} catch (RegionClearedException rce) {
clearOccured = true;
}
owner.txApplyInvalidatePart2(oldRe, oldRe.getKey(), didDestroy, true);
// didInvalidate = true;
if (invokeCallbacks) {
switchEventOwnerAndOriginRemote(cbEvent, hasRemoteOrigin);
if (pendingCallbacks == null) {
owner.invokeTXCallbacks(EnumListenerEvent.AFTER_INVALIDATE, cbEvent, true);
} else {
pendingCallbacks.add(cbEvent);
cbEventInPending = true;
}
}
if (!clearOccured) {
lruEntryUpdate(oldRe);
}
if (shouldPerformConcurrencyChecks(owner, cbEvent) && txEntryState != null) {
txEntryState.setVersionTag(cbEvent.getVersionTag());
}
} finally {
if (!cbEventInPending)
cbEvent.release();
}
}
}
}
if (!opCompleted) {
boolean invokeCallbacks = shouldCreateCBEvent(owner, owner.isInitialized());
boolean cbEventInPending = false;
cbEvent = createCBEvent(owner, localOp ? Operation.LOCAL_INVALIDATE : Operation.INVALIDATE, key, newValue, txId, txEvent, eventId, aCallbackArgument, filterRoutingInfo, bridgeContext, txEntryState, versionTag, tailKey);
try {
cbEvent.setRegionEntry(newRe);
txRemoveOldIndexEntry(Operation.INVALIDATE, newRe);
newRe.setValueResultOfSearch(false);
boolean clearOccured = false;
try {
processAndGenerateTXVersionTag(owner, cbEvent, newRe, txEntryState);
newRe.setValue(owner, newRe.prepareValueForCache(owner, newValue, true));
EntryLogger.logTXInvalidate(_getOwnerObject(), key);
// we are putting in a new invalidated
owner.updateSizeOnCreate(newRe.getKey(), 0);
// entry
} catch (RegionClearedException rce) {
clearOccured = true;
}
owner.txApplyInvalidatePart2(newRe, newRe.getKey(), didDestroy, true);
if (invokeCallbacks) {
switchEventOwnerAndOriginRemote(cbEvent, hasRemoteOrigin);
if (pendingCallbacks == null) {
owner.invokeTXCallbacks(EnumListenerEvent.AFTER_INVALIDATE, cbEvent, true);
} else {
pendingCallbacks.add(cbEvent);
cbEventInPending = true;
}
}
opCompleted = true;
if (!clearOccured) {
lruEntryCreate(newRe);
incEntryCount(1);
}
if (shouldPerformConcurrencyChecks(owner, cbEvent) && txEntryState != null) {
txEntryState.setVersionTag(cbEvent.getVersionTag());
}
} finally {
if (!cbEventInPending)
cbEvent.release();
}
}
} finally {
if (!opCompleted) {
removeEntry(key, newRe, false);
}
}
}
} else {
/* !forceNewEntry */
RegionEntry re = getEntry(key);
if (re != null) {
synchronized (re) {
{
final int oldSize = owner.calculateRegionEntryValueSize(re);
boolean wasTombstone = re.isTombstone();
// OFFHEAP eei
Object oldValue = re.getValueInVM(owner);
// Create an entry event only if the calling context is
// a receipt of a TXCommitMessage AND there are callbacks
// installed
// for this region
boolean invokeCallbacks = shouldCreateCBEvent(owner, owner.isInitialized());
boolean cbEventInPending = false;
cbEvent = createCBEvent(owner, localOp ? Operation.LOCAL_INVALIDATE : Operation.INVALIDATE, key, newValue, txId, txEvent, eventId, aCallbackArgument, filterRoutingInfo, bridgeContext, txEntryState, versionTag, tailKey);
try {
cbEvent.setRegionEntry(re);
cbEvent.setOldValue(oldValue);
txRemoveOldIndexEntry(Operation.INVALIDATE, re);
if (didDestroy) {
re.txDidDestroy(owner.cacheTimeMillis());
}
if (txEvent != null) {
txEvent.addInvalidate(owner, re, re.getKey(), newValue, aCallbackArgument);
}
re.setValueResultOfSearch(false);
processAndGenerateTXVersionTag(owner, cbEvent, re, txEntryState);
boolean clearOccured = false;
try {
re.setValue(owner, re.prepareValueForCache(owner, newValue, true));
EntryLogger.logTXInvalidate(_getOwnerObject(), key);
if (wasTombstone) {
owner.unscheduleTombstone(re);
}
owner.updateSizeOnPut(key, oldSize, 0);
} catch (RegionClearedException rce) {
clearOccured = true;
}
owner.txApplyInvalidatePart2(re, re.getKey(), didDestroy, true);
// didInvalidate = true;
if (invokeCallbacks) {
switchEventOwnerAndOriginRemote(cbEvent, hasRemoteOrigin);
if (pendingCallbacks == null) {
owner.invokeTXCallbacks(EnumListenerEvent.AFTER_INVALIDATE, cbEvent, true);
} else {
pendingCallbacks.add(cbEvent);
cbEventInPending = true;
}
}
if (!clearOccured) {
lruEntryUpdate(re);
}
if (shouldPerformConcurrencyChecks(owner, cbEvent) && txEntryState != null) {
txEntryState.setVersionTag(cbEvent.getVersionTag());
}
} finally {
if (!cbEventInPending)
cbEvent.release();
}
}
}
} else {
// re == null
// Fix bug#43594
// In cases where bucket region is re-created, it may so happen
// that the invalidate is already applied on the Initial image
// provider, thus causing region entry to be absent.
// Notify clients with client events.
boolean cbEventInPending = false;
cbEvent = createCBEvent(owner, localOp ? Operation.LOCAL_INVALIDATE : Operation.INVALIDATE, key, newValue, txId, txEvent, eventId, aCallbackArgument, filterRoutingInfo, bridgeContext, txEntryState, versionTag, tailKey);
try {
switchEventOwnerAndOriginRemote(cbEvent, hasRemoteOrigin);
if (pendingCallbacks == null) {
owner.invokeTXCallbacks(EnumListenerEvent.AFTER_INVALIDATE, cbEvent, false);
} else {
pendingCallbacks.add(cbEvent);
cbEventInPending = true;
}
} finally {
if (!cbEventInPending)
cbEvent.release();
}
}
}
} catch (DiskAccessException dae) {
owner.handleDiskAccessException(dae);
throw dae;
} finally {
if (oqlIndexManager != null) {
oqlIndexManager.countDownIndexUpdaters();
}
}
}
use of org.apache.geode.internal.offheap.annotations.Released in project geode by apache.
the class AbstractRegionMap method txApplyPut.
public void txApplyPut(Operation p_putOp, Object key, Object nv, boolean didDestroy, TransactionId txId, TXRmtEvent txEvent, EventID eventId, Object aCallbackArgument, List<EntryEventImpl> pendingCallbacks, FilterRoutingInfo filterRoutingInfo, ClientProxyMembershipID bridgeContext, TXEntryState txEntryState, VersionTag versionTag, long tailKey) {
final LocalRegion owner = _getOwner();
if (owner == null) {
// "fix" for bug 32440
Assert.assertTrue(false, "The owner for RegionMap " + this + " is null");
}
Operation putOp = p_putOp;
Object newValue = nv;
final boolean hasRemoteOrigin = !((TXId) txId).getMemberId().equals(owner.getMyId());
final boolean isTXHost = txEntryState != null;
final boolean isClientTXOriginator = owner.cache.isClient() && !hasRemoteOrigin;
final boolean isRegionReady = owner.isInitialized();
@Released EntryEventImpl cbEvent = null;
boolean invokeCallbacks = shouldCreateCBEvent(owner, isRegionReady);
boolean cbEventInPending = false;
cbEvent = createCBEvent(owner, putOp, key, newValue, txId, txEvent, eventId, aCallbackArgument, filterRoutingInfo, bridgeContext, txEntryState, versionTag, tailKey);
try {
if (logger.isDebugEnabled()) {
logger.debug("txApplyPut cbEvent={}", cbEvent);
}
if (owner.isUsedForPartitionedRegionBucket()) {
newValue = EntryEventImpl.getCachedDeserializable(nv, cbEvent);
txHandleWANEvent(owner, cbEvent, txEntryState);
}
boolean opCompleted = false;
// Fix for Bug #44431. We do NOT want to update the region and wait
// later for index INIT as region.clear() can cause inconsistency if
// happened in parallel as it also does index INIT.
IndexManager oqlIndexManager = owner.getIndexManager();
if (oqlIndexManager != null) {
oqlIndexManager.waitForIndexInit();
}
try {
if (hasRemoteOrigin && !isTXHost && !isClientTXOriginator) {
// Otherwise use the standard create/update logic
if (!owner.isAllEvents() || (!putOp.isCreate() && isRegionReady)) {
// At this point we should only apply the update if the entry exists
// Fix for bug 32347.
RegionEntry re = getEntry(key);
if (re != null) {
synchronized (re) {
if (!re.isRemoved()) {
opCompleted = true;
putOp = putOp.getCorrespondingUpdateOp();
// Net writers are not called for received transaction data
final int oldSize = owner.calculateRegionEntryValueSize(re);
if (cbEvent != null) {
cbEvent.setRegionEntry(re);
// OFFHEAP eei
cbEvent.setOldValue(re.getValueInVM(owner));
}
boolean clearOccured = false;
// Set RegionEntry updateInProgress
if (owner.indexMaintenanceSynchronous) {
re.setUpdateInProgress(true);
}
try {
txRemoveOldIndexEntry(putOp, re);
if (didDestroy) {
re.txDidDestroy(owner.cacheTimeMillis());
}
if (txEvent != null) {
txEvent.addPut(putOp, owner, re, re.getKey(), newValue, aCallbackArgument);
}
re.setValueResultOfSearch(putOp.isNetSearch());
try {
processAndGenerateTXVersionTag(owner, cbEvent, re, txEntryState);
{
re.setValue(owner, re.prepareValueForCache(owner, newValue, cbEvent, !putOp.isCreate()));
}
if (putOp.isCreate()) {
owner.updateSizeOnCreate(key, owner.calculateRegionEntryValueSize(re));
} else if (putOp.isUpdate()) {
// Rahul : fix for 41694. Negative bucket size can also be
// an issue with normal GFE Delta and will have to be fixed
// in a similar manner and may be this fix the the one for
// other delta can be combined.
{
owner.updateSizeOnPut(key, oldSize, owner.calculateRegionEntryValueSize(re));
}
}
} catch (RegionClearedException rce) {
clearOccured = true;
}
{
long lastMod = owner.cacheTimeMillis();
EntryLogger.logTXPut(_getOwnerObject(), key, nv);
re.updateStatsForPut(lastMod, lastMod);
owner.txApplyPutPart2(re, re.getKey(), lastMod, false, didDestroy, clearOccured);
}
} finally {
if (re != null && owner.indexMaintenanceSynchronous) {
re.setUpdateInProgress(false);
}
}
if (invokeCallbacks) {
cbEvent.makeUpdate();
switchEventOwnerAndOriginRemote(cbEvent, hasRemoteOrigin);
if (pendingCallbacks == null) {
owner.invokeTXCallbacks(EnumListenerEvent.AFTER_UPDATE, cbEvent, hasRemoteOrigin);
} else {
pendingCallbacks.add(cbEvent);
cbEventInPending = true;
}
}
if (!clearOccured) {
lruEntryUpdate(re);
}
}
}
if (didDestroy && !opCompleted) {
owner.txApplyInvalidatePart2(re, re.getKey(), true, false);
}
}
if (owner.concurrencyChecksEnabled && txEntryState != null && cbEvent != null) {
txEntryState.setVersionTag(cbEvent.getVersionTag());
}
return;
}
}
RegionEntry newRe = getEntryFactory().createEntry(owner, key, Token.REMOVED_PHASE1);
synchronized (newRe) {
try {
RegionEntry oldRe = putEntryIfAbsent(key, newRe);
while (!opCompleted && oldRe != null) {
synchronized (oldRe) {
if (oldRe.isRemovedPhase2()) {
owner.getCachePerfStats().incRetries();
_getMap().remove(key, oldRe);
oldRe = putEntryIfAbsent(key, newRe);
} else {
opCompleted = true;
if (!oldRe.isRemoved()) {
putOp = putOp.getCorrespondingUpdateOp();
}
// Net writers are not called for received transaction data
final int oldSize = owner.calculateRegionEntryValueSize(oldRe);
final boolean oldIsRemoved = oldRe.isDestroyedOrRemoved();
if (cbEvent != null) {
cbEvent.setRegionEntry(oldRe);
// OFFHEAP eei
cbEvent.setOldValue(oldRe.getValueInVM(owner));
}
boolean clearOccured = false;
// Set RegionEntry updateInProgress
if (owner.indexMaintenanceSynchronous) {
oldRe.setUpdateInProgress(true);
}
try {
txRemoveOldIndexEntry(putOp, oldRe);
if (didDestroy) {
oldRe.txDidDestroy(owner.cacheTimeMillis());
}
if (txEvent != null) {
txEvent.addPut(putOp, owner, oldRe, oldRe.getKey(), newValue, aCallbackArgument);
}
oldRe.setValueResultOfSearch(putOp.isNetSearch());
try {
processAndGenerateTXVersionTag(owner, cbEvent, oldRe, txEntryState);
boolean wasTombstone = oldRe.isTombstone();
{
oldRe.setValue(owner, oldRe.prepareValueForCache(owner, newValue, cbEvent, !putOp.isCreate()));
if (wasTombstone) {
owner.unscheduleTombstone(oldRe);
}
}
if (putOp.isCreate()) {
owner.updateSizeOnCreate(key, owner.calculateRegionEntryValueSize(oldRe));
} else if (putOp.isUpdate()) {
// Rahul : fix for 41694. Negative bucket size can also be
// an issue with normal GFE Delta and will have to be fixed
// in a similar manner and may be this fix the the one for
// other delta can be combined.
{
owner.updateSizeOnPut(key, oldSize, owner.calculateRegionEntryValueSize(oldRe));
}
}
} catch (RegionClearedException rce) {
clearOccured = true;
}
{
long lastMod = owner.cacheTimeMillis();
EntryLogger.logTXPut(_getOwnerObject(), key, nv);
oldRe.updateStatsForPut(lastMod, lastMod);
owner.txApplyPutPart2(oldRe, oldRe.getKey(), lastMod, false, didDestroy, clearOccured);
}
} finally {
if (oldRe != null && owner.indexMaintenanceSynchronous) {
oldRe.setUpdateInProgress(false);
}
}
if (invokeCallbacks) {
if (!oldIsRemoved) {
cbEvent.makeUpdate();
}
switchEventOwnerAndOriginRemote(cbEvent, hasRemoteOrigin);
if (pendingCallbacks == null) {
owner.invokeTXCallbacks(cbEvent.op.isCreate() ? EnumListenerEvent.AFTER_CREATE : EnumListenerEvent.AFTER_UPDATE, cbEvent, true);
} else {
pendingCallbacks.add(cbEvent);
cbEventInPending = true;
}
}
if (!clearOccured) {
lruEntryUpdate(oldRe);
}
}
}
}
if (!opCompleted) {
putOp = putOp.getCorrespondingCreateOp();
if (cbEvent != null) {
cbEvent.setRegionEntry(newRe);
cbEvent.setOldValue(null);
}
boolean clearOccured = false;
// Set RegionEntry updateInProgress
if (owner.indexMaintenanceSynchronous) {
newRe.setUpdateInProgress(true);
}
try {
txRemoveOldIndexEntry(putOp, newRe);
// creating a new entry
if (didDestroy) {
newRe.txDidDestroy(owner.cacheTimeMillis());
}
if (txEvent != null) {
txEvent.addPut(putOp, owner, newRe, newRe.getKey(), newValue, aCallbackArgument);
}
newRe.setValueResultOfSearch(putOp.isNetSearch());
try {
processAndGenerateTXVersionTag(owner, cbEvent, newRe, txEntryState);
{
newRe.setValue(owner, newRe.prepareValueForCache(owner, newValue, cbEvent, !putOp.isCreate()));
}
owner.updateSizeOnCreate(newRe.getKey(), owner.calculateRegionEntryValueSize(newRe));
} catch (RegionClearedException rce) {
clearOccured = true;
}
{
long lastMod = owner.cacheTimeMillis();
EntryLogger.logTXPut(_getOwnerObject(), key, nv);
newRe.updateStatsForPut(lastMod, lastMod);
owner.txApplyPutPart2(newRe, newRe.getKey(), lastMod, true, didDestroy, clearOccured);
}
} finally {
if (newRe != null && owner.indexMaintenanceSynchronous) {
newRe.setUpdateInProgress(false);
}
}
opCompleted = true;
if (invokeCallbacks) {
cbEvent.makeCreate();
cbEvent.setOldValue(null);
switchEventOwnerAndOriginRemote(cbEvent, hasRemoteOrigin);
if (pendingCallbacks == null) {
owner.invokeTXCallbacks(EnumListenerEvent.AFTER_CREATE, cbEvent, true);
} else {
pendingCallbacks.add(cbEvent);
cbEventInPending = true;
}
}
if (!clearOccured) {
lruEntryCreate(newRe);
incEntryCount(1);
}
}
} finally {
if (!opCompleted) {
removeEntry(key, newRe, false);
}
}
}
if (owner.concurrencyChecksEnabled && txEntryState != null && cbEvent != null) {
txEntryState.setVersionTag(cbEvent.getVersionTag());
}
} catch (DiskAccessException dae) {
owner.handleDiskAccessException(dae);
throw dae;
} finally {
if (oqlIndexManager != null) {
oqlIndexManager.countDownIndexUpdaters();
}
}
} finally {
if (!cbEventInPending)
cbEvent.release();
}
}
use of org.apache.geode.internal.offheap.annotations.Released in project geode by apache.
the class AbstractRegionMap method basicPut.
/*
* returns null if the operation fails
*/
public RegionEntry basicPut(EntryEventImpl event, final long lastModified, final boolean ifNew, // only non-null if ifOld
final boolean ifOld, // only non-null if ifOld
Object expectedOldValue, boolean requireOldValue, final boolean overwriteDestroyed) throws CacheWriterException, TimeoutException {
final LocalRegion owner = _getOwner();
boolean clearOccured = false;
if (owner == null) {
// "fix" for bug 32440
Assert.assertTrue(false, "The owner for RegionMap " + this + " is null for event " + event);
}
if (logger.isTraceEnabled(LogMarker.LRU_TOMBSTONE_COUNT) && !(owner instanceof HARegion)) {
logger.trace(LogMarker.LRU_TOMBSTONE_COUNT, "ARM.basicPut called for {} expectedOldValue={} requireOldValue={} ifNew={} ifOld={} initialized={} overwriteDestroyed={}", event, expectedOldValue, requireOldValue, ifNew, ifOld, owner.isInitialized(), overwriteDestroyed);
}
RegionEntry result = null;
long lastModifiedTime = 0;
// copy into local var to prevent race condition with setter
final CacheWriter cacheWriter = owner.basicGetWriter();
final boolean cacheWrite = !event.isOriginRemote() && !event.isNetSearch() && event.isGenerateCallbacks() && (cacheWriter != null || owner.hasServerProxy() || owner.scope.isDistributed());
/*
* For performance reason, we try to minimize object creation and do as much work as we can
* outside of synchronization, especially getting distribution advice.
*/
final Set netWriteRecipients;
if (cacheWrite) {
if (cacheWriter == null && owner.scope.isDistributed()) {
netWriteRecipients = ((DistributedRegion) owner).getCacheDistributionAdvisor().adviseNetWrite();
} else {
netWriteRecipients = null;
}
} else {
netWriteRecipients = null;
}
// mbid: this has been added to maintain consistency between the disk region
// and the region map after clear() has been called. This will set the
// reference of the diskSegmentRegion as a ThreadLocal so that if the diskRegionSegment
// is later changed by another thread, we can do the necessary.
boolean uninitialized = !owner.isInitialized();
boolean retrieveOldValueForDelta = event.getDeltaBytes() != null && event.getRawNewValue() == null;
IndexManager oqlIndexManager = null;
lockForCacheModification(owner, event);
try {
try {
// Fix for Bug #44431. We do NOT want to update the region and wait
// later for index INIT as region.clear() can cause inconsistency if
// happened in parallel as it also does index INIT.
oqlIndexManager = owner.getIndexManager();
if (oqlIndexManager != null) {
oqlIndexManager.waitForIndexInit();
}
// fix for bug #42169, replace must go to server if entry not on client
boolean replaceOnClient = event.getOperation() == Operation.REPLACE && owner.getServerProxy() != null;
// Rather than having two different blocks for synchronizing oldRe
// and newRe, have only one block and synchronize re
RegionEntry re = null;
boolean eventRecorded = false;
boolean onlyExisting = ifOld && !replaceOnClient;
re = getOrCreateRegionEntry(owner, event, Token.REMOVED_PHASE1, null, onlyExisting, false);
if (re == null) {
return null;
}
while (true) {
synchronized (re) {
// and change its state
if (re.isRemovedPhase2()) {
_getOwner().getCachePerfStats().incRetries();
_getMap().remove(event.getKey(), re);
re = getOrCreateRegionEntry(owner, event, Token.REMOVED_PHASE1, null, onlyExisting, false);
if (re == null) {
// this will happen when onlyExisting is true
return null;
}
continue;
} else {
@Released Object oldValueForDelta = null;
if (retrieveOldValueForDelta) {
// defer the lruUpdateCallback to prevent a deadlock (see bug 51121).
final boolean disabled = disableLruUpdateCallback();
try {
// Old value is faulted in from disk if not found in memory.
// OFFHEAP: if we are synced on oldRe no
oldValueForDelta = re.getValue(owner);
// issue since we can use ARE's ref
} finally {
if (disabled) {
enableLruUpdateCallback();
}
}
}
try {
event.setRegionEntry(re);
// set old value in event
setOldValueInEvent(event, re, cacheWrite, requireOldValue);
if (!continueUpdate(re, event, ifOld, replaceOnClient)) {
return null;
}
// overwrite destroyed?
if (!continueOverwriteDestroyed(re, event, overwriteDestroyed, ifNew)) {
return null;
}
// check expectedOldValue
if (!satisfiesExpectedOldValue(event, re, expectedOldValue, replaceOnClient)) {
return null;
}
// invoke cacheWriter
invokeCacheWriter(re, event, cacheWrite, cacheWriter, netWriteRecipients, requireOldValue, expectedOldValue, replaceOnClient);
// notify index of an update
notifyIndex(re, true);
try {
try {
if (// if there is a
(cacheWrite && event.getOperation().isUpdate()) || // set
!re.isRemoved() || replaceOnClient) {
// update
updateEntry(event, requireOldValue, oldValueForDelta, re);
} else {
// create
createEntry(event, owner, re);
}
owner.recordEvent(event);
eventRecorded = true;
} catch (RegionClearedException rce) {
clearOccured = true;
owner.recordEvent(event);
} catch (ConcurrentCacheModificationException ccme) {
VersionTag tag = event.getVersionTag();
if (tag != null && tag.isTimeStampUpdated()) {
// Notify gateways of new time-stamp.
owner.notifyTimestampsToGateways(event);
}
throw ccme;
}
if (uninitialized) {
event.inhibitCacheListenerNotification(true);
}
updateLru(clearOccured, re, event);
lastModifiedTime = owner.basicPutPart2(event, re, !uninitialized, lastModifiedTime, clearOccured);
} finally {
notifyIndex(re, false);
}
result = re;
break;
} finally {
OffHeapHelper.release(oldValueForDelta);
if (re != null && !onlyExisting && !isOpComplete(re, event)) {
owner.cleanUpOnIncompleteOp(event, re);
} else if (re != null && owner.isUsedForPartitionedRegionBucket()) {
BucketRegion br = (BucketRegion) owner;
CachePerfStats stats = br.getPartitionedRegion().getCachePerfStats();
}
}
// try
}
}
// sync re
}
// end while
} catch (DiskAccessException dae) {
// Asif:Feel that it is safe to destroy the region here as there appears
// to be no chance of deadlock during region destruction
result = null;
this._getOwner().handleDiskAccessException(dae);
throw dae;
} finally {
if (oqlIndexManager != null) {
oqlIndexManager.countDownIndexUpdaters();
}
if (result != null) {
try {
// Note we do distribution after releasing all sync to avoid deadlock
final boolean invokeListeners = event.basicGetNewValue() != Token.TOMBSTONE;
owner.basicPutPart3(event, result, !uninitialized, lastModifiedTime, invokeListeners, ifNew, ifOld, expectedOldValue, requireOldValue);
} finally {
// for any recipients
if (!clearOccured) {
try {
lruUpdateCallback();
} catch (DiskAccessException dae) {
// Asif:Feel that it is safe to destroy the region here as there appears
// to be no chance of deadlock during region destruction
result = null;
this._getOwner().handleDiskAccessException(dae);
throw dae;
}
}
}
// finally
} else {
resetThreadLocals();
}
}
} finally {
releaseCacheModificationLock(owner, event);
}
return result;
}
use of org.apache.geode.internal.offheap.annotations.Released in project geode by apache.
the class AbstractRegionEntry method destroy.
/**
* @throws EntryNotFoundException if expectedOldValue is not null and is not equal to current
* value
*/
@Override
@Released
public boolean destroy(LocalRegion region, EntryEventImpl event, boolean inTokenMode, boolean cacheWrite, @Unretained Object expectedOldValue, boolean forceDestroy, boolean removeRecoveredEntry) throws CacheWriterException, EntryNotFoundException, TimeoutException, RegionClearedException {
// A design decision was made to not retrieve the old value from the disk
// if the entry has been evicted to only have the CacheListener afterDestroy
// method ignore it. We don't want to pay the performance penalty. The
// getValueInVM method does not retrieve the value from disk if it has been
// evicted. Instead, it uses the NotAvailable token.
//
// If the region is a WAN queue region, the old value is actually used by the
// afterDestroy callback on a secondary. It is not needed on a primary.
// Since the destroy that sets WAN_QUEUE_TOKEN always originates on the primary
// we only pay attention to WAN_QUEUE_TOKEN if the event is originRemote.
//
// We also read old value from disk or buffer
// in the case where there is a non-null expectedOldValue
// see PartitionedRegion#remove(Object key, Object value)
ReferenceCountHelper.skipRefCountTracking();
@Retained @Released Object curValue = _getValueRetain(region, true);
ReferenceCountHelper.unskipRefCountTracking();
boolean proceed;
try {
if (curValue == null) {
curValue = Token.NOT_AVAILABLE;
}
if (curValue == Token.NOT_AVAILABLE) {
// the state of the transmitting cache's entry & should be used here
if (event.getCallbackArgument() != null && event.getCallbackArgument().equals(RegionQueue.WAN_QUEUE_TOKEN) && event.isOriginRemote()) {
// check originRemote for bug 40508
// curValue = getValue(region); can cause deadlock if GII is occurring
curValue = getValueOnDiskOrBuffer(region);
} else {
FilterProfile fp = region.getFilterProfile();
if (fp != null && (fp.getCqCount() > 0 || expectedOldValue != null)) {
// curValue = getValue(region); can cause deadlock will fault in the value
// and will confuse LRU.
curValue = getValueOnDiskOrBuffer(region);
}
}
}
if (expectedOldValue != null) {
if (!checkExpectedOldValue(expectedOldValue, curValue, region)) {
throw new EntryNotFoundException(LocalizedStrings.AbstractRegionEntry_THE_CURRENT_VALUE_WAS_NOT_EQUAL_TO_EXPECTED_VALUE.toLocalizedString());
}
}
if (inTokenMode && event.hasOldValue()) {
proceed = true;
} else {
proceed = event.setOldValue(curValue, curValue instanceof GatewaySenderEventImpl) || removeRecoveredEntry || forceDestroy || region.getConcurrencyChecksEnabled() || (event.getOperation() == Operation.REMOVE && (curValue == null || curValue == Token.LOCAL_INVALID || curValue == Token.INVALID));
}
} finally {
OffHeapHelper.releaseWithNoTracking(curValue);
}
if (proceed) {
// after the entry not found exception above.
if (!removeRecoveredEntry) {
region.generateAndSetVersionTag(event, this);
}
if (cacheWrite) {
region.cacheWriteBeforeDestroy(event, expectedOldValue);
if (event.getRegion().getServerProxy() != null) {
// server will return a version tag
// update version information (may throw ConcurrentCacheModificationException)
VersionStamp stamp = getVersionStamp();
if (stamp != null) {
stamp.processVersionTag(event);
}
}
}
region.recordEvent(event);
// RegionEntry (the old value) is invalid
if (!region.isProxy() && !isInvalid()) {
IndexManager indexManager = region.getIndexManager();
if (indexManager != null) {
try {
if (isValueNull()) {
@Released Object value = getValueOffHeapOrDiskWithoutFaultIn(region);
try {
Object preparedValue = prepareValueForCache(region, value, false);
_setValue(preparedValue);
releaseOffHeapRefIfRegionBeingClosedOrDestroyed(region, preparedValue);
} finally {
OffHeapHelper.release(value);
}
}
indexManager.updateIndexes(this, IndexManager.REMOVE_ENTRY, IndexProtocol.OTHER_OP);
} catch (QueryException e) {
throw new IndexMaintenanceException(e);
}
}
}
boolean removeEntry = false;
VersionTag v = event.getVersionTag();
if (region.concurrencyChecksEnabled && !removeRecoveredEntry && !event.isFromRILocalDestroy()) {
// Destroy will write a tombstone instead
if (v == null || !v.hasValidVersion()) {
// localDestroy and eviction and ops received with no version tag
// should create a tombstone using the existing version stamp, as should
// (bug #45245) responses from servers that do not have valid version information
VersionStamp stamp = this.getVersionStamp();
if (stamp != null) {
// proxy has no stamps
v = stamp.asVersionTag();
event.setVersionTag(v);
}
}
removeEntry = v == null || !v.hasValidVersion();
} else {
removeEntry = true;
}
if (removeEntry) {
boolean isThisTombstone = isTombstone();
if (inTokenMode && !event.getOperation().isEviction()) {
setValue(region, Token.DESTROYED);
} else {
removePhase1(region, false);
}
if (isThisTombstone) {
region.unscheduleTombstone(this);
}
} else {
makeTombstone(region, v);
}
return true;
} else {
return false;
}
}
Aggregations