2021-10-16 23:03:16 +00:00
|
|
|
package filer
|
|
|
|
|
|
|
|
import (
|
2022-07-29 07:17:28 +00:00
|
|
|
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
|
2022-04-18 02:35:43 +00:00
|
|
|
"golang.org/x/exp/slices"
|
2021-10-16 23:03:16 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func readResolvedChunks(chunks []*filer_pb.FileChunk) (visibles []VisibleInterval) {
|
|
|
|
|
|
|
|
var points []*Point
|
|
|
|
for _, chunk := range chunks {
|
|
|
|
points = append(points, &Point{
|
|
|
|
x: chunk.Offset,
|
2022-10-28 19:53:19 +00:00
|
|
|
ts: chunk.ModifiedTsNs,
|
2021-10-16 23:03:16 +00:00
|
|
|
chunk: chunk,
|
|
|
|
isStart: true,
|
|
|
|
})
|
|
|
|
points = append(points, &Point{
|
|
|
|
x: chunk.Offset + int64(chunk.Size),
|
2022-10-28 19:53:19 +00:00
|
|
|
ts: chunk.ModifiedTsNs,
|
2021-10-16 23:03:16 +00:00
|
|
|
chunk: chunk,
|
|
|
|
isStart: false,
|
|
|
|
})
|
|
|
|
}
|
2022-04-18 02:35:43 +00:00
|
|
|
slices.SortFunc(points, func(a, b *Point) bool {
|
|
|
|
if a.x != b.x {
|
|
|
|
return a.x < b.x
|
2021-10-16 23:03:16 +00:00
|
|
|
}
|
2022-04-18 02:35:43 +00:00
|
|
|
if a.ts != b.ts {
|
|
|
|
return a.ts < b.ts
|
2021-10-16 23:03:16 +00:00
|
|
|
}
|
2022-04-18 02:35:43 +00:00
|
|
|
return !a.isStart
|
2021-10-16 23:03:16 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
var prevX int64
|
|
|
|
var queue []*Point
|
|
|
|
for _, point := range points {
|
|
|
|
if point.isStart {
|
|
|
|
if len(queue) > 0 {
|
2021-11-03 06:39:16 +00:00
|
|
|
lastIndex := len(queue) - 1
|
2021-10-16 23:03:16 +00:00
|
|
|
lastPoint := queue[lastIndex]
|
|
|
|
if point.x != prevX && lastPoint.ts < point.ts {
|
|
|
|
visibles = addToVisibles(visibles, prevX, lastPoint, point)
|
|
|
|
prevX = point.x
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// insert into queue
|
|
|
|
for i := len(queue); i >= 0; i-- {
|
|
|
|
if i == 0 || queue[i-1].ts <= point.ts {
|
|
|
|
if i == len(queue) {
|
|
|
|
prevX = point.x
|
|
|
|
}
|
|
|
|
queue = addToQueue(queue, i, point)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
lastIndex := len(queue) - 1
|
|
|
|
index := lastIndex
|
|
|
|
var startPoint *Point
|
|
|
|
for ; index >= 0; index-- {
|
|
|
|
startPoint = queue[index]
|
|
|
|
if startPoint.ts == point.ts {
|
|
|
|
queue = removeFromQueue(queue, index)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if index == lastIndex && startPoint != nil {
|
|
|
|
visibles = addToVisibles(visibles, prevX, startPoint, point)
|
|
|
|
prevX = point.x
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func removeFromQueue(queue []*Point, index int) []*Point {
|
|
|
|
for i := index; i < len(queue)-1; i++ {
|
|
|
|
queue[i] = queue[i+1]
|
|
|
|
}
|
|
|
|
queue = queue[:len(queue)-1]
|
|
|
|
return queue
|
|
|
|
}
|
|
|
|
|
|
|
|
func addToQueue(queue []*Point, index int, point *Point) []*Point {
|
|
|
|
queue = append(queue, point)
|
|
|
|
for i := len(queue) - 1; i > index; i-- {
|
|
|
|
queue[i], queue[i-1] = queue[i-1], queue[i]
|
|
|
|
}
|
|
|
|
return queue
|
|
|
|
}
|
|
|
|
|
|
|
|
func addToVisibles(visibles []VisibleInterval, prevX int64, startPoint *Point, point *Point) []VisibleInterval {
|
|
|
|
if prevX < point.x {
|
|
|
|
chunk := startPoint.chunk
|
|
|
|
visibles = append(visibles, VisibleInterval{
|
|
|
|
start: prevX,
|
|
|
|
stop: point.x,
|
2021-10-17 06:34:27 +00:00
|
|
|
fileId: chunk.GetFileIdString(),
|
2022-10-28 19:53:19 +00:00
|
|
|
modifiedTsNs: chunk.ModifiedTsNs,
|
2021-10-16 23:03:16 +00:00
|
|
|
chunkOffset: prevX - chunk.Offset,
|
|
|
|
chunkSize: chunk.Size,
|
|
|
|
cipherKey: chunk.CipherKey,
|
|
|
|
isGzipped: chunk.IsCompressed,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
return visibles
|
|
|
|
}
|
|
|
|
|
|
|
|
type Point struct {
|
|
|
|
x int64
|
|
|
|
ts int64
|
|
|
|
chunk *filer_pb.FileChunk
|
|
|
|
isStart bool
|
|
|
|
}
|