use of org.apache.ignite.internal.IgniteInternalFuture in project ignite by apache.
the class CacheExchangeMergeTest method startGridsAsync.
/**
* Sequentially starts nodes so that node name is consistent with node order.
*
* @param node Some existing node.
* @param startIdx Start node index.
* @param cnt Number of nodes.
* @return Start future.
* @throws Exception If failed.
*/
private IgniteInternalFuture startGridsAsync(Ignite node, int startIdx, int cnt) throws Exception {
GridCompoundFuture fut = new GridCompoundFuture();
for (int i = 0; i < cnt; i++) {
final CountDownLatch latch = new CountDownLatch(1);
node.events().localListen(new IgnitePredicate<Event>() {
@Override
public boolean apply(Event evt) {
log.info("Got event: " + ((DiscoveryEvent) evt).eventNode().id());
latch.countDown();
return false;
}
}, EventType.EVT_NODE_JOINED);
final int nodeIdx = startIdx + i;
IgniteInternalFuture fut0 = GridTestUtils.runAsync(new Callable() {
@Override
public Object call() throws Exception {
log.info("Start new node: " + nodeIdx);
startGrid(nodeIdx);
return null;
}
}, "start-node-" + nodeIdx);
if (!latch.await(WAIT_SECONDS, TimeUnit.SECONDS))
fail();
fut.add(fut0);
}
fut.markInitialized();
return fut;
}
use of org.apache.ignite.internal.IgniteInternalFuture in project ignite by apache.
the class IgniteTxHandler method prepareNearTx.
/**
* @param nearNode Node that initiated transaction.
* @param req Near prepare request.
* @return Prepare future or {@code null} if need retry operation.
*/
@Nullable
private IgniteInternalFuture<GridNearTxPrepareResponse> prepareNearTx(final ClusterNode nearNode, final GridNearTxPrepareRequest req) {
IgniteTxEntry firstEntry;
try {
IgniteTxEntry firstWrite = unmarshal(req.writes());
IgniteTxEntry firstRead = unmarshal(req.reads());
firstEntry = firstWrite != null ? firstWrite : firstRead;
} catch (IgniteCheckedException e) {
return new GridFinishedFuture<>(e);
}
assert firstEntry != null : req;
GridDhtTxLocal tx = null;
GridCacheVersion mappedVer = ctx.tm().mappedVersion(req.version());
if (mappedVer != null) {
tx = ctx.tm().tx(mappedVer);
if (tx == null)
U.warn(log, "Missing local transaction for mapped near version [nearVer=" + req.version() + ", mappedVer=" + mappedVer + ']');
else {
if (req.concurrency() == PESSIMISTIC)
tx.nearFutureId(req.futureId());
}
} else {
GridDhtPartitionTopology top = null;
if (req.firstClientRequest()) {
assert req.concurrency() == OPTIMISTIC : req;
assert CU.clientNode(nearNode) : nearNode;
top = firstEntry.context().topology();
top.readLock();
if (req.allowWaitTopologyFuture()) {
GridDhtTopologyFuture topFut = top.topologyVersionFuture();
if (!topFut.isDone()) {
top.readUnlock();
return null;
}
}
}
try {
if (top != null) {
boolean retry = false;
GridDhtTopologyFuture topFut = top.topologyVersionFuture();
if (!req.allowWaitTopologyFuture() && !topFut.isDone()) {
retry = true;
if (txPrepareMsgLog.isDebugEnabled()) {
txPrepareMsgLog.debug("Topology change is in progress, need remap transaction [" + "txId=" + req.version() + ", node=" + nearNode.id() + ", reqTopVer=" + req.topologyVersion() + ", locTopVer=" + top.readyTopologyVersion() + ", req=" + req + ']');
}
}
if (!retry && needRemap(req.topologyVersion(), top.readyTopologyVersion(), req)) {
retry = true;
if (txPrepareMsgLog.isDebugEnabled()) {
txPrepareMsgLog.debug("Topology version mismatch for near prepare, need remap transaction [" + "txId=" + req.version() + ", node=" + nearNode.id() + ", reqTopVer=" + req.topologyVersion() + ", locTopVer=" + top.readyTopologyVersion() + ", req=" + req + ']');
}
}
if (retry) {
GridNearTxPrepareResponse res = new GridNearTxPrepareResponse(req.partition(), req.version(), req.futureId(), req.miniId(), req.version(), req.version(), null, null, top.lastTopologyChangeVersion(), req.onePhaseCommit(), req.deployInfo() != null);
try {
ctx.io().send(nearNode, res, req.policy());
if (txPrepareMsgLog.isDebugEnabled()) {
txPrepareMsgLog.debug("Sent remap response for near prepare [txId=" + req.version() + ", node=" + nearNode.id() + ']');
}
} catch (ClusterTopologyCheckedException ignored) {
if (txPrepareMsgLog.isDebugEnabled()) {
txPrepareMsgLog.debug("Failed to send remap response for near prepare, node failed [" + "txId=" + req.version() + ", node=" + nearNode.id() + ']');
}
} catch (IgniteCheckedException e) {
U.error(txPrepareMsgLog, "Failed to send remap response for near prepare " + "[txId=" + req.version() + ", node=" + nearNode.id() + ", req=" + req + ']', e);
}
return new GridFinishedFuture<>(res);
}
assert topFut.isDone();
}
tx = new GridDhtTxLocal(ctx, req.topologyVersion(), nearNode.id(), req.version(), req.futureId(), req.miniId(), req.threadId(), req.implicitSingle(), req.implicitSingle(), req.system(), req.explicitLock(), req.policy(), req.concurrency(), req.isolation(), req.timeout(), req.isInvalidate(), true, req.onePhaseCommit(), req.txSize(), req.transactionNodes(), req.subjectId(), req.taskNameHash());
tx = ctx.tm().onCreated(null, tx);
if (tx != null)
tx.topologyVersion(req.topologyVersion());
else
U.warn(log, "Failed to create local transaction (was transaction rolled back?) [xid=" + req.version() + ", req=" + req + ']');
} finally {
if (tx != null)
req.txState(tx.txState());
if (top != null)
top.readUnlock();
}
}
if (tx != null) {
req.txState(tx.txState());
if (req.explicitLock())
tx.explicitLock(true);
tx.transactionNodes(req.transactionNodes());
if (req.near())
tx.nearOnOriginatingNode(true);
if (req.onePhaseCommit()) {
assert req.last() : req;
tx.onePhaseCommit(true);
}
if (req.needReturnValue())
tx.needReturnValue(true);
IgniteInternalFuture<GridNearTxPrepareResponse> fut = tx.prepareAsync(req);
if (tx.isRollbackOnly() && !tx.commitOnPrepare()) {
if (tx.state() != TransactionState.ROLLED_BACK && tx.state() != TransactionState.ROLLING_BACK)
tx.rollbackDhtLocalAsync();
}
final GridDhtTxLocal tx0 = tx;
fut.listen(new CI1<IgniteInternalFuture<?>>() {
@Override
public void apply(IgniteInternalFuture<?> txFut) {
try {
txFut.get();
} catch (IgniteCheckedException e) {
// Just in case.
tx0.setRollbackOnly();
if (!X.hasCause(e, IgniteTxOptimisticCheckedException.class) && !X.hasCause(e, IgniteFutureCancelledException.class) && !ctx.kernalContext().isStopping())
U.error(log, "Failed to prepare DHT transaction: " + tx0, e);
}
}
});
return fut;
} else
return new GridFinishedFuture<>((GridNearTxPrepareResponse) null);
}
use of org.apache.ignite.internal.IgniteInternalFuture 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);
}
}
use of org.apache.ignite.internal.IgniteInternalFuture 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) {
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 if (e instanceof IgniteTxHeuristicCheckedException) {
U.warn(log, "Failed to commit transaction (all transaction entries were invalidated): " + CU.txString(dhtTx));
} 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.IgniteInternalFuture in project ignite by apache.
the class GridPartitionedSingleGetFuture method onNodeLeft.
/**
* {@inheritDoc}
*/
@Override
public boolean onNodeLeft(UUID nodeId) {
if (!processResponse(nodeId))
return false;
if (canRemap) {
AffinityTopologyVersion updTopVer = new AffinityTopologyVersion(Math.max(topVer.topologyVersion() + 1, cctx.discovery().topologyVersion()));
cctx.affinity().affinityReadyFuture(updTopVer).listen(new CI1<IgniteInternalFuture<AffinityTopologyVersion>>() {
@Override
public void apply(IgniteInternalFuture<AffinityTopologyVersion> fut) {
try {
remap(fut.get());
} catch (IgniteCheckedException e) {
onDone(e);
}
}
});
} else
remap(topVer);
return true;
}
Aggregations