github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/pkg/storage/tsdb/bucketindex/storage.go (about)

     1  package bucketindex
     2  
     3  import (
     4  	"bytes"
     5  	"compress/gzip"
     6  	"context"
     7  	"encoding/json"
     8  
     9  	"github.com/go-kit/log"
    10  	"github.com/grafana/dskit/runutil"
    11  	"github.com/pkg/errors"
    12  	"github.com/thanos-io/thanos/pkg/objstore"
    13  
    14  	"github.com/cortexproject/cortex/pkg/storage/bucket"
    15  )
    16  
    17  var (
    18  	ErrIndexNotFound  = errors.New("bucket index not found")
    19  	ErrIndexCorrupted = errors.New("bucket index corrupted")
    20  )
    21  
    22  // ReadIndex reads, parses and returns a bucket index from the bucket.
    23  func ReadIndex(ctx context.Context, bkt objstore.Bucket, userID string, cfgProvider bucket.TenantConfigProvider, logger log.Logger) (*Index, error) {
    24  	userBkt := bucket.NewUserBucketClient(userID, bkt, cfgProvider)
    25  
    26  	// Get the bucket index.
    27  	reader, err := userBkt.WithExpectedErrs(userBkt.IsObjNotFoundErr).Get(ctx, IndexCompressedFilename)
    28  	if err != nil {
    29  		if userBkt.IsObjNotFoundErr(err) {
    30  			return nil, ErrIndexNotFound
    31  		}
    32  		return nil, errors.Wrap(err, "read bucket index")
    33  	}
    34  	defer runutil.CloseWithLogOnErr(logger, reader, "close bucket index reader")
    35  
    36  	// Read all the content.
    37  	gzipReader, err := gzip.NewReader(reader)
    38  	if err != nil {
    39  		return nil, ErrIndexCorrupted
    40  	}
    41  	defer runutil.CloseWithLogOnErr(logger, gzipReader, "close bucket index gzip reader")
    42  
    43  	// Deserialize it.
    44  	index := &Index{}
    45  	d := json.NewDecoder(gzipReader)
    46  	if err := d.Decode(index); err != nil {
    47  		return nil, ErrIndexCorrupted
    48  	}
    49  
    50  	return index, nil
    51  }
    52  
    53  // WriteIndex uploads the provided index to the storage.
    54  func WriteIndex(ctx context.Context, bkt objstore.Bucket, userID string, cfgProvider bucket.TenantConfigProvider, idx *Index) error {
    55  	bkt = bucket.NewUserBucketClient(userID, bkt, cfgProvider)
    56  
    57  	// Marshal the index.
    58  	content, err := json.Marshal(idx)
    59  	if err != nil {
    60  		return errors.Wrap(err, "marshal bucket index")
    61  	}
    62  
    63  	// Compress it.
    64  	var gzipContent bytes.Buffer
    65  	gzip := gzip.NewWriter(&gzipContent)
    66  	gzip.Name = IndexFilename
    67  
    68  	if _, err := gzip.Write(content); err != nil {
    69  		return errors.Wrap(err, "gzip bucket index")
    70  	}
    71  	if err := gzip.Close(); err != nil {
    72  		return errors.Wrap(err, "close gzip bucket index")
    73  	}
    74  
    75  	// Upload the index to the storage.
    76  	if err := bkt.Upload(ctx, IndexCompressedFilename, &gzipContent); err != nil {
    77  		return errors.Wrap(err, "upload bucket index")
    78  	}
    79  
    80  	return nil
    81  }
    82  
    83  // DeleteIndex deletes the bucket index from the storage. No error is returned if the index
    84  // does not exist.
    85  func DeleteIndex(ctx context.Context, bkt objstore.Bucket, userID string, cfgProvider bucket.TenantConfigProvider) error {
    86  	bkt = bucket.NewUserBucketClient(userID, bkt, cfgProvider)
    87  
    88  	err := bkt.Delete(ctx, IndexCompressedFilename)
    89  	if err != nil && !bkt.IsObjNotFoundErr(err) {
    90  		return errors.Wrap(err, "delete bucket index")
    91  	}
    92  	return nil
    93  }