fs: PutObject create 0byte objects properly. (#3387)

Current code always appends to a file only if 1byte or
more was sent on the wire was affecting both PutObject
and PutObjectPart uploads.

This patch fixes such a situation and resolves #3385
master
Harshavardhana 8 years ago committed by GitHub
parent 67509453d3
commit cf17fc7774
  1. 2
      cmd/fs-createfile.go
  2. 1
      cmd/fs-v1-multipart.go
  3. 10
      cmd/fs-v1-multipart_test.go
  4. 12
      cmd/fs-v1.go

@ -27,12 +27,10 @@ func fsCreateFile(disk StorageAPI, reader io.Reader, buf []byte, tmpBucket, temp
return 0, traceError(rErr) return 0, traceError(rErr)
} }
bytesWritten += int64(n) bytesWritten += int64(n)
if n > 0 {
wErr := disk.AppendFile(tmpBucket, tempObj, buf[0:n]) wErr := disk.AppendFile(tmpBucket, tempObj, buf[0:n])
if wErr != nil { if wErr != nil {
return 0, traceError(wErr) return 0, traceError(wErr)
} }
}
if rErr == io.EOF { if rErr == io.EOF {
break break
} }

@ -301,6 +301,7 @@ func (fs fsObjects) PutObjectPart(bucket, object, uploadID string, partID int, s
fs.storage.DeleteFile(minioMetaTmpBucket, tmpPartPath) fs.storage.DeleteFile(minioMetaTmpBucket, tmpPartPath)
return "", toObjectErr(cErr, minioMetaTmpBucket, tmpPartPath) return "", toObjectErr(cErr, minioMetaTmpBucket, tmpPartPath)
} }
// Should return IncompleteBody{} error when reader has fewer // Should return IncompleteBody{} error when reader has fewer
// bytes than specified in request header. // bytes than specified in request header.
if bytesWritten < size { if bytesWritten < size {

@ -59,6 +59,12 @@ func TestNewMultipartUploadFaultyDisk(t *testing.T) {
// TestPutObjectPartFaultyDisk - test PutObjectPart with faulty disks // TestPutObjectPartFaultyDisk - test PutObjectPart with faulty disks
func TestPutObjectPartFaultyDisk(t *testing.T) { func TestPutObjectPartFaultyDisk(t *testing.T) {
root, err := newTestConfig("us-east-1")
if err != nil {
t.Fatal(err)
}
defer removeAll(root)
// Prepare for tests // Prepare for tests
disk := filepath.Join(os.TempDir(), "minio-"+nextSuffix()) disk := filepath.Join(os.TempDir(), "minio-"+nextSuffix())
defer removeAll(disk) defer removeAll(disk)
@ -69,7 +75,7 @@ func TestPutObjectPartFaultyDisk(t *testing.T) {
data := []byte("12345") data := []byte("12345")
dataLen := int64(len(data)) dataLen := int64(len(data))
if err := obj.MakeBucket(bucketName); err != nil { if err = obj.MakeBucket(bucketName); err != nil {
t.Fatal("Cannot create bucket, err: ", err) t.Fatal("Cannot create bucket, err: ", err)
} }
@ -97,7 +103,7 @@ func TestPutObjectPartFaultyDisk(t *testing.T) {
t.Fatal("Unexpected error ", err) t.Fatal("Unexpected error ", err)
} }
case 3: case 3:
case 2, 4, 5: case 2, 4, 5, 6:
if !isSameType(errorCause(err), InvalidUploadID{}) { if !isSameType(errorCause(err), InvalidUploadID{}) {
t.Fatal("Unexpected error ", err) t.Fatal("Unexpected error ", err)
} }

@ -392,15 +392,6 @@ func (fs fsObjects) PutObject(bucket string, object string, size int64, data io.
limitDataReader = data limitDataReader = data
} }
if size == 0 {
// For size 0 we write a 0byte file.
err = fs.storage.AppendFile(minioMetaTmpBucket, tempObj, []byte(""))
if err != nil {
fs.storage.DeleteFile(minioMetaTmpBucket, tempObj)
return ObjectInfo{}, toObjectErr(traceError(err), bucket, object)
}
} else {
// Prepare file to avoid disk fragmentation // Prepare file to avoid disk fragmentation
if size > 0 { if size > 0 {
err = fs.storage.PrepareFile(minioMetaTmpBucket, tempObj, size) err = fs.storage.PrepareFile(minioMetaTmpBucket, tempObj, size)
@ -414,6 +405,7 @@ func (fs fsObjects) PutObject(bucket string, object string, size int64, data io.
if size > 0 && bufSize > size { if size > 0 && bufSize > size {
bufSize = size bufSize = size
} }
buf := make([]byte, int(bufSize)) buf := make([]byte, int(bufSize))
teeReader := io.TeeReader(limitDataReader, multiWriter) teeReader := io.TeeReader(limitDataReader, multiWriter)
var bytesWritten int64 var bytesWritten int64
@ -430,7 +422,7 @@ func (fs fsObjects) PutObject(bucket string, object string, size int64, data io.
fs.storage.DeleteFile(minioMetaTmpBucket, tempObj) fs.storage.DeleteFile(minioMetaTmpBucket, tempObj)
return ObjectInfo{}, traceError(IncompleteBody{}) return ObjectInfo{}, traceError(IncompleteBody{})
} }
}
// Delete the temporary object in the case of a // Delete the temporary object in the case of a
// failure. If PutObject succeeds, then there would be // failure. If PutObject succeeds, then there would be
// nothing to delete. // nothing to delete.

Loading…
Cancel
Save