Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kvnemesis: add support for AddSSTable #89145

Merged
merged 1 commit into from
Dec 22, 2022

Conversation

erikgrinaker
Copy link
Contributor

@erikgrinaker erikgrinaker commented Oct 1, 2022

This patch adds support for AddSSTable operations in kvnemesis. It generates SSTs of 1-16 point key/value pairs, using options that make the ingestion MVCC-compliant (SSTTimestampToRequestTimestamp and DisallowConflicts).

It does not yet test ingestion of MVCC range tombstones, since this is not yet used in production code, and to avoid blocking this PR on any range key-related issues. A later PR will address this.

AddSSTable requests cannot span multiple ranges, so the generator optimistically builds SSTs based on the currently known splits. This may race with concurrent splits causing the request to fail, but the majority of requests will succeed.

Resolves #64824.

Release note: None

@erikgrinaker erikgrinaker requested review from tbg, nvanbenschoten and a team October 1, 2022 14:22
@erikgrinaker erikgrinaker self-assigned this Oct 1, 2022
@erikgrinaker erikgrinaker requested a review from a team as a code owner October 1, 2022 14:22
@cockroach-teamcity
Copy link
Member

This change is Reviewable

@erikgrinaker
Copy link
Contributor Author

@tbg Would be great if you could add in support for ingestion of MVCC point/range tombstones once you wrap up the work on deletion validation.

@erikgrinaker
Copy link
Contributor Author

@tbg This is ready for review now. With the attached bug fixes I had 20000 passes.

Copy link
Member

@tbg tbg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! A couple of comments but approving preemptively since none of them are for hills I'd choose to perish on.

pkg/kv/kvnemesis/generator.go Outdated Show resolved Hide resolved
pkg/kv/kvnemesis/generator.go Outdated Show resolved Hide resolved
pkg/kv/kvnemesis/generator.go Outdated Show resolved Hide resolved
rangeEnd = ranges[rangeIdx+1]
}
inRange := func(key string) bool {
return key >= rangeStart && (key < rangeEnd || rangeEnd == "")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All keys are encoded uints, check the fk and tk methods. You can do int arithmetic for everything and this is how we do it elsewhere, I would prefer we stick to one pattern because each way of interacting with their keys has its idiosyncrasies and diversity doesn't pay off.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, done.

pkg/kv/kvnemesis/generator.go Show resolved Hide resolved
pkg/kv/kvnemesis/validator.go Outdated Show resolved Hide resolved
// error and try again later.
} else if resultIsErrorStr(t.Result, "write for key .* at timestamp .* too old; wrote at") {
// We may race with a concurrent write. Try again later.
} else if v.checkNonAmbError(op, t.Result) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I definitely am not doing anyone a favor with this v.checkX methods, I needed to read comments two layers deep to remember how this works again. When looking at this line I was like "are you just ignoring errors here?!" but v.checkNonAmbError will emit a failure to the validator on non-exempt errors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment to clarify this.

@@ -1807,6 +1827,16 @@ func TestValidate(t *testing.T) {
rd(k1, k2, t2, s2),
),
},
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth pairing this with at least one or two other interactions with other commands? I've seen the verifier code and the changes are fairly trivial so we probably don't need too much else.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, may as well. Added some shadowing and scans.

case *roachpb.RangeFeedSSTable:
w.mu.Lock()
if len(e.Data) == 0 {
return errors.AssertionFailedf("no SST data found")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The locking here is broken, lots of error returns that never unlock.

What I don't understand is why the other code branches do this too, is this ok for some reason?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you pull this out into w.handleAddSSTable? That will solve your locking problem and also declutter this method.

If you feel generous you could do the same for the rangefeed checkpoint case above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test will fail and exit on any errors, so it doesn't really matter that we're holding the lock, and I figured since we already did this for other branches it was "fine". Anyway, will pull them out into separate methods.

if seq := mvccValue.KVNemesisSeq.Get(); seq > 0 {
w.env.Tracker.Add(key.Key, nil, key.Timestamp, seq)
}
if err := w.handleValueLocked(ctx, roachpb.Span{Key: key.Key}, mvccValue.Value, nil); err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a comment on (*SeqTracker).Add explaining that for point writes, we rely on a RangefeedValueHeaderFilter knob to tell us the seqnos of writes as they get emitted from the rangefeed, while for AddSST the emitted rangefeed event itself contains the seqno and so it is added in the watcher?
This is a leaky comment but I think it tells people everything they need to know.

@erikgrinaker
Copy link
Contributor Author

bors r+

@craig
Copy link
Contributor

craig bot commented Dec 22, 2022

Build failed:

@erikgrinaker
Copy link
Contributor Author

bors retry

This patch adds support for `AddSSTable` operations in kvnemesis. It
generates SSTs of 1-16 point key/value pairs, using options that make
the ingestion MVCC-compliant (`SSTTimestampToRequestTimestamp` and
`DisallowConflicts`).

It does not yet test ingestion of MVCC range tombstones, since this is
not yet used in production code, and to avoid blocking this PR on any
range key-related issues. A later PR will address this.

`AddSSTable` requests cannot span multiple ranges, so the generator
optimistically builds SSTs based on the currently known splits. This may
race with concurrent splits causing the request to fail, but the
majority of requests will succeed.

Release note: None
@craig
Copy link
Contributor

craig bot commented Dec 22, 2022

Canceled.

@erikgrinaker
Copy link
Contributor Author

bors retry

@craig
Copy link
Contributor

craig bot commented Dec 22, 2022

Build failed (retrying...):

@craig
Copy link
Contributor

craig bot commented Dec 22, 2022

Build succeeded:

@craig craig bot merged commit d043004 into cockroachdb:master Dec 22, 2022
@erikgrinaker erikgrinaker deleted the kvnemesis-addsstable branch December 28, 2022 11:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

kvnemesis: add AddSSTable
3 participants