github.com/pingcap/badger@v1.5.1-0.20230103063557-828f39b09b6d/y/iterator.go (about)

     1  /*
     2   * Copyright 2017 Dgraph Labs, Inc. and Contributors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package y
    18  
    19  import (
    20  	"encoding/binary"
    21  )
    22  
    23  // ValueStruct represents the value info that can be associated with a key, but also the internal
    24  // Meta field.
    25  type ValueStruct struct {
    26  	Meta     byte
    27  	UserMeta []byte
    28  	Value    []byte
    29  
    30  	Version uint64 // This field is not serialized. Only for internal usage.
    31  }
    32  
    33  // EncodedSize is the size of the ValueStruct when encoded
    34  func (v *ValueStruct) EncodedSize() uint32 {
    35  	return uint32(len(v.Value) + len(v.UserMeta) + 2 + 8) // meta
    36  }
    37  
    38  // Decode uses the length of the slice to infer the length of the Value field.
    39  func (v *ValueStruct) Decode(b []byte) {
    40  	v.Version = binary.LittleEndian.Uint64(b)
    41  	b = b[8:]
    42  	v.Meta = b[0]
    43  	v.UserMeta = nil
    44  	userMetaEnd := 2 + b[1]
    45  	if b[1] != 0 {
    46  		v.UserMeta = b[2:userMetaEnd]
    47  	}
    48  	v.Value = b[userMetaEnd:]
    49  }
    50  
    51  // Encode expects a slice of length at least v.EncodedSize().
    52  func (v *ValueStruct) Encode(b []byte) {
    53  	binary.LittleEndian.PutUint64(b, v.Version)
    54  	b = b[8:]
    55  	b[0] = v.Meta
    56  	b[1] = byte(len(v.UserMeta))
    57  	copy(b[2:], v.UserMeta)
    58  	copy(b[2+len(v.UserMeta):], v.Value)
    59  }
    60  
    61  // Valid checks if the ValueStruct is valid.
    62  func (v *ValueStruct) Valid() bool {
    63  	return v.Meta != 0 || v.Value != nil
    64  }
    65  
    66  // EncodeTo should be kept in sync with the Encode function above. The reason
    67  // this function exists is to avoid creating byte arrays per key-value pair in
    68  // table/builder.go.
    69  func (v *ValueStruct) EncodeTo(buf []byte) []byte {
    70  	tmp := make([]byte, 8)
    71  	binary.LittleEndian.PutUint64(tmp, v.Version)
    72  	buf = append(buf, tmp...)
    73  	buf = append(buf, v.Meta, byte(len(v.UserMeta)))
    74  	buf = append(buf, v.UserMeta...)
    75  	buf = append(buf, v.Value...)
    76  	return buf
    77  }
    78  
    79  // Iterator is an interface for a basic iterator.
    80  type Iterator interface {
    81  	// Next returns the next entry with different key on the latest version.
    82  	// If old version is needed, call NextVersion.
    83  	Next()
    84  	// NextVersion set the current entry to an older version.
    85  	// The iterator must be valid to call this method.
    86  	// It returns true if there is an older version, returns false if there is no older version.
    87  	// The iterator is still valid and on the same key.
    88  	NextVersion() bool
    89  	Rewind()
    90  	Seek(key []byte)
    91  	Key() Key
    92  	Value() ValueStruct
    93  	FillValue(vs *ValueStruct)
    94  	Valid() bool
    95  	Close() error
    96  }
    97  
    98  // SeekToVersion seeks a valid Iterator to the version that <= the given version.
    99  func SeekToVersion(it Iterator, version uint64) bool {
   100  	if version >= it.Key().Version {
   101  		return true
   102  	}
   103  	for it.NextVersion() {
   104  		if version >= it.Key().Version {
   105  			return true
   106  		}
   107  	}
   108  	return false
   109  }
   110  
   111  func NextAllVersion(it Iterator) {
   112  	if !it.NextVersion() {
   113  		it.Next()
   114  	}
   115  }