func (m *memberlist) RemoveLocalLabels(keys ...string) bool {
	removed := true
	m.updateLocalMember(func(member *Member) bool {
		labelsCopy := member.Labels.copy()
		any := false  
		for _, key := range keys {
			_, has := labelsCopy[key]
			delete(labelsCopy, key)
			removed = removed && has
			any = any || has
		}
		if any {
			member.Labels = labelsCopy
		}
		return any
	})
	return removed
}
RemoveLocalLabels removes the labels keyed by the keys from the local map of
labels. When changes are made to the member state a reincarnation will be
triggered and the new state of the member will be recorded in the disseminator
and subsequently be gossiped around. It is a valid operation to remove non-
existing keys. It returns true if all (and only all) labels have been removed.
package swim
import (
	"bytes"
	"encoding/json"
	"math/rand"
	"sort"
	"sync"
	"time"
	"github.com/uber/ringpop-go/membership"
	"github.com/benbjohnson/clock"
	"github.com/dgryski/go-farm"
	"github.com/uber-common/bark"
	"github.com/uber/ringpop-go/logging"
	"github.com/uber/ringpop-go/util"
)
type memberlist struct {
	node  *Node
	local *Member
	members struct {
		list      []*Member
		byAddress map[string]*Member
		checksum  uint32
		sync.RWMutex
	}
	logger bark.Logger
	sync.RWMutex
}
func newMemberlist(n *Node, initialLabels LabelMap) *memberlist {
	m := &memberlist{
		node:   n,
		logger: logging.Logger("membership").WithField("local", n.address),
		local: &Member{
			Address:     n.Address(),
			Incarnation: nowInMillis(n.clock),
			Status:      Alive,
			Labels:      initialLabels,
		},
	}
	m.members.byAddress = make(map[string]*Member)
	m.members.byAddress[m.local.Address] = m.local
	m.members.list = append(m.members.list, m.local)
	return m
}
func (m *memberlist) Checksum() uint32 {
	m.members.Lock()
	checksum := m.members.checksum
	m.members.Unlock()
	return checksum
}
func (m *memberlist) ComputeChecksum() {
	startTime := time.Now()
	m.members.Lock()
	checksum := farm.Fingerprint32([]byte(m.genChecksumString()))
	oldChecksum := m.members.checksum
	m.members.checksum = checksum
	m.members.Unlock()
	if oldChecksum != checksum {
		m.logger.WithFields(bark.Fields{
			"checksum":    checksum,
			"oldChecksum": oldChecksum,
		}).Debug("ringpop membership computed new checksum")
	}
	m.node.EmitEvent(ChecksumComputeEvent{
		Duration:    time.Now().Sub(startTime),
		Checksum:    checksum,
		OldChecksum: oldChecksum,
	})
}
func (m *memberlist) genChecksumString() string {
	var strings sort.StringSlice
	var buffer bytes.Buffer
	for _, member := range m.members.list {
		if member.Status == Tombstone {
			continue
		}
		member.checksumString(&buffer)
		strings = append(strings, buffer.String())
		buffer.Reset()
	}
	strings.Sort()
	for _, str := range strings {
		buffer.WriteString(str)
		buffer.WriteString(";")
	}
	return buffer.String()
}
func (m *memberlist) Member(address string) (*Member, bool) {
	var memberCopy *Member
	m.members.RLock()
	member, ok := m.members.byAddress[address]
	if member != nil {
		memberCopy = new(Member)
		*memberCopy = *member
	}
	m.members.RUnlock()
	return memberCopy, ok
}
func (m *memberlist) LocalMember() (member Member) {
	m.members.Lock()
	member = *m.local
	m.members.Unlock()
	return
}
func (m *memberlist) RemoveMember(address string) bool {
	m.members.Lock()
	member, hasMember := m.members.byAddress[address]
	if hasMember {
		delete(m.members.byAddress, address)
		for i, lMember := range m.members.list {
			if member == lMember {
				m.members.list, m.members.list[len(m.members.list)-1] = append(m.members.list[:i], m.members.list[i+1:]...), nil
				break
			}
		}
	}
	m.members.Unlock()
	if hasMember {
		m.ComputeChecksum()
	}
	return hasMember
}
func (m *memberlist) MemberAt(i int) *Member {
	m.members.RLock()
	member := new(Member)
	*member = *m.members.list[i]
	m.members.RUnlock()
	return member
}
func (m *memberlist) NumMembers() int {
	m.members.RLock()
	n := len(m.members.list)
	m.members.RUnlock()
	return n
}
func (m *memberlist) Pingable(member Member) bool {
	return member.Address != m.local.Address &&
		(member.Status == Alive || member.Status == Suspect)
}
func (m *memberlist) NumPingableMembers() (n int) {
	m.members.RLock()
	for _, member := range m.members.list {
		if m.Pingable(*member) {
			n++
		}
	}
	m.members.RUnlock()
	return n
}
func (m *memberlist) RandomPingableMembers(n int, excluding map[string]bool) []Member {
	members := make([]Member, 0, n)
	m.members.RLock()
	indices := rand.Perm(len(m.members.list))
	for _, index := range indices {
		member := m.members.list[index]
		if m.Pingable(*member) && !excluding[member.Address] {
			members = append(members, *member)
			if len(members) >= n {
				break
			}
		}
	}
	m.members.RUnlock()
	return members
}
func (m *memberlist) GetMembers(predicates ...MemberPredicate) (members []Member) {
	m.members.RLock()
	members = make([]Member, 0, len(m.members.list))
	for _, member := range m.members.list {
		if MemberMatchesPredicates(*member, predicates...) {
			members = append(members, *member)
		}
	}
	m.members.RUnlock()
	return
}
func (m *memberlist) bumpIncarnation() Change {
	m.local.Incarnation = nowInMillis(m.node.clock)
	change := Change{}
	change.populateSource(m.local)
	change.populateSubject(m.local)
	return change
}
func (m *memberlist) MakeAlive(address string, incarnation int64) []Change {
	m.node.EmitEvent(MakeNodeStatusEvent{Alive})
	return m.MakeChange(address, incarnation, Alive)
}
func (m *memberlist) MakeSuspect(address string, incarnation int64) []Change {
	m.node.EmitEvent(MakeNodeStatusEvent{Suspect})
	return m.MakeChange(address, incarnation, Suspect)
}
func (m *memberlist) MakeFaulty(address string, incarnation int64) []Change {
	m.node.EmitEvent(MakeNodeStatusEvent{Faulty})
	return m.MakeChange(address, incarnation, Faulty)
}
func (m *memberlist) SetLocalStatus(status string) {
	m.updateLocalMember(func(member *Member) bool {
		member.Status = status
		return true
	})
}
func (m *memberlist) SetLocalLabel(key, value string) error {
	return m.SetLocalLabels(map[string]string{key: value})
}
func (m *memberlist) GetLocalLabel(key string) (string, bool) {
	m.members.RLock()
	value, has := m.local.Labels[key]
	m.members.RUnlock()
	return value, has
}
func (m *memberlist) LocalLabelsAsMap() map[string]string {
	m.members.RLock()
	defer m.members.RUnlock()
	if len(m.local.Labels) == 0 {
		return nil
	}
	cpy := make(map[string]string, len(m.local.Labels))
	for k, v := range m.local.Labels {
		cpy[k] = v
	}
	return cpy
}
func (m *memberlist) SetLocalLabels(labels map[string]string) error {
	if err := m.node.labelLimits.validateLabels(m.local.Labels, labels); err != nil {
		return err
	}
	m.updateLocalMember(func(member *Member) bool {
		labelsCopy := member.Labels.copy()
		changes := false
		for key, value := range labels {
			old, had := labelsCopy[key]
			labelsCopy[key] = value
			if !had || old != value {
				changes = true
			}
		}
		if changes {
			member.Labels = labelsCopy
		}
		return changes
	})
	return nil
}