123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- package filer
- import (
- "container/list"
- "github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
- "golang.org/x/exp/slices"
- )
- func readResolvedChunks(chunks []*filer_pb.FileChunk, startOffset int64, stopOffset int64) (visibles *IntervalList[*VisibleInterval]) {
- var points []*Point
- for _, chunk := range chunks {
- if chunk.IsChunkManifest {
- println("This should not happen! A manifest chunk found:", chunk.GetFileIdString())
- }
- start, stop := max(chunk.Offset, startOffset), min(chunk.Offset+int64(chunk.Size), stopOffset)
- if start >= stop {
- continue
- }
- points = append(points, &Point{
- x: chunk.Offset,
- ts: chunk.ModifiedTsNs,
- chunk: chunk,
- isStart: true,
- })
- points = append(points, &Point{
- x: chunk.Offset + int64(chunk.Size),
- ts: chunk.ModifiedTsNs,
- chunk: chunk,
- isStart: false,
- })
- }
- slices.SortFunc(points, func(a, b *Point) int {
- if a.x != b.x {
- return int(a.x - b.x)
- }
- if a.ts != b.ts {
- return int(a.ts - b.ts)
- }
- if a.isStart {
- return -1
- }
- if b.isStart {
- return 1
- }
- return 0
- })
- var prevX int64
- queue := list.New() // points with higher ts are at the tail
- visibles = NewIntervalList[*VisibleInterval]()
- var prevPoint *Point
- for _, point := range points {
- if queue.Len() > 0 {
- prevPoint = queue.Back().Value.(*Point)
- } else {
- prevPoint = nil
- }
- if point.isStart {
- if prevPoint != nil {
- if point.x != prevX && prevPoint.ts < point.ts {
- addToVisibles(visibles, prevX, prevPoint, point)
- prevX = point.x
- }
- }
- // insert into queue
- if prevPoint == nil || prevPoint.ts < point.ts {
- queue.PushBack(point)
- prevX = point.x
- } else {
- for e := queue.Front(); e != nil; e = e.Next() {
- if e.Value.(*Point).ts > point.ts {
- queue.InsertBefore(point, e)
- break
- }
- }
- }
- } else {
- isLast := true
- for e := queue.Back(); e != nil; e = e.Prev() {
- if e.Value.(*Point).ts == point.ts {
- queue.Remove(e)
- break
- }
- isLast = false
- }
- if isLast && prevPoint != nil {
- addToVisibles(visibles, prevX, prevPoint, point)
- prevX = point.x
- }
- }
- }
- return
- }
- func addToVisibles(visibles *IntervalList[*VisibleInterval], prevX int64, startPoint *Point, point *Point) {
- if prevX < point.x {
- chunk := startPoint.chunk
- visible := &VisibleInterval{
- start: prevX,
- stop: point.x,
- fileId: chunk.GetFileIdString(),
- modifiedTsNs: chunk.ModifiedTsNs,
- offsetInChunk: prevX - chunk.Offset,
- chunkSize: chunk.Size,
- cipherKey: chunk.CipherKey,
- isGzipped: chunk.IsCompressed,
- }
- appendVisibleInterfal(visibles, visible)
- }
- }
- func appendVisibleInterfal(visibles *IntervalList[*VisibleInterval], visible *VisibleInterval) {
- visibles.AppendInterval(&Interval[*VisibleInterval]{
- StartOffset: visible.start,
- StopOffset: visible.stop,
- TsNs: visible.modifiedTsNs,
- Value: visible,
- })
- }
- type Point struct {
- x int64
- ts int64
- chunk *filer_pb.FileChunk
- isStart bool
- }
|