mirror of
https://github.com/minio/minio.git
synced 2024-12-24 06:05:55 -05:00
Add public data-types for easier external loading (#5170)
This change brings public data-types such that we can ask projects to implement gateway projects externally than maintaining in our repo. All publicly exported structs are maintained in object-api-datatypes.go completePart --> CompletePart uploadMetadata --> MultipartInfo All other exported errors are at object-api-errors.go
This commit is contained in:
parent
7d3eaf79ff
commit
a4d6195244
@ -359,15 +359,15 @@ func initFormatFS(fsPath string) (rlk *lock.RLockedFile, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return if the part info in uploadedParts and completeParts are same.
|
// Return if the part info in uploadedParts and CompleteParts are same.
|
||||||
func isPartsSame(uploadedParts []objectPartInfo, completeParts []completePart) bool {
|
func isPartsSame(uploadedParts []objectPartInfo, CompleteParts []CompletePart) bool {
|
||||||
if len(uploadedParts) != len(completeParts) {
|
if len(uploadedParts) != len(CompleteParts) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range completeParts {
|
for i := range CompleteParts {
|
||||||
if uploadedParts[i].Number != completeParts[i].PartNumber ||
|
if uploadedParts[i].Number != CompleteParts[i].PartNumber ||
|
||||||
uploadedParts[i].ETag != completeParts[i].ETag {
|
uploadedParts[i].ETag != CompleteParts[i].ETag {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,8 +110,8 @@ func (fs fsObjects) addUploadID(bucket, object, uploadID string, initiated time.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// listMultipartUploadIDs - list all the upload ids from a marker up to 'count'.
|
// listMultipartUploadIDs - list all the upload ids from a marker up to 'count'.
|
||||||
func (fs fsObjects) listMultipartUploadIDs(bucketName, objectName, uploadIDMarker string, count int) ([]uploadMetadata, bool, error) {
|
func (fs fsObjects) listMultipartUploadIDs(bucketName, objectName, uploadIDMarker string, count int) ([]MultipartInfo, bool, error) {
|
||||||
var uploads []uploadMetadata
|
var uploads []MultipartInfo
|
||||||
|
|
||||||
// Hold the lock so that two parallel complete-multipart-uploads
|
// Hold the lock so that two parallel complete-multipart-uploads
|
||||||
// do not leave a stale uploads.json behind.
|
// do not leave a stale uploads.json behind.
|
||||||
@ -149,7 +149,7 @@ func (fs fsObjects) listMultipartUploadIDs(bucketName, objectName, uploadIDMarke
|
|||||||
}
|
}
|
||||||
|
|
||||||
for index < len(uploadIDs.Uploads) {
|
for index < len(uploadIDs.Uploads) {
|
||||||
uploads = append(uploads, uploadMetadata{
|
uploads = append(uploads, MultipartInfo{
|
||||||
Object: objectName,
|
Object: objectName,
|
||||||
UploadID: uploadIDs.Uploads[index].UploadID,
|
UploadID: uploadIDs.Uploads[index].UploadID,
|
||||||
Initiated: uploadIDs.Uploads[index].Initiated,
|
Initiated: uploadIDs.Uploads[index].Initiated,
|
||||||
@ -191,7 +191,7 @@ func (fs fsObjects) listMultipartUploadsCleanup(bucket, prefix, keyMarker, uploa
|
|||||||
multipartMarkerPath = pathJoin(bucket, keyMarker)
|
multipartMarkerPath = pathJoin(bucket, keyMarker)
|
||||||
}
|
}
|
||||||
|
|
||||||
var uploads []uploadMetadata
|
var uploads []MultipartInfo
|
||||||
var err error
|
var err error
|
||||||
var eof bool
|
var eof bool
|
||||||
|
|
||||||
@ -244,7 +244,7 @@ func (fs fsObjects) listMultipartUploadsCleanup(bucket, prefix, keyMarker, uploa
|
|||||||
|
|
||||||
entry := strings.TrimPrefix(walkResult.entry, retainSlash(bucket))
|
entry := strings.TrimPrefix(walkResult.entry, retainSlash(bucket))
|
||||||
if hasSuffix(walkResult.entry, slashSeparator) {
|
if hasSuffix(walkResult.entry, slashSeparator) {
|
||||||
uploads = append(uploads, uploadMetadata{
|
uploads = append(uploads, MultipartInfo{
|
||||||
Object: entry,
|
Object: entry,
|
||||||
})
|
})
|
||||||
maxUploads--
|
maxUploads--
|
||||||
@ -257,7 +257,7 @@ func (fs fsObjects) listMultipartUploadsCleanup(bucket, prefix, keyMarker, uploa
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var tmpUploads []uploadMetadata
|
var tmpUploads []MultipartInfo
|
||||||
var end bool
|
var end bool
|
||||||
uploadIDMarker = ""
|
uploadIDMarker = ""
|
||||||
|
|
||||||
@ -713,7 +713,7 @@ func (fs fsObjects) ListObjectParts(bucket, object, uploadID string, partNumberM
|
|||||||
// md5sums of all the parts.
|
// md5sums of all the parts.
|
||||||
//
|
//
|
||||||
// Implements S3 compatible Complete multipart API.
|
// Implements S3 compatible Complete multipart API.
|
||||||
func (fs fsObjects) CompleteMultipartUpload(bucket string, object string, uploadID string, parts []completePart) (oi ObjectInfo, e error) {
|
func (fs fsObjects) CompleteMultipartUpload(bucket string, object string, uploadID string, parts []CompletePart) (oi ObjectInfo, e error) {
|
||||||
if err := checkCompleteMultipartArgs(bucket, object, fs); err != nil {
|
if err := checkCompleteMultipartArgs(bucket, object, fs); err != nil {
|
||||||
return oi, err
|
return oi, err
|
||||||
}
|
}
|
||||||
|
@ -216,7 +216,7 @@ func TestCompleteMultipartUploadFaultyDisk(t *testing.T) {
|
|||||||
t.Fatal("Unexpected error ", err)
|
t.Fatal("Unexpected error ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
parts := []completePart{{PartNumber: 1, ETag: md5Hex}}
|
parts := []CompletePart{{PartNumber: 1, ETag: md5Hex}}
|
||||||
|
|
||||||
fs.fsPath = filepath.Join(globalTestTmpDir, "minio-"+nextSuffix())
|
fs.fsPath = filepath.Join(globalTestTmpDir, "minio-"+nextSuffix())
|
||||||
if _, err := fs.CompleteMultipartUpload(bucketName, objectName, uploadID, parts); err != nil {
|
if _, err := fs.CompleteMultipartUpload(bucketName, objectName, uploadID, parts); err != nil {
|
||||||
@ -253,7 +253,7 @@ func TestCompleteMultipartUpload(t *testing.T) {
|
|||||||
t.Fatal("Unexpected error ", err)
|
t.Fatal("Unexpected error ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
parts := []completePart{{PartNumber: 1, ETag: md5Hex}}
|
parts := []CompletePart{{PartNumber: 1, ETag: md5Hex}}
|
||||||
|
|
||||||
if _, err := fs.CompleteMultipartUpload(bucketName, objectName, uploadID, parts); err != nil {
|
if _, err := fs.CompleteMultipartUpload(bucketName, objectName, uploadID, parts); err != nil {
|
||||||
t.Fatal("Unexpected error ", err)
|
t.Fatal("Unexpected error ", err)
|
||||||
|
@ -756,7 +756,7 @@ func (a *azureObjects) AbortMultipartUpload(bucket, object, uploadID string) (er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CompleteMultipartUpload - Use Azure equivalent PutBlockList.
|
// CompleteMultipartUpload - Use Azure equivalent PutBlockList.
|
||||||
func (a *azureObjects) CompleteMultipartUpload(bucket, object, uploadID string, uploadedParts []completePart) (objInfo ObjectInfo, err error) {
|
func (a *azureObjects) CompleteMultipartUpload(bucket, object, uploadID string, uploadedParts []CompletePart) (objInfo ObjectInfo, err error) {
|
||||||
metadataObject := getAzureMetadataObjectName(object, uploadID)
|
metadataObject := getAzureMetadataObjectName(object, uploadID)
|
||||||
if err = a.checkUploadIDExists(bucket, object, uploadID); err != nil {
|
if err = a.checkUploadIDExists(bucket, object, uploadID); err != nil {
|
||||||
return objInfo, err
|
return objInfo, err
|
||||||
|
@ -566,7 +566,7 @@ func (l *b2Objects) ListMultipartUploads(bucket string, prefix string, keyMarker
|
|||||||
lmi.NextUploadIDMarker = nextMarker
|
lmi.NextUploadIDMarker = nextMarker
|
||||||
}
|
}
|
||||||
for _, largeFile := range largeFiles {
|
for _, largeFile := range largeFiles {
|
||||||
lmi.Uploads = append(lmi.Uploads, uploadMetadata{
|
lmi.Uploads = append(lmi.Uploads, MultipartInfo{
|
||||||
Object: largeFile.Name,
|
Object: largeFile.Name,
|
||||||
UploadID: largeFile.ID,
|
UploadID: largeFile.ID,
|
||||||
Initiated: largeFile.Timestamp,
|
Initiated: largeFile.Timestamp,
|
||||||
@ -673,7 +673,7 @@ func (l *b2Objects) AbortMultipartUpload(bucket string, object string, uploadID
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CompleteMultipartUpload completes ongoing multipart upload and finalizes object, uses B2's LargeFile upload API.
|
// CompleteMultipartUpload completes ongoing multipart upload and finalizes object, uses B2's LargeFile upload API.
|
||||||
func (l *b2Objects) CompleteMultipartUpload(bucket string, object string, uploadID string, uploadedParts []completePart) (oi ObjectInfo, err error) {
|
func (l *b2Objects) CompleteMultipartUpload(bucket string, object string, uploadID string, uploadedParts []CompletePart) (oi ObjectInfo, err error) {
|
||||||
bkt, err := l.Bucket(bucket)
|
bkt, err := l.Bucket(bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return oi, err
|
return oi, err
|
||||||
|
@ -1015,7 +1015,7 @@ func (l *gcsGateway) AbortMultipartUpload(bucket string, key string, uploadID st
|
|||||||
// to the number of components you can compose per second. This rate counts both the
|
// to the number of components you can compose per second. This rate counts both the
|
||||||
// components being appended to a composite object as well as the components being
|
// components being appended to a composite object as well as the components being
|
||||||
// copied when the composite object of which they are a part is copied.
|
// copied when the composite object of which they are a part is copied.
|
||||||
func (l *gcsGateway) CompleteMultipartUpload(bucket string, key string, uploadID string, uploadedParts []completePart) (ObjectInfo, error) {
|
func (l *gcsGateway) CompleteMultipartUpload(bucket string, key string, uploadID string, uploadedParts []CompletePart) (ObjectInfo, error) {
|
||||||
meta := gcsMultipartMetaName(uploadID)
|
meta := gcsMultipartMetaName(uploadID)
|
||||||
object := l.client.Bucket(bucket).Object(meta)
|
object := l.client.Bucket(bucket).Object(meta)
|
||||||
|
|
||||||
|
@ -447,9 +447,9 @@ func (l *s3Objects) DeleteObject(bucket string, object string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// fromMinioClientUploadMetadata converts ObjectMultipartInfo to uploadMetadata
|
// fromMinioClientMultipartInfo converts ObjectMultipartInfo to MultipartInfo
|
||||||
func fromMinioClientUploadMetadata(omi minio.ObjectMultipartInfo) uploadMetadata {
|
func fromMinioClientMultipartInfo(omi minio.ObjectMultipartInfo) MultipartInfo {
|
||||||
return uploadMetadata{
|
return MultipartInfo{
|
||||||
Object: omi.Key,
|
Object: omi.Key,
|
||||||
UploadID: omi.UploadID,
|
UploadID: omi.UploadID,
|
||||||
Initiated: omi.Initiated,
|
Initiated: omi.Initiated,
|
||||||
@ -458,10 +458,10 @@ func fromMinioClientUploadMetadata(omi minio.ObjectMultipartInfo) uploadMetadata
|
|||||||
|
|
||||||
// fromMinioClientListMultipartsInfo converts minio ListMultipartUploadsResult to ListMultipartsInfo
|
// fromMinioClientListMultipartsInfo converts minio ListMultipartUploadsResult to ListMultipartsInfo
|
||||||
func fromMinioClientListMultipartsInfo(lmur minio.ListMultipartUploadsResult) ListMultipartsInfo {
|
func fromMinioClientListMultipartsInfo(lmur minio.ListMultipartUploadsResult) ListMultipartsInfo {
|
||||||
uploads := make([]uploadMetadata, len(lmur.Uploads))
|
uploads := make([]MultipartInfo, len(lmur.Uploads))
|
||||||
|
|
||||||
for i, um := range lmur.Uploads {
|
for i, um := range lmur.Uploads {
|
||||||
uploads[i] = fromMinioClientUploadMetadata(um)
|
uploads[i] = fromMinioClientMultipartInfo(um)
|
||||||
}
|
}
|
||||||
|
|
||||||
commonPrefixes := make([]string, len(lmur.CommonPrefixes))
|
commonPrefixes := make([]string, len(lmur.CommonPrefixes))
|
||||||
@ -585,16 +585,16 @@ func (l *s3Objects) AbortMultipartUpload(bucket string, object string, uploadID
|
|||||||
return s3ToObjectError(traceError(err), bucket, object)
|
return s3ToObjectError(traceError(err), bucket, object)
|
||||||
}
|
}
|
||||||
|
|
||||||
// toMinioClientCompletePart converts completePart to minio CompletePart
|
// toMinioClientCompletePart converts CompletePart to minio CompletePart
|
||||||
func toMinioClientCompletePart(part completePart) minio.CompletePart {
|
func toMinioClientCompletePart(part CompletePart) minio.CompletePart {
|
||||||
return minio.CompletePart{
|
return minio.CompletePart{
|
||||||
ETag: part.ETag,
|
ETag: part.ETag,
|
||||||
PartNumber: part.PartNumber,
|
PartNumber: part.PartNumber,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// toMinioClientCompleteParts converts []completePart to minio []CompletePart
|
// toMinioClientCompleteParts converts []CompletePart to minio []CompletePart
|
||||||
func toMinioClientCompleteParts(parts []completePart) []minio.CompletePart {
|
func toMinioClientCompleteParts(parts []CompletePart) []minio.CompletePart {
|
||||||
mparts := make([]minio.CompletePart, len(parts))
|
mparts := make([]minio.CompletePart, len(parts))
|
||||||
for i, part := range parts {
|
for i, part := range parts {
|
||||||
mparts[i] = toMinioClientCompletePart(part)
|
mparts[i] = toMinioClientCompletePart(part)
|
||||||
@ -603,7 +603,7 @@ func toMinioClientCompleteParts(parts []completePart) []minio.CompletePart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CompleteMultipartUpload completes ongoing multipart upload and finalizes object
|
// CompleteMultipartUpload completes ongoing multipart upload and finalizes object
|
||||||
func (l *s3Objects) CompleteMultipartUpload(bucket string, object string, uploadID string, uploadedParts []completePart) (oi ObjectInfo, e error) {
|
func (l *s3Objects) CompleteMultipartUpload(bucket string, object string, uploadID string, uploadedParts []CompletePart) (oi ObjectInfo, e error) {
|
||||||
err := l.Client.CompleteMultipartUpload(bucket, object, uploadID, toMinioClientCompleteParts(uploadedParts))
|
err := l.Client.CompleteMultipartUpload(bucket, object, uploadID, toMinioClientCompleteParts(uploadedParts))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return oi, s3ToObjectError(traceError(err), bucket, object)
|
return oi, s3ToObjectError(traceError(err), bucket, object)
|
||||||
|
@ -181,7 +181,7 @@ type ListMultipartsInfo struct {
|
|||||||
IsTruncated bool
|
IsTruncated bool
|
||||||
|
|
||||||
// List of all pending uploads.
|
// List of all pending uploads.
|
||||||
Uploads []uploadMetadata
|
Uploads []MultipartInfo
|
||||||
|
|
||||||
// When a prefix is provided in the request, The result contains only keys
|
// When a prefix is provided in the request, The result contains only keys
|
||||||
// starting with the specified prefix.
|
// starting with the specified prefix.
|
||||||
@ -261,8 +261,8 @@ type PartInfo struct {
|
|||||||
Size int64
|
Size int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// uploadMetadata - represents metadata in progress multipart upload.
|
// MultipartInfo - represents metadata in progress multipart upload.
|
||||||
type uploadMetadata struct {
|
type MultipartInfo struct {
|
||||||
// Object name for which the multipart upload was initiated.
|
// Object name for which the multipart upload was initiated.
|
||||||
Object string
|
Object string
|
||||||
|
|
||||||
@ -277,8 +277,9 @@ type uploadMetadata struct {
|
|||||||
HealUploadInfo *HealObjectInfo `xml:"HealUploadInfo,omitempty"`
|
HealUploadInfo *HealObjectInfo `xml:"HealUploadInfo,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// completePart - completed part container.
|
// CompletePart - represents the part that was completed, this is sent by the client
|
||||||
type completePart struct {
|
// during CompleteMultipartUpload request.
|
||||||
|
type CompletePart struct {
|
||||||
// Part number identifying the part. This is a positive integer between 1 and
|
// Part number identifying the part. This is a positive integer between 1 and
|
||||||
// 10,000
|
// 10,000
|
||||||
PartNumber int
|
PartNumber int
|
||||||
@ -287,14 +288,15 @@ type completePart struct {
|
|||||||
ETag string
|
ETag string
|
||||||
}
|
}
|
||||||
|
|
||||||
// completedParts - is a collection satisfying sort.Interface.
|
// CompletedParts - is a collection satisfying sort.Interface.
|
||||||
type completedParts []completePart
|
type CompletedParts []CompletePart
|
||||||
|
|
||||||
func (a completedParts) Len() int { return len(a) }
|
func (a CompletedParts) Len() int { return len(a) }
|
||||||
func (a completedParts) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
func (a CompletedParts) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
func (a completedParts) Less(i, j int) bool { return a[i].PartNumber < a[j].PartNumber }
|
func (a CompletedParts) Less(i, j int) bool { return a[i].PartNumber < a[j].PartNumber }
|
||||||
|
|
||||||
// completeMultipartUpload - represents input fields for completing multipart upload.
|
// CompleteMultipartUpload - represents list of parts which are completed, this is sent by the
|
||||||
type completeMultipartUpload struct {
|
// client during CompleteMultipartUpload request.
|
||||||
Parts []completePart `xml:"Part"`
|
type CompleteMultipartUpload struct {
|
||||||
|
Parts []CompletePart `xml:"Part"`
|
||||||
}
|
}
|
||||||
|
@ -263,13 +263,13 @@ func (e IncompleteBody) Error() string {
|
|||||||
|
|
||||||
// InvalidRange - invalid range typed error.
|
// InvalidRange - invalid range typed error.
|
||||||
type InvalidRange struct {
|
type InvalidRange struct {
|
||||||
offsetBegin int64
|
OffsetBegin int64
|
||||||
offsetEnd int64
|
OffsetEnd int64
|
||||||
resourceSize int64
|
ResourceSize int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e InvalidRange) Error() string {
|
func (e InvalidRange) Error() string {
|
||||||
return fmt.Sprintf("The requested range \"bytes %d-%d/%d\" is not satisfiable.", e.offsetBegin, e.offsetEnd, e.resourceSize)
|
return fmt.Sprintf("The requested range \"bytes %d-%d/%d\" is not satisfiable.", e.OffsetBegin, e.OffsetEnd, e.ResourceSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObjectTooLarge error returned when the size of the object > max object size allowed (5G) per request.
|
// ObjectTooLarge error returned when the size of the object > max object size allowed (5G) per request.
|
||||||
@ -375,7 +375,7 @@ func (e UnsupportedMetadata) Error() string {
|
|||||||
return "Unsupported headers in Metadata"
|
return "Unsupported headers in Metadata"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if error type is IncompleteBody.
|
// isErrIncompleteBody - Check if error type is IncompleteBody.
|
||||||
func isErrIncompleteBody(err error) bool {
|
func isErrIncompleteBody(err error) bool {
|
||||||
err = errorCause(err)
|
err = errorCause(err)
|
||||||
switch err.(type) {
|
switch err.(type) {
|
||||||
@ -385,7 +385,7 @@ func isErrIncompleteBody(err error) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if error type is BucketPolicyNotFound.
|
// isErrBucketPolicyNotFound - Check if error type is BucketPolicyNotFound.
|
||||||
func isErrBucketPolicyNotFound(err error) bool {
|
func isErrBucketPolicyNotFound(err error) bool {
|
||||||
err = errorCause(err)
|
err = errorCause(err)
|
||||||
switch err.(type) {
|
switch err.(type) {
|
||||||
@ -395,7 +395,7 @@ func isErrBucketPolicyNotFound(err error) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if error type is ObjectNotFound.
|
// isErrObjectNotFound - Check if error type is ObjectNotFound.
|
||||||
func isErrObjectNotFound(err error) bool {
|
func isErrObjectNotFound(err error) bool {
|
||||||
err = errorCause(err)
|
err = errorCause(err)
|
||||||
switch err.(type) {
|
switch err.(type) {
|
||||||
|
@ -49,7 +49,7 @@ type ObjectLayer interface {
|
|||||||
PutObjectPart(bucket, object, uploadID string, partID int, data *hash.Reader) (info PartInfo, err error)
|
PutObjectPart(bucket, object, uploadID string, partID int, data *hash.Reader) (info PartInfo, err error)
|
||||||
ListObjectParts(bucket, object, uploadID string, partNumberMarker int, maxParts int) (result ListPartsInfo, err error)
|
ListObjectParts(bucket, object, uploadID string, partNumberMarker int, maxParts int) (result ListPartsInfo, err error)
|
||||||
AbortMultipartUpload(bucket, object, uploadID string) error
|
AbortMultipartUpload(bucket, object, uploadID string) error
|
||||||
CompleteMultipartUpload(bucket, object, uploadID string, uploadedParts []completePart) (objInfo ObjectInfo, err error)
|
CompleteMultipartUpload(bucket, object, uploadID string, uploadedParts []CompletePart) (objInfo ObjectInfo, err error)
|
||||||
|
|
||||||
// Healing operations.
|
// Healing operations.
|
||||||
HealBucket(bucket string) error
|
HealBucket(bucket string) error
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Minio Cloud Storage, (C) 2016 Minio, Inc.
|
* Minio Cloud Storage, (C) 2016, 2017 Minio, Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -161,8 +161,8 @@ func writeUploadJSON(u *uploadsV1, uploadsPath, tmpPath string, disk StorageAPI)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// listMultipartUploadIDs - list all the upload ids from a marker up to 'count'.
|
// listMultipartUploadIDs - list all the upload ids from a marker up to 'count'.
|
||||||
func listMultipartUploadIDs(bucketName, objectName, uploadIDMarker string, count int, disk StorageAPI) ([]uploadMetadata, bool, error) {
|
func listMultipartUploadIDs(bucketName, objectName, uploadIDMarker string, count int, disk StorageAPI) ([]MultipartInfo, bool, error) {
|
||||||
var uploads []uploadMetadata
|
var uploads []MultipartInfo
|
||||||
// Read `uploads.json`.
|
// Read `uploads.json`.
|
||||||
uploadsJSON, err := readUploadsJSON(bucketName, objectName, disk)
|
uploadsJSON, err := readUploadsJSON(bucketName, objectName, disk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -179,7 +179,7 @@ func listMultipartUploadIDs(bucketName, objectName, uploadIDMarker string, count
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for index < len(uploadsJSON.Uploads) {
|
for index < len(uploadsJSON.Uploads) {
|
||||||
uploads = append(uploads, uploadMetadata{
|
uploads = append(uploads, MultipartInfo{
|
||||||
Object: objectName,
|
Object: objectName,
|
||||||
UploadID: uploadsJSON.Uploads[index].UploadID,
|
UploadID: uploadsJSON.Uploads[index].UploadID,
|
||||||
Initiated: uploadsJSON.Uploads[index].Initiated,
|
Initiated: uploadsJSON.Uploads[index].Initiated,
|
||||||
|
@ -499,7 +499,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
// ListMultipartUploads doesn't list the parts.
|
// ListMultipartUploads doesn't list the parts.
|
||||||
{
|
{
|
||||||
MaxUploads: 100,
|
MaxUploads: 100,
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[0],
|
Object: objectNames[0],
|
||||||
UploadID: uploadIDs[0],
|
UploadID: uploadIDs[0],
|
||||||
@ -515,7 +515,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
KeyMarker: "minio-object-1.txt",
|
KeyMarker: "minio-object-1.txt",
|
||||||
},
|
},
|
||||||
// listMultipartResults - 3.
|
// listMultipartResults - 3.
|
||||||
// `KeyMarker` is set, no uploadMetadata expected.
|
// `KeyMarker` is set, no MultipartInfo expected.
|
||||||
// ListMultipartUploads doesn't list the parts.
|
// ListMultipartUploads doesn't list the parts.
|
||||||
// `Maxupload` value is asserted.
|
// `Maxupload` value is asserted.
|
||||||
{
|
{
|
||||||
@ -523,7 +523,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
KeyMarker: "orange",
|
KeyMarker: "orange",
|
||||||
},
|
},
|
||||||
// listMultipartResults - 4.
|
// listMultipartResults - 4.
|
||||||
// `KeyMarker` is set, no uploadMetadata expected.
|
// `KeyMarker` is set, no MultipartInfo expected.
|
||||||
// Maxupload value is asserted.
|
// Maxupload value is asserted.
|
||||||
{
|
{
|
||||||
MaxUploads: 1,
|
MaxUploads: 1,
|
||||||
@ -531,12 +531,12 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
},
|
},
|
||||||
// listMultipartResults - 5.
|
// listMultipartResults - 5.
|
||||||
// `KeyMarker` is set. It contains part of the objectname as `KeyPrefix`.
|
// `KeyMarker` is set. It contains part of the objectname as `KeyPrefix`.
|
||||||
// Expecting the result to contain one uploadMetadata entry and Istruncated to be false.
|
// Expecting the result to contain one MultipartInfo entry and Istruncated to be false.
|
||||||
{
|
{
|
||||||
MaxUploads: 10,
|
MaxUploads: 10,
|
||||||
KeyMarker: "min",
|
KeyMarker: "min",
|
||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[0],
|
Object: objectNames[0],
|
||||||
UploadID: uploadIDs[0],
|
UploadID: uploadIDs[0],
|
||||||
@ -546,12 +546,12 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
// listMultipartResults - 6.
|
// listMultipartResults - 6.
|
||||||
// `KeyMarker` is set. It contains part of the objectname as `KeyPrefix`.
|
// `KeyMarker` is set. It contains part of the objectname as `KeyPrefix`.
|
||||||
// `MaxUploads` is set equal to the number of meta data entries in the result, the result contains only one entry.
|
// `MaxUploads` is set equal to the number of meta data entries in the result, the result contains only one entry.
|
||||||
// Expecting the result to contain one uploadMetadata entry and IsTruncated to be false.
|
// Expecting the result to contain one MultipartInfo entry and IsTruncated to be false.
|
||||||
{
|
{
|
||||||
MaxUploads: 1,
|
MaxUploads: 1,
|
||||||
KeyMarker: "min",
|
KeyMarker: "min",
|
||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[0],
|
Object: objectNames[0],
|
||||||
UploadID: uploadIDs[0],
|
UploadID: uploadIDs[0],
|
||||||
@ -561,7 +561,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
// listMultipartResults - 7.
|
// listMultipartResults - 7.
|
||||||
// `KeyMarker` is set. It contains part of the objectname as `KeyPrefix`.
|
// `KeyMarker` is set. It contains part of the objectname as `KeyPrefix`.
|
||||||
// Testing for the case with `MaxUploads` set to 0.
|
// Testing for the case with `MaxUploads` set to 0.
|
||||||
// Expecting the result to contain no uploadMetadata entry since `MaxUploads` is set to 0.
|
// Expecting the result to contain no MultipartInfo entry since `MaxUploads` is set to 0.
|
||||||
// Expecting `IsTruncated` to be true.
|
// Expecting `IsTruncated` to be true.
|
||||||
{
|
{
|
||||||
MaxUploads: 0,
|
MaxUploads: 0,
|
||||||
@ -571,7 +571,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
// listMultipartResults - 8.
|
// listMultipartResults - 8.
|
||||||
// `KeyMarker` is set. It contains part of the objectname as KeyPrefix.
|
// `KeyMarker` is set. It contains part of the objectname as KeyPrefix.
|
||||||
// Testing for the case with `MaxUploads` set to 0.
|
// Testing for the case with `MaxUploads` set to 0.
|
||||||
// Expecting the result to contain no uploadMetadata entry since `MaxUploads` is set to 0.
|
// Expecting the result to contain no MultipartInfo entry since `MaxUploads` is set to 0.
|
||||||
// Expecting `isTruncated` to be true.
|
// Expecting `isTruncated` to be true.
|
||||||
{
|
{
|
||||||
MaxUploads: 0,
|
MaxUploads: 0,
|
||||||
@ -581,12 +581,12 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
// listMultipartResults - 9.
|
// listMultipartResults - 9.
|
||||||
// `KeyMarker` is set. It contains part of the objectname as KeyPrefix.
|
// `KeyMarker` is set. It contains part of the objectname as KeyPrefix.
|
||||||
// `KeyMarker` is set equal to the object name in the result.
|
// `KeyMarker` is set equal to the object name in the result.
|
||||||
// Expecting the result to contain one uploadMetadata entry and IsTruncated to be false.
|
// Expecting the result to contain one MultipartInfo entry and IsTruncated to be false.
|
||||||
{
|
{
|
||||||
MaxUploads: 2,
|
MaxUploads: 2,
|
||||||
KeyMarker: "minio-object",
|
KeyMarker: "minio-object",
|
||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[0],
|
Object: objectNames[0],
|
||||||
UploadID: uploadIDs[0],
|
UploadID: uploadIDs[0],
|
||||||
@ -596,12 +596,12 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
// listMultipartResults - 10.
|
// listMultipartResults - 10.
|
||||||
// Prefix is set. It is set equal to the object name.
|
// Prefix is set. It is set equal to the object name.
|
||||||
// MaxUploads is set more than number of meta data entries in the result.
|
// MaxUploads is set more than number of meta data entries in the result.
|
||||||
// Expecting the result to contain one uploadMetadata entry and IsTruncated to be false.
|
// Expecting the result to contain one MultipartInfo entry and IsTruncated to be false.
|
||||||
{
|
{
|
||||||
MaxUploads: 2,
|
MaxUploads: 2,
|
||||||
Prefix: "minio-object-1.txt",
|
Prefix: "minio-object-1.txt",
|
||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[0],
|
Object: objectNames[0],
|
||||||
UploadID: uploadIDs[0],
|
UploadID: uploadIDs[0],
|
||||||
@ -611,12 +611,12 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
// listMultipartResults - 11.
|
// listMultipartResults - 11.
|
||||||
// Setting `Prefix` to contain the object name as its prefix.
|
// Setting `Prefix` to contain the object name as its prefix.
|
||||||
// MaxUploads is set more than number of meta data entries in the result.
|
// MaxUploads is set more than number of meta data entries in the result.
|
||||||
// Expecting the result to contain one uploadMetadata entry and IsTruncated to be false.
|
// Expecting the result to contain one MultipartInfo entry and IsTruncated to be false.
|
||||||
{
|
{
|
||||||
MaxUploads: 2,
|
MaxUploads: 2,
|
||||||
Prefix: "min",
|
Prefix: "min",
|
||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[0],
|
Object: objectNames[0],
|
||||||
UploadID: uploadIDs[0],
|
UploadID: uploadIDs[0],
|
||||||
@ -626,12 +626,12 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
// listMultipartResults - 12.
|
// listMultipartResults - 12.
|
||||||
// Setting `Prefix` to contain the object name as its prefix.
|
// Setting `Prefix` to contain the object name as its prefix.
|
||||||
// MaxUploads is set equal to number of meta data entries in the result.
|
// MaxUploads is set equal to number of meta data entries in the result.
|
||||||
// Expecting the result to contain one uploadMetadata entry and IsTruncated to be false.
|
// Expecting the result to contain one MultipartInfo entry and IsTruncated to be false.
|
||||||
{
|
{
|
||||||
MaxUploads: 1,
|
MaxUploads: 1,
|
||||||
Prefix: "min",
|
Prefix: "min",
|
||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[0],
|
Object: objectNames[0],
|
||||||
UploadID: uploadIDs[0],
|
UploadID: uploadIDs[0],
|
||||||
@ -659,13 +659,13 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
// listMultipartResults - 15.
|
// listMultipartResults - 15.
|
||||||
// Setting `Delimiter`.
|
// Setting `Delimiter`.
|
||||||
// MaxUploads is set more than number of meta data entries in the result.
|
// MaxUploads is set more than number of meta data entries in the result.
|
||||||
// Expecting the result to contain one uploadMetadata entry and IsTruncated to be false.
|
// Expecting the result to contain one MultipartInfo entry and IsTruncated to be false.
|
||||||
{
|
{
|
||||||
MaxUploads: 2,
|
MaxUploads: 2,
|
||||||
Delimiter: "/",
|
Delimiter: "/",
|
||||||
Prefix: "",
|
Prefix: "",
|
||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[0],
|
Object: objectNames[0],
|
||||||
UploadID: uploadIDs[0],
|
UploadID: uploadIDs[0],
|
||||||
@ -677,7 +677,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
// Will be used to list on bucketNames[1].
|
// Will be used to list on bucketNames[1].
|
||||||
{
|
{
|
||||||
MaxUploads: 100,
|
MaxUploads: 100,
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[0],
|
Object: objectNames[0],
|
||||||
UploadID: uploadIDs[1],
|
UploadID: uploadIDs[1],
|
||||||
@ -703,7 +703,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
KeyMarker: "minio-object-1.txt",
|
KeyMarker: "minio-object-1.txt",
|
||||||
UploadIDMarker: uploadIDs[1],
|
UploadIDMarker: uploadIDs[1],
|
||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[0],
|
Object: objectNames[0],
|
||||||
UploadID: uploadIDs[2],
|
UploadID: uploadIDs[2],
|
||||||
@ -725,7 +725,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
KeyMarker: "minio-object-1.txt",
|
KeyMarker: "minio-object-1.txt",
|
||||||
UploadIDMarker: uploadIDs[2],
|
UploadIDMarker: uploadIDs[2],
|
||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[0],
|
Object: objectNames[0],
|
||||||
UploadID: uploadIDs[3],
|
UploadID: uploadIDs[3],
|
||||||
@ -734,7 +734,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
},
|
},
|
||||||
// listMultipartResults - 19.
|
// listMultipartResults - 19.
|
||||||
// Testing for listing of 3 uploadID's for a given object, setting maxKeys to be 2.
|
// Testing for listing of 3 uploadID's for a given object, setting maxKeys to be 2.
|
||||||
// There are 3 uploadMetadata in the result (uploadIDs[1-3]), it should be truncated to 2.
|
// There are 3 MultipartInfo in the result (uploadIDs[1-3]), it should be truncated to 2.
|
||||||
// Since there is only single object for bucketNames[1], the NextKeyMarker is set to its name.
|
// Since there is only single object for bucketNames[1], the NextKeyMarker is set to its name.
|
||||||
// The last entry in the result, uploadIDs[2], that is should be set as NextUploadIDMarker.
|
// The last entry in the result, uploadIDs[2], that is should be set as NextUploadIDMarker.
|
||||||
// Will be used to list on bucketNames[1].
|
// Will be used to list on bucketNames[1].
|
||||||
@ -743,7 +743,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
IsTruncated: true,
|
IsTruncated: true,
|
||||||
NextKeyMarker: objectNames[0],
|
NextKeyMarker: objectNames[0],
|
||||||
NextUploadIDMarker: uploadIDs[2],
|
NextUploadIDMarker: uploadIDs[2],
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[0],
|
Object: objectNames[0],
|
||||||
UploadID: uploadIDs[1],
|
UploadID: uploadIDs[1],
|
||||||
@ -756,7 +756,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
},
|
},
|
||||||
// listMultipartResults - 20.
|
// listMultipartResults - 20.
|
||||||
// Testing for listing of 3 uploadID's for a given object, setting maxKeys to be 1.
|
// Testing for listing of 3 uploadID's for a given object, setting maxKeys to be 1.
|
||||||
// There are 3 uploadMetadata in the result (uploadIDs[1-3]), it should be truncated to 1.
|
// There are 3 MultipartInfo in the result (uploadIDs[1-3]), it should be truncated to 1.
|
||||||
// The last entry in the result, uploadIDs[1], that is should be set as NextUploadIDMarker.
|
// The last entry in the result, uploadIDs[1], that is should be set as NextUploadIDMarker.
|
||||||
// Will be used to list on bucketNames[1].
|
// Will be used to list on bucketNames[1].
|
||||||
{
|
{
|
||||||
@ -764,7 +764,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
IsTruncated: true,
|
IsTruncated: true,
|
||||||
NextKeyMarker: objectNames[0],
|
NextKeyMarker: objectNames[0],
|
||||||
NextUploadIDMarker: uploadIDs[1],
|
NextUploadIDMarker: uploadIDs[1],
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[0],
|
Object: objectNames[0],
|
||||||
UploadID: uploadIDs[1],
|
UploadID: uploadIDs[1],
|
||||||
@ -773,13 +773,13 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
},
|
},
|
||||||
// listMultipartResults - 21.
|
// listMultipartResults - 21.
|
||||||
// Testing for listing of 3 uploadID's for a given object, setting maxKeys to be 3.
|
// Testing for listing of 3 uploadID's for a given object, setting maxKeys to be 3.
|
||||||
// There are 3 uploadMetadata in the result (uploadIDs[1-3]), hence no truncation is expected.
|
// There are 3 MultipartInfo in the result (uploadIDs[1-3]), hence no truncation is expected.
|
||||||
// Since all the uploadMetadata is listed, expecting no values for NextUploadIDMarker and NextKeyMarker.
|
// Since all the MultipartInfo is listed, expecting no values for NextUploadIDMarker and NextKeyMarker.
|
||||||
// Will be used to list on bucketNames[1].
|
// Will be used to list on bucketNames[1].
|
||||||
{
|
{
|
||||||
MaxUploads: 3,
|
MaxUploads: 3,
|
||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[0],
|
Object: objectNames[0],
|
||||||
UploadID: uploadIDs[1],
|
UploadID: uploadIDs[1],
|
||||||
@ -801,7 +801,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
MaxUploads: 10,
|
MaxUploads: 10,
|
||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
Prefix: "min",
|
Prefix: "min",
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[0],
|
Object: objectNames[0],
|
||||||
UploadID: uploadIDs[1],
|
UploadID: uploadIDs[1],
|
||||||
@ -844,7 +844,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
Prefix: "min",
|
Prefix: "min",
|
||||||
UploadIDMarker: uploadIDs[1],
|
UploadIDMarker: uploadIDs[1],
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[0],
|
Object: objectNames[0],
|
||||||
UploadID: uploadIDs[2],
|
UploadID: uploadIDs[2],
|
||||||
@ -863,7 +863,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
MaxUploads: 100,
|
MaxUploads: 100,
|
||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
|
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[0],
|
Object: objectNames[0],
|
||||||
UploadID: uploadIDs[4],
|
UploadID: uploadIDs[4],
|
||||||
@ -896,7 +896,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
MaxUploads: 100,
|
MaxUploads: 100,
|
||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
Prefix: "min",
|
Prefix: "min",
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[0],
|
Object: objectNames[0],
|
||||||
UploadID: uploadIDs[4],
|
UploadID: uploadIDs[4],
|
||||||
@ -913,7 +913,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
MaxUploads: 100,
|
MaxUploads: 100,
|
||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
Prefix: "ney",
|
Prefix: "ney",
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[2],
|
Object: objectNames[2],
|
||||||
UploadID: uploadIDs[6],
|
UploadID: uploadIDs[6],
|
||||||
@ -930,7 +930,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
MaxUploads: 100,
|
MaxUploads: 100,
|
||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
Prefix: "parrot",
|
Prefix: "parrot",
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[4],
|
Object: objectNames[4],
|
||||||
UploadID: uploadIDs[8],
|
UploadID: uploadIDs[8],
|
||||||
@ -948,7 +948,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
MaxUploads: 100,
|
MaxUploads: 100,
|
||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
Prefix: "neymar.jpeg",
|
Prefix: "neymar.jpeg",
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[3],
|
Object: objectNames[3],
|
||||||
UploadID: uploadIDs[7],
|
UploadID: uploadIDs[7],
|
||||||
@ -965,7 +965,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
IsTruncated: true,
|
IsTruncated: true,
|
||||||
NextUploadIDMarker: uploadIDs[6],
|
NextUploadIDMarker: uploadIDs[6],
|
||||||
NextKeyMarker: objectNames[2],
|
NextKeyMarker: objectNames[2],
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[0],
|
Object: objectNames[0],
|
||||||
UploadID: uploadIDs[4],
|
UploadID: uploadIDs[4],
|
||||||
@ -987,7 +987,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
{
|
{
|
||||||
MaxUploads: 6,
|
MaxUploads: 6,
|
||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[0],
|
Object: objectNames[0],
|
||||||
UploadID: uploadIDs[4],
|
UploadID: uploadIDs[4],
|
||||||
@ -1020,7 +1020,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
MaxUploads: 10,
|
MaxUploads: 10,
|
||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
UploadIDMarker: uploadIDs[6],
|
UploadIDMarker: uploadIDs[6],
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[3],
|
Object: objectNames[3],
|
||||||
UploadID: uploadIDs[7],
|
UploadID: uploadIDs[7],
|
||||||
@ -1041,7 +1041,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
MaxUploads: 10,
|
MaxUploads: 10,
|
||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
KeyMarker: objectNames[3],
|
KeyMarker: objectNames[3],
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[4],
|
Object: objectNames[4],
|
||||||
UploadID: uploadIDs[8],
|
UploadID: uploadIDs[8],
|
||||||
@ -1054,7 +1054,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
},
|
},
|
||||||
// listMultipartResults - 35.
|
// listMultipartResults - 35.
|
||||||
// Checking listing with `Prefix` and `KeyMarker`.
|
// Checking listing with `Prefix` and `KeyMarker`.
|
||||||
// No upload uploadMetadata in the result expected since KeyMarker is set to last Key in the result.
|
// No upload MultipartInfo in the result expected since KeyMarker is set to last Key in the result.
|
||||||
{
|
{
|
||||||
MaxUploads: 10,
|
MaxUploads: 10,
|
||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
@ -1068,7 +1068,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
IsTruncated: false,
|
IsTruncated: false,
|
||||||
Prefix: "minio",
|
Prefix: "minio",
|
||||||
UploadIDMarker: uploadIDs[4],
|
UploadIDMarker: uploadIDs[4],
|
||||||
Uploads: []uploadMetadata{
|
Uploads: []MultipartInfo{
|
||||||
{
|
{
|
||||||
Object: objectNames[1],
|
Object: objectNames[1],
|
||||||
UploadID: uploadIDs[5],
|
UploadID: uploadIDs[5],
|
||||||
@ -1160,11 +1160,11 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
{bucketNames[1], "", "minio-object-1.txt", uploadIDs[1], "", 100, listMultipartResults[16], nil, true},
|
{bucketNames[1], "", "minio-object-1.txt", uploadIDs[1], "", 100, listMultipartResults[16], nil, true},
|
||||||
{bucketNames[1], "", "minio-object-1.txt", uploadIDs[2], "", 100, listMultipartResults[17], nil, true},
|
{bucketNames[1], "", "minio-object-1.txt", uploadIDs[2], "", 100, listMultipartResults[17], nil, true},
|
||||||
// Test cases with multiple uploadID listing for a given object (Test number 31-32).
|
// Test cases with multiple uploadID listing for a given object (Test number 31-32).
|
||||||
// MaxKeys set to values lesser than the number of entries in the uploadMetadata.
|
// MaxKeys set to values lesser than the number of entries in the MultipartInfo.
|
||||||
// IsTruncated is expected to be true.
|
// IsTruncated is expected to be true.
|
||||||
{bucketNames[1], "", "", "", "", 2, listMultipartResults[18], nil, true},
|
{bucketNames[1], "", "", "", "", 2, listMultipartResults[18], nil, true},
|
||||||
{bucketNames[1], "", "", "", "", 1, listMultipartResults[19], nil, true},
|
{bucketNames[1], "", "", "", "", 1, listMultipartResults[19], nil, true},
|
||||||
// MaxKeys set to the value which is equal to no of entries in the uploadMetadata (Test number 33).
|
// MaxKeys set to the value which is equal to no of entries in the MultipartInfo (Test number 33).
|
||||||
// In case of bucketNames[1], there are 3 entries.
|
// In case of bucketNames[1], there are 3 entries.
|
||||||
// Since all available entries are listed, IsTruncated is expected to be false
|
// Since all available entries are listed, IsTruncated is expected to be false
|
||||||
// and NextMarkers are expected to empty.
|
// and NextMarkers are expected to empty.
|
||||||
@ -1836,19 +1836,19 @@ func testObjectCompleteMultipartUpload(obj ObjectLayer, instanceType string, t T
|
|||||||
}
|
}
|
||||||
// Parts to be sent as input for CompleteMultipartUpload.
|
// Parts to be sent as input for CompleteMultipartUpload.
|
||||||
inputParts := []struct {
|
inputParts := []struct {
|
||||||
parts []completePart
|
parts []CompletePart
|
||||||
}{
|
}{
|
||||||
// inputParts - 0.
|
// inputParts - 0.
|
||||||
// Case for replicating ETag mismatch.
|
// Case for replicating ETag mismatch.
|
||||||
{
|
{
|
||||||
[]completePart{
|
[]CompletePart{
|
||||||
{ETag: "abcd", PartNumber: 1},
|
{ETag: "abcd", PartNumber: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// inputParts - 1.
|
// inputParts - 1.
|
||||||
// should error out with part too small.
|
// should error out with part too small.
|
||||||
{
|
{
|
||||||
[]completePart{
|
[]CompletePart{
|
||||||
{ETag: "e2fc714c4727ee9395f324cd2e7f331f", PartNumber: 1},
|
{ETag: "e2fc714c4727ee9395f324cd2e7f331f", PartNumber: 1},
|
||||||
{ETag: "1f7690ebdd9b4caf8fab49ca1757bf27", PartNumber: 2},
|
{ETag: "1f7690ebdd9b4caf8fab49ca1757bf27", PartNumber: 2},
|
||||||
},
|
},
|
||||||
@ -1856,7 +1856,7 @@ func testObjectCompleteMultipartUpload(obj ObjectLayer, instanceType string, t T
|
|||||||
// inputParts - 2.
|
// inputParts - 2.
|
||||||
// Case with invalid Part number.
|
// Case with invalid Part number.
|
||||||
{
|
{
|
||||||
[]completePart{
|
[]CompletePart{
|
||||||
{ETag: "e2fc714c4727ee9395f324cd2e7f331f", PartNumber: 10},
|
{ETag: "e2fc714c4727ee9395f324cd2e7f331f", PartNumber: 10},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1864,7 +1864,7 @@ func testObjectCompleteMultipartUpload(obj ObjectLayer, instanceType string, t T
|
|||||||
// Case with valid part.
|
// Case with valid part.
|
||||||
// Part size greater than 5MB.
|
// Part size greater than 5MB.
|
||||||
{
|
{
|
||||||
[]completePart{
|
[]CompletePart{
|
||||||
{ETag: validPartMD5, PartNumber: 5},
|
{ETag: validPartMD5, PartNumber: 5},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1872,7 +1872,7 @@ func testObjectCompleteMultipartUpload(obj ObjectLayer, instanceType string, t T
|
|||||||
// Used to verify that the other remaining parts are deleted after
|
// Used to verify that the other remaining parts are deleted after
|
||||||
// a successful call to CompleteMultipartUpload.
|
// a successful call to CompleteMultipartUpload.
|
||||||
{
|
{
|
||||||
[]completePart{
|
[]CompletePart{
|
||||||
{ETag: validPartMD5, PartNumber: 6},
|
{ETag: validPartMD5, PartNumber: 6},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1887,7 +1887,7 @@ func testObjectCompleteMultipartUpload(obj ObjectLayer, instanceType string, t T
|
|||||||
bucket string
|
bucket string
|
||||||
object string
|
object string
|
||||||
uploadID string
|
uploadID string
|
||||||
parts []completePart
|
parts []CompletePart
|
||||||
// Expected output of CompleteMultipartUpload.
|
// Expected output of CompleteMultipartUpload.
|
||||||
expectedS3MD5 string
|
expectedS3MD5 string
|
||||||
expectedErr error
|
expectedErr error
|
||||||
@ -1895,28 +1895,28 @@ func testObjectCompleteMultipartUpload(obj ObjectLayer, instanceType string, t T
|
|||||||
shouldPass bool
|
shouldPass bool
|
||||||
}{
|
}{
|
||||||
// Test cases with invalid bucket names (Test number 1-4).
|
// Test cases with invalid bucket names (Test number 1-4).
|
||||||
{".test", "", "", []completePart{}, "", BucketNameInvalid{Bucket: ".test"}, false},
|
{".test", "", "", []CompletePart{}, "", BucketNameInvalid{Bucket: ".test"}, false},
|
||||||
{"Test", "", "", []completePart{}, "", BucketNameInvalid{Bucket: "Test"}, false},
|
{"Test", "", "", []CompletePart{}, "", BucketNameInvalid{Bucket: "Test"}, false},
|
||||||
{"---", "", "", []completePart{}, "", BucketNameInvalid{Bucket: "---"}, false},
|
{"---", "", "", []CompletePart{}, "", BucketNameInvalid{Bucket: "---"}, false},
|
||||||
{"ad", "", "", []completePart{}, "", BucketNameInvalid{Bucket: "ad"}, false},
|
{"ad", "", "", []CompletePart{}, "", BucketNameInvalid{Bucket: "ad"}, false},
|
||||||
// Test cases for listing uploadID with single part.
|
// Test cases for listing uploadID with single part.
|
||||||
// Valid bucket names, but they donot exist (Test number 5-7).
|
// Valid bucket names, but they donot exist (Test number 5-7).
|
||||||
{"volatile-bucket-1", "", "", []completePart{}, "", BucketNotFound{Bucket: "volatile-bucket-1"}, false},
|
{"volatile-bucket-1", "", "", []CompletePart{}, "", BucketNotFound{Bucket: "volatile-bucket-1"}, false},
|
||||||
{"volatile-bucket-2", "", "", []completePart{}, "", BucketNotFound{Bucket: "volatile-bucket-2"}, false},
|
{"volatile-bucket-2", "", "", []CompletePart{}, "", BucketNotFound{Bucket: "volatile-bucket-2"}, false},
|
||||||
{"volatile-bucket-3", "", "", []completePart{}, "", BucketNotFound{Bucket: "volatile-bucket-3"}, false},
|
{"volatile-bucket-3", "", "", []CompletePart{}, "", BucketNotFound{Bucket: "volatile-bucket-3"}, false},
|
||||||
// Test case for Asserting for invalid objectName (Test number 8).
|
// Test case for Asserting for invalid objectName (Test number 8).
|
||||||
{bucketNames[0], "", "", []completePart{}, "", ObjectNameInvalid{Bucket: bucketNames[0]}, false},
|
{bucketNames[0], "", "", []CompletePart{}, "", ObjectNameInvalid{Bucket: bucketNames[0]}, false},
|
||||||
// Asserting for Invalid UploadID (Test number 9).
|
// Asserting for Invalid UploadID (Test number 9).
|
||||||
{bucketNames[0], objectNames[0], "abc", []completePart{}, "", InvalidUploadID{UploadID: "abc"}, false},
|
{bucketNames[0], objectNames[0], "abc", []CompletePart{}, "", InvalidUploadID{UploadID: "abc"}, false},
|
||||||
// Test case with invalid Part Etag (Test number 10-11).
|
// Test case with invalid Part Etag (Test number 10-11).
|
||||||
{bucketNames[0], objectNames[0], uploadIDs[0], []completePart{{ETag: "abc"}}, "", fmt.Errorf("encoding/hex: odd length hex string"), false},
|
{bucketNames[0], objectNames[0], uploadIDs[0], []CompletePart{{ETag: "abc"}}, "", fmt.Errorf("encoding/hex: odd length hex string"), false},
|
||||||
{bucketNames[0], objectNames[0], uploadIDs[0], []completePart{{ETag: "abcz"}}, "", fmt.Errorf("encoding/hex: invalid byte: U+007A 'z'"), false},
|
{bucketNames[0], objectNames[0], uploadIDs[0], []CompletePart{{ETag: "abcz"}}, "", fmt.Errorf("encoding/hex: invalid byte: U+007A 'z'"), false},
|
||||||
// Part number 0 doesn't exist, expecting InvalidPart error (Test number 12).
|
// Part number 0 doesn't exist, expecting InvalidPart error (Test number 12).
|
||||||
{bucketNames[0], objectNames[0], uploadIDs[0], []completePart{{ETag: "abcd", PartNumber: 0}}, "", InvalidPart{}, false},
|
{bucketNames[0], objectNames[0], uploadIDs[0], []CompletePart{{ETag: "abcd", PartNumber: 0}}, "", InvalidPart{}, false},
|
||||||
// // Upload and PartNumber exists, But a deliberate ETag mismatch is introduced (Test number 13).
|
// // Upload and PartNumber exists, But a deliberate ETag mismatch is introduced (Test number 13).
|
||||||
{bucketNames[0], objectNames[0], uploadIDs[0], inputParts[0].parts, "", InvalidPart{}, false},
|
{bucketNames[0], objectNames[0], uploadIDs[0], inputParts[0].parts, "", InvalidPart{}, false},
|
||||||
// Test case with non existent object name (Test number 14).
|
// Test case with non existent object name (Test number 14).
|
||||||
{bucketNames[0], "my-object", uploadIDs[0], []completePart{{ETag: "abcd", PartNumber: 1}}, "", InvalidUploadID{UploadID: uploadIDs[0]}, false},
|
{bucketNames[0], "my-object", uploadIDs[0], []CompletePart{{ETag: "abcd", PartNumber: 1}}, "", InvalidUploadID{UploadID: uploadIDs[0]}, false},
|
||||||
// Testing for Part being too small (Test number 15).
|
// Testing for Part being too small (Test number 15).
|
||||||
{bucketNames[0], objectNames[0], uploadIDs[0], inputParts[1].parts, "", PartTooSmall{PartNumber: 1}, false},
|
{bucketNames[0], objectNames[0], uploadIDs[0], inputParts[1].parts, "", PartTooSmall{PartNumber: 1}, false},
|
||||||
// TestCase with invalid Part Number (Test number 16).
|
// TestCase with invalid Part Number (Test number 16).
|
||||||
@ -1924,7 +1924,7 @@ func testObjectCompleteMultipartUpload(obj ObjectLayer, instanceType string, t T
|
|||||||
{bucketNames[0], objectNames[0], uploadIDs[0], inputParts[2].parts, "", InvalidPart{}, false},
|
{bucketNames[0], objectNames[0], uploadIDs[0], inputParts[2].parts, "", InvalidPart{}, false},
|
||||||
// Test case with unsorted parts (Test number 17).
|
// Test case with unsorted parts (Test number 17).
|
||||||
{bucketNames[0], objectNames[0], uploadIDs[0], inputParts[3].parts, s3MD5, nil, true},
|
{bucketNames[0], objectNames[0], uploadIDs[0], inputParts[3].parts, s3MD5, nil, true},
|
||||||
// The other parts will be flushed after a successful completePart (Test number 18).
|
// The other parts will be flushed after a successful CompletePart (Test number 18).
|
||||||
// the case above successfully completes CompleteMultipartUpload, the remaining Parts will be flushed.
|
// the case above successfully completes CompleteMultipartUpload, the remaining Parts will be flushed.
|
||||||
// Expecting to fail with Invalid UploadID.
|
// Expecting to fail with Invalid UploadID.
|
||||||
{bucketNames[0], objectNames[0], uploadIDs[0], inputParts[4].parts, "", InvalidUploadID{UploadID: uploadIDs[0]}, false},
|
{bucketNames[0], objectNames[0], uploadIDs[0], inputParts[4].parts, "", InvalidUploadID{UploadID: uploadIDs[0]}, false},
|
||||||
|
@ -381,7 +381,7 @@ func testObjectAPIMultipartPutObjectStaleFiles(obj ObjectLayer, instanceType str
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Complete multipart.
|
// Complete multipart.
|
||||||
parts := []completePart{
|
parts := []CompletePart{
|
||||||
{ETag: etag1, PartNumber: 1},
|
{ETag: etag1, PartNumber: 1},
|
||||||
{ETag: etag2, PartNumber: 2},
|
{ETag: etag2, PartNumber: 2},
|
||||||
}
|
}
|
||||||
|
@ -173,7 +173,7 @@ func mustGetUUID() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create an s3 compatible MD5sum for complete multipart transaction.
|
// Create an s3 compatible MD5sum for complete multipart transaction.
|
||||||
func getCompleteMultipartMD5(parts []completePart) (string, error) {
|
func getCompleteMultipartMD5(parts []CompletePart) (string, error) {
|
||||||
var finalMD5Bytes []byte
|
var finalMD5Bytes []byte
|
||||||
for _, part := range parts {
|
for _, part := range parts {
|
||||||
md5Bytes, err := hex.DecodeString(part.ETag)
|
md5Bytes, err := hex.DecodeString(part.ETag)
|
||||||
|
@ -132,18 +132,18 @@ func TestIsValidObjectName(t *testing.T) {
|
|||||||
// Tests getCompleteMultipartMD5
|
// Tests getCompleteMultipartMD5
|
||||||
func TestGetCompleteMultipartMD5(t *testing.T) {
|
func TestGetCompleteMultipartMD5(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
parts []completePart
|
parts []CompletePart
|
||||||
expectedResult string
|
expectedResult string
|
||||||
expectedErr string
|
expectedErr string
|
||||||
}{
|
}{
|
||||||
// Wrong MD5 hash string
|
// Wrong MD5 hash string
|
||||||
{[]completePart{{ETag: "wrong-md5-hash-string"}}, "", "encoding/hex: odd length hex string"},
|
{[]CompletePart{{ETag: "wrong-md5-hash-string"}}, "", "encoding/hex: odd length hex string"},
|
||||||
|
|
||||||
// Single completePart with valid MD5 hash string.
|
// Single CompletePart with valid MD5 hash string.
|
||||||
{[]completePart{{ETag: "cf1f738a5924e645913c984e0fe3d708"}}, "10dc1617fbcf0bd0858048cb96e6bd77-1", ""},
|
{[]CompletePart{{ETag: "cf1f738a5924e645913c984e0fe3d708"}}, "10dc1617fbcf0bd0858048cb96e6bd77-1", ""},
|
||||||
|
|
||||||
// Multiple completePart with valid MD5 hash string.
|
// Multiple CompletePart with valid MD5 hash string.
|
||||||
{[]completePart{{ETag: "cf1f738a5924e645913c984e0fe3d708"}, {ETag: "9ccbc9a80eee7fb6fdd22441db2aedbd"}}, "0239a86b5266bb624f0ac60ba2aed6c8-2", ""},
|
{[]CompletePart{{ETag: "cf1f738a5924e645913c984e0fe3d708"}, {ETag: "9ccbc9a80eee7fb6fdd22441db2aedbd"}}, "0239a86b5266bb624f0ac60ba2aed6c8-2", ""},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, test := range testCases {
|
for i, test := range testCases {
|
||||||
|
@ -1026,7 +1026,7 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite
|
|||||||
writeErrorResponse(w, ErrInternalError, r.URL)
|
writeErrorResponse(w, ErrInternalError, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
complMultipartUpload := &completeMultipartUpload{}
|
complMultipartUpload := &CompleteMultipartUpload{}
|
||||||
if err = xml.Unmarshal(completeMultipartBytes, complMultipartUpload); err != nil {
|
if err = xml.Unmarshal(completeMultipartBytes, complMultipartUpload); err != nil {
|
||||||
errorIf(err, "Unable to parse complete multipart upload XML.")
|
errorIf(err, "Unable to parse complete multipart upload XML.")
|
||||||
writeErrorResponse(w, ErrMalformedXML, r.URL)
|
writeErrorResponse(w, ErrMalformedXML, r.URL)
|
||||||
@ -1036,13 +1036,13 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite
|
|||||||
writeErrorResponse(w, ErrMalformedXML, r.URL)
|
writeErrorResponse(w, ErrMalformedXML, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !sort.IsSorted(completedParts(complMultipartUpload.Parts)) {
|
if !sort.IsSorted(CompletedParts(complMultipartUpload.Parts)) {
|
||||||
writeErrorResponse(w, ErrInvalidPartOrder, r.URL)
|
writeErrorResponse(w, ErrInvalidPartOrder, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Complete parts.
|
// Complete parts.
|
||||||
var completeParts []completePart
|
var completeParts []CompletePart
|
||||||
for _, part := range complMultipartUpload.Parts {
|
for _, part := range complMultipartUpload.Parts {
|
||||||
part.ETag = canonicalizeETag(part.ETag)
|
part.ETag = canonicalizeETag(part.ETag)
|
||||||
completeParts = append(completeParts, part)
|
completeParts = append(completeParts, part)
|
||||||
|
@ -1078,7 +1078,7 @@ func testAPICopyObjectPartHandlerSanity(obj ObjectLayer, instanceType, bucketNam
|
|||||||
|
|
||||||
a := 0
|
a := 0
|
||||||
b := globalMinPartSize - 1
|
b := globalMinPartSize - 1
|
||||||
var parts []completePart
|
var parts []CompletePart
|
||||||
for partNumber := 1; partNumber <= 2; partNumber++ {
|
for partNumber := 1; partNumber <= 2; partNumber++ {
|
||||||
// initialize HTTP NewRecorder, this records any mutations to response writer inside the handler.
|
// initialize HTTP NewRecorder, this records any mutations to response writer inside the handler.
|
||||||
rec := httptest.NewRecorder()
|
rec := httptest.NewRecorder()
|
||||||
@ -1109,7 +1109,7 @@ func testAPICopyObjectPartHandlerSanity(obj ObjectLayer, instanceType, bucketNam
|
|||||||
t.Fatalf("Test failed to decode XML response: <ERROR> %v", err)
|
t.Fatalf("Test failed to decode XML response: <ERROR> %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
parts = append(parts, completePart{
|
parts = append(parts, CompletePart{
|
||||||
PartNumber: partNumber,
|
PartNumber: partNumber,
|
||||||
ETag: canonicalizeETag(resp.ETag),
|
ETag: canonicalizeETag(resp.ETag),
|
||||||
})
|
})
|
||||||
@ -2162,19 +2162,19 @@ func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName s
|
|||||||
}
|
}
|
||||||
// Parts to be sent as input for CompleteMultipartUpload.
|
// Parts to be sent as input for CompleteMultipartUpload.
|
||||||
inputParts := []struct {
|
inputParts := []struct {
|
||||||
parts []completePart
|
parts []CompletePart
|
||||||
}{
|
}{
|
||||||
// inputParts - 0.
|
// inputParts - 0.
|
||||||
// Case for replicating ETag mismatch.
|
// Case for replicating ETag mismatch.
|
||||||
{
|
{
|
||||||
[]completePart{
|
[]CompletePart{
|
||||||
{ETag: "abcd", PartNumber: 1},
|
{ETag: "abcd", PartNumber: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// inputParts - 1.
|
// inputParts - 1.
|
||||||
// should error out with part too small.
|
// should error out with part too small.
|
||||||
{
|
{
|
||||||
[]completePart{
|
[]CompletePart{
|
||||||
{ETag: "e2fc714c4727ee9395f324cd2e7f331f", PartNumber: 1},
|
{ETag: "e2fc714c4727ee9395f324cd2e7f331f", PartNumber: 1},
|
||||||
{ETag: "1f7690ebdd9b4caf8fab49ca1757bf27", PartNumber: 2},
|
{ETag: "1f7690ebdd9b4caf8fab49ca1757bf27", PartNumber: 2},
|
||||||
},
|
},
|
||||||
@ -2182,7 +2182,7 @@ func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName s
|
|||||||
// inputParts - 2.
|
// inputParts - 2.
|
||||||
// Case with invalid Part number.
|
// Case with invalid Part number.
|
||||||
{
|
{
|
||||||
[]completePart{
|
[]CompletePart{
|
||||||
{ETag: "e2fc714c4727ee9395f324cd2e7f331f", PartNumber: 10},
|
{ETag: "e2fc714c4727ee9395f324cd2e7f331f", PartNumber: 10},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -2190,7 +2190,7 @@ func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName s
|
|||||||
// Case with valid parts,but parts are unsorted.
|
// Case with valid parts,but parts are unsorted.
|
||||||
// Part size greater than 5 MiB.
|
// Part size greater than 5 MiB.
|
||||||
{
|
{
|
||||||
[]completePart{
|
[]CompletePart{
|
||||||
{ETag: validPartMD5, PartNumber: 6},
|
{ETag: validPartMD5, PartNumber: 6},
|
||||||
{ETag: validPartMD5, PartNumber: 5},
|
{ETag: validPartMD5, PartNumber: 5},
|
||||||
},
|
},
|
||||||
@ -2199,7 +2199,7 @@ func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName s
|
|||||||
// Case with valid part.
|
// Case with valid part.
|
||||||
// Part size greater than 5 MiB.
|
// Part size greater than 5 MiB.
|
||||||
{
|
{
|
||||||
[]completePart{
|
[]CompletePart{
|
||||||
{ETag: validPartMD5, PartNumber: 5},
|
{ETag: validPartMD5, PartNumber: 5},
|
||||||
{ETag: validPartMD5, PartNumber: 6},
|
{ETag: validPartMD5, PartNumber: 6},
|
||||||
},
|
},
|
||||||
@ -2209,7 +2209,7 @@ func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName s
|
|||||||
// Used for the case of testing for anonymous API request.
|
// Used for the case of testing for anonymous API request.
|
||||||
// Part size greater than 5 MiB.
|
// Part size greater than 5 MiB.
|
||||||
{
|
{
|
||||||
[]completePart{
|
[]CompletePart{
|
||||||
{ETag: validPartMD5, PartNumber: 1},
|
{ETag: validPartMD5, PartNumber: 1},
|
||||||
{ETag: validPartMD5, PartNumber: 2},
|
{ETag: validPartMD5, PartNumber: 2},
|
||||||
},
|
},
|
||||||
@ -2230,7 +2230,7 @@ func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName s
|
|||||||
bucket string
|
bucket string
|
||||||
object string
|
object string
|
||||||
uploadID string
|
uploadID string
|
||||||
parts []completePart
|
parts []CompletePart
|
||||||
accessKey string
|
accessKey string
|
||||||
secretKey string
|
secretKey string
|
||||||
// Expected output of CompleteMultipartUpload.
|
// Expected output of CompleteMultipartUpload.
|
||||||
@ -2253,13 +2253,13 @@ func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName s
|
|||||||
expectedRespStatus: http.StatusBadRequest,
|
expectedRespStatus: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
// Test case - 2.
|
// Test case - 2.
|
||||||
// No parts specified in completePart{}.
|
// No parts specified in CompletePart{}.
|
||||||
// Should return ErrMalformedXML in the response body.
|
// Should return ErrMalformedXML in the response body.
|
||||||
{
|
{
|
||||||
bucket: bucketName,
|
bucket: bucketName,
|
||||||
object: objectName,
|
object: objectName,
|
||||||
uploadID: uploadIDs[0],
|
uploadID: uploadIDs[0],
|
||||||
parts: []completePart{},
|
parts: []CompletePart{},
|
||||||
accessKey: credentials.AccessKey,
|
accessKey: credentials.AccessKey,
|
||||||
secretKey: credentials.SecretKey,
|
secretKey: credentials.SecretKey,
|
||||||
|
|
||||||
@ -2361,14 +2361,14 @@ func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName s
|
|||||||
var req *http.Request
|
var req *http.Request
|
||||||
var completeBytes, actualContent []byte
|
var completeBytes, actualContent []byte
|
||||||
// Complete multipart upload parts.
|
// Complete multipart upload parts.
|
||||||
completeUploads := &completeMultipartUpload{
|
completeUploads := &CompleteMultipartUpload{
|
||||||
Parts: testCase.parts,
|
Parts: testCase.parts,
|
||||||
}
|
}
|
||||||
completeBytes, err = xml.Marshal(completeUploads)
|
completeBytes, err = xml.Marshal(completeUploads)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error XML encoding of parts: <ERROR> %s.", err)
|
t.Fatalf("Error XML encoding of parts: <ERROR> %s.", err)
|
||||||
}
|
}
|
||||||
// Indicating that all parts are uploaded and initiating completeMultipartUpload.
|
// Indicating that all parts are uploaded and initiating CompleteMultipartUpload.
|
||||||
req, err = newTestSignedRequestV4("POST", getCompleteMultipartUploadURL("", bucketName, objectName, testCase.uploadID),
|
req, err = newTestSignedRequestV4("POST", getCompleteMultipartUploadURL("", bucketName, objectName, testCase.uploadID),
|
||||||
int64(len(completeBytes)), bytes.NewReader(completeBytes), testCase.accessKey, testCase.secretKey)
|
int64(len(completeBytes)), bytes.NewReader(completeBytes), testCase.accessKey, testCase.secretKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -2400,7 +2400,7 @@ func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName s
|
|||||||
// Testing for anonymous API request.
|
// Testing for anonymous API request.
|
||||||
var completeBytes []byte
|
var completeBytes []byte
|
||||||
// Complete multipart upload parts.
|
// Complete multipart upload parts.
|
||||||
completeUploads := &completeMultipartUpload{
|
completeUploads := &CompleteMultipartUpload{
|
||||||
Parts: inputParts[5].parts,
|
Parts: inputParts[5].parts,
|
||||||
}
|
}
|
||||||
completeBytes, err = xml.Marshal(completeUploads)
|
completeBytes, err = xml.Marshal(completeUploads)
|
||||||
@ -2426,7 +2426,7 @@ func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName s
|
|||||||
// There is no need to use an existing bucket or valid input for creating the request,
|
// There is no need to use an existing bucket or valid input for creating the request,
|
||||||
// since the `objectLayer==nil` check is performed before any other checks inside the handlers.
|
// since the `objectLayer==nil` check is performed before any other checks inside the handlers.
|
||||||
// The only aim is to generate an HTTP request in a way that the relevant/registered end point is evoked/called.
|
// The only aim is to generate an HTTP request in a way that the relevant/registered end point is evoked/called.
|
||||||
// Indicating that all parts are uploaded and initiating completeMultipartUpload.
|
// Indicating that all parts are uploaded and initiating CompleteMultipartUpload.
|
||||||
nilBucket := "dummy-bucket"
|
nilBucket := "dummy-bucket"
|
||||||
nilObject := "dummy-object"
|
nilObject := "dummy-object"
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ func testMultipartObjectCreation(obj ObjectLayer, instanceType string, t TestErr
|
|||||||
}
|
}
|
||||||
// Create a byte array of 5MiB.
|
// Create a byte array of 5MiB.
|
||||||
data := bytes.Repeat([]byte("0123456789abcdef"), 5*humanize.MiByte/16)
|
data := bytes.Repeat([]byte("0123456789abcdef"), 5*humanize.MiByte/16)
|
||||||
completedParts := completeMultipartUpload{}
|
completedParts := CompleteMultipartUpload{}
|
||||||
for i := 1; i <= 10; i++ {
|
for i := 1; i <= 10; i++ {
|
||||||
expectedETaghex := getMD5Hash(data)
|
expectedETaghex := getMD5Hash(data)
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ func testMultipartObjectCreation(obj ObjectLayer, instanceType string, t TestErr
|
|||||||
if calcPartInfo.ETag != expectedETaghex {
|
if calcPartInfo.ETag != expectedETaghex {
|
||||||
t.Errorf("MD5 Mismatch")
|
t.Errorf("MD5 Mismatch")
|
||||||
}
|
}
|
||||||
completedParts.Parts = append(completedParts.Parts, completePart{
|
completedParts.Parts = append(completedParts.Parts, CompletePart{
|
||||||
PartNumber: i,
|
PartNumber: i,
|
||||||
ETag: calcPartInfo.ETag,
|
ETag: calcPartInfo.ETag,
|
||||||
})
|
})
|
||||||
|
@ -2730,8 +2730,8 @@ func (s *TestSuiteCommon) TestObjectMultipart(c *check) {
|
|||||||
c.Assert(response2.StatusCode, http.StatusOK)
|
c.Assert(response2.StatusCode, http.StatusOK)
|
||||||
|
|
||||||
// Complete multipart upload
|
// Complete multipart upload
|
||||||
completeUploads := &completeMultipartUpload{
|
completeUploads := &CompleteMultipartUpload{
|
||||||
Parts: []completePart{
|
Parts: []CompletePart{
|
||||||
{
|
{
|
||||||
PartNumber: 1,
|
PartNumber: 1,
|
||||||
ETag: response1.Header.Get("ETag"),
|
ETag: response1.Header.Get("ETag"),
|
||||||
@ -2745,7 +2745,7 @@ func (s *TestSuiteCommon) TestObjectMultipart(c *check) {
|
|||||||
|
|
||||||
completeBytes, err := xml.Marshal(completeUploads)
|
completeBytes, err := xml.Marshal(completeUploads)
|
||||||
c.Assert(err, nil)
|
c.Assert(err, nil)
|
||||||
// Indicating that all parts are uploaded and initiating completeMultipartUpload.
|
// Indicating that all parts are uploaded and initiating CompleteMultipartUpload.
|
||||||
request, err = newTestSignedRequest("POST", getCompleteMultipartUploadURL(s.endPoint, bucketName, objectName, uploadID),
|
request, err = newTestSignedRequest("POST", getCompleteMultipartUploadURL(s.endPoint, bucketName, objectName, uploadID),
|
||||||
int64(len(completeBytes)), bytes.NewReader(completeBytes), s.accessKey, s.secretKey, s.signer)
|
int64(len(completeBytes)), bytes.NewReader(completeBytes), s.accessKey, s.secretKey, s.signer)
|
||||||
c.Assert(err, nil)
|
c.Assert(err, nil)
|
||||||
@ -2754,7 +2754,7 @@ func (s *TestSuiteCommon) TestObjectMultipart(c *check) {
|
|||||||
c.Assert(err, nil)
|
c.Assert(err, nil)
|
||||||
// verify whether complete multipart was successful.
|
// verify whether complete multipart was successful.
|
||||||
c.Assert(response.StatusCode, http.StatusOK)
|
c.Assert(response.StatusCode, http.StatusOK)
|
||||||
var parts []completePart
|
var parts []CompletePart
|
||||||
for _, part := range completeUploads.Parts {
|
for _, part := range completeUploads.Parts {
|
||||||
part.ETag = canonicalizeETag(part.ETag)
|
part.ETag = canonicalizeETag(part.ETag)
|
||||||
parts = append(parts, part)
|
parts = append(parts, part)
|
||||||
|
@ -489,13 +489,13 @@ func TestHealObjectXL(t *testing.T) {
|
|||||||
t.Fatalf("Failed to create a multipart upload - %v", err)
|
t.Fatalf("Failed to create a multipart upload - %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var uploadedParts []completePart
|
var uploadedParts []CompletePart
|
||||||
for _, partID := range []int{2, 1} {
|
for _, partID := range []int{2, 1} {
|
||||||
pInfo, err1 := obj.PutObjectPart(bucket, object, uploadID, partID, mustGetHashReader(t, bytes.NewReader(data), int64(len(data)), "", ""))
|
pInfo, err1 := obj.PutObjectPart(bucket, object, uploadID, partID, mustGetHashReader(t, bytes.NewReader(data), int64(len(data)), "", ""))
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
t.Fatalf("Failed to upload a part - %v", err1)
|
t.Fatalf("Failed to upload a part - %v", err1)
|
||||||
}
|
}
|
||||||
uploadedParts = append(uploadedParts, completePart{
|
uploadedParts = append(uploadedParts, CompletePart{
|
||||||
PartNumber: pInfo.PartNumber,
|
PartNumber: pInfo.PartNumber,
|
||||||
ETag: pInfo.ETag,
|
ETag: pInfo.ETag,
|
||||||
})
|
})
|
||||||
|
@ -222,7 +222,7 @@ func (xl xlObjects) ListUploadsHeal(bucket, prefix, marker, uploadIDMarker,
|
|||||||
|
|
||||||
// Fetches list of multipart uploadIDs given bucket, keyMarker, uploadIDMarker.
|
// Fetches list of multipart uploadIDs given bucket, keyMarker, uploadIDMarker.
|
||||||
func fetchMultipartUploadIDs(bucket, keyMarker, uploadIDMarker string,
|
func fetchMultipartUploadIDs(bucket, keyMarker, uploadIDMarker string,
|
||||||
maxUploads int, disks []StorageAPI) (uploads []uploadMetadata, end bool,
|
maxUploads int, disks []StorageAPI) (uploads []MultipartInfo, end bool,
|
||||||
err error) {
|
err error) {
|
||||||
|
|
||||||
// Hold a read lock on keyMarker path.
|
// Hold a read lock on keyMarker path.
|
||||||
@ -261,7 +261,7 @@ func (xl xlObjects) listMultipartUploadsHeal(bucket, prefix, keyMarker,
|
|||||||
|
|
||||||
recursive := delimiter != slashSeparator
|
recursive := delimiter != slashSeparator
|
||||||
|
|
||||||
var uploads []uploadMetadata
|
var uploads []MultipartInfo
|
||||||
var err error
|
var err error
|
||||||
// List all upload ids for the given keyMarker, starting from
|
// List all upload ids for the given keyMarker, starting from
|
||||||
// uploadIDMarker.
|
// uploadIDMarker.
|
||||||
@ -332,7 +332,7 @@ func (xl xlObjects) listMultipartUploadsHeal(bucket, prefix, keyMarker,
|
|||||||
retainSlash(bucket))
|
retainSlash(bucket))
|
||||||
// Skip entries that are not object directory.
|
// Skip entries that are not object directory.
|
||||||
if hasSuffix(walkResult.entry, slashSeparator) {
|
if hasSuffix(walkResult.entry, slashSeparator) {
|
||||||
uploads = append(uploads, uploadMetadata{
|
uploads = append(uploads, MultipartInfo{
|
||||||
Object: entry,
|
Object: entry,
|
||||||
})
|
})
|
||||||
uploadsLeft--
|
uploadsLeft--
|
||||||
@ -344,7 +344,7 @@ func (xl xlObjects) listMultipartUploadsHeal(bucket, prefix, keyMarker,
|
|||||||
|
|
||||||
// For an object entry we get all its pending
|
// For an object entry we get all its pending
|
||||||
// uploadIDs.
|
// uploadIDs.
|
||||||
var newUploads []uploadMetadata
|
var newUploads []MultipartInfo
|
||||||
var end bool
|
var end bool
|
||||||
uploadIDMarker = ""
|
uploadIDMarker = ""
|
||||||
newUploads, end, err = fetchMultipartUploadIDs(bucket, entry, uploadIDMarker,
|
newUploads, end, err = fetchMultipartUploadIDs(bucket, entry, uploadIDMarker,
|
||||||
|
@ -297,7 +297,7 @@ func (xl xlObjects) listMultipartUploads(bucket, prefix, keyMarker, uploadIDMark
|
|||||||
if keyMarker != "" {
|
if keyMarker != "" {
|
||||||
multipartMarkerPath = pathJoin(bucket, keyMarker)
|
multipartMarkerPath = pathJoin(bucket, keyMarker)
|
||||||
}
|
}
|
||||||
var uploads []uploadMetadata
|
var uploads []MultipartInfo
|
||||||
var err error
|
var err error
|
||||||
var eof bool
|
var eof bool
|
||||||
// List all upload ids for the keyMarker starting from
|
// List all upload ids for the keyMarker starting from
|
||||||
@ -356,7 +356,7 @@ func (xl xlObjects) listMultipartUploads(bucket, prefix, keyMarker, uploadIDMark
|
|||||||
// For an entry looking like a directory, store and
|
// For an entry looking like a directory, store and
|
||||||
// continue the loop not need to fetch uploads.
|
// continue the loop not need to fetch uploads.
|
||||||
if hasSuffix(walkResult.entry, slashSeparator) {
|
if hasSuffix(walkResult.entry, slashSeparator) {
|
||||||
uploads = append(uploads, uploadMetadata{
|
uploads = append(uploads, MultipartInfo{
|
||||||
Object: entry,
|
Object: entry,
|
||||||
})
|
})
|
||||||
maxUploads--
|
maxUploads--
|
||||||
@ -366,7 +366,7 @@ func (xl xlObjects) listMultipartUploads(bucket, prefix, keyMarker, uploadIDMark
|
|||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var newUploads []uploadMetadata
|
var newUploads []MultipartInfo
|
||||||
var end bool
|
var end bool
|
||||||
uploadIDMarker = ""
|
uploadIDMarker = ""
|
||||||
|
|
||||||
@ -832,7 +832,7 @@ func (xl xlObjects) ListObjectParts(bucket, object, uploadID string, partNumberM
|
|||||||
// md5sums of all the parts.
|
// md5sums of all the parts.
|
||||||
//
|
//
|
||||||
// Implements S3 compatible Complete multipart API.
|
// Implements S3 compatible Complete multipart API.
|
||||||
func (xl xlObjects) CompleteMultipartUpload(bucket string, object string, uploadID string, parts []completePart) (oi ObjectInfo, e error) {
|
func (xl xlObjects) CompleteMultipartUpload(bucket string, object string, uploadID string, parts []CompletePart) (oi ObjectInfo, e error) {
|
||||||
if err := checkCompleteMultipartArgs(bucket, object, xl); err != nil {
|
if err := checkCompleteMultipartArgs(bucket, object, xl); err != nil {
|
||||||
return oi, err
|
return oi, err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user