chunk_interval_list.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package page_writer
  2. import (
  3. "math"
  4. )
  5. // ChunkWrittenInterval mark one written interval within one page chunk
  6. type ChunkWrittenInterval struct {
  7. StartOffset int64
  8. stopOffset int64
  9. prev *ChunkWrittenInterval
  10. next *ChunkWrittenInterval
  11. }
  12. func (interval *ChunkWrittenInterval) Size() int64 {
  13. return interval.stopOffset - interval.StartOffset
  14. }
  15. func (interval *ChunkWrittenInterval) isComplete(chunkSize int64) bool {
  16. return interval.stopOffset-interval.StartOffset == chunkSize
  17. }
  18. // ChunkWrittenIntervalList mark written intervals within one page chunk
  19. type ChunkWrittenIntervalList struct {
  20. head *ChunkWrittenInterval
  21. tail *ChunkWrittenInterval
  22. }
  23. func newChunkWrittenIntervalList() *ChunkWrittenIntervalList {
  24. list := &ChunkWrittenIntervalList{
  25. head: &ChunkWrittenInterval{
  26. StartOffset: -1,
  27. stopOffset: -1,
  28. },
  29. tail: &ChunkWrittenInterval{
  30. StartOffset: math.MaxInt64,
  31. stopOffset: math.MaxInt64,
  32. },
  33. }
  34. list.head.next = list.tail
  35. list.tail.prev = list.head
  36. return list
  37. }
  38. func (list *ChunkWrittenIntervalList) MarkWritten(startOffset, stopOffset int64) {
  39. interval := &ChunkWrittenInterval{
  40. StartOffset: startOffset,
  41. stopOffset: stopOffset,
  42. }
  43. list.addInterval(interval)
  44. }
  45. func (list *ChunkWrittenIntervalList) IsComplete(chunkSize int64) bool {
  46. return list.size() == 1 && list.head.next.isComplete(chunkSize)
  47. }
  48. func (list *ChunkWrittenIntervalList) WrittenSize() (writtenByteCount int64) {
  49. for t := list.head; t != nil; t = t.next {
  50. writtenByteCount += t.Size()
  51. }
  52. return
  53. }
  54. func (list *ChunkWrittenIntervalList) addInterval(interval *ChunkWrittenInterval) {
  55. p := list.head
  56. for ; p.next != nil && p.next.StartOffset <= interval.StartOffset; p = p.next {
  57. }
  58. q := list.tail
  59. for ; q.prev != nil && q.prev.stopOffset >= interval.stopOffset; q = q.prev {
  60. }
  61. if interval.StartOffset <= p.stopOffset && q.StartOffset <= interval.stopOffset {
  62. // merge p and q together
  63. p.stopOffset = q.stopOffset
  64. unlinkNodesBetween(p, q.next)
  65. return
  66. }
  67. if interval.StartOffset <= p.stopOffset {
  68. // merge new interval into p
  69. p.stopOffset = interval.stopOffset
  70. unlinkNodesBetween(p, q)
  71. return
  72. }
  73. if q.StartOffset <= interval.stopOffset {
  74. // merge new interval into q
  75. q.StartOffset = interval.StartOffset
  76. unlinkNodesBetween(p, q)
  77. return
  78. }
  79. // add the new interval between p and q
  80. unlinkNodesBetween(p, q)
  81. p.next = interval
  82. interval.prev = p
  83. q.prev = interval
  84. interval.next = q
  85. }
  86. // unlinkNodesBetween remove all nodes after start and before stop, exclusive
  87. func unlinkNodesBetween(start *ChunkWrittenInterval, stop *ChunkWrittenInterval) {
  88. if start.next == stop {
  89. return
  90. }
  91. start.next.prev = nil
  92. start.next = stop
  93. stop.prev.next = nil
  94. stop.prev = start
  95. }
  96. func (list *ChunkWrittenIntervalList) size() int {
  97. var count int
  98. for t := list.head; t != nil; t = t.next {
  99. count++
  100. }
  101. return count - 2
  102. }