internal static ImmutableList <ReachableMember> DiffReachable(Gossip oldGossip, Gossip newGossip) { if (newGossip.Equals(oldGossip)) { return(ImmutableList.Create <ReachableMember>()); } return (oldGossip.Overview.Reachability.AllUnreachable .Where(a => newGossip.HasMember(a) && newGossip.Overview.Reachability.IsReachable(a)) .Select(a => new ReachableMember(newGossip.GetMember(a))) .ToImmutableList()); }
/// <summary> /// TBD /// </summary> /// <param name="oldGossip">TBD</param> /// <param name="newGossip">TBD</param> /// <param name="selfUniqueAddress">TBD</param> /// <returns>TBD</returns> internal static ImmutableList <ReachableMember> DiffReachable(Gossip oldGossip, Gossip newGossip, UniqueAddress selfUniqueAddress) { if (newGossip.Equals(oldGossip)) { return(ImmutableList <ReachableMember> .Empty); } return(oldGossip.Overview.Reachability.AllUnreachable .Where(node => newGossip.HasMember(node) && newGossip.Overview.Reachability.IsReachable(node) && !node.Equals(selfUniqueAddress)) .Select(node => new ReachableMember(newGossip.GetMember(node))) .ToImmutableList()); }
/// <summary> /// TBD /// </summary> /// <param name="oldGossip">TBD</param> /// <param name="newGossip">TBD</param> /// <param name="selfUniqueAddress">TBD</param> /// <returns>TBD</returns> internal static ImmutableList<UnreachableMember> DiffUnreachable(Gossip oldGossip, Gossip newGossip, UniqueAddress selfUniqueAddress) { if (newGossip.Equals(oldGossip)) { return ImmutableList<UnreachableMember>.Empty; } var oldUnreachableNodes = oldGossip.Overview.Reachability.AllUnreachableOrTerminated; return newGossip.Overview.Reachability.AllUnreachableOrTerminated .Where(node => !oldUnreachableNodes.Contains(node) && !node.Equals(selfUniqueAddress)) .Select(node => new UnreachableMember(newGossip.GetMember(node))) .ToImmutableList(); }
internal static ImmutableList <UnreachableMember> DiffUnreachable(Gossip oldGossip, Gossip newGossip) { if (newGossip.Equals(oldGossip)) { return(ImmutableList.Create <UnreachableMember>()); } var oldUnreachableNodes = oldGossip.Overview.Reachability.AllUnreachableOrTerminated; return (newGossip.Overview.Reachability.AllUnreachableOrTerminated .Where(a => !oldUnreachableNodes.Contains(a)) .Select(a => new UnreachableMember(newGossip.GetMember(a))) .ToImmutableList()); }
/// <summary> /// The current snapshot state corresponding to latest gossip /// to mimic what you would have seen if you were listening to the events. /// </summary> private void SendCurrentClusterState(IActorRef receiver) { var unreachable = _latestGossip.Overview.Reachability.AllUnreachableOrTerminated .Where(node => !node.Equals(_selfUniqueAddress)) .Select(node => _latestGossip.GetMember(node)) .ToImmutableHashSet(); var state = new ClusterEvent.CurrentClusterState( members: _latestGossip.Members, unreachable: unreachable, seenBy: _latestGossip.SeenBy.Select(s => s.Address).ToImmutableHashSet(), leader: _latestGossip.Leader(_selfUniqueAddress) == null ? null : _latestGossip.Leader(_selfUniqueAddress).Address, roleLeaderMap: _latestGossip.AllRoles.ToImmutableDictionary(r => r, r => { var leader = _latestGossip.RoleLeader(r, _selfUniqueAddress); return leader == null ? null : leader.Address; })); receiver.Tell(state); }
internal static ImmutableList<ReachableMember> DiffReachable(Gossip oldGossip, Gossip newGossip) { if (newGossip.Equals(oldGossip)) return ImmutableList.Create<ReachableMember>(); return oldGossip.Overview.Reachability.AllUnreachable .Where(a => newGossip.HasMember(a) && newGossip.Overview.Reachability.IsReachable(a)) .Select(a => new ReachableMember(newGossip.GetMember(a))) .ToImmutableList(); }
internal static ImmutableList<UnreachableMember> DiffUnreachable(Gossip oldGossip, Gossip newGossip) { if (newGossip.Equals(oldGossip)) return ImmutableList.Create<UnreachableMember>(); var oldUnreachableNodes = oldGossip.Overview.Reachability.AllUnreachableOrTerminated; return newGossip.Overview.Reachability.AllUnreachableOrTerminated .Where(a => !oldUnreachableNodes.Contains(a)) .Select(a => new UnreachableMember(newGossip.GetMember(a))) .ToImmutableList(); }
/// <summary> /// The types of gossip actions that receive gossip has performed. /// </summary> public ReceiveGossipType ReceiveGossip(GossipEnvelope envelope) { var from = envelope.From; var remoteGossip = envelope.Gossip; var localGossip = _latestGossip; if (remoteGossip.Equals(Gossip.Empty)) { _log.Debug("Cluster Node [{0}] - Ignoring received gossip from [{1}] to protect against overload", _cluster.SelfAddress, from); return ReceiveGossipType.Ignored; } if (!envelope.To.Equals(SelfUniqueAddress)) { _log.Info("Ignoring received gossip intended for someone else, from [{0}] to [{1}]", from.Address, envelope.To); return ReceiveGossipType.Ignored; } if (!localGossip.Overview.Reachability.IsReachable(SelfUniqueAddress, from)) { _log.Info("Ignoring received gossip from unreachable [{0}]", from); return ReceiveGossipType.Ignored; } if (localGossip.Members.All(m => !m.UniqueAddress.Equals(from))) { _log.Debug("Cluster Node [{0}] - Ignoring received gossip from unknown [{1}]", _cluster.SelfAddress, from); return ReceiveGossipType.Ignored; } if (remoteGossip.Members.All(m => !m.UniqueAddress.Equals(SelfUniqueAddress))) { _log.Debug("Ignoring received gossip that does not contain myself, from [{0}]", from); return ReceiveGossipType.Ignored; } var comparison = remoteGossip.Version.CompareTo(localGossip.Version); Gossip winningGossip; bool talkback; ReceiveGossipType gossipType; switch (comparison) { case VectorClock.Ordering.Same: //same version winningGossip = remoteGossip.MergeSeen(localGossip); talkback = !remoteGossip.SeenByNode(SelfUniqueAddress); gossipType = ReceiveGossipType.Same; break; case VectorClock.Ordering.Before: //local is newer winningGossip = localGossip; talkback = true; gossipType = ReceiveGossipType.Older; break; case VectorClock.Ordering.After: //remote is newer winningGossip = remoteGossip; talkback = !remoteGossip.SeenByNode(SelfUniqueAddress); gossipType = ReceiveGossipType.Newer; break; default: //conflicting versions, merge winningGossip = remoteGossip.Merge(localGossip); talkback = true; gossipType = ReceiveGossipType.Merge; break; } _latestGossip = winningGossip.Seen(SelfUniqueAddress); // for all new joining nodes we remove them from the failure detector foreach (var node in _latestGossip.Members) { if (node.Status == MemberStatus.Joining && !localGossip.Members.Contains(node)) _cluster.FailureDetector.Remove(node.Address); } _log.Debug("Cluster Node [{0}] - Receiving gossip from [{1}]", _cluster.SelfAddress, from); if (comparison == VectorClock.Ordering.Concurrent) { _log.Debug(@"""Couldn't establish a causal relationship between ""remote"" gossip and ""local"" gossip - Remote[{0}] - Local[{1}] - merged them into [{2}]""", remoteGossip, localGossip, winningGossip); } if (_statsEnabled) { switch (gossipType) { case ReceiveGossipType.Merge: _gossipStats = _gossipStats.IncrementMergeCount(); break; case ReceiveGossipType.Same: _gossipStats = _gossipStats.IncrementSameCount(); break; case ReceiveGossipType.Newer: _gossipStats = _gossipStats.IncrementNewerCount(); break; case ReceiveGossipType.Older: _gossipStats = _gossipStats.IncrementOlderCount(); break; } } Publish(_latestGossip); var selfStatus = _latestGossip.GetMember(SelfUniqueAddress).Status; if (selfStatus == MemberStatus.Exiting || selfStatus == MemberStatus.Down) Shutdown(); else if (talkback) { // send back gossip to sender() when sender() had different view, i.e. merge, or sender() had // older or sender() had newer GossipTo(from, Sender); } return gossipType; }