Files
2026-06-29 12:35:32 +02:00

62 lines
1.5 KiB
Go

//go:build unix
// mmap-on-unix loader for SnapshotReader. The file handle stays alive for
// the lifetime of the mmap region (the kernel needs it pinned). Closer
// munmaps AND closes the fd. Uses MADV_RANDOM because the dominant access
// pattern is binary-search-by-key — touching random record slots, not
// streaming the file.
package projection
import (
"fmt"
"os"
"golang.org/x/sys/unix"
)
// loadSnapshotBytes returns the file contents (mmap'd) + a closer that munmaps
// and closes the fd.
func loadSnapshotBytes(path string) (data []byte, closer func() error, err error) {
f, err := os.Open(path)
if err != nil {
return nil, nil, err
}
info, err := f.Stat()
if err != nil {
_ = f.Close()
return nil, nil, err
}
size := info.Size()
if size == 0 {
_ = f.Close()
return []byte{}, func() error { return nil }, nil
}
if size < int64(headerSize) {
_ = f.Close()
return nil, nil, ErrSnapshotTruncated
}
data, mmapErr := unix.Mmap(int(f.Fd()), 0, int(size), unix.PROT_READ, unix.MAP_SHARED)
if mmapErr != nil {
_ = f.Close()
return nil, nil, fmt.Errorf("projection: mmap %s: %w", path, mmapErr)
}
// Binary-search by key = random page access; MADV_RANDOM tells the
// kernel NOT to do read-ahead — saves I/O on cold layers.
if maErr := unix.Madvise(data, unix.MADV_RANDOM); maErr != nil {
// non-fatal; degrade gracefully
_ = maErr
}
closer = func() error {
mErr := unix.Munmap(data)
cErr := f.Close()
if mErr != nil {
return mErr
}
return cErr
}
return data, closer, nil
}