mirror of
https://github.com/grafana/loki.git
synced 2026-03-13 09:33:58 +08:00
90 lines
2.5 KiB
Go
90 lines
2.5 KiB
Go
package dataobj
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"math"
|
|
|
|
"github.com/grafana/loki/v3/pkg/dataobj/internal/metadata/filemd"
|
|
)
|
|
|
|
type sectionReader struct {
|
|
rr rangeReader // Reader for absolute ranges within the file.
|
|
md *filemd.Metadata
|
|
sec *filemd.SectionInfo
|
|
|
|
// startOff holds the offset to shift all other offsets by.
|
|
startOff int64
|
|
|
|
extensionData []byte
|
|
}
|
|
|
|
func (sr *sectionReader) ExtensionData() []byte { return sr.extensionData }
|
|
|
|
func (sr *sectionReader) DataRange(ctx context.Context, offset, length int64) (io.ReadCloser, error) {
|
|
if offset < 0 || length < 0 {
|
|
return nil, fmt.Errorf("parameters must not be negative: offset=%d length=%d", offset, length)
|
|
}
|
|
|
|
region := sr.sec.GetLayout().GetData()
|
|
if region == nil {
|
|
return nil, fmt.Errorf("section has no data")
|
|
} else if region.Offset > math.MaxInt64 {
|
|
return nil, fmt.Errorf("section data offset is too large")
|
|
} else if region.Length > math.MaxInt64 {
|
|
return nil, fmt.Errorf("section data length is too large")
|
|
}
|
|
|
|
// Validate bounds within the range of the section.
|
|
var (
|
|
start = offset
|
|
end = offset + length - 1
|
|
)
|
|
if start > int64(region.Length) || end > int64(region.Length) {
|
|
return nil, fmt.Errorf("section data is invalid: start=%d end=%d length=%d", start, end, region.Length)
|
|
}
|
|
|
|
absoluteOffset := sr.startOff + int64(region.Offset) + offset
|
|
return sr.rr.ReadRange(ctx, absoluteOffset, length)
|
|
}
|
|
|
|
func (sr *sectionReader) MetadataRange(ctx context.Context, offset, length int64) (io.ReadCloser, error) {
|
|
if offset < 0 || length < 0 {
|
|
return nil, fmt.Errorf("parameters must not be negative: offset=%d length=%d", offset, length)
|
|
}
|
|
|
|
metadataRegion := sr.sec.GetLayout().GetMetadata()
|
|
if metadataRegion == nil {
|
|
return nil, fmt.Errorf("section has no metadata")
|
|
}
|
|
|
|
// Validate bounds within the range of the section.
|
|
var (
|
|
start = offset
|
|
end = offset + length - 1
|
|
)
|
|
if start > int64(metadataRegion.Length) || end > int64(metadataRegion.Length) {
|
|
return nil, fmt.Errorf("section data is invalid: start=%d end=%d length=%d", start, end, metadataRegion.Length)
|
|
}
|
|
|
|
absoluteOffset := sr.startOff + int64(metadataRegion.Offset) + offset
|
|
return sr.rr.ReadRange(ctx, absoluteOffset, length)
|
|
}
|
|
|
|
func (sr *sectionReader) DataSize() int64 {
|
|
dataRegion := sr.sec.GetLayout().GetData()
|
|
if dataRegion == nil {
|
|
return 0
|
|
}
|
|
return int64(dataRegion.Length)
|
|
}
|
|
|
|
func (sr *sectionReader) MetadataSize() int64 {
|
|
metadataRegion := sr.sec.GetLayout().GetMetadata()
|
|
if metadataRegion == nil {
|
|
return 0
|
|
}
|
|
return int64(metadataRegion.Length)
|
|
}
|