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 3.5 kB

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

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