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.

storage.go 6.8 kB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. package mq
  2. import (
  3. "database/sql"
  4. "fmt"
  5. "github.com/samber/lo"
  6. "gitlink.org.cn/cloudream/common/consts/errorcode"
  7. "gitlink.org.cn/cloudream/common/pkgs/logger"
  8. cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
  9. "gorm.io/gorm"
  10. "gitlink.org.cn/cloudream/common/pkgs/mq"
  11. stgmod "gitlink.org.cn/cloudream/storage/common/models"
  12. "gitlink.org.cn/cloudream/storage/common/pkgs/db2"
  13. coormq "gitlink.org.cn/cloudream/storage/common/pkgs/mq/coordinator"
  14. )
  15. func (svc *Service) GetStorage(msg *coormq.GetStorage) (*coormq.GetStorageResp, *mq.CodeMessage) {
  16. stg, err := svc.db2.Storage().GetUserStorage(svc.db2.DefCtx(), msg.UserID, msg.StorageID)
  17. if err != nil {
  18. logger.Warnf("getting user storage: %s", err.Error())
  19. return nil, mq.Failed(errorcode.OperationFailed, "get user storage failed")
  20. }
  21. return mq.ReplyOK(coormq.RespGetStorage(stg))
  22. }
  23. func (svc *Service) GetStorageDetails(msg *coormq.GetStorageDetails) (*coormq.GetStorageDetailsResp, *mq.CodeMessage) {
  24. stgsMp := make(map[cdssdk.StorageID]*stgmod.StorageDetail)
  25. svc.db2.DoTx(func(tx db2.SQLContext) error {
  26. stgs, err := svc.db2.Storage().BatchGetByID(tx, msg.StorageIDs)
  27. if err != nil && err != gorm.ErrRecordNotFound {
  28. return fmt.Errorf("getting storage: %w", err)
  29. }
  30. var masterHubIDs []cdssdk.NodeID
  31. for _, stg := range stgs {
  32. stgsMp[stg.StorageID] = &stgmod.StorageDetail{
  33. Storage: stg,
  34. }
  35. masterHubIDs = append(masterHubIDs, stg.MasterHub)
  36. }
  37. // 获取监护Hub信息
  38. masterHubs, err := svc.db2.Node().BatchGetByID(tx, masterHubIDs)
  39. if err != nil && err != gorm.ErrRecordNotFound {
  40. return fmt.Errorf("getting master hub: %w", err)
  41. }
  42. masterHubMap := make(map[cdssdk.NodeID]cdssdk.Node)
  43. for _, hub := range masterHubs {
  44. masterHubMap[hub.NodeID] = hub
  45. }
  46. // 获取分片存储
  47. shards, err := svc.db2.ShardStorage().BatchGetByStorageIDs(tx, msg.StorageIDs)
  48. if err != nil && err != gorm.ErrRecordNotFound {
  49. return fmt.Errorf("getting shard storage: %w", err)
  50. }
  51. for _, shard := range shards {
  52. stgsMp[shard.StorageID].Shard = &shard
  53. }
  54. for _, stg := range stgsMp {
  55. if stg.Shard != nil {
  56. hub := masterHubMap[stg.MasterHub.NodeID]
  57. stg.MasterHub = &hub
  58. }
  59. }
  60. // 获取共享存储的相关信息
  61. shareds, err := svc.db2.SharedStorage().BatchGetByStorageIDs(tx, msg.StorageIDs)
  62. if err != nil && err != gorm.ErrRecordNotFound {
  63. return fmt.Errorf("getting shared storage: %w", err)
  64. }
  65. for _, shared := range shareds {
  66. stgsMp[shared.StorageID].Shared = &shared
  67. }
  68. return nil
  69. })
  70. ret := make([]*stgmod.StorageDetail, len(msg.StorageIDs))
  71. for i, id := range msg.StorageIDs {
  72. stg, ok := stgsMp[id]
  73. if !ok {
  74. ret[i] = nil
  75. continue
  76. }
  77. ret[i] = stg
  78. }
  79. return mq.ReplyOK(coormq.RespGetStorageDetails(ret))
  80. }
  81. func (svc *Service) GetUserStorageDetails(msg *coormq.GetUserStorageDetails) (*coormq.GetUserStorageDetailsResp, *mq.CodeMessage) {
  82. stgsMp := make(map[cdssdk.StorageID]*stgmod.StorageDetail)
  83. svc.db2.DoTx(func(tx db2.SQLContext) error {
  84. stgs, err := svc.db2.Storage().GetUserStorages(tx, msg.UserID)
  85. if err != nil && err != gorm.ErrRecordNotFound {
  86. return fmt.Errorf("getting user storages: %w", err)
  87. }
  88. var masterHubIDs []cdssdk.NodeID
  89. for _, stg := range stgs {
  90. stgsMp[stg.StorageID] = &stgmod.StorageDetail{
  91. Storage: stg,
  92. }
  93. masterHubIDs = append(masterHubIDs, stg.MasterHub)
  94. }
  95. // 监护Hub的信息
  96. masterHubs, err := svc.db2.Node().BatchGetByID(tx, masterHubIDs)
  97. if err != nil && err != gorm.ErrRecordNotFound {
  98. return fmt.Errorf("getting master hub: %w", err)
  99. }
  100. masterHubMap := make(map[cdssdk.NodeID]cdssdk.Node)
  101. for _, hub := range masterHubs {
  102. masterHubMap[hub.NodeID] = hub
  103. }
  104. stgIDs := lo.Map(stgs, func(stg cdssdk.Storage, i int) cdssdk.StorageID { return stg.StorageID })
  105. // 获取分片存储信息
  106. shards, err := svc.db2.ShardStorage().BatchGetByStorageIDs(tx, stgIDs)
  107. if err != nil && err != gorm.ErrRecordNotFound {
  108. return fmt.Errorf("getting shard storage: %w", err)
  109. }
  110. for _, shard := range shards {
  111. stgsMp[shard.StorageID].Shard = &shard
  112. }
  113. for _, stg := range stgsMp {
  114. if stg.Shard != nil {
  115. hub := masterHubMap[stg.MasterHub.NodeID]
  116. stg.MasterHub = &hub
  117. }
  118. }
  119. // 获取共享存储的相关信息
  120. shareds, err := svc.db2.SharedStorage().BatchGetByStorageIDs(tx, stgIDs)
  121. if err != nil && err != gorm.ErrRecordNotFound {
  122. return fmt.Errorf("getting shared storage: %w", err)
  123. }
  124. for _, shared := range shareds {
  125. stgsMp[shared.StorageID].Shared = &shared
  126. }
  127. return nil
  128. })
  129. var ret []stgmod.StorageDetail
  130. for _, id := range stgsMp {
  131. ret = append(ret, *id)
  132. }
  133. return mq.ReplyOK(coormq.RespGetUserStorageDetails(ret))
  134. }
  135. func (svc *Service) GetStorageByName(msg *coormq.GetStorageByName) (*coormq.GetStorageByNameResp, *mq.CodeMessage) {
  136. stg, err := svc.db2.Storage().GetUserStorageByName(svc.db2.DefCtx(), msg.UserID, msg.Name)
  137. if err != nil {
  138. logger.Warnf("getting user storage by name: %s", err.Error())
  139. if err == sql.ErrNoRows {
  140. return nil, mq.Failed(errorcode.DataNotFound, "storage not found")
  141. }
  142. return nil, mq.Failed(errorcode.OperationFailed, "get user storage failed")
  143. }
  144. return mq.ReplyOK(coormq.RespGetStorageByNameResp(stg))
  145. }
  146. func (svc *Service) StoragePackageLoaded(msg *coormq.StoragePackageLoaded) (*coormq.StoragePackageLoadedResp, *mq.CodeMessage) {
  147. err := svc.db2.DoTx(func(tx db2.SQLContext) error {
  148. // 可以不用检查用户是否存在
  149. if ok, _ := svc.db2.Package().IsAvailable(tx, msg.UserID, msg.PackageID); !ok {
  150. return fmt.Errorf("package is not available to user")
  151. }
  152. if ok, _ := svc.db2.Storage().IsAvailable(tx, msg.UserID, msg.StorageID); !ok {
  153. return fmt.Errorf("storage is not available to user")
  154. }
  155. err := svc.db2.StoragePackage().CreateOrUpdate(tx, msg.StorageID, msg.PackageID, msg.UserID)
  156. if err != nil {
  157. return fmt.Errorf("creating storage package: %w", err)
  158. }
  159. stg, err := svc.db2.Storage().GetByID(tx, msg.StorageID)
  160. if err != nil {
  161. return fmt.Errorf("getting storage: %w", err)
  162. }
  163. err = svc.db2.PinnedObject().CreateFromPackage(tx, msg.PackageID, stg.StorageID)
  164. if err != nil {
  165. return fmt.Errorf("creating pinned object from package: %w", err)
  166. }
  167. if len(msg.PinnedBlocks) > 0 {
  168. err = svc.db2.ObjectBlock().BatchCreate(tx, msg.PinnedBlocks)
  169. if err != nil {
  170. return fmt.Errorf("batch creating object block: %w", err)
  171. }
  172. }
  173. return nil
  174. })
  175. if err != nil {
  176. logger.WithField("UserID", msg.UserID).
  177. WithField("StorageID", msg.StorageID).
  178. WithField("PackageID", msg.PackageID).
  179. Warn(err.Error())
  180. return nil, mq.Failed(errorcode.OperationFailed, "user load package to storage failed")
  181. }
  182. return mq.ReplyOK(coormq.NewStoragePackageLoadedResp())
  183. }

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