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 7.4 kB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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. for _, stg := range stgsMp {
  47. if stg.Storage.MasterHub != 0 {
  48. hub, ok := masterHubMap[stg.Storage.MasterHub]
  49. if !ok {
  50. logger.Warnf("master hub %v of storage %v not found, this storage will not be add to result", stg.Storage.MasterHub, stg.Storage)
  51. delete(stgsMp, stg.Storage.StorageID)
  52. continue
  53. }
  54. stg.MasterHub = &hub
  55. }
  56. }
  57. // 获取分片存储
  58. shards, err := svc.db2.ShardStorage().BatchGetByStorageIDs(tx, msg.StorageIDs)
  59. if err != nil && err != gorm.ErrRecordNotFound {
  60. return fmt.Errorf("getting shard storage: %w", err)
  61. }
  62. for _, shard := range shards {
  63. stg := stgsMp[shard.StorageID]
  64. if stg == nil {
  65. continue
  66. }
  67. stg.Shard = &shard
  68. }
  69. // 获取共享存储的相关信息
  70. shareds, err := svc.db2.SharedStorage().BatchGetByStorageIDs(tx, msg.StorageIDs)
  71. if err != nil && err != gorm.ErrRecordNotFound {
  72. return fmt.Errorf("getting shared storage: %w", err)
  73. }
  74. for _, shared := range shareds {
  75. stg := stgsMp[shared.StorageID]
  76. if stg == nil {
  77. continue
  78. }
  79. stg.Shared = &shared
  80. }
  81. return nil
  82. })
  83. ret := make([]*stgmod.StorageDetail, len(msg.StorageIDs))
  84. for i, id := range msg.StorageIDs {
  85. stg, ok := stgsMp[id]
  86. if !ok {
  87. ret[i] = nil
  88. continue
  89. }
  90. ret[i] = stg
  91. }
  92. return mq.ReplyOK(coormq.RespGetStorageDetails(ret))
  93. }
  94. func (svc *Service) GetUserStorageDetails(msg *coormq.GetUserStorageDetails) (*coormq.GetUserStorageDetailsResp, *mq.CodeMessage) {
  95. stgsMp := make(map[cdssdk.StorageID]*stgmod.StorageDetail)
  96. svc.db2.DoTx(func(tx db2.SQLContext) error {
  97. stgs, err := svc.db2.Storage().GetUserStorages(tx, msg.UserID)
  98. if err != nil && err != gorm.ErrRecordNotFound {
  99. return fmt.Errorf("getting user storages: %w", err)
  100. }
  101. var masterHubIDs []cdssdk.NodeID
  102. for _, stg := range stgs {
  103. stgsMp[stg.StorageID] = &stgmod.StorageDetail{
  104. Storage: stg,
  105. }
  106. masterHubIDs = append(masterHubIDs, stg.MasterHub)
  107. }
  108. // 监护Hub的信息
  109. masterHubs, err := svc.db2.Node().BatchGetByID(tx, masterHubIDs)
  110. if err != nil && err != gorm.ErrRecordNotFound {
  111. return fmt.Errorf("getting master hub: %w", err)
  112. }
  113. masterHubMap := make(map[cdssdk.NodeID]cdssdk.Node)
  114. for _, hub := range masterHubs {
  115. masterHubMap[hub.NodeID] = hub
  116. }
  117. for _, stg := range stgsMp {
  118. if stg.Storage.MasterHub != 0 {
  119. hub, ok := masterHubMap[stg.Storage.MasterHub]
  120. if !ok {
  121. logger.Warnf("master hub %v of storage %v not found, this storage will not be add to result", stg.Storage.MasterHub, stg.Storage)
  122. delete(stgsMp, stg.Storage.StorageID)
  123. continue
  124. }
  125. stg.MasterHub = &hub
  126. }
  127. }
  128. stgIDs := lo.Map(stgs, func(stg cdssdk.Storage, i int) cdssdk.StorageID { return stg.StorageID })
  129. // 获取分片存储信息
  130. shards, err := svc.db2.ShardStorage().BatchGetByStorageIDs(tx, stgIDs)
  131. if err != nil && err != gorm.ErrRecordNotFound {
  132. return fmt.Errorf("getting shard storage: %w", err)
  133. }
  134. for _, shard := range shards {
  135. stg := stgsMp[shard.StorageID]
  136. if stg == nil {
  137. continue
  138. }
  139. stg.Shard = &shard
  140. }
  141. // 获取共享存储的相关信息
  142. shareds, err := svc.db2.SharedStorage().BatchGetByStorageIDs(tx, stgIDs)
  143. if err != nil && err != gorm.ErrRecordNotFound {
  144. return fmt.Errorf("getting shared storage: %w", err)
  145. }
  146. for _, shared := range shareds {
  147. stg := stgsMp[shared.StorageID]
  148. if stg == nil {
  149. continue
  150. }
  151. stg.Shared = &shared
  152. }
  153. return nil
  154. })
  155. var ret []stgmod.StorageDetail
  156. for _, id := range stgsMp {
  157. ret = append(ret, *id)
  158. }
  159. return mq.ReplyOK(coormq.RespGetUserStorageDetails(ret))
  160. }
  161. func (svc *Service) GetStorageByName(msg *coormq.GetStorageByName) (*coormq.GetStorageByNameResp, *mq.CodeMessage) {
  162. stg, err := svc.db2.Storage().GetUserStorageByName(svc.db2.DefCtx(), msg.UserID, msg.Name)
  163. if err != nil {
  164. logger.Warnf("getting user storage by name: %s", err.Error())
  165. if err == sql.ErrNoRows {
  166. return nil, mq.Failed(errorcode.DataNotFound, "storage not found")
  167. }
  168. return nil, mq.Failed(errorcode.OperationFailed, "get user storage failed")
  169. }
  170. return mq.ReplyOK(coormq.RespGetStorageByNameResp(stg))
  171. }
  172. func (svc *Service) StoragePackageLoaded(msg *coormq.StoragePackageLoaded) (*coormq.StoragePackageLoadedResp, *mq.CodeMessage) {
  173. err := svc.db2.DoTx(func(tx db2.SQLContext) error {
  174. // 可以不用检查用户是否存在
  175. if ok, _ := svc.db2.Package().IsAvailable(tx, msg.UserID, msg.PackageID); !ok {
  176. return fmt.Errorf("package is not available to user")
  177. }
  178. if ok, _ := svc.db2.Storage().IsAvailable(tx, msg.UserID, msg.StorageID); !ok {
  179. return fmt.Errorf("storage is not available to user")
  180. }
  181. err := svc.db2.StoragePackage().CreateOrUpdate(tx, msg.StorageID, msg.PackageID, msg.UserID)
  182. if err != nil {
  183. return fmt.Errorf("creating storage package: %w", err)
  184. }
  185. stg, err := svc.db2.Storage().GetByID(tx, msg.StorageID)
  186. if err != nil {
  187. return fmt.Errorf("getting storage: %w", err)
  188. }
  189. err = svc.db2.PinnedObject().CreateFromPackage(tx, msg.PackageID, stg.StorageID)
  190. if err != nil {
  191. return fmt.Errorf("creating pinned object from package: %w", err)
  192. }
  193. if len(msg.PinnedBlocks) > 0 {
  194. err = svc.db2.ObjectBlock().BatchCreate(tx, msg.PinnedBlocks)
  195. if err != nil {
  196. return fmt.Errorf("batch creating object block: %w", err)
  197. }
  198. }
  199. return nil
  200. })
  201. if err != nil {
  202. logger.WithField("UserID", msg.UserID).
  203. WithField("StorageID", msg.StorageID).
  204. WithField("PackageID", msg.PackageID).
  205. Warn(err.Error())
  206. return nil, mq.Failed(errorcode.OperationFailed, "user load package to storage failed")
  207. }
  208. return mq.ReplyOK(coormq.NewStoragePackageLoadedResp())
  209. }

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