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.

downloader.go 4.1 kB

7 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. package downloader
  2. import (
  3. "fmt"
  4. "io"
  5. lru "github.com/hashicorp/golang-lru/v2"
  6. "gitlink.org.cn/cloudream/common/pkgs/iterator"
  7. "gitlink.org.cn/cloudream/storage2/client/internal/db"
  8. "gitlink.org.cn/cloudream/storage2/client/types"
  9. stgglb "gitlink.org.cn/cloudream/storage2/common/globals"
  10. "gitlink.org.cn/cloudream/storage2/common/pkgs/connectivity"
  11. "gitlink.org.cn/cloudream/storage2/common/pkgs/downloader/strategy"
  12. coormq "gitlink.org.cn/cloudream/storage2/common/pkgs/mq/coordinator"
  13. "gitlink.org.cn/cloudream/storage2/common/pkgs/storage/agtpool"
  14. )
  15. const (
  16. DefaultMaxStripCacheCount = 128
  17. )
  18. type DownloadIterator = iterator.Iterator[*Downloading]
  19. type DownloadReqeust struct {
  20. ObjectID types.ObjectID
  21. Offset int64
  22. Length int64
  23. }
  24. type downloadReqeust2 struct {
  25. Detail *types.ObjectDetail
  26. Raw DownloadReqeust
  27. }
  28. type Downloading struct {
  29. Object *types.Object
  30. File io.ReadCloser // 文件流,如果文件不存在,那么为nil
  31. Request DownloadReqeust
  32. }
  33. type Downloader struct {
  34. strips *StripCache
  35. cfg Config
  36. conn *connectivity.Collector
  37. stgAgts *agtpool.AgentPool
  38. selector *strategy.Selector
  39. db *db.DB
  40. }
  41. func NewDownloader(cfg Config, conn *connectivity.Collector, stgAgts *agtpool.AgentPool, sel *strategy.Selector, db *db.DB) Downloader {
  42. if cfg.MaxStripCacheCount == 0 {
  43. cfg.MaxStripCacheCount = DefaultMaxStripCacheCount
  44. }
  45. ch, _ := lru.New[ECStripKey, ObjectECStrip](cfg.MaxStripCacheCount)
  46. return Downloader{
  47. strips: ch,
  48. cfg: cfg,
  49. conn: conn,
  50. stgAgts: stgAgts,
  51. selector: sel,
  52. db: db,
  53. }
  54. }
  55. func (d *Downloader) DownloadObjects(reqs []DownloadReqeust) DownloadIterator {
  56. coorCli, err := stgglb.CoordinatorMQPool.Acquire()
  57. if err != nil {
  58. return iterator.FuseError[*Downloading](fmt.Errorf("new coordinator client: %w", err))
  59. }
  60. defer stgglb.CoordinatorMQPool.Release(coorCli)
  61. objIDs := make([]types.ObjectID, len(reqs))
  62. for i, req := range reqs {
  63. objIDs[i] = req.ObjectID
  64. }
  65. if len(objIDs) == 0 {
  66. return iterator.Empty[*Downloading]()
  67. }
  68. // objDetails, err := coorCli.GetObjectDetails(coormq.ReqGetObjectDetails(objIDs))
  69. // if err != nil {
  70. // return iterator.FuseError[*Downloading](fmt.Errorf("request to coordinator: %w", err))
  71. // }
  72. objDetails, err := d.db.GetObjectDetails(objIDs)
  73. if err != nil {
  74. return iterator.FuseError[*Downloading](fmt.Errorf("request to db: %w", err))
  75. }
  76. req2s := make([]downloadReqeust2, len(reqs))
  77. for i, req := range reqs {
  78. req2s[i] = downloadReqeust2{
  79. Detail: objDetails.Objects[i],
  80. Raw: req,
  81. }
  82. }
  83. return NewDownloadObjectIterator(d, req2s)
  84. }
  85. func (d *Downloader) DownloadObjectByDetail(detail types.ObjectDetail, off int64, length int64) (*Downloading, error) {
  86. req2s := []downloadReqeust2{{
  87. Detail: &detail,
  88. Raw: DownloadReqeust{
  89. ObjectID: detail.Object.ObjectID,
  90. Offset: off,
  91. Length: length,
  92. },
  93. }}
  94. iter := NewDownloadObjectIterator(d, req2s)
  95. return iter.MoveNext()
  96. }
  97. func (d *Downloader) DownloadPackage(pkgID types.PackageID) DownloadIterator {
  98. coorCli, err := stgglb.CoordinatorMQPool.Acquire()
  99. if err != nil {
  100. return iterator.FuseError[*Downloading](fmt.Errorf("new coordinator client: %w", err))
  101. }
  102. defer stgglb.CoordinatorMQPool.Release(coorCli)
  103. pkgDetail, err := coorCli.GetPackageObjectDetails(coormq.ReqGetPackageObjectDetails(pkgID))
  104. if err != nil {
  105. return iterator.FuseError[*Downloading](fmt.Errorf("request to coordinator: %w", err))
  106. }
  107. req2s := make([]downloadReqeust2, len(pkgDetail.Objects))
  108. for i, objDetail := range pkgDetail.Objects {
  109. dt := objDetail
  110. req2s[i] = downloadReqeust2{
  111. Detail: &dt,
  112. Raw: DownloadReqeust{
  113. ObjectID: objDetail.Object.ObjectID,
  114. Offset: 0,
  115. Length: objDetail.Object.Size,
  116. },
  117. }
  118. }
  119. return NewDownloadObjectIterator(d, req2s)
  120. }
  121. type ObjectECStrip struct {
  122. Data []byte
  123. ObjectFileHash types.FileHash // 添加这条缓存时,Object的FileHash
  124. }
  125. type ECStripKey struct {
  126. ObjectID types.ObjectID
  127. StripIndex int64
  128. }
  129. type StripCache = lru.Cache[ECStripKey, ObjectECStrip]

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