Search in sources :

Example 6 with FutureResult

use of org.apache.geode.internal.util.concurrent.FutureResult in project geode by apache.

the class DLockService method becomeLockGrantor.

/**
   * @param predecessor non-null if a predecessor asked us to take over for him
   */
void becomeLockGrantor(InternalDistributedMember predecessor) {
    Assert.assertTrue(predecessor == null);
    boolean ownLockGrantorFutureResult = false;
    FutureResult lockGrantorFutureResultRef = null;
    final boolean isDebugEnabled_DLS = logger.isTraceEnabled(LogMarker.DLS);
    LockGrantorId myLockGrantorId = null;
    try {
        // terminate loop if this thread gets control of lockGrantorFutureResult
        while (!ownLockGrantorFutureResult) {
            Assert.assertHoldsLock(this.destroyLock, false);
            synchronized (this.lockGrantorIdLock) {
                if (isCurrentlyOrIsMakingLockGrantor()) {
                    return;
                } else if (this.lockGrantorFutureResult != null) {
                    // need to wait for other thread controlling lockGrantorFutureResult
                    lockGrantorFutureResultRef = this.lockGrantorFutureResult;
                } else {
                    // this thread is in control and will procede to become grantor
                    // create new lockGrantorFutureResult for other threads to block on
                    ownLockGrantorFutureResult = true;
                    lockGrantorFutureResultRef = new FutureResult(this.dm.getCancelCriterion());
                    if (isDebugEnabled_DLS) {
                        logger.trace(LogMarker.DLS, "[becomeLockGrantor] creating lockGrantorFutureResult");
                    }
                    this.lockGrantorFutureResult = lockGrantorFutureResultRef;
                }
            }
            if (!ownLockGrantorFutureResult) {
                waitForLockGrantorFutureResult(lockGrantorFutureResultRef, 0, TimeUnit.MILLISECONDS);
                continue;
            }
        }
        // this thread is now in charge of the lockGrantorFutureResult future
        getStats().incBecomeGrantorRequests();
        // create the new grantor instance in non-ready state...
        long tempGrantorVersion = -1;
        LockGrantorId tempLockGrantorId = new LockGrantorId(this.dm, this.dm.getId(), tempGrantorVersion, getSerialNumber());
        DLockGrantor myGrantor = DLockGrantor.createGrantor(this, tempGrantorVersion);
        try {
            synchronized (this.lockGrantorIdLock) {
                Assert.assertTrue(setLockGrantorId(tempLockGrantorId, myGrantor));
            }
            if (isDebugEnabled_DLS) {
                logger.trace(LogMarker.DLS, "become set lockGrantorId to {} for service {}", this.lockGrantorId, this.serviceName);
            }
            InternalDistributedMember elder = getElderId();
            Assert.assertTrue(elder != null);
            // NOTE: elder currently returns GrantorInfo for the previous grantor
            // CONSIDER: add elderCommunicatedWith to GrantorInfo
            GrantorInfo gi = becomeGrantor(predecessor);
            boolean needsRecovery = gi.needsRecovery();
            long myGrantorVersion = gi.getVersionId() + 1;
            myGrantor.setVersionId(myGrantorVersion);
            myLockGrantorId = new LockGrantorId(this.dm, this.dm.getId(), myGrantorVersion, getSerialNumber());
            if (isDebugEnabled_DLS) {
                logger.trace(LogMarker.DLS, "[becomeLockGrantor] Calling makeLocalGrantor");
            }
            if (!makeLocalGrantor(elder, needsRecovery, myLockGrantorId, myGrantor)) {
                return;
            }
        } finally {
            Assert.assertTrue(myGrantor == null || !myGrantor.isInitializing() || this.dm.getCancelCriterion().isCancelInProgress() || isDestroyed(), "BecomeLockGrantor failed and left grantor non-ready");
        }
    } finally {
        synchronized (this.lockGrantorIdLock) {
            if (ownLockGrantorFutureResult) {
                // this thread is doing the real work and must finish the future
                Assert.assertTrue(this.lockGrantorFutureResult == lockGrantorFutureResultRef);
                boolean getLockGrantorIdFailed = myLockGrantorId == null;
                if (getLockGrantorIdFailed) {
                    // failed so cancel lockGrantorFutureResult
                    // interrupt waiting threads
                    lockGrantorFutureResultRef.cancel(true);
                } else {
                    // don't succeed if shutting
                    this.dm.getCancelCriterion().checkCancelInProgress(null);
                    // down
                    // succeeded so set lockGrantorFutureResult
                    lockGrantorFutureResultRef.set(myLockGrantorId);
                }
                // null out the reference so it is free for next usage
                this.lockGrantorFutureResult = null;
            }
        }
    }
}
Also used : FutureResult(org.apache.geode.internal.util.concurrent.FutureResult) InternalDistributedMember(org.apache.geode.distributed.internal.membership.InternalDistributedMember)

