|
|
|
@@ -5,6 +5,7 @@ import ( |
|
|
|
|
|
|
|
"gitlink.org.cn/cloudream/common/utils/lo2" |
|
|
|
"gitlink.org.cn/cloudream/common/utils/math2" |
|
|
|
"gitlink.org.cn/cloudream/common/utils/sync2" |
|
|
|
) |
|
|
|
|
|
|
|
func Join(strs []io.Reader) io.ReadCloser { |
|
|
|
@@ -105,3 +106,51 @@ func ChunkedJoin(inputs []io.Reader, chunkSize int) io.ReadCloser { |
|
|
|
chunkSize: chunkSize, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
type bufferedChunkedJoin struct { |
|
|
|
inputs []io.Reader |
|
|
|
buffer []byte |
|
|
|
chunkSize int |
|
|
|
currentRead int |
|
|
|
err error |
|
|
|
} |
|
|
|
|
|
|
|
func (s *bufferedChunkedJoin) Read(buf []byte) (int, error) { |
|
|
|
if s.err != nil { |
|
|
|
return 0, s.err |
|
|
|
} |
|
|
|
|
|
|
|
if s.currentRead == len(s.buffer) { |
|
|
|
err := sync2.ParallelDo(s.inputs, func(input io.Reader, i int) error { |
|
|
|
bufStart := i * s.chunkSize |
|
|
|
_, err := io.ReadFull(input, s.buffer[bufStart:bufStart+s.chunkSize]) |
|
|
|
return err |
|
|
|
}) |
|
|
|
if err == io.EOF { |
|
|
|
return 0, io.EOF |
|
|
|
} |
|
|
|
if err != nil { |
|
|
|
return 0, err |
|
|
|
} |
|
|
|
s.currentRead = 0 |
|
|
|
} |
|
|
|
|
|
|
|
n := copy(buf, s.buffer[s.currentRead:]) |
|
|
|
s.currentRead += n |
|
|
|
return n, nil |
|
|
|
} |
|
|
|
|
|
|
|
func (s *bufferedChunkedJoin) Close() error { |
|
|
|
s.err = io.ErrClosedPipe |
|
|
|
return nil |
|
|
|
} |
|
|
|
|
|
|
|
func BufferedChunkedJoin(inputs []io.Reader, chunkSize int) io.ReadCloser { |
|
|
|
buffer := make([]byte, len(inputs)*chunkSize) |
|
|
|
return &bufferedChunkedJoin{ |
|
|
|
inputs: inputs, |
|
|
|
buffer: buffer, |
|
|
|
chunkSize: chunkSize, |
|
|
|
currentRead: len(buffer), |
|
|
|
} |
|
|
|
} |