github.com/pingcap/br@v5.3.0-alpha.0.20220125034240-ec59c7b6ce30+incompatible/pkg/kv/checksum.go (about)

     1  // Copyright 2019 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 kv
    15  
    16  import (
    17  	"fmt"
    18  	"hash/crc64"
    19  
    20  	"go.uber.org/zap/zapcore"
    21  )
    22  
    23  var ecmaTable = crc64.MakeTable(crc64.ECMA)
    24  
    25  // Checksum represents the field needs checksum.
    26  type Checksum struct {
    27  	bytes    uint64
    28  	kvs      uint64
    29  	checksum uint64
    30  }
    31  
    32  // NewKVChecksum creates Checksum.
    33  func NewKVChecksum(checksum uint64) *Checksum {
    34  	return &Checksum{
    35  		checksum: checksum,
    36  	}
    37  }
    38  
    39  // MakeKVChecksum creates Checksum.
    40  func MakeKVChecksum(bytes uint64, kvs uint64, checksum uint64) Checksum {
    41  	return Checksum{
    42  		bytes:    bytes,
    43  		kvs:      kvs,
    44  		checksum: checksum,
    45  	}
    46  }
    47  
    48  // UpdateOne add kv with its values.
    49  func (c *Checksum) UpdateOne(kv Pair) {
    50  	sum := crc64.Update(0, ecmaTable, kv.Key)
    51  	sum = crc64.Update(sum, ecmaTable, kv.Val)
    52  
    53  	c.bytes += uint64(len(kv.Key) + len(kv.Val))
    54  	c.kvs++
    55  	c.checksum ^= sum
    56  }
    57  
    58  // Update add batch of kvs with their values.
    59  func (c *Checksum) Update(kvs []Pair) {
    60  	var (
    61  		checksum uint64
    62  		sum      uint64
    63  		kvNum    int
    64  		bytes    int
    65  	)
    66  
    67  	for _, pair := range kvs {
    68  		sum = crc64.Update(0, ecmaTable, pair.Key)
    69  		sum = crc64.Update(sum, ecmaTable, pair.Val)
    70  		checksum ^= sum
    71  		kvNum++
    72  		bytes += (len(pair.Key) + len(pair.Val))
    73  	}
    74  
    75  	c.bytes += uint64(bytes)
    76  	c.kvs += uint64(kvNum)
    77  	c.checksum ^= checksum
    78  }
    79  
    80  // Add other checksum.
    81  func (c *Checksum) Add(other *Checksum) {
    82  	c.bytes += other.bytes
    83  	c.kvs += other.kvs
    84  	c.checksum ^= other.checksum
    85  }
    86  
    87  // Sum returns the checksum.
    88  func (c *Checksum) Sum() uint64 {
    89  	return c.checksum
    90  }
    91  
    92  // SumSize returns the bytes.
    93  func (c *Checksum) SumSize() uint64 {
    94  	return c.bytes
    95  }
    96  
    97  // SumKVS returns the kv count.
    98  func (c *Checksum) SumKVS() uint64 {
    99  	return c.kvs
   100  }
   101  
   102  // MarshalLogObject implements the zapcore.ObjectMarshaler interface.
   103  func (c *Checksum) MarshalLogObject(encoder zapcore.ObjectEncoder) error {
   104  	encoder.AddUint64("cksum", c.checksum)
   105  	encoder.AddUint64("size", c.bytes)
   106  	encoder.AddUint64("kvs", c.kvs)
   107  	return nil
   108  }
   109  
   110  // MarshalJSON implements the json.Marshaler interface.
   111  func (c Checksum) MarshalJSON() ([]byte, error) {
   112  	result := fmt.Sprintf(`{"checksum":%d,"size":%d,"kvs":%d}`, c.checksum, c.bytes, c.kvs)
   113  	return []byte(result), nil
   114  }