public CurrentInternalStats(GossipStats gossipStats, VectorClockStats vclockStats) { _gossipStats = gossipStats; _vclockStats = vclockStats; }
/// <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; }