|
|
@ -87,14 +87,6 @@ func (o objectAPI) ListMultipartUploads(bucket, prefix, keyMarker, uploadIDMarke |
|
|
|
if !IsValidObjectPrefix(prefix) { |
|
|
|
if !IsValidObjectPrefix(prefix) { |
|
|
|
return ListMultipartsInfo{}, probe.NewError(ObjectNameInvalid{Bucket: bucket, Object: prefix}) |
|
|
|
return ListMultipartsInfo{}, probe.NewError(ObjectNameInvalid{Bucket: bucket, Object: prefix}) |
|
|
|
} |
|
|
|
} |
|
|
|
if _, e := o.storage.StatVol(minioMetaVolume); e != nil { |
|
|
|
|
|
|
|
if e == errVolumeNotFound { |
|
|
|
|
|
|
|
e = o.storage.MakeVol(minioMetaVolume) |
|
|
|
|
|
|
|
if e != nil { |
|
|
|
|
|
|
|
return ListMultipartsInfo{}, probe.NewError(e) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// Verify if delimiter is anything other than '/', which we do not support.
|
|
|
|
// Verify if delimiter is anything other than '/', which we do not support.
|
|
|
|
if delimiter != "" && delimiter != slashSeparator { |
|
|
|
if delimiter != "" && delimiter != slashSeparator { |
|
|
|
return ListMultipartsInfo{}, probe.NewError(UnsupportedDelimiter{ |
|
|
|
return ListMultipartsInfo{}, probe.NewError(UnsupportedDelimiter{ |
|
|
@ -292,22 +284,21 @@ func (o objectAPI) NewMultipartUpload(bucket, object string) (string, *probe.Err |
|
|
|
uploadIDPath := path.Join(bucket, object, uploadID) |
|
|
|
uploadIDPath := path.Join(bucket, object, uploadID) |
|
|
|
if _, e = o.storage.StatFile(minioMetaVolume, uploadIDPath); e != nil { |
|
|
|
if _, e = o.storage.StatFile(minioMetaVolume, uploadIDPath); e != nil { |
|
|
|
if e != errFileNotFound { |
|
|
|
if e != errFileNotFound { |
|
|
|
return "", probe.NewError(e) |
|
|
|
return "", probe.NewError(toObjectErr(e, minioMetaVolume, uploadIDPath)) |
|
|
|
} |
|
|
|
} |
|
|
|
// uploadIDPath doesn't exist, so create empty file to reserve the name
|
|
|
|
// uploadIDPath doesn't exist, so create empty file to reserve the name
|
|
|
|
var w io.WriteCloser |
|
|
|
var w io.WriteCloser |
|
|
|
if w, e = o.storage.CreateFile(minioMetaVolume, uploadIDPath); e == nil { |
|
|
|
if w, e = o.storage.CreateFile(minioMetaVolume, uploadIDPath); e == nil { |
|
|
|
// Just write some data for erasure code, rather than zero bytes.
|
|
|
|
// Just write some data for erasure code, rather than zero bytes.
|
|
|
|
w.Write([]byte(uploadID)) |
|
|
|
if _, e = w.Write([]byte(uploadID)); e != nil { |
|
|
|
|
|
|
|
return "", probe.NewError(toObjectErr(e, minioMetaVolume, uploadIDPath)) |
|
|
|
|
|
|
|
} |
|
|
|
// Close the writer.
|
|
|
|
// Close the writer.
|
|
|
|
if e = w.Close(); e != nil { |
|
|
|
if e = w.Close(); e != nil { |
|
|
|
return "", probe.NewError(e) |
|
|
|
return "", probe.NewError(e) |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
if e == errDiskFull { |
|
|
|
return "", probe.NewError(toObjectErr(e, minioMetaVolume, uploadIDPath)) |
|
|
|
return "", probe.NewError(StorageFull{}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return "", probe.NewError(e) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
return uploadID, nil |
|
|
|
return uploadID, nil |
|
|
|
} |
|
|
|
} |
|
|
@ -358,19 +349,7 @@ func (o objectAPI) PutObjectPart(bucket, object, uploadID string, partID int, si |
|
|
|
partSuffix := fmt.Sprintf("%s.%d.%s", uploadID, partID, md5Hex) |
|
|
|
partSuffix := fmt.Sprintf("%s.%d.%s", uploadID, partID, md5Hex) |
|
|
|
fileWriter, e := o.storage.CreateFile(minioMetaVolume, path.Join(bucket, object, partSuffix)) |
|
|
|
fileWriter, e := o.storage.CreateFile(minioMetaVolume, path.Join(bucket, object, partSuffix)) |
|
|
|
if e != nil { |
|
|
|
if e != nil { |
|
|
|
if e == errVolumeNotFound { |
|
|
|
return "", probe.NewError(toObjectErr(e, bucket, object)) |
|
|
|
return "", probe.NewError(BucketNotFound{ |
|
|
|
|
|
|
|
Bucket: bucket, |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} else if e == errIsNotRegular { |
|
|
|
|
|
|
|
return "", probe.NewError(ObjectExistsAsPrefix{ |
|
|
|
|
|
|
|
Bucket: bucket, |
|
|
|
|
|
|
|
Object: object, |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} else if e == errDiskFull { |
|
|
|
|
|
|
|
return "", probe.NewError(StorageFull{}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return "", probe.NewError(e) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Initialize md5 writer.
|
|
|
|
// Initialize md5 writer.
|
|
|
@ -383,10 +362,7 @@ func (o objectAPI) PutObjectPart(bucket, object, uploadID string, partID int, si |
|
|
|
if size > 0 { |
|
|
|
if size > 0 { |
|
|
|
if _, e = io.CopyN(multiWriter, data, size); e != nil { |
|
|
|
if _, e = io.CopyN(multiWriter, data, size); e != nil { |
|
|
|
safeCloseAndRemove(fileWriter) |
|
|
|
safeCloseAndRemove(fileWriter) |
|
|
|
if e == io.ErrUnexpectedEOF || e == io.ErrShortWrite { |
|
|
|
return "", probe.NewError(toObjectErr(e)) |
|
|
|
return "", probe.NewError(IncompleteBody{}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return "", probe.NewError(e) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
// Reader shouldn't have more data what mentioned in size argument.
|
|
|
|
// Reader shouldn't have more data what mentioned in size argument.
|
|
|
|
// reading one more byte from the reader to validate it.
|
|
|
|
// reading one more byte from the reader to validate it.
|
|
|
@ -398,7 +374,7 @@ func (o objectAPI) PutObjectPart(bucket, object, uploadID string, partID int, si |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
if _, e = io.Copy(multiWriter, data); e != nil { |
|
|
|
if _, e = io.Copy(multiWriter, data); e != nil { |
|
|
|
safeCloseAndRemove(fileWriter) |
|
|
|
safeCloseAndRemove(fileWriter) |
|
|
|
return "", probe.NewError(e) |
|
|
|
return "", probe.NewError(toObjectErr(e)) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -424,15 +400,6 @@ func (o objectAPI) ListObjectParts(bucket, object, uploadID string, partNumberMa |
|
|
|
if !IsValidObjectName(object) { |
|
|
|
if !IsValidObjectName(object) { |
|
|
|
return ListPartsInfo{}, probe.NewError(ObjectNameInvalid{Bucket: bucket, Object: object}) |
|
|
|
return ListPartsInfo{}, probe.NewError(ObjectNameInvalid{Bucket: bucket, Object: object}) |
|
|
|
} |
|
|
|
} |
|
|
|
// Create minio meta volume, if it doesn't exist yet.
|
|
|
|
|
|
|
|
if _, e := o.storage.StatVol(minioMetaVolume); e != nil { |
|
|
|
|
|
|
|
if e == errVolumeNotFound { |
|
|
|
|
|
|
|
e = o.storage.MakeVol(minioMetaVolume) |
|
|
|
|
|
|
|
if e != nil { |
|
|
|
|
|
|
|
return ListPartsInfo{}, probe.NewError(e) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if status, e := o.isUploadIDExists(bucket, object, uploadID); e != nil { |
|
|
|
if status, e := o.isUploadIDExists(bucket, object, uploadID); e != nil { |
|
|
|
return ListPartsInfo{}, probe.NewError(e) |
|
|
|
return ListPartsInfo{}, probe.NewError(e) |
|
|
|
} else if !status { |
|
|
|
} else if !status { |
|
|
@ -445,10 +412,10 @@ func (o objectAPI) ListObjectParts(bucket, object, uploadID string, partNumberMa |
|
|
|
// Figure out the marker for the next subsequent calls, if the
|
|
|
|
// Figure out the marker for the next subsequent calls, if the
|
|
|
|
// partNumberMarker is already set.
|
|
|
|
// partNumberMarker is already set.
|
|
|
|
if partNumberMarker > 0 { |
|
|
|
if partNumberMarker > 0 { |
|
|
|
uploadIDPartPrefix := uploadIDPath + "." + strconv.Itoa(partNumberMarker) + "." |
|
|
|
partNumberMarkerPath := uploadIDPath + "." + strconv.Itoa(partNumberMarker) + "." |
|
|
|
fileInfos, _, e := o.storage.ListFiles(minioMetaVolume, uploadIDPartPrefix, "", false, 1) |
|
|
|
fileInfos, _, e := o.storage.ListFiles(minioMetaVolume, partNumberMarkerPath, "", false, 1) |
|
|
|
if e != nil { |
|
|
|
if e != nil { |
|
|
|
return result, probe.NewError(e) |
|
|
|
return result, probe.NewError(toObjectErr(e, minioMetaVolume, partNumberMarkerPath)) |
|
|
|
} |
|
|
|
} |
|
|
|
if len(fileInfos) == 0 { |
|
|
|
if len(fileInfos) == 0 { |
|
|
|
return result, probe.NewError(InvalidPart{}) |
|
|
|
return result, probe.NewError(InvalidPart{}) |
|
|
@ -521,19 +488,7 @@ func (o objectAPI) CompleteMultipartUpload(bucket string, object string, uploadI |
|
|
|
|
|
|
|
|
|
|
|
fileWriter, e := o.storage.CreateFile(bucket, object) |
|
|
|
fileWriter, e := o.storage.CreateFile(bucket, object) |
|
|
|
if e != nil { |
|
|
|
if e != nil { |
|
|
|
if e == errVolumeNotFound { |
|
|
|
return "", probe.NewError(toObjectErr(e, bucket, object)) |
|
|
|
return "", probe.NewError(BucketNotFound{ |
|
|
|
|
|
|
|
Bucket: bucket, |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} else if e == errIsNotRegular { |
|
|
|
|
|
|
|
return "", probe.NewError(ObjectExistsAsPrefix{ |
|
|
|
|
|
|
|
Bucket: bucket, |
|
|
|
|
|
|
|
Object: object, |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} else if e == errDiskFull { |
|
|
|
|
|
|
|
return "", probe.NewError(StorageFull{}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return "", probe.NewError(e) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var md5Sums []string |
|
|
|
var md5Sums []string |
|
|
@ -585,16 +540,14 @@ func (o objectAPI) removeMultipartUpload(bucket, object, uploadID string) *probe |
|
|
|
if !IsValidObjectName(object) { |
|
|
|
if !IsValidObjectName(object) { |
|
|
|
return probe.NewError(ObjectNameInvalid{Bucket: bucket, Object: object}) |
|
|
|
return probe.NewError(ObjectNameInvalid{Bucket: bucket, Object: object}) |
|
|
|
} |
|
|
|
} |
|
|
|
if _, e := o.storage.StatVol(minioMetaVolume); e != nil { |
|
|
|
|
|
|
|
return nil |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
marker := "" |
|
|
|
marker := "" |
|
|
|
for { |
|
|
|
for { |
|
|
|
uploadIDPath := path.Join(bucket, object, uploadID) |
|
|
|
uploadIDPath := path.Join(bucket, object, uploadID) |
|
|
|
fileInfos, eof, e := o.storage.ListFiles(minioMetaVolume, uploadIDPath, marker, false, 1000) |
|
|
|
fileInfos, eof, e := o.storage.ListFiles(minioMetaVolume, uploadIDPath, marker, false, 1000) |
|
|
|
if e != nil { |
|
|
|
if e != nil { |
|
|
|
return probe.NewError(ObjectNotFound{Bucket: bucket, Object: object}) |
|
|
|
|
|
|
|
|
|
|
|
return probe.NewError(InvalidUploadID{UploadID: uploadID}) |
|
|
|
} |
|
|
|
} |
|
|
|
for _, fileInfo := range fileInfos { |
|
|
|
for _, fileInfo := range fileInfos { |
|
|
|
o.storage.DeleteFile(minioMetaVolume, fileInfo.Name) |
|
|
|
o.storage.DeleteFile(minioMetaVolume, fileInfo.Name) |
|
|
|