JCS-pub/client/internal/downloader/lrc.go

74 lines
2.1 KiB
Go

package downloader
import (
"fmt"
"io"
"gitlink.org.cn/cloudream/common/pkgs/iterator"
"gitlink.org.cn/cloudream/common/pkgs/logger"
"gitlink.org.cn/cloudream/common/utils/io2"
"gitlink.org.cn/cloudream/common/utils/math2"
"gitlink.org.cn/cloudream/jcs-pub/client/internal/downloader/strategy"
)
func (iter *DownloadObjectIterator) downloadLRCReconstruct(req downloadReqeust2, strg strategy.LRCReconstructStrategy) (io.ReadCloser, error) {
var logStrs []any = []any{fmt.Sprintf("downloading lrc object %v from: ", req.Raw.ObjectID)}
for i, b := range strg.Blocks {
if i > 0 {
logStrs = append(logStrs, ", ")
}
logStrs = append(logStrs, fmt.Sprintf("%v@%v", b.Index, strg.Spaces[i].Storage.String()))
}
logger.Debug(logStrs...)
downloadBlks := make([]downloadBlock, len(strg.Blocks))
for i, b := range strg.Blocks {
downloadBlks[i] = downloadBlock{
Block: b,
Space: strg.Spaces[i],
}
}
pr, pw := io.Pipe()
go func() {
readPos := req.Raw.Offset
totalReadLen := req.Detail.Object.Size - req.Raw.Offset
if req.Raw.Length >= 0 {
totalReadLen = math2.Min(req.Raw.Length, totalReadLen)
}
firstStripIndex := readPos / int64(strg.Redundancy.K) / int64(strg.Redundancy.ChunkSize)
stripIter := NewLRCStripIterator(iter.downloader, req.Detail.Object, downloadBlks, strg.Redundancy, firstStripIndex, iter.downloader.strips, iter.downloader.cfg.ECStripPrefetchCount)
defer stripIter.Close()
for totalReadLen > 0 {
strip, err := stripIter.MoveNext()
if err == iterator.ErrNoMoreItem {
pw.CloseWithError(io.ErrUnexpectedEOF)
return
}
if err != nil {
pw.CloseWithError(err)
return
}
readRelativePos := readPos - strip.Position
nextStripPos := strip.Position + int64(strg.Redundancy.K)*int64(strg.Redundancy.ChunkSize)
curReadLen := math2.Min(totalReadLen, nextStripPos-readPos)
err = io2.WriteAll(pw, strip.Data[readRelativePos:readRelativePos+curReadLen])
if err != nil {
pw.CloseWithError(err)
return
}
totalReadLen -= curReadLen
readPos += curReadLen
}
pw.Close()
}()
return pr, nil
}