/** * @param fut Future. * @param doneCb Closure. */ ChainFuture( GridFutureAdapter<R> fut, IgniteClosure<? super IgniteInternalFuture<R>, T> doneCb) { this.fut = fut; this.doneCb = doneCb; fut.listen(new GridFutureChainListener<>(this, doneCb)); }
/** @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(); } }
/** * @param nodeId Sender node ID. * @param msg Full partition info. */ public void onReceive(final UUID nodeId, final GridDhtPartitionsFullMessage msg) { assert msg != null; if (isDone()) { if (log.isDebugEnabled()) log.debug("Received message for finished future [msg=" + msg + ", fut=" + this + ']'); return; } if (log.isDebugEnabled()) log.debug("Received full partition map from node [nodeId=" + nodeId + ", msg=" + msg + ']'); assert exchId.topologyVersion().equals(msg.topologyVersion()); initFut.listen( new CI1<IgniteInternalFuture<Boolean>>() { @Override public void apply(IgniteInternalFuture<Boolean> t) { ClusterNode curOldest = oldestNode.get(); if (!nodeId.equals(curOldest.id())) { if (log.isDebugEnabled()) log.debug( "Received full partition map from unexpected node [oldest=" + curOldest.id() + ", unexpectedNodeId=" + nodeId + ']'); ClusterNode snd = cctx.discovery().node(nodeId); if (snd == null) { if (log.isDebugEnabled()) log.debug( "Sender node left grid, will ignore message from unexpected node [nodeId=" + nodeId + ", exchId=" + msg.exchangeId() + ']'); return; } // Will process message later if sender node becomes oldest node. if (snd.order() > curOldest.order()) fullMsgs.put(nodeId, msg); return; } assert msg.exchangeId().equals(exchId); assert msg.lastVersion() != null; cctx.versions().onReceived(nodeId, msg.lastVersion()); updatePartitionFullMap(msg); onDone(exchId.topologyVersion()); } }); }
/** * @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); } } }); } }