Sorting completed parts by part number for a better accordance with the S3 spec
Signed-off-by: Anis Elleuch <vadmeste@gmail.com>master
							parent
							
								
									cd27f179f2
								
							
						
					
					
						commit
						987faca8a6
					
				| 
						 | 
					@ -18,6 +18,7 @@ import (
 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"reflect"
 | 
						"reflect"
 | 
				
			||||||
 | 
						"sort"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
| 
						 | 
					@ -718,6 +719,12 @@ func (d *driver) newWriter(key, uploadID string, parts []*s3.Part) storagedriver
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type completedParts []*s3.CompletedPart
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a completedParts) Len() int           { return len(a) }
 | 
				
			||||||
 | 
					func (a completedParts) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
 | 
				
			||||||
 | 
					func (a completedParts) Less(i, j int) bool { return *a[i].PartNumber < *a[j].PartNumber }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (w *writer) Write(p []byte) (int, error) {
 | 
					func (w *writer) Write(p []byte) (int, error) {
 | 
				
			||||||
	if w.closed {
 | 
						if w.closed {
 | 
				
			||||||
		return 0, fmt.Errorf("already closed")
 | 
							return 0, fmt.Errorf("already closed")
 | 
				
			||||||
| 
						 | 
					@ -730,19 +737,22 @@ func (w *writer) Write(p []byte) (int, error) {
 | 
				
			||||||
	// If the last written part is smaller than minChunkSize, we need to make a
 | 
						// If the last written part is smaller than minChunkSize, we need to make a
 | 
				
			||||||
	// new multipart upload :sadface:
 | 
						// new multipart upload :sadface:
 | 
				
			||||||
	if len(w.parts) > 0 && int(*w.parts[len(w.parts)-1].Size) < minChunkSize {
 | 
						if len(w.parts) > 0 && int(*w.parts[len(w.parts)-1].Size) < minChunkSize {
 | 
				
			||||||
		var completedParts []*s3.CompletedPart
 | 
							var completedUploadedParts completedParts
 | 
				
			||||||
		for _, part := range w.parts {
 | 
							for _, part := range w.parts {
 | 
				
			||||||
			completedParts = append(completedParts, &s3.CompletedPart{
 | 
								completedUploadedParts = append(completedUploadedParts, &s3.CompletedPart{
 | 
				
			||||||
				ETag:       part.ETag,
 | 
									ETag:       part.ETag,
 | 
				
			||||||
				PartNumber: part.PartNumber,
 | 
									PartNumber: part.PartNumber,
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sort.Sort(completedUploadedParts)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		_, err := w.driver.S3.CompleteMultipartUpload(&s3.CompleteMultipartUploadInput{
 | 
							_, err := w.driver.S3.CompleteMultipartUpload(&s3.CompleteMultipartUploadInput{
 | 
				
			||||||
			Bucket:   aws.String(w.driver.Bucket),
 | 
								Bucket:   aws.String(w.driver.Bucket),
 | 
				
			||||||
			Key:      aws.String(w.key),
 | 
								Key:      aws.String(w.key),
 | 
				
			||||||
			UploadId: aws.String(w.uploadID),
 | 
								UploadId: aws.String(w.uploadID),
 | 
				
			||||||
			MultipartUpload: &s3.CompletedMultipartUpload{
 | 
								MultipartUpload: &s3.CompletedMultipartUpload{
 | 
				
			||||||
				Parts: completedParts,
 | 
									Parts: completedUploadedParts,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -882,19 +892,23 @@ func (w *writer) Commit() error {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	w.committed = true
 | 
						w.committed = true
 | 
				
			||||||
	var completedParts []*s3.CompletedPart
 | 
					
 | 
				
			||||||
 | 
						var completedUploadedParts completedParts
 | 
				
			||||||
	for _, part := range w.parts {
 | 
						for _, part := range w.parts {
 | 
				
			||||||
		completedParts = append(completedParts, &s3.CompletedPart{
 | 
							completedUploadedParts = append(completedUploadedParts, &s3.CompletedPart{
 | 
				
			||||||
			ETag:       part.ETag,
 | 
								ETag:       part.ETag,
 | 
				
			||||||
			PartNumber: part.PartNumber,
 | 
								PartNumber: part.PartNumber,
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sort.Sort(completedUploadedParts)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err = w.driver.S3.CompleteMultipartUpload(&s3.CompleteMultipartUploadInput{
 | 
						_, err = w.driver.S3.CompleteMultipartUpload(&s3.CompleteMultipartUploadInput{
 | 
				
			||||||
		Bucket:   aws.String(w.driver.Bucket),
 | 
							Bucket:   aws.String(w.driver.Bucket),
 | 
				
			||||||
		Key:      aws.String(w.key),
 | 
							Key:      aws.String(w.key),
 | 
				
			||||||
		UploadId: aws.String(w.uploadID),
 | 
							UploadId: aws.String(w.uploadID),
 | 
				
			||||||
		MultipartUpload: &s3.CompletedMultipartUpload{
 | 
							MultipartUpload: &s3.CompletedMultipartUpload{
 | 
				
			||||||
			Parts: completedParts,
 | 
								Parts: completedUploadedParts,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue