|
- package downloader
-
- import (
- "fmt"
- "io"
-
- lru "github.com/hashicorp/golang-lru/v2"
- "gitlink.org.cn/cloudream/common/pkgs/iterator"
- "gitlink.org.cn/cloudream/jcs-pub/client/internal/db"
- "gitlink.org.cn/cloudream/jcs-pub/client/internal/downloader/strategy"
- "gitlink.org.cn/cloudream/jcs-pub/client/types"
- "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/connectivity"
- "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/storage/pool"
- )
-
- const (
- DefaultMaxStripCacheCount = 128
- )
-
- type DownloadIterator = iterator.Iterator[*Downloading]
-
- type DownloadReqeust struct {
- ObjectID types.ObjectID
- Offset int64
- Length int64
- }
-
- type downloadReqeust2 struct {
- Detail *types.ObjectDetail
- Raw DownloadReqeust
- }
-
- type Downloading struct {
- Object *types.Object
- File io.ReadCloser // 文件流,如果文件不存在,那么为nil
- Request DownloadReqeust
- }
-
- type Downloader struct {
- strips *StripCache
- cfg Config
- conn *connectivity.Collector
- stgPool *pool.Pool
- selector *strategy.Selector
- db *db.DB
- }
-
- func NewDownloader(cfg Config, conn *connectivity.Collector, stgPool *pool.Pool, sel *strategy.Selector, db *db.DB) *Downloader {
- if cfg.MaxStripCacheCount == 0 {
- cfg.MaxStripCacheCount = DefaultMaxStripCacheCount
- }
-
- ch, _ := lru.New[ECStripKey, ObjectECStrip](cfg.MaxStripCacheCount)
- return &Downloader{
- strips: ch,
- cfg: cfg,
- conn: conn,
- stgPool: stgPool,
- selector: sel,
- db: db,
- }
- }
-
- func (d *Downloader) DownloadObjects(reqs []DownloadReqeust) DownloadIterator {
- objIDs := make([]types.ObjectID, len(reqs))
- for i, req := range reqs {
- objIDs[i] = req.ObjectID
- }
-
- if len(objIDs) == 0 {
- return iterator.Empty[*Downloading]()
- }
-
- objDetails, err := db.DoTx11(d.db, d.db.Object().BatchGetDetails, objIDs)
- if err != nil {
- return iterator.FuseError[*Downloading](fmt.Errorf("request to db: %w", err))
- }
-
- detailsMap := make(map[types.ObjectID]*types.ObjectDetail)
- for _, detail := range objDetails {
- d := detail
- detailsMap[detail.Object.ObjectID] = &d
- }
-
- req2s := make([]downloadReqeust2, len(reqs))
- for i, req := range reqs {
- req2s[i] = downloadReqeust2{
- Detail: detailsMap[req.ObjectID],
- Raw: req,
- }
- }
-
- return NewDownloadObjectIterator(d, req2s)
- }
-
- func (d *Downloader) DownloadObjectByDetail(detail types.ObjectDetail, off int64, length int64) (*Downloading, error) {
- req2s := []downloadReqeust2{{
- Detail: &detail,
- Raw: DownloadReqeust{
- ObjectID: detail.Object.ObjectID,
- Offset: off,
- Length: length,
- },
- }}
-
- iter := NewDownloadObjectIterator(d, req2s)
- return iter.MoveNext()
- }
-
- func (d *Downloader) DownloadPackage(pkgID types.PackageID) DownloadIterator {
- details, err := db.DoTx11(d.db, d.db.Object().GetPackageObjectDetails, pkgID)
- if err != nil {
- return iterator.FuseError[*Downloading](fmt.Errorf("get package object details: %w", err))
- }
-
- req2s := make([]downloadReqeust2, len(details))
- for i, objDetail := range details {
- dt := objDetail
- req2s[i] = downloadReqeust2{
- Detail: &dt,
- Raw: DownloadReqeust{
- ObjectID: objDetail.Object.ObjectID,
- Offset: 0,
- Length: objDetail.Object.Size,
- },
- }
- }
-
- return NewDownloadObjectIterator(d, req2s)
- }
-
- type ObjectECStrip struct {
- Data []byte
- ObjectFileHash types.FileHash // 添加这条缓存时,Object的FileHash
- }
-
- type ECStripKey struct {
- ObjectID types.ObjectID
- StripIndex int64
- }
-
- type StripCache = lru.Cache[ECStripKey, ObjectECStrip]
|