chunk_interval_list.go 2.8 KB

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