|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- package cdssdk
-
- import (
- "database/sql/driver"
- "fmt"
- "time"
-
- "github.com/samber/lo"
- "gitlink.org.cn/cloudream/common/pkgs/types"
- "gitlink.org.cn/cloudream/common/utils/serder"
- )
-
- const (
- ObjectPathSeparator = "/"
- )
-
- type HubID int64
-
- type PackageID int64
-
- type ObjectID int64
-
- type UserID int64
-
- type BucketID int64
-
- type StorageID int64
-
- type LocationID int64
-
- // 文件的SHA256哈希值,全大写的16进制字符串格式
- type FileHash string
-
- /// TODO 将分散在各处的公共结构体定义集中到这里来
-
- type Redundancy interface {
- }
-
- var RedundancyUnion = serder.UseTypeUnionInternallyTagged(types.Ref(types.NewTypeUnion[Redundancy](
- (*NoneRedundancy)(nil),
- (*RepRedundancy)(nil),
- (*ECRedundancy)(nil),
- (*LRCRedundancy)(nil),
- (*SegmentRedundancy)(nil),
- )), "type")
-
- type NoneRedundancy struct {
- serder.Metadata `union:"none"`
- Type string `json:"type"`
- }
-
- func NewNoneRedundancy() *NoneRedundancy {
- return &NoneRedundancy{
- Type: "none",
- }
- }
- func (b *NoneRedundancy) Value() (driver.Value, error) {
- return serder.ObjectToJSONEx[Redundancy](b)
- }
-
- var DefaultRepRedundancy = *NewRepRedundancy(2)
-
- type RepRedundancy struct {
- serder.Metadata `union:"rep"`
- Type string `json:"type"`
- RepCount int `json:"repCount"`
- }
-
- func NewRepRedundancy(repCount int) *RepRedundancy {
- return &RepRedundancy{
- Type: "rep",
- RepCount: repCount,
- }
- }
- func (b *RepRedundancy) Value() (driver.Value, error) {
- return serder.ObjectToJSONEx[Redundancy](b)
- }
-
- var DefaultECRedundancy = *NewECRedundancy(2, 3, 1024*1024*5)
-
- type ECRedundancy struct {
- serder.Metadata `union:"ec"`
- Type string `json:"type"`
- K int `json:"k"`
- N int `json:"n"`
- ChunkSize int `json:"chunkSize"`
- }
-
- func NewECRedundancy(k int, n int, chunkSize int) *ECRedundancy {
- return &ECRedundancy{
- Type: "ec",
- K: k,
- N: n,
- ChunkSize: chunkSize,
- }
- }
- func (b *ECRedundancy) Value() (driver.Value, error) {
- return serder.ObjectToJSONEx[Redundancy](b)
- }
-
- func (b *ECRedundancy) StripSize() int64 {
- return int64(b.ChunkSize) * int64(b.K)
- }
-
- var DefaultLRCRedundancy = *NewLRCRedundancy(2, 4, []int{2}, 1024*1024*5)
-
- type LRCRedundancy struct {
- serder.Metadata `union:"lrc"`
- Type string `json:"type"`
- K int `json:"k"`
- N int `json:"n"`
- Groups []int `json:"groups"`
- ChunkSize int `json:"chunkSize"`
- }
-
- func NewLRCRedundancy(k int, n int, groups []int, chunkSize int) *LRCRedundancy {
- return &LRCRedundancy{
- Type: "lrc",
- K: k,
- N: n,
- Groups: groups,
- ChunkSize: chunkSize,
- }
- }
- func (b *LRCRedundancy) Value() (driver.Value, error) {
- return serder.ObjectToJSONEx[Redundancy](b)
- }
-
- // 判断指定块属于哪个组。如果都不属于,则返回-1。
- func (b *LRCRedundancy) FindGroup(idx int) int {
- if idx >= b.N-len(b.Groups) {
- return idx - (b.N - len(b.Groups))
- }
-
- for i, group := range b.Groups {
- if idx < group {
- return i
- }
- idx -= group
- }
-
- return -1
- }
-
- // M = N - len(Groups),即数据块+校验块的总数,不包括组校验块。
- func (b *LRCRedundancy) M() int {
- return b.N - len(b.Groups)
- }
-
- func (b *LRCRedundancy) GetGroupElements(grp int) []int {
- var idxes []int
-
- grpStart := 0
- for i := 0; i < grp; i++ {
- grpStart += b.Groups[i]
- }
-
- for i := 0; i < b.Groups[grp]; i++ {
- idxes = append(idxes, grpStart+i)
- }
-
- idxes = append(idxes, b.N-len(b.Groups)+grp)
- return idxes
- }
-
- type SegmentRedundancy struct {
- serder.Metadata `union:"segment"`
- Type string `json:"type"`
- Segments []int64 `json:"segments"` // 每一段的大小
- }
-
- func NewSegmentRedundancy(totalSize int64, segmentCount int) *SegmentRedundancy {
- var segs []int64
- segLen := int64(0)
- // 计算每一段的大小。大小不一定都相同,但总和应该等于总大小。
- for i := 0; i < segmentCount; i++ {
- curLen := totalSize*int64(i+1)/int64(segmentCount) - segLen
- segs = append(segs, curLen)
- segLen += curLen
- }
-
- return &SegmentRedundancy{
- Type: "segment",
- Segments: segs,
- }
- }
-
- func (r *SegmentRedundancy) SegmentCount() int {
- return len(r.Segments)
- }
-
- func (r *SegmentRedundancy) CalcSegmentStart(index int) int64 {
- return lo.Sum(r.Segments[:index])
- }
-
- // 计算指定位置取整到最近的段的起始位置。
- func (r *SegmentRedundancy) FloorSegmentPosition(pos int64) int64 {
- fpos := int64(0)
- for _, segLen := range r.Segments {
- segEnd := fpos + segLen
- if pos < segEnd {
- break
- }
- fpos += segLen
- }
-
- return fpos
- }
-
- // 计算指定范围内的段索引范围,参数和返回值所代表的范围都是左闭右开的。
- // 如果end == -1,则代表计算从start到最后一个字节的范围。
- func (b *SegmentRedundancy) CalcSegmentRange(start int64, end *int64) (segIdxStart int, segIdxEnd int) {
- segIdxStart = len(b.Segments)
- segIdxEnd = len(b.Segments)
-
- // 找到第一个包含start的段索引
- segStart := int64(0)
- for i, segLen := range b.Segments {
- segEnd := segStart + segLen
- if start < segEnd {
- segIdxStart = i
- break
- }
- segStart += segLen
- }
-
- if end != nil {
- // 找到第一个包含end的段索引
- segStart = int64(0)
- for i, segLen := range b.Segments {
- segEnd := segStart + segLen
- if *end <= segEnd {
- segIdxEnd = i + 1
- break
- }
- segStart += segLen
- }
- }
-
- return
- }
-
- const (
- PackageStateNormal = "Normal"
- PackageStateDeleted = "Deleted"
- )
-
- 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"`
- State string `gorm:"column:State; type:varchar(255); not null" json:"state"`
- }
-
- 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(64); 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 Hub struct {
- HubID HubID `gorm:"column:HubID; primaryKey; type:bigint; autoIncrement" json:"hubID"`
- Name string `gorm:"column:Name; type:varchar(255); not null" json:"name"`
- Address HubAddressInfo `gorm:"column:Address; type:json; serializer:union" json:"address"`
- LocationID LocationID `gorm:"column:LocationID; type:bigint; not null" json:"locationID"`
- State string `gorm:"column:State; type:varchar(255); not null" json:"state"`
- LastReportTime *time.Time `gorm:"column:LastReportTime; type:datetime" json:"lastReportTime"`
- }
-
- func (Hub) TableName() string {
- return "Hub"
- }
-
- type HubAddressInfo interface {
- }
-
- var HubAddressUnion = types.NewTypeUnion[HubAddressInfo](
- (*GRPCAddressInfo)(nil),
- (*HttpAddressInfo)(nil),
- )
-
- var _ = serder.UseTypeUnionInternallyTagged(&HubAddressUnion, "type")
-
- type GRPCAddressInfo struct {
- serder.Metadata `union:"GRPC"`
- Type string `json:"type"`
- LocalIP string `json:"localIP"`
- ExternalIP string `json:"externalIP"`
- LocalGRPCPort int `json:"localGRPCPort"`
- ExternalGRPCPort int `json:"externalGRPCPort"`
- }
-
- type HttpAddressInfo struct {
- serder.Metadata `union:"HTTP"`
- Type string `json:"type"`
- LocalIP string `json:"localIP"`
- ExternalIP string `json:"externalIP"`
- Port int `json:"port"`
- }
-
- func (n Hub) String() string {
- return fmt.Sprintf("%v(%v)", n.Name, n.HubID)
- }
-
- type PinnedObject struct {
- ObjectID ObjectID `gorm:"column:ObjectID; primaryKey; type:bigint" json:"objectID"`
- StorageID StorageID `gorm:"column:StorageID; primaryKey; type:bigint" json:"storageID"`
- CreateTime time.Time `gorm:"column:CreateTime; type:datetime; not null" json:"createTime"`
- }
-
- func (PinnedObject) TableName() string {
- return "PinnedObject"
- }
-
- 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"`
- CreatorID UserID `gorm:"column:CreatorID; type:bigint; not null" json:"creatorID"`
- }
-
- func (Bucket) TableName() string {
- return "Bucket"
- }
-
- type HubConnectivity struct {
- FromHubID HubID `gorm:"column:FromHubID; primaryKey; type:bigint" json:"fromHubID"`
- ToHubID HubID `gorm:"column:ToHubID; primaryKey; type:bigint" json:"ToHubID"`
- Delay *float32 `gorm:"column:Delay; type:float" json:"delay"`
- TestTime time.Time `gorm:"column:TestTime; type:datetime" json:"testTime"`
- }
-
- func (HubConnectivity) TableName() string {
- return "HubConnectivity"
- }
-
- type StoragePackageCachingInfo struct {
- StorageID StorageID `json:"storageID"`
- FileSize int64 `json:"fileSize"`
- ObjectCount int64 `json:"objectCount"`
- }
-
- type PackageCachingInfo struct {
- StorageInfos []StoragePackageCachingInfo `json:"stgInfos"`
- PackageSize int64 `json:"packageSize"`
- }
-
- func NewPackageCachingInfo(stgInfos []StoragePackageCachingInfo, packageSize int64) PackageCachingInfo {
- return PackageCachingInfo{
- StorageInfos: stgInfos,
- PackageSize: packageSize,
- }
- }
-
- type CodeError struct {
- Code string `json:"code"`
- Message string `json:"message"`
- }
-
- func (e *CodeError) Error() string {
- return fmt.Sprintf("code: %s, message: %s", e.Code, e.Message)
- }
|