use of org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxPrepareResponse in project ignite by apache.
the class GridDhtTxPrepareFuture method onDone.
/** {@inheritDoc} */
@Override
public boolean onDone(GridNearTxPrepareResponse res0, Throwable err) {
assert err != null || (initialized() && !hasPending()) : "On done called for prepare future that has " + "pending mini futures: " + this;
ERR_UPD.compareAndSet(this, null, err);
// Must clear prepare future before response is sent or listeners are notified.
if (tx.optimistic())
tx.clearPrepareFuture(this);
// Do not commit one-phase commit transaction if originating node has near cache enabled.
if (tx.onePhaseCommit() && tx.commitOnPrepare()) {
assert last;
Throwable prepErr = this.err;
// Must create prepare response before transaction is committed to grab correct return value.
final GridNearTxPrepareResponse res = createPrepareResponse(prepErr);
onComplete(res);
if (tx.commitOnPrepare()) {
if (tx.markFinalizing(IgniteInternalTx.FinalizationStatus.USER_FINISH)) {
IgniteInternalFuture<IgniteInternalTx> fut = null;
CIX1<IgniteInternalFuture<IgniteInternalTx>> resClo = new CIX1<IgniteInternalFuture<IgniteInternalTx>>() {
@Override
public void applyx(IgniteInternalFuture<IgniteInternalTx> fut) {
if (REPLIED_UPD.compareAndSet(GridDhtTxPrepareFuture.this, 0, 1))
sendPrepareResponse(res);
}
};
if (prepErr == null) {
try {
fut = tx.commitAsync();
} catch (RuntimeException | Error e) {
Exception hEx = new IgniteTxHeuristicCheckedException("Commit produced a runtime " + "exception: " + CU.txString(tx), e);
res.error(hEx);
tx.systemInvalidate(true);
fut = tx.rollbackAsync();
fut.listen(resClo);
throw e;
}
} else if (!cctx.kernalContext().isStopping())
fut = tx.rollbackAsync();
if (fut != null)
fut.listen(resClo);
}
} else {
if (REPLIED_UPD.compareAndSet(this, 0, 1))
sendPrepareResponse(res);
}
return true;
} else {
if (REPLIED_UPD.compareAndSet(this, 0, 1)) {
GridNearTxPrepareResponse res = createPrepareResponse(this.err);
try {
sendPrepareResponse(res);
} finally {
// Will call super.onDone().
onComplete(res);
}
return true;
} else {
// Other thread is completing future. Wait for it to complete.
try {
if (err != null)
get();
} catch (IgniteInterruptedException e) {
onError(new IgniteCheckedException("Got interrupted while waiting for replies to be sent.", e));
} catch (IgniteCheckedException ignored) {
// No-op, get() was just synchronization.
}
return false;
}
}
}
use of org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxPrepareResponse in project ignite by apache.
the class IgniteTxCachePrimarySyncTest method checkOnePhaseMessages.
/**
* @param client Node executing cache operation.
* @param ccfg Cache configuration.
* @param c Cache update closure.
* @throws Exception If failed.
*/
private void checkOnePhaseMessages(Ignite client, final CacheConfiguration<Object, Object> ccfg, final IgniteBiInClosure<Integer, IgniteCache<Object, Object>> c) throws Exception {
Ignite ignite = ignite(0);
assertNotSame(ignite, client);
TestRecordingCommunicationSpi commSpiClient = (TestRecordingCommunicationSpi) client.configuration().getCommunicationSpi();
TestRecordingCommunicationSpi commSpi0 = (TestRecordingCommunicationSpi) ignite.configuration().getCommunicationSpi();
IgniteCache<Object, Object> cache = ignite.cache(ccfg.getName());
final Integer key = primaryKey(cache);
cache.remove(key);
waitKeyRemoved(ccfg.getName(), key);
final IgniteCache<Object, Object> clientCache = client.cache(ccfg.getName());
commSpi0.record(GridNearTxFinishResponse.class, GridNearTxPrepareResponse.class);
commSpiClient.record(GridNearTxPrepareRequest.class, GridNearTxFinishRequest.class);
c.apply(key, clientCache);
List<Object> srvMsgs = commSpi0.recordedMessages(true);
assertEquals("Unexpected messages: " + srvMsgs, 1, srvMsgs.size());
assertTrue("Unexpected message: " + srvMsgs.get(0), srvMsgs.get(0) instanceof GridNearTxPrepareResponse);
List<Object> clientMsgs = commSpiClient.recordedMessages(true);
assertEquals("Unexpected messages: " + clientMsgs, 1, clientMsgs.size());
assertTrue("Unexpected message: " + clientMsgs.get(0), clientMsgs.get(0) instanceof GridNearTxPrepareRequest);
GridNearTxPrepareRequest req = (GridNearTxPrepareRequest) clientMsgs.get(0);
assertTrue(req.onePhaseCommit());
for (Ignite ignite0 : G.allGrids()) assertEquals(key, ignite0.cache(cache.getName()).get(key));
}
use of org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxPrepareResponse in project ignite by apache.
the class GridDhtTxPrepareFuture method complete.
/**
* Completes this future.
*/
public void complete() {
GridNearTxPrepareResponse res = new GridNearTxPrepareResponse();
res.error(new IgniteCheckedException("Failed to prepare transaction."));
onComplete(res);
}
use of org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxPrepareResponse in project ignite by apache.
the class GridDhtTxPrepareFuture method createPrepareResponse.
/**
* @param prepErr Error.
* @return Prepare response.
*/
private GridNearTxPrepareResponse createPrepareResponse(@Nullable Throwable prepErr) {
assert F.isEmpty(tx.invalidPartitions());
GridNearTxPrepareResponse res = new GridNearTxPrepareResponse(-1, tx.nearXidVersion(), tx.colocated() ? tx.xid() : tx.nearFutureId(), nearMiniId, tx.xidVersion(), tx.writeVersion(), ret, prepErr, null, tx.activeCachesDeploymentEnabled());
if (prepErr == null) {
if (tx.needReturnValue() || tx.nearOnOriginatingNode() || tx.hasInterceptor())
addDhtValues(res);
GridCacheVersion min = tx.minVersion();
if (tx.needsCompletedVersions()) {
IgnitePair<Collection<GridCacheVersion>> versPair = cctx.tm().versions(min);
res.completedVersions(versPair.get1(), versPair.get2());
}
res.pending(localDhtPendingVersions(tx.writeEntries(), min));
tx.implicitSingleResult(ret);
}
res.filterFailedKeys(filterFailedKeys);
return res;
}
use of org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxPrepareResponse in project ignite by apache.
the class GridDhtTxPrepareFuture method prepare0.
/**
*
*/
private void prepare0() {
try {
if (tx.serializable() && tx.optimistic()) {
IgniteCheckedException err0;
try {
err0 = checkReadConflict(writes);
if (err0 == null)
err0 = checkReadConflict(reads);
} catch (IgniteCheckedException e) {
U.error(log, "Failed to check entry version: " + e, e);
err0 = e;
}
if (err0 != null) {
ERR_UPD.compareAndSet(this, null, err0);
tx.rollbackAsync();
final GridNearTxPrepareResponse res = createPrepareResponse(err);
onDone(res, res.error());
return;
}
}
// We are holding transaction-level locks for entries here, so we can get next write version.
onEntriesLocked();
// We are holding transaction-level locks for entries here, so we can get next write version.
tx.writeVersion(cctx.versions().next(tx.topologyVersion()));
{
// Assign keys to primary nodes.
if (!F.isEmpty(writes)) {
for (IgniteTxEntry write : writes) map(tx.entry(write.txKey()));
}
if (!F.isEmpty(reads)) {
for (IgniteTxEntry read : reads) map(tx.entry(read.txKey()));
}
}
if (isDone())
return;
if (last) {
int miniId = 0;
assert tx.transactionNodes() != null;
final long timeout = timeoutObj != null ? timeoutObj.timeout : 0;
// Create mini futures.
for (GridDistributedTxMapping dhtMapping : tx.dhtMap().values()) {
assert !dhtMapping.empty();
ClusterNode n = dhtMapping.primary();
assert !n.isLocal();
GridDistributedTxMapping nearMapping = tx.nearMap().get(n.id());
Collection<IgniteTxEntry> nearWrites = nearMapping == null ? null : nearMapping.writes();
Collection<IgniteTxEntry> dhtWrites = dhtMapping.writes();
if (F.isEmpty(dhtWrites) && F.isEmpty(nearWrites))
continue;
if (tx.remainingTime() == -1)
return;
MiniFuture fut = new MiniFuture(n.id(), ++miniId, dhtMapping, nearMapping);
// Append new future.
add(fut);
assert txNodes != null;
GridDhtTxPrepareRequest req = new GridDhtTxPrepareRequest(futId, fut.futureId(), tx.topologyVersion(), tx, timeout, dhtWrites, nearWrites, txNodes, tx.nearXidVersion(), true, tx.onePhaseCommit(), tx.subjectId(), tx.taskNameHash(), tx.activeCachesDeploymentEnabled(), retVal);
int idx = 0;
for (IgniteTxEntry entry : dhtWrites) {
try {
GridDhtCacheEntry cached = (GridDhtCacheEntry) entry.cached();
GridCacheContext<?, ?> cacheCtx = cached.context();
// Do not invalidate near entry on originating transaction node.
req.invalidateNearEntry(idx, !tx.nearNodeId().equals(n.id()) && cached.readerId(n.id()) != null);
if (cached.isNewLocked()) {
List<ClusterNode> owners = cacheCtx.topology().owners(cached.partition(), tx != null ? tx.topologyVersion() : cacheCtx.affinity().affinityTopologyVersion());
// Do not preload if local node is a partition owner.
if (!owners.contains(cctx.localNode()))
req.markKeyForPreload(idx);
}
break;
} catch (GridCacheEntryRemovedException ignore) {
assert false : "Got removed exception on entry with dht local candidate: " + entry;
}
idx++;
}
if (!F.isEmpty(nearWrites)) {
for (IgniteTxEntry entry : nearWrites) {
try {
if (entry.explicitVersion() == null) {
GridCacheMvccCandidate added = entry.cached().candidate(version());
assert added != null : "Missing candidate for cache entry:" + entry;
assert added.dhtLocal();
if (added.ownerVersion() != null)
req.owned(entry.txKey(), added.ownerVersion());
}
break;
} catch (GridCacheEntryRemovedException ignore) {
assert false : "Got removed exception on entry with dht local candidate: " + entry;
}
}
}
assert req.transactionNodes() != null;
try {
cctx.io().send(n, req, tx.ioPolicy());
if (msgLog.isDebugEnabled()) {
msgLog.debug("DHT prepare fut, sent request dht [txId=" + tx.nearXidVersion() + ", dhtTxId=" + tx.xidVersion() + ", node=" + n.id() + ']');
}
} catch (ClusterTopologyCheckedException ignored) {
fut.onNodeLeft();
} catch (IgniteCheckedException e) {
if (!cctx.kernalContext().isStopping()) {
if (msgLog.isDebugEnabled()) {
msgLog.debug("DHT prepare fut, failed to send request dht [txId=" + tx.nearXidVersion() + ", dhtTxId=" + tx.xidVersion() + ", node=" + n.id() + ']');
}
fut.onResult(e);
} else {
if (msgLog.isDebugEnabled()) {
msgLog.debug("DHT prepare fut, failed to send request dht, ignore [txId=" + tx.nearXidVersion() + ", dhtTxId=" + tx.xidVersion() + ", node=" + n.id() + ", err=" + e + ']');
}
}
}
}
for (GridDistributedTxMapping nearMapping : tx.nearMap().values()) {
if (!tx.dhtMap().containsKey(nearMapping.primary().id())) {
if (tx.remainingTime() == -1)
return;
MiniFuture fut = new MiniFuture(nearMapping.primary().id(), ++miniId, null, nearMapping);
// Append new future.
add(fut);
GridDhtTxPrepareRequest req = new GridDhtTxPrepareRequest(futId, fut.futureId(), tx.topologyVersion(), tx, timeout, null, nearMapping.writes(), tx.transactionNodes(), tx.nearXidVersion(), true, tx.onePhaseCommit(), tx.subjectId(), tx.taskNameHash(), tx.activeCachesDeploymentEnabled(), retVal);
for (IgniteTxEntry entry : nearMapping.entries()) {
if (CU.writes().apply(entry)) {
try {
if (entry.explicitVersion() == null) {
GridCacheMvccCandidate added = entry.cached().candidate(version());
assert added != null : "Null candidate for non-group-lock entry " + "[added=" + added + ", entry=" + entry + ']';
assert added.dhtLocal() : "Got non-dht-local candidate for prepare future" + "[added=" + added + ", entry=" + entry + ']';
if (added != null && added.ownerVersion() != null)
req.owned(entry.txKey(), added.ownerVersion());
}
break;
} catch (GridCacheEntryRemovedException ignore) {
assert false : "Got removed exception on entry with dht local candidate: " + entry;
}
}
}
assert req.transactionNodes() != null;
try {
cctx.io().send(nearMapping.primary(), req, tx.ioPolicy());
if (msgLog.isDebugEnabled()) {
msgLog.debug("DHT prepare fut, sent request near [txId=" + tx.nearXidVersion() + ", dhtTxId=" + tx.xidVersion() + ", node=" + nearMapping.primary().id() + ']');
}
} catch (ClusterTopologyCheckedException ignored) {
fut.onNodeLeft();
} catch (IgniteCheckedException e) {
if (!cctx.kernalContext().isStopping()) {
if (msgLog.isDebugEnabled()) {
msgLog.debug("DHT prepare fut, failed to send request near [txId=" + tx.nearXidVersion() + ", dhtTxId=" + tx.xidVersion() + ", node=" + nearMapping.primary().id() + ']');
}
fut.onResult(e);
} else {
if (msgLog.isDebugEnabled()) {
msgLog.debug("DHT prepare fut, failed to send request near, ignore [txId=" + tx.nearXidVersion() + ", dhtTxId=" + tx.xidVersion() + ", node=" + nearMapping.primary().id() + ", err=" + e + ']');
}
}
}
}
}
}
} finally {
markInitialized();
}
}
Aggregations