chrislu
3 years ago
2 changed files with 145 additions and 0 deletions
-
96weed/filesys/page_writer/page_chunk_interval_list.go
-
49weed/filesys/page_writer/page_chunk_interval_list_test.go
@ -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 |
|||
} |
@ -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") |
|||
|
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue