You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

94 lines
2.5 KiB

  1. package filer
  2. import (
  3. "github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
  4. "sync"
  5. )
  6. const SectionSize = 2 * 1024 * 1024 * 128 // 256MiB
  7. type SectionIndex int64
  8. type FileChunkSection struct {
  9. sectionIndex SectionIndex
  10. chunks []*filer_pb.FileChunk
  11. entryViewCache []VisibleInterval
  12. chunkViews []*ChunkView
  13. reader *ChunkReadAt
  14. lock sync.Mutex
  15. }
  16. func (section *FileChunkSection) addChunk(chunk *filer_pb.FileChunk) error {
  17. section.lock.Lock()
  18. defer section.lock.Unlock()
  19. section.chunks = append(section.chunks, chunk)
  20. // FIXME: this can be improved to an incremental change
  21. section.entryViewCache = nil
  22. return nil
  23. }
  24. func (section *FileChunkSection) readDataAt(group *ChunkGroup, fileSize int64, buff []byte, offset int64) (n int, tsNs int64, err error) {
  25. section.lock.Lock()
  26. defer section.lock.Unlock()
  27. section.setupForRead(group, fileSize)
  28. return section.reader.ReadAtWithTime(buff, offset)
  29. }
  30. func (section *FileChunkSection) setupForRead(group *ChunkGroup, fileSize int64) {
  31. if section.entryViewCache == nil {
  32. section.entryViewCache = readResolvedChunks(section.chunks)
  33. section.chunks, _ = SeparateGarbageChunks(section.entryViewCache, section.chunks)
  34. if section.reader != nil {
  35. _ = section.reader.Close()
  36. section.reader = nil
  37. }
  38. }
  39. if section.reader == nil {
  40. chunkViews := ViewFromVisibleIntervals(section.entryViewCache, int64(section.sectionIndex)*SectionSize, (int64(section.sectionIndex)+1)*SectionSize)
  41. section.reader = NewChunkReaderAtFromClient(group.lookupFn, chunkViews, group.chunkCache, min(int64(section.sectionIndex+1)*SectionSize, fileSize))
  42. }
  43. }
  44. func (section *FileChunkSection) DataStartOffset(group *ChunkGroup, offset int64, fileSize int64) int64 {
  45. section.lock.Lock()
  46. defer section.lock.Unlock()
  47. section.setupForRead(group, fileSize)
  48. for _, visible := range section.entryViewCache {
  49. if visible.stop <= offset {
  50. continue
  51. }
  52. if offset < visible.start {
  53. return offset
  54. }
  55. return offset
  56. }
  57. return -1
  58. }
  59. func (section *FileChunkSection) NextStopOffset(group *ChunkGroup, offset int64, fileSize int64) int64 {
  60. section.lock.Lock()
  61. defer section.lock.Unlock()
  62. section.setupForRead(group, fileSize)
  63. isAfterOffset := false
  64. for _, visible := range section.entryViewCache {
  65. if !isAfterOffset {
  66. if visible.stop <= offset {
  67. continue
  68. }
  69. isAfterOffset = true
  70. }
  71. if offset < visible.start {
  72. return offset
  73. }
  74. // now visible.start <= offset
  75. if offset < visible.stop {
  76. offset = visible.stop
  77. }
  78. }
  79. return offset
  80. }