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.

blockdistribution.go 6.5 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. package models
  2. import (
  3. "errors"
  4. "log"
  5. "strconv"
  6. "time"
  7. stgmod "gitlink.org.cn/cloudream/storage/common/models"
  8. "gitlink.org.cn/cloudream/storage/common/pkgs/sysevent"
  9. "gorm.io/gorm"
  10. )
  11. type BlockDistribution struct {
  12. BlockID int64 `gorm:"column:BlockID; primaryKey; type:bigint; autoIncrement" json:"blockID"`
  13. ObjectID int64 `gorm:"column:ObjectID; type:bigint; not null" json:"objectID"`
  14. Type string `gorm:"column:Type; type:varchar(1024); not null" json:"type"`
  15. Index int64 `gorm:"column:Index; type:bigint; not null" json:"index"`
  16. StorageID int64 `gorm:"column:StorageID; type:bigint; not null" json:"storageID"`
  17. Status int `gorm:"column:Status; type:tinyint; not null" json:"status"`
  18. Timestamp time.Time `gorm:"column:Timestamp; type:datatime; not null" json:"timestamp"`
  19. }
  20. func (BlockDistribution) TableName() string {
  21. return "blockdistribution"
  22. }
  23. type BlockDistributionRepository struct {
  24. repo *GormRepository
  25. }
  26. func NewBlockDistributionRepository(db *gorm.DB) *BlockDistributionRepository {
  27. return &BlockDistributionRepository{repo: NewGormRepository(db)}
  28. }
  29. func (r *BlockDistributionRepository) CreateBlockDistribution(block *BlockDistribution) error {
  30. return r.repo.Create(block)
  31. }
  32. func (r *BlockDistributionRepository) UpdateBlockDistribution(block *BlockDistribution) error {
  33. return r.repo.Update(block)
  34. }
  35. func (r *BlockDistributionRepository) GetAllBlocks() ([]BlockDistribution, error) {
  36. var blocks []BlockDistribution
  37. err := r.repo.GetAll(&blocks)
  38. if err != nil {
  39. return nil, err
  40. }
  41. return blocks, nil
  42. }
  43. func (r *BlockDistributionRepository) GetBlockDistributionByObjectID(objectID int64) ([]BlockDistribution, error) {
  44. var blocks []BlockDistribution
  45. query := "SELECT * FROM blockdistribution WHERE ObjectID = ?"
  46. err := r.repo.db.Raw(query, objectID).Scan(&blocks).Error
  47. if errors.Is(err, gorm.ErrRecordNotFound) {
  48. return []BlockDistribution{}, errors.New("block not found")
  49. }
  50. return blocks, nil
  51. }
  52. func (r *BlockDistributionRepository) GetStorageIDsByObjectID(objectID int64) ([]int64, error) {
  53. var storageIDs []int64
  54. query := "SELECT distinct storageID FROM blockdistribution WHERE ObjectID = ?"
  55. // 通过 ObjectID 查询
  56. err := r.repo.db.Raw(query, objectID).Scan(&storageIDs).Error
  57. if errors.Is(err, gorm.ErrRecordNotFound) {
  58. return []int64{}, errors.New("block not found")
  59. }
  60. return storageIDs, nil
  61. }
  62. func (r *BlockDistributionRepository) GetBlockDistributionByIndex(objectID int64, index int64, storageID int64) (BlockDistribution, error) {
  63. var block BlockDistribution
  64. query := "SELECT * FROM blockdistribution WHERE ObjectID = ? AND `Index` = ? AND StorageID = ?"
  65. // 通过 ObjectID 和 Index 联合查询
  66. err := r.repo.db.Exec(query, objectID, index, storageID).First(&block).Error
  67. if errors.Is(err, gorm.ErrRecordNotFound) {
  68. return BlockDistribution{}, errors.New("block not found")
  69. }
  70. return block, nil
  71. }
  72. // DeleteBlockDistribution 删除 BlockDistribution 记录 (根据 ObjectID 和 Index)
  73. func (r *BlockDistributionRepository) DeleteBlockDistribution(objectID int64, index int64, storageID int64) error {
  74. query := "DELETE FROM blockdistribution WHERE ObjectID = ? AND `Index` = ? AND StorageID = ?"
  75. return r.repo.db.Exec(query, objectID, index, storageID).Error
  76. }
  77. type BlockDistributionWatcher struct {
  78. Name string
  79. }
  80. func (w *BlockDistributionWatcher) OnEvent(event sysevent.SysEvent) {
  81. body, ok := event.Body.(*stgmod.BodyBlockDistribution)
  82. if !ok {
  83. return
  84. }
  85. repoObject := NewObjectRepository(DB)
  86. repoBlock := NewBlockDistributionRepository(DB)
  87. repoStorage := NewStorageTransferCountRepository(DB)
  88. //更新object表中的状态
  89. object, err := repoObject.GetObjectByID(int64(body.ObjectID))
  90. faultTolerance, _ := strconv.ParseFloat(body.FaultTolerance, 64)
  91. redundancy, _ := strconv.ParseFloat(body.Redundancy, 64)
  92. avgAccessCost, _ := strconv.ParseFloat(body.AvgAccessCost, 64)
  93. if errors.Is(err, gorm.ErrRecordNotFound) {
  94. err := repoObject.CreateObject(&Object{
  95. ObjectID: body.ObjectID,
  96. PackageID: body.PackageID,
  97. Path: body.Path,
  98. Size: body.Size,
  99. FileHash: body.FileHash,
  100. Status: StatusYesterdayAfter,
  101. FaultTolerance: faultTolerance,
  102. Redundancy: redundancy,
  103. AvgAccessCost: avgAccessCost,
  104. Timestamp: time.Now(),
  105. })
  106. if err != nil {
  107. log.Printf("Error create object: %v", err)
  108. }
  109. } else {
  110. object.Status = StatusYesterdayAfter
  111. err = repoObject.UpdateObject(object)
  112. if err != nil {
  113. log.Printf("Error update object: %v", err)
  114. }
  115. }
  116. //更新block表中的状态
  117. for _, blockDist := range body.BlockDistribution {
  118. blockIndex, _ := strconv.ParseInt(blockDist.Index, 10, 64)
  119. blockStorageID, _ := strconv.ParseInt(blockDist.StorageID, 10, 64)
  120. blockDist, err := repoBlock.GetBlockDistributionByIndex(int64(body.ObjectID), blockIndex, blockStorageID)
  121. if errors.Is(err, gorm.ErrRecordNotFound) {
  122. err := repoBlock.CreateBlockDistribution(&BlockDistribution{
  123. BlockID: blockDist.BlockID,
  124. ObjectID: blockDist.ObjectID,
  125. Type: blockDist.Type,
  126. Index: blockIndex,
  127. StorageID: blockStorageID,
  128. Status: StatusYesterdayAfter,
  129. Timestamp: time.Now(),
  130. })
  131. if err != nil {
  132. log.Printf("Error create BlockDistribution: %v", err)
  133. }
  134. } else {
  135. err := repoBlock.UpdateBlockDistribution(&BlockDistribution{
  136. BlockID: blockDist.BlockID,
  137. ObjectID: blockDist.ObjectID,
  138. Type: blockDist.Type,
  139. Index: blockIndex,
  140. StorageID: blockStorageID,
  141. Status: StatusYesterdayAfter,
  142. Timestamp: time.Now(),
  143. })
  144. if err != nil {
  145. log.Printf("Error update BlockDistribution: %v", err)
  146. }
  147. }
  148. }
  149. //在storageTransferCount表中添加记录
  150. for _, dataTransfer := range body.DataTransfers {
  151. sourceStorageID, _ := strconv.ParseInt(string(dataTransfer.SourceStorageID), 10, 64)
  152. targetStorageID, _ := strconv.ParseInt(string(dataTransfer.TargetStorageID), 10, 64)
  153. dataTransferCount, _ := strconv.ParseInt(dataTransfer.TransferBytes, 10, 64)
  154. err := repoStorage.CreateStorageTransferCount(&StorageTransferCount{
  155. ObjectID: int64(body.ObjectID),
  156. Status: StatusTodayBeforeYesterday,
  157. SourceStorageID: sourceStorageID,
  158. TargetStorageID: targetStorageID,
  159. DataTransferCount: dataTransferCount,
  160. Timestamp: time.Now(),
  161. })
  162. if err != nil {
  163. log.Printf("Error create StorageTransferCount : %v", err)
  164. }
  165. }
  166. }

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