Skip to content

Commit f37e9c2

Browse files
craig[bot]iskettanehbghalsravotto
committed
157153: spanset: assert that batches don't access store local and unreplicated RangeID local keys r=iskettaneh a=iskettaneh This PR adds the following test-only assertions: 1) Generated batches don't touch store-local keys. 2) Generated batches don't touch unreplicated RangeID local keys. We disable the check in exactly 3 locations we know that we currently touch those keys. Fixes: cockroachdb#156537 Release note: None 158065: sql: use new increment when restarting sequence r=bghal a=bghal Previously, if a sequence were restarted and its increment updated in the same transaction (command), the old increment would be used to set the value in KV. This change corrects the `ALTER` DDL to use the new increment value. Informs: cockroachdb#142914 Informs: cockroachdb#21564 Epic: CRDB-31283 Release note (sql change): Restarting a sequence with an updated increment has the expected initial value. 158089: ioctx: add ReaderAtSeekerAdapter for random access support r=sravotto a=sravotto This commit adds support for adapting context-aware readers that implement ReaderAtCtx and SeekerCtx into the standard io.ReaderAt and io.Seeker interfaces. This is needed for integrating cloud storage readers with libraries that require random access (e.g., Apache Parquet). The adapter: - Captures a context at construction time and uses it for all operations - Validates that the underlying reader actually supports seeking - Provides io.Reader, io.ReaderAt, io.Seeker, and io.Closer interfaces - Enables efficient random access to cloud-stored files without buffering Release note: None Epic: CRDB-23802 Co-authored-by: iskettaneh <[email protected]> Co-authored-by: Brendan Gerrity <[email protected]> Co-authored-by: Silvano Ravotto <[email protected]>
4 parents 9b16bb1 + 71bd03b + 8dfdc02 + c68e35a commit f37e9c2

21 files changed

+932
-122
lines changed

