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.

75 lines
2.0 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. package page_writer
  2. import (
  3. "github.com/chrislusf/seaweedfs/weed/util"
  4. "github.com/chrislusf/seaweedfs/weed/util/mem"
  5. "io"
  6. )
  7. type SaveToStorageFunc func(reader io.Reader, offset int64, size int64, cleanupFn func())
  8. type PageChunk interface {
  9. FreeResource()
  10. WriteDataAt(src []byte, offset int64) (n int)
  11. ReadDataAt(p []byte, off int64) (maxStop int64)
  12. IsComplete() bool
  13. SaveContent(saveFn SaveToStorageFunc)
  14. }
  15. var (
  16. _ = PageChunk(&MemChunk{})
  17. )
  18. type MemChunk struct {
  19. buf []byte
  20. usage *ChunkWrittenIntervalList
  21. chunkSize int64
  22. logicChunkIndex LogicChunkIndex
  23. }
  24. func NewMemChunk(logicChunkIndex LogicChunkIndex, chunkSize int64) *MemChunk {
  25. return &MemChunk{
  26. logicChunkIndex: logicChunkIndex,
  27. chunkSize: chunkSize,
  28. buf: mem.Allocate(int(chunkSize)),
  29. usage: newChunkWrittenIntervalList(),
  30. }
  31. }
  32. func (mc *MemChunk) FreeResource() {
  33. mem.Free(mc.buf)
  34. }
  35. func (mc *MemChunk) WriteDataAt(src []byte, offset int64) (n int) {
  36. n = copy(mc.buf[offset:], src)
  37. mc.usage.MarkWritten(offset, offset+int64(n))
  38. return
  39. }
  40. func (mc *MemChunk) ReadDataAt(p []byte, off int64) (maxStop int64) {
  41. memChunkBaseOffset := int64(mc.logicChunkIndex) * mc.chunkSize
  42. for t := mc.usage.head.next; t != mc.usage.tail; t = t.next {
  43. logicStart := max(off, int64(mc.logicChunkIndex)*mc.chunkSize+t.StartOffset)
  44. logicStop := min(off+int64(len(p)), memChunkBaseOffset+t.stopOffset)
  45. if logicStart < logicStop {
  46. copy(p[logicStart-off:logicStop-off], mc.buf[logicStart-memChunkBaseOffset:logicStop-memChunkBaseOffset])
  47. maxStop = max(maxStop, logicStop)
  48. }
  49. }
  50. return
  51. }
  52. func (mc *MemChunk) IsComplete() bool {
  53. return mc.usage.IsComplete(mc.chunkSize)
  54. }
  55. func (mc *MemChunk) SaveContent(saveFn SaveToStorageFunc) {
  56. if saveFn == nil {
  57. return
  58. }
  59. for t := mc.usage.head.next; t != mc.usage.tail; t = t.next {
  60. reader := util.NewBytesReader(mc.buf[t.StartOffset:t.stopOffset])
  61. saveFn(reader, int64(mc.logicChunkIndex)*mc.chunkSize+t.StartOffset, t.Size(), func() {
  62. })
  63. }
  64. }