Skip to content

Commit

Permalink
stores: fix completing very large mutipart uploads (#651)
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisSchinnerl authored Oct 6, 2023
1 parent d55b609 commit fb2b3e0
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 22 deletions.
25 changes: 5 additions & 20 deletions stores/multipart.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,10 +372,6 @@ func (s *SQLStore) CompleteMultipartUpload(ctx context.Context, bucket, path str
sum := h.Sum()
eTag = hex.EncodeToString(sum[:])

// Sort their primary keys to make sure retrieving them later will
// respect the part order.
sort.Sort(sortedSlices(slices))

// Create the object.
obj := dbObject{
DBBucketID: mu.DBBucketID,
Expand All @@ -389,14 +385,17 @@ func (s *SQLStore) CompleteMultipartUpload(ctx context.Context, bucket, path str
return fmt.Errorf("failed to create object: %w", err)
}

// Assign the right object id and unassign the multipart upload.
// Assign the right object id and unassign the multipart upload. Also
// clear the ID to make sure new slices are created with IDs in
// ascending order.
for i := range slices {
slices[i].ID = 0
slices[i].DBObjectID = &obj.ID
slices[i].DBMultipartPartID = nil
}

// Save updated slices.
if err := tx.Save(slices).Error; err != nil {
if err := tx.CreateInBatches(slices, 100).Error; err != nil {
return fmt.Errorf("failed to save slices: %w", err)
}

Expand All @@ -414,20 +413,6 @@ func (s *SQLStore) CompleteMultipartUpload(ctx context.Context, bucket, path str
}, nil
}

type sortedSlices []dbSlice

func (s sortedSlices) Len() int {
return len(s)
}

func (s sortedSlices) Less(i, j int) bool {
return s[i].ID < s[j].ID
}

func (s sortedSlices) Swap(i, j int) {
s[i].ID, s[j].ID = s[j].ID, s[i].ID
}

func (u dbMultipartUpload) convert() (api.MultipartUpload, error) {
var key object.EncryptionKey
if err := key.UnmarshalText(u.Key); err != nil {
Expand Down
15 changes: 13 additions & 2 deletions stores/multipart_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,20 @@ func TestMultipartUploadWithUploadPackingRegression(t *testing.T) {
ETag: etag,
})
}
_, err = db.CompleteMultipartUpload(ctx, api.DefaultBucketName, objName, resp.UploadID, parts)
if err != nil {

// Complete the upload. Check that the number of slices stays the same.
var nSlicesBefore int64
var nSlicesAfter int64
if err := db.db.Model(&dbSlice{}).Count(&nSlicesBefore).Error; err != nil {
t.Fatal(err)
} else if nSlicesBefore == 0 {
t.Fatal("expected some slices")
} else if _, err = db.CompleteMultipartUpload(ctx, api.DefaultBucketName, objName, resp.UploadID, parts); err != nil {
t.Fatal(err)
} else if err := db.db.Model(&dbSlice{}).Count(&nSlicesAfter).Error; err != nil {
t.Fatal(err)
} else if nSlicesBefore != nSlicesAfter {
t.Fatalf("expected number of slices to stay the same, but got %v before and %v after", nSlicesBefore, nSlicesAfter)
}

// Fetch the object.
Expand Down

0 comments on commit fb2b3e0

Please sign in to comment.