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.

redundancy.go 4.9 kB

7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. package types
  2. import (
  3. "github.com/samber/lo"
  4. "gitlink.org.cn/cloudream/common/pkgs/types"
  5. "gitlink.org.cn/cloudream/common/utils/math2"
  6. "gitlink.org.cn/cloudream/common/utils/serder"
  7. )
  8. type Redundancy interface {
  9. GetRedundancyType() string
  10. }
  11. var RedundancyUnion = serder.UseTypeUnionInternallyTagged(types.Ref(types.NewTypeUnion[Redundancy](
  12. (*NoneRedundancy)(nil),
  13. (*RepRedundancy)(nil),
  14. (*ECRedundancy)(nil),
  15. (*LRCRedundancy)(nil),
  16. (*SegmentRedundancy)(nil),
  17. (*MultipartUploadRedundancy)(nil),
  18. )), "type")
  19. type NoneRedundancy struct {
  20. Redundancy `json:"-"`
  21. serder.Metadata `union:"none"`
  22. Type string `json:"type"`
  23. }
  24. func NewNoneRedundancy() *NoneRedundancy {
  25. return &NoneRedundancy{
  26. Type: "none",
  27. }
  28. }
  29. var DefaultRepRedundancy = *NewRepRedundancy(2)
  30. type RepRedundancy struct {
  31. Redundancy `json:"-"`
  32. serder.Metadata `union:"rep"`
  33. Type string `json:"type"`
  34. RepCount int `json:"repCount"`
  35. }
  36. func NewRepRedundancy(repCount int) *RepRedundancy {
  37. return &RepRedundancy{
  38. Type: "rep",
  39. RepCount: repCount,
  40. }
  41. }
  42. var DefaultECRedundancy = *NewECRedundancy(2, 3, 1024*1024*5)
  43. type ECRedundancy struct {
  44. Redundancy `json:"-"`
  45. serder.Metadata `union:"ec"`
  46. Type string `json:"type"`
  47. K int `json:"k"`
  48. N int `json:"n"`
  49. ChunkSize int `json:"chunkSize"`
  50. }
  51. func NewECRedundancy(k int, n int, chunkSize int) *ECRedundancy {
  52. return &ECRedundancy{
  53. Type: "ec",
  54. K: k,
  55. N: n,
  56. ChunkSize: chunkSize,
  57. }
  58. }
  59. func (b *ECRedundancy) StripSize() int64 {
  60. return int64(b.ChunkSize) * int64(b.K)
  61. }
  62. var DefaultLRCRedundancy = *NewLRCRedundancy(2, 4, []int{2}, 1024*1024*5)
  63. type LRCRedundancy struct {
  64. Redundancy `json:"-"`
  65. serder.Metadata `union:"lrc"`
  66. Type string `json:"type"`
  67. K int `json:"k"`
  68. N int `json:"n"`
  69. Groups []int `json:"groups"`
  70. ChunkSize int `json:"chunkSize"`
  71. }
  72. func NewLRCRedundancy(k int, n int, groups []int, chunkSize int) *LRCRedundancy {
  73. return &LRCRedundancy{
  74. Type: "lrc",
  75. K: k,
  76. N: n,
  77. Groups: groups,
  78. ChunkSize: chunkSize,
  79. }
  80. }
  81. // 判断指定块属于哪个组。如果都不属于,则返回-1。
  82. func (b *LRCRedundancy) FindGroup(idx int) int {
  83. if idx >= b.N-len(b.Groups) {
  84. return idx - (b.N - len(b.Groups))
  85. }
  86. for i, group := range b.Groups {
  87. if idx < group {
  88. return i
  89. }
  90. idx -= group
  91. }
  92. return -1
  93. }
  94. // M = N - len(Groups),即数据块+校验块的总数,不包括组校验块。
  95. func (b *LRCRedundancy) M() int {
  96. return b.N - len(b.Groups)
  97. }
  98. func (b *LRCRedundancy) GetGroupElements(grp int) []int {
  99. var idxes []int
  100. grpStart := 0
  101. for i := 0; i < grp; i++ {
  102. grpStart += b.Groups[i]
  103. }
  104. for i := 0; i < b.Groups[grp]; i++ {
  105. idxes = append(idxes, grpStart+i)
  106. }
  107. idxes = append(idxes, b.N-len(b.Groups)+grp)
  108. return idxes
  109. }
  110. type SegmentRedundancy struct {
  111. Redundancy `json:"-"`
  112. serder.Metadata `union:"segment"`
  113. Type string `json:"type"`
  114. Segments []int64 `json:"segments"` // 每一段的大小
  115. }
  116. func NewSegmentRedundancy(totalSize int64, segmentCount int) *SegmentRedundancy {
  117. return &SegmentRedundancy{
  118. Type: "segment",
  119. Segments: math2.SplitN(totalSize, segmentCount),
  120. }
  121. }
  122. func (r *SegmentRedundancy) SegmentCount() int {
  123. return len(r.Segments)
  124. }
  125. func (r *SegmentRedundancy) CalcSegmentStart(index int) int64 {
  126. return lo.Sum(r.Segments[:index])
  127. }
  128. // 计算指定位置取整到最近的段的起始位置。
  129. func (r *SegmentRedundancy) FloorSegmentPosition(pos int64) int64 {
  130. fpos := int64(0)
  131. for _, segLen := range r.Segments {
  132. segEnd := fpos + segLen
  133. if pos < segEnd {
  134. break
  135. }
  136. fpos += segLen
  137. }
  138. return fpos
  139. }
  140. // 计算指定范围内的段索引范围,参数和返回值所代表的范围都是左闭右开的。
  141. // 如果end == -1,则代表计算从start到最后一个字节的范围。
  142. func (b *SegmentRedundancy) CalcSegmentRange(start int64, end *int64) (segIdxStart int, segIdxEnd int) {
  143. segIdxStart = len(b.Segments)
  144. segIdxEnd = len(b.Segments)
  145. // 找到第一个包含start的段索引
  146. segStart := int64(0)
  147. for i, segLen := range b.Segments {
  148. segEnd := segStart + segLen
  149. if start < segEnd {
  150. segIdxStart = i
  151. break
  152. }
  153. segStart += segLen
  154. }
  155. if end != nil {
  156. // 找到第一个包含end的段索引
  157. segStart = int64(0)
  158. for i, segLen := range b.Segments {
  159. segEnd := segStart + segLen
  160. if *end <= segEnd {
  161. segIdxEnd = i + 1
  162. break
  163. }
  164. segStart += segLen
  165. }
  166. }
  167. return
  168. }
  169. type MultipartUploadRedundancy struct {
  170. Redundancy `json:"-"`
  171. serder.Metadata `union:"multipartUpload"`
  172. Type string `json:"type"`
  173. }
  174. func NewMultipartUploadRedundancy() *MultipartUploadRedundancy {
  175. return &MultipartUploadRedundancy{
  176. Type: "multipartUpload",
  177. }
  178. }

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