storj.io/uplink@v1.13.0/private/metaclient/client_copy.go (about)

     1  // Copyright (C) 2022 Storj Labs, Inc.
     2  // See LICENSE for copying information.
     3  
     4  package metaclient
     5  
     6  import (
     7  	"context"
     8  
     9  	"storj.io/common/pb"
    10  	"storj.io/common/storj"
    11  )
    12  
    13  // BeginCopyObjectParams parameters for BeginCopyObject method.
    14  type BeginCopyObjectParams struct {
    15  	Bucket                []byte
    16  	EncryptedObjectKey    []byte
    17  	Version               []byte
    18  	NewBucket             []byte
    19  	NewEncryptedObjectKey []byte
    20  }
    21  
    22  // BeginCopyObjectResponse response for BeginCopyObjectResponse request.
    23  type BeginCopyObjectResponse struct {
    24  	StreamID                  storj.StreamID
    25  	EncryptedMetadataKeyNonce storj.Nonce
    26  	EncryptedMetadataKey      []byte
    27  	SegmentKeys               []EncryptedKeyAndNonce
    28  }
    29  
    30  func (params *BeginCopyObjectParams) toRequest(header *pb.RequestHeader) *pb.ObjectBeginCopyRequest {
    31  	return &pb.ObjectBeginCopyRequest{
    32  		Header:                header,
    33  		Bucket:                params.Bucket,
    34  		EncryptedObjectKey:    params.EncryptedObjectKey,
    35  		ObjectVersion:         params.Version,
    36  		NewBucket:             params.NewBucket,
    37  		NewEncryptedObjectKey: params.NewEncryptedObjectKey,
    38  	}
    39  }
    40  
    41  // BatchItem returns single item for batch request.
    42  func (params *BeginCopyObjectParams) BatchItem() *pb.BatchRequestItem {
    43  	return &pb.BatchRequestItem{
    44  		Request: &pb.BatchRequestItem_ObjectBeginCopy{
    45  			ObjectBeginCopy: params.toRequest(nil),
    46  		},
    47  	}
    48  }
    49  
    50  func newBeginCopyObjectResponse(response *pb.ObjectBeginCopyResponse) BeginCopyObjectResponse {
    51  	keys := make([]EncryptedKeyAndNonce, len(response.SegmentKeys))
    52  	for i, key := range response.SegmentKeys {
    53  		keys[i] = EncryptedKeyAndNonce{
    54  			EncryptedKeyNonce: key.EncryptedKeyNonce,
    55  			EncryptedKey:      key.EncryptedKey,
    56  		}
    57  		if key.Position != nil {
    58  			keys[i].Position = SegmentPosition{
    59  				PartNumber: key.Position.PartNumber,
    60  				Index:      key.Position.Index,
    61  			}
    62  		}
    63  	}
    64  
    65  	return BeginCopyObjectResponse{
    66  		StreamID:                  response.StreamId,
    67  		EncryptedMetadataKeyNonce: response.EncryptedMetadataKeyNonce,
    68  		EncryptedMetadataKey:      response.EncryptedMetadataKey,
    69  		SegmentKeys:               keys,
    70  	}
    71  }
    72  
    73  // BeginCopyObject requests data needed to copy an object from one key to another.
    74  func (client *Client) BeginCopyObject(ctx context.Context, params BeginCopyObjectParams) (_ BeginCopyObjectResponse, err error) {
    75  	defer mon.Task()(&ctx)(&err)
    76  	var response *pb.ObjectBeginCopyResponse
    77  	err = WithRetry(ctx, func(ctx context.Context) error {
    78  		response, err = client.client.BeginCopyObject(ctx, params.toRequest(client.header()))
    79  		return err
    80  	})
    81  	if err != nil {
    82  		return BeginCopyObjectResponse{}, Error.Wrap(err)
    83  	}
    84  	return newBeginCopyObjectResponse(response), nil
    85  }
    86  
    87  // FinishCopyObjectParams parameters for FinishCopyObject method.
    88  type FinishCopyObjectParams struct {
    89  	StreamID                     storj.StreamID
    90  	NewBucket                    []byte
    91  	NewEncryptedObjectKey        []byte
    92  	NewEncryptedMetadataKeyNonce storj.Nonce
    93  	NewEncryptedMetadataKey      []byte
    94  	NewSegmentKeys               []EncryptedKeyAndNonce
    95  }
    96  
    97  func (params *FinishCopyObjectParams) toRequest(header *pb.RequestHeader) *pb.ObjectFinishCopyRequest {
    98  	keys := make([]*pb.EncryptedKeyAndNonce, len(params.NewSegmentKeys))
    99  	for i, keyAndNonce := range params.NewSegmentKeys {
   100  		keys[i] = &pb.EncryptedKeyAndNonce{
   101  			Position: &pb.SegmentPosition{
   102  				PartNumber: keyAndNonce.Position.PartNumber,
   103  				Index:      keyAndNonce.Position.Index,
   104  			},
   105  			EncryptedKeyNonce: keyAndNonce.EncryptedKeyNonce,
   106  			EncryptedKey:      keyAndNonce.EncryptedKey,
   107  		}
   108  	}
   109  	return &pb.ObjectFinishCopyRequest{
   110  		Header:                       header,
   111  		StreamId:                     params.StreamID,
   112  		NewBucket:                    params.NewBucket,
   113  		NewEncryptedObjectKey:        params.NewEncryptedObjectKey,
   114  		NewEncryptedMetadataKeyNonce: params.NewEncryptedMetadataKeyNonce,
   115  		NewEncryptedMetadataKey:      params.NewEncryptedMetadataKey,
   116  		NewSegmentKeys:               keys,
   117  	}
   118  }
   119  
   120  // BatchItem returns single item for batch request.
   121  func (params *FinishCopyObjectParams) BatchItem() *pb.BatchRequestItem {
   122  	return &pb.BatchRequestItem{
   123  		Request: &pb.BatchRequestItem_ObjectFinishCopy{
   124  			ObjectFinishCopy: params.toRequest(nil),
   125  		},
   126  	}
   127  }
   128  
   129  // FinishCopyObjectResponse response for FinishCopyObjectResponse request.
   130  type FinishCopyObjectResponse struct {
   131  	Info RawObjectItem
   132  }
   133  
   134  // FinishCopyObject finishes process of copying object from one key to another.
   135  func (client *Client) FinishCopyObject(ctx context.Context, params FinishCopyObjectParams) (_ FinishCopyObjectResponse, err error) {
   136  	defer mon.Task()(&ctx)(&err)
   137  	var response *pb.ObjectFinishCopyResponse
   138  	err = WithRetry(ctx, func(ctx context.Context) error {
   139  		response, err = client.client.FinishCopyObject(ctx, params.toRequest(client.header()))
   140  		return err
   141  	})
   142  	if err != nil {
   143  		return FinishCopyObjectResponse{}, Error.Wrap(err)
   144  	}
   145  
   146  	return newFinishCopyObjectResponse(response), nil
   147  }
   148  
   149  func newFinishCopyObjectResponse(response *pb.ObjectFinishCopyResponse) FinishCopyObjectResponse {
   150  	info := newObjectInfo(response.Object)
   151  
   152  	return FinishCopyObjectResponse{Info: info}
   153  }