diff --git a/xl-erasure-v1-createfile.go b/xl-erasure-v1-createfile.go index 4b6b6c35b..8e3b8c31f 100644 --- a/xl-erasure-v1-createfile.go +++ b/xl-erasure-v1-createfile.go @@ -20,6 +20,7 @@ import ( "fmt" "io" slashpath "path" + "sync" "time" "github.com/Sirupsen/logrus" @@ -199,24 +200,34 @@ func (xl XL) writeErasure(volume, path string, reader *io.PipeReader, wcloser *w return } + var wg = &sync.WaitGroup{} + var wErrs = make([]error, len(writers)) // Loop through and write encoded data to quorum disks. for index, writer := range writers { if writer == nil { continue } - encodedData := dataBlocks[index] - _, err = writers[index].Write(encodedData) - if err != nil { - log.WithFields(logrus.Fields{ - "volume": volume, - "path": path, - "diskIndex": index, - }).Errorf("Writing encoded blocks failed with %s", err) - // Remove all temp writers upon error. - xl.cleanupCreateFileOps(volume, path, append(writers, metadataWriters...)...) - reader.CloseWithError(err) - return + wg.Add(1) + go func(index int, writer io.Writer) { + defer wg.Done() + encodedData := dataBlocks[index] + _, wErr := writers[index].Write(encodedData) + wErrs[index] = wErr + }(index, writer) + } + wg.Wait() + for _, wErr := range wErrs { + if wErr == nil { + continue } + log.WithFields(logrus.Fields{ + "volume": volume, + "path": path, + }).Errorf("Writing encoded blocks failed with %s", wErr) + // Remove all temp writers upon error. + xl.cleanupCreateFileOps(volume, path, append(writers, metadataWriters...)...) + reader.CloseWithError(wErr) + return } // Update total written. diff --git a/xl-erasure-v1-readfile.go b/xl-erasure-v1-readfile.go index c01fd622a..107a43228 100644 --- a/xl-erasure-v1-readfile.go +++ b/xl-erasure-v1-readfile.go @@ -21,6 +21,7 @@ import ( "fmt" "io" slashpath "path" + "sync" "github.com/Sirupsen/logrus" ) @@ -95,6 +96,7 @@ func (xl XL) ReadFile(volume, path string, startOffset int64) (io.ReadCloser, er // Calculate the current encoded block size. curEncBlockSize := getEncodedBlockLen(curBlockSize, metadata.Erasure.DataBlocks) enBlocks := make([][]byte, len(xl.storageDisks)) + var wg = &sync.WaitGroup{} // Loop through all readers and read. for index, reader := range readers { // Initialize shard slice and fill the data from each parts. @@ -102,11 +104,19 @@ func (xl XL) ReadFile(volume, path string, startOffset int64) (io.ReadCloser, er if reader == nil { continue } - _, err = io.ReadFull(reader, enBlocks[index]) - if err != nil && err != io.ErrUnexpectedEOF { - readers[index] = nil - } + // Parallelize reading. + wg.Add(1) + go func(index int, reader io.Reader) { + defer wg.Done() + // Read the necessary blocks. + _, rErr := io.ReadFull(reader, enBlocks[index]) + if rErr != nil && rErr != io.ErrUnexpectedEOF { + readers[index] = nil + } + }(index, reader) } + // Wait for the read routines to finish. + wg.Wait() // Check blocks if they are all zero in length. if checkBlockSize(enBlocks) == 0 { diff --git a/xl-objects.go b/xl-objects.go index 3b3d173da..e75c0bcd8 100644 --- a/xl-objects.go +++ b/xl-objects.go @@ -109,8 +109,7 @@ func newXLObjects(exportPaths ...string) (ObjectLayer, error) { } } - // Validate if format exists and input arguments are validated - // with backend format. + // Validate if format exists and input arguments are validated with backend format. if !isValidFormat(storage, exportPaths...) { return nil, fmt.Errorf("Command-line arguments %s is not valid.", exportPaths) }