github.com/cockroachdb/pebble@v1.1.2/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 }