gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

api-put-object-common.go (4419B)


      1 /*
      2  * MinIO Go Library for Amazon S3 Compatible Cloud Storage
      3  * Copyright 2015-2017 MinIO, Inc.
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 package minio
     19 
     20 import (
     21 	"context"
     22 	"io"
     23 	"math"
     24 	"os"
     25 
     26 	"github.com/minio/minio-go/v7/pkg/s3utils"
     27 )
     28 
     29 const nullVersionID = "null"
     30 
     31 // Verify if reader is *minio.Object
     32 func isObject(reader io.Reader) (ok bool) {
     33 	_, ok = reader.(*Object)
     34 	return
     35 }
     36 
     37 // Verify if reader is a generic ReaderAt
     38 func isReadAt(reader io.Reader) (ok bool) {
     39 	var v *os.File
     40 	v, ok = reader.(*os.File)
     41 	if ok {
     42 		// Stdin, Stdout and Stderr all have *os.File type
     43 		// which happen to also be io.ReaderAt compatible
     44 		// we need to add special conditions for them to
     45 		// be ignored by this function.
     46 		for _, f := range []string{
     47 			"/dev/stdin",
     48 			"/dev/stdout",
     49 			"/dev/stderr",
     50 		} {
     51 			if f == v.Name() {
     52 				ok = false
     53 				break
     54 			}
     55 		}
     56 	} else {
     57 		_, ok = reader.(io.ReaderAt)
     58 	}
     59 	return
     60 }
     61 
     62 // OptimalPartInfo - calculate the optimal part info for a given
     63 // object size.
     64 //
     65 // NOTE: Assumption here is that for any object to be uploaded to any S3 compatible
     66 // object storage it will have the following parameters as constants.
     67 //
     68 //	maxPartsCount - 10000
     69 //	minPartSize - 16MiB
     70 //	maxMultipartPutObjectSize - 5TiB
     71 func OptimalPartInfo(objectSize int64, configuredPartSize uint64) (totalPartsCount int, partSize int64, lastPartSize int64, err error) {
     72 	// object size is '-1' set it to 5TiB.
     73 	var unknownSize bool
     74 	if objectSize == -1 {
     75 		unknownSize = true
     76 		objectSize = maxMultipartPutObjectSize
     77 	}
     78 
     79 	// object size is larger than supported maximum.
     80 	if objectSize > maxMultipartPutObjectSize {
     81 		err = errEntityTooLarge(objectSize, maxMultipartPutObjectSize, "", "")
     82 		return
     83 	}
     84 
     85 	var partSizeFlt float64
     86 	if configuredPartSize > 0 {
     87 		if int64(configuredPartSize) > objectSize {
     88 			err = errEntityTooLarge(int64(configuredPartSize), objectSize, "", "")
     89 			return
     90 		}
     91 
     92 		if !unknownSize {
     93 			if objectSize > (int64(configuredPartSize) * maxPartsCount) {
     94 				err = errInvalidArgument("Part size * max_parts(10000) is lesser than input objectSize.")
     95 				return
     96 			}
     97 		}
     98 
     99 		if configuredPartSize < absMinPartSize {
    100 			err = errInvalidArgument("Input part size is smaller than allowed minimum of 5MiB.")
    101 			return
    102 		}
    103 
    104 		if configuredPartSize > maxPartSize {
    105 			err = errInvalidArgument("Input part size is bigger than allowed maximum of 5GiB.")
    106 			return
    107 		}
    108 
    109 		partSizeFlt = float64(configuredPartSize)
    110 		if unknownSize {
    111 			// If input has unknown size and part size is configured
    112 			// keep it to maximum allowed as per 10000 parts.
    113 			objectSize = int64(configuredPartSize) * maxPartsCount
    114 		}
    115 	} else {
    116 		configuredPartSize = minPartSize
    117 		// Use floats for part size for all calculations to avoid
    118 		// overflows during float64 to int64 conversions.
    119 		partSizeFlt = float64(objectSize / maxPartsCount)
    120 		partSizeFlt = math.Ceil(partSizeFlt/float64(configuredPartSize)) * float64(configuredPartSize)
    121 	}
    122 
    123 	// Total parts count.
    124 	totalPartsCount = int(math.Ceil(float64(objectSize) / partSizeFlt))
    125 	// Part size.
    126 	partSize = int64(partSizeFlt)
    127 	// Last part size.
    128 	lastPartSize = objectSize - int64(totalPartsCount-1)*partSize
    129 	return totalPartsCount, partSize, lastPartSize, nil
    130 }
    131 
    132 // getUploadID - fetch upload id if already present for an object name
    133 // or initiate a new request to fetch a new upload id.
    134 func (c *Client) newUploadID(ctx context.Context, bucketName, objectName string, opts PutObjectOptions) (uploadID string, err error) {
    135 	// Input validation.
    136 	if err := s3utils.CheckValidBucketName(bucketName); err != nil {
    137 		return "", err
    138 	}
    139 	if err := s3utils.CheckValidObjectName(objectName); err != nil {
    140 		return "", err
    141 	}
    142 
    143 	// Initiate multipart upload for an object.
    144 	initMultipartUploadResult, err := c.initiateMultipartUpload(ctx, bucketName, objectName, opts)
    145 	if err != nil {
    146 		return "", err
    147 	}
    148 	return initMultipartUploadResult.UploadID, nil
    149 }