Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ use_repo(
"com_github_aws_aws_sdk_go_v2_service_sts",
"com_github_bazelbuild_buildtools",
"com_github_bazelbuild_remote_apis",
"com_github_buildbarn_go_cdc",
"com_github_buildbarn_go_sha256tree",
"com_github_fxtlabs_primes",
"com_github_go_jose_go_jose_v3",
Expand Down
31 changes: 27 additions & 4 deletions cmd/bb_storage/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,27 @@ func main() {
contentAddressableStorage = authorizedBackend
}

// Chunk List Storage (CLS).
var chunkListStorage blobstore.BlobAccess
if configuration.ChunkListStorage != nil {
info, authorizedBackend, allAuthorizers, err := newScannableBlobAccess(
dependenciesGroup,
configuration.ChunkListStorage,
blobstore_configuration.NewCLSBlobAccessCreator(
contentAddressableStorageInfo,
grpcClientFactory,
int(configuration.MaximumMessageSizeBytes),
),
grpcClientFactory,
)
if err != nil {
return util.StatusWrap(err, "Failed to create Chunk Map")
}
cacheCapabilitiesProviders = append(cacheCapabilitiesProviders, info.BlobAccess)
cacheCapabilitiesAuthorizers = append(cacheCapabilitiesAuthorizers, allAuthorizers...)
chunkListStorage = authorizedBackend

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would have imagined that this added a capabilities provider to cacheCapabilitiesAuthorizers. Why doesn't t do that?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I don't need to add it because Capabilities are propagated from the CAS and not from the CLS. Do you want us to propagate the parameters from the CLS instead?

}

// Action Cache (AC).
var actionCache blobstore.BlobAccess
if configuration.ActionCache != nil {
Expand Down Expand Up @@ -193,12 +214,14 @@ func main() {
configuration.GrpcServers,
func(s grpc.ServiceRegistrar) {
if contentAddressableStorage != nil {
contentAddressableStorageServer := grpcservers.NewContentAddressableStorageServer(
contentAddressableStorage,
chunkListStorage,
configuration.MaximumMessageSizeBytes,
)
remoteexecution.RegisterContentAddressableStorageServer(
s,
grpcservers.NewContentAddressableStorageServer(
contentAddressableStorage,
configuration.MaximumMessageSizeBytes,
),
contentAddressableStorageServer,
)
bytestream.RegisterByteStreamServer(
s,
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ require (
github.com/bazelbuild/buildtools v0.0.0-20260527135131-3b47c424ecf5
github.com/bazelbuild/remote-apis v0.0.0-20260331222004-becdd8f9ff81
github.com/bazelbuild/rules_go v0.60.0
github.com/buildbarn/go-cdc v0.0.9
github.com/buildbarn/go-sha256tree v0.0.0-20250310211320-0f70f20e855b
github.com/fxtlabs/primes v0.0.0-20150821004651-dad82d10a449
github.com/go-jose/go-jose/v3 v3.0.5
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ github.com/bazelbuild/rules_go v0.60.0/go.mod h1:CYcohJVxs4n7eftbC39GCqaEJm3E1EM
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/buildbarn/go-cdc v0.0.9 h1:bWfgn92ed8Oo2zZKJdMAfB0APGz7Q8zvnqUn3hPuihM=
github.com/buildbarn/go-cdc v0.0.9/go.mod h1:KUMqSMvoRlby3uak9aKIvgz3KgNqwm2CMUoVX1EDr8k=
github.com/buildbarn/go-sha256tree v0.0.0-20250310211320-0f70f20e855b h1:IKUxixGBm9UxobU7c248z0BF0ojG19uoSLz8MFZM/KA=
github.com/buildbarn/go-sha256tree v0.0.0-20250310211320-0f70f20e855b/go.mod h1:e7g3/yWApcg+PpDqd4eQEEV8pexQmfCgK3frP+1Wuvk=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
Expand Down
1 change: 1 addition & 0 deletions pkg/blobstore/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ go_library(
"authorizing_blob_access.go",
"blob_access.go",
"cas_read_buffer_factory.go",
"cls_read_buffer_factory.go",
"deadline_enforcing_blob_access.go",
"demultiplexing_blob_access.go",
"empty_blob_injecting_blob_access.go",
Expand Down
43 changes: 43 additions & 0 deletions pkg/blobstore/chunklistvalidating/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
load("@rules_go//go:def.bzl", "go_library", "go_test")

go_library(
name = "chunklistvalidating",
srcs = [
"chunk_concatenating_reader.go",
"chunk_list_validating_blob_access.go",
"chunker.go",
"reader_chunker.go",
],
importpath = "github.com/buildbarn/bb-storage/pkg/blobstore/chunklistvalidating",
visibility = ["//visibility:public"],
deps = [
"//pkg/blobstore",
"//pkg/blobstore/buffer",
"//pkg/digest",
"//pkg/util",
"@bazel_remote_apis//build/bazel/remote/execution/v2:remote_execution_go_proto",
"@com_github_buildbarn_go_cdc//:go-cdc",
"@org_golang_google_grpc//codes",
"@org_golang_google_grpc//status",
"@org_golang_x_sync//errgroup",
],
)

go_test(
name = "chunklistvalidating_test",
srcs = [
"chunk_list_validating_blob_access_test.go",
"fake_blob_access_test.go",
"reader_chunker_test.go",
],
deps = [
":chunklistvalidating",
"//pkg/blobstore",
"//pkg/blobstore/buffer",
"//pkg/digest",
"@bazel_remote_apis//build/bazel/remote/execution/v2:remote_execution_go_proto",
"@com_github_stretchr_testify//require",
"@org_golang_google_grpc//codes",
"@org_golang_google_grpc//status",
],
)
68 changes: 68 additions & 0 deletions pkg/blobstore/chunklistvalidating/chunk_concatenating_reader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package chunklistvalidating

import (
"context"
"io"

"github.com/buildbarn/bb-storage/pkg/blobstore"
"github.com/buildbarn/bb-storage/pkg/digest"
"github.com/buildbarn/bb-storage/pkg/util"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

// chunkConcatenatingReader is a helper utility that implements the
// io.ReadCloser api over a series of digest.Digest objectes fetched
// sequentially from the CAS.
type chunkConcatenatingReader struct {
ctx context.Context
contentAddressableStorage blobstore.BlobAccess
chunkDigests []digest.Digest
currentIndex int
currentReader io.ReadCloser
closed bool
}

func (r *chunkConcatenatingReader) Read(p []byte) (int, error) {
if r.closed {
return 0, status.Error(codes.Internal, "Reader is already closed")
}
for {
if r.currentReader == nil {
if r.currentIndex >= len(r.chunkDigests) {
return 0, io.EOF
}
chunkDigest := r.chunkDigests[r.currentIndex]
b := r.contentAddressableStorage.Get(r.ctx, chunkDigest)
r.currentReader = b.ToReader()
r.currentIndex++
}

n, err := r.currentReader.Read(p)
if n > 0 {
return n, nil
}
if err == io.EOF {
err = r.currentReader.Close()
r.currentReader = nil
if err != nil {
return 0, err
}
continue
}
if err != nil {
_ = r.currentReader.Close()
r.currentReader = nil
return 0, util.StatusWrap(err, "Failed to read chunk")
}
}
}

func (r *chunkConcatenatingReader) Close() (err error) {
r.closed = true
if r.currentReader != nil {
err = r.currentReader.Close()
r.currentReader = nil
}
return err
}
Loading