package services import ( "context" "fmt" "path" "gitlink.org.cn/cloudream/common/pkgs/ioswitch/exec" cdssdk "gitlink.org.cn/cloudream/storage2/client/types" "gitlink.org.cn/cloudream/storage2/client/internal/db" "gitlink.org.cn/cloudream/storage2/client/internal/downloader/strategy" "gitlink.org.cn/cloudream/storage2/client/types" stgglb "gitlink.org.cn/cloudream/storage2/common/globals" "gitlink.org.cn/cloudream/storage2/common/pkgs/ioswitch2" "gitlink.org.cn/cloudream/storage2/common/pkgs/ioswitch2/parser" ) type UserSpaceService struct { *Service } func (svc *Service) UserSpaceSvc() *UserSpaceService { return &UserSpaceService{Service: svc} } func (svc *UserSpaceService) Get(userspaceID cdssdk.UserSpaceID) (types.UserSpace, error) { return svc.DB.UserSpace().GetByID(svc.DB.DefCtx(), userspaceID) } func (svc *UserSpaceService) GetByName(name string) (types.UserSpace, error) { return svc.DB.UserSpace().GetByName(svc.DB.DefCtx(), name) } func (svc *UserSpaceService) LoadPackage(packageID cdssdk.PackageID, userspaceID cdssdk.UserSpaceID, rootPath string) error { coorCli, err := stgglb.CoordinatorMQPool.Acquire() if err != nil { return fmt.Errorf("new coordinator client: %w", err) } defer stgglb.CoordinatorMQPool.Release(coorCli) destStg := svc.UserSpaceMeta.Get(userspaceID) if destStg == nil { return fmt.Errorf("userspace not found: %d", userspaceID) } if destStg.MasterHub == nil { return fmt.Errorf("userspace %v has no master hub", userspaceID) } details, err := db.DoTx11(svc.DB, svc.DB.Object().GetPackageObjectDetails, packageID) if err != nil { return err } var pinned []cdssdk.ObjectID plans := exec.NewPlanBuilder() for _, obj := range details { strg, err := svc.StrategySelector.Select(strategy.Request{ Detail: obj, DestHub: destStg.MasterHub.HubID, }) if err != nil { return fmt.Errorf("select download strategy: %w", err) } ft := ioswitch2.NewFromTo() switch strg := strg.(type) { case *strategy.DirectStrategy: ft.AddFrom(ioswitch2.NewFromShardstore(strg.Detail.Object.FileHash, *strg.UserSpace.MasterHub, strg.UserSpace, ioswitch2.RawStream())) case *strategy.ECReconstructStrategy: for i, b := range strg.Blocks { ft.AddFrom(ioswitch2.NewFromShardstore(b.FileHash, *strg.UserSpaces[i].MasterHub, strg.UserSpaces[i], ioswitch2.ECStream(b.Index))) ft.ECParam = &strg.Redundancy } default: return fmt.Errorf("unsupported download strategy: %T", strg) } ft.AddTo(ioswitch2.NewLoadToPublic(*destStg.MasterHub, *destStg, path.Join(rootPath, obj.Object.Path))) // 顺便保存到同存储服务的分片存储中 if destStg.UserSpace.ShardStore != nil { ft.AddTo(ioswitch2.NewToShardStore(*destStg.MasterHub, *destStg, ioswitch2.RawStream(), "")) pinned = append(pinned, obj.Object.ObjectID) } err = parser.Parse(ft, plans) if err != nil { return fmt.Errorf("parse plan: %w", err) } } // TODO2 加锁 // mutex, err := reqbuilder.NewBuilder(). // // 保护在userspace目录中下载的文件 // UserSpace().Buzy(userspaceID). // // 保护下载文件时同时保存到IPFS的文件 // Shard().Buzy(userspaceID). // MutexLock(svc.DistLock) // if err != nil { // return fmt.Errorf("acquire locks failed, err: %w", err) // } // defer mutex.Unlock() // 记录访问统计 for _, obj := range details { svc.AccessStat.AddAccessCounter(obj.Object.ObjectID, packageID, userspaceID, 1) } drv := plans.Execute(exec.NewExecContext()) _, err = drv.Wait(context.Background()) if err != nil { return err } return nil } // 请求节点启动从UserSpace中上传文件的任务。会返回节点ID和任务ID func (svc *UserSpaceService) UserSpaceCreatePackage(bucketID cdssdk.BucketID, name string, userspaceID cdssdk.UserSpaceID, path string, userspaceAffinity cdssdk.UserSpaceID) (cdssdk.Package, error) { // coorCli, err := stgglb.CoordinatorMQPool.Acquire() // if err != nil { // return cdssdk.Package{}, fmt.Errorf("new coordinator client: %w", err) // } // defer stgglb.CoordinatorMQPool.Release(coorCli) // stgResp, err := coorCli.GetUserSpaceDetails(coormq.ReqGetUserSpaceDetails([]cdssdk.UserSpaceID{userspaceID})) // if err != nil { // return cdssdk.Package{}, fmt.Errorf("getting userspace info: %w", err) // } // spaceDetail := svc.UserSpaceMeta.Get(userspaceID) // if spaceDetail == nil { // return cdssdk.Package{}, fmt.Errorf("userspace not found: %d", userspaceID) // } // if spaceDetail.UserSpace.ShardStore == nil { // return cdssdk.Package{}, fmt.Errorf("shard userspace is not enabled") // } // agentCli, err := stgglb.AgentMQPool.Acquire(spaceDetail.MasterHub.HubID) // if err != nil { // return cdssdk.Package{}, fmt.Errorf("new agent client: %w", err) // } // defer stgglb.AgentMQPool.Release(agentCli) // createResp, err := agentCli.UserSpaceCreatePackage(agtmq.ReqUserSpaceCreatePackage(bucketID, name, userspaceID, path, userspaceAffinity)) // if err != nil { // return cdssdk.Package{}, err // } // return createResp.Package, nil // TODO 待实现 return cdssdk.Package{}, fmt.Errorf("not implemented") }