Skip to content
This repository has been archived by the owner on Oct 22, 2021. It is now read-only.

Implement GSP-93, GSP-97, GSP-109 and GSP-117 #31

Merged
merged 4 commits into from
Jun 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
620 changes: 300 additions & 320 deletions generated.go

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ go 1.14
require (
github.com/aliyun/aliyun-oss-go-sdk v2.1.8+incompatible
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
github.com/beyondstorage/go-integration-test/v4 v4.0.0
github.com/beyondstorage/go-storage/v4 v4.0.1-0.20210530044854-1c928ddbe52d
github.com/beyondstorage/go-endpoint v1.0.1
github.com/beyondstorage/go-integration-test/v4 v4.1.1
github.com/beyondstorage/go-storage/v4 v4.2.0
github.com/google/uuid v1.2.0
github.com/satori/go.uuid v1.2.0 // indirect
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
Expand Down
28 changes: 17 additions & 11 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,23 @@ github.com/aliyun/aliyun-oss-go-sdk v2.1.8+incompatible h1:hLUNPbx10wawWW7DeNExv
github.com/aliyun/aliyun-oss-go-sdk v2.1.8+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f h1:ZNv7On9kyUzm7fvRZumSyy/IUiSC7AzL0I1jKKtwooA=
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
github.com/beyondstorage/go-integration-test/v4 v4.0.0 h1:tdXQV9yxQ3Q6p9xfyQKzK3MEo9r9j9g3uT5+3sbVtnQ=
github.com/beyondstorage/go-integration-test/v4 v4.0.0/go.mod h1:26/JF4b0XxRN0pL4kihpnVNhbbw+QWvmmvgxfnFJDfA=
github.com/beyondstorage/go-storage/v4 v4.0.0/go.mod h1:oa2dYco+xplPj99WSBnYVw/xXvRkIKWSSVDQKNZ5Kz8=
github.com/beyondstorage/go-storage/v4 v4.0.1-0.20210530044854-1c928ddbe52d h1:s9t6VNNRDqmg+PXyXtVEsxIM7xZQIJOYlma28IpkbNQ=
github.com/beyondstorage/go-storage/v4 v4.0.1-0.20210530044854-1c928ddbe52d/go.mod h1:kXMu07IDZaKtxbqI1ufuhqo0FjYe0nH7zPCbBanln/Y=
github.com/beyondstorage/specs/go v0.0.0-20210521044836-3d41c1d9c97f/go.mod h1:f5VvmLHc/dNJwl+/yAv/TOHdev3phvuEswx8DIXiSQQ=
github.com/beyondstorage/specs/go v0.0.0-20210530044123-3ff75e192bc9 h1:YSiF27cAHlDZk9q+oaEHQbA8dH8XTvYxeTOoPzNCwOQ=
github.com/beyondstorage/specs/go v0.0.0-20210530044123-3ff75e192bc9/go.mod h1:f5VvmLHc/dNJwl+/yAv/TOHdev3phvuEswx8DIXiSQQ=
github.com/beyondstorage/go-endpoint v1.0.1 h1:F8x2dGLMu9je6g7zPbKoxCXDlug97K26SeCx7KEHgyg=
github.com/beyondstorage/go-endpoint v1.0.1/go.mod h1:P2hknaGrziOJJKySv/XnAiVw/d3v12/LZu2gSxEx4nM=
github.com/beyondstorage/go-integration-test/v4 v4.1.1 h1:9bSXKbr6hLb4+ZsmAhWE32fvqhyrpub4U4qgBGeth4A=
github.com/beyondstorage/go-integration-test/v4 v4.1.1/go.mod h1:ihtCaOJvaHGE0v+IhY6ZUF5NU1IND6xmdrJI9Lq/jhc=
github.com/beyondstorage/go-storage/v4 v4.2.0 h1:J0xqqy4qEQRtIS2zUWMA5wRXVHx/cxX5fHsU2ezA3+I=
github.com/beyondstorage/go-storage/v4 v4.2.0/go.mod h1:rUNzOXcikYk5w0ewvNsKbztg7ndQDyDvjDuP0bznSLU=
github.com/beyondstorage/specs/go v0.0.0-20210623065218-d1c2d7d81259 h1:mW9XpHLc6pdXBRnsha1VlqF0rNsB/Oc+8l+5UYngmRA=
github.com/beyondstorage/specs/go v0.0.0-20210623065218-d1c2d7d81259/go.mod h1:vF/Q0P1tCvhVAUrxg7i6NvrARRMQVTAuQdDNqpSzR1w=
github.com/dave/dst v0.26.2 h1:lnxLAKI3tx7MgLNVDirFCsDTlTG9nKTk7GcptKcWSwY=
github.com/dave/dst v0.26.2/go.mod h1:UMDJuIRPfyUCC78eFuB+SV/WI8oDeyFDvM/JR6NI3IU=
github.com/dave/gopackages v0.0.0-20170318123100-46e7023ec56e/go.mod h1:i00+b/gKdIDIxuLDFob7ustLAVqhsZRk2qVZrArELGQ=
github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
github.com/dave/kerr v0.0.0-20170318121727-bc25dd6abe8e/go.mod h1:qZqlPyPvfsDJt+3wHJ1EvSXDuVjFTK0j2p/ca+gtsb8=
github.com/dave/rebecca v0.9.1/go.mod h1:N6XYdMD/OKw3lkF3ywh8Z6wPGuwNFDNtWYEMFWEmXBA=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang/mock v1.5.0 h1:jlYHihg//f7RRwuPfptm04yp4s7O6Kw8EZiVYIGcH0g=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/google/pprof v0.0.0-20181127221834-b4f47329b966/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
Expand All @@ -37,19 +38,22 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pelletier/go-toml v1.9.1 h1:a6qW1EVNZWH9WGI6CsYdD8WAylkoXBS5yv0XHlh17Tc=
github.com/pelletier/go-toml v1.9.1/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ=
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
Expand All @@ -68,6 +72,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sys v0.0.0-20180903190138-2b024373dcd9/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
Expand Down
12 changes: 8 additions & 4 deletions service.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,24 @@ required = ["credential"]
optional = ["service_features", "default_service_pairs", "endpoint", "http_client_options"]

[namespace.storage]
implement = ["appender", "multiparter"]
features = ["virtual_dir"]
implement = ["appender", "direr", "multiparter"]

[namespace.storage.new]
required = ["name"]
optional = ["storage_features", "default_storage_pairs", "work_dir"]

[namespace.storage.op.create]
optional = ["multipart_id"]
optional = ["multipart_id", "object_mode"]

[namespace.storage.op.create_dir]
optional = ["storage_class"]

[namespace.storage.op.delete]
optional = ["multipart_id"]
optional = ["multipart_id", "object_mode"]

[namespace.storage.op.stat]
optional = ["multipart_id"]
optional = ["multipart_id", "object_mode"]

[namespace.storage.op.list]
optional = ["list_mode"]
Expand Down
102 changes: 92 additions & 10 deletions storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package oss

import (
"context"
"fmt"
"io"
"strconv"
"time"

"github.com/aliyun/aliyun-oss-go-sdk/oss"

ps "github.com/beyondstorage/go-storage/v4/pairs"
"github.com/beyondstorage/go-storage/v4/pkg/headers"
"github.com/beyondstorage/go-storage/v4/pkg/iowrap"
"github.com/beyondstorage/go-storage/v4/services"
Expand Down Expand Up @@ -46,16 +48,27 @@ func (s *Storage) completeMultipart(ctx context.Context, o *Object, parts []*Par
}

func (s *Storage) create(path string, opt pairStorageCreate) (o *Object) {
rp := s.getAbsPath(path)

// Handle create multipart object separately.
if opt.HasMultipartID {
o = s.newObject(true)
o.Mode = ModePart
o.SetMultipartID(opt.MultipartID)
} else {
o = s.newObject(false)
o.Mode = ModeRead
if opt.HasObjectMode && opt.ObjectMode.IsDir() {
if !s.features.VirtualDir {
return
}
rp += "/"
o = s.newObject(true)
o.Mode = ModeDir
} else {
o = s.newObject(false)
o.Mode = ModeRead
}
}
o.ID = s.getAbsPath(path)
o.ID = rp
o.Path = path
return o
}
Expand Down Expand Up @@ -94,6 +107,35 @@ func (s *Storage) createAppend(ctx context.Context, path string, opt pairStorage
return o, nil
}

func (s *Storage) createDir(ctx context.Context, path string, opt pairStorageCreateDir) (o *Object, err error) {
if !s.features.VirtualDir {
err = NewOperationNotImplementedError("create_dir")
return
}
rp := s.getAbsPath(path)

// Add `/` at the end of path to simulate directory.
// ref: https://help.aliyun.com/document_detail/31978.html#title-gkg-amg-aes
rp += "/"

options := make([]oss.Option, 0)
options = append(options, oss.ContentLength(0))
if opt.HasStorageClass {
options = append(options, oss.StorageClass(oss.StorageClassType(opt.StorageClass)))
}

err = s.bucket.PutObject(rp, nil, options...)
if err != nil {
return
}

o = s.newObject(true)
o.Path = path
o.ID = rp
o.Mode |= ModeDir
return
}

func (s *Storage) createMultipart(ctx context.Context, path string, opt pairStorageCreateMultipart) (o *Object, err error) {
rp := s.getAbsPath(path)

Expand Down Expand Up @@ -124,10 +166,6 @@ func (s *Storage) createMultipart(ctx context.Context, path string, opt pairStor
o.Path = path
o.Mode |= ModePart
o.SetMultipartID(output.UploadID)
// set multipart restriction
o.SetMultipartNumberMaximum(multipartNumberMaximum)
o.SetMultipartNumberMaximum(multipartSizeMaximum)
o.SetMultipartSizeMinimum(multipartSizeMinimum)

return o, nil
}
Expand All @@ -152,6 +190,15 @@ func (s *Storage) delete(ctx context.Context, path string, opt pairStorageDelete
return
}

if opt.HasObjectMode && opt.ObjectMode.IsDir() {
if !s.features.VirtualDir {
err = services.PairUnsupportedError{Pair: ps.WithObjectMode(opt.ObjectMode)}
return
}

rp += "/"
}

// OSS DeleteObject is idempotent, so we don't need to check NoSuchKey error.
//
// References
Expand Down Expand Up @@ -201,6 +248,14 @@ func (s *Storage) metadata(opt pairStorageMetadata) (meta *StorageMeta) {
meta = NewStorageMeta()
meta.Name = s.bucket.BucketName
meta.WorkDir = s.workDir
// set write restriction
meta.SetWriteSizeMaximum(writeSizeMaximum)
// set append restriction
meta.SetAppendTotalSizeMaximum(appendTotalSizeMaximum)
// set multipart restrictions
meta.SetMultipartNumberMaximum(multipartNumberMaximum)
meta.SetMultipartNumberMaximum(multipartSizeMaximum)
meta.SetMultipartSizeMinimum(multipartSizeMinimum)
return
}

Expand Down Expand Up @@ -390,6 +445,15 @@ func (s *Storage) stat(ctx context.Context, path string, opt pairStorageStat) (o
return o, nil
}

if opt.HasObjectMode && opt.ObjectMode.IsDir() {
if !s.features.VirtualDir {
err = services.PairUnsupportedError{Pair: ps.WithObjectMode(opt.ObjectMode)}
return
}

rp += "/"
}

output, err := s.bucket.GetObjectMeta(rp)
if err != nil {
return nil, err
Expand All @@ -398,7 +462,11 @@ func (s *Storage) stat(ctx context.Context, path string, opt pairStorageStat) (o
o = s.newObject(true)
o.ID = rp
o.Path = path
o.Mode |= ModeRead
if opt.HasObjectMode && opt.ObjectMode.IsDir() {
o.Mode |= ModeDir
} else {
o.Mode |= ModeRead
}

if v := output.Get(headers.ContentLength); v != "" {
size, err := strconv.ParseInt(v, 10, 64)
Expand Down Expand Up @@ -427,7 +495,7 @@ func (s *Storage) stat(ctx context.Context, path string, opt pairStorageStat) (o
o.SetContentType(v)
}

var sm ObjectMetadata
var sm ObjectSystemMetadata
if v := output.Get(storageClassHeader); v != "" {
sm.StorageClass = v
}
Expand All @@ -437,12 +505,17 @@ func (s *Storage) stat(ctx context.Context, path string, opt pairStorageStat) (o
if v := output.Get(serverSideEncryptionKeyIdHeader); v != "" {
sm.ServerSideEncryptionKeyID = v
}
o.SetServiceMetadata(sm)
o.SetSystemMetadata(sm)

return o, nil
}

func (s *Storage) write(ctx context.Context, path string, r io.Reader, size int64, opt pairStorageWrite) (n int64, err error) {
if size > writeSizeMaximum {
err = fmt.Errorf("size limit exceeded: %w", services.ErrRestrictionDissatisfied)
return
}

if opt.HasIoCallback {
r = iowrap.CallbackReader(r, opt.IoCallback)
}
Expand Down Expand Up @@ -500,6 +573,15 @@ func (s *Storage) writeAppend(ctx context.Context, o *Object, r io.Reader, size
}

func (s *Storage) writeMultipart(ctx context.Context, o *Object, r io.Reader, size int64, index int, opt pairStorageWriteMultipart) (n int64, part *Part, err error) {
if index < 0 || index >= multipartNumberMaximum {
err = fmt.Errorf("multipart number limit exceeded: %w", services.ErrRestrictionDissatisfied)
return
}
if size > multipartSizeMaximum {
err = fmt.Errorf("size limit exceeded: %w", services.ErrRestrictionDissatisfied)
return
}

imur := oss.InitiateMultipartUploadResult{
Bucket: s.bucket.BucketName,
Key: o.ID,
Expand Down
7 changes: 7 additions & 0 deletions tests/storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,10 @@ func TestMultiparter(t *testing.T) {
}
tests.TestMultiparter(t, setupTest(t))
}

func TestDirer(t *testing.T) {
if os.Getenv("STORAGE_OSS_INTEGRATION_TEST") != "on" {
t.Skipf("STORAGE_OSS_INTEGRATION_TEST is not 'on', skipped")
}
tests.TestDirer(t, setupTest(t))
}
3 changes: 3 additions & 0 deletions tests/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ func setupTest(t *testing.T) types.Storager {
ps.WithName(os.Getenv("STORAGE_OSS_NAME")),
ps.WithEndpoint(os.Getenv("STORAGE_OSS_ENDPOINT")),
ps.WithWorkDir("/"+uuid.New().String()+"/"),
oss.WithStorageFeatures(oss.StorageFeatures{
VirtualDir: true,
}),
)
if err != nil {
t.Errorf("new storager: %v", err)
Expand Down
28 changes: 24 additions & 4 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import (

"github.com/aliyun/aliyun-oss-go-sdk/oss"

"github.com/beyondstorage/go-endpoint"
ps "github.com/beyondstorage/go-storage/v4/pairs"
"github.com/beyondstorage/go-storage/v4/pkg/credential"
"github.com/beyondstorage/go-storage/v4/pkg/endpoint"
"github.com/beyondstorage/go-storage/v4/pkg/httpclient"
"github.com/beyondstorage/go-storage/v4/services"
typ "github.com/beyondstorage/go-storage/v4/types"
Expand Down Expand Up @@ -42,6 +42,7 @@ type Storage struct {
typ.UnimplementedStorager
typ.UnimplementedAppender
typ.UnimplementedMultiparter
typ.UnimplementedDirer
}

// String implements Storager.String
Expand Down Expand Up @@ -96,12 +97,22 @@ func newServicer(pairs ...typ.Pair) (srv *Service, err error) {
return nil, err
}

var url string
switch ep.Protocol() {
case endpoint.ProtocolHTTP:
url, _, _ = ep.HTTP()
case endpoint.ProtocolHTTPS:
url, _, _ = ep.HTTPS()
default:
return nil, services.PairUnsupportedError{Pair: ps.WithEndpoint(opt.Endpoint)}
}

var copts []oss.ClientOption
if opt.HasHTTPClientOptions {
copts = append(copts, oss.HTTPClient(httpclient.New(opt.HTTPClientOptions)))
}

srv.service, err = oss.New(ep.String(), ak, sk, copts...)
srv.service, err = oss.New(url, ak, sk, copts...)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -259,11 +270,11 @@ func (s *Storage) formatFileObject(v oss.ObjectProperties) (o *typ.Object, err e
o.SetEtag(v.ETag)
}

var sm ObjectMetadata
var sm ObjectSystemMetadata
if value := v.Type; value != "" {
sm.StorageClass = value
}
o.SetServiceMetadata(sm)
o.SetSystemMetadata(sm)

return
}
Expand Down Expand Up @@ -311,3 +322,12 @@ const (
// multipartSizeMinimum is the minimum size for each part, 100KB.
multipartSizeMinimum = 100 * 1024
)

const (
// writeSizeMaximum is the maximum size for each object with a single PUT operation, 5GB.
// ref: https://help.aliyun.com/document_detail/31978.html#title-gkg-amg-aes
writeSizeMaximum = 5 * 1024 * 1024 * 1024
// appendSizeMaximum is the total maximum size for an append object, 5GB.
// ref: https://help.aliyun.com/document_detail/31981.html?spm=a2c4g.11186623.6.1684.479a3ea7S8dRgB#title-22f-5c3-0sv
appendTotalSizeMaximum = 5 * 1024 * 1024 * 1024
)