use of org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxFinishResponse in project ignite by apache.
the class IgniteTxHandler method finishDhtLocal.
/**
* @param nodeId Node ID initiated commit.
* @param locTx Optional local transaction.
* @param req Finish request.
* @return Finish future.
*/
private IgniteInternalFuture<IgniteInternalTx> finishDhtLocal(UUID nodeId, @Nullable GridNearTxLocal locTx, GridNearTxFinishRequest req) {
GridCacheVersion dhtVer = ctx.tm().mappedVersion(req.version());
GridDhtTxLocal tx = null;
if (dhtVer == null) {
if (log.isDebugEnabled())
log.debug("Received transaction finish request for unknown near version (was lock explicit?): " + req);
} else
tx = ctx.tm().tx(dhtVer);
if (tx != null)
req.txState(tx.txState());
if (tx == null && locTx != null && !req.commit()) {
U.warn(log, "DHT local tx not found for near local tx rollback " + "[req=" + req + ", dhtVer=" + dhtVer + ", tx=" + locTx + ']');
return null;
}
if (tx == null && !req.explicitLock()) {
assert locTx == null : "DHT local tx should never be lost for near local tx: " + locTx;
U.warn(txFinishMsgLog, "Received finish request for completed transaction (the message may be too late) [" + "txId=" + req.version() + ", dhtTxId=" + dhtVer + ", node=" + nodeId + ", commit=" + req.commit() + ']');
// Always send finish response.
GridCacheMessage res = new GridNearTxFinishResponse(req.partition(), req.version(), req.threadId(), req.futureId(), req.miniId(), new IgniteCheckedException("Transaction has been already completed."));
try {
ctx.io().send(nodeId, res, req.policy());
if (txFinishMsgLog.isDebugEnabled()) {
txFinishMsgLog.debug("Sent near finish response for completed tx [txId=" + req.version() + ", dhtTxId=" + dhtVer + ", node=" + nodeId + ']');
}
} catch (Throwable e) {
// Double-check.
if (ctx.discovery().node(nodeId) == null) {
if (txFinishMsgLog.isDebugEnabled()) {
txFinishMsgLog.debug("Failed to send near finish response for completed tx, node failed [" + "txId=" + req.version() + ", dhtTxId=" + dhtVer + ", node=" + nodeId + ']');
}
} else {
U.error(txFinishMsgLog, "Failed to send near finish response for completed tx, node failed [" + "txId=" + req.version() + ", dhtTxId=" + dhtVer + ", node=" + nodeId + ", req=" + req + ", res=" + res + ']', e);
}
if (e instanceof Error)
throw (Error) e;
}
return null;
}
try {
assert tx != null : "Transaction is null for near finish request [nodeId=" + nodeId + ", req=" + req + "]";
assert req.syncMode() != null : req;
tx.syncMode(req.syncMode());
tx.nearFinishFutureId(req.futureId());
tx.nearFinishMiniId(req.miniId());
tx.storeEnabled(req.storeEnabled());
if (req.commit()) {
if (!tx.markFinalizing(USER_FINISH)) {
if (log.isDebugEnabled())
log.debug("Will not finish transaction (it is handled by another thread): " + tx);
return null;
}
IgniteInternalFuture<IgniteInternalTx> commitFut = tx.commitDhtLocalAsync();
// Only for error logging.
commitFut.listen(CU.errorLogger(log));
return commitFut;
} else {
IgniteInternalFuture<IgniteInternalTx> rollbackFut = tx.rollbackDhtLocalAsync();
// Only for error logging.
rollbackFut.listen(CU.errorLogger(log));
return rollbackFut;
}
} catch (Throwable e) {
U.error(log, "Failed completing transaction [commit=" + req.commit() + ", tx=" + tx + ']', e);
if (tx != null) {
tx.commitError(e);
tx.systemInvalidate(true);
try {
IgniteInternalFuture<IgniteInternalTx> res = tx.rollbackDhtLocalAsync();
// Only for error logging.
res.listen(CU.errorLogger(log));
return res;
} catch (Throwable e1) {
e.addSuppressed(e1);
}
}
if (e instanceof Error)
throw (Error) e;
return new GridFinishedFuture<>(e);
}
}
Aggregations