// newMultipartUpload - new multipart upload request func (xl API) newMultipartUpload(bucket, object, contentType string) (string, *probe.Error) { if err := xl.listXLBuckets(); err != nil { return "", err.Trace() } if _, ok := xl.buckets[bucket]; !ok { return "", probe.NewError(BucketNotFound{Bucket: bucket}) } allbuckets, err := xl.getXLBucketMetadata() if err != nil { return "", err.Trace() } bucketMetadata := allbuckets.Buckets[bucket] multiparts := make(map[string]MultiPartSession) if len(bucketMetadata.Multiparts) > 0 { multiparts = bucketMetadata.Multiparts } id := []byte(strconv.Itoa(rand.Int()) + bucket + object + time.Now().String()) uploadIDSum := sha512.Sum512(id) uploadID := base64.URLEncoding.EncodeToString(uploadIDSum[:])[:47] multipartSession := MultiPartSession{ UploadID: uploadID, Initiated: time.Now().UTC(), Parts: make(map[string]PartMetadata), TotalParts: 0, } multiparts[object] = multipartSession bucketMetadata.Multiparts = multiparts allbuckets.Buckets[bucket] = bucketMetadata if err := xl.setXLBucketMetadata(allbuckets); err != nil { return "", err.Trace() } return uploadID, nil }
// NewMultipartUpload - initiate a new multipart session func (fs Filesystem) NewMultipartUpload(bucket, object string) (string, *probe.Error) { fs.lock.Lock() defer fs.lock.Unlock() di, e := disk.GetInfo(fs.path) if e != nil { return "", probe.NewError(e) } // Remove 5% from total space for cumulative disk space used for journalling, inodes etc. availableDiskSpace := (float64(di.Free) / (float64(di.Total) - (0.05 * float64(di.Total)))) * 100 if int64(availableDiskSpace) <= fs.minFreeDisk { return "", probe.NewError(RootPathFull{Path: fs.path}) } if !IsValidBucketName(bucket) { return "", probe.NewError(BucketNameInvalid{Bucket: bucket}) } if !IsValidObjectName(object) { return "", probe.NewError(ObjectNameInvalid{Object: object}) } bucket = fs.denormalizeBucket(bucket) bucketPath := filepath.Join(fs.path, bucket) if _, e = os.Stat(bucketPath); e != nil { // check bucket exists if os.IsNotExist(e) { return "", probe.NewError(BucketNotFound{Bucket: bucket}) } return "", probe.NewError(e) } objectPath := filepath.Join(bucketPath, object) objectDir := filepath.Dir(objectPath) if _, e = os.Stat(objectDir); e != nil { if !os.IsNotExist(e) { return "", probe.NewError(e) } e = os.MkdirAll(objectDir, 0700) if e != nil { return "", probe.NewError(e) } } id := []byte(strconv.FormatInt(rand.Int63(), 10) + bucket + object + time.Now().String()) uploadIDSum := sha512.Sum512(id) uploadID := base64.URLEncoding.EncodeToString(uploadIDSum[:])[:47] multiPartfile, e := os.OpenFile(objectPath+"$multiparts", os.O_WRONLY|os.O_CREATE, 0600) if e != nil { return "", probe.NewError(e) } defer multiPartfile.Close() mpartSession := &MultipartSession{} mpartSession.TotalParts = 0 mpartSession.UploadID = uploadID mpartSession.Initiated = time.Now().UTC() var parts []*PartMetadata mpartSession.Parts = parts fs.multiparts.ActiveSession[object] = mpartSession encoder := json.NewEncoder(multiPartfile) if e = encoder.Encode(mpartSession); e != nil { return "", probe.NewError(e) } if err := saveMultipartsSession(fs.multiparts); err != nil { return "", err.Trace() } return uploadID, nil }
// NewMultipartUpload - initiate a new multipart session func (fs Filesystem) NewMultipartUpload(bucket, object string) (string, *probe.Error) { di, e := disk.GetInfo(fs.path) if e != nil { return "", probe.NewError(e) } // Remove 5% from total space for cumulative disk space used for // journalling, inodes etc. availableDiskSpace := (float64(di.Free) / (float64(di.Total) - (0.05 * float64(di.Total)))) * 100 if int64(availableDiskSpace) <= fs.minFreeDisk { return "", probe.NewError(RootPathFull{Path: fs.path}) } // Input validation. if !IsValidBucketName(bucket) { return "", probe.NewError(BucketNameInvalid{Bucket: bucket}) } if !IsValidObjectName(object) { return "", probe.NewError(ObjectNameInvalid{Object: object}) } bucket = fs.denormalizeBucket(bucket) bucketPath := filepath.Join(fs.path, bucket) if _, e = os.Stat(bucketPath); e != nil { // Check bucket exists. if os.IsNotExist(e) { return "", probe.NewError(BucketNotFound{Bucket: bucket}) } return "", probe.NewError(e) } objectPath := filepath.Join(bucketPath, object) objectDir := filepath.Dir(objectPath) if _, e = os.Stat(objectDir); e != nil { if !os.IsNotExist(e) { return "", probe.NewError(e) } e = os.MkdirAll(objectDir, 0700) if e != nil { return "", probe.NewError(e) } } // Generate new upload id. id := []byte(strconv.FormatInt(rand.Int63(), 10) + bucket + object + time.Now().String()) uploadIDSum := sha512.Sum512(id) uploadID := base64.URLEncoding.EncodeToString(uploadIDSum[:])[:47] // Critical region requiring write lock. fs.rwLock.Lock() // Initialize multipart session. mpartSession := &MultipartSession{} mpartSession.TotalParts = 0 mpartSession.ObjectName = object mpartSession.UploadID = uploadID mpartSession.Initiated = time.Now().UTC() var parts []PartMetadata mpartSession.Parts = parts fs.multiparts.ActiveSession[uploadID] = mpartSession if err := saveMultipartsSession(*fs.multiparts); err != nil { fs.rwLock.Unlock() return "", err.Trace(objectPath) } fs.rwLock.Unlock() return uploadID, nil }