vendor: update all dependencies to latest versions

This commit is contained in:
Nick Craig-Wood
2017-09-30 15:27:27 +01:00
parent 911d121bb9
commit b017fcfe9a
3048 changed files with 537055 additions and 189679 deletions
+106
View File
@@ -0,0 +1,106 @@
package upload
import (
"bytes"
"io"
"errors"
)
const (
// QingStor has a max upload parts limit to 10000.
maxUploadParts = 10000
// We read from stream for read 1024B.
segmentSize = 1024
)
// chunk provides a struct to read file
type chunk struct {
fd io.Reader
cur int64
size int64
partSize int
}
// newChunk creates a FileChunk struct
func newChunk(fd io.Reader, partSize int) *chunk {
f := &chunk{
fd: fd,
partSize: partSize,
}
f.initSize()
return f
}
// nextPart reads the next part of the file
func (f *chunk) nextPart() (io.ReadSeeker, error) {
type readerAtSeeker interface {
io.ReaderAt
io.ReadSeeker
}
switch r := f.fd.(type) {
case readerAtSeeker:
var sectionSize int64
var err error
leftSize := f.size - f.cur
if leftSize >= int64(f.partSize) {
sectionSize = int64(f.partSize)
} else if leftSize > 0 {
sectionSize = f.size - f.cur
} else {
err = io.EOF
}
seekReader := io.NewSectionReader(r, f.cur, sectionSize)
f.cur += sectionSize
return seekReader, err
case io.Reader:
buf := make([]byte, segmentSize)
var n, lenBuf int
var err error
var chunk []byte
for {
n, _ = r.Read(buf)
if n == 0 {
if lenBuf == 0 {
err = io.EOF
}
break
}
lenBuf = lenBuf + n
chunk = append(chunk, buf...)
if lenBuf == f.partSize {
break
}
}
partBody := bytes.NewReader(chunk[:lenBuf])
return partBody, err
default:
return nil, errors.New("file does not support read")
}
}
// initSize tries to detect the total stream size, setting u.size. If
// the size is not known, size is set to -1.
func (f *chunk) initSize() {
f.size = -1
switch r := f.fd.(type) {
case io.Seeker:
pos, _ := r.Seek(0, 1)
defer r.Seek(pos, 0)
n, err := r.Seek(0, 2)
if err != nil {
return
}
f.size = n
// Try to adjust partSize if it is too small and account for
// integer division truncation.
if f.size/int64(f.partSize) >= int64(maxUploadParts) {
// Add one to the part size to account for remainders
// during the size calculation. e.g odd number of bytes.
f.partSize = int(f.size/int64(maxUploadParts)) + 1
}
}
}
+52
View File
@@ -0,0 +1,52 @@
package upload
import (
"fmt"
"os"
"os/exec"
"testing"
)
var partSize = 5 * 1024
//Test_newFileChunk is the test function for New
func Test_newFileChunk(t *testing.T) {
setup()
fd, _ := os.Open("test_file")
defer fd.Close()
fr := newChunk(fd, partSize)
if fr.size != 512000 {
t.Fatalf("expected 512000, got %d", fr.size)
}
tearDown()
}
// Test_nextPart is the test function for nextSeekablePart
func Test_nextPart(t *testing.T) {
setup()
fd, _ := os.Open("test_file")
defer fd.Close()
fr := newChunk(fd, partSize)
partBody, err := fr.nextPart()
if err != nil {
fmt.Println(err)
}
temp := make([]byte, 6000)
n, _ := partBody.Read(temp)
if n != partSize {
t.Fatalf("expected 5120, got %d", len(temp))
}
tearDown()
}
func setup() {
exec.Command("dd", "if=/dev/zero", "of=test_file", "bs=1024", "count=500").Output()
}
func tearDown() {
exec.Command("rm", "", "test_file").Output()
}
+110
View File
@@ -0,0 +1,110 @@
package upload
import (
"errors"
"github.com/yunify/qingstor-sdk-go/logger"
"github.com/yunify/qingstor-sdk-go/service"
"io"
)
// Uploader struct provides a struct to upload
type Uploader struct {
bucket *service.Bucket
partSize int
}
const smallestPartSize int = 1024 * 1024 * 4
//Init creates a uploader struct
func Init(bucket *service.Bucket, partSize int) *Uploader {
return &Uploader{
bucket: bucket,
partSize: partSize,
}
}
// Upload uploads multi parts of large object
func (u *Uploader) Upload(fd io.Reader, objectKey string) error {
if u.partSize < smallestPartSize {
logger.Errorf("Part size error")
return errors.New("the part size is too small")
}
uploadID, err := u.init(objectKey)
if err != nil {
logger.Errorf("Init multipart upload error" + err.Error())
return err
}
partNumbers, err := u.upload(fd, uploadID, objectKey)
if err != nil {
logger.Errorf("Upload multipart error" + err.Error())
return err
}
err = u.complete(objectKey, uploadID, partNumbers)
if err != nil {
logger.Errorf("Complete upload error" + err.Error())
return err
}
return nil
}
func (u *Uploader) init(objectKey string) (*string, error) {
output, err := u.bucket.InitiateMultipartUpload(
objectKey,
&service.InitiateMultipartUploadInput{},
)
if err != nil {
return nil, err
}
return output.UploadID, nil
}
func (u *Uploader) upload(fd io.Reader, uploadID *string, objectKey string) ([]*service.ObjectPartType, error) {
var partCnt int
partNumbers := []*service.ObjectPartType{}
fileReader := newChunk(fd, u.partSize)
for {
partBody, err := fileReader.nextPart()
if err == io.EOF {
break
}
if err != nil {
logger.Errorf("Get next part failed for %v", err)
return nil, err
}
_, err = u.bucket.UploadMultipart(
objectKey,
&service.UploadMultipartInput{
UploadID: uploadID,
PartNumber: &partCnt,
Body: partBody,
},
)
if err != nil {
logger.Errorf("Upload multipart failed for %v", err)
return nil, err
}
partNumbers = append(partNumbers, &service.ObjectPartType{
PartNumber: service.Int(partCnt - 0),
})
partCnt++
}
return partNumbers, nil
}
func (u *Uploader) complete(objectKey string, uploadID *string, partNumbers []*service.ObjectPartType) error {
_, err := u.bucket.CompleteMultipartUpload(
objectKey,
&service.CompleteMultipartUploadInput{
UploadID: uploadID,
ObjectParts: partNumbers,
},
)
if err != nil {
return err
}
return nil
}