chunk_interval_list.go 2.8 KB

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