mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2024-01-19 02:48:24 +00:00
add page chunk interval list
This commit is contained in:
parent
b7cd52636b
commit
7b78fc72b0
96
weed/filesys/page_writer/page_chunk_interval_list.go
Normal file
96
weed/filesys/page_writer/page_chunk_interval_list.go
Normal file
|
@ -0,0 +1,96 @@
|
|||
package page_writer
|
||||
|
||||
import "math"
|
||||
|
||||
// PageChunkWrittenInterval mark one written interval within one page chunk
|
||||
type PageChunkWrittenInterval struct {
|
||||
startOffset int64
|
||||
stopOffset int64
|
||||
prev *PageChunkWrittenInterval
|
||||
next *PageChunkWrittenInterval
|
||||
}
|
||||
|
||||
// PageChunkWrittenIntervalList mark written intervals within one page chunk
|
||||
type PageChunkWrittenIntervalList struct {
|
||||
head *PageChunkWrittenInterval
|
||||
tail *PageChunkWrittenInterval
|
||||
}
|
||||
|
||||
func newPageChunkWrittenIntervalList() *PageChunkWrittenIntervalList {
|
||||
list := &PageChunkWrittenIntervalList{
|
||||
head: &PageChunkWrittenInterval{
|
||||
startOffset: -1,
|
||||
stopOffset: -1,
|
||||
},
|
||||
tail: &PageChunkWrittenInterval{
|
||||
startOffset: math.MaxInt64,
|
||||
stopOffset: math.MaxInt64,
|
||||
},
|
||||
}
|
||||
list.head.next = list.tail
|
||||
list.tail.prev = list.head
|
||||
return list
|
||||
}
|
||||
|
||||
func (list *PageChunkWrittenIntervalList) MarkWritten(startOffset, stopOffset int64) {
|
||||
interval := &PageChunkWrittenInterval{
|
||||
startOffset: startOffset,
|
||||
stopOffset: stopOffset,
|
||||
}
|
||||
list.addInterval(interval)
|
||||
}
|
||||
func (list *PageChunkWrittenIntervalList) addInterval(interval *PageChunkWrittenInterval) {
|
||||
|
||||
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
|
||||
unlinkNodesBetween(p, q.next)
|
||||
return
|
||||
}
|
||||
if interval.startOffset <= p.stopOffset {
|
||||
// merge new interval into p
|
||||
p.stopOffset = interval.stopOffset
|
||||
unlinkNodesBetween(p, q)
|
||||
return
|
||||
}
|
||||
if q.startOffset <= interval.stopOffset {
|
||||
// merge new interval into q
|
||||
q.startOffset = interval.startOffset
|
||||
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 *PageChunkWrittenInterval, stop *PageChunkWrittenInterval) {
|
||||
if start.next == stop {
|
||||
return
|
||||
}
|
||||
start.next.prev = nil
|
||||
start.next = stop
|
||||
stop.prev.next = nil
|
||||
stop.prev = start
|
||||
}
|
||||
|
||||
func (list *PageChunkWrittenIntervalList) size() int {
|
||||
var count int
|
||||
for t := list.head; t != nil; t = t.next {
|
||||
count++
|
||||
}
|
||||
return count - 2
|
||||
}
|
49
weed/filesys/page_writer/page_chunk_interval_list_test.go
Normal file
49
weed/filesys/page_writer/page_chunk_interval_list_test.go
Normal file
|
@ -0,0 +1,49 @@
|
|||
package page_writer
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_PageChunkWrittenIntervalList(t *testing.T) {
|
||||
list := newPageChunkWrittenIntervalList()
|
||||
|
||||
assert.Equal(t, 0, list.size(), "empty list")
|
||||
|
||||
list.MarkWritten(0, 5)
|
||||
assert.Equal(t, 1, list.size(), "one interval")
|
||||
|
||||
list.MarkWritten(0, 5)
|
||||
assert.Equal(t, 1, list.size(), "duplicated interval2")
|
||||
|
||||
list.MarkWritten(95, 100)
|
||||
assert.Equal(t, 2, list.size(), "two intervals")
|
||||
|
||||
list.MarkWritten(50, 60)
|
||||
assert.Equal(t, 3, list.size(), "three intervals")
|
||||
|
||||
list.MarkWritten(50, 55)
|
||||
assert.Equal(t, 3, list.size(), "three intervals merge")
|
||||
|
||||
list.MarkWritten(40, 50)
|
||||
assert.Equal(t, 3, list.size(), "three intervals grow forward")
|
||||
|
||||
list.MarkWritten(50, 65)
|
||||
assert.Equal(t, 3, list.size(), "three intervals grow backward")
|
||||
|
||||
list.MarkWritten(70, 80)
|
||||
assert.Equal(t, 4, list.size(), "four intervals")
|
||||
|
||||
list.MarkWritten(60, 70)
|
||||
assert.Equal(t, 3, list.size(), "three intervals merged")
|
||||
|
||||
list.MarkWritten(59, 71)
|
||||
assert.Equal(t, 3, list.size(), "covered three intervals")
|
||||
|
||||
list.MarkWritten(5, 59)
|
||||
assert.Equal(t, 2, list.size(), "covered two intervals")
|
||||
|
||||
list.MarkWritten(70, 99)
|
||||
assert.Equal(t, 1, list.size(), "covered one intervals")
|
||||
|
||||
}
|
Loading…
Reference in a new issue