github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/pkg/graveler/committed/iterator.go (about)

     1  package committed
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  
     8  	"github.com/treeverse/lakefs/pkg/graveler"
     9  )
    10  
    11  type iterator struct {
    12  	ctx         context.Context
    13  	started     bool
    14  	manager     RangeManager
    15  	rangesIt    ValueIterator
    16  	rng         *Range                 // Decoded value at which rangeIt point
    17  	it          graveler.ValueIterator // nil at start of range
    18  	err         error
    19  	namespace   Namespace
    20  	beforeRange bool
    21  }
    22  
    23  func NewIterator(ctx context.Context, manager RangeManager, namespace Namespace, rangesIt ValueIterator) Iterator {
    24  	return &iterator{
    25  		ctx:       ctx,
    26  		manager:   manager,
    27  		namespace: namespace,
    28  		rangesIt:  rangesIt,
    29  	}
    30  }
    31  
    32  // loadIt loads rvi.it to start iterating over a new range.  It returns false and sets rvi.err
    33  // if it fails to open the new range.
    34  func (rvi *iterator) loadIt() bool {
    35  	it, err := rvi.manager.NewRangeIterator(rvi.ctx, rvi.namespace, rvi.rng.ID)
    36  	if err != nil {
    37  		rvi.err = fmt.Errorf("open range %s: %w", rvi.rng.ID, err)
    38  		return false
    39  	}
    40  	rvi.it = NewUnmarshalIterator(it)
    41  	return true
    42  }
    43  
    44  func (rvi *iterator) NextRange() bool {
    45  	if rvi.it != nil {
    46  		rvi.it.Close()
    47  	}
    48  	rvi.it = nil
    49  	rvi.rng = nil
    50  
    51  	var rngRecord *Record
    52  	for rngRecord == nil { // Skip this and any consecutive finished ranges.
    53  		if !rvi.rangesIt.Next() {
    54  			return false
    55  		}
    56  		rngRecord = rvi.rangesIt.Value()
    57  	}
    58  
    59  	gv, err := UnmarshalValue(rngRecord.Value)
    60  	if err != nil {
    61  		rvi.err = fmt.Errorf("unmarshal value for %s: %w", string(rngRecord.Key), err)
    62  		return false
    63  	}
    64  
    65  	rng, err := UnmarshalRange(gv.Data)
    66  	if err != nil {
    67  		rvi.err = fmt.Errorf("unmarshal %s: %w", string(rngRecord.Key), err)
    68  		return false
    69  	}
    70  
    71  	rng.ID = ID(gv.Identity)
    72  	rvi.rng = &rng
    73  
    74  	return true
    75  }
    76  
    77  func (rvi *iterator) Next() bool {
    78  	if rvi.err != nil {
    79  		return false
    80  	}
    81  	if rvi.beforeRange {
    82  		rvi.beforeRange = false
    83  		return true
    84  	}
    85  	if !rvi.started {
    86  		rvi.started = true
    87  		return rvi.NextRange()
    88  	}
    89  	if rvi.it != nil {
    90  		if rvi.it.Next() {
    91  			return true
    92  		}
    93  		// At end of range
    94  		return rvi.NextRange()
    95  	}
    96  	// Start iterating inside the range of rvi.RangesIt
    97  	if rvi.rng == nil {
    98  		return rvi.NextRange()
    99  	}
   100  
   101  	if !rvi.loadIt() {
   102  		return false
   103  	}
   104  
   105  	if rvi.it.Next() {
   106  		return true
   107  	}
   108  	// Already at end of empty range
   109  	return rvi.NextRange()
   110  }
   111  
   112  func (rvi *iterator) Value() (*graveler.ValueRecord, *Range) {
   113  	if rvi.it == nil {
   114  		return nil, rvi.rng // start new range
   115  	}
   116  	return rvi.it.Value(), rvi.rng
   117  }
   118  
   119  func (rvi *iterator) Err() error {
   120  	if rvi.err != nil {
   121  		return rvi.err
   122  	}
   123  	if rvi.it == nil {
   124  		return nil
   125  	}
   126  	return rvi.it.Err()
   127  }
   128  
   129  func (rvi *iterator) Close() {
   130  	rvi.rangesIt.Close()
   131  	if rvi.it == nil {
   132  		return
   133  	}
   134  	rvi.it.Close()
   135  }
   136  
   137  func (rvi *iterator) loadRange(key graveler.Key) bool {
   138  	rvi.rangesIt.SeekGE(Key(key))
   139  	if err := rvi.rangesIt.Err(); err != nil {
   140  		rvi.err = err
   141  		return false
   142  	}
   143  	if !rvi.NextRange() {
   144  		return false // Reached end
   145  	}
   146  	rvi.started = true // "Started": rangesIt is valid.
   147  	if bytes.Compare(key, rvi.rng.MinKey) <= 0 {
   148  		// the given key is before the next range
   149  		rvi.beforeRange = true
   150  		return false
   151  	}
   152  	return rvi.loadIt()
   153  }
   154  
   155  func (rvi *iterator) SeekGE(key graveler.Key) {
   156  	if rvi.rng == nil || rvi.it == nil || bytes.Compare(key, rvi.rng.MinKey) < 0 || bytes.Compare(key, rvi.rng.MaxKey) > 0 {
   157  		// no current range, or new key outside current range boundaries
   158  		if !rvi.loadRange(key) {
   159  			return
   160  		}
   161  	}
   162  	rvi.it.SeekGE(key)
   163  	// Ready to call Next to see values.
   164  	rvi.err = rvi.it.Err()
   165  }
   166  
   167  type emptyIterator struct{}
   168  
   169  func NewEmptyIterator() Iterator {
   170  	return &emptyIterator{}
   171  }
   172  
   173  func (e *emptyIterator) Next() bool {
   174  	return false
   175  }
   176  
   177  func (e *emptyIterator) NextRange() bool {
   178  	return false
   179  }
   180  
   181  func (e *emptyIterator) Value() (*graveler.ValueRecord, *Range) {
   182  	return nil, nil
   183  }
   184  
   185  func (e *emptyIterator) SeekGE(graveler.Key) {}
   186  
   187  func (e *emptyIterator) Err() error {
   188  	return nil
   189  }
   190  
   191  func (e *emptyIterator) Close() {}