Skip to content

kvclient, roachpb: cleanup the CPut API#50408

Merged
craig[bot] merged 3 commits intocockroachdb:masterfrom
andreimatei:cput-bytes
Jun 25, 2020
Merged

kvclient, roachpb: cleanup the CPut API#50408
craig[bot] merged 3 commits intocockroachdb:masterfrom
andreimatei:cput-bytes

Conversation

@andreimatei
Copy link
Copy Markdown
Contributor

The CPut API was funky: it took an expected value as a roachpb.Value,
but the checksum in it and the timestamp didn't matter. This was
undocumented. The checksum in particular covers both the key and the
value, so its relationship with a CPut is weird (since the key for
which we're using the value might be different from the key from whence
it came). This choice of Value had consequences for the Batch API:
Batch.CPut() was taking a *roachpb.Value, for which it cleared and then
re-initialized the checksum. This was all surprising, and meant that
some callers had to copy the underlying bytes for the value before
passing them to CPut().

This patch changes all the interfaces to just take []byte. There's no
longer a checksum or a timestamp to speak of. CPut() now also internally
copies the expected value's bytes, so the caller no longer needs to
worry about ownership.

Release note: None

@andreimatei andreimatei requested review from irfansharif, nvb and tbg June 18, 2020 23:14
@cockroach-teamcity
Copy link
Copy Markdown
Member

This change is Reviewable

@andreimatei andreimatei requested a review from bdarnell June 18, 2020 23:16
Copy link
Copy Markdown
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.

Basically looks good, had a few comments, thanks for working this out.

Reviewed 9 of 9 files at r1, 27 of 27 files at r2.
Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @andreimatei, @bdarnell, @irfansharif, and @nvanbenschoten)


Makefile, line 1230 at r2 (raw file):

PROTO_MAPPINGS := $(PROTO_MAPPINGS)Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types,
PROTO_MAPPINGS := $(PROTO_MAPPINGS)Mgoogle/protobuf/any.proto=github.com/gogo/protobuf/types,
PROTO_MAPPINGS := $(PROTO_MAPPINGS)Mgoogle/protobuf/wrappers.proto=github.com/gogo/protobuf/types,

?


pkg/roachpb/api.go, line 981 at r2 (raw file):

	var expBytes *types.BytesValue
	if expValue != nil {
		expBytes = &types.BytesValue{

Why? This is an extra alloc, what value does this provide? Distinguishing between "nothing" and empty? You could also do that with an additional bool. (I'll defer to @nvanbenschoten on whether this is important enough to do, but it's the pattern I wished protobufs in Go used generally via a bitmap).


pkg/roachpb/api.proto, line 193 at r2 (raw file):

  Value deprecated_exp_value = 3;
  // exp_bytes represents the expected existing value for the key. If missing,
  // the key is expected to not exist. If set to []byte{}, the value is expected

You can't set this to []byte{}, make this precise.


pkg/roachpb/api.proto, line 202 at r2 (raw file):

  //
  // Note that the existing value's timestamp doesn't matter, only its data. So,
  // the CPut will succeed in ABA situations.

ABA?

Copy link
Copy Markdown
Contributor Author

@andreimatei andreimatei left a comment

Choose a reason for hiding this comment

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

prepended a commit. PTAL

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @bdarnell, @irfansharif, @nvanbenschoten, and @tbg)


Makefile, line 1230 at r2 (raw file):

Previously, tbg (Tobias Grieger) wrote…

?

for google.protobuf.BytesValue. But it's gone.


pkg/roachpb/api.go, line 981 at r2 (raw file):

Previously, tbg (Tobias Grieger) wrote…

Why? This is an extra alloc, what value does this provide? Distinguishing between "nothing" and empty? You could also do that with an additional bool. (I'll defer to @nvanbenschoten on whether this is important enough to do, but it's the pattern I wished protobufs in Go used generally via a bitmap).

The distinction has gone away. See the first commit.


pkg/roachpb/api.proto, line 193 at r2 (raw file):

Previously, tbg (Tobias Grieger) wrote…

You can't set this to []byte{}, make this precise.

Well the intention was that you could set it to that. But I've done some digging and decided to remove the distinction between missing keys and keys with empty values, since the latter don't actually exist. See now.


pkg/roachpb/api.proto, line 202 at r2 (raw file):

Previously, tbg (Tobias Grieger) wrote…

ABA?

I thought it's a known term. Explained.

Copy link
Copy Markdown
Contributor

@irfansharif irfansharif left a comment

Choose a reason for hiding this comment

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

:lgtm:

Reviewed 33 of 33 files at r3, 9 of 9 files at r4, 26 of 26 files at r5.
Reviewable status: :shipit: complete! 1 of 0 LGTMs obtained (waiting on @andreimatei, @bdarnell, @nvanbenschoten, and @tbg)


pkg/kv/kvserver/replica_command.go, line 1963 at r5 (raw file):

// parsed RangeDescriptor directly as the expected value in a CPut, but proto
// message encodings aren't stable so this was fragile. Calling this method and
// then passing the returned nytes as the expected value in a CPut does the same

s/nytes/bytes


pkg/roachpb/api.proto, line 182 at r5 (raw file):

  // deprecated_exp_val represents the expected existing value for the key. If
  // the existing value is different, the request will return a
  // ConditionFailedError. A missing (Go nil) exp_value.raw_bytes means that the

s/exp_value/deprecated_exp_value

@tbg tbg self-requested a review June 23, 2020 14:59
Copy link
Copy Markdown
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, I only reviewed the "clarify that Put() with nil value is not a thing" commit. Let me know if I should also re-visit anything else.

While thinking about the CPut API, the question about whether or not
keys with empty values can exist. Comments on ConditionalPutRequest
suggest that there is such a thing as an "empty value". A completely
empty value represents a an MVCC deletion tombstone, so that part is
clear, but more intriguing is the case of a key with a value that
consists just of a checksum and nothing else. Allowing such values would
arguably make sense, but it turns out that such KVs don't exist, since
the Value would be invalid according to the Value.Verify() method which
requires a full header (a checksum and a type tag). Correspondingly, our
APIs don't provide ways to create a Value without some data in it (which
data could be an empty byte array, for example, but that has a non-empty
encoding). Figuring this out with any confidence was not trivial,
though.

