@@ -430,6 +430,105 @@ service ContentAddressableStorage {
430
430
rpc GetTree (GetTreeRequest ) returns (stream GetTreeResponse ) {
431
431
option (google.api.http ) = { get : "/v2/{instance_name=**}/blobs/{root_digest.hash}/{root_digest.size_bytes}:getTree" };
432
432
}
433
+
434
+ // Split a blob into chunks.
435
+ //
436
+ // This call splits a blob into chunks, stores the chunks in the CAS, and
437
+ // returns a list of the chunk digests. Using this list, a client can check
438
+ // which chunks are locally available and just fetch the missing ones. The
439
+ // desired blob can be assembled by concatenating the fetched chunks in the
440
+ // order of the digests from the list.
441
+ //
442
+ // This rpc can be used to reduce the required data to download a large blob
443
+ // from CAS if chunks from earlier downloads of a different version of this
444
+ // blob are locally available. For this procedure to work properly, blobs need
445
+ // to be split in a content-defined way, rather than with fixed-sized
446
+ // chunking.
447
+ //
448
+ // If a split request is answered successfully, a client can expect the
449
+ // following guarantees from the server:
450
+ // 1. The blob chunks are stored in CAS.
451
+ // 2. Concatenating the blob chunks in the order of the digest list returned
452
+ // by the server results in the original blob.
453
+ //
454
+ // Servers are free to implement this functionality, but they need to declare
455
+ // whether they support it or not by setting the
456
+ // [CacheCapabilities.blob_split_support][build.bazel.remote.execution.v2.CacheCapabilities.blob_split_support]
457
+ // field accordingly.
458
+ //
459
+ // Clients are free to use this functionality, it is just an optimization to
460
+ // reduce download network traffic, when downloading large blobs from the CAS.
461
+ // However, clients need to check first the server capabilities, whether blob
462
+ // splitting is supported by the server.
463
+ //
464
+ // Hints:
465
+ //
466
+ // * For clients, it is recommended to verify whether the digest of the blob
467
+ // assembled by the fetched chunks results in the requested blob digest.
468
+ //
469
+ // * Since the generated chunks are stored as blobs, they underlie the same
470
+ // lifetimes as other blobs. However, their lifetimes are extended if they
471
+ // are part of the result of a split blob request.
472
+ //
473
+ // * When blob splitting and splicing is used at the same time, the clients
474
+ // and the server should out-of-band agree upon a chunking algorithm used by
475
+ // all parties to benefit from each others chunk data and avoid unnecessary
476
+ // data duplication.
477
+ //
478
+ // Errors:
479
+ //
480
+ // * `NOT_FOUND`: The requested blob is not present in the CAS.
481
+ // * `RESOURCE_EXHAUSTED`: There is insufficient disk quota to store the blob
482
+ // chunks.
483
+ rpc SplitBlob (SplitBlobRequest ) returns (SplitBlobResponse ) {
484
+ option (google.api.http ) = { get : "/v2/{instance_name=**}/blobs/{blob_digest.hash}/{blob_digest.size_bytes}:splitBlob" };
485
+ }
486
+
487
+ // Splice a blob from chunks.
488
+ //
489
+ // This is the complementary operation to the
490
+ // [ContentAddressableStorage.SplitBlob][build.bazel.remote.execution.v2.ContentAddressableStorage.SplitBlob]
491
+ // function to handle the chunked upload of large blobs to save upload
492
+ // traffic.
493
+ //
494
+ // If a client needs to upload a large blob and is able to split a blob into
495
+ // chunks locally according to some content-defined chunking algorithm, it can
496
+ // first determine which parts of the blob are already available in the remote
497
+ // CAS and upload the missing chunks, and then use this API to instruct the
498
+ // server to splice the original blob from the remotely available blob chunks.
499
+ //
500
+ // Servers are free to implement this functionality, but they need to declare
501
+ // whether they support it or not by setting the
502
+ // [CacheCapabilities.blob_splice_support][build.bazel.remote.execution.v2.CacheCapabilities.blob_splice_support]
503
+ // field accordingly.
504
+ //
505
+ // Clients are free to use this functionality, it is just an optimization to
506
+ // reduce upload traffic, when uploading large blobs to the CAS. However,
507
+ // clients need to check first the server capabilities, whether blob splicing
508
+ // is supported by the server.
509
+ //
510
+ // Hints:
511
+ //
512
+ // * In order to ensure data consistency of the CAS, the server will verify
513
+ // the spliced result whether digest calculation results in the provided
514
+ // digest from the request and will reject a splice request if this check
515
+ // fails.
516
+ //
517
+ // * When blob splitting and splicing is used at the same time, the clients
518
+ // and the server should out-of-band agree upon a chunking algorithm used by
519
+ // all parties to benefit from each others chunk data and avoid unnecessary
520
+ // data duplication.
521
+ //
522
+ // Errors:
523
+ //
524
+ // * `NOT_FOUND`: At least one of the blob chunks is not present in the CAS.
525
+ // * `RESOURCE_EXHAUSTED`: There is insufficient disk quota to store the
526
+ // spliced blob.
527
+ // * `INVALID_ARGUMENT`: The digest of the spliced blob is different from the
528
+ // provided expected digest.
529
+ rpc SpliceBlob (SpliceBlobRequest ) returns (SpliceBlobResponse ) {
530
+ option (google.api.http ) = { post : "/v2/{instance_name=**}/blobs:spliceBlob" body: "*" };
531
+ }
433
532
}
434
533
435
534
// The Capabilities service may be used by remote execution clients to query
@@ -1837,6 +1936,91 @@ message GetTreeResponse {
1837
1936
string next_page_token = 2 ;
1838
1937
}
1839
1938
1939
+ // A request message for
1940
+ // [ContentAddressableStorage.SplitBlob][build.bazel.remote.execution.v2.ContentAddressableStorage.SplitBlob].
1941
+ message SplitBlobRequest {
1942
+ // The instance of the execution system to operate against. A server may
1943
+ // support multiple instances of the execution system (with their own workers,
1944
+ // storage, caches, etc.). The server MAY require use of this field to select
1945
+ // between them in an implementation-defined fashion, otherwise it can be
1946
+ // omitted.
1947
+ string instance_name = 1 ;
1948
+
1949
+ // The digest of the blob to be split.
1950
+ Digest blob_digest = 2 ;
1951
+
1952
+ // The digest function of the blob to be split.
1953
+ //
1954
+ // If the digest function used is one of MD5, MURMUR3, SHA1, SHA256,
1955
+ // SHA384, SHA512, or VSO, the client MAY leave this field unset. In
1956
+ // that case the server SHOULD infer the digest function using the
1957
+ // length of the blob digest hashes and the digest functions announced
1958
+ // in the server's capabilities.
1959
+ DigestFunction.Value digest_function = 4 ;
1960
+ }
1961
+
1962
+ // A response message for
1963
+ // [ContentAddressableStorage.SplitBlob][build.bazel.remote.execution.v2.ContentAddressableStorage.SplitBlob].
1964
+ message SplitBlobResponse {
1965
+ // The ordered list of digests of the chunks into which the blob was split.
1966
+ // The original blob is assembled by concatenating the chunk data according to
1967
+ // the order of the digests given by this list.
1968
+ repeated Digest chunk_digests = 1 ;
1969
+
1970
+ // The digest function of the chunks.
1971
+ //
1972
+ // If the digest function used is one of MD5, MURMUR3, SHA1, SHA256,
1973
+ // SHA384, SHA512, or VSO, the client MAY leave this field unset. In
1974
+ // that case the server SHOULD infer the digest function using the
1975
+ // length of the blob digest hashes and the digest functions announced
1976
+ // in the server's capabilities.
1977
+ DigestFunction.Value digest_function = 2 ;
1978
+ }
1979
+
1980
+ // A request message for
1981
+ // [ContentAddressableStorage.SpliceBlob][build.bazel.remote.execution.v2.ContentAddressableStorage.SpliceBlob].
1982
+ message SpliceBlobRequest {
1983
+ // The instance of the execution system to operate against. A server may
1984
+ // support multiple instances of the execution system (with their own workers,
1985
+ // storage, caches, etc.). The server MAY require use of this field to select
1986
+ // between them in an implementation-defined fashion, otherwise it can be
1987
+ // omitted.
1988
+ string instance_name = 1 ;
1989
+
1990
+ // Expected digest of the spliced blob.
1991
+ Digest blob_digest = 2 ;
1992
+
1993
+ // The ordered list of digests of the chunks which need to be concatenated to
1994
+ // assemble the original blob.
1995
+ repeated Digest chunk_digests = 3 ;
1996
+
1997
+ // The digest function of the blob to be spliced as well as of the chunks to
1998
+ // be concatenated.
1999
+ //
2000
+ // If the digest function used is one of MD5, MURMUR3, SHA1, SHA256,
2001
+ // SHA384, SHA512, or VSO, the client MAY leave this field unset. In
2002
+ // that case the server SHOULD infer the digest function using the
2003
+ // length of the blob digest hashes and the digest functions announced
2004
+ // in the server's capabilities.
2005
+ DigestFunction.Value digest_function = 4 ;
2006
+ }
2007
+
2008
+ // A response message for
2009
+ // [ContentAddressableStorage.SpliceBlob][build.bazel.remote.execution.v2.ContentAddressableStorage.SpliceBlob].
2010
+ message SpliceBlobResponse {
2011
+ // Computed digest of the spliced blob.
2012
+ Digest blob_digest = 1 ;
2013
+
2014
+ // The digest function of the spliced blob.
2015
+ //
2016
+ // If the digest function used is one of MD5, MURMUR3, SHA1, SHA256,
2017
+ // SHA384, SHA512, or VSO, the client MAY leave this field unset. In
2018
+ // that case the server SHOULD infer the digest function using the
2019
+ // length of the blob digest hashes and the digest functions announced
2020
+ // in the server's capabilities.
2021
+ DigestFunction.Value digest_function = 2 ;
2022
+ }
2023
+
1840
2024
// A request message for
1841
2025
// [Capabilities.GetCapabilities][build.bazel.remote.execution.v2.Capabilities.GetCapabilities].
1842
2026
message GetCapabilitiesRequest {
@@ -2056,6 +2240,20 @@ message CacheCapabilities {
2056
2240
// [BatchUpdateBlobs][build.bazel.remote.execution.v2.ContentAddressableStorage.BatchUpdateBlobs]
2057
2241
// requests.
2058
2242
repeated Compressor.Value supported_batch_update_compressors = 7 ;
2243
+
2244
+ // Whether blob splitting is supported for the particular server/instance. If
2245
+ // yes, the server/instance implements the specified behavior for blob
2246
+ // splitting and a meaningful result can be expected from the
2247
+ // [ContentAddressableStorage.SplitBlob][build.bazel.remote.execution.v2.ContentAddressableStorage.SplitBlob]
2248
+ // operation.
2249
+ bool blob_split_support = 9 ;
2250
+
2251
+ // Whether blob splicing is supported for the particular server/instance. If
2252
+ // yes, the server/instance implements the specified behavior for blob
2253
+ // splicing and a meaningful result can be expected from the
2254
+ // [ContentAddressableStorage.SpliceBlob][build.bazel.remote.execution.v2.ContentAddressableStorage.SpliceBlob]
2255
+ // operation.
2256
+ bool blob_splice_support = 10 ;
2059
2257
}
2060
2258
2061
2259
// Capabilities of the remote execution system.
0 commit comments