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.

file_segment.go 2.8 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package cache
  2. import (
  3. "gitlink.org.cn/cloudream/common/utils/lo2"
  4. "gitlink.org.cn/cloudream/common/utils/math2"
  5. )
  6. type SegmentType int
  7. const (
  8. // 数据段刚被初始化
  9. SegmentInit = iota
  10. // 数据来自本地文件
  11. SegmentLocal
  12. // 数据来自远端文件,还未写入到本地文件
  13. SegmentRemote
  14. // 数据由用户写入,还未写入到本地文件
  15. SegmentDirty
  16. )
  17. type FileSegment struct {
  18. Position int64
  19. // 有效数据的长度。不一定等于Buffer的长度
  20. Length int64
  21. Type SegmentType
  22. // 文件数据缓冲区。不可对此缓冲区进行append操作!
  23. Buffer []byte
  24. // 当前段是否正在被保存到本地文件中
  25. IsSaving bool
  26. // 引用计数。当引用计数为0时,可以安全地删除此段
  27. RefCount int
  28. }
  29. func (s *FileSegment) GetPosition() int64 {
  30. return s.Position
  31. }
  32. func (s *FileSegment) GetLength() int64 {
  33. return s.Length
  34. }
  35. func (s *FileSegment) SubSliceAbs(pos int64, len int64) []byte {
  36. start := pos - s.Position
  37. return s.Buffer[start : start+len]
  38. }
  39. // 将当前段拆分为两个段。当前段将持有第一个段,返回值持有第二个段
  40. func (s *FileSegment) SplitAbs(pos int64) *FileSegment {
  41. s2 := s.Buffer[pos-s.Position:]
  42. s2Len := math2.Max(s.Position+s.Length-pos, 0)
  43. s.Buffer = s.Buffer[:pos-s.Position]
  44. s.Length = math2.Min(int64(len(s.Buffer)), s.Length)
  45. return &FileSegment{
  46. Position: pos,
  47. Length: s2Len,
  48. Type: s.Type,
  49. Buffer: s2,
  50. }
  51. }
  52. func (s *FileSegment) AvailableEnd() int64 {
  53. return s.Position + s.Length
  54. }
  55. func (s *FileSegment) BufferEnd() int64 {
  56. return s.Position + int64(len(s.Buffer))
  57. }
  58. func (s *FileSegment) EnlargeTo(pos int64) {
  59. if pos > s.Position+s.Length {
  60. s.Length = pos - s.Position
  61. }
  62. }
  63. type SegmentBuffer struct {
  64. // 正在使用的文件段缓冲区
  65. buzys []*FileSegment
  66. }
  67. func (s *SegmentBuffer) BuzyCount() int {
  68. return len(s.buzys)
  69. }
  70. func (s *SegmentBuffer) Segment(idx int) *FileSegment {
  71. return s.buzys[idx]
  72. }
  73. func (s *SegmentBuffer) FirstContains(pos int64) int {
  74. return FirstContains(s.buzys, pos)
  75. }
  76. // 将指定段插入到段缓存的恰当位置
  77. func (s *SegmentBuffer) Insert(seg *FileSegment) {
  78. index := s.FirstContains(seg.Position)
  79. if index == -1 {
  80. s.buzys = append([]*FileSegment{seg}, s.buzys...)
  81. } else {
  82. // index是最后一个小于Position的位置,所以要加1
  83. s.buzys = lo2.Insert(s.buzys, index+1, seg)
  84. }
  85. }
  86. // 插入一个段到指定索引位置。不会检查插入后Segments是否依然保持有序。
  87. func (s *SegmentBuffer) InsertAt(index int, seg *FileSegment) {
  88. s.buzys = lo2.Insert(s.buzys, index, seg)
  89. }
  90. func (s *SegmentBuffer) RemoveAt(index int) {
  91. s.buzys = lo2.RemoveAt(s.buzys, index)
  92. }
  93. func (s *SegmentBuffer) Remove(seg *FileSegment) {
  94. s.buzys = lo2.Remove(s.buzys, seg)
  95. }

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