This patch adds assertions to Batch.Put() against trying to use such
empty values - serving mostly as documentation, and it also sprinkles
some comments about the meaning of nil values to other APIs.

Release note: None
In all other contexts, a Value's "data" does not include its tag (e.g.
the Value.dataBytes() method), except for this method. The new name
makes it explicit.

Release note: None
Copy link
Copy Markdown
Contributor Author

@andreimatei andreimatei left a comment

Choose a reason for hiding this comment

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

TFTRs

bors r+

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (and 1 stale) (waiting on @bdarnell, @irfansharif, @nvanbenschoten, and @tbg)


pkg/kv/kvserver/replica_command.go, line 1963 at r5 (raw file):

Previously, irfansharif (irfan sharif) wrote…

s/nytes/bytes

Done.


pkg/roachpb/api.proto, line 182 at r5 (raw file):

Previously, irfansharif (irfan sharif) wrote…

s/exp_value/deprecated_exp_value

done

@craig
Copy link
Copy Markdown
Contributor

craig bot commented Jun 25, 2020

Build failed

The CPut API was funky: it took an expected value as a roachpb.Value,
but the checksum in it and the timestamp didn't matter. This was
undocumented. The checksum in particular covers both the key and the
value, so its relationship with a CPut is weird (since the key for
which we're using the value might be different from the key from whence
it came). This choice of Value had consequences for the Batch API:
Batch.CPut() was taking a *roachpb.Value, for which it cleared and then
re-initialized the checksum. This was all surprising, and meant that
some callers had to copy the underlying bytes for the value before
passing them to CPut().

This patch changes all the interfaces to just take []byte. There's no
longer a checksum or a timestamp to speak of. CPut() now also internally
copies the expected value's bytes, so the caller no longer needs to
worry about ownership.

Release note: None
Copy link
Copy Markdown
Contributor Author

@andreimatei andreimatei left a comment

Choose a reason for hiding this comment

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

bors r+

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (and 1 stale) (waiting on @bdarnell, @irfansharif, @nvanbenschoten, and @tbg)

@craig
Copy link
Copy Markdown
Contributor

craig bot commented Jun 25, 2020

Canceled (will resume)

@craig
Copy link
Copy Markdown
Contributor

craig bot commented Jun 25, 2020

Build succeeded

@craig craig bot merged commit 0715b9c into cockroachdb:master Jun 25, 2020
@andreimatei andreimatei deleted the cput-bytes branch June 26, 2020 17:56
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.

4 participants