JCS-pub/client/internal/downloader/downloader.go

143 lines
3.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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]