You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

lrc.go 2.3 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package downloader
  2. import (
  3. "fmt"
  4. "io"
  5. "gitlink.org.cn/cloudream/common/pkgs/iterator"
  6. "gitlink.org.cn/cloudream/common/pkgs/logger"
  7. cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
  8. "gitlink.org.cn/cloudream/common/utils/io2"
  9. "gitlink.org.cn/cloudream/common/utils/math2"
  10. )
  11. func (iter *DownloadObjectIterator) downloadLRCObject(req downloadReqeust2, red *cdssdk.LRCRedundancy) (io.ReadCloser, error) {
  12. allNodes, err := iter.sortDownloadNodes(req)
  13. if err != nil {
  14. return nil, err
  15. }
  16. var blocks []downloadBlock
  17. selectedBlkIdx := make(map[int]bool)
  18. for _, node := range allNodes {
  19. for _, b := range node.Blocks {
  20. if b.Index >= red.M() || selectedBlkIdx[b.Index] {
  21. continue
  22. }
  23. blocks = append(blocks, downloadBlock{
  24. Node: node.Node,
  25. Block: b,
  26. })
  27. selectedBlkIdx[b.Index] = true
  28. }
  29. }
  30. if len(blocks) < red.K {
  31. return nil, fmt.Errorf("not enough blocks to download lrc object")
  32. }
  33. var logStrs []any = []any{"downloading lrc object from blocks: "}
  34. for i, b := range blocks {
  35. if i > 0 {
  36. logStrs = append(logStrs, ", ")
  37. }
  38. logStrs = append(logStrs, fmt.Sprintf("%v@%v(%v)", b.Block.Index, b.Node.Name, b.Node.NodeID))
  39. }
  40. logger.Debug(logStrs...)
  41. pr, pw := io.Pipe()
  42. go func() {
  43. readPos := req.Raw.Offset
  44. totalReadLen := req.Detail.Object.Size - req.Raw.Offset
  45. if req.Raw.Length >= 0 {
  46. totalReadLen = math2.Min(req.Raw.Length, totalReadLen)
  47. }
  48. firstStripIndex := readPos / int64(red.K) / int64(red.ChunkSize)
  49. stripIter := NewLRCStripIterator(req.Detail.Object, blocks, red, firstStripIndex, iter.downloader.strips, iter.downloader.cfg.ECStripPrefetchCount)
  50. defer stripIter.Close()
  51. for totalReadLen > 0 {
  52. strip, err := stripIter.MoveNext()
  53. if err == iterator.ErrNoMoreItem {
  54. pw.CloseWithError(io.ErrUnexpectedEOF)
  55. return
  56. }
  57. if err != nil {
  58. pw.CloseWithError(err)
  59. return
  60. }
  61. readRelativePos := readPos - strip.Position
  62. nextStripPos := strip.Position + int64(red.K)*int64(red.ChunkSize)
  63. curReadLen := math2.Min(totalReadLen, nextStripPos-readPos)
  64. err = io2.WriteAll(pw, strip.Data[readRelativePos:readRelativePos+curReadLen])
  65. if err != nil {
  66. pw.CloseWithError(err)
  67. return
  68. }
  69. totalReadLen -= curReadLen
  70. readPos += curReadLen
  71. }
  72. pw.Close()
  73. }()
  74. return pr, nil
  75. }

本项目旨在将云际存储公共基础设施化,使个人及企业可低门槛使用高效的云际存储服务(安装开箱即用云际存储客户端即可,无需关注其他组件的部署),同时支持用户灵活便捷定制云际存储的功能细节。