mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-19 13:00:45 +02:00
format: make Sniff an optional capability
Sniff sat in the mandatory adapter interface but has exactly one caller, the repack gate, which only Indexer adapters can reach - the hls-ts implementation was dead code. Move it to a Sniffer capability discovered by assertion like the others: parquet keeps it, hls-ts drops it, and repack skips the gate when an adapter cannot sniff.
This commit is contained in:
@@ -47,6 +47,12 @@ type Hint struct {
|
||||
// discovered by type assertion.
|
||||
type Format interface {
|
||||
Name() string
|
||||
}
|
||||
|
||||
// Sniffer cheaply recognizes the format from identification signals. Repack
|
||||
// gates on it before parsing, and policy-driven detection will rely on it;
|
||||
// ingest-only adapters, whose files carry their layout from birth, skip it.
|
||||
type Sniffer interface {
|
||||
Sniff(h Hint) bool
|
||||
}
|
||||
|
||||
|
||||
@@ -23,8 +23,6 @@ const (
|
||||
// interior chunk cuts land on packet boundaries.
|
||||
TSPacketSize = 188
|
||||
|
||||
tsSyncByte = 0x47
|
||||
|
||||
PlaylistContentType = "application/vnd.apple.mpegurl"
|
||||
MediaContentType = "video/MP2T"
|
||||
)
|
||||
@@ -37,13 +35,6 @@ type Adapter struct{}
|
||||
|
||||
func (Adapter) Name() string { return FormatName }
|
||||
|
||||
func (Adapter) Sniff(h format.Hint) bool {
|
||||
if len(h.Head) > TSPacketSize {
|
||||
return h.Head[0] == tsSyncByte && h.Head[TSPacketSize] == tsSyncByte
|
||||
}
|
||||
return len(h.Head) > 0 && h.Head[0] == tsSyncByte
|
||||
}
|
||||
|
||||
// playlistInfo is the adapter payload: what the generated playback playlist
|
||||
// needs beyond the extent sizes.
|
||||
type playlistInfo struct {
|
||||
|
||||
@@ -190,14 +190,3 @@ func TestMediaSequenceBoundaryRoundTrip(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSniff(t *testing.T) {
|
||||
head := make([]byte, 400)
|
||||
head[0], head[TSPacketSize] = tsSyncByte, tsSyncByte
|
||||
if !(Adapter{}).Sniff(format.Hint{Head: head}) {
|
||||
t.Fatalf("Sniff() rejected TS head")
|
||||
}
|
||||
head[TSPacketSize] = 0
|
||||
if (Adapter{}).Sniff(format.Hint{Head: head}) {
|
||||
t.Fatalf("Sniff() accepted non-TS head")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,25 +373,28 @@ func (fs *FilerServer) formatRepack(ctx context.Context, w http.ResponseWriter,
|
||||
// Close releases the private reader cache and its in-flight prefetches.
|
||||
defer readerAt.Close()
|
||||
|
||||
hint := format.Hint{Name: entry.Name(), ContentType: entry.Attr.Mime, Size: size}
|
||||
sniffSize := int64(formatSniffBytes)
|
||||
if sniffSize > size {
|
||||
sniffSize = size
|
||||
}
|
||||
head := make([]byte, sniffSize)
|
||||
if _, err := readerAt.ReadAt(head, 0); err != nil && err != io.EOF {
|
||||
writeJsonError(w, r, http.StatusInternalServerError, fmt.Errorf("read head: %w", err))
|
||||
return
|
||||
}
|
||||
tail := make([]byte, sniffSize)
|
||||
if _, err := readerAt.ReadAt(tail, size-sniffSize); err != nil && err != io.EOF {
|
||||
writeJsonError(w, r, http.StatusInternalServerError, fmt.Errorf("read tail: %w", err))
|
||||
return
|
||||
}
|
||||
hint.Head, hint.Tail = head, tail
|
||||
if !adapter.Sniff(hint) {
|
||||
writeJsonError(w, r, http.StatusBadRequest, fmt.Errorf("%s does not look like %s", entry.Name(), adapterName))
|
||||
return
|
||||
// cheap magic-byte gate before handing the bytes to the parser
|
||||
if sniffer, ok := adapter.(format.Sniffer); ok {
|
||||
hint := format.Hint{Name: entry.Name(), ContentType: entry.Attr.Mime, Size: size}
|
||||
sniffSize := int64(formatSniffBytes)
|
||||
if sniffSize > size {
|
||||
sniffSize = size
|
||||
}
|
||||
head := make([]byte, sniffSize)
|
||||
if _, err := readerAt.ReadAt(head, 0); err != nil && err != io.EOF {
|
||||
writeJsonError(w, r, http.StatusInternalServerError, fmt.Errorf("read head: %w", err))
|
||||
return
|
||||
}
|
||||
tail := make([]byte, sniffSize)
|
||||
if _, err := readerAt.ReadAt(tail, size-sniffSize); err != nil && err != io.EOF {
|
||||
writeJsonError(w, r, http.StatusInternalServerError, fmt.Errorf("read tail: %w", err))
|
||||
return
|
||||
}
|
||||
hint.Head, hint.Tail = head, tail
|
||||
if !sniffer.Sniff(hint) {
|
||||
writeJsonError(w, r, http.StatusBadRequest, fmt.Errorf("%s does not look like %s", entry.Name(), adapterName))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
layout, err := indexer.Index(ctx, readerAt, size)
|
||||
|
||||
Reference in New Issue
Block a user