Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

upload: generate a new mpart ID when NoSuchUpload #557

Merged
merged 1 commit into from
Nov 27, 2016
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
60 changes: 46 additions & 14 deletions api-put-object-common.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,37 +166,69 @@ func hashCopyN(hashAlgorithms map[string]hash.Hash, hashSums map[string][]byte,

// getUploadID - fetch upload id if already present for an object name
// or initiate a new request to fetch a new upload id.
func (c Client) getUploadID(bucketName, objectName, contentType string) (uploadID string, isNew bool, err error) {
func (c Client) newUploadID(bucketName, objectName, contentType string) (uploadID string, err error) {
// Input validation.
if err := isValidBucketName(bucketName); err != nil {
return "", false, err
return "", err
}
if err := isValidObjectName(objectName); err != nil {
return "", false, err
return "", err
}

// Set content Type to default if empty string.
if contentType == "" {
contentType = "application/octet-stream"
}

// Find upload id for previous upload for an object.
uploadID, err = c.findUploadID(bucketName, objectName)
// Initiate multipart upload for an object.
initMultipartUploadResult, err := c.initiateMultipartUpload(bucketName, objectName, contentType)
if err != nil {
return "", false, err
return "", err
}
return initMultipartUploadResult.UploadID, nil
}

// getMpartUploadSession returns the upload id and the uploaded parts to continue a previous upload session
// or initiate a new multipart session if no current one found
func (c Client) getMpartUploadSession(bucketName, objectName, contentType string) (string, map[int]objectPart, error) {
// A map of all uploaded parts.
var partsInfo map[int]objectPart
var err error

uploadID, err := c.findUploadID(bucketName, objectName)
if err != nil {
return "", nil, err
}

if uploadID == "" {
// Initiate multipart upload for an object.
initMultipartUploadResult, err := c.initiateMultipartUpload(bucketName, objectName, contentType)
// Initiates a new multipart request
uploadID, err = c.newUploadID(bucketName, objectName, contentType)
if err != nil {
return "", false, err
return "", nil, err
}
} else {
// Fetch previously upload parts and maximum part size.
partsInfo, err = c.listObjectParts(bucketName, objectName, uploadID)
if err != nil {
// When the server returns NoSuchUpload even if its previouls acknowleged the existance of the upload id,
// initiate a new multipart upload
if respErr, ok := err.(ErrorResponse); ok && respErr.Code == "NoSuchUpload" {
uploadID, err = c.newUploadID(bucketName, objectName, contentType)
if err != nil {
return "", nil, err
}
} else {
return "", nil, err
}
}
// Save the new upload id.
uploadID = initMultipartUploadResult.UploadID
// Indicate that this is a new upload id.
isNew = true
}
return uploadID, isNew, nil

// Allocate partsInfo if not done yet
if partsInfo == nil {
partsInfo = make(map[int]objectPart)
}

return uploadID, partsInfo, nil
}

// computeHash - Calculates hashes for an input read Seeker.
Expand Down
18 changes: 2 additions & 16 deletions api-put-object-file.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,8 @@ func (c Client) putObjectMultipartFromFile(bucketName, objectName string, fileRe
return 0, err
}

// Get upload id for an object, initiates a new multipart request
// if it cannot find any previously partially uploaded object.
uploadID, isNew, err := c.getUploadID(bucketName, objectName, contentType)
// Get the upload id of a previously partially uploaded object or initiate a new multipart upload
uploadID, partsInfo, err := c.getMpartUploadSession(bucketName, objectName, contentType)
if err != nil {
return 0, err
}
Expand All @@ -153,19 +152,6 @@ func (c Client) putObjectMultipartFromFile(bucketName, objectName string, fileRe
// Complete multipart upload.
var complMultipartUpload completeMultipartUpload

// A map of all uploaded parts.
var partsInfo = make(map[int]objectPart)

// If this session is a continuation of a previous session fetch all
// previously uploaded parts info.
if !isNew {
// Fetch previously upload parts and maximum part size.
partsInfo, err = c.listObjectParts(bucketName, objectName, uploadID)
if err != nil {
return 0, err
}
}

// Calculate the optimal parts info for a given size.
totalPartsCount, partSize, lastPartSize, err := optimalPartInfo(fileSize)
if err != nil {
Expand Down
19 changes: 2 additions & 17 deletions api-put-object-multipart.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,27 +83,12 @@ func (c Client) putObjectMultipartStream(bucketName, objectName string, reader i
// Complete multipart upload.
var complMultipartUpload completeMultipartUpload

// A map of all previously uploaded parts.
var partsInfo = make(map[int]objectPart)

// getUploadID for an object, initiates a new multipart request
// if it cannot find any previously partially uploaded object.
uploadID, isNew, err := c.getUploadID(bucketName, objectName, contentType)
// Get the upload id of a previously partially uploaded object or initiate a new multipart upload
uploadID, partsInfo, err := c.getMpartUploadSession(bucketName, objectName, contentType)
if err != nil {
return 0, err
}

// If This session is a continuation of a previous session fetch all
// previously uploaded parts info and as a special case only fetch partsInfo
// for only known upload size.
if !isNew {
// Fetch previously uploaded parts and maximum part size.
partsInfo, err = c.listObjectParts(bucketName, objectName, uploadID)
if err != nil {
return 0, err
}
}

// Calculate the optimal parts info for a given size.
totalPartsCount, partSize, _, err := optimalPartInfo(size)
if err != nil {
Expand Down
16 changes: 2 additions & 14 deletions api-put-object-readat.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,8 @@ func (c Client) putObjectMultipartFromReadAt(bucketName, objectName string, read
return 0, err
}

// Get upload id for an object, initiates a new multipart request
// if it cannot find any previously partially uploaded object.
uploadID, isNew, err := c.getUploadID(bucketName, objectName, contentType)
// Get the upload id of a previously partially uploaded object or initiate a new multipart upload
uploadID, partsInfo, err := c.getMpartUploadSession(bucketName, objectName, contentType)
if err != nil {
return 0, err
}
Expand All @@ -85,17 +84,6 @@ func (c Client) putObjectMultipartFromReadAt(bucketName, objectName string, read
// Complete multipart upload.
var complMultipartUpload completeMultipartUpload

// A map of all uploaded parts.
var partsInfo = make(map[int]objectPart)

// Fetch all parts info previously uploaded.
if !isNew {
partsInfo, err = c.listObjectParts(bucketName, objectName, uploadID)
if err != nil {
return 0, err
}
}

// Calculate the optimal parts info for a given size.
totalPartsCount, partSize, lastPartSize, err := optimalPartInfo(size)
if err != nil {
Expand Down