/** {@inheritDoc} */ @SuppressWarnings({"unchecked"}) @Override public void onOwnerChanged( GridCacheEntryEx entry, GridCacheMvccCandidate prev, GridCacheMvccCandidate owner) { assert entry != null; assert owner != prev : "New and previous owner are identical instances: " + owner; assert owner == null || prev == null || !owner.version().equals(prev.version()) : "New and previous owners have identical versions [owner=" + owner + ", prev=" + prev + ']'; if (log.isDebugEnabled()) log.debug( "Received owner changed callback [" + entry.key() + ", owner=" + owner + ", prev=" + prev + ']'); if (owner != null && (owner.local() || owner.nearLocal())) { Collection<? extends GridCacheFuture> futCol = futs.get(owner.version()); if (futCol != null) { for (GridCacheFuture fut : futCol) { if (fut instanceof GridCacheMvccFuture && !fut.isDone()) { GridCacheMvccFuture<Boolean> mvccFut = (GridCacheMvccFuture<Boolean>) fut; // Since this method is called outside of entry synchronization, // we can safely invoke any method on the future. // Also note that we don't remove future here if it is done. // The removal is initiated from within future itself. if (mvccFut.onOwnerChanged(entry, owner)) return; } } } } if (log.isDebugEnabled()) log.debug( "Lock future not found for owner change callback (will try transaction futures) [owner=" + owner + ", prev=" + prev + ", entry=" + entry + ']'); // If no future was found, delegate to transaction manager. if (cctx.tm().onOwnerChanged(entry, owner)) { if (log.isDebugEnabled()) log.debug("Found transaction for changed owner: " + owner); } else if (log.isDebugEnabled()) log.debug("Failed to find transaction for changed owner: " + owner); for (FinishLockFuture f : finishFuts) f.recheck(entry); }
/** @return Key. */ public K key() { GridCacheEntryEx<K, ?> parent0 = parent; if (parent0 == null) throw new IllegalStateException( "Parent entry was not initialized for MVCC candidate: " + this); return parent0.key(); }
/** {@inheritDoc} */ @Override public String toString() { GridCacheMvccCandidate<?> prev = previous(); GridCacheMvccCandidate<?> next = next(); return S.toString( GridCacheMvccCandidate.class, this, "key", parent == null ? null : parent.key(), "masks", Mask.toString(flags()), "prevVer", (prev == null ? null : prev.version()), "nextVer", (next == null ? null : next.version())); }
/** @return {@code True} if locks have been acquired. */ private boolean checkLocks() { if (!isDone() && initialized() && !hasPending()) { for (int i = 0; i < entries.size(); i++) { while (true) { GridCacheEntryEx<K, V> cached = entries.get(i); try { if (!locked(cached)) { if (log.isDebugEnabled()) log.debug( "Lock is still not acquired for entry (will keep waiting) [entry=" + cached + ", fut=" + this + ']'); return false; } break; } // Possible in concurrent cases, when owner is changed after locks // have been released or cancelled. catch (GridCacheEntryRemovedException ignore) { if (log.isDebugEnabled()) log.debug("Got removed entry in onOwnerChanged method (will retry): " + cached); // Replace old entry with new one. entries.set(i, (GridDistributedCacheEntry<K, V>) cctx.cache().entryEx(cached.key())); } } } if (log.isDebugEnabled()) log.debug("Local lock acquired for entries [fut=" + this + ", entries=" + entries + "]"); onComplete(true, true); return true; } return false; }
/** * Undoes all locks. * * @param dist If {@code true}, then remove locks from remote nodes as well. */ private void undoLocks(boolean dist) { // Transactions will undo during rollback. if (dist && tx == null) cctx.nearTx().removeLocks(lockVer, keys); else { if (tx != null) { if (tx.setRollbackOnly()) { if (log.isDebugEnabled()) log.debug( "Marked transaction as rollback only because locks could not be acquired: " + tx); } else if (log.isDebugEnabled()) log.debug( "Transaction was not marked rollback-only while locks were not acquired: " + tx); } for (GridCacheEntryEx<K, V> e : entriesCopy()) { try { e.removeLock(lockVer); } catch (GridCacheEntryRemovedException ignored) { while (true) { try { e = cctx.cache().peekEx(e.key()); if (e != null) e.removeLock(lockVer); break; } catch (GridCacheEntryRemovedException ignore) { if (log.isDebugEnabled()) log.debug( "Attempted to remove lock on removed entry (will retry) [ver=" + lockVer + ", entry=" + e + ']'); } } } } } cctx.mvcc().recheckPendingLocks(); }
/** * @param e Transaction entry. * @return {@code True} if entry is locally mapped as a primary or back up node. */ protected boolean isNearLocallyMapped(GridCacheEntryEx<K, V> e) { return F.contains(ctx.affinity(e.key(), CU.allNodes(ctx)), ctx.localNode()); }