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.

object.go 8.9 kB

1 year ago
1 year ago
1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. package services
  2. import (
  3. "context"
  4. "fmt"
  5. "gitlink.org.cn/cloudream/common/pkgs/ioswitch/exec"
  6. cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
  7. "gitlink.org.cn/cloudream/common/sdks/storage/cdsapi"
  8. stgglb "gitlink.org.cn/cloudream/storage/common/globals"
  9. stgmod "gitlink.org.cn/cloudream/storage/common/models"
  10. "gitlink.org.cn/cloudream/storage/common/pkgs/db2/model"
  11. "gitlink.org.cn/cloudream/storage/common/pkgs/downloader"
  12. "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch2/ops2"
  13. "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch2/plans"
  14. coormq "gitlink.org.cn/cloudream/storage/common/pkgs/mq/coordinator"
  15. )
  16. // ObjectService 定义了对象服务,负责管理对象的上传、下载等操作。
  17. type ObjectService struct {
  18. *Service
  19. }
  20. // ObjectSvc 返回一个ObjectService的实例。
  21. func (svc *Service) ObjectSvc() *ObjectService {
  22. return &ObjectService{Service: svc}
  23. }
  24. func (svc *ObjectService) GetByPath(userID cdssdk.UserID, pkgID cdssdk.PackageID, path string, isPrefix bool, noRecursive bool) ([]string, []cdssdk.Object, error) {
  25. coorCli, err := stgglb.CoordinatorMQPool.Acquire()
  26. if err != nil {
  27. return nil, nil, fmt.Errorf("new coordinator client: %w", err)
  28. }
  29. defer stgglb.CoordinatorMQPool.Release(coorCli)
  30. listResp, err := coorCli.GetObjectsByPath(coormq.ReqGetObjectsByPath(userID, pkgID, path, isPrefix, noRecursive))
  31. if err != nil {
  32. return nil, nil, fmt.Errorf("requsting to coodinator: %w", err)
  33. }
  34. return listResp.CommonPrefixes, listResp.Objects, nil
  35. }
  36. func (svc *ObjectService) GetByIDs(userID cdssdk.UserID, objectIDs []cdssdk.ObjectID) ([]*cdssdk.Object, error) {
  37. coorCli, err := stgglb.CoordinatorMQPool.Acquire()
  38. if err != nil {
  39. return nil, fmt.Errorf("new coordinator client: %w", err)
  40. }
  41. defer stgglb.CoordinatorMQPool.Release(coorCli)
  42. listResp, err := coorCli.GetObjects(coormq.ReqGetObjects(userID, objectIDs))
  43. if err != nil {
  44. return nil, fmt.Errorf("requsting to coodinator: %w", err)
  45. }
  46. return listResp.Objects, nil
  47. }
  48. func (svc *ObjectService) UpdateInfo(userID cdssdk.UserID, updatings []cdsapi.UpdatingObject) ([]cdssdk.ObjectID, error) {
  49. coorCli, err := stgglb.CoordinatorMQPool.Acquire()
  50. if err != nil {
  51. return nil, fmt.Errorf("new coordinator client: %w", err)
  52. }
  53. defer stgglb.CoordinatorMQPool.Release(coorCli)
  54. resp, err := coorCli.UpdateObjectInfos(coormq.ReqUpdateObjectInfos(userID, updatings))
  55. if err != nil {
  56. return nil, fmt.Errorf("requsting to coodinator: %w", err)
  57. }
  58. // TODO 考虑产生Update事件
  59. return resp.Successes, nil
  60. }
  61. func (svc *ObjectService) Move(userID cdssdk.UserID, movings []cdsapi.MovingObject) ([]cdssdk.ObjectID, error) {
  62. coorCli, err := stgglb.CoordinatorMQPool.Acquire()
  63. if err != nil {
  64. return nil, fmt.Errorf("new coordinator client: %w", err)
  65. }
  66. defer stgglb.CoordinatorMQPool.Release(coorCli)
  67. resp, err := coorCli.MoveObjects(coormq.ReqMoveObjects(userID, movings))
  68. if err != nil {
  69. return nil, fmt.Errorf("requsting to coodinator: %w", err)
  70. }
  71. return resp.Successes, nil
  72. }
  73. func (svc *ObjectService) Download(userID cdssdk.UserID, req downloader.DownloadReqeust) (*downloader.Downloading, error) {
  74. // TODO 检查用户ID
  75. iter := svc.Downloader.DownloadObjects([]downloader.DownloadReqeust{req})
  76. // 初始化下载过程
  77. downloading, err := iter.MoveNext()
  78. if downloading == nil {
  79. return nil, fmt.Errorf("object %v not found", req.ObjectID)
  80. }
  81. if err != nil {
  82. return nil, err
  83. }
  84. return downloading, nil
  85. }
  86. func (svc *ObjectService) Delete(userID cdssdk.UserID, objectIDs []cdssdk.ObjectID) error {
  87. coorCli, err := stgglb.CoordinatorMQPool.Acquire()
  88. if err != nil {
  89. return fmt.Errorf("new coordinator client: %w", err)
  90. }
  91. defer stgglb.CoordinatorMQPool.Release(coorCli)
  92. _, err = coorCli.DeleteObjects(coormq.ReqDeleteObjects(userID, objectIDs))
  93. if err != nil {
  94. return fmt.Errorf("requsting to coodinator: %w", err)
  95. }
  96. return nil
  97. }
  98. func (svc *ObjectService) Clone(userID cdssdk.UserID, clonings []cdsapi.CloningObject) ([]*cdssdk.Object, error) {
  99. coorCli, err := stgglb.CoordinatorMQPool.Acquire()
  100. if err != nil {
  101. return nil, fmt.Errorf("new coordinator client: %w", err)
  102. }
  103. defer stgglb.CoordinatorMQPool.Release(coorCli)
  104. resp, err := coorCli.CloneObjects(coormq.ReqCloneObjects(userID, clonings))
  105. if err != nil {
  106. return nil, fmt.Errorf("requsting to coodinator: %w", err)
  107. }
  108. return resp.Objects, nil
  109. }
  110. // GetPackageObjects 获取包中的对象列表。
  111. // userID: 用户ID。
  112. // packageID: 包ID。
  113. // 返回值: 对象列表和错误信息。
  114. func (svc *ObjectService) GetPackageObjects(userID cdssdk.UserID, packageID cdssdk.PackageID) ([]model.Object, error) {
  115. coorCli, err := stgglb.CoordinatorMQPool.Acquire() // 获取协调器客户端
  116. if err != nil {
  117. return nil, fmt.Errorf("new coordinator client: %w", err)
  118. }
  119. defer stgglb.CoordinatorMQPool.Release(coorCli) // 释放协调器客户端资源
  120. getResp, err := coorCli.GetPackageObjects(coormq.ReqGetPackageObjects(userID, packageID)) // 请求协调器获取套餐对象
  121. if err != nil {
  122. return nil, fmt.Errorf("requesting to coordinator: %w", err)
  123. }
  124. return getResp.Objects, nil
  125. }
  126. func (svc *ObjectService) GetObjectDetail(objectID cdssdk.ObjectID) (*stgmod.ObjectDetail, error) {
  127. coorCli, err := stgglb.CoordinatorMQPool.Acquire()
  128. if err != nil {
  129. return nil, fmt.Errorf("new coordinator client: %w", err)
  130. }
  131. defer stgglb.CoordinatorMQPool.Release(coorCli)
  132. getResp, err := coorCli.GetObjectDetails(coormq.ReqGetObjectDetails([]cdssdk.ObjectID{objectID}))
  133. if err != nil {
  134. return nil, fmt.Errorf("requsting to coodinator: %w", err)
  135. }
  136. return getResp.Objects[0], nil
  137. }
  138. func (svc *ObjectService) NewMultipartUploadObject(userID cdssdk.UserID, pkgID cdssdk.PackageID, path string) (cdssdk.Object, error) {
  139. coorCli, err := stgglb.CoordinatorMQPool.Acquire()
  140. if err != nil {
  141. return cdssdk.Object{}, fmt.Errorf("new coordinator client: %w", err)
  142. }
  143. defer stgglb.CoordinatorMQPool.Release(coorCli)
  144. resp, err := coorCli.NewMultipartUploadObject(coormq.ReqNewMultipartUploadObject(userID, pkgID, path))
  145. if err != nil {
  146. return cdssdk.Object{}, err
  147. }
  148. return resp.Object, nil
  149. }
  150. func (svc *ObjectService) CompleteMultipartUpload(userID cdssdk.UserID, objectID cdssdk.ObjectID, indexes []int) (cdssdk.Object, error) {
  151. if len(indexes) == 0 {
  152. return cdssdk.Object{}, fmt.Errorf("no block indexes specified")
  153. }
  154. coorCli, err := stgglb.CoordinatorMQPool.Acquire()
  155. if err != nil {
  156. return cdssdk.Object{}, fmt.Errorf("new coordinator client: %w", err)
  157. }
  158. defer stgglb.CoordinatorMQPool.Release(coorCli)
  159. details, err := coorCli.GetObjectDetails(coormq.ReqGetObjectDetails([]cdssdk.ObjectID{objectID}))
  160. if err != nil {
  161. return cdssdk.Object{}, err
  162. }
  163. if details.Objects[0] == nil {
  164. return cdssdk.Object{}, fmt.Errorf("object %v not found", objectID)
  165. }
  166. objDe := details.Objects[0]
  167. _, ok := objDe.Object.Redundancy.(*cdssdk.MultipartUploadRedundancy)
  168. if !ok {
  169. return cdssdk.Object{}, fmt.Errorf("object %v is not a multipart upload", objectID)
  170. }
  171. if len(objDe.Blocks) == 0 {
  172. return cdssdk.Object{}, fmt.Errorf("object %v has no blocks", objectID)
  173. }
  174. objBlkMap := make(map[int]stgmod.ObjectBlock)
  175. for _, blk := range objDe.Blocks {
  176. objBlkMap[blk.Index] = blk
  177. }
  178. var compBlks []stgmod.ObjectBlock
  179. var compBlkStgs []stgmod.StorageDetail
  180. var targetStg stgmod.StorageDetail
  181. for i, idx := range indexes {
  182. blk, ok := objBlkMap[idx]
  183. if !ok {
  184. return cdssdk.Object{}, fmt.Errorf("block %d not found in object %v", idx, objectID)
  185. }
  186. stg := svc.StorageMeta.Get(blk.StorageID)
  187. if stg == nil {
  188. return cdssdk.Object{}, fmt.Errorf("storage %d not found", blk.StorageID)
  189. }
  190. compBlks = append(compBlks, blk)
  191. compBlkStgs = append(compBlkStgs, *stg)
  192. if i == 0 {
  193. targetStg = *stg
  194. }
  195. }
  196. bld := exec.NewPlanBuilder()
  197. err = plans.CompleteMultipart(compBlks, compBlkStgs, targetStg, "shard", bld)
  198. if err != nil {
  199. return cdssdk.Object{}, err
  200. }
  201. exeCtx := exec.NewExecContext()
  202. ret, err := bld.Execute(exeCtx).Wait(context.Background())
  203. if err != nil {
  204. return cdssdk.Object{}, err
  205. }
  206. shardInfo := ret["shard"].(*ops2.ShardInfoValue)
  207. _, err = coorCli.UpdateObjectRedundancy(coormq.ReqUpdateObjectRedundancy([]coormq.UpdatingObjectRedundancy{
  208. {
  209. ObjectID: objectID,
  210. FileHash: shardInfo.Hash,
  211. Size: shardInfo.Size,
  212. Redundancy: cdssdk.NewNoneRedundancy(),
  213. Blocks: []stgmod.ObjectBlock{{
  214. ObjectID: objectID,
  215. Index: 0,
  216. StorageID: targetStg.Storage.StorageID,
  217. FileHash: shardInfo.Hash,
  218. Size: shardInfo.Size,
  219. }},
  220. },
  221. }))
  222. if err != nil {
  223. return cdssdk.Object{}, err
  224. }
  225. getObj, err := coorCli.GetObjects(coormq.ReqGetObjects(userID, []cdssdk.ObjectID{objectID}))
  226. if err != nil {
  227. return cdssdk.Object{}, err
  228. }
  229. if getObj.Objects[0] == nil {
  230. return cdssdk.Object{}, fmt.Errorf("object %v not found", objectID)
  231. }
  232. return *getObj.Objects[0], nil
  233. }

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