// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn . //go:build plus && !windows package mmap import ( "fmt" fsutils "github.com/TeaOSLab/EdgeNode/internal/utils/fs" "io" "os" "runtime" "sync/atomic" "syscall" ) var totalMMAPFileSize int64 func TotalMMAPFileSize() int64 { return atomic.LoadInt64(&totalMMAPFileSize) } // OpenFile memory-maps the file pointer for reading. func OpenFile(f *os.File, size int64) (r *ReaderAt, err error) { // update stat atomic.AddInt64(&totalMMAPFileSize, size) defer func() { if r == nil { atomic.AddInt64(&totalMMAPFileSize, -size) } }() defer func() { _ = f.Close() }() if size == 0 { return &ReaderAt{ data: make([]byte, 0), }, nil } if size < 0 { return nil, fmt.Errorf("mmap: file %q has negative size", f.Name()) } if size != int64(int(size)) { return nil, fmt.Errorf("mmap: file %q is too large", f.Name()) } fsutils.ReaderLimiter.Ack() data, err := syscall.Mmap(int(f.Fd()), 0, int(size), syscall.PROT_READ, MMAPReadFlags) fsutils.ReaderLimiter.Release() if err != nil { return nil, err } r = &ReaderAt{ data: data, size: size, } runtime.SetFinalizer(r, (*ReaderAt).Close) return r, nil } func (r *ReaderAt) Write(writer io.Writer, offset int) (int, error) { var l = len(r.data) const segmentSize = 16 << 10 if l-offset <= segmentSize { return writer.Write(r.data[offset:]) } var n int for { var n1 int var err error fsutils.ReaderLimiter.Ack() if offset+segmentSize <= l { n1, err = writer.Write(r.data[offset : offset+segmentSize]) } else { n1, err = writer.Write(r.data[offset:]) } fsutils.ReaderLimiter.Release() n += n1 offset += n1 if err != nil { return n, err } if offset >= l { break } } return n, nil }