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  }