seaweedfs/weed/filer2/filechunks.go

176 lines
3.8 KiB
Go
Raw Normal View History

2018-05-13 15:11:26 +08:00
package filer2
2018-05-21 08:06:09 +08:00
import (
2018-09-10 07:26:11 +08:00
"fmt"
"hash/fnv"
2018-05-28 02:52:26 +08:00
"sort"
2018-05-21 08:08:54 +08:00
"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
2018-05-21 08:06:09 +08:00
)
2018-05-21 08:06:09 +08:00
func TotalSize(chunks []*filer_pb.FileChunk) (size uint64) {
2018-05-13 15:11:26 +08:00
for _, c := range chunks {
t := uint64(c.Offset + int64(c.Size))
if size < t {
size = t
}
}
return
}
2018-09-10 07:25:43 +08:00
func ETag(chunks []*filer_pb.FileChunk) (etag string) {
if len(chunks) == 1 {
return chunks[0].ETag
}
h := fnv.New32a()
for _, c := range chunks {
h.Write([]byte(c.ETag))
}
return fmt.Sprintf("%x", h.Sum32())
}
2018-05-21 08:06:09 +08:00
func CompactFileChunks(chunks []*filer_pb.FileChunk) (compacted, garbage []*filer_pb.FileChunk) {
visibles := nonOverlappingVisibleIntervals(chunks)
fileIds := make(map[string]bool)
for _, interval := range visibles {
fileIds[interval.fileId] = true
}
for _, chunk := range chunks {
if found := fileIds[chunk.FileId]; found {
compacted = append(compacted, chunk)
} else {
garbage = append(garbage, chunk)
}
}
2018-05-21 08:06:09 +08:00
return
2018-05-13 15:11:26 +08:00
}
2018-05-21 08:06:09 +08:00
func FindUnusedFileChunks(oldChunks, newChunks []*filer_pb.FileChunk) (unused []*filer_pb.FileChunk) {
fileIds := make(map[string]bool)
for _, interval := range newChunks {
fileIds[interval.FileId] = true
}
for _, chunk := range oldChunks {
if found := fileIds[chunk.FileId]; !found {
unused = append(unused, chunk)
}
}
return
}
type ChunkView struct {
FileId string
Offset int64
Size uint64
LogicOffset int64
}
func ViewFromChunks(chunks []*filer_pb.FileChunk, offset int64, size int) (views []*ChunkView) {
visibles := nonOverlappingVisibleIntervals(chunks)
stop := offset + int64(size)
for _, chunk := range visibles {
2018-05-25 14:19:56 +08:00
if chunk.start <= offset && offset < chunk.stop && offset < stop {
views = append(views, &ChunkView{
FileId: chunk.fileId,
Offset: offset - chunk.start, // offset is the data starting location in this file id
Size: uint64(min(chunk.stop, stop) - offset),
LogicOffset: offset,
})
offset = min(chunk.stop, stop)
}
}
return views
}
2018-05-21 08:08:54 +08:00
func logPrintf(name string, visibles []*visibleInterval) {
2018-05-28 02:56:49 +08:00
/*
2018-05-28 14:59:49 +08:00
log.Printf("%s len %d", name, len(visibles))
for _, v := range visibles {
log.Printf("%s: => %+v", name, v)
}
2018-05-28 02:56:49 +08:00
*/
2018-05-13 15:11:26 +08:00
}
2018-05-21 08:06:09 +08:00
2018-11-19 02:07:30 +08:00
func mergeIntoVisibles(visibles []*visibleInterval, chunk *filer_pb.FileChunk) (newVisibles []*visibleInterval) {
for _, v := range visibles {
if v.start < chunk.Offset && chunk.Offset < v.stop {
newVisibles = append(newVisibles, newVisibleInterval(
v.start,
chunk.Offset,
v.fileId,
v.modifiedTime,
))
2018-05-21 08:06:09 +08:00
}
2018-11-19 02:07:30 +08:00
chunkStop := chunk.Offset + int64(chunk.Size)
if v.start < chunkStop && chunkStop < v.stop {
newVisibles = append(newVisibles, newVisibleInterval(
chunkStop,
v.stop,
v.fileId,
v.modifiedTime,
2018-05-21 08:06:09 +08:00
))
}
2018-11-19 02:07:30 +08:00
if chunkStop < v.start || v.stop <= chunk.Offset {
newVisibles = append(newVisibles, v)
}
2018-05-21 08:06:09 +08:00
}
2018-11-19 02:07:30 +08:00
newVisibles = append(newVisibles, newVisibleInterval(
chunk.Offset,
chunk.Offset+int64(chunk.Size),
chunk.FileId,
chunk.Mtime,
))
return
}
2018-05-21 08:06:09 +08:00
2018-11-19 02:07:30 +08:00
func nonOverlappingVisibleIntervals(chunks []*filer_pb.FileChunk) (visibles []*visibleInterval) {
2018-05-21 08:06:09 +08:00
2018-11-19 02:07:30 +08:00
sort.Slice(chunks, func(i, j int) bool {
return chunks[i].Mtime < chunks[j].Mtime
})
2018-05-21 08:06:09 +08:00
2018-11-19 02:07:30 +08:00
for _, chunk := range chunks {
visibles = mergeIntoVisibles(visibles, chunk)
2018-05-21 08:06:09 +08:00
}
2018-11-19 02:07:30 +08:00
sort.Slice(visibles, func(i, j int) bool {
return visibles[i].start < visibles[j].start
})
2018-05-21 08:06:09 +08:00
logPrintf("visibles", visibles)
return
}
// find non-overlapping visible intervals
// visible interval map to one file chunk
type visibleInterval struct {
start int64
stop int64
modifiedTime int64
fileId string
}
func newVisibleInterval(start, stop int64, fileId string, modifiedTime int64) *visibleInterval {
return &visibleInterval{start: start, stop: stop, fileId: fileId, modifiedTime: modifiedTime}
}
func min(x, y int64) int64 {
if x <= y {
return x
}
return y
}