|
- package ops2
-
- import (
- "fmt"
- "gitlink.org.cn/cloudream/common/pkgs/ioswitch/dag"
- "gitlink.org.cn/cloudream/common/pkgs/ioswitch/exec"
- log "gitlink.org.cn/cloudream/common/pkgs/logger"
- cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
- "gitlink.org.cn/cloudream/storage/common/pkgs/storage/cos"
- "gitlink.org.cn/cloudream/storage/common/pkgs/storage/mgr"
- "gitlink.org.cn/cloudream/storage/common/pkgs/storage/obs"
- "gitlink.org.cn/cloudream/storage/common/pkgs/storage/oss"
- "gitlink.org.cn/cloudream/storage/common/pkgs/storage/types"
- "io"
- "time"
- )
-
- func init() {
- exec.UseOp[*MultipartManage]()
- exec.UseOp[*MultipartUpload]()
- exec.UseVarValue[*InitUploadValue]()
- }
-
- type InitUploadValue struct {
- Key string `xml:"Key"` // Object name to upload
- UploadID string `xml:"UploadId"` // Generated UploadId
- }
-
- func (v *InitUploadValue) Clone() exec.VarValue {
- return &*v
- }
-
- type MultipartManage struct {
- Address cdssdk.StorageAddress `json:"address"`
- UploadArgs exec.VarID `json:"uploadArgs"`
- UploadOutput exec.VarID `json:"uploadOutput"`
- StorageID cdssdk.StorageID `json:"storageID"`
- }
-
- func (o *MultipartManage) Execute(ctx *exec.ExecContext, e *exec.Executor) error {
- manager, err := exec.GetValueByType[*mgr.Manager](ctx)
- if err != nil {
- return err
- }
-
- var client types.MultipartUploader
- switch addr := o.Address.(type) {
- case *cdssdk.OSSAddress:
- client = oss.NewMultiPartUpload(addr)
- case *cdssdk.OBSAddress:
- client = obs.NewMultiPartUpload(addr)
- case *cdssdk.COSAddress:
- client = cos.NewMultiPartUpload(addr)
- }
- defer client.Close()
-
- tempStore, err := manager.GetTempStore(o.StorageID)
- if err != nil {
- return err
- }
- objName := tempStore.CreateTemp()
-
- uploadID, err := client.InitiateMultipartUpload(objName)
- if err != nil {
- return err
- }
- e.PutVar(o.UploadArgs, &InitUploadValue{
- UploadID: uploadID,
- Key: objName,
- })
-
- parts, err := exec.BindVar[*UploadPartOutputValue](e, ctx.Context, o.UploadOutput)
- if err != nil {
- return err
- }
- err = client.CompleteMultipartUpload(uploadID, objName, parts.Parts)
- if err != nil {
- return err
- }
-
- return nil
- }
-
- func (o *MultipartManage) String() string {
- return "MultipartManage"
- }
-
- type MultipartManageNode struct {
- dag.NodeBase
- Address cdssdk.StorageAddress
- StorageID cdssdk.StorageID `json:"storageID"`
- }
-
- func (b *GraphNodeBuilder) NewMultipartManage(addr cdssdk.StorageAddress, storageID cdssdk.StorageID) *MultipartManageNode {
- node := &MultipartManageNode{
- Address: addr,
- StorageID: storageID,
- }
- b.AddNode(node)
- return node
- }
-
- func (t *MultipartManageNode) GenerateOp() (exec.Op, error) {
- return &MultipartManage{
- Address: t.Address,
- StorageID: t.StorageID,
- }, nil
- }
-
- type MultipartUpload struct {
- Address cdssdk.StorageAddress `json:"address"`
- UploadArgs exec.VarID `json:"uploadArgs"`
- UploadOutput exec.VarID `json:"uploadOutput"`
- PartNumbers []int `json:"partNumbers"`
- PartSize []int64 `json:"partSize"`
- Input exec.VarID `json:"input"`
- }
-
- type UploadPartOutputValue struct {
- Parts []*types.UploadPartOutput `json:"parts"`
- }
-
- func (v *UploadPartOutputValue) Clone() exec.VarValue {
- return &*v
- }
-
- func (o *MultipartUpload) Execute(ctx *exec.ExecContext, e *exec.Executor) error {
- initUploadResult, err := exec.BindVar[*InitUploadValue](e, ctx.Context, o.UploadArgs)
- if err == nil {
- return err
- }
-
- input, err := exec.BindVar[*exec.StreamValue](e, ctx.Context, o.Input)
- if err != nil {
- return err
- }
- defer input.Stream.Close()
-
- var client types.MultipartUploader
- switch addr := o.Address.(type) {
- case *cdssdk.OSSAddress:
- client = oss.NewMultiPartUpload(addr)
- }
-
- var parts UploadPartOutputValue
- for i := 0; i < len(o.PartNumbers); i++ {
- startTime := time.Now()
- uploadPart, err := client.UploadPart(initUploadResult.UploadID, initUploadResult.Key, o.PartSize[i], o.PartNumbers[i], io.LimitReader(input.Stream, o.PartSize[i]))
- log.Debugf("upload multipart spend time: %v", time.Since(startTime))
- if err != nil {
- return fmt.Errorf("failed to upload part: %w", err)
- }
- parts.Parts = append(parts.Parts, uploadPart)
- }
-
- e.PutVar(o.UploadOutput, &parts)
-
- return nil
- }
-
- func (o *MultipartUpload) String() string {
- return "MultipartUpload"
- }
-
- type MultipartUploadNode struct {
- dag.NodeBase
- Address cdssdk.StorageAddress
- PartNumbers []int `json:"partNumbers"`
- PartSize []int64 `json:"partSize"`
- }
-
- func (b *GraphNodeBuilder) NewMultipartUpload(addr cdssdk.StorageAddress, partNumbers []int, partSize []int64) *MultipartUploadNode {
- node := &MultipartUploadNode{
- Address: addr,
- PartNumbers: partNumbers,
- PartSize: partSize,
- }
- b.AddNode(node)
- return node
- }
-
- func (t MultipartUploadNode) GenerateOp() (exec.Op, error) {
- return &MultipartUpload{
- Address: t.Address,
- PartNumbers: t.PartNumbers,
- PartSize: t.PartSize,
- }, nil
- }
|