use of org.apache.ignite.internal.processors.cache.transactions.TxCounters in project ignite by apache.
the class GridDhtLocalPartition method nextUpdateCounter.
/**
* Used for transactions.
*
* @param cacheId Cache id.
* @param tx Tx.
* @param primaryCntr Primary counter.
*/
public long nextUpdateCounter(int cacheId, IgniteInternalTx tx, @Nullable Long primaryCntr) {
Long nextCntr;
if (primaryCntr != null)
nextCntr = primaryCntr;
else {
TxCounters txCounters = tx.txCounters(false);
assert txCounters != null : "Must have counters for tx [nearXidVer=" + tx.nearXidVersion() + ']';
// Null must never be returned on primary node.
nextCntr = txCounters.generateNextCounter(cacheId, id());
assert nextCntr != null : this;
}
if (grp.sharedGroup())
grp.onPartitionCounterUpdate(cacheId, id, nextCntr, tx.topologyVersion(), tx.local());
return nextCntr;
}
use of org.apache.ignite.internal.processors.cache.transactions.TxCounters in project ignite by apache.
the class GridDistributedTxRemoteAdapter method rollbackRemoteTx.
/**
* {@inheritDoc}
*/
@Override
public final void rollbackRemoteTx() {
try {
// they will be deleted by their corresponding transactions.
if (state(ROLLING_BACK) || state() == UNKNOWN) {
cctx.tm().rollbackTx(this, false, skipCompletedVersions());
TxCounters counters = txCounters(false);
if (counters != null)
cctx.tm().txHandler().applyPartitionsUpdatesCounters(counters.updateCounters(), true, false);
state(ROLLED_BACK);
cctx.mvccCaching().onTxFinished(this, false);
}
} catch (IgniteCheckedException | RuntimeException | Error e) {
state(UNKNOWN);
U.error(log, "Error during tx rollback.", e);
if (e instanceof IgniteCheckedException)
throw new IgniteException(e);
else if (e instanceof RuntimeException)
throw (RuntimeException) e;
else
throw (Error) e;
}
}
use of org.apache.ignite.internal.processors.cache.transactions.TxCounters in project ignite by apache.
the class MvccCachingManager method onTxFinished.
/**
* @param tx Transaction.
* @param commit {@code True} if commit.
*/
public void onTxFinished(IgniteInternalTx tx, boolean commit) throws IgniteCheckedException {
if (log.isDebugEnabled())
log.debug("Transaction finished: [commit=" + commit + ", tx=" + tx + ']');
if (tx.system() || tx.internal() || tx.mvccSnapshot() == null)
return;
cntrs.remove(new TxKey(tx.mvccSnapshot().coordinatorVersion(), tx.mvccSnapshot().counter()));
EnlistBuffer buf = enlistCache.remove(tx.xidVersion());
Map<Integer, Map<KeyCacheObject, MvccTxEntry>> allCached = buf == null ? null : buf.getCached();
TxCounters txCntrs = tx.txCounters(false);
Collection<PartitionUpdateCountersMessage> cntrsColl = txCntrs == null ? null : txCntrs.updateCounters();
if (txCntrs == null || F.isEmpty(cntrsColl))
return;
GridIntList cacheIds = tx.txState().cacheIds();
assert cacheIds != null;
for (int i = 0; i < cacheIds.size(); i++) {
int cacheId = cacheIds.get(i);
GridCacheContext ctx0 = cctx.cacheContext(cacheId);
assert ctx0 != null;
ctx0.group().listenerLock().readLock().lock();
try {
boolean hasListeners = ctx0.hasContinuousQueryListeners(tx);
boolean drEnabled = ctx0.isDrEnabled();
if (!hasListeners && !drEnabled)
// There are no listeners to notify.
continue;
// Get cached entries for the given cache.
Map<KeyCacheObject, MvccTxEntry> cached = allCached == null ? null : allCached.get(cacheId);
Map<Integer, Map<Integer, T2<AtomicLong, Long>>> cntrsMap = countersPerPartition(cntrsColl);
Map<Integer, T2<AtomicLong, Long>> cntrPerCache = cntrsMap.get(cacheId);
if (F.isEmpty(cntrPerCache))
// No updates were made for this cache.
continue;
boolean fakeEntries = false;
if (F.isEmpty(cached)) {
if (log.isDebugEnabled())
log.debug("Transaction updates were not cached fully (this can happen when listener started" + " during the transaction execution). [tx=" + tx + ']');
if (hasListeners) {
// Create fake update entries if we have CQ listeners.
cached = createFakeCachedEntries(cntrPerCache, tx, cacheId);
fakeEntries = true;
} else
// Nothing to do further if tx is not cached entirely and there are no any CQ listeners.
continue;
}
if (F.isEmpty(cached))
continue;
// Feed CQ & DR with entries.
for (Map.Entry<KeyCacheObject, MvccTxEntry> entry : cached.entrySet()) {
MvccTxEntry e = entry.getValue();
assert e.key().partition() != -1;
assert cntrPerCache != null;
assert e.cacheId() == cacheId;
T2<AtomicLong, Long> cntr = cntrPerCache.get(e.key().partition());
long resCntr = cntr.getKey().incrementAndGet();
assert resCntr <= cntr.getValue();
e.updateCounter(resCntr);
if (ctx0.group().sharedGroup()) {
ctx0.group().onPartitionCounterUpdate(cacheId, e.key().partition(), resCntr, tx.topologyVersion(), tx.local());
}
if (log.isDebugEnabled())
log.debug("Process cached entry:" + e);
// DR
if (ctx0.isDrEnabled() && !fakeEntries) {
ctx0.dr().replicate(e.key(), e.value(), e.ttl(), e.expireTime(), e.version(), tx.local() ? DR_PRIMARY : DR_BACKUP, e.topologyVersion());
}
// CQ
CacheContinuousQueryManager contQryMgr = ctx0.continuousQueries();
if (ctx0.continuousQueries().notifyContinuousQueries(tx)) {
Map<UUID, CacheContinuousQueryListener> lsnrCol = continuousQueryListeners(ctx0, tx);
if (!F.isEmpty(lsnrCol)) {
contQryMgr.onEntryUpdated(lsnrCol, e.key(), // Force skip update counter if rolled back.
commit ? e.value() : null, // Force skip update counter if rolled back.
commit ? e.oldValue() : null, false, e.key().partition(), tx.local(), false, e.updateCounter(), null, e.topologyVersion());
}
}
}
} finally {
ctx0.group().listenerLock().readLock().unlock();
}
}
}
use of org.apache.ignite.internal.processors.cache.transactions.TxCounters in project ignite by apache.
the class GridDhtTxPrepareFuture method prepare0.
/**
*/
private void prepare0() throws IgniteTxRollbackCheckedException {
boolean error = false;
try {
if (tx.serializable() && tx.optimistic()) {
IgniteCheckedException err0;
try {
err0 = checkReadConflict(req.writes());
if (err0 == null)
err0 = checkReadConflict(req.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);
try {
tx.rollbackAsync();
} catch (Throwable e) {
err0.addSuppressed(e);
}
final GridNearTxPrepareResponse res = createPrepareResponse(err);
onDone(res, res.error());
return;
}
}
onEntriesLocked();
// We are holding transaction-level locks for entries here, so we can get next write version.
tx.writeVersion(cctx.cacheContext(tx.txState().firstCacheId()).cache().nextVersion());
TxCounters counters = tx.txCounters(true);
// Assign keys to primary nodes.
if (!F.isEmpty(req.writes())) {
for (IgniteTxEntry write : req.writes()) {
IgniteTxEntry entry = tx.entry(write.txKey());
assert entry != null && entry.cached() != null : entry;
// Counter shouldn't be reserved for mvcc, local cache entries, NOOP operations and NOOP transforms.
if (!entry.cached().isLocal() && entry.op() != NOOP && !(entry.op() == TRANSFORM && (// Possible for txs over cachestore
entry.entryProcessorCalculatedValue() == null || entry.entryProcessorCalculatedValue().get1() == NOOP)))
counters.incrementUpdateCounter(entry.cacheId(), entry.cached().partition());
map(entry);
}
}
if (!F.isEmpty(req.reads())) {
for (IgniteTxEntry read : req.reads()) map(tx.entry(read.txKey()));
}
if (isDone())
return;
if (last) {
if (!tx.txState().mvccEnabled()) {
/**
* For MVCC counters are assigned on enlisting.
*/
/**
* See usage of {@link TxCounters#incrementUpdateCounter(int, int)} )
*/
tx.calculatePartitionUpdateCounters();
}
recheckOnePhaseCommit();
if (tx.onePhaseCommit())
tx.chainState(PREPARED);
sendPrepareRequests();
}
} catch (Throwable t) {
error = true;
throw t;
} finally {
if (// Prevent marking future as initialized on error.
!error)
markInitialized();
}
}
use of org.apache.ignite.internal.processors.cache.transactions.TxCounters in project ignite by apache.
the class GridDhtTxFinishFuture method onDone.
/**
* {@inheritDoc}
*/
@Override
public boolean onDone(IgniteInternalTx tx, Throwable err) {
try (TraceSurroundings ignored = MTC.support(span)) {
if (initialized() || err != null) {
Throwable e = this.err;
if (this.tx.onePhaseCommit() && (this.tx.state() == COMMITTING)) {
try {
boolean nodeStopping = X.hasCause(err, NodeStoppingException.class);
this.tx.tmFinish(err == null, nodeStopping || cctx.kernalContext().failure().nodeStopping(), false);
} catch (IgniteCheckedException finishErr) {
U.error(log, "Failed to finish tx: " + tx, e);
if (e == null)
e = finishErr;
}
}
if (commit && e == null)
e = this.tx.commitError();
Throwable finishErr = e != null ? e : err;
if (super.onDone(tx, finishErr)) {
cctx.tm().mvccFinish(this.tx);
if (finishErr == null)
finishErr = this.tx.commitError();
if (this.tx.syncMode() != PRIMARY_SYNC)
this.tx.sendFinishReply(finishErr);
if (!this.tx.txState().mvccEnabled() && !commit && shouldApplyCountersOnRollbackError(finishErr)) {
TxCounters txCounters = this.tx.txCounters(false);
if (txCounters != null) {
try {
cctx.tm().txHandler().applyPartitionsUpdatesCounters(txCounters.updateCounters(), true, true);
} catch (IgniteCheckedException e0) {
throw new IgniteException(e0);
}
}
}
// Don't forget to clean up.
cctx.mvcc().removeFuture(futId);
return true;
}
}
return false;
}
}
Aggregations