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