diff --git a/api-errors.go b/api-errors.go index 7cb6d5a7d..cc34c25a7 100644 --- a/api-errors.go +++ b/api-errors.go @@ -108,8 +108,8 @@ const ( // Add new error codes here. // Extended errors. - ErrInsufficientReadResources - ErrInsufficientWriteResources + ErrReadQuorum + ErrWriteQuorum ) // error code to APIError structure, these fields carry respective @@ -190,15 +190,15 @@ var errorCodeResponse = map[APIErrorCode]APIError{ Description: "We encountered an internal error, please try again.", HTTPStatusCode: http.StatusInternalServerError, }, - ErrInsufficientReadResources: { - Code: "InternalError", - Description: "We cannot satisfy sufficient read resources requested at this moment, please try again.", - HTTPStatusCode: http.StatusInternalServerError, + ErrReadQuorum: { + Code: "ReadQuorum", + Description: "Multiple disk failures, unable to reconstruct data.", + HTTPStatusCode: http.StatusServiceUnavailable, }, - ErrInsufficientWriteResources: { - Code: "InternalError", - Description: "We cannot satisfy sufficient write resources requested at this moment, please try again.", - HTTPStatusCode: http.StatusInternalServerError, + ErrWriteQuorum: { + Code: "WriteQuorum", + Description: "Multiple disks failures, unable to write data.", + HTTPStatusCode: http.StatusServiceUnavailable, }, ErrInvalidAccessKeyID: { Code: "InvalidAccessKeyID", @@ -418,6 +418,52 @@ var errorCodeResponse = map[APIErrorCode]APIError{ // Add your error structure here. } +// toAPIErrorCode - Converts embedded errors. Convenience +// function written to handle all cases where we have known types of +// errors returned by underlying layers. +func toAPIErrorCode(err error) (apiErr APIErrorCode) { + if err == nil { + return ErrNone + } + // Verify if the underlying error is signature mismatch. + if err == errSignatureMismatch { + return ErrSignatureDoesNotMatch + } + switch err.(type) { + case StorageFull: + apiErr = ErrStorageFull + case BadDigest: + apiErr = ErrBadDigest + case IncompleteBody: + apiErr = ErrIncompleteBody + case ObjectExistsAsPrefix: + apiErr = ErrObjectExistsAsPrefix + case BucketNameInvalid: + apiErr = ErrInvalidBucketName + case BucketNotFound: + apiErr = ErrNoSuchBucket + case BucketNotEmpty: + apiErr = ErrBucketNotEmpty + case BucketExists: + apiErr = ErrBucketAlreadyOwnedByYou + case ObjectNotFound: + apiErr = ErrNoSuchKey + case ObjectNameInvalid: + apiErr = ErrNoSuchKey + case InvalidUploadID: + apiErr = ErrNoSuchUpload + case InvalidPart: + apiErr = ErrInvalidPart + case InsufficientWriteQuorum: + apiErr = ErrWriteQuorum + case InsufficientReadQuorum: + apiErr = ErrReadQuorum + default: + apiErr = ErrInternalError + } + return apiErr +} + // getAPIError provides API Error for input API error code. func getAPIError(code APIErrorCode) APIError { return errorCodeResponse[code] diff --git a/bucket-handlers.go b/bucket-handlers.go index 3dd3e52a3..054cadcf2 100644 --- a/bucket-handlers.go +++ b/bucket-handlers.go @@ -118,14 +118,7 @@ func (api objectAPIHandlers) GetBucketLocationHandler(w http.ResponseWriter, r * if _, err := api.ObjectAPI.GetBucketInfo(bucket); err != nil { errorIf(err, "GetBucketInfo failed.", nil) - switch err.(type) { - case BucketNotFound: - writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path) - case BucketNameInvalid: - writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path) - default: - writeErrorResponse(w, r, ErrInternalError, r.URL.Path) - } + writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path) return } @@ -196,12 +189,7 @@ func (api objectAPIHandlers) ListMultipartUploadsHandler(w http.ResponseWriter, listMultipartsInfo, err := api.ObjectAPI.ListMultipartUploads(bucket, prefix, keyMarker, uploadIDMarker, delimiter, maxUploads) if err != nil { errorIf(err, "ListMultipartUploads failed.", nil) - switch err.(type) { - case BucketNotFound: - writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path) - default: - writeErrorResponse(w, r, ErrInternalError, r.URL.Path) - } + writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path) return } // generate response @@ -281,16 +269,7 @@ func (api objectAPIHandlers) ListObjectsHandler(w http.ResponseWriter, r *http.R return } errorIf(err, "ListObjects failed.", nil) - switch err.(type) { - case BucketNameInvalid: - writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path) - case BucketNotFound: - writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path) - case ObjectNameInvalid: - writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path) - default: - writeErrorResponse(w, r, ErrInternalError, r.URL.Path) - } + writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path) } // ListBucketsHandler - GET Service @@ -344,13 +323,7 @@ func (api objectAPIHandlers) ListBucketsHandler(w http.ResponseWriter, r *http.R return } errorIf(err, "ListBuckets failed.", nil) - switch err.(type) { - case StorageInsufficientReadResources: - writeErrorResponse(w, r, ErrInsufficientReadResources, r.URL.Path) - default: - writeErrorResponse(w, r, ErrInternalError, r.URL.Path) - } - + writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path) } // DeleteMultipleObjectsHandler - deletes multiple objects. @@ -419,38 +392,11 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter, }) } else { errorIf(err, "DeleteObject failed.", nil) - switch err.(type) { - case BucketNameInvalid: - deleteErrors = append(deleteErrors, DeleteError{ - Code: errorCodeResponse[ErrInvalidBucketName].Code, - Message: errorCodeResponse[ErrInvalidBucketName].Description, - Key: object.ObjectName, - }) - case BucketNotFound: - deleteErrors = append(deleteErrors, DeleteError{ - Code: errorCodeResponse[ErrNoSuchBucket].Code, - Message: errorCodeResponse[ErrNoSuchBucket].Description, - Key: object.ObjectName, - }) - case ObjectNotFound: - deleteErrors = append(deleteErrors, DeleteError{ - Code: errorCodeResponse[ErrNoSuchKey].Code, - Message: errorCodeResponse[ErrNoSuchKey].Description, - Key: object.ObjectName, - }) - case ObjectNameInvalid: - deleteErrors = append(deleteErrors, DeleteError{ - Code: errorCodeResponse[ErrNoSuchKey].Code, - Message: errorCodeResponse[ErrNoSuchKey].Description, - Key: object.ObjectName, - }) - default: - deleteErrors = append(deleteErrors, DeleteError{ - Code: errorCodeResponse[ErrInternalError].Code, - Message: errorCodeResponse[ErrInternalError].Description, - Key: object.ObjectName, - }) - } + deleteErrors = append(deleteErrors, DeleteError{ + Code: errorCodeResponse[toAPIErrorCode(err)].Code, + Message: errorCodeResponse[toAPIErrorCode(err)].Description, + Key: object.ObjectName, + }) } } // Generate response @@ -466,7 +412,6 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter, // ---------- // This implementation of the PUT operation creates a new bucket for authenticated request func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) bucket := vars["bucket"] @@ -495,14 +440,7 @@ func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Req err := api.ObjectAPI.MakeBucket(bucket) if err != nil { errorIf(err, "MakeBucket failed.", nil) - switch err.(type) { - case BucketNameInvalid: - writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path) - case BucketExists: - writeErrorResponse(w, r, ErrBucketAlreadyOwnedByYou, r.URL.Path) - default: - writeErrorResponse(w, r, ErrInternalError, r.URL.Path) - } + writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path) return } // Make sure to add Location information here only for bucket @@ -573,20 +511,7 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h md5Sum, err := api.ObjectAPI.PutObject(bucket, object, -1, fileBody, nil) if err != nil { errorIf(err, "PutObject failed.", nil) - switch err.(type) { - case StorageFull: - writeErrorResponse(w, r, ErrStorageFull, r.URL.Path) - case BucketNotFound: - writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path) - case BucketNameInvalid: - writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path) - case BadDigest: - writeErrorResponse(w, r, ErrBadDigest, r.URL.Path) - case IncompleteBody: - writeErrorResponse(w, r, ErrIncompleteBody, r.URL.Path) - default: - writeErrorResponse(w, r, ErrInternalError, r.URL.Path) - } + writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path) return } if md5Sum != "" { @@ -632,16 +557,7 @@ func (api objectAPIHandlers) HeadBucketHandler(w http.ResponseWriter, r *http.Re if _, err := api.ObjectAPI.GetBucketInfo(bucket); err != nil { errorIf(err, "GetBucketInfo failed.", nil) - switch err.(type) { - case BucketNotFound: - writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path) - case BucketNameInvalid: - writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path) - case StorageInsufficientReadResources: - writeErrorResponse(w, r, ErrInsufficientReadResources, r.URL.Path) - default: - writeErrorResponse(w, r, ErrInternalError, r.URL.Path) - } + writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path) return } writeSuccessResponse(w, nil) @@ -666,14 +582,7 @@ func (api objectAPIHandlers) DeleteBucketHandler(w http.ResponseWriter, r *http. if err := api.ObjectAPI.DeleteBucket(bucket); err != nil { errorIf(err, "DeleteBucket failed.", nil) - switch err.(type) { - case BucketNotFound: - writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path) - case BucketNotEmpty: - writeErrorResponse(w, r, ErrBucketNotEmpty, r.URL.Path) - default: - writeErrorResponse(w, r, ErrInternalError, r.URL.Path) - } + writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path) return } diff --git a/object-errors.go b/object-errors.go index f74ece6b3..b7969fce3 100644 --- a/object-errors.go +++ b/object-errors.go @@ -41,9 +41,9 @@ func toObjectErr(err error, params ...string) error { case errDiskFull: return StorageFull{} case errReadQuorum: - return StorageInsufficientReadResources{} + return InsufficientReadQuorum{} case errWriteQuorum: - return StorageInsufficientWriteResources{} + return InsufficientWriteQuorum{} case errIsNotRegular, errFileAccessDenied: if len(params) >= 2 { return ObjectExistsAsPrefix{ @@ -71,18 +71,18 @@ func (e StorageFull) Error() string { return "Storage reached its minimum free disk threshold." } -// StorageInsufficientReadResources storage cannot satisfy quorum for read operation. -type StorageInsufficientReadResources struct{} +// InsufficientReadQuorum storage cannot satisfy quorum for read operation. +type InsufficientReadQuorum struct{} -func (e StorageInsufficientReadResources) Error() string { +func (e InsufficientReadQuorum) Error() string { return "Storage resources are insufficient for the read operation." } -// StorageInsufficientWriteResources storage cannot satisfy quorum for write operation. -type StorageInsufficientWriteResources struct{} +// InsufficientWriteQuorum storage cannot satisfy quorum for write operation. +type InsufficientWriteQuorum struct{} -func (e StorageInsufficientWriteResources) Error() string { - return "Stroage resources are insufficient for the write operation." +func (e InsufficientWriteQuorum) Error() string { + return "Storage resources are insufficient for the write operation." } // GenericError - generic object layer error. diff --git a/object-handlers.go b/object-handlers.go index 93d6f0b0e..6834e2104 100644 --- a/object-handlers.go +++ b/object-handlers.go @@ -65,7 +65,6 @@ func errAllowableObjectNotFound(bucket string, r *http.Request) APIErrorCode { return ErrAccessDenied } } - return ErrNoSuchKey } @@ -100,18 +99,11 @@ func (api objectAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Req objInfo, err := api.ObjectAPI.GetObjectInfo(bucket, object) if err != nil { errorIf(err, "GetObjectInfo failed.", nil) - switch err.(type) { - case BucketNameInvalid: - writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path) - case BucketNotFound: - writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path) - case ObjectNotFound: - writeErrorResponse(w, r, errAllowableObjectNotFound(bucket, r), r.URL.Path) - case ObjectNameInvalid: - writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path) - default: - writeErrorResponse(w, r, ErrInternalError, r.URL.Path) + apiErr := toAPIErrorCode(err) + if apiErr == ErrNoSuchKey { + apiErr = errAllowableObjectNotFound(bucket, r) } + writeErrorResponse(w, r, apiErr, r.URL.Path) return } @@ -136,15 +128,12 @@ func (api objectAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Req startOffset := hrange.start readCloser, err := api.ObjectAPI.GetObject(bucket, object, startOffset) if err != nil { - switch err.(type) { - case BucketNotFound: - writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path) - case ObjectNotFound: - writeErrorResponse(w, r, errAllowableObjectNotFound(bucket, r), r.URL.Path) - default: - errorIf(err, "GetObject failed.", nil) - writeErrorResponse(w, r, ErrInternalError, r.URL.Path) + errorIf(err, "GetObject failed.", nil) + apiErr := toAPIErrorCode(err) + if apiErr == ErrNoSuchKey { + apiErr = errAllowableObjectNotFound(bucket, r) } + writeErrorResponse(w, r, apiErr, r.URL.Path) return } defer readCloser.Close() // Close after this handler returns. @@ -294,18 +283,11 @@ func (api objectAPIHandlers) HeadObjectHandler(w http.ResponseWriter, r *http.Re objInfo, err := api.ObjectAPI.GetObjectInfo(bucket, object) if err != nil { errorIf(err, "GetObjectInfo failed.", nil) - switch err.(type) { - case BucketNameInvalid: - writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path) - case BucketNotFound: - writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path) - case ObjectNotFound: - writeErrorResponse(w, r, errAllowableObjectNotFound(bucket, r), r.URL.Path) - case ObjectNameInvalid: - writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path) - default: - writeErrorResponse(w, r, ErrInternalError, r.URL.Path) + apiErr := toAPIErrorCode(err) + if apiErr == ErrNoSuchKey { + apiErr = errAllowableObjectNotFound(bucket, r) } + writeErrorResponse(w, r, apiErr, r.URL.Path) return } @@ -387,18 +369,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re objInfo, err := api.ObjectAPI.GetObjectInfo(sourceBucket, sourceObject) if err != nil { errorIf(err, "GetObjectInfo failed.", nil) - switch err.(type) { - case BucketNameInvalid: - writeErrorResponse(w, r, ErrInvalidBucketName, objectSource) - case BucketNotFound: - writeErrorResponse(w, r, ErrNoSuchBucket, objectSource) - case ObjectNotFound: - writeErrorResponse(w, r, ErrNoSuchKey, objectSource) - case ObjectNameInvalid: - writeErrorResponse(w, r, ErrNoSuchKey, objectSource) - default: - writeErrorResponse(w, r, ErrInternalError, objectSource) - } + writeErrorResponse(w, r, toAPIErrorCode(err), objectSource) return } // Verify before writing. @@ -437,14 +408,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re readCloser, err := api.ObjectAPI.GetObject(sourceBucket, sourceObject, startOffset) if err != nil { errorIf(err, "Reading "+objectSource+" failed.", nil) - switch err.(type) { - case BucketNotFound: - writeErrorResponse(w, r, ErrNoSuchBucket, objectSource) - case ObjectNotFound: - writeErrorResponse(w, r, ErrNoSuchKey, objectSource) - default: - writeErrorResponse(w, r, ErrInternalError, objectSource) - } + writeErrorResponse(w, r, toAPIErrorCode(err), objectSource) return } // Size of object. @@ -458,29 +422,14 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re md5Sum, err := api.ObjectAPI.PutObject(bucket, object, size, readCloser, metadata) if err != nil { errorIf(err, "PutObject failed.", nil) - switch err.(type) { - case StorageFull: - writeErrorResponse(w, r, ErrStorageFull, r.URL.Path) - case BucketNotFound: - writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path) - case BucketNameInvalid: - writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path) - case BadDigest: - writeErrorResponse(w, r, ErrBadDigest, r.URL.Path) - case IncompleteBody: - writeErrorResponse(w, r, ErrIncompleteBody, r.URL.Path) - case ObjectExistsAsPrefix: - writeErrorResponse(w, r, ErrObjectExistsAsPrefix, r.URL.Path) - default: - writeErrorResponse(w, r, ErrInternalError, r.URL.Path) - } + writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path) return } objInfo, err = api.ObjectAPI.GetObjectInfo(bucket, object) if err != nil { errorIf(err, "GetObjectInfo failed.", nil) - writeErrorResponse(w, r, ErrInternalError, r.URL.Path) + writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path) return } @@ -675,27 +624,7 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req } if err != nil { errorIf(err, "PutObject failed.", nil) - // Verify if the underlying error is signature mismatch. - if err == errSignatureMismatch { - writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path) - return - } - switch err.(type) { - case StorageFull: - writeErrorResponse(w, r, ErrStorageFull, r.URL.Path) - case BucketNotFound: - writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path) - case BucketNameInvalid: - writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path) - case BadDigest: - writeErrorResponse(w, r, ErrBadDigest, r.URL.Path) - case IncompleteBody: - writeErrorResponse(w, r, ErrIncompleteBody, r.URL.Path) - case ObjectExistsAsPrefix: - writeErrorResponse(w, r, ErrObjectExistsAsPrefix, r.URL.Path) - default: - writeErrorResponse(w, r, ErrInternalError, r.URL.Path) - } + writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path) return } if md5Sum != "" { @@ -734,20 +663,7 @@ func (api objectAPIHandlers) NewMultipartUploadHandler(w http.ResponseWriter, r uploadID, err := api.ObjectAPI.NewMultipartUpload(bucket, object) if err != nil { errorIf(err, "NewMultipartUpload failed.", nil) - switch err.(type) { - case StorageFull: - writeErrorResponse(w, r, ErrStorageFull, r.URL.Path) - case BucketNameInvalid: - writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path) - case BucketNotFound: - writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path) - case ObjectNotFound: - writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path) - case ObjectNameInvalid: - writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path) - default: - writeErrorResponse(w, r, ErrInternalError, r.URL.Path) - } + writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path) return } @@ -847,22 +763,7 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http if err != nil { errorIf(err, "PutObjectPart failed.", nil) // Verify if the underlying error is signature mismatch. - if err == errSignatureMismatch { - writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path) - return - } - switch err.(type) { - case StorageFull: - writeErrorResponse(w, r, ErrStorageFull, r.URL.Path) - case InvalidUploadID: - writeErrorResponse(w, r, ErrNoSuchUpload, r.URL.Path) - case BadDigest: - writeErrorResponse(w, r, ErrBadDigest, r.URL.Path) - case IncompleteBody: - writeErrorResponse(w, r, ErrIncompleteBody, r.URL.Path) - default: - writeErrorResponse(w, r, ErrInternalError, r.URL.Path) - } + writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path) return } if partMD5 != "" { @@ -898,20 +799,7 @@ func (api objectAPIHandlers) AbortMultipartUploadHandler(w http.ResponseWriter, uploadID, _, _, _ := getObjectResources(r.URL.Query()) if err := api.ObjectAPI.AbortMultipartUpload(bucket, object, uploadID); err != nil { errorIf(err, "AbortMutlipartUpload failed.", nil) - switch err.(type) { - case BucketNameInvalid: - writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path) - case BucketNotFound: - writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path) - case ObjectNotFound: - writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path) - case ObjectNameInvalid: - writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path) - case InvalidUploadID: - writeErrorResponse(w, r, ErrNoSuchUpload, r.URL.Path) - default: - writeErrorResponse(w, r, ErrInternalError, r.URL.Path) - } + writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path) return } writeSuccessNoContent(w) @@ -957,22 +845,7 @@ func (api objectAPIHandlers) ListObjectPartsHandler(w http.ResponseWriter, r *ht listPartsInfo, err := api.ObjectAPI.ListObjectParts(bucket, object, uploadID, partNumberMarker, maxParts) if err != nil { errorIf(err, "ListObjectParts failed.", nil) - switch err.(type) { - case BucketNameInvalid: - writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path) - case BucketNotFound: - writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path) - case ObjectNotFound: - writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path) - case ObjectNameInvalid: - writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path) - case InvalidUploadID: - writeErrorResponse(w, r, ErrNoSuchUpload, r.URL.Path) - case InvalidPart: - writeErrorResponse(w, r, ErrInvalidPart, r.URL.Path) - default: - writeErrorResponse(w, r, ErrInternalError, r.URL.Path) - } + writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path) return } response := generateListPartsResponse(listPartsInfo) @@ -1038,24 +911,7 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite md5Sum, err = api.ObjectAPI.CompleteMultipartUpload(bucket, object, uploadID, completeParts) if err != nil { errorIf(err, "CompleteMultipartUpload failed.", nil) - switch err.(type) { - case BucketNameInvalid: - writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path) - case BucketNotFound: - writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path) - case ObjectNotFound: - writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path) - case ObjectNameInvalid: - writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path) - case InvalidUploadID: - writeErrorResponse(w, r, ErrNoSuchUpload, r.URL.Path) - case InvalidPart: - writeErrorResponse(w, r, ErrInvalidPart, r.URL.Path) - case IncompleteBody: - writeErrorResponse(w, r, ErrIncompleteBody, r.URL.Path) - default: - writeErrorResponse(w, r, ErrInternalError, r.URL.Path) - } + writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path) return } // Get object location. @@ -1096,18 +952,7 @@ func (api objectAPIHandlers) DeleteObjectHandler(w http.ResponseWriter, r *http. } if err := api.ObjectAPI.DeleteObject(bucket, object); err != nil { errorIf(err, "DeleteObject failed.", nil) - switch err.(type) { - case BucketNameInvalid: - writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path) - case BucketNotFound: - writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path) - case ObjectNotFound: - writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path) - case ObjectNameInvalid: - writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path) - default: - writeErrorResponse(w, r, ErrInternalError, r.URL.Path) - } + writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path) return } writeSuccessNoContent(w) diff --git a/web-handlers.go b/web-handlers.go index cf2fbe55c..c599fedca 100644 --- a/web-handlers.go +++ b/web-handlers.go @@ -411,10 +411,10 @@ func writeWebErrorResponse(w http.ResponseWriter, err error) { apiErrCode = ErrNoSuchKey case ObjectNameInvalid: apiErrCode = ErrNoSuchKey - case StorageInsufficientWriteResources: - apiErrCode = ErrInsufficientWriteResources - case StorageInsufficientReadResources: - apiErrCode = ErrInsufficientReadResources + case InsufficientWriteQuorum: + apiErrCode = ErrWriteQuorum + case InsufficientReadQuorum: + apiErrCode = ErrReadQuorum default: apiErrCode = ErrInternalError } diff --git a/xl-erasure-v1-common.go b/xl-erasure-v1-common.go index 39987078f..f3f8c20e5 100644 --- a/xl-erasure-v1-common.go +++ b/xl-erasure-v1-common.go @@ -62,13 +62,12 @@ func (xl XL) listOnlineDisks(volume, path string) (onlineDisks []StorageAPI, mda for _, err := range errs { if err == errFileNotFound { notFoundCount++ - // If we have errors with file not found greater than allowed read - // quorum we return err as errFileNotFound. - if notFoundCount > len(xl.storageDisks)-xl.readQuorum { - return nil, xlMetaV1{}, false, errFileNotFound - } } } + // If we have errors with file not found equal to the number of disks. + if notFoundCount == len(xl.storageDisks) { + return nil, xlMetaV1{}, false, errFileNotFound + } highestVersion := int64(0) onlineDisks = make([]StorageAPI, len(xl.storageDisks)) // List all the file versions from partsMetadata list. diff --git a/xl-objects.go b/xl-objects.go index ce5cbe624..8fce20b37 100644 --- a/xl-objects.go +++ b/xl-objects.go @@ -163,13 +163,17 @@ func (xl xlObjects) GetObjectInfo(bucket, object string) (ObjectInfo, error) { } fi, err := xl.storage.StatFile(bucket, object) if err != nil { - info, err := getMultipartObjectInfo(xl.storage, bucket, object) - if err != nil { - return ObjectInfo{}, toObjectErr(err, bucket, object) + if err == errFileNotFound { + var info MultipartObjectInfo + info, err = getMultipartObjectInfo(xl.storage, bucket, object) + if err != nil { + return ObjectInfo{}, toObjectErr(err, bucket, object) + } + fi.Size = info.Size + fi.ModTime = info.ModTime + fi.MD5Sum = info.MD5Sum } - fi.Size = info.Size - fi.ModTime = info.ModTime - fi.MD5Sum = info.MD5Sum + return ObjectInfo{}, toObjectErr(err, bucket, object) } contentType := "application/octet-stream" if objectExt := filepath.Ext(object); objectExt != "" {