github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/internal/keyspan/iter.go (about)

     1  // Copyright 2018 The LevelDB-Go and Pebble Authors. All rights reserved. Use
     2  // of this source code is governed by a BSD-style license that can be found in
     3  // the LICENSE file.
     4  
     5  package keyspan
     6  
     7  import (
     8  	"github.com/cockroachdb/pebble/internal/base"
     9  	"github.com/cockroachdb/pebble/internal/manifest"
    10  )
    11  
    12  // FragmentIterator defines an iterator interface over spans. The spans
    13  // surfaced by a FragmentIterator must be non-overlapping. This is achieved by
    14  // fragmenting spans at overlap points (see Fragmenter).
    15  //
    16  // A Span returned by a FragmentIterator is only valid until the next
    17  // positioning method. Some implementations (eg, keyspan.Iter) may provide
    18  // longer lifetimes but implementations need only guarantee stability until the
    19  // next positioning method.
    20  type FragmentIterator interface {
    21  	// SeekGE moves the iterator to the first span covering a key greater than
    22  	// or equal to the given key. This is equivalent to seeking to the first
    23  	// span with an end key greater than the given key.
    24  	SeekGE(key []byte) *Span
    25  
    26  	// SeekLT moves the iterator to the last span covering a key less than the
    27  	// given key. This is equivalent to seeking to the last span with a start
    28  	// key less than the given key.
    29  	SeekLT(key []byte) *Span
    30  
    31  	// First moves the iterator to the first span.
    32  	First() *Span
    33  
    34  	// Last moves the iterator to the last span.
    35  	Last() *Span
    36  
    37  	// Next moves the iterator to the next span.
    38  	//
    39  	// It is valid to call Next when the iterator is positioned before the first
    40  	// key/value pair due to either a prior call to SeekLT or Prev which
    41  	// returned an invalid span. It is not allowed to call Next when the
    42  	// previous call to SeekGE, SeekPrefixGE or Next returned an invalid span.
    43  	Next() *Span
    44  
    45  	// Prev moves the iterator to the previous span.
    46  	//
    47  	// It is valid to call Prev when the iterator is positioned after the last
    48  	// key/value pair due to either a prior call to SeekGE or Next which
    49  	// returned an invalid span. It is not allowed to call Prev when the
    50  	// previous call to SeekLT or Prev returned an invalid span.
    51  	Prev() *Span
    52  
    53  	// Error returns any accumulated error.
    54  	//
    55  	// TODO(jackson): Lift errors into return values on the positioning methods.
    56  	Error() error
    57  
    58  	// Close closes the iterator and returns any accumulated error. Exhausting
    59  	// the iterator is not considered to be an error. It is valid to call Close
    60  	// multiple times. Other methods should not be called after the iterator has
    61  	// been closed.
    62  	Close() error
    63  }
    64  
    65  // TableNewSpanIter creates a new iterator for range key spans for the given
    66  // file.
    67  type TableNewSpanIter func(file *manifest.FileMetadata, iterOptions SpanIterOptions) (FragmentIterator, error)
    68  
    69  // SpanIterOptions is a subset of IterOptions that are necessary to instantiate
    70  // per-sstable span iterators.
    71  type SpanIterOptions struct {
    72  	// RangeKeyFilters can be used to avoid scanning tables and blocks in tables
    73  	// when iterating over range keys.
    74  	RangeKeyFilters []base.BlockPropertyFilter
    75  }
    76  
    77  // Iter is an iterator over a set of fragmented spans.
    78  type Iter struct {
    79  	cmp   base.Compare
    80  	spans []Span
    81  	index int
    82  }
    83  
    84  // Iter implements the FragmentIterator interface.
    85  var _ FragmentIterator = (*Iter)(nil)
    86  
    87  // NewIter returns a new iterator over a set of fragmented spans.
    88  func NewIter(cmp base.Compare, spans []Span) *Iter {
    89  	i := &Iter{}
    90  	i.Init(cmp, spans)
    91  	return i
    92  }
    93  
    94  // Count returns the number of spans contained by Iter.
    95  func (i *Iter) Count() int {
    96  	return len(i.spans)
    97  }
    98  
    99  // Init initializes an Iter with the provided spans.
   100  func (i *Iter) Init(cmp base.Compare, spans []Span) {
   101  	*i = Iter{
   102  		cmp:   cmp,
   103  		spans: spans,
   104  		index: -1,
   105  	}
   106  }
   107  
   108  // SeekGE implements FragmentIterator.SeekGE.
   109  func (i *Iter) SeekGE(key []byte) *Span {
   110  	// NB: manually inlined sort.Search is ~5% faster.
   111  	//
   112  	// Define f(j) = false iff the span i.spans[j] is strictly before `key`
   113  	// (equivalently, i.spans[j].End ≤ key.)
   114  	//
   115  	// Define f(-1) == false and f(n) == true.
   116  	// Invariant: f(index-1) == false, f(upper) == true.
   117  	i.index = 0
   118  	upper := len(i.spans)
   119  	for i.index < upper {
   120  		h := int(uint(i.index+upper) >> 1) // avoid overflow when computing h
   121  		// i.index ≤ h < upper
   122  		if i.cmp(key, i.spans[h].End) >= 0 {
   123  			i.index = h + 1 // preserves f(i-1) == false
   124  		} else {
   125  			upper = h // preserves f(j) == true
   126  		}
   127  	}
   128  
   129  	// i.index == upper, f(i.index-1) == false, and f(upper) (= f(i.index)) ==
   130  	// true => answer is i.index.
   131  	if i.index >= len(i.spans) {
   132  		return nil
   133  	}
   134  	return &i.spans[i.index]
   135  }
   136  
   137  // SeekLT implements FragmentIterator.SeekLT.
   138  func (i *Iter) SeekLT(key []byte) *Span {
   139  	// NB: manually inlined sort.Search is ~5% faster.
   140  	//
   141  	// Define f(-1) == false and f(n) == true.
   142  	// Invariant: f(index-1) == false, f(upper) == true.
   143  	i.index = 0
   144  	upper := len(i.spans)
   145  	for i.index < upper {
   146  		h := int(uint(i.index+upper) >> 1) // avoid overflow when computing h
   147  		// i.index ≤ h < upper
   148  		if i.cmp(key, i.spans[h].Start) > 0 {
   149  			i.index = h + 1 // preserves f(i-1) == false
   150  		} else {
   151  			upper = h // preserves f(j) == true
   152  		}
   153  	}
   154  	// i.index == upper, f(i.index-1) == false, and f(upper) (= f(i.index)) ==
   155  	// true => answer is i.index.
   156  
   157  	// Since keys are strictly increasing, if i.index > 0 then i.index-1 will be
   158  	// the largest whose key is < the key sought.
   159  	i.index--
   160  	if i.index < 0 {
   161  		return nil
   162  	}
   163  	return &i.spans[i.index]
   164  }
   165  
   166  // First implements FragmentIterator.First.
   167  func (i *Iter) First() *Span {
   168  	if len(i.spans) == 0 {
   169  		return nil
   170  	}
   171  	i.index = 0
   172  	return &i.spans[i.index]
   173  }
   174  
   175  // Last implements FragmentIterator.Last.
   176  func (i *Iter) Last() *Span {
   177  	if len(i.spans) == 0 {
   178  		return nil
   179  	}
   180  	i.index = len(i.spans) - 1
   181  	return &i.spans[i.index]
   182  }
   183  
   184  // Next implements FragmentIterator.Next.
   185  func (i *Iter) Next() *Span {
   186  	if i.index >= len(i.spans) {
   187  		return nil
   188  	}
   189  	i.index++
   190  	if i.index >= len(i.spans) {
   191  		return nil
   192  	}
   193  	return &i.spans[i.index]
   194  }
   195  
   196  // Prev implements FragmentIterator.Prev.
   197  func (i *Iter) Prev() *Span {
   198  	if i.index < 0 {
   199  		return nil
   200  	}
   201  	i.index--
   202  	if i.index < 0 {
   203  		return nil
   204  	}
   205  	return &i.spans[i.index]
   206  }
   207  
   208  // Error implements FragmentIterator.Error.
   209  func (i *Iter) Error() error {
   210  	return nil
   211  }
   212  
   213  // Close implements FragmentIterator.Close.
   214  func (i *Iter) Close() error {
   215  	return nil
   216  }
   217  
   218  func (i *Iter) String() string {
   219  	return "fragmented-spans"
   220  }