github.com/zuoyebang/bitalostable@v1.0.1-0.20240229032404-e3b99a834294/internal/keyspan/seek.go (about) 1 // Copyright 2018 The LevelDB-Go and Pebble Authors. All rights reserved. Use 2 // of this source code is governed by a BSD-style license that can be found in 3 // the LICENSE file. 4 5 package keyspan 6 7 import "github.com/zuoyebang/bitalostable/internal/base" 8 9 // SeekGE seeks to the span that contains the target key or the first span past 10 // the target key. 11 func SeekGE(cmp base.Compare, iter FragmentIterator, key []byte) *Span { 12 // NB: We use SeekLT in order to land on the proper span for a search 13 // key that resides in the middle of a span. Consider the scenario: 14 // 15 // a---e 16 // e---i 17 // 18 // The spans are indexed by their start keys `a` and `e`. If the 19 // search key is `c` we want to land on the span [a,e). If we were to 20 // use SeekGE then the search key `c` would land on the span [e,i) and 21 // we'd have to backtrack. The one complexity here is what happens for the 22 // search key `e`. In that case SeekLT will land us on the span [a,e) 23 // and we'll have to move forward. 24 iterSpan := iter.SeekLT(key) 25 26 // Invariant: key > iterSpan.Start 27 28 if iterSpan == nil || cmp(key, iterSpan.End) >= 0 { 29 // The current span lies entirely before the search key, or the iterator 30 // is exhausted. Advance the iterator to the next span which is 31 // guaranteed to lie at or past the search key. 32 iterSpan = iter.Next() 33 } 34 return iterSpan 35 } 36 37 // SeekLE seeks to the span that contains or is before the target key. 38 func SeekLE(cmp base.Compare, iter FragmentIterator, key []byte) *Span { 39 // NB: We use SeekLT in order to land on the proper span for a search 40 // key that resides in the middle of a span. Consider the scenario: 41 // 42 // a---e 43 // e---i 44 // 45 // The spans are indexed by their start keys `a` and `e`. If the 46 // search key is `c` we want to land on the span [a,e). If we were to 47 // use SeekGE then the search key `c` would land on the span [e,i) and 48 // we'd have to backtrack. The one complexity here is what happens for the 49 // search key `e`. In that case SeekLT will land us on the span [a,e) 50 // and we'll have to move forward. 51 iterSpan := iter.SeekLT(key) 52 53 if iterSpan == nil { 54 // Advance the iterator once to see if the next span has a start key 55 // equal to key. 56 iterSpan = iter.Next() 57 if iterSpan == nil || cmp(key, iterSpan.Start) < 0 { 58 // The iterator is exhausted or we've hit the next span. 59 return nil 60 } 61 } else { 62 // Invariant: key > iterSpan.Start 63 if cmp(key, iterSpan.End) >= 0 { 64 // The current span lies entirely before the search key. Check to see if 65 // the next span contains the search key. If it doesn't, we'll backup 66 // and return to our earlier candidate. 67 iterSpan = iter.Next() 68 if iterSpan == nil || cmp(key, iterSpan.Start) < 0 { 69 // The next span is past our search key or there is no next span. Go 70 // back. 71 iterSpan = iter.Prev() 72 } 73 } 74 } 75 return iterSpan 76 }