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 5.2 kB

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

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