From 91d85f7850b6e2e9322ee1abb222bb2403aebc46 Mon Sep 17 00:00:00 2001 From: Alex Sarkesian Date: Wed, 26 Jul 2023 02:29:52 -0400 Subject: [PATCH] storage: refactor mvcc write parameters This change introduces `MVCCWriteOptions`, a structure for bundling parameters for `MVCCPut`, `MVCCDelete`, and their many variants, and refactors usages of these functions across the code base in order to move the existing function arguments into this structure. In addition to allowing the code to eliminate specifying default values in many callers, this enables the ability to pass new flags to write operations such as the replay protection needed to address #103817. Part of: #103817 Release note: None --- pkg/ccl/storageccl/engineccl/bench_test.go | 2 +- .../storageccl/engineccl/encrypted_fs_test.go | 4 +- .../kvcoord/dist_sender_server_test.go | 2 +- pkg/kv/kvserver/abortspan/abortspan.go | 8 +- pkg/kv/kvserver/batch_spanset_test.go | 4 +- .../batcheval/cmd_add_sstable_test.go | 2 +- .../batcheval/cmd_clear_range_test.go | 4 +- .../kvserver/batcheval/cmd_conditional_put.go | 11 +- pkg/kv/kvserver/batcheval/cmd_delete.go | 8 +- pkg/kv/kvserver/batcheval/cmd_delete_range.go | 6 +- .../batcheval/cmd_delete_range_test.go | 10 +- .../kvserver/batcheval/cmd_end_transaction.go | 10 +- .../batcheval/cmd_end_transaction_test.go | 10 +- pkg/kv/kvserver/batcheval/cmd_export_test.go | 4 +- .../kvserver/batcheval/cmd_heartbeat_txn.go | 2 +- pkg/kv/kvserver/batcheval/cmd_increment.go | 8 +- pkg/kv/kvserver/batcheval/cmd_init_put.go | 10 +- pkg/kv/kvserver/batcheval/cmd_push_txn.go | 4 +- pkg/kv/kvserver/batcheval/cmd_put.go | 12 +- .../batcheval/cmd_query_intent_test.go | 2 +- .../cmd_query_resolved_timestamp_test.go | 6 +- pkg/kv/kvserver/batcheval/cmd_recover_txn.go | 2 +- .../batcheval/cmd_recover_txn_test.go | 4 +- .../batcheval/cmd_refresh_range_bench_test.go | 2 +- .../batcheval/cmd_refresh_range_test.go | 12 +- pkg/kv/kvserver/batcheval/cmd_refresh_test.go | 4 +- .../batcheval/cmd_resolve_intent_test.go | 6 +- .../batcheval/cmd_revert_range_test.go | 10 +- pkg/kv/kvserver/batcheval/cmd_scan_test.go | 4 +- .../batcheval/cmd_truncate_log_test.go | 4 +- pkg/kv/kvserver/batcheval/intent_test.go | 4 +- pkg/kv/kvserver/batcheval/transaction_test.go | 2 +- pkg/kv/kvserver/client_merge_test.go | 2 +- pkg/kv/kvserver/consistency_queue_test.go | 4 +- pkg/kv/kvserver/gc/data_distribution_test.go | 4 +- pkg/kv/kvserver/gc/gc_test.go | 4 +- pkg/kv/kvserver/kvstorage/cluster_version.go | 4 +- pkg/kv/kvserver/kvstorage/destroy.go | 4 +- pkg/kv/kvserver/kvstorage/init.go | 4 +- pkg/kv/kvserver/logstore/logstore.go | 11 +- pkg/kv/kvserver/logstore/stateloader.go | 22 +- pkg/kv/kvserver/loqrecovery/apply.go | 6 +- pkg/kv/kvserver/loqrecovery/apply_test.go | 2 +- pkg/kv/kvserver/loqrecovery/record.go | 16 +- .../kvserver/loqrecovery/recovery_env_test.go | 4 +- pkg/kv/kvserver/mvcc_gc_queue_test.go | 20 +- .../rangefeed/catchup_scan_bench_test.go | 2 +- .../kvserver/rangefeed/catchup_scan_test.go | 18 +- pkg/kv/kvserver/rangefeed/task_test.go | 2 +- .../kvserver/rditer/replica_data_iter_test.go | 2 +- pkg/kv/kvserver/readsummary/persist.go | 2 +- pkg/kv/kvserver/replica.go | 2 +- pkg/kv/kvserver/replica_consistency_test.go | 2 +- pkg/kv/kvserver/replica_evaluate_test.go | 4 +- pkg/kv/kvserver/replica_raft.go | 4 +- pkg/kv/kvserver/replica_test.go | 18 +- pkg/kv/kvserver/stateloader/stateloader.go | 20 +- pkg/kv/kvserver/store.go | 8 +- pkg/kv/kvserver/store_init.go | 16 +- pkg/kv/kvserver/store_snapshot.go | 2 +- pkg/kv/kvserver/store_test.go | 6 +- pkg/kv/kvserver/stores.go | 2 +- pkg/kv/kvserver/txn_wait_queue_test.go | 6 +- pkg/server/node_test.go | 6 +- pkg/server/node_tombstone_storage.go | 2 +- pkg/server/server_test.go | 7 +- pkg/server/settings_cache.go | 2 +- pkg/storage/bench_data_test.go | 2 +- pkg/storage/bench_pebble_test.go | 4 +- pkg/storage/bench_test.go | 38 +- pkg/storage/engine_test.go | 38 +- pkg/storage/metamorphic/operations.go | 14 +- pkg/storage/mvcc.go | 157 +++---- pkg/storage/mvcc_history_test.go | 42 +- pkg/storage/mvcc_incremental_iterator_test.go | 52 +-- pkg/storage/mvcc_logical_ops_test.go | 18 +- pkg/storage/mvcc_stats_test.go | 72 +-- pkg/storage/mvcc_test.go | 436 +++++++++--------- pkg/storage/pebble_mvcc_scanner_test.go | 2 +- pkg/storage/pebble_test.go | 2 +- pkg/storage/sst_test.go | 2 +- 81 files changed, 678 insertions(+), 624 deletions(-) diff --git a/pkg/ccl/storageccl/engineccl/bench_test.go b/pkg/ccl/storageccl/engineccl/bench_test.go index 3bbd0b656c15..7db5f4b458f1 100644 --- a/pkg/ccl/storageccl/engineccl/bench_test.go +++ b/pkg/ccl/storageccl/engineccl/bench_test.go @@ -110,7 +110,7 @@ func loadTestData( timestamp := hlc.Timestamp{WallTime: minWallTime + rand.Int63n(int64(batchTimeSpan))} value := roachpb.MakeValueFromBytes(randutil.RandBytes(rng, valueBytes)) value.InitChecksum(key) - if err := storage.MVCCPut(ctx, batch, nil, key, timestamp, hlc.ClockTimestamp{}, value, nil); err != nil { + if err := storage.MVCCPut(ctx, batch, key, timestamp, value, storage.MVCCWriteOptions{}); err != nil { return nil, err } } diff --git a/pkg/ccl/storageccl/engineccl/encrypted_fs_test.go b/pkg/ccl/storageccl/engineccl/encrypted_fs_test.go index eef8784373ee..36bf69e16b8c 100644 --- a/pkg/ccl/storageccl/engineccl/encrypted_fs_test.go +++ b/pkg/ccl/storageccl/engineccl/encrypted_fs_test.go @@ -397,12 +397,10 @@ func TestPebbleEncryption2(t *testing.T) { err = storage.MVCCPut( context.Background(), db, - nil, /* ms */ roachpb.Key(key), hlc.Timestamp{}, - hlc.ClockTimestamp{}, roachpb.MakeValueFromBytes([]byte(val)), - nil, /* txn */ + storage.MVCCWriteOptions{}, ) require.NoError(t, err) require.NoError(t, db.Flush()) diff --git a/pkg/kv/kvclient/kvcoord/dist_sender_server_test.go b/pkg/kv/kvclient/kvcoord/dist_sender_server_test.go index 3a5a0c9476bd..9abbfafb739d 100644 --- a/pkg/kv/kvclient/kvcoord/dist_sender_server_test.go +++ b/pkg/kv/kvclient/kvcoord/dist_sender_server_test.go @@ -77,7 +77,7 @@ func TestRangeLookupWithOpenTransaction(t *testing.T) { key := testutils.MakeKey(keys.Meta1Prefix, roachpb.KeyMax) now := s.Clock().Now() txn := roachpb.MakeTransaction("txn", roachpb.Key("foobar"), 0, now, 0, int32(s.SQLInstanceID())) - if err := storage.MVCCPutProto(context.Background(), s.Engines()[0], nil, key, now, hlc.ClockTimestamp{}, &txn, &roachpb.RangeDescriptor{}); err != nil { + if err := storage.MVCCPutProto(context.Background(), s.Engines()[0], key, now, &roachpb.RangeDescriptor{}, storage.MVCCWriteOptions{Txn: &txn}); err != nil { t.Fatal(err) } diff --git a/pkg/kv/kvserver/abortspan/abortspan.go b/pkg/kv/kvserver/abortspan/abortspan.go index 01942e11faa5..afb50200c651 100644 --- a/pkg/kv/kvserver/abortspan/abortspan.go +++ b/pkg/kv/kvserver/abortspan/abortspan.go @@ -120,7 +120,7 @@ func (sc *AbortSpan) Del( ctx context.Context, reader storage.ReadWriter, ms *enginepb.MVCCStats, txnID uuid.UUID, ) error { key := keys.AbortSpanKey(sc.rangeID, txnID) - _, err := storage.MVCCDelete(ctx, reader, ms, key, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil /* txn */) + _, err := storage.MVCCDelete(ctx, reader, key, hlc.Timestamp{}, storage.MVCCWriteOptions{Stats: ms}) return err } @@ -134,7 +134,7 @@ func (sc *AbortSpan) Put( ) error { log.VEventf(ctx, 2, "writing abort span entry for %s", txnID.Short()) key := keys.AbortSpanKey(sc.rangeID, txnID) - return storage.MVCCPutProto(ctx, readWriter, ms, key, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil /* txn */, entry) + return storage.MVCCPutProto(ctx, readWriter, key, hlc.Timestamp{}, entry, storage.MVCCWriteOptions{Stats: ms}) } // CopyTo copies the abort span entries to the abort span for the range @@ -178,9 +178,9 @@ func (sc *AbortSpan) CopyTo( if err != nil { return err } - return storage.MVCCPutProto(ctx, w, ms, + return storage.MVCCPutProto(ctx, w, keys.AbortSpanKey(newRangeID, txnID), - hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, &entry, + hlc.Timestamp{}, &entry, storage.MVCCWriteOptions{Stats: ms}, ) }); err != nil { return errors.Wrap(err, "AbortSpan.CopyTo") diff --git a/pkg/kv/kvserver/batch_spanset_test.go b/pkg/kv/kvserver/batch_spanset_test.go index 81e2559862ba..3e012d07f497 100644 --- a/pkg/kv/kvserver/batch_spanset_test.go +++ b/pkg/kv/kvserver/batch_spanset_test.go @@ -545,12 +545,10 @@ func TestSpanSetMVCCResolveWriteIntentRange(t *testing.T) { if err := storage.MVCCPut( ctx, eng, - nil, // ms roachpb.Key("b"), hlc.Timestamp{WallTime: 10}, // irrelevant - hlc.ClockTimestamp{}, // irrelevant value, - nil, // txn + storage.MVCCWriteOptions{}, // irrelevant ); err != nil { t.Fatal(err) } diff --git a/pkg/kv/kvserver/batcheval/cmd_add_sstable_test.go b/pkg/kv/kvserver/batcheval/cmd_add_sstable_test.go index f5682df778ee..07e57f8ea7ef 100644 --- a/pkg/kv/kvserver/batcheval/cmd_add_sstable_test.go +++ b/pkg/kv/kvserver/batcheval/cmd_add_sstable_test.go @@ -1142,7 +1142,7 @@ func TestEvalAddSSTable(t *testing.T) { kv.Key.Timestamp.WallTime *= 1e9 v, err := storage.DecodeMVCCValue(kv.Value) require.NoError(t, err) - require.NoError(t, storage.MVCCPut(ctx, b, nil, kv.Key.Key, kv.Key.Timestamp, hlc.ClockTimestamp{}, v.Value, txn)) + require.NoError(t, storage.MVCCPut(ctx, b, kv.Key.Key, kv.Key.Timestamp, v.Value, storage.MVCCWriteOptions{Txn: txn})) case storage.MVCCRangeKeyValue: v, err := storage.DecodeMVCCValue(kv.Value) require.NoError(t, err) diff --git a/pkg/kv/kvserver/batcheval/cmd_clear_range_test.go b/pkg/kv/kvserver/batcheval/cmd_clear_range_test.go index 43a310a8ddf2..0aea9898b99f 100644 --- a/pkg/kv/kvserver/batcheval/cmd_clear_range_test.go +++ b/pkg/kv/kvserver/batcheval/cmd_clear_range_test.go @@ -151,8 +151,8 @@ func TestCmdClearRange(t *testing.T) { // Write some random point keys within the cleared span, above the range tombstones. for i := 0; i < tc.keyCount; i++ { key := roachpb.Key(fmt.Sprintf("%04d", i)) - require.NoError(t, storage.MVCCPut(ctx, eng, nil, key, - hlc.Timestamp{WallTime: int64(4+i%2) * 1e9}, hlc.ClockTimestamp{}, value, nil)) + require.NoError(t, storage.MVCCPut(ctx, eng, key, + hlc.Timestamp{WallTime: int64(4+i%2) * 1e9}, value, storage.MVCCWriteOptions{})) } // Calculate the range stats. diff --git a/pkg/kv/kvserver/batcheval/cmd_conditional_put.go b/pkg/kv/kvserver/batcheval/cmd_conditional_put.go index 75bd4e1ec1bd..20982a2fb57a 100644 --- a/pkg/kv/kvserver/batcheval/cmd_conditional_put.go +++ b/pkg/kv/kvserver/batcheval/cmd_conditional_put.go @@ -55,13 +55,20 @@ func ConditionalPut( } handleMissing := storage.CPutMissingBehavior(args.AllowIfDoesNotExist) + + opts := storage.MVCCWriteOptions{ + Txn: h.Txn, + LocalTimestamp: cArgs.Now, + Stats: cArgs.Stats, + } + var err error if args.Blind { err = storage.MVCCBlindConditionalPut( - ctx, readWriter, cArgs.Stats, args.Key, ts, cArgs.Now, args.Value, args.ExpBytes, handleMissing, h.Txn) + ctx, readWriter, args.Key, ts, args.Value, args.ExpBytes, handleMissing, opts) } else { err = storage.MVCCConditionalPut( - ctx, readWriter, cArgs.Stats, args.Key, ts, cArgs.Now, args.Value, args.ExpBytes, handleMissing, h.Txn) + ctx, readWriter, args.Key, ts, args.Value, args.ExpBytes, handleMissing, opts) } // NB: even if MVCC returns an error, it may still have written an intent // into the batch. This allows callers to consume errors like WriteTooOld diff --git a/pkg/kv/kvserver/batcheval/cmd_delete.go b/pkg/kv/kvserver/batcheval/cmd_delete.go index cbefdc473979..e30e9e8a48cb 100644 --- a/pkg/kv/kvserver/batcheval/cmd_delete.go +++ b/pkg/kv/kvserver/batcheval/cmd_delete.go @@ -31,9 +31,15 @@ func Delete( h := cArgs.Header reply := resp.(*kvpb.DeleteResponse) + opts := storage.MVCCWriteOptions{ + Txn: h.Txn, + LocalTimestamp: cArgs.Now, + Stats: cArgs.Stats, + } + var err error reply.FoundKey, err = storage.MVCCDelete( - ctx, readWriter, cArgs.Stats, args.Key, h.Timestamp, cArgs.Now, h.Txn, + ctx, readWriter, args.Key, h.Timestamp, opts, ) // If requested, replace point tombstones with range tombstones. diff --git a/pkg/kv/kvserver/batcheval/cmd_delete_range.go b/pkg/kv/kvserver/batcheval/cmd_delete_range.go index c3b9df8b50fe..4532b4533561 100644 --- a/pkg/kv/kvserver/batcheval/cmd_delete_range.go +++ b/pkg/kv/kvserver/batcheval/cmd_delete_range.go @@ -223,8 +223,10 @@ func DeleteRange( // can update the Result's AcquiredLocks field. returnKeys := args.ReturnKeys || h.Txn != nil deleted, resumeSpan, num, err := storage.MVCCDeleteRange( - ctx, readWriter, cArgs.Stats, args.Key, args.EndKey, - h.MaxSpanRequestKeys, timestamp, cArgs.Now, h.Txn, returnKeys) + ctx, readWriter, args.Key, args.EndKey, + h.MaxSpanRequestKeys, timestamp, + storage.MVCCWriteOptions{Txn: h.Txn, LocalTimestamp: cArgs.Now, Stats: cArgs.Stats}, + returnKeys) if err == nil && args.ReturnKeys { reply.Keys = deleted } diff --git a/pkg/kv/kvserver/batcheval/cmd_delete_range_test.go b/pkg/kv/kvserver/batcheval/cmd_delete_range_test.go index 39743c6dbde8..160a2423f296 100644 --- a/pkg/kv/kvserver/batcheval/cmd_delete_range_test.go +++ b/pkg/kv/kvserver/batcheval/cmd_delete_range_test.go @@ -58,12 +58,12 @@ func TestDeleteRangeTombstone(t *testing.T) { var localTS hlc.ClockTimestamp txn := roachpb.MakeTransaction("test", nil /* baseKey */, roachpb.NormalUserPriority, hlc.Timestamp{WallTime: 5e9}, 0, 0) - require.NoError(t, storage.MVCCPut(ctx, rw, nil, roachpb.Key("b"), hlc.Timestamp{WallTime: 2e9}, localTS, roachpb.MakeValueFromString("b2"), nil)) - require.NoError(t, storage.MVCCPut(ctx, rw, nil, roachpb.Key("c"), hlc.Timestamp{WallTime: 4e9}, localTS, roachpb.MakeValueFromString("c4"), nil)) - require.NoError(t, storage.MVCCPut(ctx, rw, nil, roachpb.Key("d"), hlc.Timestamp{WallTime: 2e9}, localTS, roachpb.MakeValueFromString("d2"), nil)) - _, err := storage.MVCCDelete(ctx, rw, nil, roachpb.Key("d"), hlc.Timestamp{WallTime: 3e9}, localTS, nil) + require.NoError(t, storage.MVCCPut(ctx, rw, roachpb.Key("b"), hlc.Timestamp{WallTime: 2e9}, roachpb.MakeValueFromString("b2"), storage.MVCCWriteOptions{LocalTimestamp: localTS})) + require.NoError(t, storage.MVCCPut(ctx, rw, roachpb.Key("c"), hlc.Timestamp{WallTime: 4e9}, roachpb.MakeValueFromString("c4"), storage.MVCCWriteOptions{LocalTimestamp: localTS})) + require.NoError(t, storage.MVCCPut(ctx, rw, roachpb.Key("d"), hlc.Timestamp{WallTime: 2e9}, roachpb.MakeValueFromString("d2"), storage.MVCCWriteOptions{LocalTimestamp: localTS})) + _, err := storage.MVCCDelete(ctx, rw, roachpb.Key("d"), hlc.Timestamp{WallTime: 3e9}, storage.MVCCWriteOptions{LocalTimestamp: localTS}) require.NoError(t, err) - require.NoError(t, storage.MVCCPut(ctx, rw, nil, roachpb.Key("i"), hlc.Timestamp{WallTime: 5e9}, localTS, roachpb.MakeValueFromString("i5"), &txn)) + require.NoError(t, storage.MVCCPut(ctx, rw, roachpb.Key("i"), hlc.Timestamp{WallTime: 5e9}, roachpb.MakeValueFromString("i5"), storage.MVCCWriteOptions{Txn: &txn, LocalTimestamp: localTS})) require.NoError(t, storage.MVCCDeleteRangeUsingTombstone(ctx, rw, nil, roachpb.Key("f"), roachpb.Key("h"), hlc.Timestamp{WallTime: 3e9}, localTS, nil, nil, false, 0, nil)) require.NoError(t, storage.MVCCDeleteRangeUsingTombstone(ctx, rw, nil, roachpb.Key("Z"), roachpb.Key("a"), hlc.Timestamp{WallTime: 100e9}, localTS, nil, nil, false, 0, nil)) require.NoError(t, storage.MVCCDeleteRangeUsingTombstone(ctx, rw, nil, roachpb.Key("z"), roachpb.Key("|"), hlc.Timestamp{WallTime: 100e9}, localTS, nil, nil, false, 0, nil)) diff --git a/pkg/kv/kvserver/batcheval/cmd_end_transaction.go b/pkg/kv/kvserver/batcheval/cmd_end_transaction.go index 09fbecaaf7ec..508344f23d44 100644 --- a/pkg/kv/kvserver/batcheval/cmd_end_transaction.go +++ b/pkg/kv/kvserver/batcheval/cmd_end_transaction.go @@ -690,7 +690,8 @@ func updateStagingTxn( txn.LockSpans = args.LockSpans txn.InFlightWrites = args.InFlightWrites txnRecord := txn.AsRecord() - return storage.MVCCPutProto(ctx, readWriter, ms, key, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, &txnRecord) + + return storage.MVCCPutProto(ctx, readWriter, key, hlc.Timestamp{}, &txnRecord, storage.MVCCWriteOptions{Stats: ms}) } // updateFinalizedTxn persists the COMMITTED or ABORTED transaction record with @@ -707,6 +708,7 @@ func updateFinalizedTxn( recordAlreadyExisted bool, externalLocks []roachpb.Span, ) error { + opts := storage.MVCCWriteOptions{Stats: ms} if txnAutoGC && len(externalLocks) == 0 { if log.V(2) { log.Infof(ctx, "auto-gc'ed %s (%d locks)", txn.Short(), len(args.LockSpans)) @@ -717,13 +719,13 @@ func updateFinalizedTxn( // BatchRequest writes. return nil } - _, err := storage.MVCCDelete(ctx, readWriter, ms, key, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil) + _, err := storage.MVCCDelete(ctx, readWriter, key, hlc.Timestamp{}, opts) return err } txn.LockSpans = externalLocks txn.InFlightWrites = nil txnRecord := txn.AsRecord() - return storage.MVCCPutProto(ctx, readWriter, ms, key, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, &txnRecord) + return storage.MVCCPutProto(ctx, readWriter, key, hlc.Timestamp{}, &txnRecord, opts) } // RunCommitTrigger runs the commit trigger from an end transaction request. @@ -1080,7 +1082,7 @@ func splitTriggerHelper( if err != nil { return enginepb.MVCCStats{}, result.Result{}, errors.Wrap(err, "unable to fetch last replica GC timestamp") } - if err := storage.MVCCPutProto(ctx, batch, nil, keys.RangeLastReplicaGCTimestampKey(split.RightDesc.RangeID), hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, &replicaGCTS); err != nil { + if err := storage.MVCCPutProto(ctx, batch, keys.RangeLastReplicaGCTimestampKey(split.RightDesc.RangeID), hlc.Timestamp{}, &replicaGCTS, storage.MVCCWriteOptions{}); err != nil { return enginepb.MVCCStats{}, result.Result{}, errors.Wrap(err, "unable to copy last replica GC timestamp") } diff --git a/pkg/kv/kvserver/batcheval/cmd_end_transaction_test.go b/pkg/kv/kvserver/batcheval/cmd_end_transaction_test.go index df6db245f948..fa473be7edbe 100644 --- a/pkg/kv/kvserver/batcheval/cmd_end_transaction_test.go +++ b/pkg/kv/kvserver/batcheval/cmd_end_transaction_test.go @@ -1011,7 +1011,7 @@ func TestEndTxnUpdatesTransactionRecord(t *testing.T) { // Write the existing transaction record, if necessary. txnKey := keys.TransactionKey(txn.Key, txn.ID) if c.existingTxn != nil { - if err := storage.MVCCPutProto(ctx, batch, nil, txnKey, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, c.existingTxn); err != nil { + if err := storage.MVCCPutProto(ctx, batch, txnKey, hlc.Timestamp{}, c.existingTxn, storage.MVCCWriteOptions{}); err != nil { t.Fatal(err) } } @@ -1117,13 +1117,13 @@ func TestPartialRollbackOnEndTransaction(t *testing.T) { // Write a first value at key. v.SetString("a") txn.Sequence = 1 - if err := storage.MVCCPut(ctx, batch, nil, k, ts, hlc.ClockTimestamp{}, v, &txn); err != nil { + if err := storage.MVCCPut(ctx, batch, k, ts, v, storage.MVCCWriteOptions{Txn: &txn}); err != nil { t.Fatal(err) } // Write another value. v.SetString("b") txn.Sequence = 2 - if err := storage.MVCCPut(ctx, batch, nil, k, ts, hlc.ClockTimestamp{}, v, &txn); err != nil { + if err := storage.MVCCPut(ctx, batch, k, ts, v, storage.MVCCWriteOptions{Txn: &txn}); err != nil { t.Fatal(err) } @@ -1136,7 +1136,7 @@ func TestPartialRollbackOnEndTransaction(t *testing.T) { txnKey := keys.TransactionKey(txn.Key, txn.ID) if storeTxnBeforeEndTxn { txnRec := txn.AsRecord() - if err := storage.MVCCPutProto(ctx, batch, nil, txnKey, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, &txnRec); err != nil { + if err := storage.MVCCPutProto(ctx, batch, txnKey, hlc.Timestamp{}, &txnRec, storage.MVCCWriteOptions{}); err != nil { t.Fatal(err) } } @@ -1562,7 +1562,7 @@ func TestResolveLocalLocks(t *testing.T) { txn.Status = roachpb.COMMITTED for i := 0; i < numKeys; i++ { - err := storage.MVCCPut(ctx, batch, nil, intToKey(i), ts, hlc.ClockTimestamp{}, roachpb.MakeValueFromString("a"), &txn) + err := storage.MVCCPut(ctx, batch, intToKey(i), ts, roachpb.MakeValueFromString("a"), storage.MVCCWriteOptions{Txn: &txn}) require.NoError(t, err) } resolvedLocks, externalLocks, err := resolveLocalLocksWithPagination( diff --git a/pkg/kv/kvserver/batcheval/cmd_export_test.go b/pkg/kv/kvserver/batcheval/cmd_export_test.go index 87754c46a133..65fb7a7e54b7 100644 --- a/pkg/kv/kvserver/batcheval/cmd_export_test.go +++ b/pkg/kv/kvserver/batcheval/cmd_export_test.go @@ -808,7 +808,7 @@ func TestRandomKeyAndTimestampExport(t *testing.T) { valueSize := randutil.RandIntInRange(rnd, averageValueSize-100, averageValueSize+100) value := roachpb.MakeValueFromBytes(randutil.RandBytes(rnd, valueSize)) value.InitChecksum(key) - if err := storage.MVCCPut(ctx, batch, nil, key, ts, hlc.ClockTimestamp{}, value, nil); err != nil { + if err := storage.MVCCPut(ctx, batch, key, ts, value, storage.MVCCWriteOptions{}); err != nil { t.Fatal(err) } @@ -819,7 +819,7 @@ func TestRandomKeyAndTimestampExport(t *testing.T) { ts = hlc.Timestamp{WallTime: int64(curWallTime), Logical: int32(curLogical)} value = roachpb.MakeValueFromBytes(randutil.RandBytes(rnd, 200)) value.InitChecksum(key) - if err := storage.MVCCPut(ctx, batch, nil, key, ts, hlc.ClockTimestamp{}, value, nil); err != nil { + if err := storage.MVCCPut(ctx, batch, key, ts, value, storage.MVCCWriteOptions{}); err != nil { t.Fatal(err) } } diff --git a/pkg/kv/kvserver/batcheval/cmd_heartbeat_txn.go b/pkg/kv/kvserver/batcheval/cmd_heartbeat_txn.go index c0f9dc8d9680..eea2d8132c83 100644 --- a/pkg/kv/kvserver/batcheval/cmd_heartbeat_txn.go +++ b/pkg/kv/kvserver/batcheval/cmd_heartbeat_txn.go @@ -91,7 +91,7 @@ func HeartbeatTxn( // is up for debate. txn.LastHeartbeat.Forward(args.Now) txnRecord := txn.AsRecord() - if err := storage.MVCCPutProto(ctx, readWriter, cArgs.Stats, key, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, &txnRecord); err != nil { + if err := storage.MVCCPutProto(ctx, readWriter, key, hlc.Timestamp{}, &txnRecord, storage.MVCCWriteOptions{Stats: cArgs.Stats}); err != nil { return result.Result{}, err } } diff --git a/pkg/kv/kvserver/batcheval/cmd_increment.go b/pkg/kv/kvserver/batcheval/cmd_increment.go index 210552c80362..a78bba7fa61a 100644 --- a/pkg/kv/kvserver/batcheval/cmd_increment.go +++ b/pkg/kv/kvserver/batcheval/cmd_increment.go @@ -32,8 +32,14 @@ func Increment( h := cArgs.Header reply := resp.(*kvpb.IncrementResponse) + opts := storage.MVCCWriteOptions{ + Txn: h.Txn, + LocalTimestamp: cArgs.Now, + Stats: cArgs.Stats, + } + newVal, err := storage.MVCCIncrement( - ctx, readWriter, cArgs.Stats, args.Key, h.Timestamp, cArgs.Now, h.Txn, args.Increment) + ctx, readWriter, args.Key, h.Timestamp, opts, args.Increment) reply.NewValue = newVal // NB: even if MVCC returns an error, it may still have written an intent // into the batch. This allows callers to consume errors like WriteTooOld diff --git a/pkg/kv/kvserver/batcheval/cmd_init_put.go b/pkg/kv/kvserver/batcheval/cmd_init_put.go index 64c0e7f9cbfd..0c93b15ecaa6 100644 --- a/pkg/kv/kvserver/batcheval/cmd_init_put.go +++ b/pkg/kv/kvserver/batcheval/cmd_init_put.go @@ -36,13 +36,19 @@ func InitPut( args.FailOnTombstones = false } + opts := storage.MVCCWriteOptions{ + Txn: h.Txn, + LocalTimestamp: cArgs.Now, + Stats: cArgs.Stats, + } + var err error if args.Blind { err = storage.MVCCBlindInitPut( - ctx, readWriter, cArgs.Stats, args.Key, h.Timestamp, cArgs.Now, args.Value, args.FailOnTombstones, h.Txn) + ctx, readWriter, args.Key, h.Timestamp, args.Value, args.FailOnTombstones, opts) } else { err = storage.MVCCInitPut( - ctx, readWriter, cArgs.Stats, args.Key, h.Timestamp, cArgs.Now, args.Value, args.FailOnTombstones, h.Txn) + ctx, readWriter, args.Key, h.Timestamp, args.Value, args.FailOnTombstones, opts) } // NB: even if MVCC returns an error, it may still have written an intent // into the batch. This allows callers to consume errors like WriteTooOld diff --git a/pkg/kv/kvserver/batcheval/cmd_push_txn.go b/pkg/kv/kvserver/batcheval/cmd_push_txn.go index 56d76aaf05d3..fc9ad00c79b9 100644 --- a/pkg/kv/kvserver/batcheval/cmd_push_txn.go +++ b/pkg/kv/kvserver/batcheval/cmd_push_txn.go @@ -312,7 +312,7 @@ func PushTxn( // in the timestamp cache. if ok { txnRecord := reply.PusheeTxn.AsRecord() - if err := storage.MVCCPutProto(ctx, readWriter, cArgs.Stats, key, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, &txnRecord); err != nil { + if err := storage.MVCCPutProto(ctx, readWriter, key, hlc.Timestamp{}, &txnRecord, storage.MVCCWriteOptions{Stats: cArgs.Stats}); err != nil { return result.Result{}, err } } @@ -333,7 +333,7 @@ func PushTxn( // TODO(nvanbenschoten): remove this logic in v23.2. if ok && !cArgs.EvalCtx.ClusterSettings().Version.IsActive(ctx, clusterversion.V23_1) { txnRecord := reply.PusheeTxn.AsRecord() - if err := storage.MVCCPutProto(ctx, readWriter, cArgs.Stats, key, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, &txnRecord); err != nil { + if err := storage.MVCCPutProto(ctx, readWriter, key, hlc.Timestamp{}, &txnRecord, storage.MVCCWriteOptions{Stats: cArgs.Stats}); err != nil { return result.Result{}, err } } diff --git a/pkg/kv/kvserver/batcheval/cmd_put.go b/pkg/kv/kvserver/batcheval/cmd_put.go index df0074119039..56c4cb74724f 100644 --- a/pkg/kv/kvserver/batcheval/cmd_put.go +++ b/pkg/kv/kvserver/batcheval/cmd_put.go @@ -46,17 +46,23 @@ func Put( ) (result.Result, error) { args := cArgs.Args.(*kvpb.PutRequest) h := cArgs.Header - ms := cArgs.Stats var ts hlc.Timestamp if !args.Inline { ts = h.Timestamp } + + opts := storage.MVCCWriteOptions{ + Txn: h.Txn, + LocalTimestamp: cArgs.Now, + Stats: cArgs.Stats, + } + var err error if args.Blind { - err = storage.MVCCBlindPut(ctx, readWriter, ms, args.Key, ts, cArgs.Now, args.Value, h.Txn) + err = storage.MVCCBlindPut(ctx, readWriter, args.Key, ts, args.Value, opts) } else { - err = storage.MVCCPut(ctx, readWriter, ms, args.Key, ts, cArgs.Now, args.Value, h.Txn) + err = storage.MVCCPut(ctx, readWriter, args.Key, ts, args.Value, opts) } // NB: even if MVCC returns an error, it may still have written an intent // into the batch. This allows callers to consume errors like WriteTooOld diff --git a/pkg/kv/kvserver/batcheval/cmd_query_intent_test.go b/pkg/kv/kvserver/batcheval/cmd_query_intent_test.go index 534894fc3b8b..962952041316 100644 --- a/pkg/kv/kvserver/batcheval/cmd_query_intent_test.go +++ b/pkg/kv/kvserver/batcheval/cmd_query_intent_test.go @@ -40,7 +40,7 @@ func TestQueryIntent(t *testing.T) { writeIntent := func(k roachpb.Key, ts int64) roachpb.Transaction { txn := roachpb.MakeTransaction("test", k, 0, makeTS(ts), 0, 1) - _, err := storage.MVCCDelete(ctx, db, nil, k, makeTS(ts), hlc.ClockTimestamp{}, &txn) + _, err := storage.MVCCDelete(ctx, db, k, makeTS(ts), storage.MVCCWriteOptions{Txn: &txn}) require.NoError(t, err) return txn } diff --git a/pkg/kv/kvserver/batcheval/cmd_query_resolved_timestamp_test.go b/pkg/kv/kvserver/batcheval/cmd_query_resolved_timestamp_test.go index 1063061aabc3..3db7e0c0da5f 100644 --- a/pkg/kv/kvserver/batcheval/cmd_query_resolved_timestamp_test.go +++ b/pkg/kv/kvserver/batcheval/cmd_query_resolved_timestamp_test.go @@ -44,16 +44,16 @@ func TestQueryResolvedTimestamp(t *testing.T) { return hlc.Timestamp{WallTime: ts} } writeValue := func(k string, ts int64) { - _, err := storage.MVCCDelete(ctx, db, nil, roachpb.Key(k), makeTS(ts), hlc.ClockTimestamp{}, nil) + _, err := storage.MVCCDelete(ctx, db, roachpb.Key(k), makeTS(ts), storage.MVCCWriteOptions{}) require.NoError(t, err) } writeIntent := func(k string, ts int64) { txn := roachpb.MakeTransaction("test", roachpb.Key(k), 0, makeTS(ts), 0, 1) - _, err := storage.MVCCDelete(ctx, db, nil, roachpb.Key(k), makeTS(ts), hlc.ClockTimestamp{}, &txn) + _, err := storage.MVCCDelete(ctx, db, roachpb.Key(k), makeTS(ts), storage.MVCCWriteOptions{Txn: &txn}) require.NoError(t, err) } writeInline := func(k string) { - _, err := storage.MVCCDelete(ctx, db, nil, roachpb.Key(k), hlc.Timestamp{}, hlc.ClockTimestamp{}, nil) + _, err := storage.MVCCDelete(ctx, db, roachpb.Key(k), hlc.Timestamp{}, storage.MVCCWriteOptions{}) require.NoError(t, err) } diff --git a/pkg/kv/kvserver/batcheval/cmd_recover_txn.go b/pkg/kv/kvserver/batcheval/cmd_recover_txn.go index e6900c4cbfe2..0321f2a675ab 100644 --- a/pkg/kv/kvserver/batcheval/cmd_recover_txn.go +++ b/pkg/kv/kvserver/batcheval/cmd_recover_txn.go @@ -217,7 +217,7 @@ func RecoverTxn( reply.RecoveredTxn.Status = roachpb.ABORTED } txnRecord := reply.RecoveredTxn.AsRecord() - if err := storage.MVCCPutProto(ctx, readWriter, cArgs.Stats, key, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, &txnRecord); err != nil { + if err := storage.MVCCPutProto(ctx, readWriter, key, hlc.Timestamp{}, &txnRecord, storage.MVCCWriteOptions{Stats: cArgs.Stats}); err != nil { return result.Result{}, err } diff --git a/pkg/kv/kvserver/batcheval/cmd_recover_txn_test.go b/pkg/kv/kvserver/batcheval/cmd_recover_txn_test.go index 76222776f57c..7cfc01fd459d 100644 --- a/pkg/kv/kvserver/batcheval/cmd_recover_txn_test.go +++ b/pkg/kv/kvserver/batcheval/cmd_recover_txn_test.go @@ -49,7 +49,7 @@ func TestRecoverTxn(t *testing.T) { // Write the transaction record. txnKey := keys.TransactionKey(txn.Key, txn.ID) txnRecord := txn.AsRecord() - if err := storage.MVCCPutProto(ctx, db, nil, txnKey, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, &txnRecord); err != nil { + if err := storage.MVCCPutProto(ctx, db, txnKey, hlc.Timestamp{}, &txnRecord, storage.MVCCWriteOptions{}); err != nil { t.Fatal(err) } @@ -225,7 +225,7 @@ func TestRecoverTxnRecordChanged(t *testing.T) { // request is evaluated. txnKey := keys.TransactionKey(txn.Key, txn.ID) txnRecord := c.changedTxn.AsRecord() - if err := storage.MVCCPutProto(ctx, db, nil, txnKey, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, &txnRecord); err != nil { + if err := storage.MVCCPutProto(ctx, db, txnKey, hlc.Timestamp{}, &txnRecord, storage.MVCCWriteOptions{}); err != nil { t.Fatal(err) } diff --git a/pkg/kv/kvserver/batcheval/cmd_refresh_range_bench_test.go b/pkg/kv/kvserver/batcheval/cmd_refresh_range_bench_test.go index e37720a63f9d..6a24512872fd 100644 --- a/pkg/kv/kvserver/batcheval/cmd_refresh_range_bench_test.go +++ b/pkg/kv/kvserver/batcheval/cmd_refresh_range_bench_test.go @@ -270,7 +270,7 @@ func setupData( value := roachpb.MakeValueFromBytes(randutil.RandBytes(rng, opts.valueBytes)) value.InitChecksum(key) ts := hlc.Timestamp{WallTime: int64((pos + 1) * 5)} - if err := storage.MVCCPut(ctx, batch, nil /* ms */, key, ts, hlc.ClockTimestamp{}, value, nil); err != nil { + if err := storage.MVCCPut(ctx, batch, key, ts, value, storage.MVCCWriteOptions{}); err != nil { b.Fatal(err) } } diff --git a/pkg/kv/kvserver/batcheval/cmd_refresh_range_test.go b/pkg/kv/kvserver/batcheval/cmd_refresh_range_test.go index ff59fe5f9dd7..494bfff5346c 100644 --- a/pkg/kv/kvserver/batcheval/cmd_refresh_range_test.go +++ b/pkg/kv/kvserver/batcheval/cmd_refresh_range_test.go @@ -39,9 +39,9 @@ func TestRefreshRange(t *testing.T) { // Write an MVCC point key at b@3, MVCC point tombstone at b@5, and MVCC range // tombstone at [d-f)@7. require.NoError(t, storage.MVCCPut( - ctx, eng, nil, roachpb.Key("b"), hlc.Timestamp{WallTime: 3}, hlc.ClockTimestamp{}, roachpb.MakeValueFromString("value"), nil)) + ctx, eng, roachpb.Key("b"), hlc.Timestamp{WallTime: 3}, roachpb.MakeValueFromString("value"), storage.MVCCWriteOptions{})) require.NoError(t, storage.MVCCPut( - ctx, eng, nil, roachpb.Key("c"), hlc.Timestamp{WallTime: 5}, hlc.ClockTimestamp{}, roachpb.Value{}, nil)) + ctx, eng, roachpb.Key("c"), hlc.Timestamp{WallTime: 5}, roachpb.Value{}, storage.MVCCWriteOptions{})) require.NoError(t, storage.MVCCDeleteRangeUsingTombstone( ctx, eng, nil, roachpb.Key("d"), roachpb.Key("f"), hlc.Timestamp{WallTime: 7}, hlc.ClockTimestamp{}, nil, nil, false, 0, nil)) @@ -155,10 +155,10 @@ func TestRefreshRangeTimeBoundIterator(t *testing.T) { }, ReadTimestamp: ts1, } - if err := storage.MVCCPut(ctx, db, nil, k, txn.ReadTimestamp, hlc.ClockTimestamp{}, v, txn); err != nil { + if err := storage.MVCCPut(ctx, db, k, txn.ReadTimestamp, v, storage.MVCCWriteOptions{Txn: txn}); err != nil { t.Fatal(err) } - if err := storage.MVCCPut(ctx, db, nil, roachpb.Key("unused1"), ts4, hlc.ClockTimestamp{}, v, nil); err != nil { + if err := storage.MVCCPut(ctx, db, roachpb.Key("unused1"), ts4, v, storage.MVCCWriteOptions{}); err != nil { t.Fatal(err) } if err := db.Flush(); err != nil { @@ -177,7 +177,7 @@ func TestRefreshRangeTimeBoundIterator(t *testing.T) { if _, _, _, err := storage.MVCCResolveWriteIntent(ctx, db, nil, intent, storage.MVCCResolveWriteIntentOptions{}); err != nil { t.Fatal(err) } - if err := storage.MVCCPut(ctx, db, nil, roachpb.Key("unused2"), ts1, hlc.ClockTimestamp{}, v, nil); err != nil { + if err := storage.MVCCPut(ctx, db, roachpb.Key("unused2"), ts1, v, storage.MVCCWriteOptions{}); err != nil { t.Fatal(err) } if err := db.Flush(); err != nil { @@ -266,7 +266,7 @@ func TestRefreshRangeError(t *testing.T) { }, ReadTimestamp: ts2, } - if err := storage.MVCCPut(ctx, db, nil, k, txn.ReadTimestamp, hlc.ClockTimestamp{}, v, txn); err != nil { + if err := storage.MVCCPut(ctx, db, k, txn.ReadTimestamp, v, storage.MVCCWriteOptions{Txn: txn}); err != nil { t.Fatal(err) } diff --git a/pkg/kv/kvserver/batcheval/cmd_refresh_test.go b/pkg/kv/kvserver/batcheval/cmd_refresh_test.go index 808f43bf2856..b94c73931608 100644 --- a/pkg/kv/kvserver/batcheval/cmd_refresh_test.go +++ b/pkg/kv/kvserver/batcheval/cmd_refresh_test.go @@ -60,7 +60,7 @@ func TestRefreshError(t *testing.T) { }, ReadTimestamp: ts2, } - if err := storage.MVCCPut(ctx, db, nil, k, txn.ReadTimestamp, hlc.ClockTimestamp{}, v, txn); err != nil { + if err := storage.MVCCPut(ctx, db, k, txn.ReadTimestamp, v, storage.MVCCWriteOptions{Txn: txn}); err != nil { t.Fatal(err) } @@ -121,7 +121,7 @@ func TestRefreshTimestampBounds(t *testing.T) { ts3 := hlc.Timestamp{WallTime: 3} // Write to a key at time ts2. - require.NoError(t, storage.MVCCPut(ctx, db, nil, k, ts2, hlc.ClockTimestamp{}, v, nil)) + require.NoError(t, storage.MVCCPut(ctx, db, k, ts2, v, storage.MVCCWriteOptions{})) for _, tc := range []struct { from, to hlc.Timestamp diff --git a/pkg/kv/kvserver/batcheval/cmd_resolve_intent_test.go b/pkg/kv/kvserver/batcheval/cmd_resolve_intent_test.go index 09984c9b6890..bba776fc281d 100644 --- a/pkg/kv/kvserver/batcheval/cmd_resolve_intent_test.go +++ b/pkg/kv/kvserver/batcheval/cmd_resolve_intent_test.go @@ -168,13 +168,13 @@ func TestResolveIntentAfterPartialRollback(t *testing.T) { // Write a first value at key. v.SetString("a") txn.Sequence = 0 - if err := storage.MVCCPut(ctx, batch, nil, k, ts, hlc.ClockTimestamp{}, v, &txn); err != nil { + if err := storage.MVCCPut(ctx, batch, k, ts, v, storage.MVCCWriteOptions{Txn: &txn}); err != nil { t.Fatal(err) } // Write another value. v.SetString("b") txn.Sequence = 1 - if err := storage.MVCCPut(ctx, batch, nil, k, ts, hlc.ClockTimestamp{}, v, &txn); err != nil { + if err := storage.MVCCPut(ctx, batch, k, ts, v, storage.MVCCWriteOptions{Txn: &txn}); err != nil { t.Fatal(err) } if err := batch.Commit(true); err != nil { @@ -304,7 +304,7 @@ func TestResolveIntentWithTargetBytes(t *testing.T) { st := makeClusterSettingsUsingEngineIntentsSetting(db) for i, testKey := range testKeys { - err := storage.MVCCPut(ctx, batch, nil, testKey, ts, hlc.ClockTimestamp{}, values[i], &txn) + err := storage.MVCCPut(ctx, batch, testKey, ts, values[i], storage.MVCCWriteOptions{Txn: &txn}) require.NoError(t, err) } initialBytes := batch.Len() diff --git a/pkg/kv/kvserver/batcheval/cmd_revert_range_test.go b/pkg/kv/kvserver/batcheval/cmd_revert_range_test.go index 13d808987a82..756e4fea4671 100644 --- a/pkg/kv/kvserver/batcheval/cmd_revert_range_test.go +++ b/pkg/kv/kvserver/batcheval/cmd_revert_range_test.go @@ -68,7 +68,7 @@ func TestCmdRevertRange(t *testing.T) { key := roachpb.Key(fmt.Sprintf("%04d", i)) var value roachpb.Value value.SetString(fmt.Sprintf("%d", i)) - if err := storage.MVCCPut(ctx, eng, &stats, key, baseTime.Add(int64(i%10), 0), hlc.ClockTimestamp{}, value, nil); err != nil { + if err := storage.MVCCPut(ctx, eng, key, baseTime.Add(int64(i%10), 0), value, storage.MVCCWriteOptions{Stats: &stats}); err != nil { t.Fatal(err) } } @@ -82,7 +82,7 @@ func TestCmdRevertRange(t *testing.T) { key := roachpb.Key(fmt.Sprintf("%04d", i)) var value roachpb.Value value.SetString(fmt.Sprintf("%d-rev-a", i)) - if err := storage.MVCCPut(ctx, eng, &stats, key, tsA.Add(int64(i%5), 1), hlc.ClockTimestamp{}, value, nil); err != nil { + if err := storage.MVCCPut(ctx, eng, key, tsA.Add(int64(i%5), 1), value, storage.MVCCWriteOptions{Stats: &stats}); err != nil { t.Fatal(err) } } @@ -95,7 +95,7 @@ func TestCmdRevertRange(t *testing.T) { key := roachpb.Key(fmt.Sprintf("%04d", i)) var value roachpb.Value value.SetString(fmt.Sprintf("%d-rev-b", i)) - if err := storage.MVCCPut(ctx, eng, &stats, key, tsB.Add(1, int32(i%5)), hlc.ClockTimestamp{}, value, nil); err != nil { + if err := storage.MVCCPut(ctx, eng, key, tsB.Add(1, int32(i%5)), value, storage.MVCCWriteOptions{Stats: &stats}); err != nil { t.Fatal(err) } } @@ -168,7 +168,7 @@ func TestCmdRevertRange(t *testing.T) { txn := roachpb.MakeTransaction("test", nil, roachpb.NormalUserPriority, tsC, 1, 1) if err := storage.MVCCPut( - ctx, eng, &stats, []byte("0012"), tsC, hlc.ClockTimestamp{}, roachpb.MakeValueFromBytes([]byte("i")), &txn, + ctx, eng, []byte("0012"), tsC, roachpb.MakeValueFromBytes([]byte("i")), storage.MVCCWriteOptions{Txn: &txn, Stats: &stats}, ); err != nil { t.Fatal(err) } @@ -179,7 +179,7 @@ func TestCmdRevertRange(t *testing.T) { key := roachpb.Key(fmt.Sprintf("%04d", i)) var value roachpb.Value value.SetString(fmt.Sprintf("%d-rev-b", i)) - if err := storage.MVCCPut(ctx, eng, &stats, key, tsC.Add(10, int32(i%5)), hlc.ClockTimestamp{}, value, nil); err != nil { + if err := storage.MVCCPut(ctx, eng, key, tsC.Add(10, int32(i%5)), value, storage.MVCCWriteOptions{Stats: &stats}); err != nil { t.Fatalf("writing key %s: %+v", key, err) } } diff --git a/pkg/kv/kvserver/batcheval/cmd_scan_test.go b/pkg/kv/kvserver/batcheval/cmd_scan_test.go index eb3c594fe8bd..4cb31e773f42 100644 --- a/pkg/kv/kvserver/batcheval/cmd_scan_test.go +++ b/pkg/kv/kvserver/batcheval/cmd_scan_test.go @@ -88,7 +88,7 @@ func testScanReverseScanInner( // Write to k1 and k2. for _, k := range []roachpb.Key{k1, k2} { - err := storage.MVCCPut(ctx, eng, nil, k, ts, hlc.ClockTimestamp{}, roachpb.MakeValueFromString("value-"+string(k)), nil) + err := storage.MVCCPut(ctx, eng, k, ts, roachpb.MakeValueFromString("value-"+string(k)), storage.MVCCWriteOptions{}) require.NoError(t, err) } @@ -185,7 +185,7 @@ func TestScanReverseScanWholeRows(t *testing.T) { for r := 0; r < 2; r++ { for cf := uint32(0); cf < 3; cf++ { key := makeRowKey(t, r, cf) - err := storage.MVCCPut(ctx, eng, nil, key, ts, hlc.ClockTimestamp{}, roachpb.MakeValueFromString("value"), nil) + err := storage.MVCCPut(ctx, eng, key, ts, roachpb.MakeValueFromString("value"), storage.MVCCWriteOptions{}) require.NoError(t, err) rowKeys = append(rowKeys, key) } diff --git a/pkg/kv/kvserver/batcheval/cmd_truncate_log_test.go b/pkg/kv/kvserver/batcheval/cmd_truncate_log_test.go index 89bee9807284..52f3686b0264 100644 --- a/pkg/kv/kvserver/batcheval/cmd_truncate_log_test.go +++ b/pkg/kv/kvserver/batcheval/cmd_truncate_log_test.go @@ -31,8 +31,8 @@ func putTruncatedState( ) { key := keys.RaftTruncatedStateKey(rangeID) if err := storage.MVCCPutProto( - context.Background(), eng, nil, key, - hlc.Timestamp{}, hlc.ClockTimestamp{}, nil /* txn */, &truncState, + context.Background(), eng, key, + hlc.Timestamp{}, &truncState, storage.MVCCWriteOptions{}, ); err != nil { t.Fatal(err) } diff --git a/pkg/kv/kvserver/batcheval/intent_test.go b/pkg/kv/kvserver/batcheval/intent_test.go index 6dd2c9128237..798b38367d74 100644 --- a/pkg/kv/kvserver/batcheval/intent_test.go +++ b/pkg/kv/kvserver/batcheval/intent_test.go @@ -130,9 +130,9 @@ func TestCollectIntentsUsesSameIterator(t *testing.T) { txn := roachpb.MakeTransaction("test", key, roachpb.NormalUserPriority, ts, 0, 1) var err error if delete { - _, err = storage.MVCCDelete(ctx, db, nil, key, ts, hlc.ClockTimestamp{}, &txn) + _, err = storage.MVCCDelete(ctx, db, key, ts, storage.MVCCWriteOptions{Txn: &txn}) } else { - err = storage.MVCCPut(ctx, db, nil, key, ts, hlc.ClockTimestamp{}, val, &txn) + err = storage.MVCCPut(ctx, db, key, ts, val, storage.MVCCWriteOptions{Txn: &txn}) } require.NoError(t, err) diff --git a/pkg/kv/kvserver/batcheval/transaction_test.go b/pkg/kv/kvserver/batcheval/transaction_test.go index 273cd98d5ff5..e02f25b530cf 100644 --- a/pkg/kv/kvserver/batcheval/transaction_test.go +++ b/pkg/kv/kvserver/batcheval/transaction_test.go @@ -85,7 +85,7 @@ func TestUpdateAbortSpan(t *testing.T) { type evalFn func(storage.ReadWriter, EvalContext, *enginepb.MVCCStats) error addIntent := func(b storage.ReadWriter, _ EvalContext, ms *enginepb.MVCCStats) error { val := roachpb.MakeValueFromString("val") - return storage.MVCCPut(ctx, b, ms, intentKey, txn.ReadTimestamp, hlc.ClockTimestamp{}, val, &txn) + return storage.MVCCPut(ctx, b, intentKey, txn.ReadTimestamp, val, storage.MVCCWriteOptions{Txn: &txn, Stats: ms}) } addPrevAbortSpanEntry := func(b storage.ReadWriter, rec EvalContext, ms *enginepb.MVCCStats) error { return UpdateAbortSpan(ctx, rec, b, ms, prevTxn.TxnMeta, true /* poison */) diff --git a/pkg/kv/kvserver/client_merge_test.go b/pkg/kv/kvserver/client_merge_test.go index 7a1b86c36bad..2cb96e5346ce 100644 --- a/pkg/kv/kvserver/client_merge_test.go +++ b/pkg/kv/kvserver/client_merge_test.go @@ -3888,7 +3888,7 @@ func TestStoreRangeMergeRaftSnapshot(t *testing.T) { tombstoneKey := keys.RangeTombstoneKey(rangeID) tombstoneValue := &roachpb.RangeTombstone{NextReplicaID: math.MaxInt32} if err := storage.MVCCBlindPutProto( - context.Background(), &sst, nil, tombstoneKey, hlc.Timestamp{}, hlc.ClockTimestamp{}, tombstoneValue, nil, + context.Background(), &sst, tombstoneKey, hlc.Timestamp{}, tombstoneValue, storage.MVCCWriteOptions{}, ); err != nil { return err } diff --git a/pkg/kv/kvserver/consistency_queue_test.go b/pkg/kv/kvserver/consistency_queue_test.go index 609dc55318ed..8019bd27fd32 100644 --- a/pkg/kv/kvserver/consistency_queue_test.go +++ b/pkg/kv/kvserver/consistency_queue_test.go @@ -344,8 +344,8 @@ func TestCheckConsistencyInconsistent(t *testing.T) { var val roachpb.Value val.SetInt(42) // Put an inconsistent key "e" to s2, and have s1 and s3 still agree. - require.NoError(t, storage.MVCCPut(context.Background(), s2.TODOEngine(), nil, - roachpb.Key("e"), tc.Server(0).Clock().Now(), hlc.ClockTimestamp{}, val, nil)) + require.NoError(t, storage.MVCCPut(context.Background(), s2.TODOEngine(), + roachpb.Key("e"), tc.Server(0).Clock().Now(), val, storage.MVCCWriteOptions{})) // Run consistency check again, this time it should find something. resp = runConsistencyCheck() diff --git a/pkg/kv/kvserver/gc/data_distribution_test.go b/pkg/kv/kvserver/gc/data_distribution_test.go index 516e6a4f4d85..569237bb20e4 100644 --- a/pkg/kv/kvserver/gc/data_distribution_test.go +++ b/pkg/kv/kvserver/gc/data_distribution_test.go @@ -79,8 +79,8 @@ func (ds dataDistribution) setupTest( if txn.WriteTimestamp.IsEmpty() { txn.WriteTimestamp = ts } - err := storage.MVCCPut(ctx, eng, &ms, kv.Key.Key, ts, - hlc.ClockTimestamp{}, roachpb.Value{RawBytes: kv.Value}, txn) + err := storage.MVCCPut(ctx, eng, kv.Key.Key, ts, + roachpb.Value{RawBytes: kv.Value}, storage.MVCCWriteOptions{Txn: txn, Stats: &ms}) require.NoError(t, err, "failed to insert value for key %s, value length=%d", kv.Key.String(), len(kv.Value)) } diff --git a/pkg/kv/kvserver/gc/gc_test.go b/pkg/kv/kvserver/gc/gc_test.go index 0ca360bb4a2c..6ab47462c892 100644 --- a/pkg/kv/kvserver/gc/gc_test.go +++ b/pkg/kv/kvserver/gc/gc_test.go @@ -135,7 +135,7 @@ func TestIntentAgeThresholdSetting(t *testing.T) { WallTime: intentTs.Nanoseconds(), } txn := roachpb.MakeTransaction("txn", key, roachpb.NormalUserPriority, intentHlc, 1000, 0) - require.NoError(t, storage.MVCCPut(ctx, eng, nil, key, intentHlc, hlc.ClockTimestamp{}, value, &txn)) + require.NoError(t, storage.MVCCPut(ctx, eng, key, intentHlc, value, storage.MVCCWriteOptions{Txn: &txn})) require.NoError(t, eng.Flush()) // Prepare test fixtures for GC run. @@ -196,7 +196,7 @@ func TestIntentCleanupBatching(t *testing.T) { txn := roachpb.MakeTransaction("txn", key, roachpb.NormalUserPriority, intentHlc, 1000, 0) for _, suffix := range objectKeys { key := []byte{prefix, suffix} - require.NoError(t, storage.MVCCPut(ctx, eng, nil, key, intentHlc, hlc.ClockTimestamp{}, value, &txn)) + require.NoError(t, storage.MVCCPut(ctx, eng, key, intentHlc, value, storage.MVCCWriteOptions{Txn: &txn})) } require.NoError(t, eng.Flush()) } diff --git a/pkg/kv/kvserver/kvstorage/cluster_version.go b/pkg/kv/kvserver/kvstorage/cluster_version.go index 36d37964c9a9..c5a02b43546d 100644 --- a/pkg/kv/kvserver/kvstorage/cluster_version.go +++ b/pkg/kv/kvserver/kvstorage/cluster_version.go @@ -35,12 +35,10 @@ func WriteClusterVersion( if err := storage.MVCCPutProto( ctx, eng, - nil, keys.DeprecatedStoreClusterVersionKey(), hlc.Timestamp{}, - hlc.ClockTimestamp{}, - nil, &cv, + storage.MVCCWriteOptions{}, ); err != nil { return err } diff --git a/pkg/kv/kvserver/kvstorage/destroy.go b/pkg/kv/kvserver/kvstorage/destroy.go index d6506eaf099e..5cf2b37f4fc8 100644 --- a/pkg/kv/kvserver/kvstorage/destroy.go +++ b/pkg/kv/kvserver/kvstorage/destroy.go @@ -147,6 +147,6 @@ func DestroyReplica( tombstone := roachpb.RangeTombstone{NextReplicaID: nextReplicaID} // "Blind" because ms == nil and timestamp.IsEmpty(). - return storage.MVCCBlindPutProto(ctx, writer, nil, tombstoneKey, - hlc.Timestamp{}, hlc.ClockTimestamp{}, &tombstone, nil) + return storage.MVCCBlindPutProto(ctx, writer, tombstoneKey, + hlc.Timestamp{}, &tombstone, storage.MVCCWriteOptions{}) } diff --git a/pkg/kv/kvserver/kvstorage/init.go b/pkg/kv/kvserver/kvstorage/init.go index 8efae251150e..b1e30b86e63e 100644 --- a/pkg/kv/kvserver/kvstorage/init.go +++ b/pkg/kv/kvserver/kvstorage/init.go @@ -62,12 +62,10 @@ func InitEngine(ctx context.Context, eng storage.Engine, ident roachpb.StoreIden if err := storage.MVCCPutProto( ctx, batch, - nil, keys.StoreIdentKey(), hlc.Timestamp{}, - hlc.ClockTimestamp{}, - nil, &ident, + storage.MVCCWriteOptions{}, ); err != nil { batch.Close() return err diff --git a/pkg/kv/kvserver/logstore/logstore.go b/pkg/kv/kvserver/logstore/logstore.go index f20f2b80e8e0..3d989605ba37 100644 --- a/pkg/kv/kvserver/logstore/logstore.go +++ b/pkg/kv/kvserver/logstore/logstore.go @@ -379,6 +379,9 @@ func logAppend( return prev, nil } var diff enginepb.MVCCStats + opts := storage.MVCCWriteOptions{ + Stats: &diff, + } value := valPool.Get().(*roachpb.Value) value.RawBytes = value.RawBytes[:0] defer valPool.Put(value) @@ -392,9 +395,9 @@ func logAppend( value.InitChecksum(key) var err error if ent.Index > prev.LastIndex { - err = storage.MVCCBlindPut(ctx, rw, &diff, key, hlc.Timestamp{}, hlc.ClockTimestamp{}, *value, nil /* txn */) + err = storage.MVCCBlindPut(ctx, rw, key, hlc.Timestamp{}, *value, opts) } else { - err = storage.MVCCPut(ctx, rw, &diff, key, hlc.Timestamp{}, hlc.ClockTimestamp{}, *value, nil /* txn */) + err = storage.MVCCPut(ctx, rw, key, hlc.Timestamp{}, *value, opts) } if err != nil { return RaftState{}, err @@ -407,8 +410,8 @@ func logAppend( for i := newLastIndex + 1; i <= prev.LastIndex; i++ { // Note that the caller is in charge of deleting any sideloaded payloads // (which they must only do *after* the batch has committed). - _, err := storage.MVCCDelete(ctx, rw, &diff, keys.RaftLogKeyFromPrefix(raftLogPrefix, i), - hlc.Timestamp{}, hlc.ClockTimestamp{}, nil) + _, err := storage.MVCCDelete(ctx, rw, keys.RaftLogKeyFromPrefix(raftLogPrefix, i), + hlc.Timestamp{}, opts) if err != nil { return RaftState{}, err } diff --git a/pkg/kv/kvserver/logstore/stateloader.go b/pkg/kv/kvserver/logstore/stateloader.go index e36ca0639208..4f98f7451913 100644 --- a/pkg/kv/kvserver/logstore/stateloader.go +++ b/pkg/kv/kvserver/logstore/stateloader.go @@ -103,16 +103,14 @@ func (sl StateLoader) SetRaftTruncatedState( if (*truncState == roachpb.RaftTruncatedState{}) { return errors.New("cannot persist empty RaftTruncatedState") } - // "Blind" because ms == nil and timestamp.IsEmpty(). + // "Blind" because opts.Stats == nil and timestamp.IsEmpty(). return storage.MVCCBlindPutProto( ctx, writer, - nil, /* ms */ sl.RaftTruncatedStateKey(), - hlc.Timestamp{}, /* timestamp */ - hlc.ClockTimestamp{}, /* localTimestamp */ + hlc.Timestamp{}, /* timestamp */ truncState, - nil, /* txn */ + storage.MVCCWriteOptions{}, /* txn */ ) } @@ -134,16 +132,14 @@ func (sl StateLoader) LoadHardState( func (sl StateLoader) SetHardState( ctx context.Context, writer storage.Writer, hs raftpb.HardState, ) error { - // "Blind" because ms == nil and timestamp.IsEmpty(). + // "Blind" because opts.Stats == nil and timestamp.IsEmpty(). return storage.MVCCBlindPutProto( ctx, writer, - nil, /* ms */ sl.RaftHardStateKey(), - hlc.Timestamp{}, /* timestamp */ - hlc.ClockTimestamp{}, /* localTimestamp */ + hlc.Timestamp{}, /* timestamp */ &hs, - nil, /* txn */ + storage.MVCCWriteOptions{}, /* opts */ ) } @@ -191,12 +187,10 @@ func (sl StateLoader) SetRaftReplicaID( return storage.MVCCBlindPutProto( ctx, writer, - nil, /* ms */ sl.RaftReplicaIDKey(), - hlc.Timestamp{}, /* timestamp */ - hlc.ClockTimestamp{}, /* localTimestamp */ + hlc.Timestamp{}, /* timestamp */ &rid, - nil, /* txn */ + storage.MVCCWriteOptions{}, /* opts */ ) } diff --git a/pkg/kv/kvserver/loqrecovery/apply.go b/pkg/kv/kvserver/loqrecovery/apply.go index 615ea5eb8c16..37db9ef2f05d 100644 --- a/pkg/kv/kvserver/loqrecovery/apply.go +++ b/pkg/kv/kvserver/loqrecovery/apply.go @@ -266,7 +266,7 @@ func applyReplicaUpdate( // A crude form of the intent resolution process: abort the // transaction by deleting its record. txnKey := keys.TransactionKey(res.Intent.Txn.Key, res.Intent.Txn.ID) - if _, err := storage.MVCCDelete(ctx, readWriter, &ms, txnKey, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil); err != nil { + if _, err := storage.MVCCDelete(ctx, readWriter, txnKey, hlc.Timestamp{}, storage.MVCCWriteOptions{Stats: &ms}); err != nil { return PrepareReplicaReport{}, err } update := roachpb.LockUpdate{ @@ -293,8 +293,8 @@ func applyReplicaUpdate( newDesc.NextReplicaID = update.NextReplicaID if err := storage.MVCCPutProto( - ctx, readWriter, &ms, key, clock.Now(), - hlc.ClockTimestamp{}, nil /* txn */, &newDesc, + ctx, readWriter, key, clock.Now(), + &newDesc, storage.MVCCWriteOptions{Stats: &ms}, ); err != nil { return PrepareReplicaReport{}, err } diff --git a/pkg/kv/kvserver/loqrecovery/apply_test.go b/pkg/kv/kvserver/loqrecovery/apply_test.go index 0cc83adfcdce..787e137e0dd5 100644 --- a/pkg/kv/kvserver/loqrecovery/apply_test.go +++ b/pkg/kv/kvserver/loqrecovery/apply_test.go @@ -92,7 +92,7 @@ func createEngineOrFatal(ctx context.Context, t *testing.T, uuid uuid.UUID, id i StoreID: roachpb.StoreID(id), } if err = storage.MVCCPutProto( - context.Background(), eng, nil, keys.StoreIdentKey(), hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, &sIdent, + context.Background(), eng, keys.StoreIdentKey(), hlc.Timestamp{}, &sIdent, storage.MVCCWriteOptions{}, ); err != nil { t.Fatalf("failed to populate test store ident: %v", err) } diff --git a/pkg/kv/kvserver/loqrecovery/record.go b/pkg/kv/kvserver/loqrecovery/record.go index 874dfe2d3e3b..684a9521efdf 100644 --- a/pkg/kv/kvserver/loqrecovery/record.go +++ b/pkg/kv/kvserver/loqrecovery/record.go @@ -174,17 +174,17 @@ func writeNodeRecoveryResults( actions loqrecoverypb.DeferredRecoveryActions, ) error { var fullErr error - err := storage.MVCCPutProto(ctx, writer, nil, keys.StoreLossOfQuorumRecoveryStatusKey(), - hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, &result) + err := storage.MVCCPutProto(ctx, writer, keys.StoreLossOfQuorumRecoveryStatusKey(), + hlc.Timestamp{}, &result, storage.MVCCWriteOptions{}) fullErr = errors.Wrap(err, "failed to write loss of quorum recovery plan application status") if !actions.Empty() { - err = storage.MVCCPutProto(ctx, writer, nil, keys.StoreLossOfQuorumRecoveryCleanupActionsKey(), - hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, &actions) + err = storage.MVCCPutProto(ctx, writer, keys.StoreLossOfQuorumRecoveryCleanupActionsKey(), + hlc.Timestamp{}, &actions, storage.MVCCWriteOptions{}) fullErr = errors.CombineErrors(fullErr, errors.Wrap(err, "failed to write loss of quorum recovery cleanup action")) } else { - _, err = storage.MVCCDelete(ctx, writer, nil, keys.StoreLossOfQuorumRecoveryCleanupActionsKey(), - hlc.Timestamp{}, hlc.ClockTimestamp{}, nil) + _, err = storage.MVCCDelete(ctx, writer, keys.StoreLossOfQuorumRecoveryCleanupActionsKey(), + hlc.Timestamp{}, storage.MVCCWriteOptions{}) fullErr = errors.CombineErrors(fullErr, errors.Wrap(err, "failed to clean loss of quorum recovery cleanup action")) } @@ -222,7 +222,7 @@ func ReadCleanupActionsInfo( // RemoveCleanupActionsInfo removes cleanup actions info if it is present in the // reader. func RemoveCleanupActionsInfo(ctx context.Context, writer storage.ReadWriter) error { - _, err := storage.MVCCDelete(ctx, writer, nil, keys.StoreLossOfQuorumRecoveryCleanupActionsKey(), - hlc.Timestamp{}, hlc.ClockTimestamp{}, nil) + _, err := storage.MVCCDelete(ctx, writer, keys.StoreLossOfQuorumRecoveryCleanupActionsKey(), + hlc.Timestamp{}, storage.MVCCWriteOptions{}) return err } diff --git a/pkg/kv/kvserver/loqrecovery/recovery_env_test.go b/pkg/kv/kvserver/loqrecovery/recovery_env_test.go index ba219121b04b..51903280a6ac 100644 --- a/pkg/kv/kvserver/loqrecovery/recovery_env_test.go +++ b/pkg/kv/kvserver/loqrecovery/recovery_env_test.go @@ -327,7 +327,7 @@ func (e *quorumRecoveryEnv) handleReplicationData(t *testing.T, d datadriven.Tes eng := e.getOrCreateStore(ctx, t, replica.StoreID, replica.NodeID) if err = storage.MVCCPutProto( - ctx, eng, nil, key, clock.Now(), hlc.ClockTimestamp{}, nil /* txn */, &desc, + ctx, eng, key, clock.Now(), &desc, storage.MVCCWriteOptions{}, ); err != nil { t.Fatalf("failed to write range descriptor into store: %v", err) } @@ -621,7 +621,7 @@ func (e *quorumRecoveryEnv) getOrCreateStore( StoreID: storeID, } if err = storage.MVCCPutProto( - context.Background(), eng, nil, keys.StoreIdentKey(), hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, &sIdent, + context.Background(), eng, keys.StoreIdentKey(), hlc.Timestamp{}, &sIdent, storage.MVCCWriteOptions{}, ); err != nil { t.Fatalf("failed to populate test store ident: %v", err) } diff --git a/pkg/kv/kvserver/mvcc_gc_queue_test.go b/pkg/kv/kvserver/mvcc_gc_queue_test.go index 1516185c4f6a..bbcb07eaefe5 100644 --- a/pkg/kv/kvserver/mvcc_gc_queue_test.go +++ b/pkg/kv/kvserver/mvcc_gc_queue_test.go @@ -300,7 +300,11 @@ func (cws *cachedWriteSimulator) multiKey( ts := hlc.Timestamp{}.Add(ms.LastUpdateNanos, 0) key, value := []byte("multikey"), cws.value(size) var eachMS enginepb.MVCCStats - if err := storage.MVCCPut(ctx, eng, &eachMS, key, ts, hlc.ClockTimestamp{}, value, txn); err != nil { + opts := storage.MVCCWriteOptions{ + Txn: txn, + Stats: &eachMS, + } + if err := storage.MVCCPut(ctx, eng, key, ts, value, opts); err != nil { t.Fatal(err) } for i := 1; i < numOps; i++ { @@ -329,7 +333,7 @@ func (cws *cachedWriteSimulator) singleKeySteady( for i := 0; i < qps; i++ { now := initialNow.Add(elapsed.Nanoseconds(), int32(i)) - if err := storage.MVCCPut(ctx, eng, ms, key, now, hlc.ClockTimestamp{}, value, nil); err != nil { + if err := storage.MVCCPut(ctx, eng, key, now, value, storage.MVCCWriteOptions{Stats: ms}); err != nil { t.Fatal(err) } if len(firstSl) < cacheFirstLen { @@ -524,9 +528,9 @@ func TestFullRangeDeleteHeuristic(t *testing.T) { if rng.Float32() > 0.5 { value.SetBytes(make([]byte, 20)) } - require.NoError(t, storage.MVCCPut(ctx, rw, &ms, key, - hlc.Timestamp{WallTime: time.Millisecond.Nanoseconds() * int64(i)}, hlc.ClockTimestamp{}, - value, nil)) + require.NoError(t, storage.MVCCPut(ctx, rw, key, + hlc.Timestamp{WallTime: time.Millisecond.Nanoseconds() * int64(i)}, + value, storage.MVCCWriteOptions{Stats: &ms})) } return ms, hlc.Timestamp{WallTime: time.Millisecond.Nanoseconds() * int64(valCount)} } @@ -537,7 +541,7 @@ func TestFullRangeDeleteHeuristic(t *testing.T) { } deleteWithPoints := func(rw storage.ReadWriter, delTime hlc.Timestamp, ms *enginepb.MVCCStats) { for _, key := range keys { - require.NoError(t, storage.MVCCPut(ctx, rw, ms, key, delTime, hlc.ClockTimestamp{}, roachpb.Value{}, nil)) + require.NoError(t, storage.MVCCPut(ctx, rw, key, delTime, roachpb.Value{}, storage.MVCCWriteOptions{Stats: ms})) } } @@ -1127,7 +1131,7 @@ func TestMVCCGCQueueTransactionTable(t *testing.T) { txns[strKey] = *txn for _, addrKey := range []roachpb.Key{baseKey, outsideKey} { key := keys.TransactionKey(addrKey, txn.ID) - if err := storage.MVCCPutProto(ctx, tc.engine, nil, key, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, txn); err != nil { + if err := storage.MVCCPutProto(ctx, tc.engine, key, hlc.Timestamp{}, txn, storage.MVCCWriteOptions{}); err != nil { t.Fatal(err) } } @@ -1331,7 +1335,7 @@ func TestMVCCGCQueueLastProcessedTimestamps(t *testing.T) { ts := tc.Clock().Now() for _, lpv := range lastProcessedVals { - if err := storage.MVCCPutProto(ctx, tc.engine, nil, lpv.key, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, &ts); err != nil { + if err := storage.MVCCPutProto(ctx, tc.engine, lpv.key, hlc.Timestamp{}, &ts, storage.MVCCWriteOptions{}); err != nil { t.Fatal(err) } } diff --git a/pkg/kv/kvserver/rangefeed/catchup_scan_bench_test.go b/pkg/kv/kvserver/rangefeed/catchup_scan_bench_test.go index c1a76ce35221..ec1b7abbf37e 100644 --- a/pkg/kv/kvserver/rangefeed/catchup_scan_bench_test.go +++ b/pkg/kv/kvserver/rangefeed/catchup_scan_bench_test.go @@ -307,7 +307,7 @@ func setupData( value := roachpb.MakeValueFromBytes(randutil.RandBytes(rng, opts.valueBytes)) value.InitChecksum(key) ts := hlc.Timestamp{WallTime: int64((pos + 1) * 5)} - if err := storage.MVCCPut(ctx, batch, nil /* ms */, key, ts, hlc.ClockTimestamp{}, value, nil); err != nil { + if err := storage.MVCCPut(ctx, batch, key, ts, value, storage.MVCCWriteOptions{}); err != nil { b.Fatal(err) } } diff --git a/pkg/kv/kvserver/rangefeed/catchup_scan_test.go b/pkg/kv/kvserver/rangefeed/catchup_scan_test.go index dfe610273590..d71dc4cbb548 100644 --- a/pkg/kv/kvserver/rangefeed/catchup_scan_test.go +++ b/pkg/kv/kvserver/rangefeed/catchup_scan_test.go @@ -102,12 +102,12 @@ func TestCatchupScan(t *testing.T) { // Put with no intent. for _, kv := range []storage.MVCCKeyValue{kv1_1_1, kv1_2_2, kv1_3_3, kv2_1_1, kv2_2_2, kv2_5_3} { v := roachpb.Value{RawBytes: kv.Value} - if err := storage.MVCCPut(ctx, eng, nil, kv.Key.Key, kv.Key.Timestamp, hlc.ClockTimestamp{}, v, nil); err != nil { + if err := storage.MVCCPut(ctx, eng, kv.Key.Key, kv.Key.Timestamp, v, storage.MVCCWriteOptions{}); err != nil { t.Fatal(err) } } // Put with an intent. - if err := storage.MVCCPut(ctx, eng, nil, kv1_4_4.Key.Key, txn.ReadTimestamp, hlc.ClockTimestamp{}, val, &txn); err != nil { + if err := storage.MVCCPut(ctx, eng, kv1_4_4.Key.Key, txn.ReadTimestamp, val, storage.MVCCWriteOptions{Txn: &txn}); err != nil { t.Fatal(err) } testutils.RunTrueAndFalse(t, "withDiff", func(t *testing.T, withDiff bool) { @@ -151,7 +151,7 @@ func TestCatchupScanInlineError(t *testing.T) { defer eng.Close() // Write an inline value. - require.NoError(t, storage.MVCCPut(ctx, eng, nil, roachpb.Key("inline"), hlc.Timestamp{}, hlc.ClockTimestamp{}, roachpb.MakeValueFromString("foo"), nil)) + require.NoError(t, storage.MVCCPut(ctx, eng, roachpb.Key("inline"), hlc.Timestamp{}, roachpb.MakeValueFromString("foo"), storage.MVCCWriteOptions{})) // Run a catchup scan across the span and watch it error. span := roachpb.Span{Key: keys.LocalMax, EndKey: keys.MaxKey} @@ -183,15 +183,15 @@ func TestCatchupScanSeesOldIntent(t *testing.T) { tsIntent := tsCutoff.Add(-10, 0) // the intent is below the lower bound tsVersionInWindow := tsCutoff.Add(10, 0) // an unrelated version is above the lower bound - require.NoError(t, storage.MVCCPut(ctx, eng, nil, roachpb.Key("b"), - tsVersionInWindow, hlc.ClockTimestamp{}, roachpb.MakeValueFromString("foo"), nil)) + require.NoError(t, storage.MVCCPut(ctx, eng, roachpb.Key("b"), + tsVersionInWindow, roachpb.MakeValueFromString("foo"), storage.MVCCWriteOptions{})) txn := roachpb.MakeTransaction("foo", roachpb.Key("d"), roachpb.NormalUserPriority, tsIntent, 100, 0) - require.NoError(t, storage.MVCCPut(ctx, eng, nil, roachpb.Key("d"), - tsIntent, hlc.ClockTimestamp{}, roachpb.MakeValueFromString("intent"), &txn)) + require.NoError(t, storage.MVCCPut(ctx, eng, roachpb.Key("d"), + tsIntent, roachpb.MakeValueFromString("intent"), storage.MVCCWriteOptions{Txn: &txn})) - require.NoError(t, storage.MVCCPut(ctx, eng, nil, roachpb.Key("e"), - tsVersionInWindow, hlc.ClockTimestamp{}, roachpb.MakeValueFromString("bar"), nil)) + require.NoError(t, storage.MVCCPut(ctx, eng, roachpb.Key("e"), + tsVersionInWindow, roachpb.MakeValueFromString("bar"), storage.MVCCWriteOptions{})) // Run a catchup scan across the span and watch it succeed. span := roachpb.Span{Key: keys.LocalMax, EndKey: keys.MaxKey} diff --git a/pkg/kv/kvserver/rangefeed/task_test.go b/pkg/kv/kvserver/rangefeed/task_test.go index bf2f1e5a2bf5..e40d9addd9d4 100644 --- a/pkg/kv/kvserver/rangefeed/task_test.go +++ b/pkg/kv/kvserver/rangefeed/task_test.go @@ -297,7 +297,7 @@ func TestInitResolvedTSScan(t *testing.T) { } for _, op := range testData { kv := op.kv - err := storage.MVCCPut(ctx, engine, nil, kv.Key.Key, kv.Key.Timestamp, hlc.ClockTimestamp{}, roachpb.Value{RawBytes: kv.Value}, op.txn) + err := storage.MVCCPut(ctx, engine, kv.Key.Key, kv.Key.Timestamp, roachpb.Value{RawBytes: kv.Value}, storage.MVCCWriteOptions{Txn: op.txn}) require.NoError(t, err) } return engine diff --git a/pkg/kv/kvserver/rditer/replica_data_iter_test.go b/pkg/kv/kvserver/rditer/replica_data_iter_test.go index f163fcea5c09..d533b8ea564e 100644 --- a/pkg/kv/kvserver/rditer/replica_data_iter_test.go +++ b/pkg/kv/kvserver/rditer/replica_data_iter_test.go @@ -126,7 +126,7 @@ func createRangeData( }) for _, pk := range ps { - require.NoError(t, storage.MVCCPut(ctx, eng, nil, pk.Key, pk.Timestamp, localTS, value, nil)) + require.NoError(t, storage.MVCCPut(ctx, eng, pk.Key, pk.Timestamp, value, storage.MVCCWriteOptions{LocalTimestamp: localTS})) } for _, rk := range rs { require.NoError(t, eng.PutMVCCRangeKey(rk, storage.MVCCValue{})) diff --git a/pkg/kv/kvserver/readsummary/persist.go b/pkg/kv/kvserver/readsummary/persist.go index bde7509f6e33..e1f9dcd115c5 100644 --- a/pkg/kv/kvserver/readsummary/persist.go +++ b/pkg/kv/kvserver/readsummary/persist.go @@ -44,5 +44,5 @@ func Set( sum *rspb.ReadSummary, ) error { key := keys.RangePriorReadSummaryKey(rangeID) - return storage.MVCCPutProto(ctx, readWriter, ms, key, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, sum) + return storage.MVCCPutProto(ctx, readWriter, key, hlc.Timestamp{}, sum, storage.MVCCWriteOptions{Stats: ms}) } diff --git a/pkg/kv/kvserver/replica.go b/pkg/kv/kvserver/replica.go index 6f72733ed1d4..cf146d1c31db 100644 --- a/pkg/kv/kvserver/replica.go +++ b/pkg/kv/kvserver/replica.go @@ -1378,7 +1378,7 @@ func (r *Replica) GetLastReplicaGCTimestamp(ctx context.Context) (hlc.Timestamp, func (r *Replica) setLastReplicaGCTimestamp(ctx context.Context, timestamp hlc.Timestamp) error { key := keys.RangeLastReplicaGCTimestampKey(r.RangeID) return storage.MVCCPutProto( - ctx, r.store.TODOEngine(), nil, key, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, ×tamp) + ctx, r.store.TODOEngine(), key, hlc.Timestamp{}, ×tamp, storage.MVCCWriteOptions{}) } // getQueueLastProcessed returns the last processed timestamp for the diff --git a/pkg/kv/kvserver/replica_consistency_test.go b/pkg/kv/kvserver/replica_consistency_test.go index d5be211ce6f7..7857c1a30d4c 100644 --- a/pkg/kv/kvserver/replica_consistency_test.go +++ b/pkg/kv/kvserver/replica_consistency_test.go @@ -306,7 +306,7 @@ func TestReplicaChecksumSHA512(t *testing.T) { require.NoError(t, storage.MVCCDeleteRangeUsingTombstone( ctx, eng, nil, key, endKey, ts, localTS, nil, nil, false, 0, nil)) } else { - require.NoError(t, storage.MVCCPut(ctx, eng, nil, key, ts, localTS, value, nil)) + require.NoError(t, storage.MVCCPut(ctx, eng, key, ts, value, storage.MVCCWriteOptions{LocalTimestamp: localTS})) } rd, err = CalcReplicaDigest(ctx, desc, eng, kvpb.ChecksumMode_CHECK_FULL, unlim) diff --git a/pkg/kv/kvserver/replica_evaluate_test.go b/pkg/kv/kvserver/replica_evaluate_test.go index 0ea68f2354cc..c37528cab591 100644 --- a/pkg/kv/kvserver/replica_evaluate_test.go +++ b/pkg/kv/kvserver/replica_evaluate_test.go @@ -734,8 +734,8 @@ func writeABCDEFIntents(t *testing.T, d *data, txn *roachpb.Transaction) { func writeABCDEFWith(t *testing.T, eng storage.Engine, ts hlc.Timestamp, txn *roachpb.Transaction) { for _, k := range []string{"a", "b", "c", "d", "e", "f"} { require.NoError(t, storage.MVCCPut( - context.Background(), eng, nil /* ms */, roachpb.Key(k), ts, hlc.ClockTimestamp{}, - roachpb.MakeValueFromString("value-"+k), txn)) + context.Background(), eng, roachpb.Key(k), ts, + roachpb.MakeValueFromString("value-"+k), storage.MVCCWriteOptions{Txn: txn})) } } diff --git a/pkg/kv/kvserver/replica_raft.go b/pkg/kv/kvserver/replica_raft.go index 0e7a827248d0..caa8cfcba2cc 100644 --- a/pkg/kv/kvserver/replica_raft.go +++ b/pkg/kv/kvserver/replica_raft.go @@ -2429,12 +2429,10 @@ func handleTruncatedStateBelowRaftPreApply( if err := storage.MVCCPutProto( ctx, readWriter, - nil, /* ms */ prefixBuf.RaftTruncatedStateKey(), hlc.Timestamp{}, - hlc.ClockTimestamp{}, - nil, /* txn */ suggestedTruncatedState, + storage.MVCCWriteOptions{}, ); err != nil { return false, errors.Wrap(err, "unable to write RaftTruncatedState") } diff --git a/pkg/kv/kvserver/replica_test.go b/pkg/kv/kvserver/replica_test.go index 6d48e204d63b..705ac5b48d60 100644 --- a/pkg/kv/kvserver/replica_test.go +++ b/pkg/kv/kvserver/replica_test.go @@ -1793,8 +1793,8 @@ func TestOptimizePuts(t *testing.T) { require.NoError(t, storage.MVCCDeleteRangeUsingTombstone(ctx, tc.engine, nil, c.exKey, c.exEndKey, hlc.MinTimestamp, hlc.ClockTimestamp{}, nil, nil, false, 0, nil)) } else if c.exKey != nil { - require.NoError(t, storage.MVCCPut(ctx, tc.engine, nil, c.exKey, - hlc.Timestamp{}, hlc.ClockTimestamp{}, roachpb.MakeValueFromString("foo"), nil)) + require.NoError(t, storage.MVCCPut(ctx, tc.engine, c.exKey, + hlc.Timestamp{}, roachpb.MakeValueFromString("foo"), storage.MVCCWriteOptions{})) } batch := kvpb.BatchRequest{} for _, r := range c.reqs { @@ -3453,7 +3453,7 @@ func TestReplicaAbortSpanReadError(t *testing.T) { // Overwrite Abort span entry with garbage for the last op. key := keys.AbortSpanKey(tc.repl.RangeID, txn.ID) - err := storage.MVCCPut(ctx, tc.engine, nil, key, hlc.Timestamp{}, hlc.ClockTimestamp{}, roachpb.MakeValueFromString("never read in this test"), nil) + err := storage.MVCCPut(ctx, tc.engine, key, hlc.Timestamp{}, roachpb.MakeValueFromString("never read in this test"), storage.MVCCWriteOptions{}) if err != nil { t.Fatal(err) } @@ -4531,7 +4531,7 @@ func TestEndTxnWithErrors(t *testing.T) { existTxnRecord := existTxn.AsRecord() txnKey := keys.TransactionKey(test.key, txn.ID) if err := storage.MVCCPutProto( - ctx, tc.repl.store.TODOEngine(), nil, txnKey, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, &existTxnRecord, + ctx, tc.repl.store.TODOEngine(), txnKey, hlc.Timestamp{}, &existTxnRecord, storage.MVCCWriteOptions{}, ); err != nil { t.Fatal(err) } @@ -4574,7 +4574,7 @@ func TestEndTxnWithErrorAndSyncIntentResolution(t *testing.T) { existTxn.Status = roachpb.ABORTED existTxnRec := existTxn.AsRecord() txnKey := keys.TransactionKey(txn.Key, txn.ID) - err := storage.MVCCPutProto(ctx, tc.repl.store.TODOEngine(), nil, txnKey, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, &existTxnRec) + err := storage.MVCCPutProto(ctx, tc.repl.store.TODOEngine(), txnKey, hlc.Timestamp{}, &existTxnRec, storage.MVCCWriteOptions{}) require.NoError(t, err) // End the transaction, verify expected error, shouldn't deadlock. @@ -11141,7 +11141,7 @@ func TestReplicaPushed1PC(t *testing.T) { // Write a value outside the transaction. tc.manualClock.Advance(10) ts2 := tc.Clock().Now() - if err := storage.MVCCPut(ctx, tc.engine, nil, k, ts2, hlc.ClockTimestamp{}, roachpb.MakeValueFromString("one"), nil); err != nil { + if err := storage.MVCCPut(ctx, tc.engine, k, ts2, roachpb.MakeValueFromString("one"), storage.MVCCWriteOptions{}); err != nil { t.Fatalf("writing interfering value: %+v", err) } @@ -13729,10 +13729,10 @@ func setMockPutWithEstimates(containsEstimatesDelta int64) (undo func()) { ctx context.Context, readWriter storage.ReadWriter, cArgs batcheval.CommandArgs, _ kvpb.Response, ) (result.Result, error) { args := cArgs.Args.(*kvpb.PutRequest) - ms := cArgs.Stats - ms.ContainsEstimates += containsEstimatesDelta + opts := storage.MVCCWriteOptions{Txn: cArgs.Header.Txn, Stats: cArgs.Stats} + opts.Stats.ContainsEstimates += containsEstimatesDelta ts := cArgs.Header.Timestamp - return result.Result{}, storage.MVCCBlindPut(ctx, readWriter, ms, args.Key, ts, hlc.ClockTimestamp{}, args.Value, cArgs.Header.Txn) + return result.Result{}, storage.MVCCBlindPut(ctx, readWriter, args.Key, ts, args.Value, opts) } batcheval.UnregisterCommand(kvpb.Put) diff --git a/pkg/kv/kvserver/stateloader/stateloader.go b/pkg/kv/kvserver/stateloader/stateloader.go index 3ca9496cd36a..1ed749d655f1 100644 --- a/pkg/kv/kvserver/stateloader/stateloader.go +++ b/pkg/kv/kvserver/stateloader/stateloader.go @@ -165,8 +165,8 @@ func (rsl StateLoader) LoadLease( func (rsl StateLoader) SetLease( ctx context.Context, readWriter storage.ReadWriter, ms *enginepb.MVCCStats, lease roachpb.Lease, ) error { - return storage.MVCCPutProto(ctx, readWriter, ms, rsl.RangeLeaseKey(), - hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, &lease) + return storage.MVCCPutProto(ctx, readWriter, rsl.RangeLeaseKey(), + hlc.Timestamp{}, &lease, storage.MVCCWriteOptions{Stats: ms}) } // LoadRangeAppliedState loads the Range applied state. @@ -219,8 +219,8 @@ func (rsl StateLoader) SetRangeAppliedState( // The RangeAppliedStateKey is not included in stats. This is also reflected // in ComputeStats. ms := (*enginepb.MVCCStats)(nil) - return storage.MVCCPutProto(ctx, readWriter, ms, rsl.RangeAppliedStateKey(), - hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, as) + return storage.MVCCPutProto(ctx, readWriter, rsl.RangeAppliedStateKey(), + hlc.Timestamp{}, as, storage.MVCCWriteOptions{Stats: ms}) } // SetMVCCStats overwrites the MVCC stats. This needs to perform a read on the @@ -273,8 +273,8 @@ func (rsl StateLoader) SetGCThreshold( if threshold == nil { return errors.New("cannot persist nil GCThreshold") } - return storage.MVCCPutProto(ctx, readWriter, ms, rsl.RangeGCThresholdKey(), - hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, threshold) + return storage.MVCCPutProto(ctx, readWriter, rsl.RangeGCThresholdKey(), + hlc.Timestamp{}, threshold, storage.MVCCWriteOptions{Stats: ms}) } // LoadGCHint loads GC hint. @@ -297,8 +297,8 @@ func (rsl StateLoader) SetGCHint( if hint == nil { return false, errors.New("cannot persist nil GCHint") } - if err := storage.MVCCPutProto(ctx, readWriter, ms, rsl.RangeGCHintKey(), - hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, hint); err != nil { + if err := storage.MVCCPutProto(ctx, readWriter, rsl.RangeGCHintKey(), + hlc.Timestamp{}, hint, storage.MVCCWriteOptions{Stats: ms}); err != nil { return false, err } return true, nil @@ -321,8 +321,8 @@ func (rsl StateLoader) SetVersion( ms *enginepb.MVCCStats, version *roachpb.Version, ) error { - return storage.MVCCPutProto(ctx, readWriter, ms, rsl.RangeVersionKey(), - hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, version) + return storage.MVCCPutProto(ctx, readWriter, rsl.RangeVersionKey(), + hlc.Timestamp{}, version, storage.MVCCWriteOptions{Stats: ms}) } // UninitializedReplicaState returns the ReplicaState of an uninitialized diff --git a/pkg/kv/kvserver/store.go b/pkg/kv/kvserver/store.go index cc34f4dc07f9..f53942a93471 100644 --- a/pkg/kv/kvserver/store.go +++ b/pkg/kv/kvserver/store.go @@ -2547,12 +2547,10 @@ func (s *Store) WriteLastUpTimestamp(ctx context.Context, time hlc.Timestamp) er return storage.MVCCPutProto( ctx, s.TODOEngine(), // TODO(sep-raft-log): probably state engine - nil, keys.StoreLastUpKey(), hlc.Timestamp{}, - hlc.ClockTimestamp{}, - nil, &time, + storage.MVCCWriteOptions{}, ) } @@ -2583,12 +2581,10 @@ func (s *Store) WriteHLCUpperBound(ctx context.Context, time int64) error { if err := storage.MVCCPutProto( ctx, batch, - nil, keys.StoreHLCUpperBoundKey(), hlc.Timestamp{}, - hlc.ClockTimestamp{}, - nil, &ts, + storage.MVCCWriteOptions{}, ); err != nil { return err } diff --git a/pkg/kv/kvserver/store_init.go b/pkg/kv/kvserver/store_init.go index bed46a0ba29b..e73f6f579e6d 100644 --- a/pkg/kv/kvserver/store_init.go +++ b/pkg/kv/kvserver/store_init.go @@ -168,24 +168,24 @@ func WriteInitialClusterData( // Range descriptor. if err := storage.MVCCPutProto( - ctx, batch, nil /* ms */, keys.RangeDescriptorKey(desc.StartKey), - now, hlc.ClockTimestamp{}, nil /* txn */, desc, + ctx, batch, keys.RangeDescriptorKey(desc.StartKey), + now, desc, storage.MVCCWriteOptions{}, ); err != nil { return err } // Replica GC timestamp. if err := storage.MVCCPutProto( - ctx, batch, nil /* ms */, keys.RangeLastReplicaGCTimestampKey(desc.RangeID), - hlc.Timestamp{}, hlc.ClockTimestamp{}, nil /* txn */, &now, + ctx, batch, keys.RangeLastReplicaGCTimestampKey(desc.RangeID), + hlc.Timestamp{}, &now, storage.MVCCWriteOptions{}, ); err != nil { return err } // Range addressing for meta2. meta2Key := keys.RangeMetaKey(endKey) if err := storage.MVCCPutProto( - ctx, batch, firstRangeMS, meta2Key.AsRawKey(), - now, hlc.ClockTimestamp{}, nil /* txn */, desc, + ctx, batch, meta2Key.AsRawKey(), + now, desc, storage.MVCCWriteOptions{Stats: firstRangeMS}, ); err != nil { return err } @@ -195,7 +195,7 @@ func WriteInitialClusterData( // Range addressing for meta1. meta1Key := keys.RangeMetaKey(keys.RangeMetaKey(roachpb.RKeyMax)) if err := storage.MVCCPutProto( - ctx, batch, nil /* ms */, meta1Key.AsRawKey(), now, hlc.ClockTimestamp{}, nil /* txn */, desc, + ctx, batch, meta1Key.AsRawKey(), now, desc, storage.MVCCWriteOptions{}, ); err != nil { return err } @@ -206,7 +206,7 @@ func WriteInitialClusterData( // Initialize the checksums. kv.Value.InitChecksum(kv.Key) if err := storage.MVCCPut( - ctx, batch, nil /* ms */, kv.Key, now, hlc.ClockTimestamp{}, kv.Value, nil, /* txn */ + ctx, batch, kv.Key, now, kv.Value, storage.MVCCWriteOptions{}, ); err != nil { return err } diff --git a/pkg/kv/kvserver/store_snapshot.go b/pkg/kv/kvserver/store_snapshot.go index 66c5c66633c7..703878636d32 100644 --- a/pkg/kv/kvserver/store_snapshot.go +++ b/pkg/kv/kvserver/store_snapshot.go @@ -1354,7 +1354,7 @@ func SendEmptySnapshot( var ms enginepb.MVCCStats // Seed an empty range into the new engine. if err := storage.MVCCPutProto( - ctx, eng, &ms, keys.RangeDescriptorKey(desc.StartKey), now, hlc.ClockTimestamp{}, nil /* txn */, &desc, + ctx, eng, keys.RangeDescriptorKey(desc.StartKey), now, &desc, storage.MVCCWriteOptions{Stats: &ms}, ); err != nil { return err } diff --git a/pkg/kv/kvserver/store_test.go b/pkg/kv/kvserver/store_test.go index 9b817d640006..5bf0a0897657 100644 --- a/pkg/kv/kvserver/store_test.go +++ b/pkg/kv/kvserver/store_test.go @@ -371,12 +371,10 @@ func TestIterateIDPrefixKeys(t *testing.T) { if err := storage.MVCCPut( ctx, eng, - nil, /* ms */ key, hlc.Timestamp{}, - hlc.ClockTimestamp{}, roachpb.MakeValueFromString("fake value for "+key.String()), - nil, /* txn */ + storage.MVCCWriteOptions{}, ); err != nil { t.Fatal(err) } @@ -408,7 +406,7 @@ func TestIterateIDPrefixKeys(t *testing.T) { t.Logf("writing tombstone at rangeID=%d", rangeID) if err := storage.MVCCPutProto( - ctx, eng, nil /* ms */, keys.RangeTombstoneKey(rangeID), hlc.Timestamp{}, hlc.ClockTimestamp{}, nil /* txn */, &tombstone, + ctx, eng, keys.RangeTombstoneKey(rangeID), hlc.Timestamp{}, &tombstone, storage.MVCCWriteOptions{}, ); err != nil { t.Fatal(err) } diff --git a/pkg/kv/kvserver/stores.go b/pkg/kv/kvserver/stores.go index c4e7e7ae9d9c..ce7407565dd0 100644 --- a/pkg/kv/kvserver/stores.go +++ b/pkg/kv/kvserver/stores.go @@ -297,7 +297,7 @@ func (ls *Stores) updateBootstrapInfoLocked(bi *gossip.BootstrapInfo) error { ls.storeMap.Range(func(k int64, v unsafe.Pointer) bool { s := (*Store)(v) // TODO(sep-raft-log): see ReadBootstrapInfo. - err = storage.MVCCPutProto(ctx, s.TODOEngine(), nil, keys.StoreGossipKey(), hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, bi) + err = storage.MVCCPutProto(ctx, s.TODOEngine(), keys.StoreGossipKey(), hlc.Timestamp{}, bi, storage.MVCCWriteOptions{}) return err == nil }) return err diff --git a/pkg/kv/kvserver/txn_wait_queue_test.go b/pkg/kv/kvserver/txn_wait_queue_test.go index 32e00bdb5000..b803ac02a440 100644 --- a/pkg/kv/kvserver/txn_wait_queue_test.go +++ b/pkg/kv/kvserver/txn_wait_queue_test.go @@ -39,9 +39,9 @@ import ( "github.com/stretchr/testify/require" ) -func writeTxnRecord(ctx context.Context, tc *testContext, txn *roachpb.Transaction) error { - key := keys.TransactionKey(txn.Key, txn.ID) - return storage.MVCCPutProto(ctx, tc.store.TODOEngine(), nil, key, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, txn) +func writeTxnRecord(ctx context.Context, tc *testContext, txnRecord *roachpb.Transaction) error { + key := keys.TransactionKey(txnRecord.Key, txnRecord.ID) + return storage.MVCCPutProto(ctx, tc.store.TODOEngine(), key, hlc.Timestamp{}, txnRecord, storage.MVCCWriteOptions{}) } // createTxnForPushQueue creates a txn struct and writes a "fake" diff --git a/pkg/server/node_test.go b/pkg/server/node_test.go index 781e6ca7e578..e44399e4e5d9 100644 --- a/pkg/server/node_test.go +++ b/pkg/server/node_test.go @@ -271,7 +271,7 @@ func TestCorruptedClusterID(t *testing.T) { StoreID: 1, } if err := storage.MVCCPutProto( - ctx, e, nil /* ms */, keys.StoreIdentKey(), hlc.Timestamp{}, hlc.ClockTimestamp{}, nil /* txn */, &sIdent, + ctx, e, keys.StoreIdentKey(), hlc.Timestamp{}, &sIdent, storage.MVCCWriteOptions{}, ); err != nil { t.Fatal(err) } @@ -865,8 +865,8 @@ func TestDiskStatsMap(t *testing.T) { engineIDs := []roachpb.StoreID{10, 5} for i := range engines { ident := roachpb.StoreIdent{StoreID: engineIDs[i]} - require.NoError(t, storage.MVCCBlindPutProto(ctx, engines[i], nil, keys.StoreIdentKey(), - hlc.Timestamp{}, hlc.ClockTimestamp{}, &ident, nil)) + require.NoError(t, storage.MVCCBlindPutProto(ctx, engines[i], keys.StoreIdentKey(), + hlc.Timestamp{}, &ident, storage.MVCCWriteOptions{})) } var dsm diskStatsMap clusterProvisionedBW := int64(150) diff --git a/pkg/server/node_tombstone_storage.go b/pkg/server/node_tombstone_storage.go index 312a97c44a40..9d7a576ef247 100644 --- a/pkg/server/node_tombstone_storage.go +++ b/pkg/server/node_tombstone_storage.go @@ -136,7 +136,7 @@ func (s *nodeTombstoneStorage) SetDecommissioned( } if err := storage.MVCCPut( - ctx, eng, nil /* ms */, k, hlc.Timestamp{}, hlc.ClockTimestamp{}, v, nil, /* txn */ + ctx, eng, k, hlc.Timestamp{}, v, storage.MVCCWriteOptions{}, ); err != nil { return err } diff --git a/pkg/server/server_test.go b/pkg/server/server_test.go index 02ccbb0551ce..78154770b3b8 100644 --- a/pkg/server/server_test.go +++ b/pkg/server/server_test.go @@ -482,9 +482,8 @@ func TestClusterIDMismatch(t *testing.T) { StoreID: roachpb.StoreID(i + 1), } if err := storage.MVCCPutProto( - context.Background(), e, nil, keys.StoreIdentKey(), hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, &sIdent, + context.Background(), e, keys.StoreIdentKey(), hlc.Timestamp{}, &sIdent, storage.MVCCWriteOptions{}, ); err != nil { - t.Fatal(err) } engines[i] = e @@ -1081,8 +1080,8 @@ func TestAssertEnginesEmpty(t *testing.T) { require.NoError(t, assertEnginesEmpty([]storage.Engine{eng})) - require.NoError(t, storage.MVCCPutProto(ctx, eng, nil, keys.DeprecatedStoreClusterVersionKey(), - hlc.Timestamp{}, hlc.ClockTimestamp{}, nil, &roachpb.Version{Major: 21, Minor: 1, Internal: 122})) + require.NoError(t, storage.MVCCPutProto(ctx, eng, keys.DeprecatedStoreClusterVersionKey(), + hlc.Timestamp{}, &roachpb.Version{Major: 21, Minor: 1, Internal: 122}, storage.MVCCWriteOptions{})) require.NoError(t, assertEnginesEmpty([]storage.Engine{eng})) batch := eng.NewBatch() diff --git a/pkg/server/settings_cache.go b/pkg/server/settings_cache.go index 0067a1a06bd8..2e73ada82704 100644 --- a/pkg/server/settings_cache.go +++ b/pkg/server/settings_cache.go @@ -102,7 +102,7 @@ func storeCachedSettingsKVs(ctx context.Context, eng storage.Engine, kvs []roach for _, kv := range kvs { kv.Value.Timestamp = hlc.Timestamp{} // nb: Timestamp is not part of checksum if err := storage.MVCCPut( - ctx, batch, nil, keys.StoreCachedSettingsKey(kv.Key), hlc.Timestamp{}, hlc.ClockTimestamp{}, kv.Value, nil, + ctx, batch, keys.StoreCachedSettingsKey(kv.Key), hlc.Timestamp{}, kv.Value, storage.MVCCWriteOptions{}, ); err != nil { return err } diff --git a/pkg/storage/bench_data_test.go b/pkg/storage/bench_data_test.go index 5a4f8a7aa412..f530b9847a5b 100644 --- a/pkg/storage/bench_data_test.go +++ b/pkg/storage/bench_data_test.go @@ -358,7 +358,7 @@ func (d mvccBenchData) Build(ctx context.Context, b *testing.B, eng Engine) erro txn.ReadTimestamp = ts txn.WriteTimestamp = ts } - require.NoError(b, MVCCPut(ctx, batch, nil, key, ts, hlc.ClockTimestamp{}, value, txn)) + require.NoError(b, MVCCPut(ctx, batch, key, ts, value, MVCCWriteOptions{Txn: txn})) } resolveLastIntent := func(batch Batch, idx int) { diff --git a/pkg/storage/bench_pebble_test.go b/pkg/storage/bench_pebble_test.go index d0f7fbbdca4c..c5efbd19d972 100644 --- a/pkg/storage/bench_pebble_test.go +++ b/pkg/storage/bench_pebble_test.go @@ -361,10 +361,10 @@ func BenchmarkMVCCPutDelete_Pebble(b *testing.B) { key := encoding.EncodeVarintAscending(nil, blockID) key = encoding.EncodeVarintAscending(key, blockNum) - if err := MVCCPut(ctx, db, nil, key, hlc.Timestamp{}, hlc.ClockTimestamp{}, value, nil); err != nil { + if err := MVCCPut(ctx, db, key, hlc.Timestamp{}, value, MVCCWriteOptions{}); err != nil { b.Fatal(err) } - if _, err := MVCCDelete(ctx, db, nil, key, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil); err != nil { + if _, err := MVCCDelete(ctx, db, key, hlc.Timestamp{}, MVCCWriteOptions{}); err != nil { b.Fatal(err) } } diff --git a/pkg/storage/bench_test.go b/pkg/storage/bench_test.go index d747464f79b6..963a1fda361a 100644 --- a/pkg/storage/bench_test.go +++ b/pkg/storage/bench_test.go @@ -318,7 +318,7 @@ func setupKeysWithIntent( putTxn = &otherTxn } key := makeKey(nil, j) - require.NoError(b, MVCCPut(context.Background(), batch, nil, key, ts, hlc.ClockTimestamp{}, value, putTxn)) + require.NoError(b, MVCCPut(context.Background(), batch, key, ts, value, MVCCWriteOptions{Txn: putTxn})) } require.NoError(b, batch.Commit(true)) batch.Close() @@ -714,7 +714,7 @@ func loadTestData(dir string, numKeys, numBatches, batchTimeSpan, valueBytes int timestamp := hlc.Timestamp{WallTime: minWallTime + rand.Int63n(int64(batchTimeSpan))} value := roachpb.MakeValueFromBytes(randutil.RandBytes(rng, valueBytes)) value.InitChecksum(key) - if err := MVCCPut(ctx, batch, nil, key, timestamp, hlc.ClockTimestamp{}, value, nil); err != nil { + if err := MVCCPut(ctx, batch, key, timestamp, value, MVCCWriteOptions{}); err != nil { return nil, err } } @@ -889,7 +889,7 @@ func runMVCCPut( for j := 0; j < versions; j++ { key := roachpb.Key(encoding.EncodeUvarintAscending(keyBuf[:4], uint64(i))) ts := hlc.Timestamp{WallTime: timeutil.Now().UnixNano()} - if err := MVCCPut(ctx, rw, nil, key, ts, hlc.ClockTimestamp{}, value, nil); err != nil { + if err := MVCCPut(ctx, rw, key, ts, value, MVCCWriteOptions{}); err != nil { b.Fatalf("failed put: %+v", err) } } @@ -912,7 +912,7 @@ func runMVCCBlindPut(ctx context.Context, b *testing.B, emk engineMaker, valueSi for i := 0; i < b.N; i++ { key := roachpb.Key(encoding.EncodeUvarintAscending(keyBuf[:4], uint64(i))) ts := hlc.Timestamp{WallTime: timeutil.Now().UnixNano()} - if err := MVCCBlindPut(ctx, eng, nil, key, ts, hlc.ClockTimestamp{}, value, nil); err != nil { + if err := MVCCBlindPut(ctx, eng, key, ts, value, MVCCWriteOptions{}); err != nil { b.Fatalf("failed put: %+v", err) } } @@ -936,7 +936,7 @@ func runMVCCConditionalPut( for i := 0; i < b.N; i++ { key := roachpb.Key(encoding.EncodeUvarintAscending(keyBuf[:4], uint64(i))) ts := hlc.Timestamp{WallTime: timeutil.Now().UnixNano()} - if err := MVCCPut(ctx, eng, nil, key, ts, hlc.ClockTimestamp{}, value, nil); err != nil { + if err := MVCCPut(ctx, eng, key, ts, value, MVCCWriteOptions{}); err != nil { b.Fatalf("failed put: %+v", err) } } @@ -948,7 +948,7 @@ func runMVCCConditionalPut( for i := 0; i < b.N; i++ { key := roachpb.Key(encoding.EncodeUvarintAscending(keyBuf[:4], uint64(i))) ts := hlc.Timestamp{WallTime: timeutil.Now().UnixNano()} - if err := MVCCConditionalPut(ctx, eng, nil, key, ts, hlc.ClockTimestamp{}, value, expected, CPutFailIfMissing, nil); err != nil { + if err := MVCCConditionalPut(ctx, eng, key, ts, value, expected, CPutFailIfMissing, MVCCWriteOptions{}); err != nil { b.Fatalf("failed put: %+v", err) } } @@ -971,7 +971,7 @@ func runMVCCBlindConditionalPut(ctx context.Context, b *testing.B, emk engineMak key := roachpb.Key(encoding.EncodeUvarintAscending(keyBuf[:4], uint64(i))) ts := hlc.Timestamp{WallTime: timeutil.Now().UnixNano()} if err := MVCCBlindConditionalPut( - ctx, eng, nil, key, ts, hlc.ClockTimestamp{}, value, nil, CPutFailIfMissing, nil, + ctx, eng, key, ts, value, nil, CPutFailIfMissing, MVCCWriteOptions{}, ); err != nil { b.Fatalf("failed put: %+v", err) } @@ -994,7 +994,7 @@ func runMVCCInitPut(ctx context.Context, b *testing.B, emk engineMaker, valueSiz for i := 0; i < b.N; i++ { key := roachpb.Key(encoding.EncodeUvarintAscending(keyBuf[:4], uint64(i))) ts := hlc.Timestamp{WallTime: timeutil.Now().UnixNano()} - if err := MVCCInitPut(ctx, eng, nil, key, ts, hlc.ClockTimestamp{}, value, false, nil); err != nil { + if err := MVCCInitPut(ctx, eng, key, ts, value, false, MVCCWriteOptions{}); err != nil { b.Fatalf("failed put: %+v", err) } } @@ -1016,7 +1016,7 @@ func runMVCCBlindInitPut(ctx context.Context, b *testing.B, emk engineMaker, val for i := 0; i < b.N; i++ { key := roachpb.Key(encoding.EncodeUvarintAscending(keyBuf[:4], uint64(i))) ts := hlc.Timestamp{WallTime: timeutil.Now().UnixNano()} - if err := MVCCBlindInitPut(ctx, eng, nil, key, ts, hlc.ClockTimestamp{}, value, false, nil); err != nil { + if err := MVCCBlindInitPut(ctx, eng, key, ts, value, false, MVCCWriteOptions{}); err != nil { b.Fatalf("failed put: %+v", err) } } @@ -1046,7 +1046,7 @@ func runMVCCBatchPut(ctx context.Context, b *testing.B, emk engineMaker, valueSi for j := i; j < end; j++ { key := roachpb.Key(encoding.EncodeUvarintAscending(keyBuf[:4], uint64(j))) ts := hlc.Timestamp{WallTime: timeutil.Now().UnixNano()} - if err := MVCCPut(ctx, batch, nil, key, ts, hlc.ClockTimestamp{}, value, nil); err != nil { + if err := MVCCPut(ctx, batch, key, ts, value, MVCCWriteOptions{}); err != nil { b.Fatalf("failed put: %+v", err) } } @@ -1179,13 +1179,18 @@ func runMVCCDeleteRange(ctx context.Context, b *testing.B, valueBytes int) { if _, _, _, err := MVCCDeleteRange( ctx, eng, - &enginepb.MVCCStats{}, keys.LocalMax, roachpb.KeyMax, math.MaxInt64, hlc.MaxTimestamp, - hlc.ClockTimestamp{}, - nil, + MVCCWriteOptions{ + // NB: Though we don't capture the stats object, passing nil would + // disable stats computations, which should be included in benchmarks. + // This cost is not always negligible, e.g. in some cases such as + // with MVCC range tombstones where additional seeks to find boundary + // conditions are involved. + Stats: &enginepb.MVCCStats{}, + }, false, ); err != nil { b.Fatal(err) @@ -1432,8 +1437,7 @@ func runMVCCGarbageCollect( break } for _, key := range pointKeys { - if err := MVCCPut(ctx, batch, nil, key, pts, hlc.ClockTimestamp{}, val, - nil); err != nil { + if err := MVCCPut(ctx, batch, key, pts, val, MVCCWriteOptions{}); err != nil { b.Fatal(err) } } @@ -1493,7 +1497,7 @@ func runBatchApplyBatchRepr( for i := 0; i < batchSize; i++ { key := roachpb.Key(encoding.EncodeUvarintAscending(keyBuf[:4], uint64(order[i]))) ts := hlc.Timestamp{WallTime: timeutil.Now().UnixNano()} - if err := MVCCBlindPut(ctx, batch, nil, key, ts, hlc.ClockTimestamp{}, value, nil); err != nil { + if err := MVCCBlindPut(ctx, batch, key, ts, value, MVCCWriteOptions{}); err != nil { b.Fatal(err) } } @@ -1902,7 +1906,7 @@ func BenchmarkMVCCScannerWithIntentsAndVersions(b *testing.B) { // Put the keys for this iteration. for j := 0; j < numKeys; j++ { key := makeKey(nil, j) - require.NoError(b, MVCCPut(ctx, batch, nil, key, ts, hlc.ClockTimestamp{}, value, &txn)) + require.NoError(b, MVCCPut(ctx, batch, key, ts, value, MVCCWriteOptions{Txn: &txn})) } numPrevKeys = numKeys // Read the keys from the Batch and write them to a sstable to ingest. diff --git a/pkg/storage/engine_test.go b/pkg/storage/engine_test.go index e1d3b5a93055..552bb7ef4bbc 100644 --- a/pkg/storage/engine_test.go +++ b/pkg/storage/engine_test.go @@ -174,13 +174,13 @@ func TestEngineBatchStaleCachedIterator(t *testing.T) { // Put a value so that the deletion below finds a value to seek // to. - if err := MVCCPut(context.Background(), batch, nil, key, hlc.Timestamp{}, hlc.ClockTimestamp{}, roachpb.MakeValueFromString("x"), nil); err != nil { + if err := MVCCPut(context.Background(), batch, key, hlc.Timestamp{}, roachpb.MakeValueFromString("x"), MVCCWriteOptions{}); err != nil { t.Fatal(err) } // Seek the iterator to `key` and clear the value (but without // telling the iterator about that). - if _, err := MVCCDelete(context.Background(), batch, nil, key, hlc.Timestamp{}, hlc.ClockTimestamp{}, nil); err != nil { + if _, err := MVCCDelete(context.Background(), batch, key, hlc.Timestamp{}, MVCCWriteOptions{}); err != nil { t.Fatal(err) } @@ -1472,7 +1472,7 @@ func TestGetIntent(t *testing.T) { for _, keyName := range []string{"a", "aa"} { key := roachpb.Key(keyName) - err := MVCCPut(ctx, reader, nil, key, txn1.ReadTimestamp, hlc.ClockTimestamp{}, roachpb.Value{RawBytes: key}, txn1) + err := MVCCPut(ctx, reader, key, txn1.ReadTimestamp, roachpb.Value{RawBytes: key}, MVCCWriteOptions{Txn: txn1}) require.NoError(t, err) } @@ -1481,7 +1481,7 @@ func TestGetIntent(t *testing.T) { txn2 := &roachpb.Transaction{TxnMeta: enginepb.TxnMeta{Key: roachpb.Key("a"), ID: txn2ID, Epoch: 2, WriteTimestamp: txn2TS, MinTimestamp: txn2TS, CoordinatorNodeID: 2}, ReadTimestamp: txn2TS} key := roachpb.Key("b") - err = MVCCPut(ctx, reader, nil, key, txn2.ReadTimestamp, hlc.ClockTimestamp{}, roachpb.Value{RawBytes: key}, txn2) + err = MVCCPut(ctx, reader, key, txn2.ReadTimestamp, roachpb.Value{RawBytes: key}, MVCCWriteOptions{Txn: txn2}) require.NoError(t, err) tests := []struct { @@ -1556,7 +1556,7 @@ func TestScanIntents(t *testing.T) { defer eng.Close() for _, key := range keys { - err := MVCCPut(ctx, eng, nil, key, txn1.ReadTimestamp, hlc.ClockTimestamp{}, roachpb.Value{RawBytes: key}, txn1) + err := MVCCPut(ctx, eng, key, txn1.ReadTimestamp, roachpb.Value{RawBytes: key}, MVCCWriteOptions{Txn: txn1}) require.NoError(t, err) } @@ -1605,20 +1605,20 @@ func TestEngineClearRange(t *testing.T) { writeInitialData := func(t *testing.T, rw ReadWriter) { var localTS hlc.ClockTimestamp txn := roachpb.MakeTransaction("test", nil, roachpb.NormalUserPriority, wallTS(6), 1, 1) - require.NoError(t, MVCCPut(ctx, rw, nil, roachpb.Key("c"), wallTS(1), localTS, stringValue("c1").Value, nil)) + require.NoError(t, MVCCPut(ctx, rw, roachpb.Key("c"), wallTS(1), stringValue("c1").Value, MVCCWriteOptions{LocalTimestamp: localTS})) require.NoError(t, rw.PutMVCCRangeKey(rangeKey("d", "h", 1), MVCCValue{})) require.NoError(t, rw.PutMVCCRangeKey(rangeKey("a", "f", 2), MVCCValue{})) - require.NoError(t, MVCCPut(ctx, rw, nil, roachpb.Key("g"), wallTS(2), localTS, stringValue("g2").Value, nil)) - require.NoError(t, MVCCPut(ctx, rw, nil, roachpb.Key("e"), wallTS(3), localTS, stringValue("e3").Value, nil)) + require.NoError(t, MVCCPut(ctx, rw, roachpb.Key("g"), wallTS(2), stringValue("g2").Value, MVCCWriteOptions{})) + require.NoError(t, MVCCPut(ctx, rw, roachpb.Key("e"), wallTS(3), stringValue("e3").Value, MVCCWriteOptions{})) require.NoError(t, rw.PutMVCCRangeKey(rangeKey("a", "f", 4), MVCCValue{})) require.NoError(t, rw.PutMVCCRangeKey(rangeKey("g", "h", 4), MVCCValue{})) - require.NoError(t, MVCCPut(ctx, rw, nil, roachpb.Key("a"), wallTS(5), localTS, stringValue("a2").Value, nil)) - require.NoError(t, MVCCPut(ctx, rw, nil, roachpb.Key("b"), wallTS(5), localTS, stringValue("b2").Value, nil)) - require.NoError(t, MVCCPut(ctx, rw, nil, roachpb.Key("c"), wallTS(5), localTS, stringValue("c2").Value, nil)) - require.NoError(t, MVCCPut(ctx, rw, nil, roachpb.Key("a"), wallTS(6), localTS, stringValue("a6").Value, &txn)) - require.NoError(t, MVCCPut(ctx, rw, nil, roachpb.Key("b"), wallTS(6), localTS, stringValue("b6").Value, &txn)) - require.NoError(t, MVCCPut(ctx, rw, nil, roachpb.Key("e"), wallTS(6), localTS, stringValue("e6").Value, &txn)) - require.NoError(t, MVCCPut(ctx, rw, nil, roachpb.Key("g"), wallTS(6), localTS, stringValue("g6").Value, &txn)) + require.NoError(t, MVCCPut(ctx, rw, roachpb.Key("a"), wallTS(5), stringValue("a2").Value, MVCCWriteOptions{})) + require.NoError(t, MVCCPut(ctx, rw, roachpb.Key("b"), wallTS(5), stringValue("b2").Value, MVCCWriteOptions{})) + require.NoError(t, MVCCPut(ctx, rw, roachpb.Key("c"), wallTS(5), stringValue("c2").Value, MVCCWriteOptions{})) + require.NoError(t, MVCCPut(ctx, rw, roachpb.Key("a"), wallTS(6), stringValue("a6").Value, MVCCWriteOptions{Txn: &txn})) + require.NoError(t, MVCCPut(ctx, rw, roachpb.Key("b"), wallTS(6), stringValue("b6").Value, MVCCWriteOptions{Txn: &txn})) + require.NoError(t, MVCCPut(ctx, rw, roachpb.Key("e"), wallTS(6), stringValue("e6").Value, MVCCWriteOptions{Txn: &txn})) + require.NoError(t, MVCCPut(ctx, rw, roachpb.Key("g"), wallTS(6), stringValue("g6").Value, MVCCWriteOptions{Txn: &txn})) } start, end := roachpb.Key("b"), roachpb.Key("g") @@ -2081,7 +2081,7 @@ func TestScanConflictingIntentsForDroppingLatchesEarly(t *testing.T) { setup: func(t *testing.T, rw ReadWriter, txn *roachpb.Transaction) { conflictingTxn := newTxn(belowTxnTS) // test txn should see this intent err := MVCCPut( - ctx, rw, nil, keyA, conflictingTxn.WriteTimestamp, hlc.ClockTimestamp{}, val, conflictingTxn, + ctx, rw, keyA, conflictingTxn.WriteTimestamp, val, MVCCWriteOptions{Txn: conflictingTxn}, ) require.NoError(t, err) }, @@ -2095,7 +2095,7 @@ func TestScanConflictingIntentsForDroppingLatchesEarly(t *testing.T) { setup: func(t *testing.T, rw ReadWriter, txn *roachpb.Transaction) { conflictingTxn := newTxn(aboveTxnTS) // test txn shouldn't see this intent err := MVCCPut( - ctx, rw, nil, keyA, conflictingTxn.WriteTimestamp, hlc.ClockTimestamp{}, val, conflictingTxn, + ctx, rw, keyA, conflictingTxn.WriteTimestamp, val, MVCCWriteOptions{Txn: conflictingTxn}, ) require.NoError(t, err) }, @@ -2107,7 +2107,7 @@ func TestScanConflictingIntentsForDroppingLatchesEarly(t *testing.T) { { name: "bounds do not include (latest) own write", setup: func(t *testing.T, rw ReadWriter, txn *roachpb.Transaction) { - err := MVCCPut(ctx, rw, nil, keyA, txn.WriteTimestamp, hlc.ClockTimestamp{}, val, txn) + err := MVCCPut(ctx, rw, keyA, txn.WriteTimestamp, val, MVCCWriteOptions{Txn: txn}) require.NoError(t, err) }, start: keyB, @@ -2338,7 +2338,7 @@ func TestScanConflictingIntentsForDroppingLatchesEarlyReadYourOwnWrites(t *testi txn.Sequence = tc.intentSequenceNumber txn.ReadTimestamp = tc.intentTS txn.WriteTimestamp = tc.intentTS - err := MVCCPut(ctx, eng, nil, keyA, txn.WriteTimestamp, hlc.ClockTimestamp{}, val, txn) + err := MVCCPut(ctx, eng, keyA, txn.WriteTimestamp, val, MVCCWriteOptions{Txn: txn}) require.NoError(t, err) // Set up the read. diff --git a/pkg/storage/metamorphic/operations.go b/pkg/storage/metamorphic/operations.go index 915670343e86..92b25c64c7b4 100644 --- a/pkg/storage/metamorphic/operations.go +++ b/pkg/storage/metamorphic/operations.go @@ -207,7 +207,7 @@ func (m mvccPutOp) run(ctx context.Context) string { txn.Sequence++ writer := m.m.getReadWriter(m.writer) - err := storage.MVCCPut(ctx, writer, nil, m.key, txn.ReadTimestamp, hlc.ClockTimestamp{}, m.value, txn) + err := storage.MVCCPut(ctx, writer, m.key, txn.ReadTimestamp, m.value, storage.MVCCWriteOptions{Txn: txn}) if err != nil { if writeTooOldErr := (*kvpb.WriteTooOldError)(nil); errors.As(err, &writeTooOldErr) { txn.WriteTimestamp.Forward(writeTooOldErr.ActualTimestamp) @@ -236,8 +236,8 @@ func (m mvccCPutOp) run(ctx context.Context) string { writer := m.m.getReadWriter(m.writer) txn.Sequence++ - err := storage.MVCCConditionalPut(ctx, writer, nil, m.key, - txn.ReadTimestamp, hlc.ClockTimestamp{}, m.value, m.expVal, true, txn) + err := storage.MVCCConditionalPut(ctx, writer, m.key, + txn.ReadTimestamp, m.value, m.expVal, true, storage.MVCCWriteOptions{Txn: txn}) if err != nil { if writeTooOldErr := (*kvpb.WriteTooOldError)(nil); errors.As(err, &writeTooOldErr) { txn.WriteTimestamp.Forward(writeTooOldErr.ActualTimestamp) @@ -265,7 +265,7 @@ func (m mvccInitPutOp) run(ctx context.Context) string { writer := m.m.getReadWriter(m.writer) txn.Sequence++ - err := storage.MVCCInitPut(ctx, writer, nil, m.key, txn.ReadTimestamp, hlc.ClockTimestamp{}, m.value, false, txn) + err := storage.MVCCInitPut(ctx, writer, m.key, txn.ReadTimestamp, m.value, false, storage.MVCCWriteOptions{Txn: txn}) if err != nil { if writeTooOldErr := (*kvpb.WriteTooOldError)(nil); errors.As(err, &writeTooOldErr) { txn.WriteTimestamp.Forward(writeTooOldErr.ActualTimestamp) @@ -298,8 +298,8 @@ func (m mvccDeleteRangeOp) run(ctx context.Context) string { txn.Sequence++ - keys, _, _, err := storage.MVCCDeleteRange(ctx, writer, nil, m.key, m.endKey, - 0, txn.WriteTimestamp, hlc.ClockTimestamp{}, txn, true) + keys, _, _, err := storage.MVCCDeleteRange(ctx, writer, m.key, m.endKey, + 0, txn.WriteTimestamp, storage.MVCCWriteOptions{Txn: txn}, true) if err != nil { return fmt.Sprintf("error: %s", err) } @@ -377,7 +377,7 @@ func (m mvccDeleteOp) run(ctx context.Context) string { writer := m.m.getReadWriter(m.writer) txn.Sequence++ - _, err := storage.MVCCDelete(ctx, writer, nil, m.key, txn.ReadTimestamp, hlc.ClockTimestamp{}, txn) + _, err := storage.MVCCDelete(ctx, writer, m.key, txn.ReadTimestamp, storage.MVCCWriteOptions{Txn: txn}) if err != nil { if writeTooOldErr := (*kvpb.WriteTooOldError)(nil); errors.As(err, &writeTooOldErr) { txn.WriteTimestamp.Forward(writeTooOldErr.ActualTimestamp) diff --git a/pkg/storage/mvcc.go b/pkg/storage/mvcc.go index 9b30adceb0db..7723d885baa8 100644 --- a/pkg/storage/mvcc.go +++ b/pkg/storage/mvcc.go @@ -832,19 +832,17 @@ func MVCCGetProto( func MVCCPutProto( ctx context.Context, rw ReadWriter, - ms *enginepb.MVCCStats, key roachpb.Key, timestamp hlc.Timestamp, - localTimestamp hlc.ClockTimestamp, - txn *roachpb.Transaction, msg protoutil.Message, + opts MVCCWriteOptions, ) error { value := roachpb.Value{} if err := value.SetProto(msg); err != nil { return err } value.InitChecksum(key) - return MVCCPut(ctx, rw, ms, key, timestamp, localTimestamp, value, txn) + return MVCCPut(ctx, rw, key, timestamp, value, opts) } // MVCCBlindPutProto sets the given key to the protobuf-serialized byte string @@ -853,19 +851,17 @@ func MVCCPutProto( func MVCCBlindPutProto( ctx context.Context, writer Writer, - ms *enginepb.MVCCStats, key roachpb.Key, timestamp hlc.Timestamp, - localTimestamp hlc.ClockTimestamp, msg protoutil.Message, - txn *roachpb.Transaction, + opts MVCCWriteOptions, ) error { value := roachpb.Value{} if err := value.SetProto(msg); err != nil { return err } value.InitChecksum(key) - return MVCCBlindPut(ctx, writer, ms, key, timestamp, localTimestamp, value, txn) + return MVCCBlindPut(ctx, writer, key, timestamp, value, opts) } // LockTableView is a transaction-bound view into an in-memory collections of @@ -1442,17 +1438,15 @@ func (b *putBuffer) putIntentMeta( func MVCCPut( ctx context.Context, rw ReadWriter, - ms *enginepb.MVCCStats, key roachpb.Key, timestamp hlc.Timestamp, - localTimestamp hlc.ClockTimestamp, value roachpb.Value, - txn *roachpb.Transaction, + opts MVCCWriteOptions, ) error { // If we're not tracking stats for the key and we're writing a non-versioned // key we can utilize a blind put to avoid reading any existing value. var iter MVCCIterator - blind := ms == nil && timestamp.IsEmpty() + blind := opts.Stats == nil && timestamp.IsEmpty() if !blind { iter = newMVCCIterator( rw, timestamp, false /* rangeKeyMasking */, false /* noInterleavedIntents */, IterOptions{ @@ -1462,7 +1456,7 @@ func MVCCPut( ) defer iter.Close() } - return mvccPutUsingIter(ctx, rw, iter, ms, key, timestamp, localTimestamp, value, txn, nil) + return mvccPutUsingIter(ctx, rw, iter, key, timestamp, value, nil, opts) } // MVCCBlindPut is a fast-path of MVCCPut. See the MVCCPut comments for details @@ -1478,14 +1472,12 @@ func MVCCPut( func MVCCBlindPut( ctx context.Context, writer Writer, - ms *enginepb.MVCCStats, key roachpb.Key, timestamp hlc.Timestamp, - localTimestamp hlc.ClockTimestamp, value roachpb.Value, - txn *roachpb.Transaction, + opts MVCCWriteOptions, ) error { - return mvccPutUsingIter(ctx, writer, nil, ms, key, timestamp, localTimestamp, value, txn, nil) + return mvccPutUsingIter(ctx, writer, nil, key, timestamp, value, nil, opts) } // MVCCDelete marks the key deleted so that it will not be returned in @@ -1500,11 +1492,9 @@ func MVCCBlindPut( func MVCCDelete( ctx context.Context, rw ReadWriter, - ms *enginepb.MVCCStats, key roachpb.Key, timestamp hlc.Timestamp, - localTimestamp hlc.ClockTimestamp, - txn *roachpb.Transaction, + opts MVCCWriteOptions, ) (foundKey bool, err error) { iter := newMVCCIterator( rw, timestamp, false /* rangeKeyMasking */, false /* noInterleavedIntents */, IterOptions{ @@ -1519,7 +1509,7 @@ func MVCCDelete( // TODO(yuzefovich): can we avoid the put if the key does not exist? return mvccPutInternal( - ctx, rw, iter, ms, key, timestamp, localTimestamp, noValue, txn, buf, nil) + ctx, rw, iter, key, timestamp, noValue, buf, nil, opts) } var noValue = roachpb.Value{} @@ -1532,13 +1522,11 @@ func mvccPutUsingIter( ctx context.Context, writer Writer, iter MVCCIterator, - ms *enginepb.MVCCStats, key roachpb.Key, timestamp hlc.Timestamp, - localTimestamp hlc.ClockTimestamp, value roachpb.Value, - txn *roachpb.Transaction, valueFn func(optionalValue) (roachpb.Value, error), + opts MVCCWriteOptions, ) error { buf := newPutBuffer() defer buf.release() @@ -1546,7 +1534,7 @@ func mvccPutUsingIter( // Most callers don't care about the returned exReplaced value. The ones that // do can call mvccPutInternal directly. _, err := mvccPutInternal( - ctx, writer, iter, ms, key, timestamp, localTimestamp, value, txn, buf, valueFn) + ctx, writer, iter, key, timestamp, value, buf, valueFn, opts) return err } @@ -1706,6 +1694,7 @@ func replayTransactionalWrite( return errors.AssertionFailedf("transaction %s with sequence %d has a different value %+v after recomputing from what was written: %+v", txn.ID, txn.Sequence, value.RawBytes, writtenValue.RawBytes) } + return nil } @@ -1748,7 +1737,7 @@ func replayTransactionalWrite( // parameter be set to hlc.Timestamp{} when writing transactionally, but // hlc.Timestamp{} is already used as a sentinel for inline puts.) // -// The local timestamp parameter dictates the local clock timestamp +// The opts.LocalTimestamp parameter dictates the local clock timestamp // assigned to the key-value. It should be taken from the local HLC // clock on the leaseholder that is performing the write and must be // below the leaseholder's lease expiration. If the supplied local @@ -1760,14 +1749,12 @@ func mvccPutInternal( ctx context.Context, writer Writer, iter MVCCIterator, - ms *enginepb.MVCCStats, key roachpb.Key, timestamp hlc.Timestamp, - localTimestamp hlc.ClockTimestamp, value roachpb.Value, - txn *roachpb.Transaction, buf *putBuffer, valueFn func(optionalValue) (roachpb.Value, error), + opts MVCCWriteOptions, ) (bool, error) { if len(key) == 0 { return false, emptyKeyError() @@ -1796,7 +1783,7 @@ func mvccPutInternal( // aren't allowed within transactions. MVCC range tombstones cannot exist // across them either. if putIsInline { - if txn != nil { + if opts.Txn != nil { return false, errors.Errorf("%q: inline writes not allowed within transactions", metaKey) } var metaKeySize, metaValSize int64 @@ -1809,8 +1796,8 @@ func mvccPutInternal( buf.meta = enginepb.MVCCMetadata{RawBytes: value.RawBytes} metaKeySize, metaValSize, err = buf.putInlineMeta(writer, metaKey, &buf.meta) } - if ms != nil { - updateStatsForInline(ms, key, origMetaKeySize, origMetaValSize, metaKeySize, metaValSize) + if opts.Stats != nil { + updateStatsForInline(opts.Stats, key, origMetaKeySize, origMetaValSize, metaKeySize, metaValSize) } return ok && !buf.meta.Deleted, err } @@ -1822,14 +1809,14 @@ func mvccPutInternal( // definition for rationale. readTimestamp := timestamp writeTimestamp := timestamp - if txn != nil { - readTimestamp = txn.ReadTimestamp + if opts.Txn != nil { + readTimestamp = opts.Txn.ReadTimestamp if readTimestamp != timestamp { return false, errors.AssertionFailedf( "mvccPutInternal: txn's read timestamp %s does not match timestamp %s", readTimestamp, timestamp) } - writeTimestamp = txn.WriteTimestamp + writeTimestamp = opts.Txn.WriteTimestamp } timestamp = hlc.Timestamp{} // prevent accidental use below @@ -1837,7 +1824,7 @@ func mvccPutInternal( // Determine what the logical operation is. Are we writing an intent // or a value directly? logicalOp := MVCCWriteValueOpType - if txn != nil { + if opts.Txn != nil { logicalOp = MVCCWriteIntentOpType } @@ -1860,20 +1847,20 @@ func mvccPutInternal( // handling, since they cannot be transactional. if meta.Txn != nil { // There is an uncommitted write intent. - if txn == nil || meta.Txn.ID != txn.ID { + if opts.Txn == nil || meta.Txn.ID != opts.Txn.ID { // The current Put operation does not come from the same // transaction. return false, &kvpb.WriteIntentError{Intents: []roachpb.Intent{ roachpb.MakeIntent(meta.Txn, key), }} - } else if txn.Epoch < meta.Txn.Epoch { + } else if opts.Txn.Epoch < meta.Txn.Epoch { return false, errors.Errorf("put with epoch %d came after put with epoch %d in txn %s", - txn.Epoch, meta.Txn.Epoch, txn.ID) - } else if txn.Epoch == meta.Txn.Epoch && txn.Sequence <= meta.Txn.Sequence { + opts.Txn.Epoch, meta.Txn.Epoch, opts.Txn.ID) + } else if opts.Txn.Epoch == meta.Txn.Epoch && opts.Txn.Sequence <= meta.Txn.Sequence { // The transaction has executed at this sequence before. This is merely a // replay of the transactional write. Assert that all is in order and return // early. - return false, replayTransactionalWrite(ctx, iter, meta, key, readTimestamp, value, txn, valueFn) + return false, replayTransactionalWrite(ctx, iter, meta, key, readTimestamp, value, opts.Txn, valueFn) } // We're overwriting the intent that was present at this key, before we do @@ -1903,8 +1890,8 @@ func mvccPutInternal( // Set when the current provisional value is not ignored due to a txn // restart or a savepoint rollback. Represents an encoded MVCCValue. var curProvValRaw []byte - if txn.Epoch == meta.Txn.Epoch /* last write inside txn */ { - if !enginepb.TxnSeqIsIgnored(meta.Txn.Sequence, txn.IgnoredSeqNums) { + if opts.Txn.Epoch == meta.Txn.Epoch /* last write inside txn */ { + if !enginepb.TxnSeqIsIgnored(meta.Txn.Sequence, opts.Txn.IgnoredSeqNums) { // Seqnum of last write is not ignored. Retrieve the value. iter.SeekGE(oldVersionKey) var hasPoint bool @@ -1930,7 +1917,7 @@ func mvccPutInternal( exVal = makeOptionalValue(curIntentVal.Value) } else { // Seqnum of last write was ignored. Try retrieving the value from the history. - prevIntent, prevIntentOk := meta.GetPrevIntentSeq(txn.Sequence, txn.IgnoredSeqNums) + prevIntent, prevIntentOk := meta.GetPrevIntentSeq(opts.Txn.Sequence, opts.Txn.IgnoredSeqNums) if prevIntentOk { prevIntentVal, err := DecodeMVCCValue(prevIntent.Value) if err != nil { @@ -2047,7 +2034,7 @@ func mvccPutInternal( // transaction are ignored, and there are no past committed values // at this key. In that case, we can also blow up the intent // history. - if txn.Epoch == meta.Txn.Epoch && exVal.exists { + if opts.Txn.Epoch == meta.Txn.Epoch && exVal.exists { // Only add the current provisional value to the intent // history if the current sequence number is not ignored. There's no // reason to add past committed values or a value already in the intent @@ -2090,7 +2077,7 @@ func mvccPutInternal( // timestamp is returned to the caller in maybeTooOldErr. Because // we're outside of a transaction, we'll never actually commit this // value, but that's a concern of evaluateBatch and not here. - if txn == nil { + if opts.Txn == nil { readTimestamp = writeTimestamp } // Inject a function to inspect the existing value at readTimestamp and @@ -2126,7 +2113,7 @@ func mvccPutInternal( versionValue := MVCCValue{} versionValue.Value = value - versionValue.LocalTimestamp = localTimestamp + versionValue.LocalTimestamp = opts.LocalTimestamp if buildutil.CrdbTestBuild { if seq, seqOK := kvnemesisutil.FromContext(ctx); seqOK { @@ -2146,8 +2133,8 @@ func mvccPutInternal( newMeta := &buf.newMeta { var txnMeta *enginepb.TxnMeta - if txn != nil { - txnMeta = &txn.TxnMeta + if opts.Txn != nil { + txnMeta = &opts.Txn.TxnMeta // If we bumped the WriteTimestamp, we update both the TxnMeta and the // MVCCMetadata.Timestamp. if txnMeta.WriteTimestamp != versionKey.Timestamp { @@ -2197,7 +2184,7 @@ func mvccPutInternal( } // Update MVCC stats. - if ms != nil { + if opts.Stats != nil { // Adjust the stats metadata for MVCC range tombstones. The MVCC stats // update only cares about changes to real point keys, but the above logic // needs to care about MVCC range tombstones for conflict purposes. @@ -2213,7 +2200,7 @@ func mvccPutInternal( if meta != nil { meta.Timestamp = origRealKeyChanged.ToLegacyTimestamp() } - ms.Add(updateStatsOnPut(key, prevIsValue, prevValSize, origMetaKeySize, origMetaValSize, + opts.Stats.Add(updateStatsOnPut(key, prevIsValue, prevValSize, origMetaKeySize, origMetaValSize, metaKeySize, metaValSize, meta, newMeta)) } @@ -2244,11 +2231,9 @@ func mvccPutInternal( func MVCCIncrement( ctx context.Context, rw ReadWriter, - ms *enginepb.MVCCStats, key roachpb.Key, timestamp hlc.Timestamp, - localTimestamp hlc.ClockTimestamp, - txn *roachpb.Transaction, + opts MVCCWriteOptions, inc int64, ) (int64, error) { iter := newMVCCIterator( @@ -2286,7 +2271,8 @@ func MVCCIncrement( newValue.InitChecksum(key) return newValue, nil } - err := mvccPutUsingIter(ctx, rw, iter, ms, key, timestamp, localTimestamp, noValue, txn, valueFn) + + err := mvccPutUsingIter(ctx, rw, iter, key, timestamp, noValue, valueFn, opts) return newInt64Val, err } @@ -2321,14 +2307,12 @@ const ( func MVCCConditionalPut( ctx context.Context, rw ReadWriter, - ms *enginepb.MVCCStats, key roachpb.Key, timestamp hlc.Timestamp, - localTimestamp hlc.ClockTimestamp, value roachpb.Value, expVal []byte, allowIfDoesNotExist CPutMissingBehavior, - txn *roachpb.Transaction, + opts MVCCWriteOptions, ) error { iter := newMVCCIterator( rw, timestamp, false /* rangeKeyMasking */, false /* noInterleavedIntents */, IterOptions{ @@ -2339,7 +2323,7 @@ func MVCCConditionalPut( defer iter.Close() return mvccConditionalPutUsingIter( - ctx, rw, iter, ms, key, timestamp, localTimestamp, value, expVal, allowIfDoesNotExist, txn) + ctx, rw, iter, key, timestamp, value, expVal, allowIfDoesNotExist, opts) } // MVCCBlindConditionalPut is a fast-path of MVCCConditionalPut. See the @@ -2354,31 +2338,27 @@ func MVCCConditionalPut( func MVCCBlindConditionalPut( ctx context.Context, writer Writer, - ms *enginepb.MVCCStats, key roachpb.Key, timestamp hlc.Timestamp, - localTimestamp hlc.ClockTimestamp, value roachpb.Value, expVal []byte, allowIfDoesNotExist CPutMissingBehavior, - txn *roachpb.Transaction, + opts MVCCWriteOptions, ) error { return mvccConditionalPutUsingIter( - ctx, writer, nil, ms, key, timestamp, localTimestamp, value, expVal, allowIfDoesNotExist, txn) + ctx, writer, nil, key, timestamp, value, expVal, allowIfDoesNotExist, opts) } func mvccConditionalPutUsingIter( ctx context.Context, writer Writer, iter MVCCIterator, - ms *enginepb.MVCCStats, key roachpb.Key, timestamp hlc.Timestamp, - localTimestamp hlc.ClockTimestamp, value roachpb.Value, expBytes []byte, allowNoExisting CPutMissingBehavior, - txn *roachpb.Transaction, + opts MVCCWriteOptions, ) error { valueFn := func(existVal optionalValue) (roachpb.Value, error) { if expValPresent, existValPresent := len(expBytes) != 0, existVal.IsPresent(); expValPresent && existValPresent { @@ -2394,7 +2374,7 @@ func mvccConditionalPutUsingIter( } return value, nil } - return mvccPutUsingIter(ctx, writer, iter, ms, key, timestamp, localTimestamp, noValue, txn, valueFn) + return mvccPutUsingIter(ctx, writer, iter, key, timestamp, noValue, valueFn, opts) } // MVCCInitPut sets the value for a specified key if the key doesn't exist. It @@ -2409,13 +2389,11 @@ func mvccConditionalPutUsingIter( func MVCCInitPut( ctx context.Context, rw ReadWriter, - ms *enginepb.MVCCStats, key roachpb.Key, timestamp hlc.Timestamp, - localTimestamp hlc.ClockTimestamp, value roachpb.Value, failOnTombstones bool, - txn *roachpb.Transaction, + opts MVCCWriteOptions, ) error { iter := newMVCCIterator( rw, timestamp, false /* rangeKeyMasking */, false /* noInterleavedIntents */, IterOptions{ @@ -2424,7 +2402,7 @@ func MVCCInitPut( }, ) defer iter.Close() - return mvccInitPutUsingIter(ctx, rw, iter, ms, key, timestamp, localTimestamp, value, failOnTombstones, txn) + return mvccInitPutUsingIter(ctx, rw, iter, key, timestamp, value, failOnTombstones, opts) } // MVCCBlindInitPut is a fast-path of MVCCInitPut. See the MVCCInitPut @@ -2438,29 +2416,25 @@ func MVCCInitPut( func MVCCBlindInitPut( ctx context.Context, rw ReadWriter, - ms *enginepb.MVCCStats, key roachpb.Key, timestamp hlc.Timestamp, - localTimestamp hlc.ClockTimestamp, value roachpb.Value, failOnTombstones bool, - txn *roachpb.Transaction, + opts MVCCWriteOptions, ) error { return mvccInitPutUsingIter( - ctx, rw, nil, ms, key, timestamp, localTimestamp, value, failOnTombstones, txn) + ctx, rw, nil, key, timestamp, value, failOnTombstones, opts) } func mvccInitPutUsingIter( ctx context.Context, rw ReadWriter, iter MVCCIterator, - ms *enginepb.MVCCStats, key roachpb.Key, timestamp hlc.Timestamp, - localTimestamp hlc.ClockTimestamp, value roachpb.Value, failOnTombstones bool, - txn *roachpb.Transaction, + opts MVCCWriteOptions, ) error { valueFn := func(existVal optionalValue) (roachpb.Value, error) { if failOnTombstones && existVal.IsTombstone() { @@ -2477,7 +2451,7 @@ func mvccInitPutUsingIter( } return value, nil } - return mvccPutUsingIter(ctx, rw, iter, ms, key, timestamp, localTimestamp, noValue, txn, valueFn) + return mvccPutUsingIter(ctx, rw, iter, key, timestamp, noValue, valueFn, opts) } // mvccKeyFormatter is an fmt.Formatter for MVCC Keys. @@ -2992,12 +2966,10 @@ func MVCCClearTimeRange( func MVCCDeleteRange( ctx context.Context, rw ReadWriter, - ms *enginepb.MVCCStats, key, endKey roachpb.Key, max int64, timestamp hlc.Timestamp, - localTimestamp hlc.ClockTimestamp, - txn *roachpb.Transaction, + opts MVCCWriteOptions, returnKeys bool, ) ([]roachpb.Key, *roachpb.Span, int64, error) { // Scan to find the keys to delete. @@ -3029,8 +3001,8 @@ func MVCCDeleteRange( // need to perform the initial scan at the previous sequence number so that // we don't see the result from equal or later sequences. var scanTxn *roachpb.Transaction - if txn != nil { - prevSeqTxn := txn.Clone() + if opts.Txn != nil { + prevSeqTxn := opts.Txn.Clone() prevSeqTxn.Sequence-- scanTxn = prevSeqTxn } @@ -3054,7 +3026,7 @@ func MVCCDeleteRange( var keys []roachpb.Key for i, kv := range res.KVs { if _, err := mvccPutInternal( - ctx, rw, iter, ms, kv.Key, timestamp, localTimestamp, noValue, txn, buf, nil, + ctx, rw, iter, kv.Key, timestamp, noValue, buf, nil, opts, ); err != nil { return nil, nil, 0, err } @@ -3235,8 +3207,8 @@ func MVCCPredicateDeleteRange( } else { // Use Point tombstones for i := int64(0); i < runSize; i++ { - if _, err := mvccPutInternal(ctx, rw, pointTombstoneIter, ms, buf[i], endTime, localTimestamp, noValue, - nil, pointTombstoneBuf, nil); err != nil { + if _, err := mvccPutInternal(ctx, rw, pointTombstoneIter, buf[i], endTime, noValue, + pointTombstoneBuf, nil, MVCCWriteOptions{LocalTimestamp: localTimestamp, Stats: ms}); err != nil { return err } } @@ -3386,6 +3358,9 @@ func MVCCPredicateDeleteRange( // When deleting an entire Raft range, passing the current MVCCStats as // msCovered and setting left/rightPeekBound to start/endKey will make the // deletion significantly faster. +// +// TODO(sarkesian): Consider accepting MVCCWriteOptions for this function +// and its relevant callers. func MVCCDeleteRangeUsingTombstone( ctx context.Context, rw ReadWriter, @@ -3873,6 +3848,14 @@ func buildScanIntents(data []byte) ([]roachpb.Intent, error) { return intents, nil } +// MVCCWriteOptions bundles options for the MVCCPut and MVCCDelete families of functions. +type MVCCWriteOptions struct { + // See the comment on mvccPutInternal for details on these parameters. + Txn *roachpb.Transaction + LocalTimestamp hlc.ClockTimestamp + Stats *enginepb.MVCCStats +} + // MVCCScanOptions bundles options for the MVCCScan family of functions. type MVCCScanOptions struct { // See the documentation for MVCCScan for information on these parameters. diff --git a/pkg/storage/mvcc_history_test.go b/pkg/storage/mvcc_history_test.go index 10bd0045352a..5cc63e62abbb 100644 --- a/pkg/storage/mvcc_history_test.go +++ b/pkg/storage/mvcc_history_test.go @@ -1087,7 +1087,12 @@ func cmdCPut(e *evalCtx) error { resolve, resolveStatus := e.getResolve() return e.withWriter("cput", func(rw storage.ReadWriter) error { - if err := storage.MVCCConditionalPut(e.ctx, rw, e.ms, key, ts, localTs, val, expVal, behavior, txn); err != nil { + opts := storage.MVCCWriteOptions{ + Txn: txn, + LocalTimestamp: localTs, + Stats: e.ms, + } + if err := storage.MVCCConditionalPut(e.ctx, rw, key, ts, val, expVal, behavior, opts); err != nil { return err } if resolve { @@ -1108,7 +1113,12 @@ func cmdInitPut(e *evalCtx) error { resolve, resolveStatus := e.getResolve() return e.withWriter("initput", func(rw storage.ReadWriter) error { - if err := storage.MVCCInitPut(e.ctx, rw, e.ms, key, ts, localTs, val, failOnTombstones, txn); err != nil { + opts := storage.MVCCWriteOptions{ + Txn: txn, + LocalTimestamp: localTs, + Stats: e.ms, + } + if err := storage.MVCCInitPut(e.ctx, rw, key, ts, val, failOnTombstones, opts); err != nil { return err } if resolve { @@ -1125,7 +1135,12 @@ func cmdDelete(e *evalCtx) error { localTs := hlc.ClockTimestamp(e.getTsWithName("localTs")) resolve, resolveStatus := e.getResolve() return e.withWriter("del", func(rw storage.ReadWriter) error { - foundKey, err := storage.MVCCDelete(e.ctx, rw, e.ms, key, ts, localTs, txn) + opts := storage.MVCCWriteOptions{ + Txn: txn, + LocalTimestamp: localTs, + Stats: e.ms, + } + foundKey, err := storage.MVCCDelete(e.ctx, rw, key, ts, opts) if err == nil || errors.HasType(err, &kvpb.WriteTooOldError{}) { // We want to output foundKey even if a WriteTooOldError is returned, // since the error may be swallowed/deferred during evaluation. @@ -1154,8 +1169,13 @@ func cmdDeleteRange(e *evalCtx) error { resolve, resolveStatus := e.getResolve() return e.withWriter("del_range", func(rw storage.ReadWriter) error { + opts := storage.MVCCWriteOptions{ + Txn: txn, + LocalTimestamp: localTs, + Stats: e.ms, + } deleted, resumeSpan, num, err := storage.MVCCDeleteRange( - e.ctx, rw, e.ms, key, endKey, int64(max), ts, localTs, txn, returnKeys) + e.ctx, rw, key, endKey, int64(max), ts, opts, returnKeys) if err != nil { return err } @@ -1308,7 +1328,12 @@ func cmdIncrement(e *evalCtx) error { resolve, resolveStatus := e.getResolve() return e.withWriter("increment", func(rw storage.ReadWriter) error { - curVal, err := storage.MVCCIncrement(e.ctx, rw, e.ms, key, ts, localTs, txn, inc) + opts := storage.MVCCWriteOptions{ + Txn: txn, + LocalTimestamp: localTs, + Stats: e.ms, + } + curVal, err := storage.MVCCIncrement(e.ctx, rw, key, ts, opts, inc) if err != nil { return err } @@ -1344,7 +1369,12 @@ func cmdPut(e *evalCtx) error { resolve, resolveStatus := e.getResolve() return e.withWriter("put", func(rw storage.ReadWriter) error { - if err := storage.MVCCPut(e.ctx, rw, e.ms, key, ts, localTs, val, txn); err != nil { + opts := storage.MVCCWriteOptions{ + Txn: txn, + LocalTimestamp: localTs, + Stats: e.ms, + } + if err := storage.MVCCPut(e.ctx, rw, key, ts, val, opts); err != nil { return err } if resolve { diff --git a/pkg/storage/mvcc_incremental_iterator_test.go b/pkg/storage/mvcc_incremental_iterator_test.go index 9dd59ed6b1fc..7e272f838518 100644 --- a/pkg/storage/mvcc_incremental_iterator_test.go +++ b/pkg/storage/mvcc_incremental_iterator_test.go @@ -466,7 +466,7 @@ func TestMVCCIncrementalIteratorNextIgnoringTime(t *testing.T) { for _, kv := range kvs(kv1_1_1, kv1_2_2, kv2_2_2) { v := roachpb.Value{RawBytes: kv.Value} - if err := MVCCPut(ctx, e, nil, kv.Key.Key, kv.Key.Timestamp, hlc.ClockTimestamp{}, v, nil); err != nil { + if err := MVCCPut(ctx, e, kv.Key.Key, kv.Key.Timestamp, v, MVCCWriteOptions{}); err != nil { t.Fatal(err) } } @@ -505,7 +505,7 @@ func TestMVCCIncrementalIteratorNextIgnoringTime(t *testing.T) { }) // Exercise deletion. - if _, err := MVCCDelete(ctx, e, nil, testKey1, ts3, hlc.ClockTimestamp{}, nil); err != nil { + if _, err := MVCCDelete(ctx, e, testKey1, ts3, MVCCWriteOptions{}); err != nil { t.Fatal(err) } // Returns the kv_1_1_1 even though it is outside (startTime, endTime]. @@ -525,7 +525,7 @@ func TestMVCCIncrementalIteratorNextIgnoringTime(t *testing.T) { }, ReadTimestamp: ts4, } - if err := MVCCPut(ctx, e, nil, txn1.TxnMeta.Key, txn1.ReadTimestamp, hlc.ClockTimestamp{}, testValue4, &txn1); err != nil { + if err := MVCCPut(ctx, e, txn1.TxnMeta.Key, txn1.ReadTimestamp, testValue4, MVCCWriteOptions{Txn: &txn1}); err != nil { t.Fatal(err) } @@ -602,7 +602,7 @@ func TestMVCCIncrementalIteratorNextKeyIgnoringTime(t *testing.T) { for _, kv := range kvs(kv1_1_1, kv1_2_2, kv2_2_2) { v := roachpb.Value{RawBytes: kv.Value} - if err := MVCCPut(ctx, e, nil, kv.Key.Key, kv.Key.Timestamp, hlc.ClockTimestamp{}, v, nil); err != nil { + if err := MVCCPut(ctx, e, kv.Key.Key, kv.Key.Timestamp, v, MVCCWriteOptions{}); err != nil { t.Fatal(err) } } @@ -638,7 +638,7 @@ func TestMVCCIncrementalIteratorNextKeyIgnoringTime(t *testing.T) { }) // Exercise deletion. - if _, err := MVCCDelete(ctx, e, nil, testKey1, ts3, hlc.ClockTimestamp{}, nil); err != nil { + if _, err := MVCCDelete(ctx, e, testKey1, ts3, MVCCWriteOptions{}); err != nil { t.Fatal(err) } // Returns the kv_1_1_1 even though it is outside (startTime, endTime]. @@ -658,7 +658,7 @@ func TestMVCCIncrementalIteratorNextKeyIgnoringTime(t *testing.T) { }, ReadTimestamp: ts4, } - if err := MVCCPut(ctx, e, nil, txn1.TxnMeta.Key, txn1.ReadTimestamp, hlc.ClockTimestamp{}, testValue4, &txn1); err != nil { + if err := MVCCPut(ctx, e, txn1.TxnMeta.Key, txn1.ReadTimestamp, testValue4, MVCCWriteOptions{Txn: &txn1}); err != nil { t.Fatal(err) } @@ -723,7 +723,7 @@ func TestMVCCIncrementalIteratorInlinePolicy(t *testing.T) { defer e.Close() for _, kv := range []MVCCKeyValue{inline1_1_1, kv2_1_1, kv2_2_2, inline3_2_1} { v := roachpb.Value{RawBytes: kv.Value} - if err := MVCCPut(ctx, e, nil, kv.Key.Key, kv.Key.Timestamp, hlc.ClockTimestamp{}, v, nil); err != nil { + if err := MVCCPut(ctx, e, kv.Key.Key, kv.Key.Timestamp, v, MVCCWriteOptions{}); err != nil { t.Fatal(err) } } @@ -793,11 +793,11 @@ func TestMVCCIncrementalIteratorIntentPolicy(t *testing.T) { defer e.Close() for _, kv := range []MVCCKeyValue{kv1_1_1, kv1_2_2, kv1_3_3, kv2_1_1} { v := roachpb.Value{RawBytes: kv.Value} - if err := MVCCPut(ctx, e, nil, kv.Key.Key, kv.Key.Timestamp, hlc.ClockTimestamp{}, v, nil); err != nil { + if err := MVCCPut(ctx, e, kv.Key.Key, kv.Key.Timestamp, v, MVCCWriteOptions{}); err != nil { t.Fatal(err) } } - if err := MVCCPut(ctx, e, nil, txn.TxnMeta.Key, txn.ReadTimestamp, hlc.ClockTimestamp{}, testValue2, &txn); err != nil { + if err := MVCCPut(ctx, e, txn.TxnMeta.Key, txn.ReadTimestamp, testValue2, MVCCWriteOptions{Txn: &txn}); err != nil { t.Fatal(err) } t.Run("PolicyError returns error if an intent is in the time range", func(t *testing.T) { @@ -958,7 +958,7 @@ func TestMVCCIncrementalIterator(t *testing.T) { for _, kv := range kvs(kv1_1_1, kv1_2_2, kv2_2_2) { v := roachpb.Value{RawBytes: kv.Value} - if err := MVCCPut(ctx, e, nil, kv.Key.Key, kv.Key.Timestamp, hlc.ClockTimestamp{}, v, nil); err != nil { + if err := MVCCPut(ctx, e, kv.Key.Key, kv.Key.Timestamp, v, MVCCWriteOptions{}); err != nil { t.Fatal(err) } } @@ -976,18 +976,18 @@ func TestMVCCIncrementalIterator(t *testing.T) { t.Run("kv [1-2)", assertEqualKVs(e, testKey1, testKey2, tsMin, tsMax, latest, kvs(kv1_2_2))) // Exercise deletion. - if _, err := MVCCDelete(ctx, e, nil, testKey1, ts3, hlc.ClockTimestamp{}, nil); err != nil { + if _, err := MVCCDelete(ctx, e, testKey1, ts3, MVCCWriteOptions{}); err != nil { t.Fatal(err) } t.Run("del", assertEqualKVs(e, localMax, keyMax, ts1, tsMax, latest, kvs(kv1Deleted3, kv2_2_2))) // Exercise intent handling. txn1, intentErr1 := makeKVTxn(testKey1, ts4) - if err := MVCCPut(ctx, e, nil, txn1.TxnMeta.Key, txn1.ReadTimestamp, hlc.ClockTimestamp{}, testValue4, &txn1); err != nil { + if err := MVCCPut(ctx, e, txn1.TxnMeta.Key, txn1.ReadTimestamp, testValue4, MVCCWriteOptions{Txn: &txn1}); err != nil { t.Fatal(err) } txn2, intentErr2 := makeKVTxn(testKey2, ts4) - if err := MVCCPut(ctx, e, nil, txn2.TxnMeta.Key, txn2.ReadTimestamp, hlc.ClockTimestamp{}, testValue4, &txn2); err != nil { + if err := MVCCPut(ctx, e, txn2.TxnMeta.Key, txn2.ReadTimestamp, testValue4, MVCCWriteOptions{Txn: &txn2}); err != nil { t.Fatal(err) } t.Run("intents-1", @@ -1024,7 +1024,7 @@ func TestMVCCIncrementalIterator(t *testing.T) { for _, kv := range kvs(kv1_1_1, kv1_2_2, kv2_2_2) { v := roachpb.Value{RawBytes: kv.Value} - if err := MVCCPut(ctx, e, nil, kv.Key.Key, kv.Key.Timestamp, hlc.ClockTimestamp{}, v, nil); err != nil { + if err := MVCCPut(ctx, e, kv.Key.Key, kv.Key.Timestamp, v, MVCCWriteOptions{}); err != nil { t.Fatal(err) } } @@ -1042,18 +1042,18 @@ func TestMVCCIncrementalIterator(t *testing.T) { t.Run("kv [1-2)", assertEqualKVs(e, testKey1, testKey2, tsMin, tsMax, all, kvs(kv1_2_2, kv1_1_1))) // Exercise deletion. - if _, err := MVCCDelete(ctx, e, nil, testKey1, ts3, hlc.ClockTimestamp{}, nil); err != nil { + if _, err := MVCCDelete(ctx, e, testKey1, ts3, MVCCWriteOptions{}); err != nil { t.Fatal(err) } t.Run("del", assertEqualKVs(e, localMax, keyMax, ts1, tsMax, all, kvs(kv1Deleted3, kv1_2_2, kv2_2_2))) // Exercise intent handling. txn1, intentErr1 := makeKVTxn(testKey1, ts4) - if err := MVCCPut(ctx, e, nil, txn1.TxnMeta.Key, txn1.ReadTimestamp, hlc.ClockTimestamp{}, testValue4, &txn1); err != nil { + if err := MVCCPut(ctx, e, txn1.TxnMeta.Key, txn1.ReadTimestamp, testValue4, MVCCWriteOptions{Txn: &txn1}); err != nil { t.Fatal(err) } txn2, intentErr2 := makeKVTxn(testKey2, ts4) - if err := MVCCPut(ctx, e, nil, txn2.TxnMeta.Key, txn2.ReadTimestamp, hlc.ClockTimestamp{}, testValue4, &txn2); err != nil { + if err := MVCCPut(ctx, e, txn2.TxnMeta.Key, txn2.ReadTimestamp, testValue4, MVCCWriteOptions{Txn: &txn2}); err != nil { t.Fatal(err) } // Single intent tests are verifying behavior when intent collection is not enabled. @@ -1142,7 +1142,7 @@ func TestMVCCIncrementalIteratorIntentRewrittenConcurrently(t *testing.T) { }, ReadTimestamp: ts1, } - if err := MVCCPut(ctx, e, nil, kA, ts1, hlc.ClockTimestamp{}, vA1, txn); err != nil { + if err := MVCCPut(ctx, e, kA, ts1, vA1, MVCCWriteOptions{Txn: txn}); err != nil { t.Fatal(err) } @@ -1160,7 +1160,7 @@ func TestMVCCIncrementalIteratorIntentRewrittenConcurrently(t *testing.T) { // in intentInterleavingIter to be violated. b := e.NewBatch() defer b.Close() - if err := MVCCPut(ctx, b, nil, kA, ts1, hlc.ClockTimestamp{}, vA2, txn); err != nil { + if err := MVCCPut(ctx, b, kA, ts1, vA2, MVCCWriteOptions{Txn: txn}); err != nil { return err } return b.Commit(false) @@ -1255,17 +1255,17 @@ func TestMVCCIncrementalIteratorIntentDeletion(t *testing.T) { // kA:3 -> vA3 // kA:2 -> vA2 // kB -> (intent deletion) - require.NoError(t, MVCCPut(ctx, db, nil, kA, txnA1.ReadTimestamp, hlc.ClockTimestamp{}, vA1, txnA1)) - require.NoError(t, MVCCPut(ctx, db, nil, kB, txnB1.ReadTimestamp, hlc.ClockTimestamp{}, vB1, txnB1)) - require.NoError(t, MVCCPut(ctx, db, nil, kC, txnC1.ReadTimestamp, hlc.ClockTimestamp{}, vC1, txnC1)) + require.NoError(t, MVCCPut(ctx, db, kA, txnA1.ReadTimestamp, vA1, MVCCWriteOptions{Txn: txnA1})) + require.NoError(t, MVCCPut(ctx, db, kB, txnB1.ReadTimestamp, vB1, MVCCWriteOptions{Txn: txnB1})) + require.NoError(t, MVCCPut(ctx, db, kC, txnC1.ReadTimestamp, vC1, MVCCWriteOptions{Txn: txnC1})) require.NoError(t, db.Flush()) require.NoError(t, db.Compact()) _, _, _, err := MVCCResolveWriteIntent(ctx, db, nil, intent(txnA1), MVCCResolveWriteIntentOptions{}) require.NoError(t, err) _, _, _, err = MVCCResolveWriteIntent(ctx, db, nil, intent(txnB1), MVCCResolveWriteIntentOptions{}) require.NoError(t, err) - require.NoError(t, MVCCPut(ctx, db, nil, kA, ts2, hlc.ClockTimestamp{}, vA2, nil)) - require.NoError(t, MVCCPut(ctx, db, nil, kA, txnA3.WriteTimestamp, hlc.ClockTimestamp{}, vA3, txnA3)) + require.NoError(t, MVCCPut(ctx, db, kA, ts2, vA2, MVCCWriteOptions{})) + require.NoError(t, MVCCPut(ctx, db, kA, txnA3.WriteTimestamp, vA3, MVCCWriteOptions{Txn: txnA3})) require.NoError(t, db.Flush()) // The kA ts1 intent has been resolved. There's now a new intent on kA, but @@ -1314,7 +1314,7 @@ func TestMVCCIncrementalIteratorIntentStraddlesSStables(t *testing.T) { put := func(key, value string, ts int64, txn *roachpb.Transaction) { v := roachpb.MakeValueFromString(value) - if err := MVCCPut(ctx, db1, nil, roachpb.Key(key), hlc.Timestamp{WallTime: ts}, hlc.ClockTimestamp{}, v, txn); err != nil { + if err := MVCCPut(ctx, db1, roachpb.Key(key), hlc.Timestamp{WallTime: ts}, v, MVCCWriteOptions{Txn: txn}); err != nil { t.Fatal(err) } } @@ -1600,7 +1600,7 @@ func BenchmarkMVCCIncrementalIteratorForOldData(b *testing.B) { value := roachpb.MakeValueFromBytes(randutil.RandBytes(rng, valueSize)) value.InitChecksum(key) ts := hlc.Timestamp{WallTime: baseTimestamp + 100*int64(i%keyAgeInterval)} - if err := MVCCPut(context.Background(), batch, nil, key, ts, hlc.ClockTimestamp{}, value, nil); err != nil { + if err := MVCCPut(context.Background(), batch, key, ts, value, MVCCWriteOptions{}); err != nil { b.Fatal(err) } } diff --git a/pkg/storage/mvcc_logical_ops_test.go b/pkg/storage/mvcc_logical_ops_test.go index 537eb700d6f0..e837e7fd188c 100644 --- a/pkg/storage/mvcc_logical_ops_test.go +++ b/pkg/storage/mvcc_logical_ops_test.go @@ -36,36 +36,36 @@ func TestMVCCOpLogWriter(t *testing.T) { defer ol.Close() // Write a value and an intent. - if err := MVCCPut(ctx, ol, nil, testKey1, hlc.Timestamp{Logical: 1}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, ol, testKey1, hlc.Timestamp{Logical: 1}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } txn1ts := makeTxn(*txn1, hlc.Timestamp{Logical: 2}) - if err := MVCCPut(ctx, ol, nil, testKey1, txn1ts.ReadTimestamp, hlc.ClockTimestamp{}, value2, txn1ts); err != nil { + if err := MVCCPut(ctx, ol, testKey1, txn1ts.ReadTimestamp, value2, MVCCWriteOptions{Txn: txn1ts}); err != nil { t.Fatal(err) } // Write a value and an intent on local keys. localKey := keys.MakeRangeIDPrefix(1) - if err := MVCCPut(ctx, ol, nil, localKey, hlc.Timestamp{Logical: 1}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, ol, localKey, hlc.Timestamp{Logical: 1}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, ol, nil, localKey, txn1ts.ReadTimestamp, hlc.ClockTimestamp{}, value2, txn1ts); err != nil { + if err := MVCCPut(ctx, ol, localKey, txn1ts.ReadTimestamp, value2, MVCCWriteOptions{Txn: txn1ts}); err != nil { t.Fatal(err) } // Update the intents and write another. txn1ts.Sequence++ txn1ts.WriteTimestamp = hlc.Timestamp{Logical: 3} - if err := MVCCPut(ctx, ol, nil, testKey1, txn1ts.ReadTimestamp, hlc.ClockTimestamp{}, value2, txn1ts); err != nil { + if err := MVCCPut(ctx, ol, testKey1, txn1ts.ReadTimestamp, value2, MVCCWriteOptions{Txn: txn1ts}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, ol, nil, localKey, txn1ts.ReadTimestamp, hlc.ClockTimestamp{}, value2, txn1ts); err != nil { + if err := MVCCPut(ctx, ol, localKey, txn1ts.ReadTimestamp, value2, MVCCWriteOptions{Txn: txn1ts}); err != nil { t.Fatal(err) } // Set the txn timestamp to a larger value than the intent. txn1LargerTS := makeTxn(*txn1, hlc.Timestamp{Logical: 4}) txn1LargerTS.WriteTimestamp = hlc.Timestamp{Logical: 4} - if err := MVCCPut(ctx, ol, nil, testKey2, txn1LargerTS.ReadTimestamp, hlc.ClockTimestamp{}, value3, txn1LargerTS); err != nil { + if err := MVCCPut(ctx, ol, testKey2, txn1LargerTS.ReadTimestamp, value3, MVCCWriteOptions{Txn: txn1LargerTS}); err != nil { t.Fatal(err) } @@ -89,7 +89,7 @@ func TestMVCCOpLogWriter(t *testing.T) { // Write another intent, push it, then abort it. txn2ts := makeTxn(*txn2, hlc.Timestamp{Logical: 5}) - if err := MVCCPut(ctx, ol, nil, testKey3, txn2ts.ReadTimestamp, hlc.ClockTimestamp{}, value4, txn2ts); err != nil { + if err := MVCCPut(ctx, ol, testKey3, txn2ts.ReadTimestamp, value4, MVCCWriteOptions{Txn: txn2ts}); err != nil { t.Fatal(err) } txn2Pushed := *txn2 @@ -110,7 +110,7 @@ func TestMVCCOpLogWriter(t *testing.T) { } // Write an inline value. This should be ignored by the log. - if err := MVCCPut(ctx, ol, nil, testKey6, hlc.Timestamp{}, hlc.ClockTimestamp{}, value6, nil); err != nil { + if err := MVCCPut(ctx, ol, testKey6, hlc.Timestamp{}, value6, MVCCWriteOptions{}); err != nil { t.Fatal(err) } diff --git a/pkg/storage/mvcc_stats_test.go b/pkg/storage/mvcc_stats_test.go index 0a4e1b509865..b635d76d03cb 100644 --- a/pkg/storage/mvcc_stats_test.go +++ b/pkg/storage/mvcc_stats_test.go @@ -98,7 +98,7 @@ func TestMVCCStatsDeleteCommitMovesTimestamp(t *testing.T) { ts1 := hlc.Timestamp{WallTime: 1e9} // Put a value. value := roachpb.MakeValueFromString("value") - if err := MVCCPut(ctx, engine, aggMS, key, ts1, hlc.ClockTimestamp{}, value, nil); err != nil { + if err := MVCCPut(ctx, engine, key, ts1, value, MVCCWriteOptions{Stats: aggMS}); err != nil { t.Fatal(err) } @@ -126,7 +126,7 @@ func TestMVCCStatsDeleteCommitMovesTimestamp(t *testing.T) { TxnMeta: enginepb.TxnMeta{ID: uuid.MakeV4(), WriteTimestamp: ts3}, ReadTimestamp: ts3, } - if _, err := MVCCDelete(ctx, engine, aggMS, key, txn.ReadTimestamp, hlc.ClockTimestamp{}, txn); err != nil { + if _, err := MVCCDelete(ctx, engine, key, txn.ReadTimestamp, MVCCWriteOptions{Txn: txn, Stats: aggMS}); err != nil { t.Fatal(err) } @@ -188,7 +188,7 @@ func TestMVCCStatsPutCommitMovesTimestamp(t *testing.T) { } // Write an intent at t=1s. value := roachpb.MakeValueFromString("value") - if err := MVCCPut(ctx, engine, aggMS, key, ts1, hlc.ClockTimestamp{}, value, txn); err != nil { + if err := MVCCPut(ctx, engine, key, ts1, value, MVCCWriteOptions{Txn: txn, Stats: aggMS}); err != nil { t.Fatal(err) } @@ -277,7 +277,7 @@ func TestMVCCStatsPutPushMovesTimestamp(t *testing.T) { } // Write an intent. value := roachpb.MakeValueFromString("value") - if err := MVCCPut(ctx, engine, aggMS, key, txn.ReadTimestamp, hlc.ClockTimestamp{}, value, txn); err != nil { + if err := MVCCPut(ctx, engine, key, txn.ReadTimestamp, value, MVCCWriteOptions{Txn: txn, Stats: aggMS}); err != nil { t.Fatal(err) } @@ -374,7 +374,7 @@ func TestMVCCStatsDeleteMovesTimestamp(t *testing.T) { // Write an intent. value := roachpb.MakeValueFromString("value") - if err := MVCCPut(ctx, engine, aggMS, key, txn.ReadTimestamp, hlc.ClockTimestamp{}, value, txn); err != nil { + if err := MVCCPut(ctx, engine, key, txn.ReadTimestamp, value, MVCCWriteOptions{Txn: txn, Stats: aggMS}); err != nil { t.Fatal(err) } @@ -449,7 +449,7 @@ func TestMVCCStatsDeleteMovesTimestamp(t *testing.T) { } require.EqualValues(t, expM2ValSize, m2ValSize) - if _, err := MVCCDelete(ctx, engine, aggMS, key, txn.ReadTimestamp, hlc.ClockTimestamp{}, txn); err != nil { + if _, err := MVCCDelete(ctx, engine, key, txn.ReadTimestamp, MVCCWriteOptions{Txn: txn, Stats: aggMS}); err != nil { t.Fatal(err) } @@ -504,7 +504,7 @@ func TestMVCCStatsPutMovesDeletionTimestamp(t *testing.T) { } // Write a deletion tombstone intent. - if _, err := MVCCDelete(ctx, engine, aggMS, key, txn.ReadTimestamp, hlc.ClockTimestamp{}, txn); err != nil { + if _, err := MVCCDelete(ctx, engine, key, txn.ReadTimestamp, MVCCWriteOptions{Txn: txn, Stats: aggMS}); err != nil { t.Fatal(err) } @@ -577,7 +577,7 @@ func TestMVCCStatsPutMovesDeletionTimestamp(t *testing.T) { require.EqualValues(t, vVal2Size, 17) } - if err := MVCCPut(ctx, engine, aggMS, key, txn.ReadTimestamp, hlc.ClockTimestamp{}, value, txn); err != nil { + if err := MVCCPut(ctx, engine, key, txn.ReadTimestamp, value, MVCCWriteOptions{Txn: txn, Stats: aggMS}); err != nil { t.Fatal(err) } @@ -625,7 +625,7 @@ func TestMVCCStatsDelDelCommitMovesTimestamp(t *testing.T) { ts3 := hlc.Timestamp{WallTime: 3e9} // Write a non-transactional tombstone at t=1s. - if _, err := MVCCDelete(ctx, engine, aggMS, key, ts1, hlc.ClockTimestamp{}, nil); err != nil { + if _, err := MVCCDelete(ctx, engine, key, ts1, MVCCWriteOptions{Stats: aggMS}); err != nil { t.Fatal(err) } @@ -654,7 +654,7 @@ func TestMVCCStatsDelDelCommitMovesTimestamp(t *testing.T) { TxnMeta: enginepb.TxnMeta{ID: uuid.MakeV4(), WriteTimestamp: ts2}, ReadTimestamp: ts2, } - if _, err := MVCCDelete(ctx, engine, aggMS, key, txn.ReadTimestamp, hlc.ClockTimestamp{}, txn); err != nil { + if _, err := MVCCDelete(ctx, engine, key, txn.ReadTimestamp, MVCCWriteOptions{Txn: txn, Stats: aggMS}); err != nil { t.Fatal(err) } @@ -779,7 +779,7 @@ func TestMVCCStatsPutDelPutMovesTimestamp(t *testing.T) { // Write a non-transactional value at t=1s. value := roachpb.MakeValueFromString("value") - if err := MVCCPut(ctx, engine, aggMS, key, ts1, hlc.ClockTimestamp{}, value, nil); err != nil { + if err := MVCCPut(ctx, engine, key, ts1, value, MVCCWriteOptions{Stats: aggMS}); err != nil { t.Fatal(err) } @@ -812,7 +812,7 @@ func TestMVCCStatsPutDelPutMovesTimestamp(t *testing.T) { TxnMeta: enginepb.TxnMeta{ID: uuid.MakeV4(), WriteTimestamp: ts2}, ReadTimestamp: ts2, } - if _, err := MVCCDelete(ctx, engine, aggMS, key, txn.ReadTimestamp, hlc.ClockTimestamp{}, txn); err != nil { + if _, err := MVCCDelete(ctx, engine, key, txn.ReadTimestamp, MVCCWriteOptions{Txn: txn, Stats: aggMS}); err != nil { t.Fatal(err) } @@ -903,7 +903,7 @@ func TestMVCCStatsPutDelPutMovesTimestamp(t *testing.T) { } txn.WriteTimestamp.Forward(ts3) - if err := MVCCPut(ctx, engine, &aggMS, key, txn.ReadTimestamp, hlc.ClockTimestamp{}, val2, txn); err != nil { + if err := MVCCPut(ctx, engine, key, txn.ReadTimestamp, val2, MVCCWriteOptions{Txn: txn, Stats: &aggMS}); err != nil { t.Fatal(err) } @@ -963,10 +963,10 @@ func TestMVCCStatsDelDelGC(t *testing.T) { ts2 := hlc.Timestamp{WallTime: 2e9} // Write tombstones at ts1 and ts2. - if _, err := MVCCDelete(ctx, engine, aggMS, key, ts1, hlc.ClockTimestamp{}, nil); err != nil { + if _, err := MVCCDelete(ctx, engine, key, ts1, MVCCWriteOptions{Stats: aggMS}); err != nil { t.Fatal(err) } - if _, err := MVCCDelete(ctx, engine, aggMS, key, ts2, hlc.ClockTimestamp{}, nil); err != nil { + if _, err := MVCCDelete(ctx, engine, key, ts2, MVCCWriteOptions{Stats: aggMS}); err != nil { t.Fatal(err) } @@ -1046,7 +1046,7 @@ func TestMVCCStatsPutIntentTimestampNotPutTimestamp(t *testing.T) { } // Write an intent at 2s+1. value := roachpb.MakeValueFromString("value") - if err := MVCCPut(ctx, engine, aggMS, key, txn.ReadTimestamp, hlc.ClockTimestamp{}, value, txn); err != nil { + if err := MVCCPut(ctx, engine, key, txn.ReadTimestamp, value, MVCCWriteOptions{Txn: txn, Stats: aggMS}); err != nil { t.Fatal(err) } @@ -1096,7 +1096,7 @@ func TestMVCCStatsPutIntentTimestampNotPutTimestamp(t *testing.T) { {Sequence: 0, Value: encValue}, }, }).Size()) - if err := MVCCPut(ctx, engine, aggMS, key, txn.ReadTimestamp, hlc.ClockTimestamp{}, value, txn); err != nil { + if err := MVCCPut(ctx, engine, key, txn.ReadTimestamp, value, MVCCWriteOptions{Txn: txn, Stats: aggMS}); err != nil { t.Fatal(err) } @@ -1141,7 +1141,7 @@ func TestMVCCStatsPutWaitDeleteGC(t *testing.T) { // Write a value at ts1. val1 := roachpb.MakeValueFromString("value") - if err := MVCCPut(ctx, engine, aggMS, key, ts1, hlc.ClockTimestamp{}, val1, nil); err != nil { + if err := MVCCPut(ctx, engine, key, ts1, val1, MVCCWriteOptions{Stats: aggMS}); err != nil { t.Fatal(err) } @@ -1171,7 +1171,7 @@ func TestMVCCStatsPutWaitDeleteGC(t *testing.T) { // Delete the value at ts5. - if _, err := MVCCDelete(ctx, engine, aggMS, key, ts2, hlc.ClockTimestamp{}, nil); err != nil { + if _, err := MVCCDelete(ctx, engine, key, ts2, MVCCWriteOptions{Stats: aggMS}); err != nil { t.Fatal(err) } @@ -1240,7 +1240,7 @@ func TestMVCCStatsTxnSysPutPut(t *testing.T) { // Write an intent at ts1. val1 := roachpb.MakeValueFromString("value") - if err := MVCCPut(ctx, engine, aggMS, key, txn.ReadTimestamp, hlc.ClockTimestamp{}, val1, txn); err != nil { + if err := MVCCPut(ctx, engine, key, txn.ReadTimestamp, val1, MVCCWriteOptions{Txn: txn, Stats: aggMS}); err != nil { t.Fatal(err) } @@ -1303,7 +1303,7 @@ func TestMVCCStatsTxnSysPutPut(t *testing.T) { } require.EqualValues(t, expMVal2Size, mVal2Size) - if err := MVCCPut(ctx, engine, aggMS, key, txn.ReadTimestamp, hlc.ClockTimestamp{}, val2, txn); err != nil { + if err := MVCCPut(ctx, engine, key, txn.ReadTimestamp, val2, MVCCWriteOptions{Txn: txn, Stats: aggMS}); err != nil { t.Fatal(err) } @@ -1340,7 +1340,7 @@ func TestMVCCStatsTxnSysPutAbort(t *testing.T) { // Write a system intent at ts1. val1 := roachpb.MakeValueFromString("value") - if err := MVCCPut(ctx, engine, aggMS, key, txn.ReadTimestamp, hlc.ClockTimestamp{}, val1, txn); err != nil { + if err := MVCCPut(ctx, engine, key, txn.ReadTimestamp, val1, MVCCWriteOptions{Txn: txn, Stats: aggMS}); err != nil { t.Fatal(err) } @@ -1415,7 +1415,7 @@ func TestMVCCStatsSysPutPut(t *testing.T) { // Write a value at ts1. val1 := roachpb.MakeValueFromString("value") - if err := MVCCPut(ctx, engine, aggMS, key, ts1, hlc.ClockTimestamp{}, val1, nil); err != nil { + if err := MVCCPut(ctx, engine, key, ts1, val1, MVCCWriteOptions{Stats: aggMS}); err != nil { t.Fatal(err) } @@ -1449,7 +1449,7 @@ func TestMVCCStatsSysPutPut(t *testing.T) { // Put another value at ts2. - if err := MVCCPut(ctx, engine, aggMS, key, ts2, hlc.ClockTimestamp{}, val2, nil); err != nil { + if err := MVCCPut(ctx, engine, key, ts2, val2, MVCCWriteOptions{Stats: aggMS}); err != nil { t.Fatal(err) } @@ -1642,26 +1642,42 @@ func TestMVCCStatsRandomized(t *testing.T) { } actions["Put"] = func(s *state) (bool, string) { - if err := MVCCPut(ctx, s.batch, s.MSDelta, s.key, s.TS, hlc.ClockTimestamp{}, s.rngVal(), s.Txn); err != nil { + opts := MVCCWriteOptions{ + Txn: s.Txn, + Stats: s.MSDelta, + } + if err := MVCCPut(ctx, s.batch, s.key, s.TS, s.rngVal(), opts); err != nil { return false, err.Error() } return true, "" } actions["InitPut"] = func(s *state) (bool, string) { + opts := MVCCWriteOptions{ + Txn: s.Txn, + Stats: s.MSDelta, + } failOnTombstones := s.rng.Intn(2) == 0 desc := fmt.Sprintf("failOnTombstones=%t", failOnTombstones) - if err := MVCCInitPut(ctx, s.batch, s.MSDelta, s.key, s.TS, hlc.ClockTimestamp{}, s.rngVal(), failOnTombstones, s.Txn); err != nil { + if err := MVCCInitPut(ctx, s.batch, s.key, s.TS, s.rngVal(), failOnTombstones, opts); err != nil { return false, desc + ": " + err.Error() } return true, desc } actions["Del"] = func(s *state) (bool, string) { - if _, err := MVCCDelete(ctx, s.batch, s.MSDelta, s.key, s.TS, hlc.ClockTimestamp{}, s.Txn); err != nil { + opts := MVCCWriteOptions{ + Txn: s.Txn, + Stats: s.MSDelta, + } + if _, err := MVCCDelete(ctx, s.batch, s.key, s.TS, opts); err != nil { return false, err.Error() } return true, "" } actions["DelRange"] = func(s *state) (bool, string) { + opts := MVCCWriteOptions{ + Txn: s.Txn, + Stats: s.MSDelta, + } keySpan := currentKeySpan(s) mvccRangeDel := !s.isLocalKey && s.Txn == nil && s.rng.Intn(2) == 0 @@ -1699,7 +1715,7 @@ func TestMVCCStatsRandomized(t *testing.T) { if !mvccRangeDel { desc = fmt.Sprintf("mvccDeleteRange=%s, returnKeys=%t, max=%d", keySpan, returnKeys, max) _, _, _, err = MVCCDeleteRange( - ctx, s.batch, s.MSDelta, keySpan.Key, keySpan.EndKey, max, s.TS, hlc.ClockTimestamp{}, s.Txn, returnKeys, + ctx, s.batch, keySpan.Key, keySpan.EndKey, max, s.TS, opts, returnKeys, ) } else if predicates == (kvpb.DeleteRangePredicates{}) { desc = fmt.Sprintf("mvccDeleteRangeUsingTombstone=%s", diff --git a/pkg/storage/mvcc_test.go b/pkg/storage/mvcc_test.go index 24071ea7f9ab..04ceacedbca2 100644 --- a/pkg/storage/mvcc_test.go +++ b/pkg/storage/mvcc_test.go @@ -270,10 +270,10 @@ func TestMVCCGetNoMoreOldVersion(t *testing.T) { // b // // If we search for a, the scan should not return "b". - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 3}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 3}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey2, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value2, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey2, hlc.Timestamp{WallTime: 1}, value2, MVCCWriteOptions{}); err != nil { t.Fatal(err) } valueRes, err := MVCCGet(ctx, engine, testKey1, hlc.Timestamp{WallTime: 2}, MVCCGetOptions{}) @@ -293,7 +293,7 @@ func TestMVCCGetWithValueHeader(t *testing.T) { engine := NewDefaultInMemForTesting() defer engine.Close() - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 1, Logical: 1}, hlc.ClockTimestamp{WallTime: 1}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 1, Logical: 1}, value1, MVCCWriteOptions{LocalTimestamp: hlc.ClockTimestamp{WallTime: 1}}); err != nil { t.Fatal(err) } valueRes, vh, err := MVCCGetWithValueHeader(ctx, engine, testKey1, hlc.Timestamp{WallTime: 2}, MVCCGetOptions{}) @@ -305,7 +305,7 @@ func TestMVCCGetWithValueHeader(t *testing.T) { } require.Equal(t, hlc.ClockTimestamp{WallTime: 1}, vh.LocalTimestamp) - _, err = MVCCDelete(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 3}, hlc.ClockTimestamp{WallTime: 2, Logical: 1}, nil) + _, err = MVCCDelete(ctx, engine, testKey1, hlc.Timestamp{WallTime: 3}, MVCCWriteOptions{LocalTimestamp: hlc.ClockTimestamp{WallTime: 2, Logical: 1}}) if err != nil { t.Fatal(err) } @@ -354,11 +354,11 @@ func TestMVCCWriteWithOlderTimestampAfterDeletionOfNonexistentKey(t *testing.T) engine := NewDefaultInMemForTesting() defer engine.Close() - if _, err := MVCCDelete(context.Background(), engine, nil, testKey1, hlc.Timestamp{WallTime: 3}, hlc.ClockTimestamp{}, nil); err != nil { + if _, err := MVCCDelete(context.Background(), engine, testKey1, hlc.Timestamp{WallTime: 3}, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(context.Background(), engine, nil, testKey1, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value1, nil); !testutils.IsError( + if err := MVCCPut(context.Background(), engine, testKey1, hlc.Timestamp{WallTime: 1}, value1, MVCCWriteOptions{}); !testutils.IsError( err, "write for key \"/db1\" at timestamp 0.000000001,0 too old; wrote at 0.000000003,1", ) { t.Fatal(err) @@ -401,7 +401,7 @@ func TestMVCCInlineWithTxn(t *testing.T) { defer engine.Close() // Put an inline value. - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } @@ -423,7 +423,7 @@ func TestMVCCInlineWithTxn(t *testing.T) { } // Verify inline put with txn is an error. - err = MVCCPut(ctx, engine, nil, testKey2, hlc.Timestamp{}, hlc.ClockTimestamp{}, value2, txn2) + err = MVCCPut(ctx, engine, testKey2, hlc.Timestamp{}, value2, MVCCWriteOptions{Txn: txn2}) if !testutils.IsError(err, "writes not allowed within transactions") { t.Errorf("unexpected error: %+v", err) } @@ -439,7 +439,7 @@ func TestMVCCDeleteMissingKey(t *testing.T) { engine := NewDefaultInMemForTesting() defer engine.Close() - if _, err := MVCCDelete(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, nil); err != nil { + if _, err := MVCCDelete(ctx, engine, testKey1, hlc.Timestamp{WallTime: 1}, MVCCWriteOptions{}); err != nil { t.Fatal(err) } require.Empty(t, mvccGetRaw(t, engine, mvccKey(testKey1))) @@ -456,7 +456,7 @@ func TestMVCCGetAndDeleteInTxn(t *testing.T) { txn := makeTxn(*txn1, hlc.Timestamp{WallTime: 1}) txn.Sequence++ - if err := MVCCPut(ctx, engine, nil, testKey1, txn.ReadTimestamp, hlc.ClockTimestamp{}, value1, txn); err != nil { + if err := MVCCPut(ctx, engine, testKey1, txn.ReadTimestamp, value1, MVCCWriteOptions{Txn: txn}); err != nil { t.Fatal(err) } @@ -470,7 +470,7 @@ func TestMVCCGetAndDeleteInTxn(t *testing.T) { txn.Sequence++ txn.WriteTimestamp = hlc.Timestamp{WallTime: 3} - if _, err := MVCCDelete(ctx, engine, nil, testKey1, txn.ReadTimestamp, hlc.ClockTimestamp{}, txn); err != nil { + if _, err := MVCCDelete(ctx, engine, testKey1, txn.ReadTimestamp, MVCCWriteOptions{Txn: txn}); err != nil { t.Fatal(err) } @@ -509,7 +509,7 @@ func TestMVCCGetWriteIntentError(t *testing.T) { engine := NewDefaultInMemForTesting() defer engine.Close() - if err := MVCCPut(ctx, engine, nil, testKey1, txn1.ReadTimestamp, hlc.ClockTimestamp{}, value1, txn1); err != nil { + if err := MVCCPut(ctx, engine, testKey1, txn1.ReadTimestamp, value1, MVCCWriteOptions{Txn: txn1}); err != nil { t.Fatal(err) } @@ -562,7 +562,7 @@ func TestMVCCScanWriteIntentError(t *testing.T) { for i, kv := range fixtureKVs { v := *protoutil.Clone(&kv.Value).(*roachpb.Value) v.Timestamp = hlc.Timestamp{} - if err := MVCCPut(ctx, engine, nil, kv.Key, kv.Value.Timestamp, hlc.ClockTimestamp{}, v, txnMap[i]); err != nil { + if err := MVCCPut(ctx, engine, kv.Key, kv.Value.Timestamp, v, MVCCWriteOptions{Txn: txnMap[i]}); err != nil { t.Fatal(err) } } @@ -665,11 +665,11 @@ func TestMVCCGetInconsistent(t *testing.T) { defer engine.Close() // Put two values to key 1, the latest with a txn. - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 1}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } txn1ts := makeTxn(*txn1, hlc.Timestamp{WallTime: 2}) - if err := MVCCPut(ctx, engine, nil, testKey1, txn1ts.ReadTimestamp, hlc.ClockTimestamp{}, value2, txn1ts); err != nil { + if err := MVCCPut(ctx, engine, testKey1, txn1ts.ReadTimestamp, value2, MVCCWriteOptions{Txn: txn1ts}); err != nil { t.Fatal(err) } @@ -699,7 +699,7 @@ func TestMVCCGetInconsistent(t *testing.T) { } // Write a single intent for key 2 and verify get returns empty. - if err := MVCCPut(ctx, engine, nil, testKey2, txn2.ReadTimestamp, hlc.ClockTimestamp{}, value1, txn2); err != nil { + if err := MVCCPut(ctx, engine, testKey2, txn2.ReadTimestamp, value1, MVCCWriteOptions{Txn: txn2}); err != nil { t.Fatal(err) } res, err := MVCCGet(ctx, engine, testKey2, hlc.Timestamp{WallTime: 2}, @@ -735,11 +735,11 @@ func TestMVCCGetProtoInconsistent(t *testing.T) { v2 := roachpb.MakeValueFromBytes(bytes2) // Put two values to key 1, the latest with a txn. - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, v1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 1}, v1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } txn1ts := makeTxn(*txn1, hlc.Timestamp{WallTime: 2}) - if err := MVCCPut(ctx, engine, nil, testKey1, txn1ts.ReadTimestamp, hlc.ClockTimestamp{}, v2, txn1ts); err != nil { + if err := MVCCPut(ctx, engine, testKey1, txn1ts.ReadTimestamp, v2, MVCCWriteOptions{Txn: txn1ts}); err != nil { t.Fatal(err) } @@ -781,7 +781,7 @@ func TestMVCCGetProtoInconsistent(t *testing.T) { { // Write a single intent for key 2 and verify get returns empty. - if err := MVCCPut(ctx, engine, nil, testKey2, txn2.ReadTimestamp, hlc.ClockTimestamp{}, v1, txn2); err != nil { + if err := MVCCPut(ctx, engine, testKey2, txn2.ReadTimestamp, v1, MVCCWriteOptions{Txn: txn2}); err != nil { t.Fatal(err) } val := roachpb.Value{} @@ -800,10 +800,10 @@ func TestMVCCGetProtoInconsistent(t *testing.T) { // Write a malformed value (not an encoded MVCCKeyValue) and a // write intent to key 3; the parse error is returned instead of the // write intent. - if err := MVCCPut(ctx, engine, nil, testKey3, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value3, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey3, hlc.Timestamp{WallTime: 1}, value3, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey3, txn1ts.ReadTimestamp, hlc.ClockTimestamp{}, v2, txn1ts); err != nil { + if err := MVCCPut(ctx, engine, testKey3, txn1ts.ReadTimestamp, v2, MVCCWriteOptions{Txn: txn1ts}); err != nil { t.Fatal(err) } val := roachpb.Value{} @@ -837,7 +837,7 @@ func TestMVCCInvalidateIterator(t *testing.T) { ts2 := hlc.Timestamp{WallTime: 2} key := roachpb.Key("a") - if err := MVCCPut(ctx, engine, nil, key, ts1, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, key, ts1, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } @@ -892,28 +892,28 @@ func TestMVCCInvalidateIterator(t *testing.T) { } func mvccScanTest(ctx context.Context, t *testing.T, engine Engine) { - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 1}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 2}, hlc.ClockTimestamp{}, value4, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 2}, value4, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey2, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value2, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey2, hlc.Timestamp{WallTime: 1}, value2, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey2, hlc.Timestamp{WallTime: 3}, hlc.ClockTimestamp{}, value3, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey2, hlc.Timestamp{WallTime: 3}, value3, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey3, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value3, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey3, hlc.Timestamp{WallTime: 1}, value3, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey3, hlc.Timestamp{WallTime: 4}, hlc.ClockTimestamp{}, value2, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey3, hlc.Timestamp{WallTime: 4}, value2, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey4, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value4, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey4, hlc.Timestamp{WallTime: 1}, value4, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey4, hlc.Timestamp{WallTime: 5}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey4, hlc.Timestamp{WallTime: 5}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } @@ -1006,19 +1006,19 @@ func TestMVCCScanMaxNum(t *testing.T) { engine := NewDefaultInMemForTesting() defer engine.Close() - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 1}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey2, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value2, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey2, hlc.Timestamp{WallTime: 1}, value2, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey3, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value3, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey3, hlc.Timestamp{WallTime: 1}, value3, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey4, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value4, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey4, hlc.Timestamp{WallTime: 1}, value4, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey6, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value4, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey6, hlc.Timestamp{WallTime: 1}, value4, MVCCWriteOptions{}); err != nil { t.Fatal(err) } @@ -1094,19 +1094,19 @@ func TestMVCCScanWithKeyPrefix(t *testing.T) { // b // In this case, if we scan from "a"-"b", we wish to skip // a and a and find "aa'. - if err := MVCCPut(ctx, engine, nil, roachpb.Key("/a"), hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, roachpb.Key("/a"), hlc.Timestamp{WallTime: 1}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, roachpb.Key("/a"), hlc.Timestamp{WallTime: 2}, hlc.ClockTimestamp{}, value2, nil); err != nil { + if err := MVCCPut(ctx, engine, roachpb.Key("/a"), hlc.Timestamp{WallTime: 2}, value2, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, roachpb.Key("/aa"), hlc.Timestamp{WallTime: 2}, hlc.ClockTimestamp{}, value2, nil); err != nil { + if err := MVCCPut(ctx, engine, roachpb.Key("/aa"), hlc.Timestamp{WallTime: 2}, value2, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, roachpb.Key("/aa"), hlc.Timestamp{WallTime: 3}, hlc.ClockTimestamp{}, value3, nil); err != nil { + if err := MVCCPut(ctx, engine, roachpb.Key("/aa"), hlc.Timestamp{WallTime: 3}, value3, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, roachpb.Key("/b"), hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value3, nil); err != nil { + if err := MVCCPut(ctx, engine, roachpb.Key("/b"), hlc.Timestamp{WallTime: 1}, value3, MVCCWriteOptions{}); err != nil { t.Fatal(err) } @@ -1132,17 +1132,17 @@ func TestMVCCScanInTxn(t *testing.T) { engine := NewDefaultInMemForTesting() defer engine.Close() - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 1}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey2, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value2, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey2, hlc.Timestamp{WallTime: 1}, value2, MVCCWriteOptions{}); err != nil { t.Fatal(err) } txn := makeTxn(*txn1, hlc.Timestamp{WallTime: 1}) - if err := MVCCPut(ctx, engine, nil, testKey3, txn.ReadTimestamp, hlc.ClockTimestamp{}, value3, txn); err != nil { + if err := MVCCPut(ctx, engine, testKey3, txn.ReadTimestamp, value3, MVCCWriteOptions{Txn: txn}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey4, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value4, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey4, hlc.Timestamp{WallTime: 1}, value4, MVCCWriteOptions{}); err != nil { t.Fatal(err) } @@ -1190,24 +1190,24 @@ func TestMVCCScanInconsistent(t *testing.T) { ts4 := hlc.Timestamp{WallTime: 4} ts5 := hlc.Timestamp{WallTime: 5} ts6 := hlc.Timestamp{WallTime: 6} - if err := MVCCPut(ctx, engine, nil, testKey1, ts1, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, ts1, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } txn1ts2 := makeTxn(*txn1, ts2) - if err := MVCCPut(ctx, engine, nil, testKey1, txn1ts2.ReadTimestamp, hlc.ClockTimestamp{}, value2, txn1ts2); err != nil { + if err := MVCCPut(ctx, engine, testKey1, txn1ts2.ReadTimestamp, value2, MVCCWriteOptions{Txn: txn1ts2}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey2, ts3, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey2, ts3, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey2, ts4, hlc.ClockTimestamp{}, value2, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey2, ts4, value2, MVCCWriteOptions{}); err != nil { t.Fatal(err) } txn2ts5 := makeTxn(*txn2, ts5) - if err := MVCCPut(ctx, engine, nil, testKey3, txn2ts5.ReadTimestamp, hlc.ClockTimestamp{}, value3, txn2ts5); err != nil { + if err := MVCCPut(ctx, engine, testKey3, txn2ts5.ReadTimestamp, value3, MVCCWriteOptions{Txn: txn2ts5}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey4, ts6, hlc.ClockTimestamp{}, value4, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey4, ts6, value4, MVCCWriteOptions{}); err != nil { t.Fatal(err) } @@ -1264,28 +1264,28 @@ func TestMVCCDeleteRange(t *testing.T) { engine := NewDefaultInMemForTesting() defer engine.Close() - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 1}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey2, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value2, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey2, hlc.Timestamp{WallTime: 1}, value2, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey3, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value3, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey3, hlc.Timestamp{WallTime: 1}, value3, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey4, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value4, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey4, hlc.Timestamp{WallTime: 1}, value4, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey5, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value5, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey5, hlc.Timestamp{WallTime: 1}, value5, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey6, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value6, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey6, hlc.Timestamp{WallTime: 1}, value6, MVCCWriteOptions{}); err != nil { t.Fatal(err) } // Attempt to delete two keys. - deleted, resumeSpan, num, err := MVCCDeleteRange(ctx, engine, nil, testKey2, testKey6, - 2, hlc.Timestamp{WallTime: 2}, hlc.ClockTimestamp{}, nil, false) + deleted, resumeSpan, num, err := MVCCDeleteRange(ctx, engine, testKey2, testKey6, + 2, hlc.Timestamp{WallTime: 2}, MVCCWriteOptions{}, false) if err != nil { t.Fatal(err) } @@ -1340,8 +1340,8 @@ func TestMVCCDeleteRange(t *testing.T) { } // Attempt to delete no keys. - deleted, resumeSpan, num, err = MVCCDeleteRange(ctx, engine, nil, testKey2, testKey6, - -1, hlc.Timestamp{WallTime: 2}, hlc.ClockTimestamp{}, nil, false) + deleted, resumeSpan, num, err = MVCCDeleteRange(ctx, engine, testKey2, testKey6, + -1, hlc.Timestamp{WallTime: 2}, MVCCWriteOptions{}, false) if err != nil { t.Fatal(err) } @@ -1368,8 +1368,8 @@ func TestMVCCDeleteRange(t *testing.T) { t.Fatal("the value should not be empty") } - deleted, resumeSpan, num, err = MVCCDeleteRange(ctx, engine, nil, testKey4, keyMax, - 0, hlc.Timestamp{WallTime: 2}, hlc.ClockTimestamp{}, nil, false) + deleted, resumeSpan, num, err = MVCCDeleteRange(ctx, engine, testKey4, keyMax, + 0, hlc.Timestamp{WallTime: 2}, MVCCWriteOptions{}, false) if err != nil { t.Fatal(err) } @@ -1393,8 +1393,8 @@ func TestMVCCDeleteRange(t *testing.T) { t.Fatalf("the value should not be empty: %+v", res.KVs) } - deleted, resumeSpan, num, err = MVCCDeleteRange(ctx, engine, nil, localMax, testKey2, - 0, hlc.Timestamp{WallTime: 2}, hlc.ClockTimestamp{}, nil, false) + deleted, resumeSpan, num, err = MVCCDeleteRange(ctx, engine, localMax, testKey2, + 0, hlc.Timestamp{WallTime: 2}, MVCCWriteOptions{}, false) if err != nil { t.Fatal(err) } @@ -1425,28 +1425,28 @@ func TestMVCCDeleteRangeReturnKeys(t *testing.T) { engine := NewDefaultInMemForTesting() defer engine.Close() - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 1}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey2, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value2, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey2, hlc.Timestamp{WallTime: 1}, value2, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey3, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value3, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey3, hlc.Timestamp{WallTime: 1}, value3, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey4, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value4, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey4, hlc.Timestamp{WallTime: 1}, value4, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey5, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value5, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey5, hlc.Timestamp{WallTime: 1}, value5, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey6, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value6, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey6, hlc.Timestamp{WallTime: 1}, value6, MVCCWriteOptions{}); err != nil { t.Fatal(err) } // Attempt to delete two keys. - deleted, resumeSpan, num, err := MVCCDeleteRange(ctx, engine, nil, testKey2, testKey6, - 2, hlc.Timestamp{WallTime: 2}, hlc.ClockTimestamp{}, nil, true) + deleted, resumeSpan, num, err := MVCCDeleteRange(ctx, engine, testKey2, testKey6, + 2, hlc.Timestamp{WallTime: 2}, MVCCWriteOptions{}, true) if err != nil { t.Fatal(err) } @@ -1480,8 +1480,8 @@ func TestMVCCDeleteRangeReturnKeys(t *testing.T) { } // Attempt to delete no keys. - deleted, resumeSpan, num, err = MVCCDeleteRange(ctx, engine, nil, testKey2, testKey6, - -1, hlc.Timestamp{WallTime: 2}, hlc.ClockTimestamp{}, nil, true) + deleted, resumeSpan, num, err = MVCCDeleteRange(ctx, engine, testKey2, testKey6, + -1, hlc.Timestamp{WallTime: 2}, MVCCWriteOptions{}, true) if err != nil { t.Fatal(err) } @@ -1508,8 +1508,8 @@ func TestMVCCDeleteRangeReturnKeys(t *testing.T) { t.Fatal("the value should not be empty") } - deleted, resumeSpan, num, err = MVCCDeleteRange(ctx, engine, nil, testKey4, keyMax, - math.MaxInt64, hlc.Timestamp{WallTime: 2}, hlc.ClockTimestamp{}, nil, true) + deleted, resumeSpan, num, err = MVCCDeleteRange(ctx, engine, testKey4, keyMax, + math.MaxInt64, hlc.Timestamp{WallTime: 2}, MVCCWriteOptions{}, true) if err != nil { t.Fatal(err) } @@ -1539,8 +1539,8 @@ func TestMVCCDeleteRangeReturnKeys(t *testing.T) { t.Fatal("the value should not be empty") } - deleted, resumeSpan, num, err = MVCCDeleteRange(ctx, engine, nil, localMax, testKey2, - math.MaxInt64, hlc.Timestamp{WallTime: 2}, hlc.ClockTimestamp{}, nil, true) + deleted, resumeSpan, num, err = MVCCDeleteRange(ctx, engine, localMax, testKey2, + math.MaxInt64, hlc.Timestamp{WallTime: 2}, MVCCWriteOptions{}, true) if err != nil { t.Fatal(err) } @@ -1572,29 +1572,29 @@ func TestMVCCDeleteRangeFailed(t *testing.T) { defer engine.Close() txn := makeTxn(*txn1, hlc.Timestamp{WallTime: 1}) - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 1}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } txn.Sequence++ - if err := MVCCPut(ctx, engine, nil, testKey2, txn.ReadTimestamp, hlc.ClockTimestamp{}, value2, txn); err != nil { + if err := MVCCPut(ctx, engine, testKey2, txn.ReadTimestamp, value2, MVCCWriteOptions{Txn: txn}); err != nil { t.Fatal(err) } txn.Sequence++ - if err := MVCCPut(ctx, engine, nil, testKey3, txn.ReadTimestamp, hlc.ClockTimestamp{}, value3, txn); err != nil { + if err := MVCCPut(ctx, engine, testKey3, txn.ReadTimestamp, value3, MVCCWriteOptions{Txn: txn}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey4, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value4, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey4, hlc.Timestamp{WallTime: 1}, value4, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if _, _, _, err := MVCCDeleteRange(ctx, engine, nil, testKey2, testKey4, - math.MaxInt64, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, nil, false); err == nil { + if _, _, _, err := MVCCDeleteRange(ctx, engine, testKey2, testKey4, + math.MaxInt64, hlc.Timestamp{WallTime: 1}, MVCCWriteOptions{}, false); err == nil { t.Fatal("expected error on uncommitted write intent") } txn.Sequence++ - if _, _, _, err := MVCCDeleteRange(ctx, engine, nil, testKey2, testKey4, - math.MaxInt64, txn.ReadTimestamp, hlc.ClockTimestamp{}, txn, false); err != nil { + if _, _, _, err := MVCCDeleteRange(ctx, engine, testKey2, testKey4, + math.MaxInt64, txn.ReadTimestamp, MVCCWriteOptions{Txn: txn}, false); err != nil { t.Fatal(err) } } @@ -1610,21 +1610,21 @@ func TestMVCCDeleteRangeConcurrentTxn(t *testing.T) { txn1ts := makeTxn(*txn1, hlc.Timestamp{WallTime: 1}) txn2ts := makeTxn(*txn2, hlc.Timestamp{WallTime: 2}) - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 1}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey2, txn1ts.ReadTimestamp, hlc.ClockTimestamp{}, value2, txn1ts); err != nil { + if err := MVCCPut(ctx, engine, testKey2, txn1ts.ReadTimestamp, value2, MVCCWriteOptions{Txn: txn1ts}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey3, txn2ts.ReadTimestamp, hlc.ClockTimestamp{}, value3, txn2ts); err != nil { + if err := MVCCPut(ctx, engine, testKey3, txn2ts.ReadTimestamp, value3, MVCCWriteOptions{Txn: txn2ts}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey4, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value4, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey4, hlc.Timestamp{WallTime: 1}, value4, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if _, _, _, err := MVCCDeleteRange(ctx, engine, nil, testKey2, testKey4, - math.MaxInt64, txn1ts.ReadTimestamp, hlc.ClockTimestamp{}, txn1ts, false, + if _, _, _, err := MVCCDeleteRange(ctx, engine, testKey2, testKey4, + math.MaxInt64, txn1ts.ReadTimestamp, MVCCWriteOptions{Txn: txn1ts}, false, ); err == nil { t.Fatal("expected error on uncommitted write intent") } @@ -1640,23 +1640,23 @@ func TestMVCCUncommittedDeleteRangeVisible(t *testing.T) { engine := NewDefaultInMemForTesting() defer engine.Close() - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 1}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey2, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value2, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey2, hlc.Timestamp{WallTime: 1}, value2, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey3, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value3, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey3, hlc.Timestamp{WallTime: 1}, value3, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if _, err := MVCCDelete(ctx, engine, nil, testKey2, hlc.Timestamp{WallTime: 2, Logical: 1}, hlc.ClockTimestamp{}, nil); err != nil { + if _, err := MVCCDelete(ctx, engine, testKey2, hlc.Timestamp{WallTime: 2, Logical: 1}, MVCCWriteOptions{}); err != nil { t.Fatal(err) } txn := makeTxn(*txn1, hlc.Timestamp{WallTime: 2, Logical: 2}) - if _, _, _, err := MVCCDeleteRange(ctx, engine, nil, testKey1, testKey4, - math.MaxInt64, txn.ReadTimestamp, hlc.ClockTimestamp{}, txn, false, + if _, _, _, err := MVCCDeleteRange(ctx, engine, testKey1, testKey4, + math.MaxInt64, txn.ReadTimestamp, MVCCWriteOptions{Txn: txn}, false, ); err != nil { t.Fatal(err) } @@ -1678,15 +1678,15 @@ func TestMVCCDeleteRangeOldTimestamp(t *testing.T) { ctx := context.Background() engine := NewDefaultInMemForTesting() defer engine.Close() - err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value1, nil) + err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 1}, value1, MVCCWriteOptions{}) if err != nil { t.Fatal(err) } - err = MVCCPut(ctx, engine, nil, testKey2, hlc.Timestamp{WallTime: 3}, hlc.ClockTimestamp{}, value2, nil) + err = MVCCPut(ctx, engine, testKey2, hlc.Timestamp{WallTime: 3}, value2, MVCCWriteOptions{}) if err != nil { t.Fatal(err) } - _, err = MVCCDelete(ctx, engine, nil, testKey2, hlc.Timestamp{WallTime: 5}, hlc.ClockTimestamp{}, nil) + _, err = MVCCDelete(ctx, engine, testKey2, hlc.Timestamp{WallTime: 5}, MVCCWriteOptions{}) if err != nil { t.Fatal(err) } @@ -1694,8 +1694,8 @@ func TestMVCCDeleteRangeOldTimestamp(t *testing.T) { // Delete at a time before the tombstone. Should return a WriteTooOld error. b := engine.NewBatch() defer b.Close() - keys, resume, keyCount, err := MVCCDeleteRange(ctx, b, nil, testKey1, testKey4, - math.MaxInt64, hlc.Timestamp{WallTime: 4}, hlc.ClockTimestamp{}, nil, true) + keys, resume, keyCount, err := MVCCDeleteRange(ctx, b, testKey1, testKey4, + math.MaxInt64, hlc.Timestamp{WallTime: 4}, MVCCWriteOptions{}, true) require.Nil(t, keys) require.Nil(t, resume) require.Equal(t, int64(0), keyCount) @@ -1705,8 +1705,8 @@ func TestMVCCDeleteRangeOldTimestamp(t *testing.T) { // Delete at the same time as the tombstone. Should return a WriteTooOld error. b = engine.NewBatch() defer b.Close() - keys, resume, keyCount, err = MVCCDeleteRange(ctx, b, nil, testKey1, testKey4, - math.MaxInt64, hlc.Timestamp{WallTime: 5}, hlc.ClockTimestamp{}, nil, true) + keys, resume, keyCount, err = MVCCDeleteRange(ctx, b, testKey1, testKey4, + math.MaxInt64, hlc.Timestamp{WallTime: 5}, MVCCWriteOptions{}, true) require.Nil(t, keys) require.Nil(t, resume) require.Equal(t, int64(0), keyCount) @@ -1717,8 +1717,8 @@ func TestMVCCDeleteRangeOldTimestamp(t *testing.T) { // include the tombstone in the returned keys. b = engine.NewBatch() defer b.Close() - keys, resume, keyCount, err = MVCCDeleteRange(ctx, b, nil, testKey1, testKey4, - math.MaxInt64, hlc.Timestamp{WallTime: 6}, hlc.ClockTimestamp{}, nil, true) + keys, resume, keyCount, err = MVCCDeleteRange(ctx, b, testKey1, testKey4, + math.MaxInt64, hlc.Timestamp{WallTime: 6}, MVCCWriteOptions{}, true) require.Equal(t, []roachpb.Key{testKey1}, keys) require.Nil(t, resume) require.Equal(t, int64(1), keyCount) @@ -1744,19 +1744,19 @@ func TestMVCCDeleteRangeInline(t *testing.T) { {testKey4, value4}, {testKey5, value5}, } { - if err := MVCCPut(ctx, engine, nil, kv.key, hlc.Timestamp{Logical: 0}, hlc.ClockTimestamp{}, kv.value, nil); err != nil { + if err := MVCCPut(ctx, engine, kv.key, hlc.Timestamp{Logical: 0}, kv.value, MVCCWriteOptions{}); err != nil { t.Fatalf("%d: %+v", i, err) } } // Create one non-inline value (non-zero timestamp). - if err := MVCCPut(ctx, engine, nil, testKey6, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value6, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey6, hlc.Timestamp{WallTime: 1}, value6, MVCCWriteOptions{}); err != nil { t.Fatal(err) } // Attempt to delete two inline keys, should succeed. - deleted, resumeSpan, num, err := MVCCDeleteRange(ctx, engine, nil, testKey2, testKey6, - 2, hlc.Timestamp{Logical: 0}, hlc.ClockTimestamp{}, nil, true) + deleted, resumeSpan, num, err := MVCCDeleteRange(ctx, engine, testKey2, testKey6, + 2, hlc.Timestamp{Logical: 0}, MVCCWriteOptions{}, true) if err != nil { t.Fatal(err) } @@ -1772,22 +1772,22 @@ func TestMVCCDeleteRangeInline(t *testing.T) { // Attempt to delete inline keys at a timestamp; should fail. const inlineMismatchErrString = "put is inline" - if _, _, _, err := MVCCDeleteRange(ctx, engine, nil, testKey1, testKey6, - 1, hlc.Timestamp{WallTime: 2}, hlc.ClockTimestamp{}, nil, true, + if _, _, _, err := MVCCDeleteRange(ctx, engine, testKey1, testKey6, + 1, hlc.Timestamp{WallTime: 2}, MVCCWriteOptions{}, true, ); !testutils.IsError(err, inlineMismatchErrString) { t.Fatalf("got error %v, expected error with text '%s'", err, inlineMismatchErrString) } // Attempt to delete non-inline key at zero timestamp; should fail. - if _, _, _, err := MVCCDeleteRange(ctx, engine, nil, testKey6, keyMax, - 1, hlc.Timestamp{Logical: 0}, hlc.ClockTimestamp{}, nil, true, + if _, _, _, err := MVCCDeleteRange(ctx, engine, testKey6, keyMax, + 1, hlc.Timestamp{Logical: 0}, MVCCWriteOptions{}, true, ); !testutils.IsError(err, inlineMismatchErrString) { t.Fatalf("got error %v, expected error with text '%s'", err, inlineMismatchErrString) } // Attempt to delete inline keys in a transaction; should fail. - if _, _, _, err := MVCCDeleteRange(ctx, engine, nil, testKey2, testKey6, - 2, hlc.Timestamp{Logical: 0}, hlc.ClockTimestamp{}, txn1, true, + if _, _, _, err := MVCCDeleteRange(ctx, engine, testKey2, testKey6, + 2, hlc.Timestamp{Logical: 0}, MVCCWriteOptions{Txn: txn1}, true, ); !testutils.IsError(err, "writes not allowed within transactions") { t.Errorf("unexpected error: %+v", err) } @@ -1876,12 +1876,12 @@ func TestMVCCClearTimeRange(t *testing.T) { // keys eng := NewDefaultInMemForTesting() defer eng.Close() - require.NoError(t, MVCCPut(ctx, eng, nil, testKey2, ts1, hlc.ClockTimestamp{}, value1, nil)) - require.NoError(t, MVCCPut(ctx, eng, nil, testKey2, ts2, hlc.ClockTimestamp{}, value2, nil)) - require.NoError(t, MVCCPut(ctx, eng, nil, testKey5, ts2, hlc.ClockTimestamp{}, value2, nil)) - require.NoError(t, MVCCPut(ctx, eng, nil, testKey1, ts3, hlc.ClockTimestamp{}, value3, nil)) - require.NoError(t, MVCCPut(ctx, eng, nil, testKey5, ts4, hlc.ClockTimestamp{}, value4, nil)) - require.NoError(t, MVCCPut(ctx, eng, nil, testKey2, ts4, hlc.ClockTimestamp{}, value4, nil)) + require.NoError(t, MVCCPut(ctx, eng, testKey2, ts1, value1, MVCCWriteOptions{})) + require.NoError(t, MVCCPut(ctx, eng, testKey2, ts2, value2, MVCCWriteOptions{})) + require.NoError(t, MVCCPut(ctx, eng, testKey5, ts2, value2, MVCCWriteOptions{})) + require.NoError(t, MVCCPut(ctx, eng, testKey1, ts3, value3, MVCCWriteOptions{})) + require.NoError(t, MVCCPut(ctx, eng, testKey5, ts4, value4, MVCCWriteOptions{})) + require.NoError(t, MVCCPut(ctx, eng, testKey2, ts4, value4, MVCCWriteOptions{})) assertKVs := func(t *testing.T, reader Reader, at hlc.Timestamp, expected []roachpb.KeyValue) { t.Helper() @@ -2024,7 +2024,7 @@ func TestMVCCClearTimeRange(t *testing.T) { // Add an intent at k3@ts3. txn := roachpb.MakeTransaction("test", nil, roachpb.NormalUserPriority, ts3, 1, 1) addIntent := func(t *testing.T, rw ReadWriter) { - require.NoError(t, MVCCPut(ctx, rw, nil, testKey3, ts3, hlc.ClockTimestamp{}, value3, &txn)) + require.NoError(t, MVCCPut(ctx, rw, testKey3, ts3, value3, MVCCWriteOptions{Txn: &txn})) } t.Run("clear everything hitting intent fails", func(t *testing.T) { b := eng.NewBatch() @@ -2119,25 +2119,25 @@ func TestMVCCClearTimeRangeOnRandomData(t *testing.T) { key := roachpb.Key(fmt.Sprintf("%05d", k)) if rand.Float64() > 0.8 { - _, err := MVCCDelete(ctx, e, &ms, key, hlc.Timestamp{WallTime: ts}, hlc.ClockTimestamp{}, nil) + _, err := MVCCDelete(ctx, e, key, hlc.Timestamp{WallTime: ts}, MVCCWriteOptions{Stats: &ms}) require.NoError(t, err) } else { v := roachpb.MakeValueFromString(fmt.Sprintf("v-%d", i)) - require.NoError(t, MVCCPut(ctx, e, &ms, key, hlc.Timestamp{WallTime: ts}, hlc.ClockTimestamp{}, v, nil)) + require.NoError(t, MVCCPut(ctx, e, key, hlc.Timestamp{WallTime: ts}, v, MVCCWriteOptions{Stats: &ms})) } } swathTime := rand.Intn(randTimeRange-100) + 100 for i := swathStart; i < swathEnd; i++ { key := roachpb.Key(fmt.Sprintf("%05d", i)) v := roachpb.MakeValueFromString(fmt.Sprintf("v-%d", i)) - require.NoError(t, MVCCPut(ctx, e, &ms, key, hlc.Timestamp{WallTime: int64(swathTime)}, hlc.ClockTimestamp{}, v, nil)) + require.NoError(t, MVCCPut(ctx, e, key, hlc.Timestamp{WallTime: int64(swathTime)}, v, MVCCWriteOptions{Stats: &ms})) } // Add another swath of keys above to exercise an after-iteration range flush. for i := keyRange; i < keyRange+200; i++ { key := roachpb.Key(fmt.Sprintf("%05d", i)) v := roachpb.MakeValueFromString(fmt.Sprintf("v-%d", i)) - require.NoError(t, MVCCPut(ctx, e, &ms, key, hlc.Timestamp{WallTime: int64(randTimeRange + 1)}, hlc.ClockTimestamp{}, v, nil)) + require.NoError(t, MVCCPut(ctx, e, key, hlc.Timestamp{WallTime: int64(randTimeRange + 1)}, v, MVCCWriteOptions{Stats: &ms})) } ms.AgeTo(2000) @@ -2202,25 +2202,25 @@ func TestMVCCInitPut(t *testing.T) { engine := NewDefaultInMemForTesting() defer engine.Close() - err := MVCCInitPut(ctx, engine, nil, testKey1, hlc.Timestamp{Logical: 1}, hlc.ClockTimestamp{}, value1, false, nil) + err := MVCCInitPut(ctx, engine, testKey1, hlc.Timestamp{Logical: 1}, value1, false, MVCCWriteOptions{}) if err != nil { t.Fatal(err) } // A repeat of the command will still succeed - err = MVCCInitPut(ctx, engine, nil, testKey1, hlc.Timestamp{Logical: 2}, hlc.ClockTimestamp{}, value1, false, nil) + err = MVCCInitPut(ctx, engine, testKey1, hlc.Timestamp{Logical: 2}, value1, false, MVCCWriteOptions{}) if err != nil { t.Fatal(err) } // Delete. - _, err = MVCCDelete(ctx, engine, nil, testKey1, hlc.Timestamp{Logical: 3}, hlc.ClockTimestamp{}, nil) + _, err = MVCCDelete(ctx, engine, testKey1, hlc.Timestamp{Logical: 3}, MVCCWriteOptions{}) if err != nil { t.Fatal(err) } // Reinserting the value fails if we fail on tombstones. - err = MVCCInitPut(ctx, engine, nil, testKey1, hlc.Timestamp{Logical: 4}, hlc.ClockTimestamp{}, value1, true, nil) + err = MVCCInitPut(ctx, engine, testKey1, hlc.Timestamp{Logical: 4}, value1, true, MVCCWriteOptions{}) if e := (*kvpb.ConditionFailedError)(nil); errors.As(err, &e) { if !bytes.Equal(e.ActualValue.RawBytes, nil) { t.Fatalf("the value %s in get result is not a tombstone", e.ActualValue.RawBytes) @@ -2232,13 +2232,13 @@ func TestMVCCInitPut(t *testing.T) { } // But doesn't if we *don't* fail on tombstones. - err = MVCCInitPut(ctx, engine, nil, testKey1, hlc.Timestamp{Logical: 5}, hlc.ClockTimestamp{}, value1, false, nil) + err = MVCCInitPut(ctx, engine, testKey1, hlc.Timestamp{Logical: 5}, value1, false, MVCCWriteOptions{}) if err != nil { t.Fatal(err) } // A repeat of the command with a different value will fail. - err = MVCCInitPut(ctx, engine, nil, testKey1, hlc.Timestamp{Logical: 6}, hlc.ClockTimestamp{}, value2, false, nil) + err = MVCCInitPut(ctx, engine, testKey1, hlc.Timestamp{Logical: 6}, value2, false, MVCCWriteOptions{}) if e := (*kvpb.ConditionFailedError)(nil); errors.As(err, &e) { if !bytes.Equal(e.ActualValue.RawBytes, value1.RawBytes) { t.Fatalf("the value %s in get result does not match the value %s in request", @@ -2294,14 +2294,14 @@ func TestMVCCInitPutWithTxn(t *testing.T) { txn := *txn1 txn.Sequence++ - err := MVCCInitPut(ctx, engine, nil, testKey1, txn.ReadTimestamp, hlc.ClockTimestamp{}, value1, false, &txn) + err := MVCCInitPut(ctx, engine, testKey1, txn.ReadTimestamp, value1, false, MVCCWriteOptions{Txn: &txn}) if err != nil { t.Fatal(err) } // A repeat of the command will still succeed. txn.Sequence++ - err = MVCCInitPut(ctx, engine, nil, testKey1, txn.ReadTimestamp, hlc.ClockTimestamp{}, value1, false, &txn) + err = MVCCInitPut(ctx, engine, testKey1, txn.ReadTimestamp, value1, false, MVCCWriteOptions{Txn: &txn}) if err != nil { t.Fatal(err) } @@ -2310,7 +2310,7 @@ func TestMVCCInitPutWithTxn(t *testing.T) { // will still succeed. txn.Sequence++ txn.Epoch = 2 - err = MVCCInitPut(ctx, engine, nil, testKey1, txn.ReadTimestamp, hlc.ClockTimestamp{}, value2, false, &txn) + err = MVCCInitPut(ctx, engine, testKey1, txn.ReadTimestamp, value2, false, MVCCWriteOptions{Txn: &txn}) if err != nil { t.Fatal(err) } @@ -2326,7 +2326,7 @@ func TestMVCCInitPutWithTxn(t *testing.T) { } // Write value4 with an old timestamp without txn...should get an error. - err = MVCCInitPut(ctx, engine, nil, testKey1, clock.Now(), hlc.ClockTimestamp{}, value4, false, nil) + err = MVCCInitPut(ctx, engine, testKey1, clock.Now(), value4, false, MVCCWriteOptions{}) if e := (*kvpb.ConditionFailedError)(nil); errors.As(err, &e) { if !bytes.Equal(e.ActualValue.RawBytes, value2.RawBytes) { t.Fatalf("the value %s in get result does not match the value %s in request", @@ -2347,28 +2347,28 @@ func TestMVCCReverseScan(t *testing.T) { engine := NewDefaultInMemForTesting() defer engine.Close() - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 1}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 2}, hlc.ClockTimestamp{}, value2, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 2}, value2, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey2, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value3, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey2, hlc.Timestamp{WallTime: 1}, value3, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey2, hlc.Timestamp{WallTime: 3}, hlc.ClockTimestamp{}, value4, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey2, hlc.Timestamp{WallTime: 3}, value4, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey3, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey3, hlc.Timestamp{WallTime: 1}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey4, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value2, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey4, hlc.Timestamp{WallTime: 1}, value2, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey5, hlc.Timestamp{WallTime: 3}, hlc.ClockTimestamp{}, value5, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey5, hlc.Timestamp{WallTime: 3}, value5, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey6, hlc.Timestamp{WallTime: 3}, hlc.ClockTimestamp{}, value6, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey6, hlc.Timestamp{WallTime: 3}, value6, MVCCWriteOptions{}); err != nil { t.Fatal(err) } @@ -2479,10 +2479,10 @@ func TestMVCCReverseScanFirstKeyInFuture(t *testing.T) { // Before fixing #17825, the MVCC version scan on key3 would fall out of the // scan bounds and if it never found another valid key before reaching // KeyMax, would stop the ReverseScan from continuing. - if err := MVCCPut(ctx, engine, nil, testKey2, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value2, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey2, hlc.Timestamp{WallTime: 1}, value2, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey3, hlc.Timestamp{WallTime: 3}, hlc.ClockTimestamp{}, value3, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey3, hlc.Timestamp{WallTime: 3}, value3, MVCCWriteOptions{}); err != nil { t.Fatal(err) } @@ -2515,12 +2515,12 @@ func TestMVCCReverseScanSeeksOverRepeatedKeys(t *testing.T) { // written. Repeat the key enough times to make sure the `SeekForPrev()` // optimization will be used. for i := 1; i <= 10; i++ { - if err := MVCCPut(ctx, engine, nil, testKey2, hlc.Timestamp{WallTime: int64(i)}, hlc.ClockTimestamp{}, value2, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey2, hlc.Timestamp{WallTime: int64(i)}, value2, MVCCWriteOptions{}); err != nil { t.Fatal(err) } } txn1ts := makeTxn(*txn1, hlc.Timestamp{WallTime: 11}) - if err := MVCCPut(ctx, engine, nil, testKey2, txn1ts.ReadTimestamp, hlc.ClockTimestamp{}, value2, txn1ts); err != nil { + if err := MVCCPut(ctx, engine, testKey2, txn1ts.ReadTimestamp, value2, MVCCWriteOptions{Txn: txn1ts}); err != nil { t.Fatal(err) } @@ -2565,7 +2565,7 @@ func TestMVCCReverseScanStopAtSmallestKey(t *testing.T) { defer engine.Close() for i := 1; i <= numPuts; i++ { - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: int64(i)}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: int64(i)}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } } @@ -2602,7 +2602,7 @@ func TestMVCCResolveTxn(t *testing.T) { engine := NewDefaultInMemForTesting() defer engine.Close() - if err := MVCCPut(ctx, engine, nil, testKey1, txn1.ReadTimestamp, hlc.ClockTimestamp{}, value1, txn1); err != nil { + if err := MVCCPut(ctx, engine, testKey1, txn1.ReadTimestamp, value1, MVCCWriteOptions{Txn: txn1}); err != nil { t.Fatal(err) } @@ -2649,12 +2649,12 @@ func TestMVCCResolveNewerIntent(t *testing.T) { defer engine.Close() // Write first value. - if err := MVCCPut(ctx, engine, nil, testKey1, txn1Commit.WriteTimestamp, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, txn1Commit.WriteTimestamp, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } // Now, put down an intent which should return a write too old error // (but will still write the intent at tx1Commit.Timestamp+1. - err := MVCCPut(ctx, engine, nil, testKey1, txn1.ReadTimestamp, hlc.ClockTimestamp{}, value2, txn1) + err := MVCCPut(ctx, engine, testKey1, txn1.ReadTimestamp, value2, MVCCWriteOptions{Txn: txn1}) if !errors.HasType(err, (*kvpb.WriteTooOldError)(nil)) { t.Fatalf("expected write too old error; got %s", err) } @@ -2805,7 +2805,7 @@ func TestMVCCResolveIntentTxnTimestampMismatch(t *testing.T) { txn.TxnMeta.WriteTimestamp.Forward(tsEarly.Add(10, 0)) // Write an intent which has txn.WriteTimestamp > meta.timestamp. - if err := MVCCPut(ctx, engine, nil, testKey1, tsEarly, hlc.ClockTimestamp{}, value1, txn); err != nil { + if err := MVCCPut(ctx, engine, testKey1, tsEarly, value1, MVCCWriteOptions{Txn: txn}); err != nil { t.Fatal(err) } @@ -2852,17 +2852,17 @@ func TestMVCCConditionalPutOldTimestamp(t *testing.T) { ctx := context.Background() engine := NewDefaultInMemForTesting() defer engine.Close() - err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value1, nil) + err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 1}, value1, MVCCWriteOptions{}) if err != nil { t.Fatal(err) } - err = MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 3}, hlc.ClockTimestamp{}, value2, nil) + err = MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 3}, value2, MVCCWriteOptions{}) if err != nil { t.Fatal(err) } // Check nothing is written if the value doesn't match. - err = MVCCConditionalPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 2}, hlc.ClockTimestamp{}, value3, value1.TagAndDataBytes(), CPutFailIfMissing, nil) + err = MVCCConditionalPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 2}, value3, value1.TagAndDataBytes(), CPutFailIfMissing, MVCCWriteOptions{}) if err == nil { t.Errorf("unexpected success on conditional put") } @@ -2872,7 +2872,7 @@ func TestMVCCConditionalPutOldTimestamp(t *testing.T) { // But if value does match the most recently written version, we'll get // a write too old error but still write updated value. - err = MVCCConditionalPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 2}, hlc.ClockTimestamp{}, value3, value2.TagAndDataBytes(), CPutFailIfMissing, nil) + err = MVCCConditionalPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 2}, value3, value2.TagAndDataBytes(), CPutFailIfMissing, MVCCWriteOptions{}) if err == nil { t.Errorf("unexpected success on conditional put") } @@ -2901,7 +2901,7 @@ func TestMVCCMultiplePutOldTimestamp(t *testing.T) { engine := NewDefaultInMemForTesting() defer engine.Close() - err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 3}, hlc.ClockTimestamp{}, value1, nil) + err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 3}, value1, MVCCWriteOptions{}) if err != nil { t.Fatal(err) } @@ -2910,7 +2910,7 @@ func TestMVCCMultiplePutOldTimestamp(t *testing.T) { // intent is written at the advanced timestamp. txn := makeTxn(*txn1, hlc.Timestamp{WallTime: 1}) txn.Sequence++ - err = MVCCPut(ctx, engine, nil, testKey1, txn.ReadTimestamp, hlc.ClockTimestamp{}, value2, txn) + err = MVCCPut(ctx, engine, testKey1, txn.ReadTimestamp, value2, MVCCWriteOptions{Txn: txn}) if !errors.HasType(err, (*kvpb.WriteTooOldError)(nil)) { t.Errorf("expected WriteTooOldError on Put; got %v", err) } @@ -2928,7 +2928,7 @@ func TestMVCCMultiplePutOldTimestamp(t *testing.T) { // Put again and verify no WriteTooOldError, but timestamp should continue // to be set to (3,1). txn.Sequence++ - err = MVCCPut(ctx, engine, nil, testKey1, txn.ReadTimestamp, hlc.ClockTimestamp{}, value3, txn) + err = MVCCPut(ctx, engine, testKey1, txn.ReadTimestamp, value3, MVCCWriteOptions{Txn: txn}) if err != nil { t.Error(err) } @@ -2953,7 +2953,7 @@ func TestMVCCPutNegativeTimestampError(t *testing.T) { timestamp := hlc.Timestamp{WallTime: -1} expectedErrorString := fmt.Sprintf("cannot write to %q at timestamp %s", testKey1, timestamp) - err := MVCCPut(ctx, engine, nil, testKey1, timestamp, hlc.ClockTimestamp{}, value1, nil) + err := MVCCPut(ctx, engine, testKey1, timestamp, value1, MVCCWriteOptions{}) require.EqualError(t, err, expectedErrorString) } @@ -2971,7 +2971,7 @@ func TestMVCCPutOldOrigTimestampNewCommitTimestamp(t *testing.T) { engine := NewDefaultInMemForTesting() defer engine.Close() - err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 3}, hlc.ClockTimestamp{}, value1, nil) + err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 3}, value1, MVCCWriteOptions{}) if err != nil { t.Fatal(err) } @@ -2982,7 +2982,7 @@ func TestMVCCPutOldOrigTimestampNewCommitTimestamp(t *testing.T) { txn := makeTxn(*txn1, hlc.Timestamp{WallTime: 1}) txn.WriteTimestamp = hlc.Timestamp{WallTime: 5} txn.Sequence++ - err = MVCCPut(ctx, engine, nil, testKey1, txn.ReadTimestamp, hlc.ClockTimestamp{}, value2, txn) + err = MVCCPut(ctx, engine, testKey1, txn.ReadTimestamp, value2, MVCCWriteOptions{Txn: txn}) // Verify that the Put returned a WriteTooOld with the ActualTime set to the // transactions provisional commit timestamp. @@ -3011,7 +3011,7 @@ func TestMVCCAbortTxn(t *testing.T) { engine := NewDefaultInMemForTesting() defer engine.Close() - if err := MVCCPut(ctx, engine, nil, testKey1, txn1.ReadTimestamp, hlc.ClockTimestamp{}, value1, txn1); err != nil { + if err := MVCCPut(ctx, engine, testKey1, txn1.ReadTimestamp, value1, MVCCWriteOptions{Txn: txn1}); err != nil { t.Fatal(err) } @@ -3043,14 +3043,14 @@ func TestMVCCAbortTxnWithPreviousVersion(t *testing.T) { engine := NewDefaultInMemForTesting() defer engine.Close() - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{Logical: 1}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{Logical: 1}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value2, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 1}, value2, MVCCWriteOptions{}); err != nil { t.Fatal(err) } txn1ts := makeTxn(*txn1, hlc.Timestamp{WallTime: 2}) - if err := MVCCPut(ctx, engine, nil, testKey1, txn1ts.ReadTimestamp, hlc.ClockTimestamp{}, value3, txn1ts); err != nil { + if err := MVCCPut(ctx, engine, testKey1, txn1ts.ReadTimestamp, value3, MVCCWriteOptions{Txn: txn1ts}); err != nil { t.Fatal(err) } @@ -3095,32 +3095,34 @@ func TestMVCCWriteWithDiffTimestampsAndEpochs(t *testing.T) { // Start with epoch 1. txn := *txn1 txn.Sequence++ - if err := MVCCPut(ctx, engine, nil, testKey1, txn.ReadTimestamp, hlc.ClockTimestamp{}, value1, &txn); err != nil { + if err := MVCCPut(ctx, engine, testKey1, txn.ReadTimestamp, value1, MVCCWriteOptions{Txn: &txn}); err != nil { t.Fatal(err) } + // Now write with greater timestamp and epoch 2. txne2 := txn txne2.Sequence++ txne2.Epoch = 2 txne2.WriteTimestamp = hlc.Timestamp{WallTime: 1} - if err := MVCCPut(ctx, engine, nil, testKey1, txne2.ReadTimestamp, hlc.ClockTimestamp{}, value2, &txne2); err != nil { + if err := MVCCPut(ctx, engine, testKey1, txne2.ReadTimestamp, value2, MVCCWriteOptions{Txn: &txne2}); err != nil { t.Fatal(err) } // Try a write with an earlier timestamp; this is just ignored. txne2.Sequence++ txne2.WriteTimestamp = hlc.Timestamp{WallTime: 1} - if err := MVCCPut(ctx, engine, nil, testKey1, txne2.ReadTimestamp, hlc.ClockTimestamp{}, value1, &txne2); err != nil { + if err := MVCCPut(ctx, engine, testKey1, txne2.ReadTimestamp, value1, MVCCWriteOptions{Txn: &txne2}); err != nil { t.Fatal(err) } // Try a write with an earlier epoch; again ignored. - if err := MVCCPut(ctx, engine, nil, testKey1, txn.ReadTimestamp, hlc.ClockTimestamp{}, value1, &txn); err == nil { + if err := MVCCPut(ctx, engine, testKey1, txn.ReadTimestamp, value1, MVCCWriteOptions{Txn: &txn}); err == nil { t.Fatal("unexpected success of a write with an earlier epoch") } // Try a write with different value using both later timestamp and epoch. txne2.Sequence++ - if err := MVCCPut(ctx, engine, nil, testKey1, txne2.ReadTimestamp, hlc.ClockTimestamp{}, value3, &txne2); err != nil { + if err := MVCCPut(ctx, engine, testKey1, txne2.ReadTimestamp, value3, MVCCWriteOptions{Txn: &txne2}); err != nil { t.Fatal(err) } + // Resolve the intent. txne2Commit := txne2 txne2Commit.Status = roachpb.COMMITTED @@ -3134,7 +3136,7 @@ func TestMVCCWriteWithDiffTimestampsAndEpochs(t *testing.T) { expTS := txne2Commit.WriteTimestamp.Next() // Now try writing an earlier value without a txn--should get WriteTooOldError. - err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{Logical: 1}, hlc.ClockTimestamp{}, value4, nil) + err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{Logical: 1}, value4, MVCCWriteOptions{}) if wtoErr := (*kvpb.WriteTooOldError)(nil); !errors.As(err, &wtoErr) { t.Fatal("unexpected success") } else if wtoErr.ActualTimestamp != expTS { @@ -3147,7 +3149,7 @@ func TestMVCCWriteWithDiffTimestampsAndEpochs(t *testing.T) { err, valueRes.Value.Timestamp, expTS, value4.RawBytes, valueRes.Value.RawBytes) } // Now write an intent with exactly the same timestamp--ties also get WriteTooOldError. - err = MVCCPut(ctx, engine, nil, testKey1, txn2.ReadTimestamp, hlc.ClockTimestamp{}, value5, txn2) + err = MVCCPut(ctx, engine, testKey1, txn2.ReadTimestamp, value5, MVCCWriteOptions{Txn: txn2}) intentTS := expTS.Next() if wtoErr := (*kvpb.WriteTooOldError)(nil); !errors.As(err, &wtoErr) { t.Fatal("unexpected success") @@ -3160,6 +3162,7 @@ func TestMVCCWriteWithDiffTimestampsAndEpochs(t *testing.T) { t.Fatalf("expected err=nil (got %s), timestamp=%s (got %s), value=%q (got %q)", err, valueRes.Value.Timestamp, intentTS, value5.RawBytes, valueRes.Value.RawBytes) } + // Attempt to read older timestamp; should fail. valueRes, err = MVCCGet(ctx, engine, testKey1, hlc.Timestamp{Logical: 0}, MVCCGetOptions{}) if valueRes.Value != nil || err != nil { @@ -3191,12 +3194,12 @@ func TestMVCCGetWithDiffEpochs(t *testing.T) { defer engine.Close() // Write initial value without a txn. - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{Logical: 1}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{Logical: 1}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } // Now write using txn1, epoch 1. txn1ts := makeTxn(*txn1, hlc.Timestamp{WallTime: 1}) - if err := MVCCPut(ctx, engine, nil, testKey1, txn1ts.ReadTimestamp, hlc.ClockTimestamp{}, value2, txn1ts); err != nil { + if err := MVCCPut(ctx, engine, testKey1, txn1ts.ReadTimestamp, value2, MVCCWriteOptions{Txn: txn1ts}); err != nil { t.Fatal(err) } // Try reading using different txns & epochs. @@ -3248,11 +3251,11 @@ func TestMVCCGetWithDiffEpochsAndTimestamps(t *testing.T) { defer engine.Close() // Write initial value without a txn at timestamp 1. - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 1}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 1}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } // Write another value without a txn at timestamp 3. - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{WallTime: 3}, hlc.ClockTimestamp{}, value2, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{WallTime: 3}, value2, MVCCWriteOptions{}); err != nil { t.Fatal(err) } // Now write using txn1, epoch 1. @@ -3260,7 +3263,7 @@ func TestMVCCGetWithDiffEpochsAndTimestamps(t *testing.T) { // Bump epoch 1's write timestamp to timestamp 4. txn1ts.WriteTimestamp = hlc.Timestamp{WallTime: 4} // Expected to hit WriteTooOld error but to still lay down intent. - err := MVCCPut(ctx, engine, nil, testKey1, txn1ts.ReadTimestamp, hlc.ClockTimestamp{}, value3, txn1ts) + err := MVCCPut(ctx, engine, testKey1, txn1ts.ReadTimestamp, value3, MVCCWriteOptions{Txn: txn1ts}) if wtoErr := (*kvpb.WriteTooOldError)(nil); !errors.As(err, &wtoErr) { t.Fatalf("unexpectedly not WriteTooOld: %+v", err) } else if expTS, actTS := txn1ts.WriteTimestamp, wtoErr.ActualTimestamp; expTS != actTS { @@ -3313,7 +3316,7 @@ func TestMVCCGetWithOldEpoch(t *testing.T) { engine := NewDefaultInMemForTesting() defer engine.Close() - if err := MVCCPut(ctx, engine, nil, testKey1, txn1e2.ReadTimestamp, hlc.ClockTimestamp{}, value2, txn1e2); err != nil { + if err := MVCCPut(ctx, engine, testKey1, txn1e2.ReadTimestamp, value2, MVCCWriteOptions{Txn: txn1e2}); err != nil { t.Fatal(err) } _, err := MVCCGet(ctx, engine, testKey1, hlc.Timestamp{WallTime: 2}, MVCCGetOptions{ @@ -3354,7 +3357,7 @@ func TestMVCCDeleteRangeWithSequence(t *testing.T) { for i := enginepb.TxnSeq(0); i < 3; i++ { key := append(prefix, []byte(strconv.Itoa(int(i)))...) txn.Sequence = 2 + i - if err := MVCCPut(ctx, engine, nil, key, txn.WriteTimestamp, hlc.ClockTimestamp{}, value1, &txn); err != nil { + if err := MVCCPut(ctx, engine, key, txn.WriteTimestamp, value1, MVCCWriteOptions{Txn: &txn}); err != nil { t.Fatal(err) } } @@ -3362,15 +3365,15 @@ func TestMVCCDeleteRangeWithSequence(t *testing.T) { // Perform the initial DeleteRange. const origSeq = 6 txn.Sequence = origSeq - origDeleted, _, origNum, err := MVCCDeleteRange(ctx, engine, nil, - prefix, prefix.PrefixEnd(), math.MaxInt64, txn.WriteTimestamp, hlc.ClockTimestamp{}, &txn, true) + origDeleted, _, origNum, err := MVCCDeleteRange(ctx, engine, prefix, prefix.PrefixEnd(), + math.MaxInt64, txn.WriteTimestamp, MVCCWriteOptions{Txn: &txn}, true) if err != nil { t.Fatal(err) } txn.Sequence = tc.sequence - deleted, _, num, err := MVCCDeleteRange(ctx, engine, nil, - prefix, prefix.PrefixEnd(), math.MaxInt64, txn.WriteTimestamp, hlc.ClockTimestamp{}, &txn, true) + deleted, _, num, err := MVCCDeleteRange(ctx, engine, prefix, prefix.PrefixEnd(), + math.MaxInt64, txn.WriteTimestamp, MVCCWriteOptions{Txn: &txn}, true) if tc.expErr != "" && err != nil { if !testutils.IsError(err, tc.expErr) { t.Fatalf("unexpected error: %+v", err) @@ -3409,7 +3412,7 @@ func TestMVCCGetWithPushedTimestamp(t *testing.T) { defer engine.Close() // Start with epoch 1. - if err := MVCCPut(ctx, engine, nil, testKey1, txn1.ReadTimestamp, hlc.ClockTimestamp{}, value1, txn1); err != nil { + if err := MVCCPut(ctx, engine, testKey1, txn1.ReadTimestamp, value1, MVCCWriteOptions{Txn: txn1}); err != nil { t.Fatal(err) } // Resolve the intent, pushing its timestamp forward. @@ -3436,10 +3439,10 @@ func TestMVCCResolveWithDiffEpochs(t *testing.T) { engine := NewDefaultInMemForTesting() defer engine.Close() - if err := MVCCPut(ctx, engine, nil, testKey1, txn1.ReadTimestamp, hlc.ClockTimestamp{}, value1, txn1); err != nil { + if err := MVCCPut(ctx, engine, testKey1, txn1.ReadTimestamp, value1, MVCCWriteOptions{Txn: txn1}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey2, txn1e2.ReadTimestamp, hlc.ClockTimestamp{}, value2, txn1e2); err != nil { + if err := MVCCPut(ctx, engine, testKey2, txn1e2.ReadTimestamp, value2, MVCCWriteOptions{Txn: txn1e2}); err != nil { t.Fatal(err) } numKeys, _, _, _, err := MVCCResolveWriteIntentRange(ctx, engine, nil, @@ -3478,7 +3481,7 @@ func TestMVCCResolveWithUpdatedTimestamp(t *testing.T) { engine := NewDefaultInMemForTesting() defer engine.Close() - if err := MVCCPut(ctx, engine, nil, testKey1, txn1.ReadTimestamp, hlc.ClockTimestamp{}, value1, txn1); err != nil { + if err := MVCCPut(ctx, engine, testKey1, txn1.ReadTimestamp, value1, MVCCWriteOptions{Txn: txn1}); err != nil { t.Fatal(err) } @@ -3528,7 +3531,7 @@ func TestMVCCResolveWithPushedTimestamp(t *testing.T) { engine := NewDefaultInMemForTesting() defer engine.Close() - if err := MVCCPut(ctx, engine, nil, testKey1, txn1.ReadTimestamp, hlc.ClockTimestamp{}, value1, txn1); err != nil { + if err := MVCCPut(ctx, engine, testKey1, txn1.ReadTimestamp, value1, MVCCWriteOptions{Txn: txn1}); err != nil { t.Fatal(err) } valueRes, err := MVCCGet(ctx, engine, testKey1, hlc.Timestamp{WallTime: 1}, MVCCGetOptions{ @@ -3588,7 +3591,7 @@ func TestMVCCResolveTxnNoOps(t *testing.T) { } // Add key and resolve despite there being no intent. - if err := MVCCPut(ctx, engine, nil, testKey1, hlc.Timestamp{Logical: 1}, hlc.ClockTimestamp{}, value1, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey1, hlc.Timestamp{Logical: 1}, value1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } if _, _, _, err := MVCCResolveWriteIntent(ctx, engine, nil, @@ -3598,7 +3601,7 @@ func TestMVCCResolveTxnNoOps(t *testing.T) { } // Write intent and resolve with different txn. - if err := MVCCPut(ctx, engine, nil, testKey2, txn1.ReadTimestamp, hlc.ClockTimestamp{}, value2, txn1); err != nil { + if err := MVCCPut(ctx, engine, testKey2, txn1.ReadTimestamp, value2, MVCCWriteOptions{Txn: txn1}); err != nil { t.Fatal(err) } @@ -3619,16 +3622,16 @@ func TestMVCCResolveTxnRange(t *testing.T) { engine := NewDefaultInMemForTesting() defer engine.Close() - if err := MVCCPut(ctx, engine, nil, testKey1, txn1.ReadTimestamp, hlc.ClockTimestamp{}, value1, txn1); err != nil { + if err := MVCCPut(ctx, engine, testKey1, txn1.ReadTimestamp, value1, MVCCWriteOptions{Txn: txn1}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey2, hlc.Timestamp{Logical: 1}, hlc.ClockTimestamp{}, value2, nil); err != nil { + if err := MVCCPut(ctx, engine, testKey2, hlc.Timestamp{Logical: 1}, value2, MVCCWriteOptions{}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey3, txn2.ReadTimestamp, hlc.ClockTimestamp{}, value3, txn2); err != nil { + if err := MVCCPut(ctx, engine, testKey3, txn2.ReadTimestamp, value3, MVCCWriteOptions{Txn: txn2}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, testKey4, txn1.ReadTimestamp, hlc.ClockTimestamp{}, value4, txn1); err != nil { + if err := MVCCPut(ctx, engine, testKey4, txn1.ReadTimestamp, value4, MVCCWriteOptions{Txn: txn1}); err != nil { t.Fatal(err) } @@ -3705,14 +3708,14 @@ func TestMVCCResolveTxnRangeResume(t *testing.T) { key0 := roachpb.Key(fmt.Sprintf("%02d%d", i+0, i+0)) key1 := roachpb.Key(fmt.Sprintf("%02d%d", i+1, i+1)) key2 := roachpb.Key(fmt.Sprintf("%02d%d", i+2, i+2)) - if err := MVCCPut(ctx, engine, nil, key0, txn1.ReadTimestamp, hlc.ClockTimestamp{}, value1, txn1); err != nil { + if err := MVCCPut(ctx, engine, key0, txn1.ReadTimestamp, value1, MVCCWriteOptions{Txn: txn1}); err != nil { t.Fatal(err) } txn2ts := makeTxn(*txn2, hlc.Timestamp{Logical: 2}) - if err := MVCCPut(ctx, engine, nil, key1, txn2ts.ReadTimestamp, hlc.ClockTimestamp{}, value2, txn2ts); err != nil { + if err := MVCCPut(ctx, engine, key1, txn2ts.ReadTimestamp, value2, MVCCWriteOptions{Txn: txn2ts}); err != nil { t.Fatal(err) } - if err := MVCCPut(ctx, engine, nil, key2, hlc.Timestamp{Logical: 3}, hlc.ClockTimestamp{}, value3, nil); err != nil { + if err := MVCCPut(ctx, engine, key2, hlc.Timestamp{Logical: 3}, value3, MVCCWriteOptions{}); err != nil { t.Fatal(err) } } @@ -3825,7 +3828,7 @@ func writeToEngine( log.Infof(ctx, "Put: %s, seq: %d, writets: %s", p.key.String(), txn.Sequence, txn.WriteTimestamp.String()) } - require.NoError(t, MVCCPut(ctx, eng, nil, p.key, txn.ReadTimestamp, hlc.ClockTimestamp{}, p.values[i], txn)) + require.NoError(t, MVCCPut(ctx, eng, p.key, txn.ReadTimestamp, p.values[i], MVCCWriteOptions{Txn: txn})) } } } @@ -4224,7 +4227,7 @@ func TestFindSplitKey(t *testing.T) { v := strings.Repeat("X", 10-len(k)) val := roachpb.MakeValueFromString(v) // Write the key and value through MVCC - if err := MVCCPut(ctx, engine, ms, []byte(k), hlc.Timestamp{Logical: 1}, hlc.ClockTimestamp{}, val, nil); err != nil { + if err := MVCCPut(ctx, engine, []byte(k), hlc.Timestamp{Logical: 1}, val, MVCCWriteOptions{Stats: ms}); err != nil { t.Fatal(err) } } @@ -4589,7 +4592,7 @@ func TestFindBalancedSplitKeys(t *testing.T) { expKey = key } val := roachpb.MakeValueFromString(strings.Repeat("X", test.valSizes[j])) - if err := MVCCPut(ctx, engine, ms, key, hlc.Timestamp{Logical: 1}, hlc.ClockTimestamp{}, val, nil); err != nil { + if err := MVCCPut(ctx, engine, key, hlc.Timestamp{Logical: 1}, val, MVCCWriteOptions{Stats: ms}); err != nil { t.Fatal(err) } } @@ -4636,7 +4639,7 @@ func testPopulateKeysWithVersions( ts := hlc.Timestamp{Logical: int32(j)} require.NoError( t, - MVCCPut(ctx, engine, ms, []byte(k), ts, hlc.ClockTimestamp{}, val, nil), + MVCCPut(ctx, engine, []byte(k), ts, val, MVCCWriteOptions{Stats: ms}), ) } } @@ -4870,16 +4873,15 @@ func TestMVCCGarbageCollect(t *testing.T) { } for _, val := range test.vals[i : i+1] { if i == len(test.vals)-1 && test.isDeleted { - if _, err := MVCCDelete(ctx, engine, ms, test.key, val.Timestamp, hlc.ClockTimestamp{}, - nil); err != nil { + if _, err := MVCCDelete(ctx, engine, test.key, val.Timestamp, MVCCWriteOptions{Stats: ms}); err != nil { t.Fatal(err) } continue } valCpy := *protoutil.Clone(&val).(*roachpb.Value) valCpy.Timestamp = hlc.Timestamp{} - if err := MVCCPut(ctx, engine, ms, test.key, val.Timestamp, hlc.ClockTimestamp{}, - valCpy, nil); err != nil { + if err := MVCCPut(ctx, engine, test.key, val.Timestamp, + valCpy, MVCCWriteOptions{Stats: ms}); err != nil { t.Fatal(err) } } @@ -5016,7 +5018,7 @@ func TestMVCCGarbageCollectNonDeleted(t *testing.T) { for _, val := range test.vals { valCpy := *protoutil.Clone(&val).(*roachpb.Value) valCpy.Timestamp = hlc.Timestamp{} - if err := MVCCPut(ctx, engine, nil, test.key, val.Timestamp, hlc.ClockTimestamp{}, valCpy, nil); err != nil { + if err := MVCCPut(ctx, engine, test.key, val.Timestamp, valCpy, MVCCWriteOptions{}); err != nil { t.Fatal(err) } } @@ -5046,7 +5048,7 @@ func TestMVCCGarbageCollectIntent(t *testing.T) { key := roachpb.Key("a") { val1 := roachpb.MakeValueFromBytes(bytes) - if err := MVCCPut(ctx, engine, nil, key, ts1, hlc.ClockTimestamp{}, val1, nil); err != nil { + if err := MVCCPut(ctx, engine, key, ts1, val1, MVCCWriteOptions{}); err != nil { t.Fatal(err) } } @@ -5054,7 +5056,7 @@ func TestMVCCGarbageCollectIntent(t *testing.T) { TxnMeta: enginepb.TxnMeta{ID: uuid.MakeV4(), WriteTimestamp: ts2}, ReadTimestamp: ts2, } - if _, err := MVCCDelete(ctx, engine, nil, key, txn.ReadTimestamp, hlc.ClockTimestamp{}, txn); err != nil { + if _, err := MVCCDelete(ctx, engine, key, txn.ReadTimestamp, MVCCWriteOptions{Txn: txn}); err != nil { t.Fatal(err) } keys := []kvpb.GCRequest_GCKey{ @@ -5145,7 +5147,7 @@ func TestMVCCGarbageCollectUsesSeekLTAppropriately(t *testing.T) { for _, seconds := range key.timestamps { val := roachpb.MakeValueFromBytes(bytes) ts := toHLC(seconds) - if err := MVCCPut(ctx, engine, ms, roachpb.Key(key.key), ts, hlc.ClockTimestamp{}, val, nil); err != nil { + if err := MVCCPut(ctx, engine, roachpb.Key(key.key), ts, val, MVCCWriteOptions{Stats: ms}); err != nil { t.Fatal(err) } } @@ -5285,11 +5287,11 @@ func (d rangeTestData) populateEngine( for _, v := range d { if v.rangeTombstone.Timestamp.IsEmpty() { if v.point.Value != nil { - require.NoError(t, MVCCPut(ctx, engine, ms, v.point.Key.Key, v.point.Key.Timestamp, - hlc.ClockTimestamp{}, roachpb.MakeValueFromBytes(v.point.Value), v.txn), + require.NoError(t, MVCCPut(ctx, engine, v.point.Key.Key, v.point.Key.Timestamp, + roachpb.MakeValueFromBytes(v.point.Value), MVCCWriteOptions{Txn: v.txn, Stats: ms}), "failed to insert test value into engine (%s)", v.point.Key.String()) } else { - _, err := MVCCDelete(ctx, engine, ms, v.point.Key.Key, v.point.Key.Timestamp, hlc.ClockTimestamp{}, v.txn) + _, err := MVCCDelete(ctx, engine, v.point.Key.Key, v.point.Key.Timestamp, MVCCWriteOptions{Txn: v.txn, Stats: ms}) require.NoError(t, err, "failed to insert tombstone value into engine (%s)", v.point.Key.String()) } ts = v.point.Key.Timestamp @@ -6183,7 +6185,7 @@ func TestResolveIntentWithLowerEpoch(t *testing.T) { defer engine.Close() // Lay down an intent with a high epoch. - if err := MVCCPut(ctx, engine, nil, testKey1, txn1e2.ReadTimestamp, hlc.ClockTimestamp{}, value1, txn1e2); err != nil { + if err := MVCCPut(ctx, engine, testKey1, txn1e2.ReadTimestamp, value1, MVCCWriteOptions{Txn: txn1e2}); err != nil { t.Fatal(err) } // Resolve the intent with a low epoch. diff --git a/pkg/storage/pebble_mvcc_scanner_test.go b/pkg/storage/pebble_mvcc_scanner_test.go index 74b032992417..ac92c7747f20 100644 --- a/pkg/storage/pebble_mvcc_scanner_test.go +++ b/pkg/storage/pebble_mvcc_scanner_test.go @@ -218,7 +218,7 @@ func TestMVCCScanWithMemoryAccounting(t *testing.T) { defer batch.Close() for i := 0; i < 10; i++ { key := makeKey(nil, i) - require.NoError(t, MVCCPut(context.Background(), batch, nil, key, ts1, hlc.ClockTimestamp{}, val, &txn1)) + require.NoError(t, MVCCPut(context.Background(), batch, key, ts1, val, MVCCWriteOptions{Txn: &txn1})) } require.NoError(t, batch.Commit(true)) }() diff --git a/pkg/storage/pebble_test.go b/pkg/storage/pebble_test.go index 636ededa9e7a..8cf350c7152b 100644 --- a/pkg/storage/pebble_test.go +++ b/pkg/storage/pebble_test.go @@ -472,7 +472,7 @@ func fillInData(ctx context.Context, engine Engine, data []testValue) error { batch := engine.NewBatch() defer batch.Close() for _, val := range data { - if err := MVCCPut(ctx, batch, nil, val.key, val.timestamp, hlc.ClockTimestamp{}, val.value, val.txn); err != nil { + if err := MVCCPut(ctx, batch, val.key, val.timestamp, val.value, MVCCWriteOptions{Txn: val.txn}); err != nil { return err } } diff --git a/pkg/storage/sst_test.go b/pkg/storage/sst_test.go index ce4b0846cd9b..8a937a384f51 100644 --- a/pkg/storage/sst_test.go +++ b/pkg/storage/sst_test.go @@ -79,7 +79,7 @@ func TestCheckSSTConflictsMaxIntents(t *testing.T) { require.NoError(t, batch.PutMVCC(mvccKey, mvccValue)) } for _, key := range intents { - require.NoError(t, MVCCPut(ctx, batch, nil, roachpb.Key(key), txn1TS, hlc.ClockTimestamp{}, roachpb.MakeValueFromString("intent"), txn1)) + require.NoError(t, MVCCPut(ctx, batch, roachpb.Key(key), txn1TS, roachpb.MakeValueFromString("intent"), MVCCWriteOptions{Txn: txn1})) } require.NoError(t, batch.Commit(true)) batch.Close()