@@ -283,6 +283,10 @@ type ClientOperationConfig struct {
283
283
// FlushLockTable is an operation that moves unreplicated locks in the
284
284
// in-memory lock table into the
285
285
FlushLockTable int
286
+
287
+ // MutateBatchHeader mutates elements of the batch Header that may influence
288
+ // batch evaluation. Only relevant for BatchOperations.
289
+ MutateBatchHeader int
286
290
}
287
291
288
292
// BatchOperationConfig configures the relative probability of generating a
@@ -433,6 +437,7 @@ func newAllOperationsConfig() GeneratorConfig {
433
437
AddSSTable : 1 ,
434
438
Barrier : 1 ,
435
439
FlushLockTable : 1 ,
440
+ MutateBatchHeader : 1 ,
436
441
}
437
442
batchOpConfig := BatchOperationConfig {
438
443
Batch : 4 ,
@@ -498,6 +503,14 @@ func newAllOperationsConfig() GeneratorConfig {
498
503
// operations/make some operations more likely.
499
504
func NewDefaultConfig () GeneratorConfig {
500
505
config := newAllOperationsConfig ()
506
+
507
+ // MutateBatchHeader is only valid in batches.
508
+ config .Ops .DB .MutateBatchHeader = 0
509
+ config .Ops .ClosureTxn .TxnClientOps .MutateBatchHeader = 0
510
+
511
+ // TODO(#153446): Header mutations with EndTransaction are not currently safe.
512
+ config .Ops .ClosureTxn .CommitBatchOps .MutateBatchHeader = 0
513
+
501
514
// DeleteRangeUsingTombstone does not support transactions.
502
515
config .Ops .ClosureTxn .TxnClientOps .DeleteRangeUsingTombstone = 0
503
516
config .Ops .ClosureTxn .TxnBatchOps .Ops .DeleteRangeUsingTombstone = 0
@@ -876,6 +889,7 @@ func (g *generator) registerClientOps(allowed *[]opGen, c *ClientOperationConfig
876
889
addOpGen (allowed , randAddSSTable , c .AddSSTable )
877
890
addOpGen (allowed , randBarrier , c .Barrier )
878
891
addOpGen (allowed , randFlushLockTable , c .FlushLockTable )
892
+ addOpGen (allowed , randBatchMutation , c .MutateBatchHeader )
879
893
}
880
894
881
895
func (g * generator ) registerBatchOps (allowed * []opGen , c * BatchOperationConfig ) {
@@ -1452,6 +1466,19 @@ func randMergeIsSplit(g *generator, rng *rand.Rand) Operation {
1452
1466
return merge (key )
1453
1467
}
1454
1468
1469
+ func randBatchMutation (g * generator , rng * rand.Rand ) Operation {
1470
+ op := & MutateBatchHeaderOperation {}
1471
+ // We currently only support two header option mutations, both of which can
1472
+ // lead to early termination. Half the time we choose a value very likely to
1473
+ // lead to early termination.
1474
+ if rng .Float64 () > 0.5 {
1475
+ op .MaxSpanRequestKeys = randItem (rng , []int64 {1 , 100 })
1476
+ } else {
1477
+ op .TargetBytes = randItem (rng , []int64 {1 , 1 << 20 /* 1MiB */ })
1478
+ }
1479
+ return Operation {MutateBatchHeader : op }
1480
+ }
1481
+
1455
1482
func makeRemoveReplicaFn (key string , current []roachpb.ReplicationTarget , voter bool ) opGenFunc {
1456
1483
return func (g * generator , rng * rand.Rand ) Operation {
1457
1484
var changeType roachpb.ReplicaChangeType
@@ -1565,6 +1592,13 @@ func makeRandBatch(c *ClientOperationConfig) opGenFunc {
1565
1592
numOps := rng .Intn (4 )
1566
1593
ops := make ([]Operation , numOps )
1567
1594
var addedForwardScan , addedReverseScan bool
1595
+
1596
+ // TODO(ssd): MutateBatchHeader is disallowed with Puts because of
1597
+ // validation in the txnWriteBuffer that disallows such requests. We could
1598
+ // relax this restriction for many batches if we had information about the
1599
+ // enclosing transaction here.
1600
+ var addedPutOrCPut , addedBatchHeaderMutation bool
1601
+
1568
1602
for i := 0 ; i < numOps ; i ++ {
1569
1603
ops [i ] = g .selectOp (rng , allowed )
1570
1604
if ops [i ].Scan != nil {
@@ -1585,6 +1619,20 @@ func makeRandBatch(c *ClientOperationConfig) opGenFunc {
1585
1619
}
1586
1620
addedReverseScan = true
1587
1621
}
1622
+ } else if ops [i ].Put != nil {
1623
+ if addedBatchHeaderMutation {
1624
+ i --
1625
+ continue
1626
+ }
1627
+ addedPutOrCPut = true
1628
+ } else if ops [i ].MutateBatchHeader != nil {
1629
+ // In addition to avoiding batch mutations when we have Puts or CPuts,
1630
+ // we also skip adding mutations if one is already added.
1631
+ if addedPutOrCPut || addedBatchHeaderMutation {
1632
+ i --
1633
+ continue
1634
+ }
1635
+ addedBatchHeaderMutation = true
1588
1636
}
1589
1637
}
1590
1638
return batch (ops ... )
@@ -1803,6 +1851,10 @@ func keysBetween(keys map[string]struct{}, start, end string) []string {
1803
1851
return between
1804
1852
}
1805
1853
1854
+ func randItem [T any ](rng * rand.Rand , l []T ) T {
1855
+ return l [rng .Intn (len (l ))]
1856
+ }
1857
+
1806
1858
func randKey (rng * rand.Rand ) string {
1807
1859
// Avoid the endpoints because having point writes at the
1808
1860
// endpoints complicates randRangeSpan.
0 commit comments