LCOV - code coverage report
Current view: top level - pebble/internal/keyspan - iter.go (source / functions) Hit Total Coverage
Test: 2024-01-16 08:16Z 27d566eb - tests only.lcov Lines: 94 97 96.9 %
Date: 2024-01-16 08:16:46 Functions: 0 0 -

          Line data    Source code
       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             : //
      21             : // If any positioning method fails to find a span, the iterator is left
      22             : // positioned at an exhausted position in the direction of iteration. For
      23             : // example, a caller than finds SeekGE(k)=nil may call Prev to move the iterator
      24             : // to the last span.
      25             : type FragmentIterator interface {
      26             :         // SeekGE moves the iterator to the first span covering a key greater than
      27             :         // or equal to the given key. This is equivalent to seeking to the first
      28             :         // span with an end key greater than the given key.
      29             :         SeekGE(key []byte) *Span
      30             : 
      31             :         // SeekLT moves the iterator to the last span covering a key less than the
      32             :         // given key. This is equivalent to seeking to the last span with a start
      33             :         // key less than the given key.
      34             :         SeekLT(key []byte) *Span
      35             : 
      36             :         // First moves the iterator to the first span.
      37             :         First() *Span
      38             : 
      39             :         // Last moves the iterator to the last span.
      40             :         Last() *Span
      41             : 
      42             :         // Next moves the iterator to the next span.
      43             :         //
      44             :         // It is valid to call Next when the iterator is positioned before the first
      45             :         // key/value pair due to either a prior call to SeekLT or Prev which
      46             :         // returned an invalid span. It is not allowed to call Next when the
      47             :         // previous call to SeekGE, SeekPrefixGE or Next returned an invalid span.
      48             :         Next() *Span
      49             : 
      50             :         // Prev moves the iterator to the previous span.
      51             :         //
      52             :         // It is valid to call Prev when the iterator is positioned after the last
      53             :         // key/value pair due to either a prior call to SeekGE or Next which
      54             :         // returned an invalid span. It is not allowed to call Prev when the
      55             :         // previous call to SeekLT or Prev returned an invalid span.
      56             :         Prev() *Span
      57             : 
      58             :         // Error returns any accumulated error.
      59             :         //
      60             :         // TODO(jackson): Lift errors into return values on the positioning methods.
      61             :         Error() error
      62             : 
      63             :         // Close closes the iterator and returns any accumulated error. Exhausting
      64             :         // the iterator is not considered to be an error. It is valid to call Close
      65             :         // multiple times. Other methods should not be called after the iterator has
      66             :         // been closed.
      67             :         Close() error
      68             : 
      69             :         // WrapChildren wraps any child iterators using the given function. The
      70             :         // function can call WrapChildren to recursively wrap an entire iterator
      71             :         // stack. Used only for debug logging.
      72             :         WrapChildren(wrap WrapFn)
      73             : }
      74             : 
      75             : // TableNewSpanIter creates a new iterator for range key spans for the given
      76             : // file.
      77             : type TableNewSpanIter func(file *manifest.FileMetadata, iterOptions SpanIterOptions) (FragmentIterator, error)
      78             : 
      79             : // SpanIterOptions is a subset of IterOptions that are necessary to instantiate
      80             : // per-sstable span iterators.
      81             : type SpanIterOptions struct {
      82             :         // RangeKeyFilters can be used to avoid scanning tables and blocks in tables
      83             :         // when iterating over range keys.
      84             :         RangeKeyFilters []base.BlockPropertyFilter
      85             : }
      86             : 
      87             : // Iter is an iterator over a set of fragmented spans.
      88             : type Iter struct {
      89             :         cmp   base.Compare
      90             :         spans []Span
      91             :         index int
      92             : }
      93             : 
      94             : // Iter implements the FragmentIterator interface.
      95             : var _ FragmentIterator = (*Iter)(nil)
      96             : 
      97             : // NewIter returns a new iterator over a set of fragmented spans.
      98           1 : func NewIter(cmp base.Compare, spans []Span) *Iter {
      99           1 :         i := &Iter{}
     100           1 :         i.Init(cmp, spans)
     101           1 :         return i
     102           1 : }
     103             : 
     104             : // Count returns the number of spans contained by Iter.
     105           1 : func (i *Iter) Count() int {
     106           1 :         return len(i.spans)
     107           1 : }
     108             : 
     109             : // Init initializes an Iter with the provided spans.
     110           1 : func (i *Iter) Init(cmp base.Compare, spans []Span) {
     111           1 :         *i = Iter{
     112           1 :                 cmp:   cmp,
     113           1 :                 spans: spans,
     114           1 :                 index: -1,
     115           1 :         }
     116           1 : }
     117             : 
     118             : // SeekGE implements FragmentIterator.SeekGE.
     119           1 : func (i *Iter) SeekGE(key []byte) *Span {
     120           1 :         // NB: manually inlined sort.Search is ~5% faster.
     121           1 :         //
     122           1 :         // Define f(j) = false iff the span i.spans[j] is strictly before `key`
     123           1 :         // (equivalently, i.spans[j].End ≤ key.)
     124           1 :         //
     125           1 :         // Define f(-1) == false and f(n) == true.
     126           1 :         // Invariant: f(index-1) == false, f(upper) == true.
     127           1 :         i.index = 0
     128           1 :         upper := len(i.spans)
     129           1 :         for i.index < upper {
     130           1 :                 h := int(uint(i.index+upper) >> 1) // avoid overflow when computing h
     131           1 :                 // i.index ≤ h < upper
     132           1 :                 if i.cmp(key, i.spans[h].End) >= 0 {
     133           1 :                         i.index = h + 1 // preserves f(i-1) == false
     134           1 :                 } else {
     135           1 :                         upper = h // preserves f(j) == true
     136           1 :                 }
     137             :         }
     138             : 
     139             :         // i.index == upper, f(i.index-1) == false, and f(upper) (= f(i.index)) ==
     140             :         // true => answer is i.index.
     141           1 :         if i.index >= len(i.spans) {
     142           1 :                 return nil
     143           1 :         }
     144           1 :         return &i.spans[i.index]
     145             : }
     146             : 
     147             : // SeekLT implements FragmentIterator.SeekLT.
     148           1 : func (i *Iter) SeekLT(key []byte) *Span {
     149           1 :         // NB: manually inlined sort.Search is ~5% faster.
     150           1 :         //
     151           1 :         // Define f(-1) == false and f(n) == true.
     152           1 :         // Invariant: f(index-1) == false, f(upper) == true.
     153           1 :         i.index = 0
     154           1 :         upper := len(i.spans)
     155           1 :         for i.index < upper {
     156           1 :                 h := int(uint(i.index+upper) >> 1) // avoid overflow when computing h
     157           1 :                 // i.index ≤ h < upper
     158           1 :                 if i.cmp(key, i.spans[h].Start) > 0 {
     159           1 :                         i.index = h + 1 // preserves f(i-1) == false
     160           1 :                 } else {
     161           1 :                         upper = h // preserves f(j) == true
     162           1 :                 }
     163             :         }
     164             :         // i.index == upper, f(i.index-1) == false, and f(upper) (= f(i.index)) ==
     165             :         // true => answer is i.index.
     166             : 
     167             :         // Since keys are strictly increasing, if i.index > 0 then i.index-1 will be
     168             :         // the largest whose key is < the key sought.
     169           1 :         i.index--
     170           1 :         if i.index < 0 {
     171           1 :                 return nil
     172           1 :         }
     173           1 :         return &i.spans[i.index]
     174             : }
     175             : 
     176             : // First implements FragmentIterator.First.
     177           1 : func (i *Iter) First() *Span {
     178           1 :         if len(i.spans) == 0 {
     179           1 :                 return nil
     180           1 :         }
     181           1 :         i.index = 0
     182           1 :         return &i.spans[i.index]
     183             : }
     184             : 
     185             : // Last implements FragmentIterator.Last.
     186           1 : func (i *Iter) Last() *Span {
     187           1 :         if len(i.spans) == 0 {
     188           1 :                 return nil
     189           1 :         }
     190           1 :         i.index = len(i.spans) - 1
     191           1 :         return &i.spans[i.index]
     192             : }
     193             : 
     194             : // Next implements FragmentIterator.Next.
     195           1 : func (i *Iter) Next() *Span {
     196           1 :         if i.index >= len(i.spans) {
     197           1 :                 return nil
     198           1 :         }
     199           1 :         i.index++
     200           1 :         if i.index >= len(i.spans) {
     201           1 :                 return nil
     202           1 :         }
     203           1 :         return &i.spans[i.index]
     204             : }
     205             : 
     206             : // Prev implements FragmentIterator.Prev.
     207           1 : func (i *Iter) Prev() *Span {
     208           1 :         if i.index < 0 {
     209           1 :                 return nil
     210           1 :         }
     211           1 :         i.index--
     212           1 :         if i.index < 0 {
     213           1 :                 return nil
     214           1 :         }
     215           1 :         return &i.spans[i.index]
     216             : }
     217             : 
     218             : // Error implements FragmentIterator.Error.
     219           1 : func (i *Iter) Error() error {
     220           1 :         return nil
     221           1 : }
     222             : 
     223             : // Close implements FragmentIterator.Close.
     224           1 : func (i *Iter) Close() error {
     225           1 :         return nil
     226           1 : }
     227             : 
     228           0 : func (i *Iter) String() string {
     229           0 :         return "fragmented-spans"
     230           0 : }
     231             : 
     232             : // WrapChildren implements FragmentIterator.
     233           1 : func (i *Iter) WrapChildren(wrap WrapFn) {}

Generated by: LCOV version 1.14