Example 7 with FutureResult

use of org.apache.geode.internal.util.concurrent.FutureResult in project geode by apache.

the class DLockService method notLockGrantorId.

/**
   * nulls out grantor to force call to elder
   * 
   * @param timeToWait how long to wait for a new grantor. -1 don't wait, 0 no time limit
   * @param timeUnit the unit of measure of timeToWait
   */
private void notLockGrantorId(LockGrantorId notLockGrantorId, long timeToWait, final TimeUnit timeUnit) {
    if (notLockGrantorId.isLocal(getSerialNumber())) {
        if (logger.isTraceEnabled(LogMarker.DLS)) {
            logger.trace(LogMarker.DLS, "notLockGrantorId {} returning early because notGrantor {} was equal to the local dm {}", this.serviceName, notLockGrantorId, this.dm.getId());
        }
        // Let the local destroy or processing of transfer do the clear
        return;
    }
    boolean ownLockGrantorFutureResult = false;
    FutureResult lockGrantorFutureResultRef = null;
    long statStart = -1;
    LockGrantorId currentLockGrantorId = null;
    try {
        Assert.assertHoldsLock(this.destroyLock, false);
        synchronized (this.lockGrantorIdLock) {
            currentLockGrantorId = this.lockGrantorId;
            if (this.lockGrantorFutureResult != null) {
                // some other thread is talking to elder
                lockGrantorFutureResultRef = this.lockGrantorFutureResult;
            } else if (!notLockGrantorId.sameAs(currentLockGrantorId)) {
                return;
            } else {
                // this thread needs to talk to elder
                ownLockGrantorFutureResult = true;
                lockGrantorFutureResultRef = new FutureResult(this.dm.getCancelCriterion());
                this.lockGrantorFutureResult = lockGrantorFutureResultRef;
            }
        }
        statStart = getStats().startGrantorWait();
        if (!ownLockGrantorFutureResult) {
            if (timeToWait >= 0) {
                waitForLockGrantorFutureResult(lockGrantorFutureResultRef, timeToWait, timeUnit);
            }
            return;
        }
        InternalDistributedMember elder = getElderId();
        Assert.assertTrue(elder != null);
        LockGrantorId elderLockGrantorId = null;
        GrantorInfo gi = peekGrantor();
        if (gi.getId() != null) {
            elderLockGrantorId = new LockGrantorId(this.dm, gi.getId(), gi.getVersionId(), gi.getSerialNumber());
        }
        if (notLockGrantorId.sameAs(elderLockGrantorId)) {
            // elder says that notLockGrantorId is still the grantor...
            sleep(NOT_GRANTOR_SLEEP);
            return;
        } else {
            // elder says another member is the grantor
            nullLockGrantorId(notLockGrantorId);
            if (logger.isTraceEnabled(LogMarker.DLS)) {
                logger.trace(LogMarker.DLS, "notLockGrantorId cleared lockGrantorId for service {}", this.serviceName);
            }
        }
    } finally {
        synchronized (this.lockGrantorIdLock) {
            if (statStart > -1) {
                getStats().endGrantorWait(statStart, false);
            }
            if (ownLockGrantorFutureResult) {
                // this thread is doing the real work and must finish the future
                Assert.assertTrue(this.lockGrantorFutureResult == lockGrantorFutureResultRef);
                // cancel lockGrantorFutureResult
                lockGrantorFutureResultRef.cancel(false);
                // null out the reference so it is free for next usage
                this.lockGrantorFutureResult = null;
            }
        }
    }
// finally block for lockGrantorFutureResult
}
Also used : FutureResult(org.apache.geode.internal.util.concurrent.FutureResult) InternalDistributedMember(org.apache.geode.distributed.internal.membership.InternalDistributedMember)

