github.com/KinWaiYuen/client-go/v2@v2.5.4/internal/unionstore/memdb_iterator.go (about)

     1  // Copyright 2021 TiKV Authors
     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  // NOTE: The code in this file is based on code from the
    16  // TiDB project, licensed under the Apache License v 2.0
    17  //
    18  // https://github.com/pingcap/tidb/tree/cc5e161ac06827589c4966674597c137cc9e809c/store/tikv/unionstore/memdb_iterator.go
    19  //
    20  
    21  // Copyright 2020 PingCAP, Inc.
    22  //
    23  // Licensed under the Apache License, Version 2.0 (the "License");
    24  // you may not use this file except in compliance with the License.
    25  // You may obtain a copy of the License at
    26  //
    27  //     http://www.apache.org/licenses/LICENSE-2.0
    28  //
    29  // Unless required by applicable law or agreed to in writing, software
    30  // distributed under the License is distributed on an "AS IS" BASIS,
    31  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    32  // See the License for the specific language governing permissions and
    33  // limitations under the License.
    34  
    35  package unionstore
    36  
    37  import (
    38  	"bytes"
    39  
    40  	"github.com/KinWaiYuen/client-go/v2/kv"
    41  )
    42  
    43  // MemdbIterator is an Iterator with KeyFlags related functions.
    44  type MemdbIterator struct {
    45  	db           *MemDB
    46  	curr         memdbNodeAddr
    47  	start        []byte
    48  	end          []byte
    49  	reverse      bool
    50  	includeFlags bool
    51  }
    52  
    53  // Iter creates an Iterator positioned on the first entry that k <= entry's key.
    54  // If such entry is not found, it returns an invalid Iterator with no error.
    55  // It yields only keys that < upperBound. If upperBound is nil, it means the upperBound is unbounded.
    56  // The Iterator must be Closed after use.
    57  func (db *MemDB) Iter(k []byte, upperBound []byte) (Iterator, error) {
    58  	i := &MemdbIterator{
    59  		db:    db,
    60  		start: k,
    61  		end:   upperBound,
    62  	}
    63  	i.init()
    64  	return i, nil
    65  }
    66  
    67  // IterReverse creates a reversed Iterator positioned on the first entry which key is less than k.
    68  // The returned iterator will iterate from greater key to smaller key.
    69  // If k is nil, the returned iterator will be positioned at the last key.
    70  // TODO: Add lower bound limit
    71  func (db *MemDB) IterReverse(k []byte) (Iterator, error) {
    72  	i := &MemdbIterator{
    73  		db:      db,
    74  		end:     k,
    75  		reverse: true,
    76  	}
    77  	i.init()
    78  	return i, nil
    79  }
    80  
    81  // IterWithFlags returns a MemdbIterator.
    82  func (db *MemDB) IterWithFlags(k []byte, upperBound []byte) *MemdbIterator {
    83  	i := &MemdbIterator{
    84  		db:           db,
    85  		start:        k,
    86  		end:          upperBound,
    87  		includeFlags: true,
    88  	}
    89  	i.init()
    90  	return i
    91  }
    92  
    93  // IterReverseWithFlags returns a reversed MemdbIterator.
    94  func (db *MemDB) IterReverseWithFlags(k []byte) *MemdbIterator {
    95  	i := &MemdbIterator{
    96  		db:           db,
    97  		end:          k,
    98  		reverse:      true,
    99  		includeFlags: true,
   100  	}
   101  	i.init()
   102  	return i
   103  }
   104  
   105  func (i *MemdbIterator) init() {
   106  	if i.reverse {
   107  		if len(i.end) == 0 {
   108  			i.seekToLast()
   109  		} else {
   110  			i.seek(i.end)
   111  		}
   112  	} else {
   113  		if len(i.start) == 0 {
   114  			i.seekToFirst()
   115  		} else {
   116  			i.seek(i.start)
   117  		}
   118  	}
   119  
   120  	if i.isFlagsOnly() && !i.includeFlags {
   121  		err := i.Next()
   122  		_ = err // memdbIterator will never fail
   123  	}
   124  }
   125  
   126  // Valid returns true if the current iterator is valid.
   127  func (i *MemdbIterator) Valid() bool {
   128  	if !i.reverse {
   129  		return !i.curr.isNull() && (i.end == nil || bytes.Compare(i.Key(), i.end) < 0)
   130  	}
   131  	return !i.curr.isNull()
   132  }
   133  
   134  // Flags returns flags belong to current iterator.
   135  func (i *MemdbIterator) Flags() kv.KeyFlags {
   136  	return i.curr.getKeyFlags()
   137  }
   138  
   139  // UpdateFlags updates and apply with flagsOp.
   140  func (i *MemdbIterator) UpdateFlags(ops ...kv.FlagsOp) {
   141  	origin := i.curr.getKeyFlags()
   142  	n := kv.ApplyFlagsOps(origin, ops...)
   143  	i.curr.setKeyFlags(n)
   144  }
   145  
   146  // HasValue returns false if it is flags only.
   147  func (i *MemdbIterator) HasValue() bool {
   148  	return !i.isFlagsOnly()
   149  }
   150  
   151  // Key returns current key.
   152  func (i *MemdbIterator) Key() []byte {
   153  	return i.curr.getKey()
   154  }
   155  
   156  // Handle returns MemKeyHandle with the current position.
   157  func (i *MemdbIterator) Handle() MemKeyHandle {
   158  	return MemKeyHandle{
   159  		idx: uint16(i.curr.addr.idx),
   160  		off: i.curr.addr.off,
   161  	}
   162  }
   163  
   164  // Value returns the value.
   165  func (i *MemdbIterator) Value() []byte {
   166  	return i.db.vlog.getValue(i.curr.vptr)
   167  }
   168  
   169  // Next goes the next position.
   170  func (i *MemdbIterator) Next() error {
   171  	for {
   172  		if i.reverse {
   173  			i.curr = i.db.predecessor(i.curr)
   174  		} else {
   175  			i.curr = i.db.successor(i.curr)
   176  		}
   177  
   178  		// We need to skip persistent flags only nodes.
   179  		if i.includeFlags || !i.isFlagsOnly() {
   180  			break
   181  		}
   182  	}
   183  	return nil
   184  }
   185  
   186  // Close closes the current iterator.
   187  func (i *MemdbIterator) Close() {}
   188  
   189  func (i *MemdbIterator) seekToFirst() {
   190  	y := memdbNodeAddr{nil, nullAddr}
   191  	x := i.db.getNode(i.db.root)
   192  
   193  	for !x.isNull() {
   194  		y = x
   195  		x = y.getLeft(i.db)
   196  	}
   197  
   198  	i.curr = y
   199  }
   200  
   201  func (i *MemdbIterator) seekToLast() {
   202  	y := memdbNodeAddr{nil, nullAddr}
   203  	x := i.db.getNode(i.db.root)
   204  
   205  	for !x.isNull() {
   206  		y = x
   207  		x = y.getRight(i.db)
   208  	}
   209  
   210  	i.curr = y
   211  }
   212  
   213  func (i *MemdbIterator) seek(key []byte) {
   214  	y := memdbNodeAddr{nil, nullAddr}
   215  	x := i.db.getNode(i.db.root)
   216  
   217  	var cmp int
   218  	for !x.isNull() {
   219  		y = x
   220  		cmp = bytes.Compare(key, y.getKey())
   221  
   222  		if cmp < 0 {
   223  			x = y.getLeft(i.db)
   224  		} else if cmp > 0 {
   225  			x = y.getRight(i.db)
   226  		} else {
   227  			break
   228  		}
   229  	}
   230  
   231  	if !i.reverse {
   232  		if cmp > 0 {
   233  			// Move to next
   234  			i.curr = i.db.successor(y)
   235  			return
   236  		}
   237  		i.curr = y
   238  		return
   239  	}
   240  
   241  	if cmp <= 0 && !y.isNull() {
   242  		i.curr = i.db.predecessor(y)
   243  		return
   244  	}
   245  	i.curr = y
   246  }
   247  
   248  func (i *MemdbIterator) isFlagsOnly() bool {
   249  	return !i.curr.isNull() && i.curr.vptr.isNull()
   250  }