diff --git a/kv/memberlist/memberlist_client.go b/kv/memberlist/memberlist_client.go index 1b21fa5c4..637ce6764 100644 --- a/kv/memberlist/memberlist_client.go +++ b/kv/memberlist/memberlist_client.go @@ -1184,7 +1184,7 @@ func (m *KV) mergeValueForKey(key string, incomingValue Mergeable, casVersion ui m.storeMu.Lock() defer m.storeMu.Unlock() - curr := m.store[key].Clone() + curr := m.store[key] // if casVersion is 0, then there was no previous value, so we will just do normal merge, without localCAS flag set. if casVersion > 0 && curr.version != casVersion { return nil, 0, errVersionMismatch diff --git a/ring/model.go b/ring/model.go index cb2d7c787..fd93a214b 100644 --- a/ring/model.go +++ b/ring/model.go @@ -192,7 +192,8 @@ func (d *Desc) mergeWithTime(mergeable memberlist.Mergeable, localCAS bool, now return nil, nil } - thisIngesterMap := buildNormalizedIngestersMap(d) + normalizeIngestersMap(d) + thisIngesterMap := d.Ingesters otherIngesterMap := buildNormalizedIngestersMap(other) var updated []string @@ -303,6 +304,41 @@ func buildNormalizedIngestersMap(inputRing *Desc) map[string]InstanceDesc { return out } +// normalizeIngestersMap will do the following: +// - sorts tokens and removes duplicates (only within single ingester) +// - modifies the input ring +func normalizeIngestersMap(inputRing *Desc) { + for n, ing := range inputRing.Ingesters { + // Make sure LEFT ingesters have no tokens + if ing.State == LEFT { + ing.Tokens = nil + } + + // Sort tokens, and remove duplicates + if len(ing.Tokens) == 0 { + inputRing.Ingesters[n] = ing + continue + } + + if !sort.IsSorted(Tokens(ing.Tokens)) { + sort.Sort(Tokens(ing.Tokens)) + } + + // tokens are sorted now, we can easily remove duplicates. + prev := ing.Tokens[0] + for ix := 1; ix < len(ing.Tokens); { + if ing.Tokens[ix] == prev { + ing.Tokens = append(ing.Tokens[:ix], ing.Tokens[ix+1:]...) + } else { + prev = ing.Tokens[ix] + ix++ + } + } + + inputRing.Ingesters[n] = ing + } +} + func conflictingTokensExist(normalizedIngesters map[string]InstanceDesc) bool { count := 0 for _, ing := range normalizedIngesters {