diff --git a/partitions.go b/partitions.go index 851a7206..d9fe7daf 100644 --- a/partitions.go +++ b/partitions.go @@ -25,7 +25,7 @@ type partitions struct { selected map[int]bool local map[int]bool remote map[int][]string - old map[int][]string + disappeared map[int][]string numMissing int ready chan bool readyClosed bool @@ -45,7 +45,7 @@ func watchPartitions(zkWatcher *zkWatcher, peers *peers, db, version string, num replication: replication, local: make(map[int]bool), remote: make(map[int][]string), - old: make(map[int][]string, 1024), + disappeared: make(map[int][]string, 1024), ready: make(chan bool), } @@ -113,6 +113,19 @@ func (p *partitions) updateLocalPartitions(local map[int]bool) { } } +func (p *partitions) deDupe(nodes []string) []string { + found := map[string]bool{} + dedupedNodes := make([]string, len(nodes)) + for _, node := range nodes { + if !found[node] { + found[node] = true + + dedupedNodes = append(dedupedNodes, node) + } + } + return dedupedNodes +} + func (p *partitions) updateRemotePartitions(nodes []string) { if p.peers == nil { return @@ -131,23 +144,14 @@ func (p *partitions) updateRemotePartitions(nodes []string) { } } - // Keep track of old peers in case zookeeper goes away. for partitionId, partition := range remote { newPartition := make([]string, len(partition)) copy(newPartition, partition) - unDedupedPartition := append(newPartition, p.old[partitionId]...) - found := map[string]bool{} - - // Shitty dedupe, iterate though the remote peers - for _, node := range unDedupedPartition { - if !found[node] { - found[node] = true - p.old[partitionId] = append([]string{node}, p.old[partitionId]...) - } - } - if len(p.old[partitionId]) >= 1024 { - p.old[partitionId] = p.old[partitionId][:1024] + unDedupedPartition := append(newPartition, p.disappeared[partitionId]...) + p.disappeared[partitionId] = p.deDupe(unDedupedPartition) + if len(p.disappeared[partitionId]) >= 1024 { + p.disappeared[partitionId] = p.disappeared[partitionId][:1024] } } @@ -243,23 +247,21 @@ func (p *partitions) partitionZKNode(partition int) string { } // getPeers returns the list of peers who have the given partition available. -func (p *partitions) getPeers(partition int) []string { - if p.peers == nil { - return nil - } - +func (p *partitions) getPeers(partition int) ([]string, []string) { p.lock.RLock() defer p.lock.RUnlock() + disappearedPeers := make([]string, 1024) + copy(disappearedPeers, p.disappeared[partition]) + + if p.peers == nil { + return nil, disappearedPeers + } + peers := make([]string, len(p.remote[partition])) copy(peers, p.remote[partition]) - oldPeers := make([]string, 1024) - copy(oldPeers, p.old[partition]) - // Append old peers to peer list, in case of Zookeeper issues. - peers = append(peers, oldPeers...) - - return peers + return peers, disappearedPeers } // partitionId returns a string id for the given partition, to be used for the diff --git a/serve.go b/serve.go index c80a4222..1a0fcf58 100644 --- a/serve.go +++ b/serve.go @@ -120,12 +120,11 @@ func (vs *version) serveError(w http.ResponseWriter, key string, err error) { w.WriteHeader(http.StatusInternalServerError) } -func shuffle(vs []string) []string { +func shuffle(vs []string, disappeared []string) []string { shuffled := make([]string, len(vs)) perm := rand.Perm(len(vs)) for i, v := range perm { shuffled[v] = vs[i] } - - return shuffled + return append(shuffled, disappeared...) }