Search in sources :

Example 1 with GatewayConflictHelper

use of org.apache.geode.cache.util.GatewayConflictHelper in project geode by apache.

the class AbstractRegionEntry method processGatewayTag.

private boolean processGatewayTag(EntryEvent cacheEvent) {
    // Gateway tags are installed in the server-side LocalRegion cache
    // modification methods. They do not have version numbers or distributed
    // member IDs. Instead they only have timestamps and distributed system IDs.
    // If there is a resolver plug-in, invoke it. Otherwise we use the timestamps and
    // distributed system IDs to determine whether to allow the event to proceed.
    final boolean isDebugEnabled = logger.isDebugEnabled();
    if (this.isRemoved() && !this.isTombstone()) {
        // no conflict on a new entry
        return true;
    }
    EntryEventImpl event = (EntryEventImpl) cacheEvent;
    VersionTag tag = event.getVersionTag();
    long stampTime = getVersionStamp().getVersionTimeStamp();
    long tagTime = tag.getVersionTimeStamp();
    int stampDsid = getVersionStamp().getDistributedSystemId();
    int tagDsid = tag.getDistributedSystemId();
    if (isDebugEnabled) {
        logger.debug("processing gateway version information for {}.  Stamp dsid={} time={} Tag dsid={} time={}", event.getKey(), stampDsid, stampTime, tagDsid, tagTime);
    }
    if (tagTime == VersionTag.ILLEGAL_VERSION_TIMESTAMP) {
        // no timestamp received from other system - just apply it
        return true;
    }
    if (tagDsid == stampDsid || stampDsid == -1) {
        return true;
    }
    GatewayConflictResolver resolver = event.getRegion().getCache().getGatewayConflictResolver();
    if (resolver != null) {
        if (isDebugEnabled) {
            logger.debug("invoking gateway conflict resolver");
        }
        final boolean[] disallow = new boolean[1];
        final Object[] newValue = new Object[] { this };
        GatewayConflictHelper helper = new GatewayConflictHelper() {

            @Override
            public void disallowEvent() {
                disallow[0] = true;
            }

            @Override
            public void changeEventValue(Object value) {
                newValue[0] = value;
            }
        };
        @Released TimestampedEntryEventImpl timestampedEvent = (TimestampedEntryEventImpl) event.getTimestampedEvent(tagDsid, stampDsid, tagTime, stampTime);
        // gateway conflict resolvers will usually want to see the old value
        if (!timestampedEvent.hasOldValue() && isRemoved()) {
            // OFFHEAP: since isRemoved I think getValue will never be stored off heap in this case
            timestampedEvent.setOldValue(getValue(timestampedEvent.getRegion()));
        }
        Throwable thr = null;
        try {
            resolver.onEvent(timestampedEvent, helper);
        } catch (CancelException cancelled) {
            throw cancelled;
        } catch (VirtualMachineError err) {
            SystemFailure.initiateFailure(err);
            // now, so don't let this thread continue.
            throw err;
        } catch (Throwable t) {
            // Whenever you catch Error or Throwable, you must also
            // catch VirtualMachineError (see above). However, there is
            // _still_ a possibility that you are dealing with a cascading
            // error condition, so you also need to check to see if the JVM
            // is still usable:
            SystemFailure.checkFailure();
            logger.error(LocalizedMessage.create(LocalizedStrings.LocalRegion_EXCEPTION_OCCURRED_IN_CONFLICTRESOLVER), t);
            thr = t;
        } finally {
            timestampedEvent.release();
        }
        if (isDebugEnabled) {
            logger.debug("done invoking resolver", thr);
        }
        if (thr == null) {
            if (disallow[0]) {
                if (isDebugEnabled) {
                    logger.debug("conflict resolver rejected the event for {}", event.getKey());
                }
                throw new ConcurrentCacheModificationException("WAN conflict resolver rejected the operation");
            }
            tag.setAllowedByResolver(true);
            if (newValue[0] != this) {
                if (isDebugEnabled) {
                    logger.debug("conflict resolver changed the value of the event for {}", event.getKey());
                }
                // the resolver changed the event value!
                event.setNewValue(newValue[0]);
            }
            // if nothing was done then we allow the event
            if (isDebugEnabled) {
                logger.debug("change was allowed by conflict resolver: {}", tag);
            }
            return true;
        }
    }
    if (isDebugEnabled) {
        logger.debug("performing normal WAN conflict check");
    }
    if (tagTime > stampTime || tagTime == stampTime && tagDsid >= stampDsid) {
        if (isDebugEnabled) {
            logger.debug("allowing event");
        }
        return true;
    }
    if (isDebugEnabled) {
        logger.debug("disallowing event for {}", event.getKey());
    }
    throw new ConcurrentCacheModificationException("conflicting WAN event detected");
}
Also used : Released(org.apache.geode.internal.offheap.annotations.Released) GatewayConflictResolver(org.apache.geode.cache.util.GatewayConflictResolver) ConcurrentCacheModificationException(org.apache.geode.internal.cache.versions.ConcurrentCacheModificationException) GatewayConflictHelper(org.apache.geode.cache.util.GatewayConflictHelper) VersionTag(org.apache.geode.internal.cache.versions.VersionTag) StoredObject(org.apache.geode.internal.offheap.StoredObject) CancelException(org.apache.geode.CancelException)

Aggregations

CancelException (org.apache.geode.CancelException)1 GatewayConflictHelper (org.apache.geode.cache.util.GatewayConflictHelper)1 GatewayConflictResolver (org.apache.geode.cache.util.GatewayConflictResolver)1 ConcurrentCacheModificationException (org.apache.geode.internal.cache.versions.ConcurrentCacheModificationException)1 VersionTag (org.apache.geode.internal.cache.versions.VersionTag)1 StoredObject (org.apache.geode.internal.offheap.StoredObject)1 Released (org.apache.geode.internal.offheap.annotations.Released)1