From 149c6ca0944abe4f6c4a3d0743190890094b0fde Mon Sep 17 00:00:00 2001 From: Krishna Srinivas Date: Sun, 17 Apr 2016 00:13:03 +0530 Subject: [PATCH] listMultipart: bugfixes. (#1318) --- object-api-multipart.go | 63 +++++++++++++++++++++++------------------ object-utils.go | 8 ++++++ 2 files changed, 43 insertions(+), 28 deletions(-) diff --git a/object-api-multipart.go b/object-api-multipart.go index eb60fe472..bbb442b17 100644 --- a/object-api-multipart.go +++ b/object-api-multipart.go @@ -31,8 +31,7 @@ import ( ) const ( - minioMetaVolume = ".minio" - slashPathSeparator = "/" + minioMetaVolume = ".minio" ) // checkLeafDirectory - verifies if a given path is leaf directory if @@ -109,14 +108,16 @@ func (o objectAPI) ListMultipartUploads(bucket, prefix, keyMarker, uploadIDMarke recursive = false } result.IsTruncated = true + result.MaxUploads = maxUploads newMaxUploads := 0 - prefixPath := path.Join(bucket, prefix) - if strings.HasSuffix(prefix, slashPathSeparator) { - // Add back the slash separator removed after 'path.Join'. - prefixPath = prefixPath + slashPathSeparator - } + // not using path.Join() as it strips off the trailing '/'. + // Also bucket should always be followed by '/' even if prefix is empty. + prefixPath := pathJoin(bucket, prefix) if recursive { - keyMarkerPath := path.Join(keyMarker, uploadIDMarker) + keyMarkerPath := "" + if keyMarker != "" { + keyMarkerPath = path.Join(bucket, keyMarker, uploadIDMarker) + } outerLoop: for { fileInfos, eof, e := o.storage.ListFiles(minioMetaVolume, prefixPath, keyMarkerPath, recursive, maxUploads-newMaxUploads) @@ -125,26 +126,31 @@ func (o objectAPI) ListMultipartUploads(bucket, prefix, keyMarker, uploadIDMarke } for _, fi := range fileInfos { keyMarkerPath = fi.Name - fileName := path.Base(fi.Name) - if strings.Contains(fileName, ".") { - // fileName contains partnumber and md5sum info, skip this. + // fi.Name will look like bucket/object/uploadID, extract object and uploadID. + uploadID := path.Base(fi.Name) + objectName := strings.TrimPrefix(path.Dir(fi.Name), bucket+slashPathSeparator) + if strings.Contains(uploadID, ".") { + // contains partnumber and md5sum info, skip this. continue } result.Uploads = append(result.Uploads, uploadMetadata{ - Object: path.Dir(fi.Name), - UploadID: fileName, + Object: objectName, + UploadID: uploadID, Initiated: fi.ModTime, }) - result.NextKeyMarker = path.Dir(fi.Name) - result.NextUploadIDMarker = fileName + result.NextKeyMarker = objectName + result.NextUploadIDMarker = uploadID newMaxUploads++ if newMaxUploads == maxUploads { + if eof { + result.IsTruncated = false + } break outerLoop } } if eof { result.IsTruncated = false - break outerLoop + break } } if !result.IsTruncated { @@ -176,21 +182,22 @@ func (o objectAPI) ListMultipartUploads(bucket, prefix, keyMarker, uploadIDMarke var uploads []uploadMetadata for _, fi := range fileInfos { leaf, entries := o.checkLeafDirectory(fi.Name) + objectName := strings.TrimPrefix(fi.Name, bucket+slashPathSeparator) if leaf { for _, entry := range entries { if strings.Contains(entry.Name, ".") { continue } uploads = append(uploads, uploadMetadata{ - Object: strings.TrimSuffix(fi.Name, slashPathSeparator), - UploadID: entry.Name, + Object: strings.TrimSuffix(objectName, slashPathSeparator), + UploadID: path.Base(entry.Name), Initiated: entry.ModTime, }) } continue } uploads = append(uploads, uploadMetadata{ - Object: fi.Name, + Object: objectName, }) } index := 0 @@ -199,27 +206,27 @@ func (o objectAPI) ListMultipartUploads(bucket, prefix, keyMarker, uploadIDMarke if upload.Object > keyMarker { break } - if uploads[index].Object == keyMarker && uploadIDMarker != "" { - if upload.UploadID > uploadIDMarker { - break - } + if uploads[index].Object == keyMarker && upload.UploadID > uploadIDMarker { + break } } for ; index < len(uploads); index++ { - newMaxUploads++ - if newMaxUploads == maxUploads { + if (len(result.Uploads) + len(result.CommonPrefixes)) == maxUploads { break } + result.NextKeyMarker = uploads[index].Object if strings.HasSuffix(uploads[index].Object, slashPathSeparator) { + // for a directory entry result.CommonPrefixes = append(result.CommonPrefixes, uploads[index].Object) continue } + result.NextUploadIDMarker = uploads[index].UploadID result.Uploads = append(result.Uploads, uploads[index]) } - result.MaxUploads = newMaxUploads - result.IsTruncated = true - if index >= len(uploads)-1 { + if index == len(uploads) { result.IsTruncated = false + result.NextKeyMarker = "" + result.NextUploadIDMarker = "" } return result, nil } diff --git a/object-utils.go b/object-utils.go index c8173d60b..9be07b0f8 100644 --- a/object-utils.go +++ b/object-utils.go @@ -22,6 +22,10 @@ import ( "unicode/utf8" ) +const ( + slashPathSeparator = "/" +) + // validBucket regexp. var validBucket = regexp.MustCompile(`^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$`) @@ -85,3 +89,7 @@ func IsValidObjectPrefix(object string) bool { return IsValidObjectName(object) } + +func pathJoin(path1 string, path2 string) string { + return strings.TrimSuffix(path1, slashPathSeparator) + slashPathSeparator + path2 +}