func (r *HashRing) ServerCount() int {
	r.RLock()
	count := len(r.serverSet)
	r.RUnlock()
	return count
}
ServerCount returns the number of servers contained in the HashRing.
package hashring
import (
	"fmt"
	"strings"
	"sync"
	"github.com/uber/ringpop-go/events"
	"github.com/uber/ringpop-go/logging"
	"github.com/uber/ringpop-go/membership"
	"github.com/uber-common/bark"
)
type Configuration struct {
	ReplicaPoints int
}
type replicaPoint struct {
	hash int
	identity string
	address string
	index int
}
func (r replicaPoint) Compare(other interface{}) (result int) {
	o := other.(replicaPoint)
	result = r.hash - o.hash
	if result != 0 {
		return
	}
	result = strings.Compare(r.address, o.address)
	if result != 0 {
		return
	}
	result = r.index - o.index
	return
}
type HashRing struct {
	sync.RWMutex
	events.SyncEventEmitter
	hashfunc      func(string) int
	replicaPoints int
	serverSet map[string]struct{}
	tree      *redBlackTree
	legacyChecksum uint32
	checksummers map[string]Checksummer
	checksums map[string]uint32
	logger bark.Logger
}
func New(hashfunc func([]byte) uint32, replicaPoints int) *HashRing {
	r := &HashRing{
		replicaPoints: replicaPoints,
		hashfunc: func(str string) int {
			return int(hashfunc([]byte(str)))
		},
		logger: logging.Logger("ring"),
		checksummers: map[string]Checksummer{
			"replica": &replicaPointChecksummer{},
		},
	}
	r.serverSet = make(map[string]struct{})
	r.tree = &redBlackTree{}
	return r
}
func (r *HashRing) Checksum() (checksum uint32) {
	r.RLock()
	checksum = r.legacyChecksum
	r.RUnlock()
	return
}
func (r *HashRing) Checksums() (checksums map[string]uint32) {
	r.RLock()
	checksums = r.checksums
	r.RUnlock()
	return
}
func (r *HashRing) computeChecksumsNoLock() {
	oldChecksums := r.checksums
	r.checksums = make(map[string]uint32)
	changed := false
	for name, checksummer := range r.checksummers {
		oldChecksum := oldChecksums[name]
		newChecksum := checksummer.Checksum(r)
		r.checksums[name] = newChecksum
		if oldChecksum != newChecksum {
			changed = true
		}
	}
	legacyChecksummer := identityChecksummer{}
	oldChecksum := r.legacyChecksum
	newChecksum := legacyChecksummer.Checksum(r)
	r.legacyChecksum = newChecksum
	if oldChecksum != newChecksum {
		changed = true
	}
	if changed {
		r.logger.WithFields(bark.Fields{
			"checksum":    r.legacyChecksum,
			"oldChecksum": oldChecksum,
			"checksums":   r.checksums,
		}).Debug("ringpop ring computed new checksum")
	}
	r.EmitEvent(events.RingChecksumEvent{
		OldChecksum:  oldChecksum,
		NewChecksum:  r.legacyChecksum,
		OldChecksums: oldChecksums,
		NewChecksums: r.checksums,
	})
}
func (r *HashRing) replicaPointForServer(server membership.Member, replica int) replicaPoint {
	identity := server.Identity()
	var replicaStr string
	if identity == server.GetAddress() {
		replicaStr = fmt.Sprintf("%s%v", identity, replica)
	} else {
		replicaStr = fmt.Sprintf("%s#%v", identity, replica)
	}
	return replicaPoint{
		hash:     r.hashfunc(replicaStr),
		identity: identity,
		address:  server.GetAddress(),
		index:    replica,
	}
}
func (r *HashRing) AddMembers(members ...membership.Member) bool {
	r.Lock()
	changed := false
	var added []string
	for _, member := range members {
		if r.addMemberNoLock(member) {
			added = append(added, member.GetAddress())
			changed = true
		}
	}
	if changed {
		r.computeChecksumsNoLock()
		r.EmitEvent(events.RingChangedEvent{
			ServersAdded: added,
		})
	}
	r.Unlock()
	return changed
}
func (r *HashRing) addMemberNoLock(member membership.Member) bool {
	if _, ok := r.serverSet[member.GetAddress()]; ok {
		return false
	}
	r.serverSet[member.GetAddress()] = struct{}{}
	for i := 0; i < r.replicaPoints; i++ {
		r.tree.Insert(
			r.replicaPointForServer(member, i),
			member.GetAddress(),
		)
	}
	return true
}
func (r *HashRing) RemoveMembers(members ...membership.Member) bool {
	r.Lock()
	changed := false
	var removed []string
	for _, server := range members {
		if r.removeMemberNoLock(server) {
			removed = append(removed, server.GetAddress())
			changed = true
		}
	}
	if changed {
		r.computeChecksumsNoLock()
		r.EmitEvent(events.RingChangedEvent{
			ServersRemoved: removed,
		})
	}
	r.Unlock()
	return changed
}
func (r *HashRing) removeMemberNoLock(member membership.Member) bool {
	if _, ok := r.serverSet[member.GetAddress()]; !ok {
		return false
	}
	delete(r.serverSet, member.GetAddress())
	for i := 0; i < r.replicaPoints; i++ {
		r.tree.Delete(
			r.replicaPointForServer(member, i),
		)
	}
	return true
}
func (r *HashRing) ProcessMembershipChanges(changes []membership.MemberChange) {
	r.Lock()
	changed := false
	var added, updated, removed []string
	for _, change := range changes {
		if change.Before == nil && change.After != nil {
			if r.addMemberNoLock(change.After) {
				added = append(added, change.After.GetAddress())
				changed = true
			}
		} else if change.Before != nil && change.After == nil {
			if r.removeMemberNoLock(change.Before) {
				removed = append(removed, change.Before.GetAddress())
				changed = true
			}
		} else {
			if change.Before.Identity() != change.After.Identity() {
				r.removeMemberNoLock(change.Before)
				r.addMemberNoLock(change.After)
				updated = append(updated, change.After.GetAddress())
				changed = true
			}
		}
	}
	if changed {
		r.computeChecksumsNoLock()
		r.EmitEvent(events.RingChangedEvent{
			ServersAdded:   added,
			ServersUpdated: updated,
			ServersRemoved: removed,
		})
	}
	r.Unlock()
}
func (r *HashRing) HasServer(server string) bool {
	r.RLock()
	_, ok := r.serverSet[server]
	r.RUnlock()
	return ok
}
func (r *HashRing) Servers() []string {
	r.RLock()
	servers := r.copyServersNoLock()
	r.RUnlock()
	return servers
}
func (r *HashRing) copyServersNoLock() []string {
	servers := make([]string, 0, len(r.serverSet))
	for server := range r.serverSet {
		servers = append(servers, server)
	}
	return servers
}