/** * @param from From version. * @param to To version. */ public void mapVersion(GridCacheVersion from, GridCacheVersion to) { assert from != null; assert to != null; GridCacheVersion old = near2dht.put(from, to); assert old == null || old == to || old.equals(to); if (log.isDebugEnabled()) log.debug("Added version mapping [from=" + from + ", to=" + to + ']'); }
/** {@inheritDoc} */ @Override protected void updateExplicitVersion(IgniteTxEntry txEntry, GridCacheEntryEx entry) throws GridCacheEntryRemovedException { if (entry.detached()) { GridCacheMvccCandidate cand = cctx.mvcc().explicitLock(threadId(), entry.txKey()); if (cand != null && !xidVersion().equals(cand.version())) { GridCacheVersion candVer = cand.version(); txEntry.explicitVersion(candVer); if (candVer.isLess(minVer)) minVer = candVer; } } else super.updateExplicitVersion(txEntry, entry); }
/** * Cache preloader should call this method within partition lock. * * @param key Key. * @param ver Version. * @return {@code True} if preloading is permitted. */ public boolean preloadingPermitted(KeyCacheObject key, GridCacheVersion ver) { assert key != null; assert ver != null; assert lock.isHeldByCurrentThread(); // Only one thread can enter this method at a time. if (state() != MOVING) return false; Map<KeyCacheObject, GridCacheVersion> evictHist0 = evictHist; if (evictHist0 != null) { GridCacheVersion ver0 = evictHist0.get(key); // Permit preloading if version in history // is missing or less than passed in. return ver0 == null || ver0.isLess(ver); } return false; }
/** * @param key Key. * @param ver Version. */ public void onEntryEvicted(KeyCacheObject key, GridCacheVersion ver) { assert key != null; assert ver != null; assert lock.isHeldByCurrentThread(); // Only one thread can enter this method at a time. if (state() != MOVING) return; Map<KeyCacheObject, GridCacheVersion> evictHist0 = evictHist; if (evictHist0 != null) { GridCacheVersion ver0 = evictHist0.get(key); if (ver0 == null || ver0.isLess(ver)) { GridCacheVersion ver1 = evictHist0.put(key, ver); assert ver1 == ver0; } } }
@Override public int compare(GridCacheVersion ver1, GridCacheVersion ver2) { long time1 = ver1.globalTime(); long time2 = ver2.globalTime(); if (time1 == time2) { int nodeOrder1 = ver1.nodeOrder(); int nodeOrder2 = ver2.nodeOrder(); if (nodeOrder1 == nodeOrder2) { long order1 = ver1.order(); long order2 = ver2.order(); assert order1 != order2; return order1 > order2 ? 1 : -1; } else return nodeOrder1 > nodeOrder2 ? 1 : -1; } else return time1 > time2 ? 1 : -1; }
/** * @param nodeId Sender node id. * @param msg Single partition info. */ public void onReceive(final UUID nodeId, final GridDhtPartitionsSingleMessage msg) { assert msg != null; assert msg.exchangeId().equals(exchId); // Update last seen version. while (true) { GridCacheVersion old = lastVer.get(); if (old == null || old.compareTo(msg.lastVersion()) < 0) { if (lastVer.compareAndSet(old, msg.lastVersion())) break; } else break; } if (isDone()) { if (log.isDebugEnabled()) log.debug( "Received message for finished future (will reply only to sender) [msg=" + msg + ", fut=" + this + ']'); sendAllPartitions(nodeId, cctx.gridConfig().getNetworkSendRetryCount()); } else { initFut.listen( new CI1<IgniteInternalFuture<Boolean>>() { @Override public void apply(IgniteInternalFuture<Boolean> t) { try { if (!t.get()) // Just to check if there was an error. return; ClusterNode loc = cctx.localNode(); singleMsgs.put(nodeId, msg); boolean match = true; // Check if oldest node has changed. if (!oldestNode.get().equals(loc)) { match = false; synchronized (mux) { // Double check. if (oldestNode.get().equals(loc)) match = true; } } if (match) { boolean allReceived; synchronized (rcvdIds) { if (rcvdIds.add(nodeId)) updatePartitionSingleMap(msg); allReceived = allReceived(); } // If got all replies, and initialization finished, and reply has not been sent // yet. if (allReceived && ready.get() && replied.compareAndSet(false, true)) { spreadPartitions(); onDone(exchId.topologyVersion()); } else if (log.isDebugEnabled()) log.debug( "Exchange future full map is not sent [allReceived=" + allReceived() + ", ready=" + ready + ", replied=" + replied.get() + ", init=" + init.get() + ", fut=" + this + ']'); } } catch (IgniteCheckedException e) { U.error(log, "Failed to initialize exchange future: " + this, e); } } }); } }
/** {@inheritDoc} */ @Override public IgniteUuid futureId() { return futVer.asGridUuid(); }
/** * Marks near-local candidate as ready and makes locks reassignment. Following reorderings are * performed when candidate is marked ready: * * <ul> * <li/>All candidates preceding ready one are moved right after it. * <li/>Near local candidate is assigned a mapped dht version. All remote non-pending candidates * with version less then mapped dht version are marked as owned. * </ul> * * @param ver Version to mark as ready. * @param mappedVer Mapped dht version. * @param committedVers Committed versions. * @param rolledBackVers Rolled back versions. * @param pending Pending dht versions that are not owned and which version is less then mapped. * @return Lock owner after reassignment. */ @Nullable public CacheLockCandidates readyNearLocal( GridCacheVersion ver, GridCacheVersion mappedVer, Collection<GridCacheVersion> committedVers, Collection<GridCacheVersion> rolledBackVers, Collection<GridCacheVersion> pending) { GridCacheMvccCandidate cand = candidate(locs, ver); if (cand != null) { assert cand.nearLocal() : "Near local candidate is not marked as near local: " + cand; cand.setReady(); boolean setMapped = cand.otherVersion(mappedVer); assert setMapped : "Failed to set mapped dht version for near local candidate [mappedVer=" + mappedVer + ", cand=" + cand + ']'; // For near locals we move all not owned candidates after this one. List<GridCacheMvccCandidate> mvAfter = null; for (ListIterator<GridCacheMvccCandidate> it = locs.listIterator(); it.hasNext(); ) { GridCacheMvccCandidate c = it.next(); assert c.nearLocal() : "Near local candidate is not marked as near local: " + c; if (c == cand) { if (mvAfter != null) for (GridCacheMvccCandidate mv : mvAfter) it.add(mv); break; } else { if (c.owner()) continue; assert !c.ready() || (c.read() && cand.read()) : "Cannot have more then one ready near-local candidate [c=" + c + ", cand=" + cand + ", mvcc=" + this + ']'; it.remove(); if (mvAfter == null) mvAfter = new LinkedList<>(); mvAfter.add(c); } } // Mark all remote candidates with less version as owner unless it is pending. if (rmts != null) { for (GridCacheMvccCandidate rmt : rmts) { GridCacheVersion rmtVer = rmt.version(); if (rmtVer.isLess(mappedVer)) { if (!pending.contains(rmtVer) && !mappedVer.equals(rmt.ownerVersion())) rmt.setOwner(); } else { // Remote version is greater, so need to check if it was committed or rolled back. if (committedVers.contains(rmtVer) || rolledBackVers.contains(rmtVer)) rmt.setOwner(); } } } reassign(); } return allOwners(); }