mirror of
https://github.com/minio/minio.git
synced 2025-07-08 08:32:18 -04:00
avoid double listObjectParts calls improves performance (#9606)
this PR is to avoid double calls across multiple calls in APIs - CopyObjectPart - PutObjectPart
This commit is contained in:
parent
b730bd1396
commit
d348ec0f6c
@ -95,7 +95,7 @@ func (m gwMetaV1) ToObjectInfo(bucket, object string) minio.ObjectInfo {
|
|||||||
ContentType: m.Meta["content-type"],
|
ContentType: m.Meta["content-type"],
|
||||||
ContentEncoding: m.Meta["content-encoding"],
|
ContentEncoding: m.Meta["content-encoding"],
|
||||||
ETag: minio.CanonicalizeETag(m.ETag),
|
ETag: minio.CanonicalizeETag(m.ETag),
|
||||||
UserDefined: minio.CleanMetadataKeys(m.Meta, filterKeys...),
|
UserDefined: minio.CleanMinioInternalMetadataKeys(minio.CleanMetadataKeys(m.Meta, filterKeys...)),
|
||||||
Parts: m.Parts,
|
Parts: m.Parts,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,7 +314,6 @@ func (l *s3EncObjects) GetObjectNInfo(ctx context.Context, bucket, object string
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return l.s3Objects.GetObjectNInfo(ctx, bucket, object, rs, h, lockType, opts)
|
return l.s3Objects.GetObjectNInfo(ctx, bucket, object, rs, h, lockType, opts)
|
||||||
}
|
}
|
||||||
objInfo.UserDefined = minio.CleanMinioInternalMetadataKeys(objInfo.UserDefined)
|
|
||||||
fn, off, length, err := minio.NewGetObjectReader(rs, objInfo, o)
|
fn, off, length, err := minio.NewGetObjectReader(rs, objInfo, o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, minio.ErrorRespToObjectError(err)
|
return nil, minio.ErrorRespToObjectError(err)
|
||||||
@ -549,7 +548,7 @@ func (l *s3EncObjects) ListObjectParts(ctx context.Context, bucket string, objec
|
|||||||
}
|
}
|
||||||
lpi.Parts[i].ETag = partMeta.ETag
|
lpi.Parts[i].ETag = partMeta.ETag
|
||||||
}
|
}
|
||||||
lpi.UserDefined = dm.Meta
|
lpi.UserDefined = dm.ToObjectInfo(bucket, object).UserDefined
|
||||||
lpi.Object = object
|
lpi.Object = object
|
||||||
return lpi, nil
|
return lpi, nil
|
||||||
}
|
}
|
||||||
|
@ -369,7 +369,6 @@ func (api objectAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Req
|
|||||||
objInfo.UserDefined = objectlock.FilterObjectLockMetadata(objInfo.UserDefined, getRetPerms != ErrNone, legalHoldPerms != ErrNone)
|
objInfo.UserDefined = objectlock.FilterObjectLockMetadata(objInfo.UserDefined, getRetPerms != ErrNone, legalHoldPerms != ErrNone)
|
||||||
|
|
||||||
if objectAPI.IsEncryptionSupported() {
|
if objectAPI.IsEncryptionSupported() {
|
||||||
objInfo.UserDefined = CleanMinioInternalMetadataKeys(objInfo.UserDefined)
|
|
||||||
if _, err = DecryptObjectInfo(&objInfo, r.Header); err != nil {
|
if _, err = DecryptObjectInfo(&objInfo, r.Header); err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
||||||
return
|
return
|
||||||
@ -545,7 +544,6 @@ func (api objectAPIHandlers) HeadObjectHandler(w http.ResponseWriter, r *http.Re
|
|||||||
writeErrorResponseHeadersOnly(w, toAPIError(ctx, err))
|
writeErrorResponseHeadersOnly(w, toAPIError(ctx, err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
objInfo.UserDefined = CleanMinioInternalMetadataKeys(objInfo.UserDefined)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set encryption response headers
|
// Set encryption response headers
|
||||||
@ -1820,8 +1818,7 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read compression metadata preserved in the init multipart for the decision.
|
// Read compression metadata preserved in the init multipart for the decision.
|
||||||
_, compressPart := li.UserDefined[ReservedMetadataPrefix+"compression"]
|
_, isCompressed := li.UserDefined[ReservedMetadataPrefix+"compression"]
|
||||||
isCompressed := compressPart
|
|
||||||
// Compress only if the compression is enabled during initial multipart.
|
// Compress only if the compression is enabled during initial multipart.
|
||||||
if isCompressed {
|
if isCompressed {
|
||||||
s2c := newS2CompressReader(gr)
|
s2c := newS2CompressReader(gr)
|
||||||
@ -1838,24 +1835,18 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rawReader := srcInfo.Reader
|
|
||||||
pReader := NewPutObjReader(rawReader, nil, nil)
|
|
||||||
|
|
||||||
isEncrypted := false
|
|
||||||
var objectEncryptionKey crypto.ObjectKey
|
|
||||||
if objectAPI.IsEncryptionSupported() && !isCompressed {
|
|
||||||
li, lerr := objectAPI.ListObjectParts(ctx, dstBucket, dstObject, uploadID, 0, 1, dstOpts)
|
|
||||||
if lerr != nil {
|
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, lerr), r.URL, guessIsBrowserReq(r))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
li.UserDefined = CleanMinioInternalMetadataKeys(li.UserDefined)
|
|
||||||
dstOpts, err = copyDstOpts(ctx, r, dstBucket, dstObject, li.UserDefined)
|
dstOpts, err = copyDstOpts(ctx, r, dstBucket, dstObject, li.UserDefined)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if crypto.IsEncrypted(li.UserDefined) {
|
|
||||||
|
rawReader := srcInfo.Reader
|
||||||
|
pReader := NewPutObjReader(rawReader, nil, nil)
|
||||||
|
|
||||||
|
isEncrypted := crypto.IsEncrypted(li.UserDefined)
|
||||||
|
var objectEncryptionKey crypto.ObjectKey
|
||||||
|
if objectAPI.IsEncryptionSupported() && !isCompressed && isEncrypted {
|
||||||
if !crypto.SSEC.IsRequested(r.Header) && crypto.SSEC.IsEncrypted(li.UserDefined) {
|
if !crypto.SSEC.IsRequested(r.Header) && crypto.SSEC.IsEncrypted(li.UserDefined) {
|
||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrSSEMultipartEncrypted), r.URL, guessIsBrowserReq(r))
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrSSEMultipartEncrypted), r.URL, guessIsBrowserReq(r))
|
||||||
return
|
return
|
||||||
@ -1864,7 +1855,6 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt
|
|||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrSSEMultipartEncrypted), r.URL, guessIsBrowserReq(r))
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrSSEMultipartEncrypted), r.URL, guessIsBrowserReq(r))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
isEncrypted = true
|
|
||||||
var key []byte
|
var key []byte
|
||||||
if crypto.SSEC.IsRequested(r.Header) {
|
if crypto.SSEC.IsRequested(r.Header) {
|
||||||
key, err = ParseSSECustomerRequest(r)
|
key, err = ParseSSECustomerRequest(r)
|
||||||
@ -1895,7 +1885,7 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt
|
|||||||
}
|
}
|
||||||
pReader = NewPutObjReader(rawReader, srcInfo.Reader, &objectEncryptionKey)
|
pReader = NewPutObjReader(rawReader, srcInfo.Reader, &objectEncryptionKey)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
srcInfo.PutObjReader = pReader
|
srcInfo.PutObjReader = pReader
|
||||||
// Copy source object to destination, if source and destination
|
// Copy source object to destination, if source and destination
|
||||||
// object is same then only metadata is updated.
|
// object is same then only metadata is updated.
|
||||||
@ -2062,11 +2052,11 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http
|
|||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Read compression metadata preserved in the init multipart for the decision.
|
|
||||||
_, compressPart := li.UserDefined[ReservedMetadataPrefix+"compression"]
|
|
||||||
|
|
||||||
isCompressed := false
|
// Read compression metadata preserved in the init multipart for the decision.
|
||||||
if objectAPI.IsCompressionSupported() && compressPart {
|
_, isCompressed := li.UserDefined[ReservedMetadataPrefix+"compression"]
|
||||||
|
|
||||||
|
if objectAPI.IsCompressionSupported() && isCompressed {
|
||||||
actualReader, err := hash.NewReader(reader, size, md5hex, sha256hex, actualSize, globalCLIContext.StrictS3Compat)
|
actualReader, err := hash.NewReader(reader, size, md5hex, sha256hex, actualSize, globalCLIContext.StrictS3Compat)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
||||||
@ -2080,7 +2070,6 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http
|
|||||||
size = -1 // Since compressed size is un-predictable.
|
size = -1 // Since compressed size is un-predictable.
|
||||||
md5hex = "" // Do not try to verify the content.
|
md5hex = "" // Do not try to verify the content.
|
||||||
sha256hex = ""
|
sha256hex = ""
|
||||||
isCompressed = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hashReader, err := hash.NewReader(reader, size, md5hex, sha256hex, actualSize, globalCLIContext.StrictS3Compat)
|
hashReader, err := hash.NewReader(reader, size, md5hex, sha256hex, actualSize, globalCLIContext.StrictS3Compat)
|
||||||
@ -2091,23 +2080,14 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http
|
|||||||
rawReader := hashReader
|
rawReader := hashReader
|
||||||
pReader := NewPutObjReader(rawReader, nil, nil)
|
pReader := NewPutObjReader(rawReader, nil, nil)
|
||||||
|
|
||||||
isEncrypted := false
|
isEncrypted := crypto.IsEncrypted(li.UserDefined)
|
||||||
var objectEncryptionKey crypto.ObjectKey
|
var objectEncryptionKey crypto.ObjectKey
|
||||||
if objectAPI.IsEncryptionSupported() && !isCompressed {
|
if objectAPI.IsEncryptionSupported() && !isCompressed && isEncrypted {
|
||||||
var li ListPartsInfo
|
|
||||||
li, err = objectAPI.ListObjectParts(ctx, bucket, object, uploadID, 0, 1, ObjectOptions{})
|
|
||||||
if err != nil {
|
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
li.UserDefined = CleanMinioInternalMetadataKeys(li.UserDefined)
|
|
||||||
if crypto.IsEncrypted(li.UserDefined) {
|
|
||||||
if !crypto.SSEC.IsRequested(r.Header) && crypto.SSEC.IsEncrypted(li.UserDefined) {
|
if !crypto.SSEC.IsRequested(r.Header) && crypto.SSEC.IsEncrypted(li.UserDefined) {
|
||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrSSEMultipartEncrypted), r.URL, guessIsBrowserReq(r))
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrSSEMultipartEncrypted), r.URL, guessIsBrowserReq(r))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isEncrypted = true // to detect SSE-S3 encryption
|
|
||||||
opts, err = putOpts(ctx, r, bucket, object, li.UserDefined)
|
opts, err = putOpts(ctx, r, bucket, object, li.UserDefined)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
||||||
@ -2152,7 +2132,6 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http
|
|||||||
}
|
}
|
||||||
pReader = NewPutObjReader(rawReader, hashReader, &objectEncryptionKey)
|
pReader = NewPutObjReader(rawReader, hashReader, &objectEncryptionKey)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
putObjectPart := objectAPI.PutObjectPart
|
putObjectPart := objectAPI.PutObjectPart
|
||||||
|
|
||||||
@ -2249,29 +2228,24 @@ func (api objectAPIHandlers) ListObjectPartsHandler(w http.ResponseWriter, r *ht
|
|||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrInvalidMaxParts), r.URL, guessIsBrowserReq(r))
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrInvalidMaxParts), r.URL, guessIsBrowserReq(r))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var opts ObjectOptions
|
var opts ObjectOptions
|
||||||
listPartsInfo, err := objectAPI.ListObjectParts(ctx, bucket, object, uploadID, partNumberMarker, maxParts, opts)
|
listPartsInfo, err := objectAPI.ListObjectParts(ctx, bucket, object, uploadID, partNumberMarker, maxParts, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var ssec bool
|
var ssec bool
|
||||||
if objectAPI.IsEncryptionSupported() {
|
if objectAPI.IsEncryptionSupported() && crypto.IsEncrypted(listPartsInfo.UserDefined) {
|
||||||
var li ListPartsInfo
|
|
||||||
li, err = objectAPI.ListObjectParts(ctx, bucket, object, uploadID, 0, 1, opts)
|
|
||||||
if err != nil {
|
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if crypto.IsEncrypted(li.UserDefined) {
|
|
||||||
var key []byte
|
var key []byte
|
||||||
if crypto.SSEC.IsEncrypted(li.UserDefined) {
|
if crypto.SSEC.IsEncrypted(listPartsInfo.UserDefined) {
|
||||||
ssec = true
|
ssec = true
|
||||||
}
|
}
|
||||||
var objectEncryptionKey []byte
|
var objectEncryptionKey []byte
|
||||||
if crypto.S3.IsEncrypted(li.UserDefined) {
|
if crypto.S3.IsEncrypted(listPartsInfo.UserDefined) {
|
||||||
// Calculating object encryption key
|
// Calculating object encryption key
|
||||||
objectEncryptionKey, err = decryptObjectInfo(key, bucket, object, li.UserDefined)
|
objectEncryptionKey, err = decryptObjectInfo(key, bucket, object, listPartsInfo.UserDefined)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
||||||
return
|
return
|
||||||
@ -2285,7 +2259,6 @@ func (api objectAPIHandlers) ListObjectPartsHandler(w http.ResponseWriter, r *ht
|
|||||||
}
|
}
|
||||||
listPartsInfo.Parts = parts
|
listPartsInfo.Parts = parts
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
response := generateListPartsResponse(listPartsInfo, encodingType)
|
response := generateListPartsResponse(listPartsInfo, encodingType)
|
||||||
encodedSuccessResponse := encodeResponse(response)
|
encodedSuccessResponse := encodeResponse(response)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user