Example 8 with FutureResult

use of org.apache.geode.internal.util.concurrent.FutureResult in project geode by apache.

the class LocalRegion method nonTxnFindObject.

/**
   * optimized to only allow one thread to do a search/load, other threads wait on a future
   * 
   * @param isCreate true if call found no entry; false if updating an existing entry
   * @param localValue the value retrieved from the region for this object.
   * @param disableCopyOnRead if true then do not make a copy
   * @param preferCD true if the preferred result form is CachedDeserializable
   * @param clientEvent the client event, if any
   * @param returnTombstones whether to return tombstones
   */
@Retained
Object nonTxnFindObject(KeyInfo keyInfo, boolean isCreate, boolean generateCallbacks, Object localValue, boolean disableCopyOnRead, boolean preferCD, ClientProxyMembershipID requestingClient, EntryEventImpl clientEvent, boolean returnTombstones) throws TimeoutException, CacheLoaderException {
    @Retained Object result = null;
    FutureResult thisFuture = new FutureResult(this.stopper);
    Future otherFuture = (Future) this.getFutures.putIfAbsent(keyInfo.getKey(), thisFuture);
    // only one thread can get their future into the map for this key at a time
    if (otherFuture != null) {
        try {
            Object[] valueAndVersion = (Object[]) otherFuture.get();
            if (valueAndVersion != null) {
                result = valueAndVersion[0];
                if (clientEvent != null) {
                    clientEvent.setVersionTag((VersionTag) valueAndVersion[1]);
                }
                if (!preferCD && result instanceof CachedDeserializable) {
                    CachedDeserializable cd = (CachedDeserializable) result;
                    // fix for bug 43023
                    if (!disableCopyOnRead && isCopyOnRead()) {
                        result = cd.getDeserializedWritableCopy(null, null);
                    } else {
                        result = cd.getDeserializedForReading();
                    }
                } else if (!disableCopyOnRead) {
                    result = conditionalCopy(result);
                }
                // what was a miss is now a hit
                if (isCreate) {
                    RegionEntry regionEntry = basicGetEntry(keyInfo.getKey());
                    updateStatsForGet(regionEntry, true);
                }
                return result;
            }
        // if value == null, try our own search/load
        } catch (InterruptedException ignore) {
            Thread.currentThread().interrupt();
            // TODO check a CancelCriterion here?
            return null;
        } catch (ExecutionException e) {
            // NOTE: this was creating InternalGemFireError and initCause with itself
            throw new InternalGemFireError(LocalizedStrings.LocalRegion_UNEXPECTED_EXCEPTION.toLocalizedString(), e);
        }
    }
    // condition where the future was just removed by another thread
    try {
        boolean partitioned = this.getDataPolicy().withPartitioning();
        if (!partitioned) {
            localValue = getDeserializedValue(null, keyInfo, isCreate, disableCopyOnRead, preferCD, clientEvent, false, false);
            // stats have now been updated
            if (localValue != null && !Token.isInvalid(localValue)) {
                result = localValue;
                return result;
            }
            isCreate = localValue == null;
            result = findObjectInSystem(keyInfo, isCreate, null, generateCallbacks, localValue, disableCopyOnRead, preferCD, requestingClient, clientEvent, returnTombstones);
        } else {
            // For PRs we don't want to deserialize the value and we can't use findObjectInSystem
            // because it can invoke code that is transactional.
            result = getSharedDataView().findObject(keyInfo, this, isCreate, generateCallbacks, localValue, disableCopyOnRead, preferCD, requestingClient, clientEvent, returnTombstones);
        }
        if (result == null && localValue != null) {
            if (localValue != Token.TOMBSTONE || returnTombstones) {
                result = localValue;
            }
        }
    // findObjectInSystem does not call conditionalCopy
    } finally {
        if (result != null) {
            VersionTag tag = clientEvent == null ? null : clientEvent.getVersionTag();
            thisFuture.set(new Object[] { result, tag });
        } else {
            thisFuture.set(null);
        }
        this.getFutures.remove(keyInfo.getKey());
    }
    if (!disableCopyOnRead) {
        result = conditionalCopy(result);
    }
    return result;
}
Also used : Retained(org.apache.geode.internal.offheap.annotations.Retained) FutureResult(org.apache.geode.internal.util.concurrent.FutureResult) VersionTag(org.apache.geode.internal.cache.versions.VersionTag) Future(java.util.concurrent.Future) StoredObject(org.apache.geode.internal.offheap.StoredObject) ExecutionException(java.util.concurrent.ExecutionException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) InternalGemFireError(org.apache.geode.InternalGemFireError) Retained(org.apache.geode.internal.offheap.annotations.Retained)

