From 8287ab091cc35c903ebb82d597d5d05adb5187d4 Mon Sep 17 00:00:00 2001 From: Nitish Tiwari Date: Thu, 19 Oct 2017 02:56:20 +0530 Subject: [PATCH] Ignore file not found error for multipart-uploads (#5065) Dont print the error errFileNotFound, as it is expected that concurrent complete-multipart-uploads or abort-multipart-uploads would have deleted the file, and the file may not be found Fixes: https://github.com/minio/minio/issues/5056 --- cmd/fs-v1-multipart.go | 16 +++++++-- cmd/fs-v1-multipart_test.go | 66 +++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/cmd/fs-v1-multipart.go b/cmd/fs-v1-multipart.go index cb0e38e40..7daf3c111 100644 --- a/cmd/fs-v1-multipart.go +++ b/cmd/fs-v1-multipart.go @@ -744,7 +744,13 @@ func (fs fsObjects) CompleteMultipartUpload(bucket string, object string, upload if removeObjectDir { basePath := pathJoin(fs.fsPath, minioMetaMultipartBucket, bucket) derr := fsDeleteFile(basePath, pathJoin(basePath, object)) - errorIf(derr, "unable to remove %s in %s", pathJoin(basePath, object), basePath) + if derr = errorCause(derr); derr != nil { + // In parallel execution, CompleteMultipartUpload could have deleted temporary + // state files/directory, it is safe to ignore errFileNotFound + if derr != errFileNotFound { + errorIf(derr, "unable to remove %s in %s", pathJoin(basePath, object), basePath) + } + } } objectMPartPathLock.Unlock() }() @@ -979,7 +985,13 @@ func (fs fsObjects) AbortMultipartUpload(bucket, object, uploadID string) error if removeObjectDir { basePath := pathJoin(fs.fsPath, minioMetaMultipartBucket, bucket) derr := fsDeleteFile(basePath, pathJoin(basePath, object)) - errorIf(derr, "unable to remove %s in %s", pathJoin(basePath, object), basePath) + if derr = errorCause(derr); derr != nil { + // In parallel execution, AbortMultipartUpload could have deleted temporary + // state files/directory, it is safe to ignore errFileNotFound + if derr != errFileNotFound { + errorIf(derr, "unable to remove %s in %s", pathJoin(basePath, object), basePath) + } + } } objectMPartPathLock.Unlock() }() diff --git a/cmd/fs-v1-multipart_test.go b/cmd/fs-v1-multipart_test.go index 78b426358..299b4d168 100644 --- a/cmd/fs-v1-multipart_test.go +++ b/cmd/fs-v1-multipart_test.go @@ -226,6 +226,72 @@ func TestCompleteMultipartUploadFaultyDisk(t *testing.T) { } } +// TestCompleteMultipartUploadFaultyDisk - test CompleteMultipartUpload with faulty disks +func TestCompleteMultipartUpload(t *testing.T) { + // Prepare for tests + disk := filepath.Join(globalTestTmpDir, "minio-"+nextSuffix()) + defer os.RemoveAll(disk) + obj := initFSObjects(disk, t) + + fs := obj.(*fsObjects) + bucketName := "bucket" + objectName := "object" + data := []byte("12345") + + if err := obj.MakeBucketWithLocation(bucketName, ""); err != nil { + t.Fatal("Cannot create bucket, err: ", err) + } + + uploadID, err := fs.NewMultipartUpload(bucketName, objectName, map[string]string{"X-Amz-Meta-xid": "3f"}) + if err != nil { + t.Fatal("Unexpected error ", err) + } + + md5Hex := getMD5Hash(data) + + if _, err := fs.PutObjectPart(bucketName, objectName, uploadID, 1, NewHashReader(bytes.NewReader(data), 5, md5Hex, "")); err != nil { + t.Fatal("Unexpected error ", err) + } + + parts := []completePart{{PartNumber: 1, ETag: md5Hex}} + + if _, err := fs.CompleteMultipartUpload(bucketName, objectName, uploadID, parts); err != nil { + t.Fatal("Unexpected error ", err) + } +} + +// TestCompleteMultipartUploadFaultyDisk - test CompleteMultipartUpload with faulty disks +func TestAbortMultipartUpload(t *testing.T) { + // Prepare for tests + disk := filepath.Join(globalTestTmpDir, "minio-"+nextSuffix()) + defer os.RemoveAll(disk) + obj := initFSObjects(disk, t) + + fs := obj.(*fsObjects) + bucketName := "bucket" + objectName := "object" + data := []byte("12345") + + if err := obj.MakeBucketWithLocation(bucketName, ""); err != nil { + t.Fatal("Cannot create bucket, err: ", err) + } + + uploadID, err := fs.NewMultipartUpload(bucketName, objectName, map[string]string{"X-Amz-Meta-xid": "3f"}) + if err != nil { + t.Fatal("Unexpected error ", err) + } + + md5Hex := getMD5Hash(data) + + if _, err := fs.PutObjectPart(bucketName, objectName, uploadID, 1, NewHashReader(bytes.NewReader(data), 5, md5Hex, "")); err != nil { + t.Fatal("Unexpected error ", err) + } + + if err := fs.AbortMultipartUpload(bucketName, objectName, uploadID); err != nil { + t.Fatal("Unexpected error ", err) + } +} + // TestListMultipartUploadsFaultyDisk - test ListMultipartUploads with faulty disks func TestListMultipartUploadsFaultyDisk(t *testing.T) { // Prepare for tests