github.com/cockroachdb/pebble@v0.0.0-20231214172447-ab4952c5f87b/get_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 pebble
     6  
     7  import (
     8  	"context"
     9  	"fmt"
    10  
    11  	"github.com/cockroachdb/pebble/internal/base"
    12  	"github.com/cockroachdb/pebble/internal/keyspan"
    13  	"github.com/cockroachdb/pebble/internal/manifest"
    14  	"github.com/cockroachdb/pebble/sstable"
    15  )
    16  
    17  // getIter is an internal iterator used to perform gets. It iterates through
    18  // the values for a particular key, level by level. It is not a general purpose
    19  // internalIterator, but specialized for Get operations so that it loads data
    20  // lazily.
    21  type getIter struct {
    22  	logger       Logger
    23  	comparer     *Comparer
    24  	newIters     tableNewIters
    25  	snapshot     uint64
    26  	key          []byte
    27  	iter         internalIterator
    28  	rangeDelIter keyspan.FragmentIterator
    29  	tombstone    *keyspan.Span
    30  	levelIter    levelIter
    31  	level        int
    32  	batch        *Batch
    33  	mem          flushableList
    34  	l0           []manifest.LevelSlice
    35  	version      *version
    36  	iterKey      *InternalKey
    37  	iterValue    base.LazyValue
    38  	err          error
    39  }
    40  
    41  // TODO(sumeer): CockroachDB code doesn't use getIter, but, for completeness,
    42  // make this implement InternalIteratorWithStats.
    43  
    44  // getIter implements the base.InternalIterator interface.
    45  var _ base.InternalIterator = (*getIter)(nil)
    46  
    47  func (g *getIter) String() string {
    48  	return fmt.Sprintf("len(l0)=%d, len(mem)=%d, level=%d", len(g.l0), len(g.mem), g.level)
    49  }
    50  
    51  func (g *getIter) SeekGE(key []byte, flags base.SeekGEFlags) (*InternalKey, base.LazyValue) {
    52  	panic("pebble: SeekGE unimplemented")
    53  }
    54  
    55  func (g *getIter) SeekPrefixGE(
    56  	prefix, key []byte, flags base.SeekGEFlags,
    57  ) (*base.InternalKey, base.LazyValue) {
    58  	panic("pebble: SeekPrefixGE unimplemented")
    59  }
    60  
    61  func (g *getIter) SeekLT(key []byte, flags base.SeekLTFlags) (*InternalKey, base.LazyValue) {
    62  	panic("pebble: SeekLT unimplemented")
    63  }
    64  
    65  func (g *getIter) First() (*InternalKey, base.LazyValue) {
    66  	return g.Next()
    67  }
    68  
    69  func (g *getIter) Last() (*InternalKey, base.LazyValue) {
    70  	panic("pebble: Last unimplemented")
    71  }
    72  
    73  func (g *getIter) Next() (*InternalKey, base.LazyValue) {
    74  	if g.iter != nil {
    75  		g.iterKey, g.iterValue = g.iter.Next()
    76  	}
    77  
    78  	for {
    79  		if g.iter != nil {
    80  			// We have to check rangeDelIter on each iteration because a single
    81  			// user-key can be spread across multiple tables in a level. A range
    82  			// tombstone will appear in the table corresponding to its start
    83  			// key. Every call to levelIter.Next() potentially switches to a new
    84  			// table and thus reinitializes rangeDelIter.
    85  			if g.rangeDelIter != nil {
    86  				g.tombstone = keyspan.Get(g.comparer.Compare, g.rangeDelIter, g.key)
    87  				if g.err = g.rangeDelIter.Close(); g.err != nil {
    88  					return nil, base.LazyValue{}
    89  				}
    90  				g.rangeDelIter = nil
    91  			}
    92  
    93  			if g.iterKey != nil {
    94  				key := g.iterKey
    95  				if g.tombstone != nil && g.tombstone.CoversAt(g.snapshot, key.SeqNum()) {
    96  					// We have a range tombstone covering this key. Rather than return a
    97  					// point or range deletion here, we return false and close our
    98  					// internal iterator which will make Valid() return false,
    99  					// effectively stopping iteration.
   100  					g.err = g.iter.Close()
   101  					g.iter = nil
   102  					return nil, base.LazyValue{}
   103  				}
   104  				if g.comparer.Equal(g.key, key.UserKey) {
   105  					if !key.Visible(g.snapshot, base.InternalKeySeqNumMax) {
   106  						g.iterKey, g.iterValue = g.iter.Next()
   107  						continue
   108  					}
   109  					return g.iterKey, g.iterValue
   110  				}
   111  			}
   112  			// We've advanced the iterator passed the desired key. Move on to the
   113  			// next memtable / level.
   114  			g.err = g.iter.Close()
   115  			g.iter = nil
   116  			if g.err != nil {
   117  				return nil, base.LazyValue{}
   118  			}
   119  		}
   120  
   121  		// Create an iterator from the batch.
   122  		if g.batch != nil {
   123  			if g.batch.index == nil {
   124  				g.err = ErrNotIndexed
   125  				g.iterKey, g.iterValue = nil, base.LazyValue{}
   126  				return nil, base.LazyValue{}
   127  			}
   128  			g.iter = g.batch.newInternalIter(nil)
   129  			g.rangeDelIter = g.batch.newRangeDelIter(
   130  				nil,
   131  				// Get always reads the entirety of the batch's history, so no
   132  				// batch keys should be filtered.
   133  				base.InternalKeySeqNumMax,
   134  			)
   135  			g.iterKey, g.iterValue = g.iter.SeekGE(g.key, base.SeekGEFlagsNone)
   136  			g.batch = nil
   137  			continue
   138  		}
   139  
   140  		// If we have a tombstone from a previous level it is guaranteed to delete
   141  		// keys in lower levels.
   142  		if g.tombstone != nil && g.tombstone.VisibleAt(g.snapshot) {
   143  			return nil, base.LazyValue{}
   144  		}
   145  
   146  		// Create iterators from memtables from newest to oldest.
   147  		if n := len(g.mem); n > 0 {
   148  			m := g.mem[n-1]
   149  			g.iter = m.newIter(nil)
   150  			g.rangeDelIter = m.newRangeDelIter(nil)
   151  			g.mem = g.mem[:n-1]
   152  			g.iterKey, g.iterValue = g.iter.SeekGE(g.key, base.SeekGEFlagsNone)
   153  			continue
   154  		}
   155  
   156  		if g.level == 0 {
   157  			// Create iterators from L0 from newest to oldest.
   158  			if n := len(g.l0); n > 0 {
   159  				files := g.l0[n-1].Iter()
   160  				g.l0 = g.l0[:n-1]
   161  				iterOpts := IterOptions{
   162  					// TODO(sumeer): replace with a parameter provided by the caller.
   163  					CategoryAndQoS: sstable.CategoryAndQoS{
   164  						Category: "pebble-get",
   165  						QoSLevel: sstable.LatencySensitiveQoSLevel,
   166  					},
   167  					logger:                        g.logger,
   168  					snapshotForHideObsoletePoints: g.snapshot}
   169  				g.levelIter.init(context.Background(), iterOpts, g.comparer, g.newIters,
   170  					files, manifest.L0Sublevel(n), internalIterOpts{})
   171  				g.levelIter.initRangeDel(&g.rangeDelIter)
   172  				bc := levelIterBoundaryContext{}
   173  				g.levelIter.initBoundaryContext(&bc)
   174  				g.iter = &g.levelIter
   175  
   176  				// Compute the key prefix for bloom filtering if split function is
   177  				// specified, or use the user key as default.
   178  				prefix := g.key
   179  				if g.comparer.Split != nil {
   180  					prefix = g.key[:g.comparer.Split(g.key)]
   181  				}
   182  				g.iterKey, g.iterValue = g.iter.SeekPrefixGE(prefix, g.key, base.SeekGEFlagsNone)
   183  				if bc.isSyntheticIterBoundsKey || bc.isIgnorableBoundaryKey {
   184  					g.iterKey = nil
   185  					g.iterValue = base.LazyValue{}
   186  				}
   187  				continue
   188  			}
   189  			g.level++
   190  		}
   191  
   192  		if g.level >= numLevels {
   193  			return nil, base.LazyValue{}
   194  		}
   195  		if g.version.Levels[g.level].Empty() {
   196  			g.level++
   197  			continue
   198  		}
   199  
   200  		iterOpts := IterOptions{
   201  			// TODO(sumeer): replace with a parameter provided by the caller.
   202  			CategoryAndQoS: sstable.CategoryAndQoS{
   203  				Category: "pebble-get",
   204  				QoSLevel: sstable.LatencySensitiveQoSLevel,
   205  			}, logger: g.logger, snapshotForHideObsoletePoints: g.snapshot}
   206  		g.levelIter.init(context.Background(), iterOpts, g.comparer, g.newIters,
   207  			g.version.Levels[g.level].Iter(), manifest.Level(g.level), internalIterOpts{})
   208  		g.levelIter.initRangeDel(&g.rangeDelIter)
   209  		bc := levelIterBoundaryContext{}
   210  		g.levelIter.initBoundaryContext(&bc)
   211  		g.level++
   212  		g.iter = &g.levelIter
   213  
   214  		// Compute the key prefix for bloom filtering if split function is
   215  		// specified, or use the user key as default.
   216  		prefix := g.key
   217  		if g.comparer.Split != nil {
   218  			prefix = g.key[:g.comparer.Split(g.key)]
   219  		}
   220  		g.iterKey, g.iterValue = g.iter.SeekPrefixGE(prefix, g.key, base.SeekGEFlagsNone)
   221  		if bc.isSyntheticIterBoundsKey || bc.isIgnorableBoundaryKey {
   222  			g.iterKey = nil
   223  			g.iterValue = base.LazyValue{}
   224  		}
   225  	}
   226  }
   227  
   228  func (g *getIter) Prev() (*InternalKey, base.LazyValue) {
   229  	panic("pebble: Prev unimplemented")
   230  }
   231  
   232  func (g *getIter) NextPrefix([]byte) (*InternalKey, base.LazyValue) {
   233  	panic("pebble: NextPrefix unimplemented")
   234  }
   235  
   236  func (g *getIter) Valid() bool {
   237  	return g.iterKey != nil && g.err == nil
   238  }
   239  
   240  func (g *getIter) Error() error {
   241  	return g.err
   242  }
   243  
   244  func (g *getIter) Close() error {
   245  	if g.iter != nil {
   246  		if err := g.iter.Close(); err != nil && g.err == nil {
   247  			g.err = err
   248  		}
   249  		g.iter = nil
   250  	}
   251  	return g.err
   252  }
   253  
   254  func (g *getIter) SetBounds(lower, upper []byte) {
   255  	panic("pebble: SetBounds unimplemented")
   256  }
   257  
   258  func (g *getIter) SetContext(_ context.Context) {}