github.com/cockroachdb/pebble@v0.0.0-20231214172447-ab4952c5f87b/internal/batchskl/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 batchskl
    19  
    20  import "github.com/cockroachdb/pebble/internal/base"
    21  
    22  type splice struct {
    23  	prev uint32
    24  	next uint32
    25  }
    26  
    27  // Iterator is an iterator over the skiplist object. Use Skiplist.NewIter
    28  // to construct an iterator. The current state of the iterator can be cloned
    29  // by simply value copying the struct.
    30  type Iterator struct {
    31  	list  *Skiplist
    32  	nd    uint32
    33  	key   base.InternalKey
    34  	lower []byte
    35  	upper []byte
    36  }
    37  
    38  // Close resets the iterator.
    39  func (it *Iterator) Close() error {
    40  	it.list = nil
    41  	it.nd = 0
    42  	return nil
    43  }
    44  
    45  // SeekGE moves the iterator to the first entry whose key is greater than or
    46  // equal to the given key. Returns true if the iterator is pointing at a valid
    47  // entry and false otherwise. Note that SeekGE only checks the upper bound. It
    48  // is up to the caller to ensure that key is greater than or equal to the lower
    49  // bound.
    50  func (it *Iterator) SeekGE(key []byte, flags base.SeekGEFlags) *base.InternalKey {
    51  	if flags.TrySeekUsingNext() {
    52  		if it.nd == it.list.tail {
    53  			// Iterator is done.
    54  			return nil
    55  		}
    56  		less := it.list.cmp(it.key.UserKey, key) < 0
    57  		// Arbitrary constant. By measuring the seek cost as a function of the
    58  		// number of elements in the skip list, and fitting to a model, we
    59  		// could adjust the number of nexts based on the current size of the
    60  		// skip list.
    61  		const numNexts = 5
    62  		for i := 0; less && i < numNexts; i++ {
    63  			k := it.Next()
    64  			if k == nil {
    65  				// Iterator is done.
    66  				return nil
    67  			}
    68  			less = it.list.cmp(k.UserKey, key) < 0
    69  		}
    70  		if !less {
    71  			return &it.key
    72  		}
    73  	}
    74  
    75  	_, it.nd = it.seekForBaseSplice(key, it.list.abbreviatedKey(key))
    76  	if it.nd == it.list.tail {
    77  		return nil
    78  	}
    79  	nodeKey := it.list.getKey(it.nd)
    80  	if it.upper != nil && it.list.cmp(it.upper, nodeKey.UserKey) <= 0 {
    81  		it.nd = it.list.tail
    82  		return nil
    83  	}
    84  	it.key = nodeKey
    85  	return &it.key
    86  }
    87  
    88  // SeekLT moves the iterator to the last entry whose key is less the given
    89  // key. Returns true if the iterator is pointing at a valid entry and false
    90  // otherwise. Note that SeekLT only checks the lower bound. It is up to the
    91  // caller to ensure that key is less than the upper bound.
    92  func (it *Iterator) SeekLT(key []byte) *base.InternalKey {
    93  	it.nd, _ = it.seekForBaseSplice(key, it.list.abbreviatedKey(key))
    94  	if it.nd == it.list.head {
    95  		return nil
    96  	}
    97  	nodeKey := it.list.getKey(it.nd)
    98  	if it.lower != nil && it.list.cmp(it.lower, nodeKey.UserKey) > 0 {
    99  		it.nd = it.list.head
   100  		return nil
   101  	}
   102  	it.key = nodeKey
   103  	return &it.key
   104  }
   105  
   106  // First seeks position at the first entry in list. Final state of iterator is
   107  // Valid() iff list is not empty. Note that First only checks the upper
   108  // bound. It is up to the caller to ensure that key is greater than or equal to
   109  // the lower bound (e.g. via a call to SeekGE(lower)).
   110  func (it *Iterator) First() *base.InternalKey {
   111  	it.nd = it.list.getNext(it.list.head, 0)
   112  	if it.nd == it.list.tail {
   113  		return nil
   114  	}
   115  	nodeKey := it.list.getKey(it.nd)
   116  	if it.upper != nil && it.list.cmp(it.upper, nodeKey.UserKey) <= 0 {
   117  		it.nd = it.list.tail
   118  		return nil
   119  	}
   120  	it.key = nodeKey
   121  	return &it.key
   122  }
   123  
   124  // Last seeks position at the last entry in list. Final state of iterator is
   125  // Valid() iff list is not empty. Note that Last only checks the lower
   126  // bound. It is up to the caller to ensure that key is less than the upper
   127  // bound (e.g. via a call to SeekLT(upper)).
   128  func (it *Iterator) Last() *base.InternalKey {
   129  	it.nd = it.list.getPrev(it.list.tail, 0)
   130  	if it.nd == it.list.head {
   131  		return nil
   132  	}
   133  	nodeKey := it.list.getKey(it.nd)
   134  	if it.lower != nil && it.list.cmp(it.lower, nodeKey.UserKey) > 0 {
   135  		it.nd = it.list.head
   136  		return nil
   137  	}
   138  	it.key = nodeKey
   139  	return &it.key
   140  }
   141  
   142  // Next advances to the next position. If there are no following nodes, then
   143  // Valid() will be false after this call.
   144  func (it *Iterator) Next() *base.InternalKey {
   145  	it.nd = it.list.getNext(it.nd, 0)
   146  	if it.nd == it.list.tail {
   147  		return nil
   148  	}
   149  	nodeKey := it.list.getKey(it.nd)
   150  	if it.upper != nil && it.list.cmp(it.upper, nodeKey.UserKey) <= 0 {
   151  		it.nd = it.list.tail
   152  		return nil
   153  	}
   154  	it.key = nodeKey
   155  	return &it.key
   156  }
   157  
   158  // Prev moves to the previous position. If there are no previous nodes, then
   159  // Valid() will be false after this call.
   160  func (it *Iterator) Prev() *base.InternalKey {
   161  	it.nd = it.list.getPrev(it.nd, 0)
   162  	if it.nd == it.list.head {
   163  		return nil
   164  	}
   165  	nodeKey := it.list.getKey(it.nd)
   166  	if it.lower != nil && it.list.cmp(it.lower, nodeKey.UserKey) > 0 {
   167  		it.nd = it.list.head
   168  		return nil
   169  	}
   170  	it.key = nodeKey
   171  	return &it.key
   172  }
   173  
   174  // Key returns the key at the current position.
   175  func (it *Iterator) Key() *base.InternalKey {
   176  	return &it.key
   177  }
   178  
   179  // KeyInfo returns the offset of the start of the record, the start of the key,
   180  // and the end of the key.
   181  func (it *Iterator) KeyInfo() (offset, keyStart, keyEnd uint32) {
   182  	n := it.list.node(it.nd)
   183  	return n.offset, n.keyStart, n.keyEnd
   184  }
   185  
   186  // Head true iff the iterator is positioned at the sentinel head node.
   187  func (it *Iterator) Head() bool {
   188  	return it.nd == it.list.head
   189  }
   190  
   191  // Tail true iff the iterator is positioned at the sentinel tail node.
   192  func (it *Iterator) Tail() bool {
   193  	return it.nd == it.list.tail
   194  }
   195  
   196  // Valid returns nil iff the iterator is positioned at a valid node.
   197  func (it *Iterator) Valid() bool {
   198  	return it.list != nil && it.nd != it.list.head && it.nd != it.list.tail
   199  }
   200  
   201  func (it *Iterator) String() string {
   202  	return "batch"
   203  }
   204  
   205  // SetBounds sets the lower and upper bounds for the iterator. Note that the
   206  // result of Next and Prev will be undefined until the iterator has been
   207  // repositioned with SeekGE, SeekLT, First, or Last.
   208  func (it *Iterator) SetBounds(lower, upper []byte) {
   209  	it.lower = lower
   210  	it.upper = upper
   211  }
   212  
   213  func (it *Iterator) seekForBaseSplice(key []byte, abbreviatedKey uint64) (prev, next uint32) {
   214  	prev = it.list.head
   215  	for level := it.list.height - 1; ; level-- {
   216  		prev, next = it.list.findSpliceForLevel(key, abbreviatedKey, level, prev)
   217  		if level == 0 {
   218  			break
   219  		}
   220  	}
   221  
   222  	return
   223  }