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

     1  /*
     2   * Copyright 2017 Dgraph Labs, Inc. and Contributors
     3   * Modifications copyright (C) 2017 Andy Kimball and Contributors
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  package arenaskl
    19  
    20  import (
    21  	"sync"
    22  
    23  	"github.com/cockroachdb/pebble/internal/base"
    24  )
    25  
    26  type splice struct {
    27  	prev *node
    28  	next *node
    29  }
    30  
    31  func (s *splice) init(prev, next *node) {
    32  	s.prev = prev
    33  	s.next = next
    34  }
    35  
    36  // Iterator is an iterator over the skiplist object. Use Skiplist.NewIter
    37  // to construct an iterator. The current state of the iterator can be cloned by
    38  // simply value copying the struct. All iterator methods are thread-safe.
    39  type Iterator struct {
    40  	list  *Skiplist
    41  	nd    *node
    42  	key   base.InternalKey
    43  	lower []byte
    44  	upper []byte
    45  }
    46  
    47  // Iterator implements the base.InternalIterator interface.
    48  var _ base.InternalIterator = (*Iterator)(nil)
    49  
    50  var iterPool = sync.Pool{
    51  	New: func() interface{} {
    52  		return &Iterator{}
    53  	},
    54  }
    55  
    56  // Close resets the iterator.
    57  func (it *Iterator) Close() error {
    58  	it.list = nil
    59  	it.nd = nil
    60  	it.lower = nil
    61  	it.upper = nil
    62  	iterPool.Put(it)
    63  	return nil
    64  }
    65  
    66  func (it *Iterator) String() string {
    67  	return "memtable"
    68  }
    69  
    70  // Error returns any accumulated error.
    71  func (it *Iterator) Error() error {
    72  	return nil
    73  }
    74  
    75  // SeekGE moves the iterator to the first entry whose key is greater than or
    76  // equal to the given key. Returns the key and value if the iterator is
    77  // pointing at a valid entry, and (nil, nil) otherwise. Note that SeekGE only
    78  // checks the upper bound. It is up to the caller to ensure that key is greater
    79  // than or equal to the lower bound.
    80  func (it *Iterator) SeekGE(key []byte, flags base.SeekGEFlags) (*base.InternalKey, base.LazyValue) {
    81  	if flags.TrySeekUsingNext() {
    82  		if it.nd == it.list.tail {
    83  			// Iterator is done.
    84  			return nil, base.LazyValue{}
    85  		}
    86  		less := it.list.cmp(it.key.UserKey, key) < 0
    87  		// Arbitrary constant. By measuring the seek cost as a function of the
    88  		// number of elements in the skip list, and fitting to a model, we
    89  		// could adjust the number of nexts based on the current size of the
    90  		// skip list.
    91  		const numNexts = 5
    92  		for i := 0; less && i < numNexts; i++ {
    93  			k, _ := it.Next()
    94  			if k == nil {
    95  				// Iterator is done.
    96  				return nil, base.LazyValue{}
    97  			}
    98  			less = it.list.cmp(it.key.UserKey, key) < 0
    99  		}
   100  		if !less {
   101  			return &it.key, base.MakeInPlaceValue(it.value())
   102  		}
   103  	}
   104  	_, it.nd, _ = it.seekForBaseSplice(key)
   105  	if it.nd == it.list.tail {
   106  		return nil, base.LazyValue{}
   107  	}
   108  	it.decodeKey()
   109  	if it.upper != nil && it.list.cmp(it.upper, it.key.UserKey) <= 0 {
   110  		it.nd = it.list.tail
   111  		return nil, base.LazyValue{}
   112  	}
   113  	return &it.key, base.MakeInPlaceValue(it.value())
   114  }
   115  
   116  // SeekPrefixGE moves the iterator to the first entry whose key is greater than
   117  // or equal to the given key. This method is equivalent to SeekGE and is
   118  // provided so that an arenaskl.Iterator implements the
   119  // internal/base.InternalIterator interface.
   120  func (it *Iterator) SeekPrefixGE(
   121  	prefix, key []byte, flags base.SeekGEFlags,
   122  ) (*base.InternalKey, base.LazyValue) {
   123  	return it.SeekGE(key, flags)
   124  }
   125  
   126  // SeekLT moves the iterator to the last entry whose key is less than the given
   127  // key. Returns the key and value if the iterator is pointing at a valid entry,
   128  // and (nil, nil) otherwise. Note that SeekLT only checks the lower bound. It
   129  // is up to the caller to ensure that key is less than the upper bound.
   130  func (it *Iterator) SeekLT(key []byte, flags base.SeekLTFlags) (*base.InternalKey, base.LazyValue) {
   131  	// NB: the top-level Iterator has already adjusted key based on
   132  	// the upper-bound.
   133  	it.nd, _, _ = it.seekForBaseSplice(key)
   134  	if it.nd == it.list.head {
   135  		return nil, base.LazyValue{}
   136  	}
   137  	it.decodeKey()
   138  	if it.lower != nil && it.list.cmp(it.lower, it.key.UserKey) > 0 {
   139  		it.nd = it.list.head
   140  		return nil, base.LazyValue{}
   141  	}
   142  	return &it.key, base.MakeInPlaceValue(it.value())
   143  }
   144  
   145  // First seeks position at the first entry in list. Returns the key and value
   146  // if the iterator is pointing at a valid entry, and (nil, nil) otherwise. Note
   147  // that First only checks the upper bound. It is up to the caller to ensure
   148  // that key is greater than or equal to the lower bound (e.g. via a call to SeekGE(lower)).
   149  func (it *Iterator) First() (*base.InternalKey, base.LazyValue) {
   150  	it.nd = it.list.getNext(it.list.head, 0)
   151  	if it.nd == it.list.tail {
   152  		return nil, base.LazyValue{}
   153  	}
   154  	it.decodeKey()
   155  	if it.upper != nil && it.list.cmp(it.upper, it.key.UserKey) <= 0 {
   156  		it.nd = it.list.tail
   157  		return nil, base.LazyValue{}
   158  	}
   159  	return &it.key, base.MakeInPlaceValue(it.value())
   160  }
   161  
   162  // Last seeks position at the last entry in list. Returns the key and value if
   163  // the iterator is pointing at a valid entry, and (nil, nil) otherwise. Note
   164  // that Last only checks the lower bound. It is up to the caller to ensure that
   165  // key is less than the upper bound (e.g. via a call to SeekLT(upper)).
   166  func (it *Iterator) Last() (*base.InternalKey, base.LazyValue) {
   167  	it.nd = it.list.getPrev(it.list.tail, 0)
   168  	if it.nd == it.list.head {
   169  		return nil, base.LazyValue{}
   170  	}
   171  	it.decodeKey()
   172  	if it.lower != nil && it.list.cmp(it.lower, it.key.UserKey) > 0 {
   173  		it.nd = it.list.head
   174  		return nil, base.LazyValue{}
   175  	}
   176  	return &it.key, base.MakeInPlaceValue(it.value())
   177  }
   178  
   179  // Next advances to the next position. Returns the key and value if the
   180  // iterator is pointing at a valid entry, and (nil, nil) otherwise.
   181  // Note: flushIterator.Next mirrors the implementation of Iterator.Next
   182  // due to performance. Keep the two in sync.
   183  func (it *Iterator) Next() (*base.InternalKey, base.LazyValue) {
   184  	it.nd = it.list.getNext(it.nd, 0)
   185  	if it.nd == it.list.tail {
   186  		return nil, base.LazyValue{}
   187  	}
   188  	it.decodeKey()
   189  	if it.upper != nil && it.list.cmp(it.upper, it.key.UserKey) <= 0 {
   190  		it.nd = it.list.tail
   191  		return nil, base.LazyValue{}
   192  	}
   193  	return &it.key, base.MakeInPlaceValue(it.value())
   194  }
   195  
   196  // NextPrefix advances to the next position with a new prefix. Returns the key
   197  // and value if the iterator is pointing at a valid entry, and (nil, nil)
   198  // otherwise.
   199  func (it *Iterator) NextPrefix(succKey []byte) (*base.InternalKey, base.LazyValue) {
   200  	return it.SeekGE(succKey, base.SeekGEFlagsNone.EnableTrySeekUsingNext())
   201  }
   202  
   203  // Prev moves to the previous position. Returns the key and value if the
   204  // iterator is pointing at a valid entry, and (nil, nil) otherwise.
   205  func (it *Iterator) Prev() (*base.InternalKey, base.LazyValue) {
   206  	it.nd = it.list.getPrev(it.nd, 0)
   207  	if it.nd == it.list.head {
   208  		return nil, base.LazyValue{}
   209  	}
   210  	it.decodeKey()
   211  	if it.lower != nil && it.list.cmp(it.lower, it.key.UserKey) > 0 {
   212  		it.nd = it.list.head
   213  		return nil, base.LazyValue{}
   214  	}
   215  	return &it.key, base.MakeInPlaceValue(it.value())
   216  }
   217  
   218  // value returns the value at the current position.
   219  func (it *Iterator) value() []byte {
   220  	return it.nd.getValue(it.list.arena)
   221  }
   222  
   223  // Head true iff the iterator is positioned at the sentinel head node.
   224  func (it *Iterator) Head() bool {
   225  	return it.nd == it.list.head
   226  }
   227  
   228  // Tail true iff the iterator is positioned at the sentinel tail node.
   229  func (it *Iterator) Tail() bool {
   230  	return it.nd == it.list.tail
   231  }
   232  
   233  // SetBounds sets the lower and upper bounds for the iterator. Note that the
   234  // result of Next and Prev will be undefined until the iterator has been
   235  // repositioned with SeekGE, SeekPrefixGE, SeekLT, First, or Last.
   236  func (it *Iterator) SetBounds(lower, upper []byte) {
   237  	it.lower = lower
   238  	it.upper = upper
   239  }
   240  
   241  func (it *Iterator) decodeKey() {
   242  	it.key.UserKey = it.list.arena.getBytes(it.nd.keyOffset, it.nd.keySize)
   243  	it.key.Trailer = it.nd.keyTrailer
   244  }
   245  
   246  func (it *Iterator) seekForBaseSplice(key []byte) (prev, next *node, found bool) {
   247  	ikey := base.MakeSearchKey(key)
   248  	level := int(it.list.Height() - 1)
   249  
   250  	prev = it.list.head
   251  	for {
   252  		prev, next, found = it.list.findSpliceForLevel(ikey, level, prev)
   253  
   254  		if found {
   255  			if level != 0 {
   256  				// next is pointing at the target node, but we need to find previous on
   257  				// the bottom level.
   258  				prev = it.list.getPrev(next, 0)
   259  			}
   260  			break
   261  		}
   262  
   263  		if level == 0 {
   264  			break
   265  		}
   266  
   267  		level--
   268  	}
   269  
   270  	return
   271  }