From ce5e6383244242adef27e98e9e87d1bcf03d6864 Mon Sep 17 00:00:00 2001 From: Zac Bergquist Date: Wed, 2 Mar 2022 09:43:54 -0700 Subject: [PATCH] Open parts files one at a time When completing a file-based upload, open the parts files one at a time and write them to the upload, closing each file before opening the next one. This is preferrable to opening them all at once and closing all files at the end, because it consumes less file descriptors. Updates #10660 --- lib/events/filesessions/filestream.go | 34 ++++++++++++--------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/lib/events/filesessions/filestream.go b/lib/events/filesessions/filestream.go index bbfb3d746c82a..4a5baf0ad4b12 100644 --- a/lib/events/filesessions/filestream.go +++ b/lib/events/filesessions/filestream.go @@ -124,30 +124,26 @@ func (h *Handler) CompleteUpload(ctx context.Context, upload events.StreamUpload } }() - files := make([]*os.File, 0, len(parts)) - readers := make([]io.Reader, 0, len(parts)) - - defer func() { - for i := 0; i < len(files); i++ { - if err := files[i].Close(); err != nil { - h.WithError(err).Errorf("Failed to close file %q.", files[i].Name()) - } + writePartToFile := func(path string) error { + file, err := os.Open(path) + if err != nil { + return err } - }() + defer func() { + if err := file.Close(); err != nil { + h.WithError(err).Errorf("failed to close file %q", path) + } + }() + + _, err = io.Copy(f, file) + return err + } for _, part := range parts { partPath := h.partPath(upload, part.Number) - file, err := os.Open(partPath) - if err != nil { - return trace.ConvertSystemError(err) + if err := writePartToFile(partPath); err != nil { + return trace.Wrap(err) } - files = append(files, file) - readers = append(readers, file) - } - - _, err = io.Copy(f, io.MultiReader(readers...)) - if err != nil { - return trace.Wrap(err) } err = h.Config.OnBeforeComplete(ctx, upload)