Example 9 with FutureResult

use of org.apache.geode.internal.util.concurrent.FutureResult in project geode by apache.

the class AdminDistributedSystemImpl method initializeCacheServers.

/**
   * Creates <code>CacheServer</code> instances for every cache server entry in the
   * {@link org.apache.geode.admin.DistributedSystemConfig}
   */
private void initializeCacheServers() {
    CacheServerConfig[] cacheServerConfigs = this.config.getCacheServerConfigs();
    for (int i = 0; i < cacheServerConfigs.length; i++) {
        try {
            CacheServerConfig conf = cacheServerConfigs[i];
            CacheServerConfigImpl copy = new CacheServerConfigImpl(conf);
            this.cacheServerSet.add(new FutureResult(createCacheServer(copy)));
        } catch (java.lang.Exception e) {
            logger.warn(e.getMessage(), e);
            continue;
        } catch (VirtualMachineError err) {
            SystemFailure.initiateFailure(err);
            // now, so don't let this thread continue.
            throw err;
        } catch (java.lang.Error e) {
            // 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(e.getMessage(), e);
            continue;
        }
    }
}
Also used : FutureResult(org.apache.geode.internal.util.concurrent.FutureResult)

Example 10 with FutureResult

use of org.apache.geode.internal.util.concurrent.FutureResult in project geode by apache.

the class DLockService method getLockGrantorId.

/**
   * Returns id of the current lock grantor for this service. If necessary, a request will be sent
   * to the elder to fetch this information.
   */
