github.com/vescale/zgraph@v0.0.0-20230410094002-959c02d50f95/storage/resolver/txn_status.go (about)

     1  // Copyright 2022 zGraph Authors. All rights reserved.
     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  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package resolver
    16  
    17  import (
    18  	"time"
    19  
    20  	"github.com/cockroachdb/pebble"
    21  	"github.com/pingcap/errors"
    22  	"github.com/vescale/zgraph/storage/kv"
    23  	"github.com/vescale/zgraph/storage/mvcc"
    24  )
    25  
    26  type TxnAction byte
    27  
    28  const (
    29  	TxnActionNone TxnAction = iota
    30  	TxnActionTTLExpireRollback
    31  	TxnActionLockNotExistRollback
    32  	TxnActionLockNotExistDoNothing
    33  )
    34  
    35  type TxnStatus struct {
    36  	CommitVer kv.Version
    37  	Action    TxnAction
    38  }
    39  
    40  // CheckTxnStatus checks the transaction status according to the primary key.
    41  func CheckTxnStatus(db *pebble.DB, vp kv.VersionProvider, primaryKey kv.Key, startVer kv.Version) (TxnStatus, error) {
    42  	opt := pebble.IterOptions{LowerBound: mvcc.LockKey(primaryKey)}
    43  	iter := db.NewIter(&opt)
    44  	iter.First()
    45  	defer iter.Close()
    46  
    47  	if !iter.Valid() {
    48  		return TxnStatus{}, errors.New("txn not found")
    49  	}
    50  
    51  	decoder := mvcc.LockDecoder{ExpectKey: primaryKey}
    52  	exists, err := decoder.Decode(iter)
    53  	if err != nil {
    54  		return TxnStatus{}, err
    55  	}
    56  
    57  	// If the transaction lock exists means the current transaction not committed.
    58  	if exists && decoder.Lock.StartVer == startVer {
    59  		ver := vp.CurrentVersion()
    60  		exp := startVer + kv.Version(time.Duration(decoder.Lock.TTL)*time.Millisecond)
    61  		if exp < ver {
    62  			return TxnStatus{Action: TxnActionTTLExpireRollback}, nil
    63  		}
    64  		return TxnStatus{Action: TxnActionNone}, nil
    65  	}
    66  
    67  	c, exists, err := getTxnCommitInfo(iter, primaryKey, startVer)
    68  	if err != nil {
    69  		return TxnStatus{}, err
    70  	}
    71  	if exists {
    72  		if c.Type == mvcc.ValueTypeRollback {
    73  			return TxnStatus{Action: TxnActionLockNotExistRollback}, nil
    74  		}
    75  		return TxnStatus{CommitVer: c.CommitVer, Action: TxnActionLockNotExistDoNothing}, nil
    76  	}
    77  
    78  	return TxnStatus{}, errors.New("transaction status missing")
    79  }