in swim/member.go [215:274]
func shouldProcessGossip(old *Member, gossip *Member) bool {
// tombstones will not be accepted if we have no knowledge about the member
if gossip.Status == Tombstone && old == nil {
return false
}
// accept the gossip if we learn about the member through a gossip
if old == nil {
return true
}
// gossips with a higher incarnation number will always be accepted since
// it is a newer version of the member than we know
if gossip.Incarnation > old.Incarnation {
return true
}
// gossips with a lower incarnation number will never be accepted as we
// have a newer version of the member already
if gossip.Incarnation < old.Incarnation {
return false
}
// now we know that the incarnation number of the gossip and the current
// view of the member are the same 'age'. Lets evaluate member state to see
// which version to pick
// if the status of the gossip takes precedence over the status of our
// current member we will accept the gossip.
if statePrecedence(gossip.Status) > statePrecedence(old.Status) {
return true
}
if statePrecedence(gossip.Status) < statePrecedence(old.Status) {
return false
}
// keep the checksum values in local variables. The checksums are not cached
// and require some compute to get them, better to do once than twice.
gossipLabelsChecksum := gossip.Labels.checksum()
oldLabelsChecksum := old.Labels.checksum()
// Gossips with a higher checksum should be processed to let the cluster
// converge to the labels that cause the highest checksum.
if gossipLabelsChecksum > oldLabelsChecksum {
return true
}
// If the gossipped labels have a lower checksum we do want to keep the
// current memberstate in our memberlist, therefore the gossip should not be
// processed.
if gossipLabelsChecksum < oldLabelsChecksum {
return false
}
// we prefer the old member over the gossiped member if they have the same
// internal state. This prevents the gossip to be continuously be gossiped
// around in the network
return false
}