github.com/vescale/zgraph@v0.0.0-20230410094002-959c02d50f95/storage/memdb_iterator.go (about)

     1  // Copyright 2022 zGraph Authors. All rights reserved.
     2  //
     3  // Copyright 2020 PingCAP, Inc.
     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  package storage
    18  
    19  import (
    20  	"bytes"
    21  
    22  	"github.com/vescale/zgraph/storage/kv"
    23  )
    24  
    25  // MemDBIter is an Iterator with KeyFlags related functions.
    26  type MemDBIter struct {
    27  	db           *MemDB
    28  	curr         memdbNodeAddr
    29  	start        []byte
    30  	end          []byte
    31  	reverse      bool
    32  	includeFlags bool
    33  }
    34  
    35  // Iter creates an Iterator positioned on the first entry that k <= entry's key.
    36  // If such entry is not found, it returns an invalid Iterator with no error.
    37  // It yields only keys that < upperBound. If upperBound is nil, it means the upperBound is unbounded.
    38  // The Iterator must be Closed after use.
    39  func (db *MemDB) Iter(lowerBound, upperBound kv.Key) (kv.Iterator, error) {
    40  	i := &MemDBIter{
    41  		db:    db,
    42  		start: lowerBound,
    43  		end:   upperBound,
    44  	}
    45  	i.init()
    46  	return i, nil
    47  }
    48  
    49  // IterReverse creates a reversed Iterator positioned on the first entry which key is less than k.
    50  // The returned SnapshotIter will iterate from greater key to smaller key.
    51  // If k is nil, the returned SnapshotIter will be positioned at the last key.
    52  func (db *MemDB) IterReverse(lowerBound, upperBound kv.Key) (kv.Iterator, error) {
    53  	i := &MemDBIter{
    54  		db:      db,
    55  		start:   lowerBound,
    56  		end:     upperBound,
    57  		reverse: true,
    58  	}
    59  	i.init()
    60  	return i, nil
    61  }
    62  
    63  // IterWithFlags returns a MemDBIter.
    64  func (db *MemDB) IterWithFlags(lowerBound []byte, upperBound []byte) *MemDBIter {
    65  	i := &MemDBIter{
    66  		db:           db,
    67  		start:        lowerBound,
    68  		end:          upperBound,
    69  		includeFlags: true,
    70  	}
    71  	i.init()
    72  	return i
    73  }
    74  
    75  // IterReverseWithFlags returns a reversed MemDBIter.
    76  func (db *MemDB) IterReverseWithFlags(k []byte) *MemDBIter {
    77  	i := &MemDBIter{
    78  		db:           db,
    79  		end:          k,
    80  		reverse:      true,
    81  		includeFlags: true,
    82  	}
    83  	i.init()
    84  	return i
    85  }
    86  
    87  func (i *MemDBIter) init() {
    88  	if i.reverse {
    89  		if len(i.end) == 0 {
    90  			i.seekToLast()
    91  		} else {
    92  			i.seek(i.end)
    93  		}
    94  	} else {
    95  		if len(i.start) == 0 {
    96  			i.seekToFirst()
    97  		} else {
    98  			i.seek(i.start)
    99  		}
   100  	}
   101  
   102  	if i.isFlagsOnly() && !i.includeFlags {
   103  		err := i.Next()
   104  		_ = err // memdbIterator will never fail
   105  	}
   106  }
   107  
   108  // Valid returns true if the current SnapshotIter is valid.
   109  func (i *MemDBIter) Valid() bool {
   110  	if !i.reverse {
   111  		return !i.curr.isNull() && (i.end == nil || bytes.Compare(i.Key(), i.end) < 0)
   112  	}
   113  	return !i.curr.isNull()
   114  }
   115  
   116  // Flags returns flags belong to current SnapshotIter.
   117  func (i *MemDBIter) Flags() kv.KeyFlags {
   118  	return i.curr.getKeyFlags()
   119  }
   120  
   121  // UpdateFlags updates and apply with flagsOp.
   122  func (i *MemDBIter) UpdateFlags(ops ...kv.FlagsOp) {
   123  	origin := i.curr.getKeyFlags()
   124  	n := kv.ApplyFlagsOps(origin, ops...)
   125  	i.curr.setKeyFlags(n)
   126  }
   127  
   128  // HasValue returns false if it is flags only.
   129  func (i *MemDBIter) HasValue() bool {
   130  	return !i.isFlagsOnly()
   131  }
   132  
   133  // Key returns current key.
   134  func (i *MemDBIter) Key() kv.Key {
   135  	return i.curr.getKey()
   136  }
   137  
   138  // Handle returns MemKeyHandle with the current position.
   139  func (i *MemDBIter) Handle() MemKeyHandle {
   140  	return MemKeyHandle{
   141  		idx: uint16(i.curr.addr.idx),
   142  		off: i.curr.addr.off,
   143  	}
   144  }
   145  
   146  // Value returns the value.
   147  func (i *MemDBIter) Value() []byte {
   148  	return i.db.vlog.getValue(i.curr.vptr)
   149  }
   150  
   151  // Next goes the next position.
   152  func (i *MemDBIter) Next() error {
   153  	for {
   154  		if i.reverse {
   155  			i.curr = i.db.predecessor(i.curr)
   156  		} else {
   157  			i.curr = i.db.successor(i.curr)
   158  		}
   159  
   160  		// We need to skip persistent flags only nodes.
   161  		if i.includeFlags || !i.isFlagsOnly() {
   162  			break
   163  		}
   164  	}
   165  	return nil
   166  }
   167  
   168  // Close closes the current SnapshotIter.
   169  func (i *MemDBIter) Close() {}
   170  
   171  func (i *MemDBIter) seekToFirst() {
   172  	y := memdbNodeAddr{nil, nullAddr}
   173  	x := i.db.getNode(i.db.root)
   174  
   175  	for !x.isNull() {
   176  		y = x
   177  		x = y.getLeft(i.db)
   178  	}
   179  
   180  	i.curr = y
   181  }
   182  
   183  func (i *MemDBIter) seekToLast() {
   184  	y := memdbNodeAddr{nil, nullAddr}
   185  	x := i.db.getNode(i.db.root)
   186  
   187  	for !x.isNull() {
   188  		y = x
   189  		x = y.getRight(i.db)
   190  	}
   191  
   192  	i.curr = y
   193  }
   194  
   195  func (i *MemDBIter) seek(key []byte) {
   196  	y := memdbNodeAddr{nil, nullAddr}
   197  	x := i.db.getNode(i.db.root)
   198  
   199  	var cmp int
   200  	for !x.isNull() {
   201  		y = x
   202  		cmp = bytes.Compare(key, y.getKey())
   203  
   204  		if cmp < 0 {
   205  			x = y.getLeft(i.db)
   206  		} else if cmp > 0 {
   207  			x = y.getRight(i.db)
   208  		} else {
   209  			break
   210  		}
   211  	}
   212  
   213  	if !i.reverse {
   214  		if cmp > 0 {
   215  			// Move to next
   216  			i.curr = i.db.successor(y)
   217  			return
   218  		}
   219  		i.curr = y
   220  		return
   221  	}
   222  
   223  	if cmp <= 0 && !y.isNull() {
   224  		i.curr = i.db.predecessor(y)
   225  		return
   226  	}
   227  	i.curr = y
   228  }
   229  
   230  func (i *MemDBIter) isFlagsOnly() bool {
   231  	return !i.curr.isNull() && i.curr.vptr.isNull()
   232  }