seaweedfs/weed/filesys/page_writer/chunk_interval_list.go

116 lines
2.8 KiB
Go
Raw Normal View History

2021-12-22 10:53:33 +00:00
package page_writer
import "math"
2021-12-24 01:35:57 +00:00
// ChunkWrittenInterval mark one written interval within one page chunk
type ChunkWrittenInterval struct {
StartOffset int64
2021-12-22 10:53:33 +00:00
stopOffset int64
2021-12-24 01:35:57 +00:00
prev *ChunkWrittenInterval
next *ChunkWrittenInterval
2021-12-22 10:53:33 +00:00
}
2021-12-24 01:35:57 +00:00
func (interval *ChunkWrittenInterval) Size() int64 {
return interval.stopOffset - interval.StartOffset
}
func (interval *ChunkWrittenInterval) isComplete(chunkSize int64) bool {
return interval.stopOffset-interval.StartOffset == chunkSize
2021-12-24 01:17:32 +00:00
}
2021-12-24 01:35:57 +00:00
// ChunkWrittenIntervalList mark written intervals within one page chunk
type ChunkWrittenIntervalList struct {
head *ChunkWrittenInterval
tail *ChunkWrittenInterval
2021-12-22 10:53:33 +00:00
}
2021-12-24 01:35:57 +00:00
func newChunkWrittenIntervalList() *ChunkWrittenIntervalList {
list := &ChunkWrittenIntervalList{
head: &ChunkWrittenInterval{
StartOffset: -1,
2021-12-22 10:53:33 +00:00
stopOffset: -1,
},
2021-12-24 01:35:57 +00:00
tail: &ChunkWrittenInterval{
StartOffset: math.MaxInt64,
2021-12-22 10:53:33 +00:00
stopOffset: math.MaxInt64,
},
}
list.head.next = list.tail
list.tail.prev = list.head
return list
}
2021-12-24 01:35:57 +00:00
func (list *ChunkWrittenIntervalList) MarkWritten(startOffset, stopOffset int64) {
interval := &ChunkWrittenInterval{
StartOffset: startOffset,
2021-12-22 10:53:33 +00:00
stopOffset: stopOffset,
}
list.addInterval(interval)
}
func (list *ChunkWrittenIntervalList) IsComplete(chunkSize int64) bool {
return list.size() == 1 && list.head.next.isComplete(chunkSize)
}
func (list *ChunkWrittenIntervalList) WrittenSize() (writtenByteCount int64) {
for t := list.head; t != nil; t = t.next {
writtenByteCount += t.Size()
}
return
}
2021-12-24 01:35:57 +00:00
func (list *ChunkWrittenIntervalList) addInterval(interval *ChunkWrittenInterval) {
2021-12-22 10:53:33 +00:00
p := list.head
for ; p.next != nil && p.next.StartOffset <= interval.StartOffset; p = p.next {
2021-12-22 10:53:33 +00:00
}
q := list.tail
for ; q.prev != nil && q.prev.stopOffset >= interval.stopOffset; q = q.prev {
}
if interval.StartOffset <= p.stopOffset && q.StartOffset <= interval.stopOffset {
2021-12-22 10:53:33 +00:00
// merge p and q together
p.stopOffset = q.stopOffset
unlinkNodesBetween(p, q.next)
return
}
if interval.StartOffset <= p.stopOffset {
2021-12-22 10:53:33 +00:00
// merge new interval into p
p.stopOffset = interval.stopOffset
unlinkNodesBetween(p, q)
return
}
if q.StartOffset <= interval.stopOffset {
2021-12-22 10:53:33 +00:00
// merge new interval into q
q.StartOffset = interval.StartOffset
2021-12-22 10:53:33 +00:00
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
2021-12-24 01:35:57 +00:00
func unlinkNodesBetween(start *ChunkWrittenInterval, stop *ChunkWrittenInterval) {
2021-12-22 10:53:33 +00:00
if start.next == stop {
return
}
start.next.prev = nil
start.next = stop
stop.prev.next = nil
stop.prev = start
}
2021-12-24 01:35:57 +00:00
func (list *ChunkWrittenIntervalList) size() int {
2021-12-22 10:53:33 +00:00
var count int
for t := list.head; t != nil; t = t.next {
count++
}
return count - 2
}