talent-plan-tinykv/kv/transaction/mvcc/lock.go
Connor1996 73f60164cb fix transaction test build
Signed-off-by: Connor1996 <zbk602423539@gmail.com>
2020-04-30 15:31:26 +08:00

99 lines
2.4 KiB
Go

package mvcc
import (
"bytes"
"encoding/binary"
"fmt"
"reflect"
"github.com/pingcap-incubator/tinykv/kv/util/engine_util"
"github.com/pingcap-incubator/tinykv/proto/pkg/kvrpcpb"
)
const TsMax uint64 = ^uint64(0)
type Lock struct {
Primary []byte
Ts uint64
Ttl uint64
Kind WriteKind
}
type KlPair struct {
Key []byte
Lock *Lock
}
// Info creates a LockInfo object from a Lock object for key.
func (lock *Lock) Info(key []byte) *kvrpcpb.LockInfo {
info := kvrpcpb.LockInfo{}
info.Key = key
info.LockVersion = lock.Ts
info.PrimaryLock = lock.Primary
info.LockTtl = lock.Ttl
return &info
}
func (lock *Lock) ToBytes() []byte {
buf := append(lock.Primary, byte(lock.Kind))
buf = append(buf, make([]byte, 16)...)
binary.BigEndian.PutUint64(buf[len(lock.Primary)+1:], lock.Ts)
binary.BigEndian.PutUint64(buf[len(lock.Primary)+9:], lock.Ttl)
return buf
}
// ParseLock attempts to parse a byte string into a Lock object.
func ParseLock(input []byte) (*Lock, error) {
if len(input) <= 16 {
return nil, fmt.Errorf("mvcc: error parsing lock, not enough input, found %d bytes", len(input))
}
primaryLen := len(input) - 17
primary := input[:primaryLen]
kind := WriteKind(input[primaryLen])
ts := binary.BigEndian.Uint64(input[primaryLen+1:])
ttl := binary.BigEndian.Uint64(input[primaryLen+9:])
return &Lock{Primary: primary, Ts: ts, Ttl: ttl, Kind: kind}, nil
}
// IsLockedFor checks if lock locks key at txnStartTs.
func (lock *Lock) IsLockedFor(key []byte, txnStartTs uint64, resp interface{}) bool {
if lock == nil {
return false
}
if txnStartTs == TsMax && bytes.Compare(key, lock.Primary) != 0 {
return false
}
if lock.Ts <= txnStartTs {
err := &kvrpcpb.KeyError{Locked: lock.Info(key)}
respValue := reflect.ValueOf(resp)
reflect.Indirect(respValue).FieldByName("Error").Set(reflect.ValueOf(err))
return true
}
return false
}
// AllLocksForTxn returns all locks for the current transaction.
func AllLocksForTxn(txn *MvccTxn) ([]KlPair, error) {
var result []KlPair
iter := txn.Reader.IterCF(engine_util.CfLock)
defer iter.Close()
for ; iter.Valid(); iter.Next() {
item := iter.Item()
val, err := item.Value()
if err != nil {
return nil, err
}
lock, err := ParseLock(val)
if err != nil {
return nil, err
}
if lock.Ts == txn.StartTS {
result = append(result, KlPair{item.Key(), lock})
}
}
return result, nil
}