Skip to content

Commit 892c5d3

Browse files
chore: perform checksum for single shot uploads (#13733)
1 parent 592a782 commit 892c5d3

7 files changed

Lines changed: 161 additions & 53 deletions

File tree

storage/doc.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -407,9 +407,14 @@ roles which must be enabled in order to do the export successfully. To
407407
disable this export, you can use the [WithDisabledClientMetrics] client
408408
option.
409409
410-
The gRPC client automatically computes and sends CRC32C checksums for uploads using [Writer],
411-
which provides an additional layer of data integrity validation when compared to the HTTP client.
412-
This behavior can optionally be disabled by using [Writer.DisableAutoChecksum].
410+
The client automatically computes and sends CRC32C checksums for uploads using [Writer],
411+
providing an additional layer of data integrity validation with a slight CPU overhead.
412+
413+
Note: With a chunk size of 0 (no buffering) in JSON uploads, an auto-calculated checksum mismatch
414+
returns an error but may leave corrupt data on the server, requiring manual cleanup. This risk does not
415+
apply to single-shot uploads when user-provided checksum is provided.
416+
417+
Automatic checksumming can be disabled using [Writer.DisableAutoChecksum].
413418
414419
# Storage Control API
415420

storage/go.mod

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ retract [v1.25.0, v1.27.0] // due to https://github.com/googleapis/google-cloud-
66

77
require (
88
cloud.google.com/go v0.123.0
9-
cloud.google.com/go/auth v0.18.0
9+
cloud.google.com/go/auth v0.18.1
1010
cloud.google.com/go/compute/metadata v0.9.0
1111
cloud.google.com/go/iam v1.5.3
1212
cloud.google.com/go/longrunning v0.8.0
@@ -22,10 +22,10 @@ require (
2222
go.opentelemetry.io/otel/trace v1.39.0
2323
golang.org/x/oauth2 v0.34.0
2424
golang.org/x/sync v0.19.0
25-
google.golang.org/api v0.259.0
25+
google.golang.org/api v0.265.0
2626
google.golang.org/genproto v0.0.0-20251202230838-ff82c1b0f217
27-
google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b
28-
google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b
27+
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217
28+
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409
2929
google.golang.org/grpc v1.78.0
3030
google.golang.org/protobuf v1.36.11
3131
)
@@ -46,16 +46,16 @@ require (
4646
github.com/go-logr/stdr v1.2.2 // indirect
4747
github.com/google/martian/v3 v3.3.3 // indirect
4848
github.com/google/s2a-go v0.1.9 // indirect
49-
github.com/googleapis/enterprise-certificate-proxy v0.3.7 // indirect
49+
github.com/googleapis/enterprise-certificate-proxy v0.3.11 // indirect
5050
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
5151
github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect
5252
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
5353
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 // indirect
5454
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
5555
go.opentelemetry.io/otel/metric v1.39.0 // indirect
56-
golang.org/x/crypto v0.46.0 // indirect
57-
golang.org/x/net v0.48.0 // indirect
58-
golang.org/x/sys v0.39.0 // indirect
59-
golang.org/x/text v0.32.0 // indirect
56+
golang.org/x/crypto v0.47.0 // indirect
57+
golang.org/x/net v0.49.0 // indirect
58+
golang.org/x/sys v0.40.0 // indirect
59+
golang.org/x/text v0.33.0 // indirect
6060
golang.org/x/time v0.14.0 // indirect
6161
)

storage/go.sum

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY=
22
cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
33
cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE=
44
cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU=
5-
cloud.google.com/go/auth v0.18.0 h1:wnqy5hrv7p3k7cShwAU/Br3nzod7fxoqG+k0VZ+/Pk0=
6-
cloud.google.com/go/auth v0.18.0/go.mod h1:wwkPM1AgE1f2u6dG443MiWoD8C3BtOywNsUMcUTVDRo=
5+
cloud.google.com/go/auth v0.18.1 h1:IwTEx92GFUo2pJ6Qea0EU3zYvKnTAeRCODxfA/G5UWs=
6+
cloud.google.com/go/auth v0.18.1/go.mod h1:GfTYoS9G3CWpRA3Va9doKN9mjPGRS+v41jmZAhBzbrA=
77
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
88
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
99
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
@@ -61,8 +61,8 @@ github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
6161
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
6262
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
6363
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
64-
github.com/googleapis/enterprise-certificate-proxy v0.3.7 h1:zrn2Ee/nWmHulBx5sAVrGgAa0f2/R35S4DJwfFaUPFQ=
65-
github.com/googleapis/enterprise-certificate-proxy v0.3.7/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
64+
github.com/googleapis/enterprise-certificate-proxy v0.3.11 h1:vAe81Msw+8tKUxi2Dqh/NZMz7475yUvmRIkXr4oN2ao=
65+
github.com/googleapis/enterprise-certificate-proxy v0.3.11/go.mod h1:RFV7MUdlb7AgEq2v7FmMCfeSMCllAzWxFgRdusoGks8=
6666
github.com/googleapis/gax-go/v2 v2.16.0 h1:iHbQmKLLZrexmb0OSsNGTeSTS0HO4YvFOG8g5E4Zd0Y=
6767
github.com/googleapis/gax-go/v2 v2.16.0/go.mod h1:o1vfQjjNZn4+dPnRdl/4ZD7S9414Y4xA+a/6Icj6l14=
6868
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
@@ -95,30 +95,30 @@ go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6
9595
go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=
9696
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
9797
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
98-
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
99-
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
100-
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
101-
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
98+
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
99+
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
100+
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
101+
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
102102
golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
103103
golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
104104
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
105105
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
106-
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
107-
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
108-
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
109-
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
106+
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
107+
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
108+
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
109+
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
110110
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
111111
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
112112
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
113113
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
114-
google.golang.org/api v0.259.0 h1:90TaGVIxScrh1Vn/XI2426kRpBqHwWIzVBzJsVZ5XrQ=
115-
google.golang.org/api v0.259.0/go.mod h1:LC2ISWGWbRoyQVpxGntWwLWN/vLNxxKBK9KuJRI8Te4=
114+
google.golang.org/api v0.265.0 h1:FZvfUdI8nfmuNrE34aOWFPmLC+qRBEiNm3JdivTvAAU=
115+
google.golang.org/api v0.265.0/go.mod h1:uAvfEl3SLUj/7n6k+lJutcswVojHPp2Sp08jWCu8hLY=
116116
google.golang.org/genproto v0.0.0-20251202230838-ff82c1b0f217 h1:GvESR9BIyHUahIb0NcTum6itIWtdoglGX+rnGxm2934=
117117
google.golang.org/genproto v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:yJ2HH4EHEDTd3JiLmhds6NkJ17ITVYOdV3m3VKOnws0=
118-
google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b h1:uA40e2M6fYRBf0+8uN5mLlqUtV192iiksiICIBkYJ1E=
119-
google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:Xa7le7qx2vmqB/SzWUBa7KdMjpdpAHlh5QCSnjessQk=
120-
google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b h1:Mv8VFug0MP9e5vUxfBcE3vUkV6CImK3cMNMIDFjmzxU=
121-
google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
118+
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls=
119+
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto=
120+
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 h1:H86B94AW+VfJWDqFeEbBPhEtHzJwJfTbgE2lZa54ZAQ=
121+
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
122122
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
123123
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
124124
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=

storage/http_client.go

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -983,11 +983,48 @@ func (c *httpStorageClient) newRangeReaderJSON(ctx context.Context, params *newR
983983
return parseReadResponse(res, params, reopen)
984984
}
985985

986+
// httpInternalWriter writes data for an HTTP upload. For single-shot uploads,
987+
// it also calculates the CRC32C checksum of the data and validates it against
988+
// the checksum returned by the server.
986989
type httpInternalWriter struct {
987990
*io.PipeWriter
991+
chunkSize int
992+
checksumDisabled bool
993+
fullObjectChecksum uint32
994+
// In single-shot mode, the server-provided checksum is received on this
995+
// channel for validation after the upload is complete.
996+
serverChecksumChan chan uint32
988997
}
989998

990-
func (hiw httpInternalWriter) Flush() (int64, error) {
999+
// validateChecksum validates the computed checksum against the server-provided checksum.
1000+
func (hiw *httpInternalWriter) validateChecksumFromServer() error {
1001+
serverChecksum, ok := <-hiw.serverChecksumChan
1002+
// Do not check for channel closure as error is already set on the writer
1003+
// if serverChecksumChan is closed without checksum
1004+
if ok && hiw.fullObjectChecksum != serverChecksum {
1005+
return fmt.Errorf("storage: object checksum mismatch: computed %q, server %q; the bucket may contain corrupted object", encodeUint32(hiw.fullObjectChecksum), encodeUint32(serverChecksum))
1006+
}
1007+
return nil
1008+
}
1009+
1010+
func (hiw *httpInternalWriter) Write(data []byte) (n int, err error) {
1011+
if !hiw.checksumDisabled && hiw.chunkSize == 0 {
1012+
hiw.fullObjectChecksum = crc32.Update(hiw.fullObjectChecksum, crc32cTable, data)
1013+
}
1014+
return hiw.PipeWriter.Write(data)
1015+
}
1016+
1017+
func (hiw *httpInternalWriter) Close() error {
1018+
if err := hiw.PipeWriter.Close(); err != nil {
1019+
return err
1020+
}
1021+
if !hiw.checksumDisabled && hiw.chunkSize == 0 {
1022+
return hiw.validateChecksumFromServer()
1023+
}
1024+
return nil
1025+
}
1026+
1027+
func (hiw *httpInternalWriter) Flush() (int64, error) {
9911028
return 0, errors.New("Writer.Flush is only supported for gRPC-based clients")
9921029
}
9931030

@@ -1014,15 +1051,20 @@ func (c *httpStorageClient) OpenWriter(params *openWriterParams, opts ...storage
10141051
if params.chunkTransferTimeout != 0 {
10151052
mediaOpts = append(mediaOpts, googleapi.ChunkTransferTimeout(params.chunkTransferTimeout))
10161053
}
1017-
if !params.disableAutoChecksum {
1018-
mediaOpts = append(mediaOpts, googleapi.EnableAutoChecksum())
1019-
}
10201054

10211055
pr, pw := io.Pipe()
1022-
1056+
var (
1057+
serverChecksumChan = make(chan uint32, 1)
1058+
checksumDisabled = params.disableAutoChecksum || params.sendCRC32C
1059+
)
1060+
if !checksumDisabled {
1061+
mediaOpts = append(mediaOpts, googleapi.EnableAutoChecksum())
1062+
}
10231063
go func() {
1024-
defer close(params.donec)
1025-
1064+
defer func() {
1065+
close(params.donec)
1066+
close(serverChecksumChan)
1067+
}()
10261068
rawObj := attrs.toRawObject(params.bucket)
10271069
if params.sendCRC32C {
10281070
rawObj.Crc32c = encodeUint32(attrs.CRC32C)
@@ -1084,10 +1126,18 @@ func (c *httpStorageClient) OpenWriter(params *openWriterParams, opts ...storage
10841126
pr.CloseWithError(err)
10851127
return
10861128
}
1087-
setObj(newObject(resp))
1129+
newObj := newObject(resp)
1130+
if !checksumDisabled && params.chunkSize == 0 {
1131+
serverChecksumChan <- newObj.CRC32C
1132+
}
1133+
setObj(newObj)
10881134
}()
1089-
1090-
return httpInternalWriter{pw}, nil
1135+
return &httpInternalWriter{
1136+
PipeWriter: pw,
1137+
chunkSize: params.chunkSize,
1138+
serverChecksumChan: serverChecksumChan,
1139+
checksumDisabled: checksumDisabled,
1140+
}, nil
10911141
}
10921142

10931143
// IAM methods.

storage/http_client_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package storage
1616

1717
import (
1818
"context"
19+
"fmt"
1920
"net/http"
2021
"testing"
2122

@@ -125,3 +126,48 @@ func TestAppendableWriteUnsupported(t *testing.T) {
125126
t.Errorf("OpenWriter: got ok; want error")
126127
}
127128
}
129+
130+
func TestValidateChecksumFromServer(t *testing.T) {
131+
correctChecksum := 1
132+
tests := []struct {
133+
name string
134+
wrongChecksum bool
135+
wantErr error
136+
}{
137+
{
138+
name: "correct checksum",
139+
wrongChecksum: false,
140+
},
141+
{
142+
name: "wrong checksum",
143+
wrongChecksum: true,
144+
wantErr: fmt.Errorf("storage: computed object checksum (%q) doesn't match with server's object checksum (%q)", encodeUint32(2), encodeUint32(1)),
145+
},
146+
}
147+
for _, test := range tests {
148+
t.Run(test.name, func(t *testing.T) {
149+
serverChecksumChan := make(chan uint32, 1)
150+
checksum := correctChecksum
151+
if test.wrongChecksum {
152+
checksum = 2
153+
}
154+
hiw := &httpInternalWriter{
155+
serverChecksumChan: serverChecksumChan,
156+
fullObjectChecksum: uint32(checksum),
157+
}
158+
go func() {
159+
serverChecksumChan <- uint32(correctChecksum)
160+
}()
161+
err := hiw.validateChecksumFromServer()
162+
if test.wantErr == nil {
163+
if err != nil {
164+
t.Fatalf("Unexpected error: %v", err)
165+
}
166+
return
167+
}
168+
if err.Error() != test.wantErr.Error() {
169+
t.Errorf("Want err: %v, got err: %v", err, test.wantErr)
170+
}
171+
})
172+
}
173+
}

storage/integration_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1998,6 +1998,11 @@ func TestIntegration_WriterCRC32CValidation(t *testing.T) {
19981998
chunkSize: 256 * 1024,
19991999
sendCRC32C: true,
20002000
},
2001+
{
2002+
name: "small uploads - data size < chunk size with default CRC32C",
2003+
content: bytes.Repeat([]byte("a"), 200*1024),
2004+
chunkSize: 256 * 1024,
2005+
},
20012006
{
20022007
name: "resumable with default CRC32",
20032008
content: bytes.Repeat([]byte("a"), 1*MiB),

storage/writer.go

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,33 +47,35 @@ type Writer struct {
4747
// It is necessary to set this field to true in addition to setting the
4848
// Writer's CRC32C field because zero is a valid CRC.
4949
//
50-
// When using gRPC, the client automatically calculates and sends checksums
51-
// per-chunk and for the full object. However, A user-provided checksum takes
52-
// precedence over the auto-calculated checksum for full object.
53-
// To disable auto checksum behavior, see DisableAutoChecksum.
50+
// By default, the client automatically calculates and sends checksums.
51+
// When using gRPC, checksums are sent for both individual chunks and the full object.
52+
// When using JSON, checksums are sent only for the full object.
53+
// However, a user-provided checksum takes precedence over the auto-calculated checksum
54+
// for the full object.
5455
//
5556
// Note: SendCRC32C must be set before the first call to Writer.Write().
5657
SendCRC32C bool
5758

5859
// DisableAutoChecksum disables automatic CRC32C checksum calculation and
59-
// validation. By default, the Writer automatically performs checksum
60-
// validation for both gRPC and JSON uploads. For gRPC, this includes
61-
// validation for both individual chunks and the entire object. For JSON,
62-
// checksums are validated for full object but only for resumable uploads. Setting
63-
// this to true disables this automatic checksumming behavior.
60+
// validation in the Writer. By default, the Writer automatically performs
61+
// checksum validation. Setting this to true disables this behavior.
6462
//
6563
// Disabling automatic checksumming does not prevent a user-provided checksum
6664
// from being sent. If SendCRC32C is true and the Writer's CRC32C field is
6765
// populated, that checksum will still be sent to GCS for validation.
6866
//
67+
// For single-shot JSON uploads, a mismatch in the auto-calculated checksum returns
68+
// an error but may leave data on the server. This issue does not apply when
69+
// user-provided checksum is used. Callers relying on auto-checksum should handle the
70+
// error by removing the object or restoring a previous version.
71+
//
6972
// Automatic CRC32C checksum calculation introduces increased CPU overhead
70-
// because of checksum computation in gRPC writes. Use this field to disable
73+
// because of checksum computation in writes. Use this field to disable
7174
// it if needed.
7275
//
7376
// Note: DisableAutoChecksum must be set before the first call to
74-
// Writer.Write(). Automatic checksumming is not enabled for writes
75-
// using the HTTP client or for full object checksums for unfinalized writes to
76-
// appendable objects in gRPC.
77+
// Writer.Write(). Automatic checksumming is not enabled for full object
78+
// checksums for unfinalized writes to appendable objects in gRPC.
7779
DisableAutoChecksum bool
7880

7981
// ChunkSize controls the maximum number of bytes of the object that the

0 commit comments

Comments
 (0)