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 }