Search in sources :

Example 6 with Released

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();
    }
}
Also used : Released(org.apache.geode.internal.offheap.annotations.Released) InternalDistributedMember(org.apache.geode.distributed.internal.membership.InternalDistributedMember) DataLocationException(org.apache.geode.internal.cache.DataLocationException) EntryEventImpl(org.apache.geode.internal.cache.EntryEventImpl) EntryNotFoundException(org.apache.geode.cache.EntryNotFoundException) PartitionedRegionDataStore(org.apache.geode.internal.cache.PartitionedRegionDataStore) PrimaryBucketException(org.apache.geode.internal.cache.PrimaryBucketException) ReplyException(org.apache.geode.distributed.internal.ReplyException)

Example 7 with Released

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();
        }
    }
}
Also used : IndexManager(org.apache.geode.cache.query.internal.index.IndexManager) Released(org.apache.geode.internal.offheap.annotations.Released) DiskAccessException(org.apache.geode.cache.DiskAccessException) StoredObject(org.apache.geode.internal.offheap.StoredObject)

Example 8 with Released

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();
    }
}
Also used : IndexManager(org.apache.geode.cache.query.internal.index.IndexManager) Released(org.apache.geode.internal.offheap.annotations.Released) DiskAccessException(org.apache.geode.cache.DiskAccessException) StoredObject(org.apache.geode.internal.offheap.StoredObject) Operation(org.apache.geode.cache.Operation)

Example 9 with Released

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;
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) Released(org.apache.geode.internal.offheap.annotations.Released) ConcurrentCacheModificationException(org.apache.geode.internal.cache.versions.ConcurrentCacheModificationException) IndexManager(org.apache.geode.cache.query.internal.index.IndexManager) CacheWriter(org.apache.geode.cache.CacheWriter) VersionTag(org.apache.geode.internal.cache.versions.VersionTag) DiskAccessException(org.apache.geode.cache.DiskAccessException) StoredObject(org.apache.geode.internal.offheap.StoredObject)

Example 10 with Released

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;
    }
}
Also used : IndexManager(org.apache.geode.cache.query.internal.index.IndexManager) QueryException(org.apache.geode.cache.query.QueryException) Released(org.apache.geode.internal.offheap.annotations.Released) Retained(org.apache.geode.internal.offheap.annotations.Retained) EntryNotFoundException(org.apache.geode.cache.EntryNotFoundException) GatewaySenderEventImpl(org.apache.geode.internal.cache.wan.GatewaySenderEventImpl) VersionTag(org.apache.geode.internal.cache.versions.VersionTag) StoredObject(org.apache.geode.internal.offheap.StoredObject) VersionStamp(org.apache.geode.internal.cache.versions.VersionStamp) IndexMaintenanceException(org.apache.geode.cache.query.IndexMaintenanceException) Released(org.apache.geode.internal.offheap.annotations.Released)

Aggregations

Released (org.apache.geode.internal.offheap.annotations.Released)57 StoredObject (org.apache.geode.internal.offheap.StoredObject)29 CacheWriterException (org.apache.geode.cache.CacheWriterException)13 EntryNotFoundException (org.apache.geode.cache.EntryNotFoundException)13 InternalDistributedMember (org.apache.geode.distributed.internal.membership.InternalDistributedMember)12 ConcurrentCacheModificationException (org.apache.geode.internal.cache.versions.ConcurrentCacheModificationException)9 GatewaySenderEventCallbackArgument (org.apache.geode.internal.cache.wan.GatewaySenderEventCallbackArgument)9 Retained (org.apache.geode.internal.offheap.annotations.Retained)9 EntryEventImpl (org.apache.geode.internal.cache.EntryEventImpl)8 VersionedObjectList (org.apache.geode.internal.cache.tier.sockets.VersionedObjectList)8 DiskAccessException (org.apache.geode.cache.DiskAccessException)6 Operation (org.apache.geode.cache.Operation)6 ReplyException (org.apache.geode.distributed.internal.ReplyException)6 RegionDestroyedException (org.apache.geode.cache.RegionDestroyedException)5 IndexManager (org.apache.geode.cache.query.internal.index.IndexManager)5 PartitionedRegionDataStore (org.apache.geode.internal.cache.PartitionedRegionDataStore)5 TimeoutException (org.apache.geode.cache.TimeoutException)4 EventID (org.apache.geode.internal.cache.EventID)4 IOException (java.io.IOException)3 ArrayList (java.util.ArrayList)3