use of org.apache.ignite.internal.util.future.GridFutureAdapter in project ignite by apache.
the class ClientComputeImpl method executeAsync0.
/**
* @param taskName Task name.
* @param arg Argument.
* @param clusterGrp Cluster group.
* @param flags Flags.
* @param timeout Timeout.
*/
private <T, R> IgniteClientFuture<R> executeAsync0(String taskName, @Nullable T arg, ClientClusterGroupImpl clusterGrp, byte flags, long timeout) throws ClientException {
Collection<UUID> nodeIds = clusterGrp.nodeIds();
if (F.isEmpty(taskName))
throw new ClientException("Task name can't be null or empty.");
if (nodeIds != null && nodeIds.isEmpty())
throw new ClientException("Cluster group is empty.");
Consumer<PayloadOutputChannel> payloadWriter = ch -> writeExecuteTaskRequest(ch, taskName, arg, nodeIds, flags, timeout);
Function<PayloadInputChannel, ClientComputeTask<R>> payloadReader = ch -> {
Long taskId = ch.in().readLong();
ClientComputeTask<R> task = new ClientComputeTask<>(utils, ch.clientChannel(), taskId);
ch.clientChannel().addNotificationListener(COMPUTE_TASK_FINISHED, taskId, task);
return task;
};
IgniteClientFuture<ClientComputeTask<R>> initFut = ch.serviceAsync(COMPUTE_TASK_EXECUTE, payloadWriter, payloadReader);
CompletableFuture<R> resFut = new CompletableFuture<>();
AtomicReference<Object> cancellationToken = new AtomicReference<>();
initFut.handle((task, err) -> handleExecuteInitFuture(resFut, cancellationToken, task, err));
return new IgniteClientFutureImpl<>(resFut, mayInterruptIfRunning -> {
// 2. initFut has completed - cancel compute future.
if (!cancellationToken.compareAndSet(null, mayInterruptIfRunning)) {
GridFutureAdapter<?> fut = (GridFutureAdapter<?>) cancellationToken.get();
if (!cancelGridFuture(fut, mayInterruptIfRunning))
return false;
}
resFut.cancel(mayInterruptIfRunning);
return true;
});
}
use of org.apache.ignite.internal.util.future.GridFutureAdapter in project ignite by apache.
the class GridCacheAdapter method asyncOp.
/**
* @param tx Transaction.
* @param op Cache operation.
* @param opCtx Cache operation context.
* @param <T> Return type.
* @return Future.
*/
@SuppressWarnings("unchecked")
protected <T> IgniteInternalFuture<T> asyncOp(GridNearTxLocal tx, final AsyncOp<T> op, final CacheOperationContext opCtx, final boolean retry) {
IgniteInternalFuture<T> fail = asyncOpAcquire(retry);
if (fail != null)
return fail;
FutureHolder holder = lastFut.get();
holder.lock();
try {
IgniteInternalFuture fut = holder.future();
final GridNearTxLocal tx0 = tx;
final CX1 clo = new CX1<IgniteInternalFuture<T>, T>() {
@Override
public T applyx(IgniteInternalFuture<T> tFut) throws IgniteCheckedException {
try {
return tFut.get();
} catch (IgniteTxTimeoutCheckedException | IgniteTxRollbackCheckedException | NodeStoppingException | IgniteConsistencyViolationException e) {
throw e;
} catch (IgniteCheckedException e1) {
try {
tx0.rollbackNearTxLocalAsync();
} catch (Throwable e2) {
if (e1 != e2)
e1.addSuppressed(e2);
}
throw e1;
} finally {
ctx.shared().txContextReset();
}
}
};
if (fut != null && !fut.isDone()) {
IgniteInternalFuture<T> f = new GridEmbeddedFuture(fut, (IgniteOutClosure<IgniteInternalFuture>) () -> {
GridFutureAdapter resFut = new GridFutureAdapter();
ctx.kernalContext().closure().runLocalSafe((GridPlainRunnable) () -> {
IgniteInternalFuture fut0;
if (ctx.kernalContext().isStopping())
fut0 = new GridFinishedFuture<>(new IgniteCheckedException("Operation has been cancelled (node or cache is stopping)."));
else if (ctx.gate().isStopped())
fut0 = new GridFinishedFuture<>(new CacheStoppedException(ctx.name()));
else {
ctx.operationContextPerCall(opCtx);
ctx.shared().txContextReset();
try {
fut0 = op.op(tx0).chain(clo);
} finally {
// It is necessary to clear tx context in this thread as well.
ctx.shared().txContextReset();
ctx.operationContextPerCall(null);
}
}
fut0.listen((IgniteInClosure<IgniteInternalFuture>) fut01 -> {
try {
resFut.onDone(fut01.get());
} catch (Throwable ex) {
resFut.onDone(ex);
}
});
}, true);
return resFut;
});
saveFuture(holder, f, retry);
return f;
}
/**
* Wait for concurrent tx operation to finish.
* See {@link GridDhtTxLocalAdapter#updateLockFuture(IgniteInternalFuture, IgniteInternalFuture)}
*/
if (!tx0.txState().implicitSingle())
tx0.txState().awaitLastFuture(ctx.shared());
IgniteInternalFuture<T> f;
try {
f = op.op(tx).chain(clo);
} finally {
// It is necessary to clear tx context in this thread as well.
ctx.shared().txContextReset();
}
saveFuture(holder, f, retry);
if (tx.implicit())
ctx.tm().resetContext();
return f;
} finally {
holder.unlock();
}
}
use of org.apache.ignite.internal.util.future.GridFutureAdapter in project ignite by apache.
the class GridNearTxLocal method getAllAsync.
/**
* @param cacheCtx Cache context.
* @param keys Keys to get.
* @param deserializeBinary Deserialize binary flag.
* @param skipVals Skip values flag.
* @param keepCacheObjects Keep cache objects
* @param skipStore Skip store flag.
* @param readRepairStrategy Read Repair strategy.
* @return Future for this get.
*/
@SuppressWarnings("unchecked")
public <K, V> IgniteInternalFuture<Map<K, V>> getAllAsync(final GridCacheContext cacheCtx, @Nullable final AffinityTopologyVersion entryTopVer, final Collection<KeyCacheObject> keys, final boolean deserializeBinary, final boolean skipVals, final boolean keepCacheObjects, final boolean skipStore, final boolean recovery, final ReadRepairStrategy readRepairStrategy, final boolean needVer) {
if (F.isEmpty(keys))
return new GridFinishedFuture<>(Collections.<K, V>emptyMap());
if (cacheCtx.mvccEnabled() && !isOperationAllowed(true))
return txTypeMismatchFinishFuture();
init();
int keysCnt = keys.size();
boolean single = keysCnt == 1;
try {
checkValid();
GridFutureAdapter<?> enlistFut = new GridFutureAdapter<>();
if (!updateLockFuture(null, enlistFut))
return new GridFinishedFuture<>(timedOut() ? timeoutException() : rollbackException());
final Map<K, V> retMap = new GridLeanMap<>(keysCnt);
final Map<KeyCacheObject, GridCacheVersion> missed = new GridLeanMap<>(pessimistic() ? keysCnt : 0);
CacheOperationContext opCtx = cacheCtx.operationContextPerCall();
ExpiryPolicy expiryPlc = opCtx != null ? opCtx.expiry() : null;
final Collection<KeyCacheObject> lockKeys;
try {
lockKeys = enlistRead(cacheCtx, entryTopVer, keys, expiryPlc, retMap, missed, keysCnt, deserializeBinary, skipVals, keepCacheObjects, skipStore, recovery, readRepairStrategy, needVer);
} catch (IgniteCheckedException e) {
return new GridFinishedFuture<>(e);
} finally {
finishFuture(enlistFut, null, true);
}
if (isRollbackOnly())
return new GridFinishedFuture<>(timedOut() ? timeoutException() : rollbackException());
if (single && missed.isEmpty())
return new GridFinishedFuture<>(retMap);
// Handle locks.
if (pessimistic() && !readCommitted() && !skipVals) {
if (expiryPlc == null)
expiryPlc = cacheCtx.expiry();
long accessTtl = expiryPlc != null ? CU.toTtl(expiryPlc.getExpiryForAccess()) : CU.TTL_NOT_CHANGED;
long createTtl = expiryPlc != null ? CU.toTtl(expiryPlc.getExpiryForCreation()) : CU.TTL_NOT_CHANGED;
long timeout = remainingTime();
if (timeout == -1)
return new GridFinishedFuture<>(timeoutException());
IgniteInternalFuture<Boolean> fut = cacheCtx.cache().txLockAsync(lockKeys, timeout, this, true, true, isolation, isInvalidate(), createTtl, accessTtl);
final ExpiryPolicy expiryPlc0 = expiryPlc;
PLC2<Map<K, V>> plc2 = new PLC2<Map<K, V>>() {
@Override
public IgniteInternalFuture<Map<K, V>> postLock() throws IgniteCheckedException {
if (log.isDebugEnabled())
log.debug("Acquired transaction lock for read on keys: " + lockKeys);
// Load keys only after the locks have been acquired.
for (KeyCacheObject cacheKey : lockKeys) {
K keyVal = (K) (keepCacheObjects ? cacheKey : cacheCtx.cacheObjectContext().unwrapBinaryIfNeeded(cacheKey, !deserializeBinary, true, null));
if (retMap.containsKey(keyVal))
// We already have a return value.
continue;
IgniteTxKey txKey = cacheCtx.txKey(cacheKey);
IgniteTxEntry txEntry = entry(txKey);
assert txEntry != null;
// Check if there is cached value.
while (true) {
GridCacheEntryEx cached = txEntry.cached();
CacheObject val = null;
GridCacheVersion readVer = null;
EntryGetResult getRes = null;
try {
Object transformClo = (!F.isEmpty(txEntry.entryProcessors()) && cctx.gridEvents().isRecordable(EVT_CACHE_OBJECT_READ)) ? F.first(txEntry.entryProcessors()) : null;
if (needVer) {
getRes = cached.innerGetVersioned(null, GridNearTxLocal.this, /*update-metrics*/
true, /*event*/
!skipVals, transformClo, resolveTaskName(), null, txEntry.keepBinary(), null);
if (getRes != null) {
val = getRes.value();
readVer = getRes.version();
}
} else {
val = cached.innerGet(null, GridNearTxLocal.this, /*read through*/
false, /*metrics*/
true, /*events*/
!skipVals, transformClo, resolveTaskName(), null, txEntry.keepBinary());
}
// If value is in cache and passed the filter.
if (val != null) {
missed.remove(cacheKey);
txEntry.setAndMarkValid(val);
if (!F.isEmpty(txEntry.entryProcessors()))
val = txEntry.applyEntryProcessors(val);
cacheCtx.addResult(retMap, cacheKey, val, skipVals, keepCacheObjects, deserializeBinary, false, getRes, readVer, 0, 0, needVer, U.deploymentClassLoader(cctx.kernalContext(), deploymentLdrId));
if (readVer != null)
txEntry.entryReadVersion(readVer);
}
// While.
break;
} catch (GridCacheEntryRemovedException ignore) {
if (log.isDebugEnabled())
log.debug("Got removed exception in get postLock (will retry): " + cached);
txEntry.cached(entryEx(cacheCtx, txKey, topologyVersion()));
}
}
}
if (!missed.isEmpty() && cacheCtx.isLocal()) {
AffinityTopologyVersion topVer = topologyVersionSnapshot();
if (topVer == null)
topVer = entryTopVer;
return checkMissed(cacheCtx, topVer != null ? topVer : topologyVersion(), retMap, missed, deserializeBinary, skipVals, keepCacheObjects, skipStore, recovery, readRepairStrategy, needVer, expiryPlc0);
}
if (readRepairStrategy != null) {
// Checking and repairing each locked entry (if necessary).
return new GridNearReadRepairFuture(topVer != null ? topVer : topologyVersion(), cacheCtx, keys, readRepairStrategy, !skipStore, taskName, deserializeBinary, recovery, cacheCtx.cache().expiryPolicy(expiryPlc0), GridNearTxLocal.this).chain((fut) -> {
try {
// For every fixed entry.
for (Map.Entry<KeyCacheObject, EntryGetResult> entry : fut.get().entrySet()) {
EntryGetResult getRes = entry.getValue();
KeyCacheObject key = entry.getKey();
enlistWrite(cacheCtx, entryTopVer, key, getRes != null ? getRes.value() : null, expiryPlc0, null, null, false, false, null, null, skipStore, false, !deserializeBinary, recovery, null);
// Rewriting fixed, initially filled by explicit lock operation.
if (getRes != null)
cacheCtx.addResult(retMap, key, getRes.value(), skipVals, keepCacheObjects, deserializeBinary, false, getRes, getRes.version(), 0, 0, needVer, U.deploymentClassLoader(cctx.kernalContext(), deploymentLdrId));
else
retMap.remove(keepCacheObjects ? key : cacheCtx.cacheObjectContext().unwrapBinaryIfNeeded(key, !deserializeBinary, false, U.deploymentClassLoader(cctx.kernalContext(), deploymentLdrId)));
}
return Collections.emptyMap();
} catch (Exception e) {
throw new GridClosureException(e);
}
});
}
return new GridFinishedFuture<>(Collections.emptyMap());
}
};
FinishClosure<Map<K, V>> finClos = new FinishClosure<Map<K, V>>() {
@Override
Map<K, V> finish(Map<K, V> loaded) {
retMap.putAll(loaded);
return retMap;
}
};
if (fut.isDone()) {
try {
IgniteInternalFuture<Map<K, V>> fut1 = plc2.apply(fut.get(), null);
return nonInterruptable(fut1.isDone() ? new GridFinishedFuture<>(finClos.apply(fut1.get(), null)) : new GridEmbeddedFuture<>(finClos, fut1));
} catch (GridClosureException e) {
return new GridFinishedFuture<>(e.unwrap());
} catch (IgniteCheckedException e) {
try {
return nonInterruptable(plc2.apply(false, e));
} catch (Exception e1) {
return new GridFinishedFuture<>(e1);
}
}
} else {
return nonInterruptable(new GridEmbeddedFuture<>(fut, plc2, finClos));
}
} else {
assert optimistic() || readCommitted() || skipVals;
if (!missed.isEmpty()) {
if (!readCommitted())
for (Iterator<KeyCacheObject> it = missed.keySet().iterator(); it.hasNext(); ) {
KeyCacheObject cacheKey = it.next();
K keyVal = (K) (keepCacheObjects ? cacheKey : cacheCtx.cacheObjectContext().unwrapBinaryIfNeeded(cacheKey, !deserializeBinary, false, null));
if (retMap.containsKey(keyVal))
it.remove();
}
if (missed.isEmpty())
return new GridFinishedFuture<>(retMap);
AffinityTopologyVersion topVer = topologyVersionSnapshot();
if (topVer == null)
topVer = entryTopVer;
return checkMissed(cacheCtx, topVer != null ? topVer : topologyVersion(), retMap, missed, deserializeBinary, skipVals, keepCacheObjects, skipStore, recovery, readRepairStrategy, needVer, expiryPlc);
}
return new GridFinishedFuture<>(retMap);
}
} catch (IgniteCheckedException e) {
setRollbackOnly();
return new GridFinishedFuture<>(e);
}
}
use of org.apache.ignite.internal.util.future.GridFutureAdapter in project ignite by apache.
the class GridNearTxLocal method enlistWrite.
/**
* @param cacheCtx Cache context.
* @param cacheKey Key to enlist.
* @param val Value.
* @param expiryPlc Explicitly specified expiry policy for entry.
* @param entryProcessor Entry processor (for invoke operation).
* @param invokeArgs Optional arguments for EntryProcessor.
* @param retval Flag indicating whether a value should be returned.
* @param lockOnly If {@code true}, then entry will be enlisted as noop.
* @param filter User filters.
* @param ret Return value.
* @param skipStore Skip store flag.
* @param singleRmv {@code True} for single key remove operation ({@link Cache#remove(Object)}.
* @param recovery Recovery flag.
* @param dataCenterId Optional data center Id.
* @return Future for entry values loading.
*/
private <K, V> IgniteInternalFuture<Void> enlistWrite(final GridCacheContext cacheCtx, @Nullable AffinityTopologyVersion entryTopVer, KeyCacheObject cacheKey, Object val, @Nullable ExpiryPolicy expiryPlc, @Nullable EntryProcessor<K, V, Object> entryProcessor, @Nullable Object[] invokeArgs, final boolean retval, boolean lockOnly, final CacheEntryPredicate[] filter, final GridCacheReturn ret, boolean skipStore, final boolean singleRmv, boolean keepBinary, boolean recovery, Byte dataCenterId) {
try (TraceSurroundings ignored2 = MTC.support(context().kernalContext().tracing().create(TX_NEAR_ENLIST_WRITE, MTC.span()))) {
GridFutureAdapter<Void> enlistFut = new GridFutureAdapter<>();
try {
if (!updateLockFuture(null, enlistFut))
return finishFuture(enlistFut, timedOut() ? timeoutException() : rollbackException(), false);
addActiveCache(cacheCtx, recovery);
final boolean hasFilters = !F.isEmptyOrNulls(filter) && !F.isAlwaysTrue(filter);
final boolean needVal = singleRmv || retval || hasFilters;
final boolean needReadVer = needVal && (serializable() && optimistic());
if (entryProcessor != null)
transform = true;
GridCacheVersion drVer = dataCenterId != null ? cacheCtx.cache().nextVersion(dataCenterId) : null;
boolean loadMissed = enlistWriteEntry(cacheCtx, entryTopVer, cacheKey, val, entryProcessor, invokeArgs, expiryPlc, retval, lockOnly, filter, /*drVer*/
drVer, /*drTtl*/
-1L, /*drExpireTime*/
-1L, ret, /*enlisted*/
null, skipStore, singleRmv, hasFilters, needVal, needReadVer, keepBinary, recovery);
if (loadMissed) {
AffinityTopologyVersion topVer = topologyVersionSnapshot();
if (topVer == null)
topVer = entryTopVer;
IgniteInternalFuture<Void> loadFut = loadMissing(cacheCtx, topVer != null ? topVer : topologyVersion(), Collections.singleton(cacheKey), filter, ret, needReadVer, singleRmv, hasFilters, /*read through*/
(entryProcessor != null || cacheCtx.config().isLoadPreviousValue()) && !skipStore, retval, keepBinary, recovery, expiryPlc);
loadFut.listen(new IgniteInClosure<IgniteInternalFuture<Void>>() {
@Override
public void apply(IgniteInternalFuture<Void> fut) {
try {
fut.get();
finishFuture(enlistFut, null, true);
} catch (IgniteCheckedException e) {
finishFuture(enlistFut, e, true);
}
}
});
return enlistFut;
}
finishFuture(enlistFut, null, true);
return enlistFut;
} catch (IgniteCheckedException e) {
return finishFuture(enlistFut, e, true);
}
}
}
use of org.apache.ignite.internal.util.future.GridFutureAdapter in project ignite by apache.
the class GridNearTxLocal method chainFinishFuture.
/**
* @param fut Already started finish future.
* @param commit Commit flag.
* @param clearThreadMap Clear thread map.
* @return Finish future.
*/
private IgniteInternalFuture<IgniteInternalTx> chainFinishFuture(final NearTxFinishFuture fut, final boolean commit, final boolean clearThreadMap, final boolean onTimeout) {
assert fut != null;
if (fut.commit() != commit) {
final GridNearTxLocal tx = this;
if (!commit) {
final GridNearTxFinishFuture rollbackFut = new GridNearTxFinishFuture<>(cctx, this, false);
fut.listen(new IgniteInClosure<IgniteInternalFuture<IgniteInternalTx>>() {
@Override
public void apply(IgniteInternalFuture<IgniteInternalTx> fut0) {
if (FINISH_FUT_UPD.compareAndSet(tx, fut, rollbackFut)) {
switch(tx.state()) {
case COMMITTED:
if (log.isDebugEnabled())
log.debug("Failed to rollback, transaction is already committed: " + tx);
case ROLLED_BACK:
rollbackFut.forceFinish();
assert rollbackFut.isDone() : rollbackFut;
break;
default:
// First finish attempt was unsuccessful. Try again.
rollbackFut.finish(false, clearThreadMap, onTimeout);
}
} else {
finishFut.listen(new IgniteInClosure<IgniteInternalFuture<IgniteInternalTx>>() {
@Override
public void apply(IgniteInternalFuture<IgniteInternalTx> fut) {
try {
fut.get();
rollbackFut.markInitialized();
} catch (IgniteCheckedException e) {
rollbackFut.onDone(e);
}
}
});
}
}
});
return rollbackFut;
} else {
final GridFutureAdapter<IgniteInternalTx> fut0 = new GridFutureAdapter<>();
fut.listen(new IgniteInClosure<IgniteInternalFuture<IgniteInternalTx>>() {
@Override
public void apply(IgniteInternalFuture<IgniteInternalTx> fut) {
if (timedOut())
fut0.onDone(new IgniteTxTimeoutCheckedException("Failed to commit transaction, " + "transaction is concurrently rolled back on timeout: " + tx));
else
fut0.onDone(new IgniteTxRollbackCheckedException("Failed to commit transaction, " + "transaction is concurrently rolled back: " + tx));
}
});
return fut0;
}
}
return fut;
}
Aggregations