github.com/grafana/pyroscope@v1.18.0/pkg/storegateway/block.go (about)

     1  package storegateway
     2  
     3  import (
     4  	"context"
     5  	"os"
     6  	"path"
     7  	"path/filepath"
     8  
     9  	"github.com/go-kit/log"
    10  	"github.com/pkg/errors"
    11  
    12  	"github.com/grafana/pyroscope/pkg/phlaredb"
    13  	"github.com/grafana/pyroscope/pkg/phlaredb/block"
    14  )
    15  
    16  type BlockCloser interface {
    17  	phlaredb.Querier
    18  	Close() error
    19  }
    20  
    21  type Block struct {
    22  	BlockCloser
    23  	meta   *block.Meta
    24  	logger log.Logger
    25  }
    26  
    27  func (bs *BucketStore) createBlock(ctx context.Context, meta *block.Meta) (*Block, error) {
    28  	blockLocalPath := bs.localPath(meta.ULID.String())
    29  	// add the dir if it doesn't exist
    30  	if _, err := os.Stat(blockLocalPath); errors.Is(err, os.ErrNotExist) {
    31  		if err := os.MkdirAll(blockLocalPath, 0o750); err != nil {
    32  			return nil, errors.Wrap(err, "create dir")
    33  		}
    34  	}
    35  	metaPath := filepath.Join(blockLocalPath, block.MetaFilename)
    36  	var outMeta *block.Meta
    37  	if _, err := os.Stat(metaPath); errors.Is(err, os.ErrNotExist) {
    38  		// fetch the meta from the bucket
    39  		r, err := bs.bucket.Get(ctx, path.Join(meta.ULID.String(), block.MetaFilename))
    40  		if err != nil {
    41  			return nil, errors.Wrap(err, "get meta")
    42  		}
    43  		meta, err := block.Read(r)
    44  		if err != nil {
    45  			return nil, errors.Wrap(err, "read meta")
    46  		}
    47  		// add meta.json if it does not exist
    48  		if _, err := meta.WriteToFile(bs.logger, blockLocalPath); err != nil {
    49  			return nil, errors.Wrap(err, "write meta.json")
    50  		}
    51  		outMeta = meta.Clone()
    52  	} else {
    53  		// read meta.json if it exists and validate it
    54  		diskMeta, _, err := block.MetaFromDir(blockLocalPath)
    55  		if err != nil {
    56  			return nil, errors.Wrap(err, "read meta.json")
    57  		}
    58  
    59  		if meta.ULID.String() != diskMeta.ULID.String() {
    60  			return nil, errors.Wrap(err, "meta.json does not match")
    61  		}
    62  		outMeta = diskMeta.Clone()
    63  
    64  	}
    65  
    66  	if outMeta.Version == 0 || len(outMeta.Files) == 0 {
    67  		return nil, errors.New("meta.json is empty")
    68  	}
    69  
    70  	return &Block{
    71  		meta:        outMeta,
    72  		logger:      bs.logger,
    73  		BlockCloser: phlaredb.NewSingleBlockQuerierFromMeta(ctx, bs.bucket, outMeta),
    74  	}, nil
    75  }