use of org.apache.ignite.lang.IgniteInClosure in project ignite by apache.
the class GridDhtTxLocal method finishTx.
/**
* @param commit Commit flag.
* @param prepFut Prepare future.
* @param fut Finish future.
*/
private void finishTx(boolean commit, @Nullable IgniteInternalFuture prepFut, GridDhtTxFinishFuture fut) {
assert prepFut == null || prepFut.isDone();
boolean primarySync = syncMode() == PRIMARY_SYNC;
IgniteCheckedException err = null;
if (!commit) {
final IgniteInternalFuture<?> lockFut = tryRollbackAsync();
if (lockFut != null) {
if (lockFut instanceof DhtLockFuture)
((DhtLockFuture<?>) lockFut).onError(rollbackException());
else if (!lockFut.isDone()) {
/*
* Prevents race with {@link GridDhtTransactionalCacheAdapter#lockAllAsync
* (GridCacheContext, ClusterNode, GridNearLockRequest, CacheEntryPredicate[])}
*/
final IgniteInternalFuture finalPrepFut = prepFut;
lockFut.listen(new IgniteInClosure<IgniteInternalFuture<?>>() {
@Override
public void apply(IgniteInternalFuture<?> ignored) {
finishTx(false, finalPrepFut, fut);
}
});
return;
}
}
}
if (!commit && prepFut != null) {
try {
prepFut.get();
} catch (IgniteCheckedException e) {
if (log.isDebugEnabled())
log.debug("Failed to prepare transaction [tx=" + this + ", e=" + e + ']');
} finally {
prepFut = null;
}
}
try {
if (prepFut != null)
// Check for errors.
prepFut.get();
boolean finished = localFinish(commit, false);
if (!finished)
err = new IgniteCheckedException("Failed to finish transaction [commit=" + commit + ", tx=" + CU.txString(this) + ']');
} catch (IgniteCheckedException e) {
logTxFinishErrorSafe(log, commit, e);
// Treat heuristic exception as critical.
if (X.hasCause(e, IgniteTxHeuristicCheckedException.class))
cctx.kernalContext().failure().process(new FailureContext(FailureType.CRITICAL_ERROR, e));
err = e;
} catch (Throwable t) {
fut.onDone(t);
throw t;
}
if (primarySync)
sendFinishReply(err);
if (err != null)
fut.rollbackOnError(err);
else
fut.finish(commit);
}
use of org.apache.ignite.lang.IgniteInClosure in project ignite by apache.
the class GridTaskCommandHandler method handleAsyncUnsafe.
/**
* @param req Request.
* @return Future.
* @throws IgniteCheckedException On any handling exception.
*/
private IgniteInternalFuture<GridRestResponse> handleAsyncUnsafe(final GridRestRequest req) throws IgniteCheckedException {
assert req instanceof GridRestTaskRequest : "Invalid command for topology handler: " + req;
assert SUPPORTED_COMMANDS.contains(req.command());
if (log.isDebugEnabled())
log.debug("Handling task REST request: " + req);
GridRestTaskRequest req0 = (GridRestTaskRequest) req;
final GridFutureAdapter<GridRestResponse> fut = new GridFutureAdapter<>();
final GridRestResponse res = new GridRestResponse();
final GridClientTaskResultBean taskRestRes = new GridClientTaskResultBean();
// Set ID placeholder for the case it wouldn't be available due to remote execution.
taskRestRes.setId('~' + ctx.localNodeId().toString());
final boolean locExec = req0.destinationId() == null || req0.destinationId().equals(ctx.localNodeId()) || ctx.discovery().node(req0.destinationId()) == null;
switch(req.command()) {
case EXE:
{
final boolean async = req0.async();
final String name = req0.taskName();
if (F.isEmpty(name))
throw new IgniteCheckedException(missingParameter("name"));
final List<Object> params = req0.params();
long timeout = req0.timeout();
final IgniteInternalFuture<Object> taskFut;
if (locExec) {
ctx.task().setThreadContext(TC_TIMEOUT, timeout);
Object arg = !F.isEmpty(params) ? params.size() == 1 ? params.get(0) : params.toArray() : null;
taskFut = ctx.task().execute(name, arg);
} else {
// Using predicate instead of node intentionally
// in order to provide user well-structured EmptyProjectionException.
ClusterGroup prj = ctx.grid().cluster().forPredicate(F.nodeForNodeId(req.destinationId()));
ctx.task().setThreadContext(TC_NO_FAILOVER, true);
taskFut = ctx.closure().callAsync(BALANCE, new ExeCallable(name, params, timeout), prj.nodes());
}
if (async) {
if (locExec) {
IgniteUuid tid = ((ComputeTaskInternalFuture) taskFut).getTaskSession().getId();
taskDescs.put(tid, new TaskDescriptor(false, null, null));
taskRestRes.setId(tid.toString() + '~' + ctx.localNodeId().toString());
res.setResponse(taskRestRes);
} else
res.setError("Asynchronous task execution is not supported for routing request.");
fut.onDone(res);
}
taskFut.listen(new IgniteInClosure<IgniteInternalFuture<Object>>() {
@Override
public void apply(IgniteInternalFuture<Object> taskFut) {
try {
TaskDescriptor desc;
try {
desc = new TaskDescriptor(true, taskFut.get(), null);
} catch (IgniteCheckedException e) {
if (e.hasCause(ClusterTopologyCheckedException.class, ClusterGroupEmptyCheckedException.class))
U.warn(log, "Failed to execute task due to topology issues (are all mapped " + "nodes alive?) [name=" + name + ", clientId=" + req.clientId() + ", err=" + e + ']');
else {
if (!X.hasCause(e, VisorClusterGroupEmptyException.class))
U.error(log, "Failed to execute task [name=" + name + ", clientId=" + req.clientId() + ']', e);
}
desc = new TaskDescriptor(true, null, e);
}
if (async && locExec) {
assert taskFut instanceof ComputeTaskInternalFuture;
IgniteUuid tid = ((ComputeTaskInternalFuture) taskFut).getTaskSession().getId();
taskDescs.put(tid, desc);
}
if (!async) {
if (desc.error() == null) {
try {
taskRestRes.setFinished(true);
taskRestRes.setResult(desc.result());
res.setResponse(taskRestRes);
fut.onDone(res);
} catch (IgniteException e) {
fut.onDone(new IgniteCheckedException("Failed to marshal task result: " + desc.result(), e));
}
} else
fut.onDone(desc.error());
}
} finally {
if (!async && !fut.isDone())
fut.onDone(new IgniteCheckedException("Failed to execute task (see server logs for details)."));
}
}
});
break;
}
case RESULT:
{
String id = req0.taskId();
if (F.isEmpty(id))
throw new IgniteCheckedException(missingParameter("id"));
StringTokenizer st = new StringTokenizer(id, "~");
if (st.countTokens() != 2)
throw new IgniteCheckedException("Failed to parse id parameter: " + id);
String tidParam = st.nextToken();
String resHolderIdParam = st.nextToken();
taskRestRes.setId(id);
try {
IgniteUuid tid = !F.isEmpty(tidParam) ? IgniteUuid.fromString(tidParam) : null;
UUID resHolderId = !F.isEmpty(resHolderIdParam) ? UUID.fromString(resHolderIdParam) : null;
if (tid == null || resHolderId == null)
throw new IgniteCheckedException("Failed to parse id parameter: " + id);
if (ctx.localNodeId().equals(resHolderId)) {
TaskDescriptor desc = taskDescs.get(tid);
if (desc == null)
throw new IgniteCheckedException("Task with provided id has never been started on provided node" + " [taskId=" + tidParam + ", taskResHolderId=" + resHolderIdParam + ']');
taskRestRes.setFinished(desc.finished());
if (desc.error() != null)
throw new IgniteCheckedException(desc.error().getMessage());
taskRestRes.setResult(desc.result());
res.setResponse(taskRestRes);
} else {
IgniteBiTuple<String, GridTaskResultResponse> t = requestTaskResult(resHolderId, tid);
if (t.get1() != null)
throw new IgniteCheckedException(t.get1());
GridTaskResultResponse taskRes = t.get2();
assert taskRes != null;
if (!taskRes.found())
throw new IgniteCheckedException("Task with provided id has never been started on provided node " + "[taskId=" + tidParam + ", taskResHolderId=" + resHolderIdParam + ']');
taskRestRes.setFinished(taskRes.finished());
if (taskRes.error() != null)
throw new IgniteCheckedException(taskRes.error());
taskRestRes.setResult(taskRes.result());
res.setResponse(taskRestRes);
}
} catch (IllegalArgumentException e) {
String msg = "Failed to parse parameters [taskId=" + tidParam + ", taskResHolderId=" + resHolderIdParam + ", err=" + e.getMessage() + ']';
if (log.isDebugEnabled())
log.debug(msg);
throw new IgniteCheckedException(msg, e);
}
fut.onDone(res);
break;
}
case NOOP:
{
fut.onDone(new GridRestResponse());
break;
}
default:
assert false : "Invalid command for task handler: " + req;
}
if (log.isDebugEnabled())
log.debug("Handled task REST request [res=" + res + ", req=" + req + ']');
return fut;
}
use of org.apache.ignite.lang.IgniteInClosure in project ignite by apache.
the class CacheAsyncContinuationExecutorTest method testRemoteOperationContinuesOnDefaultExecutor.
/**
* Tests future chain / listen with default executor.
*
* This test would hang before {@link IgniteConfiguration#setAsyncContinuationExecutor(Executor)}
* was introduced, or if we set {@link Runnable#run()} as the executor.
*/
private void testRemoteOperationContinuesOnDefaultExecutor(boolean chain) throws Exception {
final String key = getPrimaryKey(1);
IgniteCache<String, Integer> cache = jcache(0);
CyclicBarrier barrier = new CyclicBarrier(2);
AtomicReference<String> listenThreadName = new AtomicReference<>("");
IgniteInClosure<IgniteFuture<Void>> clos = f -> {
listenThreadName.set(Thread.currentThread().getName());
if (allowCacheOperationsInContinuation()) {
// Check that cache operations do not deadlock.
cache.replace(key, 2);
}
try {
barrier.await(10, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
}
};
IgniteFuture<Void> fut = cache.putAsync(key, 1);
if (chain)
fut.chain(f -> {
clos.apply(f);
return new IgniteFinishedFutureImpl<>();
});
else
fut.listen(clos);
barrier.await(10, TimeUnit.SECONDS);
assertEquals(allowCacheOperationsInContinuation() ? 2 : 1, cache.get(key).intValue());
assertTrue(listenThreadName.get(), listenThreadName.get().startsWith(expectedThreadNamePrefix()));
}
use of org.apache.ignite.lang.IgniteInClosure in project ignite by apache.
the class GridNearTxAbstractEnlistFuture method init.
/**
*/
public void init() {
if (timeout < 0) {
// Time is out.
onDone(timeoutException());
return;
} else if (timeout > 0)
timeoutObj = new LockTimeoutObject();
while (true) {
IgniteInternalFuture<?> fut = tx.lockFuture();
if (fut == GridDhtTxLocalAdapter.ROLLBACK_FUT) {
onDone(tx.timedOut() ? tx.timeoutException() : tx.rollbackException());
return;
} else if (fut != null) {
// Wait for previous future.
assert fut instanceof GridNearTxAbstractEnlistFuture || fut instanceof GridDhtTxAbstractEnlistFuture : fut;
// Terminate this future if parent future is terminated by rollback.
if (!fut.isDone()) {
fut.listen(new IgniteInClosure<IgniteInternalFuture>() {
@Override
public void apply(IgniteInternalFuture fut) {
if (fut.error() != null)
onDone(fut.error());
}
});
} else if (fut.error() != null)
onDone(fut.error());
break;
} else if (tx.updateLockFuture(null, this))
break;
}
boolean added = cctx.mvcc().addFuture(this);
assert added : this;
if (isDone()) {
cctx.mvcc().removeFuture(futId);
return;
}
try {
tx.addActiveCache(cctx, false);
} catch (IgniteCheckedException e) {
onDone(e);
return;
}
if (timeoutObj != null)
cctx.time().addTimeoutObject(timeoutObj);
// Obtain the topology version to use.
long threadId = Thread.currentThread().getId();
AffinityTopologyVersion topVer = cctx.mvcc().lastExplicitLockTopologyVersion(threadId);
// If there is another system transaction in progress, use it's topology version to prevent deadlock.
if (topVer == null && tx.system())
topVer = cctx.tm().lockedTopologyVersion(threadId, tx);
if (topVer != null)
tx.topologyVersion(topVer);
if (topVer == null)
topVer = tx.topologyVersionSnapshot();
if (topVer != null) {
for (GridDhtTopologyFuture fut : cctx.shared().exchange().exchangeFutures()) {
if (fut.exchangeDone() && fut.topologyVersion().equals(topVer)) {
Throwable err = null;
// Before cache validation, make sure that this topology future is already completed.
try {
fut.get();
} catch (IgniteCheckedException e) {
err = fut.error();
}
if (err == null)
err = fut.validateCache(cctx, false, false, null, null);
if (err != null) {
onDone(err);
return;
}
break;
}
}
if (this.topVer == null)
this.topVer = topVer;
map(true);
return;
}
mapOnTopology();
}
use of org.apache.ignite.lang.IgniteInClosure in project ignite by apache.
the class CachePartitionDefragmentationManager method defragmentOnePartition.
/**
* Defragment one given partition.
*/
private boolean defragmentOnePartition(CacheGroupContext oldGrpCtx, int grpId, File workDir, GridCacheOffheapManager offheap, FileVersionCheckingFactory pageStoreFactory, GridCompoundFuture<Object, Object> cmpFut, PageMemoryEx oldPageMem, CacheGroupContext newGrpCtx, CacheDataStore oldCacheDataStore) throws IgniteCheckedException {
TreeIterator treeIter = new TreeIterator(pageSize);
checkCancellation();
int partId = oldCacheDataStore.partId();
PartitionContext partCtx = new PartitionContext(workDir, grpId, partId, partDataRegion, mappingDataRegion, oldGrpCtx, newGrpCtx, oldCacheDataStore, pageStoreFactory);
if (skipAlreadyDefragmentedPartition(workDir, grpId, partId, log)) {
partCtx.createPageStore(() -> defragmentedPartMappingFile(workDir, partId).toPath(), partCtx.mappingPagesAllocated, partCtx.mappingPageMemory);
linkMapByPart.put(partId, partCtx.createLinkMapTree(false));
return false;
}
partCtx.createPageStore(() -> defragmentedPartMappingFile(workDir, partId).toPath(), partCtx.mappingPagesAllocated, partCtx.mappingPageMemory);
linkMapByPart.put(partId, partCtx.createLinkMapTree(true));
checkCancellation();
partCtx.createPageStore(() -> defragmentedPartTmpFile(workDir, partId).toPath(), partCtx.partPagesAllocated, partCtx.partPageMemory);
partCtx.createNewCacheDataStore(offheap);
copyPartitionData(partCtx, treeIter);
DefragmentationPageReadWriteManager pageMgr = (DefragmentationPageReadWriteManager) partCtx.partPageMemory.pageManager();
PageStore oldPageStore = filePageStoreMgr.getStore(grpId, partId);
status.onPartitionDefragmented(oldGrpCtx, oldPageStore.size(), // + file header.
pageSize + partCtx.partPagesAllocated.get() * pageSize);
// TODO Move inside of defragmentSinglePartition.
IgniteInClosure<IgniteInternalFuture<?>> cpLsnr = fut -> {
if (fut.error() == null) {
if (log.isDebugEnabled()) {
log.debug(S.toString("Partition defragmented", "grpId", grpId, false, "partId", partId, false, "oldPages", oldPageStore.pages(), false, "newPages", partCtx.partPagesAllocated.get() + 1, false, "mappingPages", partCtx.mappingPagesAllocated.get() + 1, false, "pageSize", pageSize, false, "partFile", defragmentedPartFile(workDir, partId).getName(), false, "workDir", workDir, false));
}
oldPageMem.invalidate(grpId, partId);
partCtx.partPageMemory.invalidate(grpId, partId);
// Yes, it'll be invalid in a second.
pageMgr.pageStoreMap().removePageStore(grpId, partId);
renameTempPartitionFile(workDir, partId);
}
};
GridFutureAdapter<?> cpFut = defragmentationCheckpoint.forceCheckpoint("partition defragmented", null).futureFor(FINISHED);
cpFut.listen(cpLsnr);
cmpFut.add((IgniteInternalFuture<Object>) cpFut);
return true;
}
Aggregations