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  }