|
- package downloader
-
- import (
- "fmt"
- "io"
-
- "gitlink.org.cn/cloudream/common/pkgs/iterator"
- "gitlink.org.cn/cloudream/common/pkgs/logger"
- cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
- "gitlink.org.cn/cloudream/common/utils/io2"
- "gitlink.org.cn/cloudream/common/utils/math2"
- )
-
- func (iter *DownloadObjectIterator) downloadLRCObject(req downloadReqeust2, red *cdssdk.LRCRedundancy) (io.ReadCloser, error) {
- allStgs, err := iter.sortDownloadStorages(req)
- if err != nil {
- return nil, err
- }
-
- var blocks []downloadBlock
- selectedBlkIdx := make(map[int]bool)
- for _, stg := range allStgs {
- for _, b := range stg.Blocks {
- if b.Index >= red.M() || selectedBlkIdx[b.Index] {
- continue
- }
- blocks = append(blocks, downloadBlock{
- Storage: stg.Storage,
- Block: b,
- })
- selectedBlkIdx[b.Index] = true
- }
- }
- if len(blocks) < red.K {
- return nil, fmt.Errorf("not enough blocks to download lrc object")
- }
-
- var logStrs []any = []any{"downloading lrc object from blocks: "}
- for i, b := range blocks {
- if i > 0 {
- logStrs = append(logStrs, ", ")
- }
- logStrs = append(logStrs, fmt.Sprintf("%v@%v", b.Block.Index, b.Storage.Storage.String()))
- }
- logger.Debug(logStrs...)
-
- 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(red.K) / int64(red.ChunkSize)
- stripIter := NewLRCStripIterator(iter.downloader, req.Detail.Object, blocks, red, 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(red.K)*int64(red.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
- }
|