123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- package page_writer
- import "math"
- // ChunkWrittenInterval mark one written interval within one page chunk
- type ChunkWrittenInterval struct {
- StartOffset int64
- stopOffset int64
- flushed bool
- prev *ChunkWrittenInterval
- next *ChunkWrittenInterval
- }
- func (interval *ChunkWrittenInterval) Size() int64 {
- return interval.stopOffset - interval.StartOffset
- }
- func (interval *ChunkWrittenInterval) isComplete(chunkSize int64) bool {
- return interval.stopOffset-interval.StartOffset == chunkSize
- }
- func (interval *ChunkWrittenInterval) MarkFlushed() {
- interval.flushed = true
- }
- // ChunkWrittenIntervalList mark written intervals within one page chunk
- type ChunkWrittenIntervalList struct {
- head *ChunkWrittenInterval
- tail *ChunkWrittenInterval
- }
- func newChunkWrittenIntervalList() *ChunkWrittenIntervalList {
- list := &ChunkWrittenIntervalList{
- head: &ChunkWrittenInterval{
- StartOffset: -1,
- stopOffset: -1,
- },
- tail: &ChunkWrittenInterval{
- StartOffset: math.MaxInt64,
- stopOffset: math.MaxInt64,
- },
- }
- list.head.next = list.tail
- list.tail.prev = list.head
- return list
- }
- func (list *ChunkWrittenIntervalList) MarkWritten(startOffset, stopOffset int64) {
- interval := &ChunkWrittenInterval{
- StartOffset: startOffset,
- stopOffset: stopOffset,
- }
- list.addInterval(interval)
- }
- func (list *ChunkWrittenIntervalList) IsComplete(chunkSize int64) bool {
- return list.size() == 1 && list.head.next.isComplete(chunkSize)
- }
- func (list *ChunkWrittenIntervalList) addInterval(interval *ChunkWrittenInterval) {
- p := list.head
- for ; p.next != nil && p.next.StartOffset <= interval.StartOffset; p = p.next {
- }
- q := list.tail
- for ; q.prev != nil && q.prev.stopOffset >= interval.stopOffset; q = q.prev {
- }
- if interval.StartOffset <= p.stopOffset && q.StartOffset <= interval.stopOffset {
- // merge p and q together
- p.stopOffset = q.stopOffset
- p.flushed = false
- unlinkNodesBetween(p, q.next)
- return
- }
- if interval.StartOffset <= p.stopOffset {
- // merge new interval into p
- p.stopOffset = interval.stopOffset
- p.flushed = false
- unlinkNodesBetween(p, q)
- return
- }
- if q.StartOffset <= interval.stopOffset {
- // merge new interval into q
- q.StartOffset = interval.StartOffset
- q.flushed = false
- unlinkNodesBetween(p, q)
- return
- }
- // add the new interval between p and q
- unlinkNodesBetween(p, q)
- p.next = interval
- interval.prev = p
- q.prev = interval
- interval.next = q
- }
- // unlinkNodesBetween remove all nodes after start and before stop, exclusive
- func unlinkNodesBetween(start *ChunkWrittenInterval, stop *ChunkWrittenInterval) {
- if start.next == stop {
- return
- }
- start.next.prev = nil
- start.next = stop
- stop.prev.next = nil
- stop.prev = start
- }
- func (list *ChunkWrittenIntervalList) size() int {
- var count int
- for t := list.head; t != nil; t = t.next {
- count++
- }
- return count - 2
- }
|