use of org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxRemote in project ignite by apache.
the class IgniteTxHandler method processDhtTxPrepareRequest.
/**
* @param nodeId Sender node ID.
* @param req Request.
*/
private void processDhtTxPrepareRequest(final UUID nodeId, final GridDhtTxPrepareRequest req) {
try (TraceSurroundings ignored = MTC.support(ctx.kernalContext().tracing().create(TX_PROCESS_DHT_PREPARE_REQ, MTC.span()))) {
if (txPrepareMsgLog.isDebugEnabled()) {
txPrepareMsgLog.debug("Received dht prepare request [txId=" + req.nearXidVersion() + ", dhtTxId=" + req.version() + ", node=" + nodeId + ']');
}
assert nodeId != null;
assert req != null;
assert req.transactionNodes() != null;
GridDhtTxRemote dhtTx = null;
GridNearTxRemote nearTx = null;
GridDhtTxPrepareResponse res;
try {
res = new GridDhtTxPrepareResponse(req.partition(), req.version(), req.futureId(), req.miniId(), req.deployInfo() != null);
// Start near transaction first.
nearTx = !F.isEmpty(req.nearWrites()) ? startNearRemoteTx(ctx.deploy().globalLoader(), nodeId, req) : null;
dhtTx = startRemoteTx(nodeId, req, res);
// Set evicted keys from near transaction.
if (nearTx != null)
res.nearEvicted(nearTx.evicted());
List<IgniteTxKey> writesCacheMissed = req.nearWritesCacheMissed();
if (writesCacheMissed != null) {
Collection<IgniteTxKey> evicted0 = res.nearEvicted();
if (evicted0 != null)
writesCacheMissed.addAll(evicted0);
res.nearEvicted(writesCacheMissed);
}
if (dhtTx != null)
req.txState(dhtTx.txState());
else if (nearTx != null)
req.txState(nearTx.txState());
if (dhtTx != null && !F.isEmpty(dhtTx.invalidPartitions()))
res.invalidPartitionsByCacheId(dhtTx.invalidPartitions());
if (req.onePhaseCommit()) {
assert req.last();
if (dhtTx != null) {
dhtTx.onePhaseCommit(true);
dhtTx.needReturnValue(req.needReturnValue());
finish(dhtTx, req);
}
if (nearTx != null) {
nearTx.onePhaseCommit(true);
finish(nearTx, req);
}
}
} catch (IgniteCheckedException e) {
if (e instanceof IgniteTxRollbackCheckedException)
U.error(log, "Transaction was rolled back before prepare completed: " + req, e);
else if (e instanceof IgniteTxOptimisticCheckedException) {
if (log.isDebugEnabled())
log.debug("Optimistic failure for remote transaction (will rollback): " + req);
} else
U.error(log, "Failed to process prepare request: " + req, e);
if (nearTx != null)
try {
nearTx.rollbackRemoteTx();
} catch (Throwable e1) {
e.addSuppressed(e1);
}
res = new GridDhtTxPrepareResponse(req.partition(), req.version(), req.futureId(), req.miniId(), e, req.deployInfo() != null);
}
if (req.onePhaseCommit()) {
IgniteInternalFuture completeFut;
IgniteInternalFuture<IgniteInternalTx> dhtFin = dhtTx == null ? null : dhtTx.done() ? null : dhtTx.finishFuture();
final IgniteInternalFuture<IgniteInternalTx> nearFin = nearTx == null ? null : nearTx.done() ? null : nearTx.finishFuture();
if (dhtFin != null && nearFin != null) {
GridCompoundFuture fut = new GridCompoundFuture();
fut.add(dhtFin);
fut.add(nearFin);
fut.markInitialized();
completeFut = fut;
} else
completeFut = dhtFin != null ? dhtFin : nearFin;
if (completeFut != null) {
final GridDhtTxPrepareResponse res0 = res;
final GridDhtTxRemote dhtTx0 = dhtTx;
final GridNearTxRemote nearTx0 = nearTx;
completeFut.listen(new CI1<IgniteInternalFuture<IgniteInternalTx>>() {
@Override
public void apply(IgniteInternalFuture<IgniteInternalTx> fut) {
sendReply(nodeId, req, res0, dhtTx0, nearTx0);
}
});
} else
sendReply(nodeId, req, res, dhtTx, nearTx);
} else
sendReply(nodeId, req, res, dhtTx, nearTx);
assert req.txState() != null || res.error() != null || (dhtTx == null && nearTx == null) : req + " tx=" + dhtTx + " nearTx=" + nearTx;
}
}
use of org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxRemote in project ignite by apache.
the class GridDhtTransactionalCacheAdapter method processDhtLockRequest0.
/**
* @param nodeId Node ID.
* @param req Request.
*/
private void processDhtLockRequest0(UUID nodeId, GridDhtLockRequest req) {
assert nodeId != null;
assert req != null;
assert !nodeId.equals(locNodeId);
int cnt = F.size(req.keys());
GridDhtLockResponse res;
GridDhtTxRemote dhtTx = null;
GridNearTxRemote nearTx = null;
boolean fail = false;
boolean cancelled = false;
try {
res = new GridDhtLockResponse(ctx.cacheId(), req.version(), req.futureId(), req.miniId(), cnt, ctx.deploymentEnabled());
dhtTx = startRemoteTx(nodeId, req, res);
nearTx = isNearEnabled(cacheCfg) ? near().startRemoteTx(nodeId, req) : null;
if (nearTx != null && !nearTx.empty())
res.nearEvicted(nearTx.evicted());
else {
if (!F.isEmpty(req.nearKeys())) {
Collection<IgniteTxKey> nearEvicted = new ArrayList<>(req.nearKeys().size());
nearEvicted.addAll(F.viewReadOnly(req.nearKeys(), new C1<KeyCacheObject, IgniteTxKey>() {
@Override
public IgniteTxKey apply(KeyCacheObject k) {
return ctx.txKey(k);
}
}));
res.nearEvicted(nearEvicted);
}
}
} catch (IgniteTxRollbackCheckedException e) {
String err = "Failed processing DHT lock request (transaction has been completed): " + req;
U.error(log, err, e);
res = new GridDhtLockResponse(ctx.cacheId(), req.version(), req.futureId(), req.miniId(), new IgniteTxRollbackCheckedException(err, e), ctx.deploymentEnabled());
fail = true;
} catch (IgniteCheckedException e) {
String err = "Failed processing DHT lock request: " + req;
U.error(log, err, e);
res = new GridDhtLockResponse(ctx.cacheId(), req.version(), req.futureId(), req.miniId(), new IgniteCheckedException(err, e), ctx.deploymentEnabled());
fail = true;
} catch (GridDistributedLockCancelledException ignored) {
// Received lock request for cancelled lock.
if (log.isDebugEnabled())
log.debug("Received lock request for canceled lock (will ignore): " + req);
res = null;
fail = true;
cancelled = true;
}
boolean releaseAll = false;
if (res != null) {
try {
// Reply back to sender.
ctx.io().send(nodeId, res, ctx.ioPolicy());
if (txLockMsgLog.isDebugEnabled()) {
txLockMsgLog.debug("Sent dht lock response [txId=" + req.nearXidVersion() + ", dhtTxId=" + req.version() + ", inTx=" + req.inTx() + ", node=" + nodeId + ']');
}
} catch (ClusterTopologyCheckedException ignored) {
U.warn(txLockMsgLog, "Failed to send dht lock response, node failed [" + "txId=" + req.nearXidVersion() + ", dhtTxId=" + req.version() + ", inTx=" + req.inTx() + ", node=" + nodeId + ']');
fail = true;
releaseAll = true;
} catch (IgniteCheckedException e) {
U.error(txLockMsgLog, "Failed to send dht lock response (lock will not be acquired) " + "txId=" + req.nearXidVersion() + ", dhtTxId=" + req.version() + ", inTx=" + req.inTx() + ", node=" + nodeId + ']', e);
fail = true;
}
}
if (fail) {
if (dhtTx != null)
dhtTx.rollbackRemoteTx();
if (// Even though this should never happen, we leave this check for consistency.
nearTx != null)
nearTx.rollbackRemoteTx();
List<KeyCacheObject> keys = req.keys();
if (keys != null) {
for (KeyCacheObject key : keys) {
while (true) {
GridDistributedCacheEntry entry = peekExx(key);
try {
if (entry != null) {
// Release all locks because sender node left grid.
if (releaseAll)
entry.removeExplicitNodeLocks(req.nodeId());
else
entry.removeLock(req.version());
}
break;
} catch (GridCacheEntryRemovedException ignore) {
if (log.isDebugEnabled())
log.debug("Attempted to remove lock on removed entity during during failure " + "handling for dht lock request (will retry): " + entry);
}
}
}
}
if (releaseAll && !cancelled)
U.warn(log, "Sender node left grid in the midst of lock acquisition (locks have been released).");
}
}
use of org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxRemote in project ignite by apache.
the class IgniteTxHandler method processDhtTxFinishRequest.
/**
* @param nodeId Node ID.
* @param req Request.
*/
@SuppressWarnings({ "unchecked" })
private void processDhtTxFinishRequest(final UUID nodeId, final GridDhtTxFinishRequest req) {
try (TraceSurroundings ignored = MTC.support(ctx.kernalContext().tracing().create(TX_PROCESS_DHT_FINISH_REQ, MTC.span()))) {
assert nodeId != null;
assert req != null;
if (req.checkCommitted()) {
boolean committed = req.waitRemoteTransactions() || !ctx.tm().addRolledbackTx(null, req.version());
if (!committed || req.syncMode() != FULL_SYNC)
sendReply(nodeId, req, committed, null);
else {
IgniteInternalFuture<?> fut = ctx.tm().remoteTxFinishFuture(req.version());
fut.listen(new CI1<IgniteInternalFuture<?>>() {
@Override
public void apply(IgniteInternalFuture<?> fut) {
sendReply(nodeId, req, true, null);
}
});
}
return;
}
// Always add version to rollback history to prevent races with rollbacks.
if (!req.commit())
ctx.tm().addRolledbackTx(null, req.version());
GridDhtTxRemote dhtTx = ctx.tm().tx(req.version());
GridNearTxRemote nearTx = ctx.tm().nearTx(req.version());
IgniteInternalTx anyTx = U.<IgniteInternalTx>firstNotNull(dhtTx, nearTx);
final GridCacheVersion nearTxId = anyTx != null ? anyTx.nearXidVersion() : null;
if (txFinishMsgLog.isDebugEnabled())
txFinishMsgLog.debug("Received dht finish request [txId=" + nearTxId + ", dhtTxId=" + req.version() + ", node=" + nodeId + ']');
if (anyTx == null && req.commit())
ctx.tm().addCommittedTx(null, req.version(), null);
if (dhtTx != null)
finish(nodeId, dhtTx, req);
else {
try {
applyPartitionsUpdatesCounters(req.updateCounters(), !req.commit(), false);
} catch (IgniteCheckedException e) {
throw new IgniteException(e);
}
}
if (nearTx != null)
finish(nodeId, nearTx, req);
if (req.replyRequired()) {
IgniteInternalFuture completeFut;
IgniteInternalFuture<IgniteInternalTx> dhtFin = dhtTx == null ? null : dhtTx.done() ? null : dhtTx.finishFuture();
final IgniteInternalFuture<IgniteInternalTx> nearFin = nearTx == null ? null : nearTx.done() ? null : nearTx.finishFuture();
if (dhtFin != null && nearFin != null) {
GridCompoundFuture fut = new GridCompoundFuture();
fut.add(dhtFin);
fut.add(nearFin);
fut.markInitialized();
completeFut = fut;
} else
completeFut = dhtFin != null ? dhtFin : nearFin;
if (completeFut != null) {
completeFut.listen(new CI1<IgniteInternalFuture<IgniteInternalTx>>() {
@Override
public void apply(IgniteInternalFuture<IgniteInternalTx> fut) {
sendReply(nodeId, req, true, nearTxId);
}
});
} else
sendReply(nodeId, req, true, nearTxId);
} else
sendReply(nodeId, req, true, null);
assert req.txState() != null || (dhtTx == null && nearTx == null) : req + " tx=" + dhtTx + " nearTx=" + nearTx;
}
}
use of org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxRemote in project ignite by apache.
the class IgniteTxHandler method startNearRemoteTx.
/**
* Called while processing dht tx prepare request.
*
* @param ldr Loader.
* @param nodeId Sender node ID.
* @param req Request.
* @return Remote transaction.
* @throws IgniteCheckedException If failed.
*/
@Nullable
private GridNearTxRemote startNearRemoteTx(ClassLoader ldr, UUID nodeId, GridDhtTxPrepareRequest req) throws IgniteCheckedException {
if (!F.isEmpty(req.nearWrites())) {
GridNearTxRemote tx = ctx.tm().nearTx(req.version());
if (tx == null) {
tx = new GridNearTxRemote(ctx, req.topologyVersion(), ldr, nodeId, req.nearNodeId(), req.version(), null, req.system(), req.policy(), req.concurrency(), req.isolation(), req.isInvalidate(), req.timeout(), req.nearWrites(), req.txSize(), securitySubjectId(ctx), req.taskNameHash(), req.txLabel());
tx.writeVersion(req.writeVersion());
if (!tx.empty()) {
tx = ctx.tm().onCreated(null, tx);
if (tx == null || !ctx.tm().onStarted(tx))
throw new IgniteTxRollbackCheckedException("Attempt to start a completed transaction: " + tx);
}
} else
tx.addEntries(ldr, req.nearWrites());
tx.ownedVersions(req.owned());
// Prepare prior to reordering, so the pending locks added
// in prepare phase will get properly ordered as well.
tx.prepareRemoteTx();
if (req.last())
tx.state(PREPARED);
return tx;
}
return null;
}
Aggregations