JCS-pub/common/types/redundancy.go

232 lines
5.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package jcstypes
import (
"github.com/samber/lo"
"gitlink.org.cn/cloudream/common/pkgs/types"
"gitlink.org.cn/cloudream/common/utils/math2"
"gitlink.org.cn/cloudream/common/utils/serder"
)
type Redundancy interface {
GetRedundancyType() string
}
var RedundancyUnion = serder.UseTypeUnionInternallyTagged(types.Ref(types.NewTypeUnion[Redundancy](
(*NoneRedundancy)(nil),
(*RepRedundancy)(nil),
(*ECRedundancy)(nil),
(*LRCRedundancy)(nil),
(*SegmentRedundancy)(nil),
(*MultipartUploadRedundancy)(nil),
)), "type")
type NoneRedundancy struct {
serder.Metadata `union:"none"`
Type string `json:"type"`
}
func (r *NoneRedundancy) GetRedundancyType() string {
return "none"
}
func NewNoneRedundancy() *NoneRedundancy {
return &NoneRedundancy{
Type: "none",
}
}
var DefaultRepRedundancy = *NewRepRedundancy(2)
type RepRedundancy struct {
serder.Metadata `union:"rep"`
Type string `json:"type"`
RepCount int `json:"repCount"`
}
func (r *RepRedundancy) GetRedundancyType() string {
return "rep"
}
func NewRepRedundancy(repCount int) *RepRedundancy {
return &RepRedundancy{
Type: "rep",
RepCount: repCount,
}
}
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 (b *ECRedundancy) GetRedundancyType() string {
return "ec"
}
func NewECRedundancy(k int, n int, chunkSize int) *ECRedundancy {
return &ECRedundancy{
Type: "ec",
K: k,
N: n,
ChunkSize: chunkSize,
}
}
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 (b *LRCRedundancy) GetRedundancyType() string {
return "lrc"
}
func NewLRCRedundancy(k int, n int, groups []int, chunkSize int) *LRCRedundancy {
return &LRCRedundancy{
Type: "lrc",
K: k,
N: n,
Groups: groups,
ChunkSize: chunkSize,
}
}
// 判断指定块属于哪个组。如果都不属于,则返回-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 (r *SegmentRedundancy) GetRedundancyType() string {
return "segment"
}
func NewSegmentRedundancy(totalSize int64, segmentCount int) *SegmentRedundancy {
return &SegmentRedundancy{
Type: "segment",
Segments: math2.SplitN(totalSize, segmentCount),
}
}
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
}
type MultipartUploadRedundancy struct {
serder.Metadata `union:"multipartUpload"`
Type string `json:"type"`
}
func (r *MultipartUploadRedundancy) GetRedundancyType() string {
return "multipartUpload"
}
func NewMultipartUploadRedundancy() *MultipartUploadRedundancy {
return &MultipartUploadRedundancy{
Type: "multipartUpload",
}
}