github.com/pingcap/br@v5.3.0-alpha.0.20220125034240-ec59c7b6ce30+incompatible/pkg/lightning/backend/local/key_adapter.go (about)

     1  // Copyright 2021 PingCAP, 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 local
    15  
    16  import (
    17  	"encoding/binary"
    18  
    19  	"github.com/pingcap/errors"
    20  	"github.com/pingcap/tidb/util/codec"
    21  )
    22  
    23  // KeyAdapter is used to encode and decode keys.
    24  type KeyAdapter interface {
    25  	// Encode encodes key with rowID and offset. It guarantees the encoded key is in ascending order for comparison.
    26  	// `buf` is used to buffer data to avoid the cost of make slice.
    27  	// Implementations of Encode must not reuse the key for encoding.
    28  	Encode(buf []byte, key []byte, rowID int64, offset int64) []byte
    29  
    30  	// Decode decodes the original key. `buf` is used to buffer data to avoid the cost of make slice.
    31  	// Implementations of Decode must not reuse the data for decoding.
    32  	Decode(buf []byte, data []byte) (key []byte, rowID int64, offset int64, err error)
    33  
    34  	// EncodedLen returns the encoded key length.
    35  	EncodedLen(key []byte) int
    36  }
    37  
    38  func reallocBytes(b []byte, n int) []byte {
    39  	newSize := len(b) + n
    40  	if cap(b) < newSize {
    41  		bs := make([]byte, len(b), newSize)
    42  		copy(bs, b)
    43  		return bs
    44  	}
    45  	return b
    46  }
    47  
    48  type noopKeyAdapter struct{}
    49  
    50  func (noopKeyAdapter) Encode(buf []byte, key []byte, _ int64, _ int64) []byte {
    51  	return append(buf[:0], key...)
    52  }
    53  
    54  func (noopKeyAdapter) Decode(buf []byte, data []byte) (key []byte, rowID int64, offset int64, err error) {
    55  	key = append(buf[:0], data...)
    56  	return
    57  }
    58  
    59  func (noopKeyAdapter) EncodedLen(key []byte) int {
    60  	return len(key)
    61  }
    62  
    63  var _ KeyAdapter = noopKeyAdapter{}
    64  
    65  type duplicateKeyAdapter struct{}
    66  
    67  func (duplicateKeyAdapter) Encode(buf []byte, key []byte, rowID int64, offset int64) []byte {
    68  	buf = codec.EncodeBytes(buf[:0], key)
    69  	buf = reallocBytes(buf, 16)
    70  	n := len(buf)
    71  	buf = buf[:n+16]
    72  	binary.BigEndian.PutUint64(buf[n:n+8], uint64(rowID))
    73  	binary.BigEndian.PutUint64(buf[n+8:], uint64(offset))
    74  	return buf
    75  }
    76  
    77  func (duplicateKeyAdapter) Decode(buf []byte, data []byte) (key []byte, rowID int64, offset int64, err error) {
    78  	if len(data) < 16 {
    79  		return nil, 0, 0, errors.New("insufficient bytes to decode value")
    80  	}
    81  	_, key, err = codec.DecodeBytes(data[:len(data)-16], buf)
    82  	if err != nil {
    83  		return
    84  	}
    85  	rowID = int64(binary.BigEndian.Uint64(data[len(data)-16 : len(data)-8]))
    86  	offset = int64(binary.BigEndian.Uint64(data[len(data)-8:]))
    87  	return
    88  }
    89  
    90  func (duplicateKeyAdapter) EncodedLen(key []byte) int {
    91  	return codec.EncodedBytesLength(len(key)) + 16
    92  }
    93  
    94  var _ KeyAdapter = duplicateKeyAdapter{}