github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/kv/kvserver/spanset/merge.go (about) 1 // Copyright 2019 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package spanset 12 13 import "sort" 14 15 type sortedSpans []Span 16 17 func (s sortedSpans) Less(i, j int) bool { 18 // Sort first on the start key and second on the end key. Note that we're 19 // relying on EndKey = nil (and len(EndKey) == 0) sorting before other 20 // EndKeys. 21 c := s[i].Key.Compare(s[j].Key) 22 if c != 0 { 23 return c < 0 24 } 25 return s[i].EndKey.Compare(s[j].EndKey) < 0 26 } 27 28 func (s sortedSpans) Swap(i, j int) { 29 s[i], s[j] = s[j], s[i] 30 } 31 32 func (s sortedSpans) Len() int { 33 return len(s) 34 } 35 36 // mergeSpans sorts the given spans and merges ones with overlapping 37 // spans and equal access timestamps. The implementation is a copy of 38 // roachpb.MergeSpans. 39 // 40 // Returns true iff all of the spans are distinct. 41 // The input spans are not safe for re-use. 42 func mergeSpans(latches []Span) ([]Span, bool) { 43 if len(latches) == 0 { 44 return latches, true 45 } 46 47 sort.Sort(sortedSpans(latches)) 48 49 // We build up the resulting slice of merged spans in place. This is safe 50 // because "r" grows by at most 1 element on each iteration, staying abreast 51 // or behind the iteration over "latches". 52 r := latches[:1] 53 distinct := true 54 55 for _, cur := range latches[1:] { 56 prev := &r[len(r)-1] 57 if len(cur.EndKey) == 0 && len(prev.EndKey) == 0 { 58 if cur.Key.Compare(prev.Key) != 0 { 59 // [a, nil] merge [b, nil] 60 r = append(r, cur) 61 } else { 62 // [a, nil] merge [a, nil] 63 if cur.Timestamp != prev.Timestamp { 64 r = append(r, cur) 65 } 66 distinct = false 67 } 68 continue 69 } 70 if len(prev.EndKey) == 0 { 71 if cur.Key.Compare(prev.Key) == 0 { 72 // [a, nil] merge [a, b] 73 if cur.Timestamp != prev.Timestamp { 74 r = append(r, cur) 75 } else { 76 prev.EndKey = cur.EndKey 77 } 78 distinct = false 79 } else { 80 // [a, nil] merge [b, c] 81 r = append(r, cur) 82 } 83 continue 84 } 85 86 if c := prev.EndKey.Compare(cur.Key); c >= 0 { 87 if cur.EndKey != nil { 88 if prev.EndKey.Compare(cur.EndKey) < 0 { 89 // [a, c] merge [b, d] 90 if cur.Timestamp != prev.Timestamp { 91 r = append(r, cur) 92 } else { 93 prev.EndKey = cur.EndKey 94 } 95 if c > 0 { 96 distinct = false 97 } 98 } else { 99 // [a, c] merge [b, c] 100 if cur.Timestamp != prev.Timestamp { 101 r = append(r, cur) 102 } 103 distinct = false 104 } 105 } else if c == 0 { 106 // [a, b] merge [b, nil] 107 if cur.Timestamp != prev.Timestamp { 108 r = append(r, cur) 109 } 110 prev.EndKey = cur.Key.Next() 111 } else { 112 // [a, c] merge [b, nil] 113 if cur.Timestamp != prev.Timestamp { 114 r = append(r, cur) 115 } 116 distinct = false 117 } 118 continue 119 } 120 r = append(r, cur) 121 } 122 return r, distinct 123 }