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{}