You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							128 lines
						
					
					
						
							3.0 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							128 lines
						
					
					
						
							3.0 KiB
						
					
					
				| package filer | |
| 
 | |
| import ( | |
| 	"container/list" | |
| 	"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb" | |
| 	"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 | |
| }
 |