diff --git a/pkg/storage/mvcc_history_test.go b/pkg/storage/mvcc_history_test.go index de394ba89980..c69d787eb290 100644 --- a/pkg/storage/mvcc_history_test.go +++ b/pkg/storage/mvcc_history_test.go @@ -82,10 +82,10 @@ var ( // txn_status t= status= // txn_ignore_seqs t= seqs=[-[,-...]] // -// resolve_intent t= k= [status=] [clockWhilePending=[,]] [targetBytes=] -// resolve_intent_range t= k= end= [status=] [maxKeys=] [targetBytes=] -// check_intent k= [none] -// add_lock t= k= +// resolve_intent t= k= [status=] [clockWhilePending=[,]] [targetBytes=] +// resolve_intent_range t= k= end= [status=] [maxKeys=] [targetBytes=] +// check_intent k= [none] +// add_unreplicated_lock t= k= // // cput [t=] [ts=[,]] [localTs=[,]] [resolve [status=]] [ambiguousReplay] k= v= [raw] [cond=] // del [t=] [ts=[,]] [localTs=[,]] [resolve [status=]] [ambiguousReplay] k= @@ -349,7 +349,23 @@ func TestMVCCHistories(t *testing.T) { } } } + return nil + } + // reportLockTable outputs the contents of the lock table. + reportLockTable := func(e *evalCtx, buf *redact.StringBuilder) error { + if len(e.unreplLocks) > 0 { + var ks []string + for k := range e.unreplLocks { + ks = append(ks, k) + } + sort.Strings(ks) + for _, k := range ks { + txn := e.unreplLocks[k] + buf.Printf("lock (%s): %v/%s -> %+v\n", + lock.Unreplicated, k, lock.Exclusive, txn) + } + } return nil } @@ -470,19 +486,15 @@ func TestMVCCHistories(t *testing.T) { } } if printLocks { - var ks []string - for k := range e.locks { - ks = append(ks, k) - } - sort.Strings(ks) - buf.Printf("lock-table: {") - for i, k := range ks { - if i > 0 { - buf.Printf(", ") + err = reportLockTable(e, &buf) + if err != nil { + if foundErr == nil { + // Handle the error below. + foundErr = err + } else { + buf.Printf("error reading locks: (%T:) %v\n", err, err) } - buf.Printf("%s:%s", k, e.locks[k].ID) } - buf.Printf("}\n") } } @@ -720,10 +732,10 @@ var commands = map[string]cmd{ "txn_step": {typTxnUpdate, cmdTxnStep}, "txn_update": {typTxnUpdate, cmdTxnUpdate}, - "resolve_intent": {typDataUpdate, cmdResolveIntent}, - "resolve_intent_range": {typDataUpdate, cmdResolveIntentRange}, - "check_intent": {typReadOnly, cmdCheckIntent}, - "add_lock": {typLocksUpdate, cmdAddLock}, + "resolve_intent": {typDataUpdate, cmdResolveIntent}, + "resolve_intent_range": {typDataUpdate, cmdResolveIntentRange}, + "check_intent": {typReadOnly, cmdCheckIntent}, + "add_unreplicated_lock": {typLocksUpdate, cmdAddUnreplicatedLock}, "clear": {typDataUpdate, cmdClear}, "clear_range": {typDataUpdate, cmdClearRange}, @@ -994,10 +1006,10 @@ func cmdCheckIntent(e *evalCtx) error { }) } -func cmdAddLock(e *evalCtx) error { +func cmdAddUnreplicatedLock(e *evalCtx) error { txn := e.getTxn(mandatory) key := e.getKey() - e.locks[string(key)] = txn + e.unreplLocks[string(key)] = &txn.TxnMeta return nil } @@ -2218,7 +2230,7 @@ type evalCtx struct { td *datadriven.TestData txns map[string]*roachpb.Transaction txnCounter uint32 - locks map[string]*roachpb.Transaction + unreplLocks map[string]*enginepb.TxnMeta ms *enginepb.MVCCStats sstWriter *storage.SSTWriter sstFile *storage.MemObject @@ -2227,11 +2239,11 @@ type evalCtx struct { func newEvalCtx(ctx context.Context, engine storage.Engine) *evalCtx { return &evalCtx{ - ctx: ctx, - st: cluster.MakeTestingClusterSettings(), - engine: engine, - txns: make(map[string]*roachpb.Transaction), - locks: make(map[string]*roachpb.Transaction), + ctx: ctx, + st: cluster.MakeTestingClusterSettings(), + engine: engine, + txns: make(map[string]*roachpb.Transaction), + unreplLocks: make(map[string]*enginepb.TxnMeta), } } @@ -2526,20 +2538,20 @@ func (e *evalCtx) lookupTxn(txnName string) (*roachpb.Transaction, error) { func (e *evalCtx) newLockTableView( txn *roachpb.Transaction, ts hlc.Timestamp, ) storage.LockTableView { - return &mockLockTableView{locks: e.locks, txn: txn, ts: ts} + return &mockLockTableView{unreplLocks: e.unreplLocks, txn: txn, ts: ts} } // mockLockTableView is a mock implementation of LockTableView. type mockLockTableView struct { - locks map[string]*roachpb.Transaction - txn *roachpb.Transaction - ts hlc.Timestamp + unreplLocks map[string]*enginepb.TxnMeta + txn *roachpb.Transaction + ts hlc.Timestamp } func (lt *mockLockTableView) IsKeyLockedByConflictingTxn( k roachpb.Key, s lock.Strength, ) (bool, *enginepb.TxnMeta, error) { - holder, ok := lt.locks[string(k)] + holder, ok := lt.unreplLocks[string(k)] if !ok { return false, nil, nil } @@ -2549,7 +2561,7 @@ func (lt *mockLockTableView) IsKeyLockedByConflictingTxn( if s == lock.None && lt.ts.Less(holder.WriteTimestamp) { return false, nil, nil } - return true, &holder.TxnMeta, nil + return true, holder, nil } func (e *evalCtx) visitWrappedIters(fn func(it storage.SimpleMVCCIterator) (done bool)) { diff --git a/pkg/storage/testdata/mvcc_histories/skip_locked b/pkg/storage/testdata/mvcc_histories/skip_locked index 23b05eb3ade6..7119e9782ed3 100644 --- a/pkg/storage/testdata/mvcc_histories/skip_locked +++ b/pkg/storage/testdata/mvcc_histories/skip_locked @@ -28,7 +28,7 @@ put k=k2 v=v3 ts=13,0 t=B put k=k3 v=v4 ts=14,0 t=C put k=k4 v=v5 ts=15,0 put k=k5 v=v6 ts=17,0 -add_lock k=k4 t=E +add_unreplicated_lock k=k4 t=E ---- >> at end: data: "k1"/11.000000000,0 -> /BYTES/v1 @@ -39,7 +39,7 @@ meta: "k3"/0,0 -> txn={id=00000003 key=/Min iso=Serializable pri=0.00000000 epo= data: "k3"/14.000000000,0 -> /BYTES/v4 data: "k4"/15.000000000,0 -> /BYTES/v5 data: "k5"/17.000000000,0 -> /BYTES/v6 -lock-table: {k4:00000005-0000-0000-0000-000000000000} +lock (Unreplicated): k4/Exclusive -> id=00000005 key=/Min iso=Serializable pri=0.00000000 epo=0 ts=16.000000000,0 min=0,0 seq=0 # Test cases: #