github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/blobs/service.go (about) 1 // Copyright 2019 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 /* 12 Package blobs contains a gRPC service to be used for remote file access. 13 14 It is used for bulk file reads and writes to files on any CockroachDB node. 15 Each node will run a blob service, which serves the file access for files on 16 that node. Each node will also have a blob client, which uses the nodedialer 17 to connect to another node's blob service, and access its files. The blob client 18 is the point of entry to this service and it supports the `BlobClient` interface, 19 which includes the following functionalities: 20 - ReadFile 21 - WriteFile 22 - List 23 - Delete 24 - Stat 25 */ 26 package blobs 27 28 import ( 29 "context" 30 31 "github.com/cockroachdb/cockroach/pkg/blobs/blobspb" 32 "github.com/cockroachdb/errors" 33 "google.golang.org/grpc/metadata" 34 ) 35 36 // Service implements the gRPC BlobService which exchanges bulk files between different nodes. 37 type Service struct { 38 localStorage *LocalStorage 39 } 40 41 var _ blobspb.BlobServer = &Service{} 42 43 // NewBlobService instantiates a blob service server. 44 func NewBlobService(externalIODir string) (*Service, error) { 45 localStorage, err := NewLocalStorage(externalIODir) 46 return &Service{localStorage: localStorage}, err 47 } 48 49 // GetStream implements the gRPC service. 50 func (s *Service) GetStream(req *blobspb.GetRequest, stream blobspb.Blob_GetStreamServer) error { 51 content, err := s.localStorage.ReadFile(req.Filename) 52 if err != nil { 53 return err 54 } 55 defer content.Close() 56 return streamContent(stream, content) 57 } 58 59 // PutStream implements the gRPC service. 60 func (s *Service) PutStream(stream blobspb.Blob_PutStreamServer) error { 61 md, ok := metadata.FromIncomingContext(stream.Context()) 62 if !ok { 63 return errors.New("could not fetch metadata") 64 } 65 filename := md.Get("filename") 66 if len(filename) < 1 || filename[0] == "" { 67 return errors.New("no filename in metadata") 68 } 69 reader := newPutStreamReader(stream) 70 defer reader.Close() 71 err := s.localStorage.WriteFile(filename[0], reader) 72 return err 73 } 74 75 // List implements the gRPC service. 76 func (s *Service) List( 77 ctx context.Context, req *blobspb.GlobRequest, 78 ) (*blobspb.GlobResponse, error) { 79 matches, err := s.localStorage.List(req.Pattern) 80 return &blobspb.GlobResponse{Files: matches}, err 81 } 82 83 // Delete implements the gRPC service. 84 func (s *Service) Delete( 85 ctx context.Context, req *blobspb.DeleteRequest, 86 ) (*blobspb.DeleteResponse, error) { 87 return &blobspb.DeleteResponse{}, s.localStorage.Delete(req.Filename) 88 } 89 90 // Stat implements the gRPC service. 91 func (s *Service) Stat(ctx context.Context, req *blobspb.StatRequest) (*blobspb.BlobStat, error) { 92 return s.localStorage.Stat(req.Filename) 93 }