/** * @param entry Entry to enlist. * @throws IgniteCheckedException If failed. * @return {@code True} if entry was enlisted. */ private boolean addEntry(IgniteTxEntry entry) throws IgniteCheckedException { checkInternal(entry.txKey()); GridCacheContext cacheCtx = entry.context(); if (!cacheCtx.isNear()) cacheCtx = cacheCtx.dht().near().context(); GridNearCacheEntry cached = cacheCtx.near().peekExx(entry.key()); if (cached == null) { evicted.add(entry.txKey()); return false; } else { try { cached.unswap(); CacheObject val = cached.peek(true, false, false, null); if (val == null && cached.evictInternal(false, xidVer, null)) { evicted.add(entry.txKey()); return false; } else { // Initialize cache entry. entry.cached(cached); txState.addWriteEntry(entry.txKey(), entry); addExplicit(entry); return true; } } catch (GridCacheEntryRemovedException ignore) { evicted.add(entry.txKey()); if (log.isDebugEnabled()) log.debug("Got removed entry when adding to remote transaction (will ignore): " + cached); return false; } } }
/** * @param entries Entries. * @param dhtVer DHT version. * @param pendingVers Pending versions. * @param committedVers Committed versions. * @param rolledbackVers Rolled back versions. */ void readyNearLocks( Collection<IgniteTxEntry> entries, GridCacheVersion dhtVer, Collection<GridCacheVersion> pendingVers, Collection<GridCacheVersion> committedVers, Collection<GridCacheVersion> rolledbackVers) { for (IgniteTxEntry txEntry : entries) { while (true) { GridCacheContext cacheCtx = txEntry.cached().context(); assert cacheCtx.isNear(); GridDistributedCacheEntry entry = (GridDistributedCacheEntry) txEntry.cached(); try { // Handle explicit locks. GridCacheVersion explicit = txEntry.explicitVersion(); if (explicit == null) { entry.readyNearLock(xidVer, dhtVer, committedVers, rolledbackVers, pendingVers); } break; } catch (GridCacheEntryRemovedException ignored) { assert entry.obsoleteVersion() != null; if (log.isDebugEnabled()) log.debug( "Replacing obsolete entry in remote transaction [entry=" + entry + ", tx=" + this + ']'); // Replace the entry. txEntry.cached(txEntry.context().cache().entryEx(txEntry.key())); } } } }
/** {@inheritDoc} */ @Override public boolean onDone(IgniteInternalTx tx0, Throwable err) { if (isDone()) return false; synchronized (this) { if (isDone()) return false; if (err != null) { tx.commitError(err); boolean marked = tx.setRollbackOnly(); if (err instanceof IgniteTxRollbackCheckedException) { if (marked) { try { tx.rollback(); } catch (IgniteCheckedException ex) { U.error(log, "Failed to automatically rollback transaction: " + tx, ex); } } } else if (tx.implicit() && tx.isSystemInvalidate()) { // Finish implicit transaction on heuristic error. try { tx.close(); } catch (IgniteCheckedException ex) { U.error(log, "Failed to invalidate transaction: " + tx, ex); } } } if (initialized() || err != null) { if (tx.needCheckBackup()) { assert tx.onePhaseCommit(); if (err != null) err = new TransactionRollbackException("Failed to commit transaction.", err); try { tx.finish(err == null); } catch (IgniteCheckedException e) { if (err != null) err.addSuppressed(e); else err = e; } } if (tx.onePhaseCommit()) { boolean commit = this.commit && err == null; finishOnePhase(commit); tx.tmFinish(commit); } if (super.onDone(tx0, err)) { if (error() instanceof IgniteTxHeuristicCheckedException) { AffinityTopologyVersion topVer = tx.topologyVersion(); for (IgniteTxEntry e : tx.writeMap().values()) { GridCacheContext cacheCtx = e.context(); try { if (e.op() != NOOP && !cacheCtx.affinity().localNode(e.key(), topVer)) { GridCacheEntryEx entry = cacheCtx.cache().peekEx(e.key()); if (entry != null) entry.invalidate(null, tx.xidVersion()); } } catch (Throwable t) { U.error(log, "Failed to invalidate entry.", t); if (t instanceof Error) throw (Error) t; } } } // Don't forget to clean up. cctx.mvcc().removeFuture(futId); return true; } } } return false; }