Add chunk implementation from old code base

This commit is contained in:
Felix Geisendörfer 2013-03-18 11:56:53 +01:00
parent a5a78c786a
commit 4f811a8ffe
2 changed files with 165 additions and 0 deletions

66
src/cmd/tusd/chunk.go Normal file
View File

@ -0,0 +1,66 @@
package main
import (
"sort"
)
// chunk holds the offsets for a partial piece of data
type chunk struct {
Start int64 `json:"start"`
End int64 `json:"end"`
}
// Size returns the number of bytes between Start and End.
func (c chunk) Size() int64 {
return c.End - c.Start + 1
}
// chunkSet holds a set of chunks and helps with adding/merging new chunks into
// set set.
type chunkSet []chunk
// Add merges a newChunk into a chunkSet. This may lead to the chunk being
// combined with one or more adjecent chunks, possibly shrinking the chunkSet
// down to a single member.
func (c *chunkSet) Add(newChunk chunk) {
if newChunk.Size() <= 0 {
return
}
*c = append(*c, newChunk)
sort.Sort(c)
// merge chunks that can be combined
for i := 0; i < len(*c)-1; i++ {
current := (*c)[i]
next := (*c)[i+1]
if current.End+1 < next.Start {
continue
}
*c = append((*c)[0:i], (*c)[i+1:]...)
if current.End > next.End {
(*c)[i].End = current.End
}
if current.Start < next.Start {
(*c)[i].Start = current.Start
}
i--
}
}
func (c chunkSet) Len() int {
return len(c)
}
func (c chunkSet) Less(i, j int) bool {
return c[i].Start < c[j].Start
}
func (c chunkSet) Swap(i, j int) {
c[i], c[j] = c[j], c[i]
}

View File

@ -0,0 +1,99 @@
package main
import (
"fmt"
"testing"
)
var chunkSet_AddTests = []struct {
Name string
Add []chunk
Expect []chunk
}{
{
Name: "add one",
Add: []chunk{{Start: 1, End: 5}},
Expect: []chunk{{Start: 1, End: 5}},
},
{
Name: "add twice",
Add: []chunk{{Start: 1, End: 5}, {Start: 1, End: 5}},
Expect: []chunk{{Start: 1, End: 5}},
},
{
Name: "append",
Add: []chunk{{Start: 1, End: 5}, {Start: 7, End: 10}},
Expect: []chunk{{Start: 1, End: 5}, {Start: 7, End: 10}},
},
{
Name: "insert",
Add: []chunk{{Start: 0, End: 5}, {Start: 12, End: 15}, {Start: 7, End: 10}},
Expect: []chunk{{Start: 0, End: 5}, {Start: 7, End: 10}, {Start: 12, End: 15}},
},
{
Name: "prepend",
Add: []chunk{{Start: 5, End: 10}, {Start: 1, End: 3}},
Expect: []chunk{{Start: 1, End: 3}, {Start: 5, End: 10}},
},
{
Name: "grow start",
Add: []chunk{{Start: 1, End: 5}, {Start: 0, End: 5}},
Expect: []chunk{{Start: 0, End: 5}},
},
{
Name: "grow end",
Add: []chunk{{Start: 1, End: 5}, {Start: 1, End: 6}},
Expect: []chunk{{Start: 1, End: 6}},
},
{
Name: "grow end with multiple items",
Add: []chunk{{Start: 1, End: 5}, {Start: 7, End: 10}, {Start: 8, End: 15}},
Expect: []chunk{{Start: 1, End: 5}, {Start: 7, End: 15}},
},
{
Name: "grow exact end match",
Add: []chunk{{Start: 1, End: 5}, {Start: 6, End: 6}},
Expect: []chunk{{Start: 1, End: 6}},
},
{
Name: "sink",
Add: []chunk{{Start: 1, End: 5}, {Start: 2, End: 3}},
Expect: []chunk{{Start: 1, End: 5}},
},
{
Name: "swallow",
Add: []chunk{{Start: 1, End: 5}, {Start: 6, End: 10}, {Start: 0, End: 11}},
Expect: []chunk{{Start: 0, End: 11}},
},
{
Name: "ignore 0 byte chunks",
Add: []chunk{{Start: 0, End: -1}},
Expect: []chunk{},
},
{
Name: "ignore invalid chunks",
Add: []chunk{{Start: 0, End: -2}},
Expect: []chunk{},
},
}
func Test_chunkSet_Add(t *testing.T) {
for _, test := range chunkSet_AddTests {
var chunks chunkSet
for _, chunk := range test.Add {
chunks.Add(chunk)
}
expected := fmt.Sprintf("%+v", test.Expect)
got := fmt.Sprintf("%+v", chunks)
if got != expected {
t.Errorf(
"Failed test '%s':\nexpected: %s\ngot: %s",
test.Name,
expected,
got,
)
}
}
}