github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/bitpage/page_iterator.go (about)

     1  // Copyright 2021 The Bitalosdb author(hustxrb@163.com) and other contributors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package bitpage
    16  
    17  import (
    18  	"sync"
    19  
    20  	"github.com/cockroachdb/errors"
    21  	"github.com/zuoyebang/bitalosdb/internal/base"
    22  	"github.com/zuoyebang/bitalosdb/internal/utils"
    23  )
    24  
    25  type iterPos int8
    26  
    27  const (
    28  	iterPosCurForward iterPos = 0
    29  	iterPosNext       iterPos = 1
    30  	iterPosPrev       iterPos = -1
    31  	iterPosCurReverse iterPos = -2
    32  )
    33  
    34  const maxKeyBufCacheSize = 4 << 10
    35  
    36  type pageIterAlloc struct {
    37  	dbi                 PageIterator
    38  	key                 internalKey
    39  	keyBuf              []byte
    40  	prefixOrFullSeekKey []byte
    41  	merging             mergingIter
    42  	mlevels             [3]mergingIterLevel
    43  }
    44  
    45  var pageIterAllocPool = sync.Pool{
    46  	New: func() interface{} {
    47  		return &pageIterAlloc{}
    48  	},
    49  }
    50  
    51  type PageIterator struct {
    52  	opts                iterOptions
    53  	cmp                 base.Compare
    54  	equal               base.Equal
    55  	iter                internalIterator
    56  	readState           *readState
    57  	readStateCloser     func()
    58  	err                 error
    59  	key                 *internalKey
    60  	keyBuf              []byte
    61  	value               []byte
    62  	iterKey             *internalKey
    63  	iterValue           []byte
    64  	alloc               *pageIterAlloc
    65  	prefixOrFullSeekKey []byte
    66  	iterValidityState   IterValidityState
    67  	pos                 iterPos
    68  	lastPositioningOp   lastPositioningOpKind
    69  }
    70  
    71  type lastPositioningOpKind int8
    72  
    73  const (
    74  	unknownLastPositionOp lastPositioningOpKind = iota
    75  	seekGELastPositioningOp
    76  	seekLTLastPositioningOp
    77  )
    78  
    79  type IterValidityState int8
    80  
    81  const (
    82  	IterExhausted IterValidityState = iota
    83  	IterValid
    84  )
    85  
    86  func (i *PageIterator) getKV() (*base.InternalKey, []byte) {
    87  	if i.iterValidityState == IterValid {
    88  		return i.key, i.value
    89  	}
    90  
    91  	return nil, nil
    92  }
    93  
    94  func (i *PageIterator) findNextEntry() {
    95  	i.iterValidityState = IterExhausted
    96  	i.pos = iterPosCurForward
    97  
    98  	for i.iterKey != nil {
    99  		key := *i.iterKey
   100  
   101  		switch key.Kind() {
   102  		case internalKeyKindSet:
   103  			i.keyBuf = append(i.keyBuf[:0], key.UserKey...)
   104  			*i.key = base.MakeInternalKey2(i.keyBuf, key.Trailer)
   105  			i.value = i.iterValue
   106  			i.iterValidityState = IterValid
   107  			return
   108  
   109  		case internalKeyKindDelete, internalKeyKindPrefixDelete:
   110  			i.keyBuf = append(i.keyBuf[:0], key.UserKey...)
   111  			*i.key = base.MakeInternalKey2(i.keyBuf, key.Trailer)
   112  			i.value = nil
   113  			i.iterValidityState = IterValid
   114  			return
   115  
   116  		default:
   117  			i.err = errors.Errorf("bitpage: invalid internal key kind %s", key.Kind())
   118  			i.iterValidityState = IterExhausted
   119  			return
   120  		}
   121  	}
   122  }
   123  
   124  func (i *PageIterator) nextUserKey() {
   125  	if i.iterKey == nil {
   126  		return
   127  	}
   128  
   129  	if i.iterValidityState != IterValid {
   130  		i.keyBuf = append(i.keyBuf[:0], i.iterKey.UserKey...)
   131  		*i.key = base.MakeInternalKey2(i.keyBuf, i.iterKey.Trailer)
   132  	}
   133  
   134  	for {
   135  		i.iterKey, i.iterValue = i.iter.Next()
   136  		if i.iterKey == nil || !i.equal(i.key.UserKey, i.iterKey.UserKey) {
   137  			break
   138  		}
   139  	}
   140  }
   141  
   142  func (i *PageIterator) findPrevEntry() {
   143  	i.iterValidityState = IterExhausted
   144  	i.pos = iterPosCurReverse
   145  
   146  	for i.iterKey != nil {
   147  		key := *i.iterKey
   148  
   149  		if i.iterValidityState == IterValid {
   150  			if !i.equal(key.UserKey, i.key.UserKey) {
   151  				i.pos = iterPosPrev
   152  				if i.err != nil {
   153  					i.iterValidityState = IterExhausted
   154  				}
   155  				return
   156  			}
   157  		}
   158  
   159  		switch key.Kind() {
   160  		case internalKeyKindSet:
   161  			i.keyBuf = append(i.keyBuf[:0], key.UserKey...)
   162  			*i.key = base.MakeInternalKey2(i.keyBuf, key.Trailer)
   163  			i.value = i.iterValue
   164  			i.iterValidityState = IterValid
   165  			i.iterKey, i.iterValue = i.iter.Prev()
   166  		case internalKeyKindDelete, internalKeyKindPrefixDelete:
   167  			i.keyBuf = append(i.keyBuf[:0], key.UserKey...)
   168  			*i.key = base.MakeInternalKey2(i.keyBuf, key.Trailer)
   169  			i.value = nil
   170  			i.iterValidityState = IterValid
   171  			i.iterKey, i.iterValue = i.iter.Prev()
   172  		default:
   173  			i.err = errors.Errorf("bitpage: invalid internal key kind %s", key.Kind())
   174  			i.iterValidityState = IterExhausted
   175  			return
   176  		}
   177  	}
   178  
   179  	if i.iterValidityState == IterValid {
   180  		i.pos = iterPosPrev
   181  		if i.err != nil {
   182  			i.iterValidityState = IterExhausted
   183  		}
   184  	}
   185  }
   186  
   187  func (i *PageIterator) prevUserKey() {
   188  	if i.iterKey == nil {
   189  		return
   190  	}
   191  	if i.iterValidityState != IterValid {
   192  		i.keyBuf = append(i.keyBuf[:0], i.iterKey.UserKey...)
   193  		*i.key = base.MakeInternalKey2(i.keyBuf, i.iterKey.Trailer)
   194  	}
   195  	for {
   196  		i.iterKey, i.iterValue = i.iter.Prev()
   197  		if i.iterKey == nil {
   198  			break
   199  		}
   200  		if !i.equal(i.key.UserKey, i.iterKey.UserKey) {
   201  			break
   202  		}
   203  	}
   204  }
   205  
   206  func (i *PageIterator) SeekGE(key []byte) (*internalKey, []byte) {
   207  	lastPositioningOp := i.lastPositioningOp
   208  
   209  	i.lastPositioningOp = unknownLastPositionOp
   210  	i.err = nil
   211  	if lowerBound := i.opts.GetLowerBound(); lowerBound != nil && i.cmp(key, lowerBound) < 0 {
   212  		key = lowerBound
   213  	} else if upperBound := i.opts.GetUpperBound(); upperBound != nil && i.cmp(key, upperBound) > 0 {
   214  		key = upperBound
   215  	}
   216  
   217  	if lastPositioningOp == seekGELastPositioningOp {
   218  		if i.cmp(i.prefixOrFullSeekKey, key) <= 0 {
   219  			if i.iterValidityState == IterExhausted || (i.iterValidityState == IterValid && i.cmp(key, i.key.UserKey) <= 0) {
   220  				return i.getKV()
   221  			}
   222  		}
   223  	}
   224  
   225  	i.iterKey, i.iterValue = i.iter.SeekGE(key)
   226  	i.findNextEntry()
   227  	if i.Error() == nil {
   228  		i.prefixOrFullSeekKey = append(i.prefixOrFullSeekKey[:0], key...)
   229  		i.lastPositioningOp = seekGELastPositioningOp
   230  	}
   231  	return i.getKV()
   232  }
   233  
   234  func (i *PageIterator) SeekPrefixGE(prefix, key []byte, trySeekUsingNext bool) (*internalKey, []byte) {
   235  	return nil, nil
   236  }
   237  
   238  func (i *PageIterator) SeekLT(key []byte) (*internalKey, []byte) {
   239  	lastPositioningOp := i.lastPositioningOp
   240  	i.lastPositioningOp = unknownLastPositionOp
   241  	i.err = nil
   242  	if upperBound := i.opts.GetUpperBound(); upperBound != nil && i.cmp(key, upperBound) > 0 {
   243  		key = upperBound
   244  	} else if lowerBound := i.opts.GetLowerBound(); lowerBound != nil && i.cmp(key, lowerBound) < 0 {
   245  		key = lowerBound
   246  	}
   247  
   248  	if lastPositioningOp == seekLTLastPositioningOp {
   249  		if i.cmp(key, i.prefixOrFullSeekKey) <= 0 {
   250  			if i.iterValidityState == IterExhausted || (i.iterValidityState == IterValid && i.cmp(i.key.UserKey, key) < 0) {
   251  				return i.getKV()
   252  			}
   253  		}
   254  	}
   255  
   256  	i.iterKey, i.iterValue = i.iter.SeekLT(key)
   257  	i.findPrevEntry()
   258  	if i.Error() == nil {
   259  		i.prefixOrFullSeekKey = append(i.prefixOrFullSeekKey[:0], key...)
   260  		i.lastPositioningOp = seekLTLastPositioningOp
   261  	}
   262  	return i.getKV()
   263  }
   264  
   265  func (i *PageIterator) First() (*internalKey, []byte) {
   266  	i.err = nil
   267  	i.lastPositioningOp = unknownLastPositionOp
   268  	if lowerBound := i.opts.GetLowerBound(); lowerBound != nil {
   269  		i.iterKey, i.iterValue = i.iter.SeekGE(lowerBound)
   270  	} else {
   271  		i.iterKey, i.iterValue = i.iter.First()
   272  	}
   273  	i.findNextEntry()
   274  	return i.getKV()
   275  }
   276  
   277  func (i *PageIterator) Last() (*internalKey, []byte) {
   278  	i.err = nil
   279  	i.lastPositioningOp = unknownLastPositionOp
   280  	if upperBound := i.opts.GetUpperBound(); upperBound != nil {
   281  		i.iterKey, i.iterValue = i.iter.SeekLT(upperBound)
   282  	} else {
   283  		i.iterKey, i.iterValue = i.iter.Last()
   284  	}
   285  	i.findPrevEntry()
   286  	return i.getKV()
   287  }
   288  
   289  func (i *PageIterator) Next() (*internalKey, []byte) {
   290  	if i.err != nil {
   291  		return i.getKV()
   292  	}
   293  	i.lastPositioningOp = unknownLastPositionOp
   294  	switch i.pos {
   295  	case iterPosCurForward:
   296  		i.nextUserKey()
   297  	case iterPosCurReverse:
   298  		if i.iterKey != nil {
   299  			i.err = errors.New("switching from reverse to forward but iter is not at prev")
   300  			i.iterValidityState = IterExhausted
   301  			break
   302  		}
   303  		if lowerBound := i.opts.GetLowerBound(); lowerBound != nil {
   304  			i.iterKey, i.iterValue = i.iter.SeekGE(lowerBound)
   305  		} else {
   306  			i.iterKey, i.iterValue = i.iter.First()
   307  		}
   308  	case iterPosPrev:
   309  		i.iterValidityState = IterExhausted
   310  		if i.iterKey == nil {
   311  			if lowerBound := i.opts.GetLowerBound(); lowerBound != nil {
   312  				i.iterKey, i.iterValue = i.iter.SeekGE(lowerBound)
   313  			} else {
   314  				i.iterKey, i.iterValue = i.iter.First()
   315  			}
   316  		} else {
   317  			i.nextUserKey()
   318  		}
   319  		i.nextUserKey()
   320  	}
   321  	i.findNextEntry()
   322  	return i.getKV()
   323  }
   324  
   325  func (i *PageIterator) Prev() (*internalKey, []byte) {
   326  	if i.err != nil {
   327  		return i.getKV()
   328  	}
   329  	i.lastPositioningOp = unknownLastPositionOp
   330  	switch i.pos {
   331  	case iterPosCurForward:
   332  	case iterPosCurReverse:
   333  		i.prevUserKey()
   334  	case iterPosPrev:
   335  	}
   336  	if i.pos == iterPosCurForward {
   337  		i.iterValidityState = IterExhausted
   338  		if i.iterKey == nil {
   339  			if upperBound := i.opts.GetUpperBound(); upperBound != nil {
   340  				i.iterKey, i.iterValue = i.iter.SeekLT(upperBound)
   341  			} else {
   342  				i.iterKey, i.iterValue = i.iter.Last()
   343  			}
   344  		} else {
   345  			i.prevUserKey()
   346  		}
   347  	}
   348  	i.findPrevEntry()
   349  	return i.getKV()
   350  }
   351  
   352  func (i *PageIterator) String() string {
   353  	return "PageIterator"
   354  }
   355  
   356  func (i *PageIterator) Error() error {
   357  	err := i.err
   358  	if i.iter != nil {
   359  		err = utils.FirstError(i.err, i.iter.Error())
   360  	}
   361  	return err
   362  }
   363  
   364  func (i *PageIterator) Close() error {
   365  	if i.iter != nil {
   366  		i.err = utils.FirstError(i.err, i.iter.Close())
   367  	}
   368  	err := i.err
   369  
   370  	if i.readStateCloser != nil {
   371  		i.readStateCloser()
   372  		i.readStateCloser = nil
   373  	}
   374  
   375  	if alloc := i.alloc; alloc != nil {
   376  		if cap(i.keyBuf) >= maxKeyBufCacheSize {
   377  			alloc.keyBuf = nil
   378  		} else {
   379  			alloc.keyBuf = i.keyBuf
   380  		}
   381  		if cap(i.prefixOrFullSeekKey) >= maxKeyBufCacheSize {
   382  			alloc.prefixOrFullSeekKey = nil
   383  		} else {
   384  			alloc.prefixOrFullSeekKey = i.prefixOrFullSeekKey
   385  		}
   386  		*i = PageIterator{}
   387  		pageIterAllocPool.Put(alloc)
   388  	}
   389  	return err
   390  }
   391  
   392  func (i *PageIterator) SetBounds(lower, upper []byte) {
   393  	i.lastPositioningOp = unknownLastPositionOp
   394  	i.iterKey = nil
   395  	i.iterValue = nil
   396  
   397  	switch i.pos {
   398  	case iterPosCurForward:
   399  		i.pos = iterPosCurForward
   400  	case iterPosCurReverse, iterPosPrev:
   401  		i.pos = iterPosCurReverse
   402  	}
   403  	i.iterValidityState = IterExhausted
   404  
   405  	i.opts.LowerBound = lower
   406  	i.opts.UpperBound = upper
   407  	i.iter.SetBounds(lower, upper)
   408  }