github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/allegrosql/memdb_iterator.go (about)

     1  // Copyright 2020 WHTCORPS INC, Inc.
     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  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package ekv
    15  
    16  import "bytes"
    17  
    18  type memdbIterator struct {
    19  	EDB          *memdb
    20  	curr         memdbNodeAddr
    21  	start        Key
    22  	end          Key
    23  	reverse      bool
    24  	includeFlags bool
    25  }
    26  
    27  func (EDB *memdb) Iter(k Key, upperBound Key) (Iterator, error) {
    28  	i := &memdbIterator{
    29  		EDB:   EDB,
    30  		start: k,
    31  		end:   upperBound,
    32  	}
    33  	i.init()
    34  	return i, nil
    35  }
    36  
    37  func (EDB *memdb) IterReverse(k Key) (Iterator, error) {
    38  	i := &memdbIterator{
    39  		EDB:     EDB,
    40  		end:     k,
    41  		reverse: true,
    42  	}
    43  	i.init()
    44  	return i, nil
    45  }
    46  
    47  func (EDB *memdb) IterWithFlags(k Key, upperBound Key) MemBufferIterator {
    48  	i := &memdbIterator{
    49  		EDB:          EDB,
    50  		start:        k,
    51  		end:          upperBound,
    52  		includeFlags: true,
    53  	}
    54  	i.init()
    55  	return i
    56  }
    57  
    58  func (EDB *memdb) IterReverseWithFlags(k Key) MemBufferIterator {
    59  	i := &memdbIterator{
    60  		EDB:          EDB,
    61  		end:          k,
    62  		reverse:      true,
    63  		includeFlags: true,
    64  	}
    65  	i.init()
    66  	return i
    67  }
    68  
    69  func (i *memdbIterator) init() {
    70  	if i.reverse {
    71  		if len(i.end) == 0 {
    72  			i.seekToLast()
    73  		} else {
    74  			i.seek(i.end)
    75  		}
    76  	} else {
    77  		if len(i.start) == 0 {
    78  			i.seekToFirst()
    79  		} else {
    80  			i.seek(i.start)
    81  		}
    82  	}
    83  
    84  	if i.isFlagsOnly() && !i.includeFlags {
    85  		err := i.Next()
    86  		_ = err // memdbIterator will never fail
    87  	}
    88  }
    89  
    90  func (i *memdbIterator) Valid() bool {
    91  	if !i.reverse {
    92  		return !i.curr.isNull() && (i.end == nil || bytes.Compare(i.Key(), i.end) < 0)
    93  	}
    94  	return !i.curr.isNull()
    95  }
    96  
    97  func (i *memdbIterator) Flags() KeyFlags {
    98  	return i.curr.getKeyFlags()
    99  }
   100  
   101  func (i *memdbIterator) HasValue() bool {
   102  	return !i.isFlagsOnly()
   103  }
   104  
   105  func (i *memdbIterator) Key() Key {
   106  	return i.curr.getKey()
   107  }
   108  
   109  func (i *memdbIterator) Value() []byte {
   110  	return i.EDB.vlog.getValue(i.curr.vptr)
   111  }
   112  
   113  func (i *memdbIterator) Next() error {
   114  	for {
   115  		if i.reverse {
   116  			i.curr = i.EDB.predecessor(i.curr)
   117  		} else {
   118  			i.curr = i.EDB.successor(i.curr)
   119  		}
   120  
   121  		// We need to skip persistent flags only nodes.
   122  		if i.includeFlags || !i.isFlagsOnly() {
   123  			break
   124  		}
   125  	}
   126  	return nil
   127  }
   128  
   129  func (i *memdbIterator) Close() {}
   130  
   131  func (i *memdbIterator) seekToFirst() {
   132  	y := memdbNodeAddr{nil, nullAddr}
   133  	x := i.EDB.getNode(i.EDB.root)
   134  
   135  	for !x.isNull() {
   136  		y = x
   137  		x = y.getLeft(i.EDB)
   138  	}
   139  
   140  	i.curr = y
   141  }
   142  
   143  func (i *memdbIterator) seekToLast() {
   144  	y := memdbNodeAddr{nil, nullAddr}
   145  	x := i.EDB.getNode(i.EDB.root)
   146  
   147  	for !x.isNull() {
   148  		y = x
   149  		x = y.getRight(i.EDB)
   150  	}
   151  
   152  	i.curr = y
   153  }
   154  
   155  func (i *memdbIterator) seek(key Key) {
   156  	y := memdbNodeAddr{nil, nullAddr}
   157  	x := i.EDB.getNode(i.EDB.root)
   158  
   159  	var cmp int
   160  	for !x.isNull() {
   161  		y = x
   162  		cmp = bytes.Compare(key, y.getKey())
   163  
   164  		if cmp < 0 {
   165  			x = y.getLeft(i.EDB)
   166  		} else if cmp > 0 {
   167  			x = y.getRight(i.EDB)
   168  		} else {
   169  			break
   170  		}
   171  	}
   172  
   173  	if !i.reverse {
   174  		if cmp > 0 {
   175  			// Move to next
   176  			i.curr = i.EDB.successor(y)
   177  			return
   178  		}
   179  		i.curr = y
   180  		return
   181  	}
   182  
   183  	if cmp <= 0 && !y.isNull() {
   184  		i.curr = i.EDB.predecessor(y)
   185  		return
   186  	}
   187  	i.curr = y
   188  }
   189  
   190  func (i *memdbIterator) isFlagsOnly() bool {
   191  	return !i.curr.isNull() && i.curr.vptr.isNull()
   192  }