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.

package.go 7.2 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. package db
  2. import (
  3. "fmt"
  4. "time"
  5. "gitlink.org.cn/cloudream/jcs-pub/client/types"
  6. "gorm.io/gorm"
  7. )
  8. type PackageDB struct {
  9. *DB
  10. }
  11. func (db *DB) Package() *PackageDB {
  12. return &PackageDB{DB: db}
  13. }
  14. func (db *PackageDB) GetByID(ctx SQLContext, packageID types.PackageID) (types.Package, error) {
  15. var ret types.Package
  16. err := ctx.Table("Package").Where("PackageID = ?", packageID).First(&ret).Error
  17. return ret, err
  18. }
  19. func (db *PackageDB) GetByName(ctx SQLContext, bucketID types.BucketID, name string) (types.Package, error) {
  20. var ret types.Package
  21. err := ctx.Table("Package").Where("BucketID = ? AND Name = ?", bucketID, name).First(&ret).Error
  22. return ret, err
  23. }
  24. func (db *PackageDB) BatchTestPackageID(ctx SQLContext, pkgIDs []types.PackageID) (map[types.PackageID]bool, error) {
  25. if len(pkgIDs) == 0 {
  26. return make(map[types.PackageID]bool), nil
  27. }
  28. var avaiIDs []types.PackageID
  29. err := ctx.Table("Package").
  30. Select("PackageID").
  31. Where("PackageID IN ?", pkgIDs).
  32. Find(&avaiIDs).Error
  33. if err != nil {
  34. return nil, err
  35. }
  36. avaiIDMap := make(map[types.PackageID]bool)
  37. for _, pkgID := range avaiIDs {
  38. avaiIDMap[pkgID] = true
  39. }
  40. return avaiIDMap, nil
  41. }
  42. func (*PackageDB) BatchGetAllPackageIDs(ctx SQLContext, start int, count int) ([]types.PackageID, error) {
  43. var ret []types.PackageID
  44. err := ctx.Table("Package").Select("PackageID").Limit(count).Offset(start).Find(&ret).Error
  45. return ret, err
  46. }
  47. func (db *PackageDB) GetBucketPackages(ctx SQLContext, bucketID types.BucketID) ([]types.Package, error) {
  48. var ret []types.Package
  49. err := ctx.Table("Package").
  50. Select("Package.*").
  51. Where("BucketID = ?", bucketID).
  52. Find(&ret).Error
  53. return ret, err
  54. }
  55. func (db *PackageDB) GetBucketPackagesByName(ctx SQLContext, bucketName string) ([]types.Package, error) {
  56. var ret []types.Package
  57. err := ctx.Table("Package").
  58. Select("Package.*").
  59. Joins("JOIN Bucket ON Package.BucketID = Bucket.BucketID").
  60. Where("Bucket.Name = ?", bucketName).
  61. Find(&ret).Error
  62. return ret, err
  63. }
  64. // 在指定名称的Bucket中查找指定名称的Package
  65. func (*PackageDB) GetByFullName(ctx SQLContext, bucketName string, packageName string) (types.Package, error) {
  66. var ret types.Package
  67. err := ctx.Table("Package").
  68. Select("Package.*").
  69. Joins("JOIN Bucket ON Package.BucketID = Bucket.BucketID").
  70. Where("Package.Name = ? AND Bucket.Name = ?", packageName, bucketName).
  71. First(&ret).Error
  72. return ret, err
  73. }
  74. func (db *PackageDB) Create(ctx SQLContext, bucketID types.BucketID, name string) (types.Package, error) {
  75. var packageID int64
  76. err := ctx.Table("Package").
  77. Select("PackageID").
  78. Where("Name = ? AND BucketID = ?", name, bucketID).
  79. Scan(&packageID).Error
  80. if err != nil {
  81. return types.Package{}, err
  82. }
  83. if packageID != 0 {
  84. return types.Package{}, gorm.ErrDuplicatedKey
  85. }
  86. newPackage := types.Package{Name: name, BucketID: bucketID, CreateTime: time.Now()}
  87. if err := ctx.Create(&newPackage).Error; err != nil {
  88. return types.Package{}, fmt.Errorf("insert package failed, err: %w", err)
  89. }
  90. return newPackage, nil
  91. }
  92. func (*PackageDB) Delete(ctx SQLContext, packageID types.PackageID) error {
  93. err := ctx.Delete(&types.Package{}, "PackageID = ?", packageID).Error
  94. return err
  95. }
  96. // 删除与Package相关的所有数据
  97. func (db *PackageDB) DeleteComplete(ctx SQLContext, packageID types.PackageID) error {
  98. if err := db.Package().Delete(ctx, packageID); err != nil {
  99. return fmt.Errorf("delete package state: %w", err)
  100. }
  101. if err := db.ObjectAccessStat().DeleteInPackage(ctx, packageID); err != nil {
  102. return fmt.Errorf("delete from object access stat: %w", err)
  103. }
  104. if err := db.ObjectBlock().DeleteInPackage(ctx, packageID); err != nil {
  105. return fmt.Errorf("delete from object block failed, err: %w", err)
  106. }
  107. if err := db.PinnedObject().DeleteInPackage(ctx, packageID); err != nil {
  108. return fmt.Errorf("deleting pinned objects in package: %w", err)
  109. }
  110. if err := db.Object().DeleteInPackage(ctx, packageID); err != nil {
  111. return fmt.Errorf("deleting objects in package: %w", err)
  112. }
  113. if err := db.PackageAccessStat().DeleteByPackageID(ctx, packageID); err != nil {
  114. return fmt.Errorf("deleting package access stat: %w", err)
  115. }
  116. return nil
  117. }
  118. func (*PackageDB) ChangeState(ctx SQLContext, packageID types.PackageID, state string) error {
  119. err := ctx.Exec("UPDATE Package SET State = ? WHERE PackageID = ?", state, packageID).Error
  120. return err
  121. }
  122. // 返回ErrRecordNotFound表示没有找到指定名称的Bucket,nil表示找到了
  123. func (*PackageDB) HasPackageIn(ctx SQLContext, bucketID types.BucketID) error {
  124. var pkg types.Package
  125. return ctx.Table("Package").Where("BucketID = ?", bucketID).First(&pkg).Error
  126. }
  127. func (*PackageDB) Move(ctx SQLContext, packageID types.PackageID, newBktID types.BucketID, newName string) error {
  128. err := ctx.Table("Package").Where("PackageID = ?", packageID).Update("BucketID", newBktID).Update("Name", newName).Error
  129. return err
  130. }
  131. type AddAccessStatEntry struct {
  132. ObjectID types.ObjectID `json:"objectID"`
  133. PackageID types.PackageID `json:"packageID"`
  134. UserSpaceID types.UserSpaceID `json:"userSpaceID"`
  135. Counter float64 `json:"counter"`
  136. }
  137. func (db *PackageDB) BatchAddPackageAccessStat(ctx SQLContext, entries []AddAccessStatEntry) error {
  138. pkgIDs := make([]types.PackageID, len(entries))
  139. objIDs := make([]types.ObjectID, len(entries))
  140. for i, e := range entries {
  141. pkgIDs[i] = e.PackageID
  142. objIDs[i] = e.ObjectID
  143. }
  144. avaiPkgIDs, err := db.Package().BatchTestPackageID(ctx, pkgIDs)
  145. if err != nil {
  146. return fmt.Errorf("batch test package id: %w", err)
  147. }
  148. avaiObjIDs, err := db.Object().BatchTestObjectID(ctx, objIDs)
  149. if err != nil {
  150. return fmt.Errorf("batch test object id: %w", err)
  151. }
  152. var willAdds []AddAccessStatEntry
  153. for _, e := range entries {
  154. if avaiPkgIDs[e.PackageID] && avaiObjIDs[e.ObjectID] {
  155. willAdds = append(willAdds, e)
  156. }
  157. }
  158. if len(willAdds) > 0 {
  159. err := db.PackageAccessStat().BatchAddCounter(ctx, willAdds)
  160. if err != nil {
  161. return fmt.Errorf("batch add package access stat counter: %w", err)
  162. }
  163. err = db.ObjectAccessStat().BatchAddCounter(ctx, willAdds)
  164. if err != nil {
  165. return fmt.Errorf("batch add object access stat counter: %w", err)
  166. }
  167. }
  168. return nil
  169. }
  170. // 尝试创建指定名称的Bucket和Package,如果Bucket不存在,则创建Bucket,如果Package已存在,则直接返回已有的Package
  171. func (db *PackageDB) TryCreateAll(ctx SQLContext, bktName string, pkgName string) (types.Package, error) {
  172. bkt, err := db.Bucket().GetByName(ctx, bktName)
  173. if err == gorm.ErrRecordNotFound {
  174. bkt, err = db.Bucket().Create(ctx, bktName, time.Now())
  175. if err != nil {
  176. return types.Package{}, fmt.Errorf("create bucket: %w", err)
  177. }
  178. } else if err != nil {
  179. return types.Package{}, fmt.Errorf("get bucket by name: %w", err)
  180. }
  181. pkg, err := db.GetByName(ctx, bkt.BucketID, pkgName)
  182. if err == nil {
  183. return pkg, nil
  184. }
  185. if err != gorm.ErrRecordNotFound {
  186. return types.Package{}, fmt.Errorf("get package by name: %w", err)
  187. }
  188. pkg, err = db.Create(ctx, bkt.BucketID, pkgName)
  189. if err != nil {
  190. return types.Package{}, fmt.Errorf("create package: %w", err)
  191. }
  192. return pkg, nil
  193. }

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