Files
waf-platform/EdgeNode/internal/utils/mmap/mmap_ext_unix.go

96 lines
1.8 KiB
Go

// 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
}