/** @param nodeId Left node id. */ public void onNodeLeft(final UUID nodeId) { if (isDone()) return; if (!enterBusy()) return; try { // Wait for initialization part of this future to complete. initFut.listen( new CI1<IgniteInternalFuture<?>>() { @Override public void apply(IgniteInternalFuture<?> f) { if (isDone()) return; if (!enterBusy()) return; try { // Pretend to have received message from this node. rcvdIds.add(nodeId); Collection<UUID> rmtIds = GridDhtPartitionsExchangeFuture.this.rmtIds; assert rmtIds != null; ClusterNode oldest = oldestNode.get(); if (oldest.id().equals(nodeId)) { if (log.isDebugEnabled()) log.debug( "Oldest node left or failed on partition exchange " + "(will restart exchange process)) [oldestNodeId=" + oldest.id() + ", exchangeId=" + exchId + ']'); boolean set = false; ClusterNode newOldest = CU.oldestAliveCacheServerNode(cctx, exchId.topologyVersion()); if (newOldest != null) { // If local node is now oldest. if (newOldest.id().equals(cctx.localNodeId())) { synchronized (mux) { if (oldestNode.compareAndSet(oldest, newOldest)) { // If local node is just joining. if (exchId.nodeId().equals(cctx.localNodeId())) { try { for (GridCacheContext cacheCtx : cctx.cacheContexts()) { if (!cacheCtx.isLocal()) cacheCtx .topology() .beforeExchange(GridDhtPartitionsExchangeFuture.this); } } catch (IgniteCheckedException e) { onDone(e); return; } } set = true; } } } else { synchronized (mux) { set = oldestNode.compareAndSet(oldest, newOldest); } if (set && log.isDebugEnabled()) log.debug( "Reassigned oldest node [this=" + cctx.localNodeId() + ", old=" + oldest.id() + ", new=" + newOldest.id() + ']'); } } if (set) { // If received any messages, process them. for (Map.Entry<UUID, GridDhtPartitionsSingleMessage> m : singleMsgs.entrySet()) onReceive(m.getKey(), m.getValue()); for (Map.Entry<UUID, GridDhtPartitionsFullMessage> m : fullMsgs.entrySet()) onReceive(m.getKey(), m.getValue()); // Reassign oldest node and resend. recheck(); } } else if (rmtIds.contains(nodeId)) { if (log.isDebugEnabled()) log.debug( "Remote node left of failed during partition exchange (will ignore) " + "[rmtNode=" + nodeId + ", exchangeId=" + exchId + ']'); assert rmtNodes != null; for (Iterator<ClusterNode> it = rmtNodes.iterator(); it.hasNext(); ) { if (it.next().id().equals(nodeId)) it.remove(); } if (allReceived() && ready.get() && replied.compareAndSet(false, true)) if (spreadPartitions()) onDone(exchId.topologyVersion()); } } finally { leaveBusy(); } } }); } finally { leaveBusy(); } }