public LockGrantorId getLockGrantorId() {
    final boolean isDebugEnabled_DLS = logger.isTraceEnabled(LogMarker.DLS);
    boolean ownLockGrantorFutureResult = false;
    FutureResult lockGrantorFutureResultRef = null;
    long statStart = -1;
    LockGrantorId theLockGrantorId = null;
    while (theLockGrantorId == null) {
        ownLockGrantorFutureResult = false;
        try {
            Assert.assertHoldsLock(this.destroyLock, false);
            synchronized (this.lockGrantorIdLock) {
                if (this.lockGrantorFutureResult != null) {
                    lockGrantorFutureResultRef = this.lockGrantorFutureResult;
                } else if (this.lockGrantorId != null) {
                    return this.lockGrantorId;
                } else {
                    ownLockGrantorFutureResult = true;
                    lockGrantorFutureResultRef = new FutureResult(this.dm.getCancelCriterion());
                    if (isDebugEnabled_DLS) {
                        logger.trace(LogMarker.DLS, "[getLockGrantorId] creating lockGrantorFutureResult");
                    }
                    this.lockGrantorFutureResult = lockGrantorFutureResultRef;
                }
            }
            statStart = getStats().startGrantorWait();
            if (!ownLockGrantorFutureResult) {
                LockGrantorId lockGrantorIdRef = waitForLockGrantorFutureResult(lockGrantorFutureResultRef, 0, TimeUnit.MILLISECONDS);
                if (lockGrantorIdRef != null) {
                    return lockGrantorIdRef;
                } else {
                    continue;
                }
            }
            InternalDistributedMember elder = getElderId();
            Assert.assertTrue(elder != null);
            GrantorInfo gi = getGrantorRequest();
            theLockGrantorId = new LockGrantorId(this.dm, gi.getId(), gi.getVersionId(), gi.getSerialNumber());
            if (isDebugEnabled_DLS) {
                logger.trace(LogMarker.DLS, "[getLockGrantorId] elder says grantor is {}", theLockGrantorId);
            }
            // elder tells us to be the grantor...
            if (theLockGrantorId.isLocal(getSerialNumber())) {
                boolean needsRecovery = gi.needsRecovery();
                if (!needsRecovery) {
                    if (isDebugEnabled_DLS) {
                        logger.trace(LogMarker.DLS, "[getLockGrantorId] needsRecovery is false");
                    }
                    synchronized (this.lockGrantorIdLock) {
                        // either no previous grantor or grantor is newer
                        Assert.assertTrue(this.lockGrantorId == null || this.lockGrantorId.isNewerThan(theLockGrantorId) || this.lockGrantorId.sameAs(theLockGrantorId), this.lockGrantorId + " should be null or newer than or same as " + theLockGrantorId);
                    }
                }
                if (!createLocalGrantor(elder, needsRecovery, theLockGrantorId)) {
                    theLockGrantorId = this.lockGrantorId;
                }
            } else // elder says another member is the grantor
            {
                synchronized (this.lockGrantorIdLock) {
                    if (!setLockGrantorId(theLockGrantorId)) {
                        theLockGrantorId = this.lockGrantorId;
                    }
                }
            }
        } finally {
            synchronized (this.lockGrantorIdLock) {
                boolean getLockGrantorIdFailed = theLockGrantorId == null;
                if (statStart > -1) {
                    getStats().endGrantorWait(statStart, getLockGrantorIdFailed);
                }
                if (ownLockGrantorFutureResult) {
                    // this thread is doing the real work and must finish the future
                    Assert.assertTrue(this.lockGrantorFutureResult == lockGrantorFutureResultRef);
                    if (getLockGrantorIdFailed) {
                        // failed so cancel lockGrantorFutureResult
                        lockGrantorFutureResultRef.cancel(false);
                    } else {
                        // succeeded so set lockGrantorFutureResult
                        lockGrantorFutureResultRef.set(theLockGrantorId);
                    }
                    // null out the reference so it is free for next usage
                    this.lockGrantorFutureResult = null;
                }
            }
        }
    // finally block for lockGrantorFutureResult
    }
    // while theLockGrantorId == null
    return theLockGrantorId;
}
Also used : FutureResult(org.apache.geode.internal.util.concurrent.FutureResult) InternalDistributedMember(org.apache.geode.distributed.internal.membership.InternalDistributedMember)

Aggregations

FutureResult (org.apache.geode.internal.util.concurrent.FutureResult)10 InternalDistributedMember (org.apache.geode.distributed.internal.membership.InternalDistributedMember)3 InetAddress (java.net.InetAddress)1 ExecutionException (java.util.concurrent.ExecutionException)1 Future (java.util.concurrent.Future)1 RejectedExecutionException (java.util.concurrent.RejectedExecutionException)1 InternalGemFireError (org.apache.geode.InternalGemFireError)1 VersionTag (org.apache.geode.internal.cache.versions.VersionTag)1 StoredObject (org.apache.geode.internal.offheap.StoredObject)1 Retained (org.apache.geode.internal.offheap.annotations.Retained)1