package types import ( "fmt" "time" "github.com/samber/lo" "gitlink.org.cn/cloudream/common/utils/sort2" cotypes "gitlink.org.cn/cloudream/jcs-pub/coordinator/types" ) const ( ObjectPathSeparator = "/" ) type PackageID int64 type ObjectID int64 type BucketID int64 type UserSpaceID int64 type Bucket struct { BucketID BucketID `gorm:"column:BucketID; primaryKey; type:bigint; autoIncrement" json:"bucketID"` Name string `gorm:"column:Name; type:varchar(255); not null" json:"name"` CreateTime time.Time `gorm:"column:CreateTime; type:datetime; not null" json:"createTime"` } func (Bucket) TableName() string { return "Bucket" } type Package struct { PackageID PackageID `gorm:"column:PackageID; primaryKey; type:bigint; autoIncrement" json:"packageID"` Name string `gorm:"column:Name; type:varchar(255); not null" json:"name"` BucketID BucketID `gorm:"column:BucketID; type:bigint; not null" json:"bucketID"` CreateTime time.Time `gorm:"column:CreateTime; type:datetime; not null" json:"createTime"` } func (Package) TableName() string { return "Package" } type Object struct { ObjectID ObjectID `json:"objectID" gorm:"column:ObjectID; primaryKey; type:bigint; autoIncrement" ` PackageID PackageID `json:"packageID" gorm:"column:PackageID; type:bigint; not null"` Path string `json:"path" gorm:"column:Path; type:varchar(1024); not null"` Size int64 `json:"size,string" gorm:"column:Size; type:bigint; not null"` FileHash FileHash `json:"fileHash" gorm:"column:FileHash; type:char(68); not null"` Redundancy Redundancy `json:"redundancy" gorm:"column:Redundancy; type: json; serializer:union"` CreateTime time.Time `json:"createTime" gorm:"column:CreateTime; type:datetime; not null"` UpdateTime time.Time `json:"updateTime" gorm:"column:UpdateTime; type:datetime; not null"` } func (Object) TableName() string { return "Object" } type ObjectBlock struct { ObjectID ObjectID `gorm:"column:ObjectID; primaryKey; type:bigint" json:"objectID"` Index int `gorm:"column:Index; primaryKey; type:int" json:"index"` // 这个块应该在哪个空间中 UserSpaceID UserSpaceID `gorm:"column:UserSpaceID; primaryKey; type:bigint" json:"userSpaceID"` FileHash FileHash `gorm:"column:FileHash; type:char(68); not null" json:"fileHash"` Size int64 `gorm:"column:Size; type:bigint" json:"size"` } func (ObjectBlock) TableName() string { return "ObjectBlock" } type UserSpace struct { UserSpaceID UserSpaceID `gorm:"column:UserSpaceID; primaryKey; type:bigint" json:"userSpaceID"` // 用户空间名称 Name string `gorm:"column:Name; type:varchar(255); not null" json:"name"` // 用户空间所在的存储节点 StorageID cotypes.StorageID `gorm:"column:StorageID; type:bigint; not null" json:"storageID"` // 用户在指定存储节点的凭证信息,比如用户账户,AK/SK等 Credential cotypes.StorageCredential `gorm:"column:Credential; type:json; not null; serializer:union" json:"credential"` // 用户空间的分片存储配置,如果为空,则表示不使用分片存储 ShardStore *cotypes.ShardStoreUserConfig `gorm:"column:ShardStore; type:json; serializer:json" json:"shardStore"` // 用户空间信息的版本号,每一次更改都需要更新版本号 Revision int64 `gorm:"column:Revision; type:bigint; not null" json:"revision"` } func (UserSpace) TableName() string { return "UserSpace" } func (s UserSpace) String() string { return fmt.Sprintf("%v[id=%v,storageID=%v,rev=%v]", s.Name, s.UserSpaceID, s.StorageID, s.Revision) } type PackageAccessStat struct { PackageID PackageID `gorm:"column:PackageID; primaryKey; type:bigint" json:"packageID"` // 发起读取(调度)的用户空间ID UserSpaceID UserSpaceID `gorm:"column:UserSpaceID; primaryKey; type:bigint" json:"storageID"` // 前一日的读取量的滑动平均值 Amount float64 `gorm:"column:Amount; type:double" json:"amount"` // 当日的读取量 Counter float64 `gorm:"column:Counter; type:double" json:"counter"` } func (PackageAccessStat) TableName() string { return "PackageAccessStat" } type ObjectAccessStat struct { ObjectID ObjectID `gorm:"column:ObjectID; primaryKey; type:bigint" json:"objectID"` // 发起读取(调度)的用户空间ID UserSpaceID UserSpaceID `gorm:"column:UserSpaceID; primaryKey; type:bigint" json:"userStorageID"` // 前一日的读取量的滑动平均值 Amount float64 `gorm:"column:Amount; type:float; not null" json:"amount"` // 当日的读取量 Counter float64 `gorm:"column:Counter; type:float; not null" json:"counter"` } func (ObjectAccessStat) TableName() string { return "ObjectAccessStat" } type PinnedObject struct { ObjectID ObjectID `gorm:"column:ObjectID; primaryKey; type:bigint" json:"objectID"` UserSpaceID UserSpaceID `gorm:"column:UserSpaceID; primaryKey; type:bigint" json:"userSpaceID"` CreateTime time.Time `gorm:"column:CreateTime; type:datetime; not null" json:"createTime"` } func (PinnedObject) TableName() string { return "PinnedObject" } type ObjectDetail struct { Object Object `json:"object"` PinnedAt []UserSpaceID `json:"pinnedAt"` Blocks []ObjectBlock `json:"blocks"` } func NewObjectDetail(object Object, pinnedAt []UserSpaceID, blocks []ObjectBlock) ObjectDetail { return ObjectDetail{ Object: object, PinnedAt: pinnedAt, Blocks: blocks, } } func DetailsFromObjects(objects []Object) []ObjectDetail { details := make([]ObjectDetail, len(objects)) for i, object := range objects { details[i] = ObjectDetail{ Object: object, } } return details } // 将blocks放到对应的object中。要求objs和blocks都按ObjectID升序 func DetailsFillObjectBlocks(objs []ObjectDetail, blocks []ObjectBlock) { blksCur := 0 for i := range objs { obj := &objs[i] // 1. 查询Object和ObjectBlock时均按照ObjectID升序排序 // 2. ObjectBlock结果集中的不同ObjectID数只会比Object结果集的少 // 因此在两个结果集上同时从头开始遍历时,如果两边的ObjectID字段不同,那么一定是ObjectBlock这边的ObjectID > Object的ObjectID, // 此时让Object的遍历游标前进,直到两边的ObjectID再次相等 for ; blksCur < len(blocks); blksCur++ { if blocks[blksCur].ObjectID != obj.Object.ObjectID { break } obj.Blocks = append(obj.Blocks, blocks[blksCur]) } } } // 将pinnedAt放到对应的object中。要求objs和pinnedAt都按ObjectID升序 func DetailsFillPinnedAt(objs []ObjectDetail, pinnedAt []PinnedObject) { pinnedCur := 0 for i := range objs { obj := &objs[i] for ; pinnedCur < len(pinnedAt); pinnedCur++ { if pinnedAt[pinnedCur].ObjectID != obj.Object.ObjectID { break } obj.PinnedAt = append(obj.PinnedAt, pinnedAt[pinnedCur].UserSpaceID) } } } type GrouppedObjectBlock struct { ObjectID ObjectID Index int FileHash FileHash Size int64 UserSpaceIDs []UserSpaceID } func (o *ObjectDetail) GroupBlocks() []GrouppedObjectBlock { grps := make(map[int]GrouppedObjectBlock) for _, block := range o.Blocks { grp, ok := grps[block.Index] if !ok { grp = GrouppedObjectBlock{ ObjectID: block.ObjectID, Index: block.Index, FileHash: block.FileHash, Size: block.Size, } } grp.UserSpaceIDs = append(grp.UserSpaceIDs, block.UserSpaceID) grps[block.Index] = grp } return sort2.Sort(lo.Values(grps), func(l, r GrouppedObjectBlock) int { return l.Index - r.Index }) } type UserSpaceDetail struct { UserID cotypes.UserID UserSpace UserSpace Storage cotypes.Storage MasterHub *cotypes.Hub } func (d UserSpaceDetail) String() string { return d.UserSpace.String() } type PackageDetail struct { Package Package ObjectCount int64 TotalSize int64 }