pkg/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,7 @@ ALL_TESTS = [
771771
"//pkg/util/interval/generic:generic_test",
772772
"//pkg/util/interval:interval_test",
773773
"//pkg/util/intsets:intsets_test",
774+
"//pkg/util/ioctx:ioctx_test",
774775
"//pkg/util/ipaddr:ipaddr_test",
775776
"//pkg/util/iterutil:iterutil_test",
776777
"//pkg/util/json/tokenizer:tokenizer_test",
@@ -2692,6 +2693,7 @@ GO_TARGETS = [
26922693
"//pkg/util/intsets:intsets",
26932694
"//pkg/util/intsets:intsets_test",
26942695
"//pkg/util/ioctx:ioctx",
2696+
"//pkg/util/ioctx:ioctx_test",
26952697
"//pkg/util/ipaddr:ipaddr",
26962698
"//pkg/util/ipaddr:ipaddr_test",
26972699
"//pkg/util/iterutil:iterutil",

pkg/keys/constants.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ var (
163163
//
164164
// LocalStorePrefix is the prefix identifying per-store data.
165165
LocalStorePrefix = makeKey(LocalPrefix, roachpb.Key("s"))
166+
LocalStoreMax = roachpb.Key(LocalStorePrefix).PrefixEnd()
166167
// localStoreClusterVersionSuffix stores the cluster-wide version
167168
// information for this store, updated any time the operator
168169
// updates the minimum cluster version.

pkg/keys/keys.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,17 @@ func DecodeRangeIDKey(
308308
return roachpb.RangeID(rangeInt), infix, suffix, b, nil
309309
}
310310

311+
// DecodeRangeIDPrefix parses a local range ID prefix into range ID.
312+
func DecodeRangeIDPrefix(key roachpb.Key) (roachpb.RangeID, error) {
313+
if !bytes.HasPrefix(key, LocalRangeIDPrefix) {
314+
return 0, errors.Errorf("key %s does not have %s prefix", key, LocalRangeIDPrefix)
315+
}
316+
// Cut the prefix, the Range ID, and the infix specifier.
317+
b := key[len(LocalRangeIDPrefix):]
318+
_, rangeInt, err := encoding.DecodeUvarintAscending(b)
319+
return roachpb.RangeID(rangeInt), err
320+
}
321+
311322
// AbortSpanKey returns a range-local key by Range ID for an
312323
// AbortSpan entry, with detail specified by encoding the
313324
// supplied transaction ID.

pkg/kv/kvserver/batcheval/cmd_add_sstable.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ func EvalAddSSTable(
337337
// addition, and instead just use this key-only iterator. If a caller actually
338338
// needs to know what data is there, it must issue its own real Scan.
339339
if args.ReturnFollowingLikelyNonEmptySpanStart {
340-
existingIter, err := spanset.DisableReaderAssertions(readWriter).NewMVCCIterator(
340+
existingIter, err := spanset.DisableUndeclaredSpanAssertions(readWriter).NewMVCCIterator(
341341
ctx,
342342
storage.MVCCKeyIterKind, // don't care if it is committed or not, just that it isn't empty.
343343
storage.IterOptions{

pkg/kv/kvserver/batcheval/cmd_delete.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func Delete(
5858
// If requested, replace point tombstones with range tombstones.
5959
if cArgs.EvalCtx.EvalKnobs().UseRangeTombstonesForPointDeletes && h.Txn == nil {
6060
if err := storage.ReplacePointTombstonesWithRangeTombstones(
61-
ctx, spanset.DisableReadWriterAssertions(readWriter),
61+
ctx, spanset.DisableUndeclaredSpanAssertions(readWriter),
6262
cArgs.Stats, args.Key, args.EndKey); err != nil {
6363
return result.Result{}, err
6464
}

pkg/kv/kvserver/batcheval/cmd_delete_range.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ func deleteRangeTransactional(
302302
// If requested, replace point tombstones with range tombstones.
303303
if cArgs.EvalCtx.EvalKnobs().UseRangeTombstonesForPointDeletes && h.Txn == nil {
304304
if err := storage.ReplacePointTombstonesWithRangeTombstones(
305-
ctx, spanset.DisableReadWriterAssertions(readWriter),
305+
ctx, spanset.DisableUndeclaredSpanAssertions(readWriter),
306306
cArgs.Stats, args.Key, args.EndKey); err != nil {
307307
return result.Result{}, err
308308
}

pkg/kv/kvserver/batcheval/cmd_end_transaction.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -719,7 +719,7 @@ func resolveLocalLocksWithPagination(
719719
// If requested, replace point tombstones with range tombstones.
720720
if ok && evalCtx.EvalKnobs().UseRangeTombstonesForPointDeletes {
721721
if err := storage.ReplacePointTombstonesWithRangeTombstones(
722-
ctx, spanset.DisableReadWriterAssertions(readWriter),
722+
ctx, spanset.DisableUndeclaredSpanAssertions(readWriter),
723723
ms, update.Key, update.EndKey); err != nil {
724724
return 0, 0, 0, errors.Wrapf(err,
725725
"replacing point tombstones with range tombstones for write intent at %s on end transaction [%s]",
@@ -757,7 +757,7 @@ func resolveLocalLocksWithPagination(
757757
// If requested, replace point tombstones with range tombstones.
758758
if evalCtx.EvalKnobs().UseRangeTombstonesForPointDeletes {
759759
if err := storage.ReplacePointTombstonesWithRangeTombstones(
760-
ctx, spanset.DisableReadWriterAssertions(readWriter),
760+
ctx, spanset.DisableUndeclaredSpanAssertions(readWriter),
761761
ms, update.Key, update.EndKey); err != nil {
762762
return 0, 0, 0, errors.Wrapf(err,
763763
"replacing point tombstones with range tombstones for write intent range at %s on end transaction [%s]",
@@ -1340,8 +1340,10 @@ func splitTriggerHelper(
13401340
if err != nil {
13411341
return enginepb.MVCCStats{}, result.Result{}, errors.Wrap(err, "unable to fetch last replica GC timestamp")
13421342
}
1343+
13431344
if err := storage.MVCCPutProto(
1344-
ctx, batch, keys.RangeLastReplicaGCTimestampKey(split.RightDesc.RangeID), hlc.Timestamp{},
1345+
ctx, spanset.DisableForbiddenSpanAssertions(batch),
1346+
keys.RangeLastReplicaGCTimestampKey(split.RightDesc.RangeID), hlc.Timestamp{},
13451347
&replicaGCTS, storage.MVCCWriteOptions{Category: fs.BatchEvalReadCategory}); err != nil {
13461348
return enginepb.MVCCStats{}, result.Result{}, errors.Wrap(err, "unable to copy last replica GC timestamp")
13471349
}
@@ -1541,7 +1543,8 @@ func splitTriggerHelper(
15411543
// as all replicas will be responsible for writing it locally before
15421544
// applying the split.
15431545
if !rec.ClusterSettings().Version.IsActive(ctx, clusterversion.V25_4_WriteInitialTruncStateBeforeSplitApplication) {
1544-
if err := kvstorage.WriteInitialTruncState(ctx, batch, split.RightDesc.RangeID); err != nil {
1546+
if err := kvstorage.WriteInitialTruncState(ctx,
1547+
spanset.DisableForbiddenSpanAssertions(batch), split.RightDesc.RangeID); err != nil {
15451548
return enginepb.MVCCStats{}, result.Result{}, errors.Wrap(err, "unable to write initial Replica state")
15461549
}
15471550
}

pkg/kv/kvserver/batcheval/cmd_resolve_intent.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ func ResolveIntent(
129129
// If requested, replace point tombstones with range tombstones.
130130
if ok && cArgs.EvalCtx.EvalKnobs().UseRangeTombstonesForPointDeletes {
131131
if err := storage.ReplacePointTombstonesWithRangeTombstones(ctx,
132-
spanset.DisableReadWriterAssertions(readWriter), ms, update.Key, update.EndKey); err != nil {
132+
spanset.DisableUndeclaredSpanAssertions(readWriter), ms, update.Key, update.EndKey); err != nil {
133133
return result.Result{}, err
134134
}
135135
}

pkg/kv/kvserver/batcheval/cmd_resolve_intent_range.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ func ResolveIntentRange(
9999
// If requested, replace point tombstones with range tombstones.
100100
if cArgs.EvalCtx.EvalKnobs().UseRangeTombstonesForPointDeletes {
101101
if err := storage.ReplacePointTombstonesWithRangeTombstones(ctx,
102-
spanset.DisableReadWriterAssertions(readWriter), ms, args.Key, args.EndKey); err != nil {
102+
spanset.DisableUndeclaredSpanAssertions(readWriter), ms, args.Key, args.EndKey); err != nil {
103103
return result.Result{}, err
104104
}
105105
}

pkg/kv/kvserver/replica_eval_context_span.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ func (rec *SpanSetReplicaEvalContext) IsFirstRange() bool {
110110
func (rec SpanSetReplicaEvalContext) Desc() *roachpb.RangeDescriptor {
111111
desc := rec.i.Desc()
112112
rec.ss.AssertAllowed(spanset.SpanReadOnly,
113-
roachpb.Span{Key: keys.RangeDescriptorKey(desc.StartKey)},
113+
spanset.TrickySpan{Key: keys.RangeDescriptorKey(desc.StartKey)},
114114
)
115115
return desc
116116
}
@@ -151,7 +151,7 @@ func (rec SpanSetReplicaEvalContext) CanCreateTxnRecord(
151151
ctx context.Context, txnID uuid.UUID, txnKey []byte, txnMinTS hlc.Timestamp,
152152
) (bool, kvpb.TransactionAbortedReason) {
153153
rec.ss.AssertAllowed(spanset.SpanReadOnly,
154-
roachpb.Span{Key: keys.TransactionKey(txnKey, txnID)},
154+
spanset.TrickySpan{Key: keys.TransactionKey(txnKey, txnID)},
155155
)
156156
return rec.i.CanCreateTxnRecord(ctx, txnID, txnKey, txnMinTS)
157157
}
@@ -163,7 +163,7 @@ func (rec SpanSetReplicaEvalContext) MinTxnCommitTS(
163163
ctx context.Context, txnID uuid.UUID, txnKey []byte,
164164
) hlc.Timestamp {
165165
rec.ss.AssertAllowed(spanset.SpanReadOnly,
166-
roachpb.Span{Key: keys.TransactionKey(txnKey, txnID)},
166+
spanset.TrickySpan{Key: keys.TransactionKey(txnKey, txnID)},
167167
)
168168
return rec.i.MinTxnCommitTS(ctx, txnID, txnKey)
169169
}
@@ -173,7 +173,7 @@ func (rec SpanSetReplicaEvalContext) MinTxnCommitTS(
173173
// not be served.
174174
func (rec SpanSetReplicaEvalContext) GetGCThreshold() hlc.Timestamp {
175175
rec.ss.AssertAllowed(spanset.SpanReadOnly,
176-
roachpb.Span{Key: keys.RangeGCThresholdKey(rec.GetRangeID())},
176+
spanset.TrickySpan{Key: keys.RangeGCThresholdKey(rec.GetRangeID())},
177177
)
178178
return rec.i.GetGCThreshold()
179179
}
@@ -197,7 +197,7 @@ func (rec SpanSetReplicaEvalContext) GetLastReplicaGCTimestamp(
197197
ctx context.Context,
198198
) (hlc.Timestamp, error) {
199199
if err := rec.ss.CheckAllowed(spanset.SpanReadOnly,
200-
roachpb.Span{Key: keys.RangeLastReplicaGCTimestampKey(rec.GetRangeID())},
200+
spanset.TrickySpan{Key: keys.RangeLastReplicaGCTimestampKey(rec.GetRangeID())},
201201
); err != nil {
202202
return hlc.Timestamp{}, err
203203
}
@@ -228,11 +228,11 @@ func (rec *SpanSetReplicaEvalContext) GetCurrentReadSummary(ctx context.Context)
228228
// To capture a read summary over the range, all keys must be latched for
229229
// writing to prevent any concurrent reads or writes.
230230
desc := rec.i.Desc()
231-
rec.ss.AssertAllowed(spanset.SpanReadWrite, roachpb.Span{
231+
rec.ss.AssertAllowed(spanset.SpanReadWrite, spanset.TrickySpan{
232232
Key: keys.MakeRangeKeyPrefix(desc.StartKey),
233233
EndKey: keys.MakeRangeKeyPrefix(desc.EndKey),
234234
})
235-
rec.ss.AssertAllowed(spanset.SpanReadWrite, roachpb.Span{
235+
rec.ss.AssertAllowed(spanset.SpanReadWrite, spanset.TrickySpan{
236236
Key: desc.StartKey.AsRawKey(),
237237
EndKey: desc.EndKey.AsRawKey(),
238238
})

0 commit comments

Comments
 (0)