Skip to content

Commit

Permalink
🐳 mmap: migrate to unix.MmapPtr & unix.MunmapPtr
Browse files Browse the repository at this point in the history
While here, improve the API and add a fallback path for files on unsupported filesystems.
  • Loading branch information
database64128 committed Jul 5, 2024
1 parent 7143719 commit d88ced6
Show file tree
Hide file tree
Showing 15 changed files with 147 additions and 172 deletions.
4 changes: 2 additions & 2 deletions cmd/shadowsocks-go-domain-set-converter/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ func main() {
os.Exit(1)
}

data, err := mmap.ReadFile[string](inPath)
data, close, err := mmap.ReadFile[string](inPath)
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to read input file:", err)
os.Exit(1)
}
defer mmap.Unmap(data)
defer close()

dsb, err := inFunc(data)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions cred/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,11 +254,11 @@ func (s *ManagedServer) DeleteCredential(username string) error {
// LoadFromFile loads credentials from the configured credential file
// and applies the changes to the associated credential stores.
func (s *ManagedServer) LoadFromFile() error {
content, err := mmap.ReadFile[string](s.path)
content, close, err := mmap.ReadFile[string](s.path)
if err != nil {
return err
}
defer mmap.Unmap(content)
defer close()

s.mu.Lock()
// Skip if the file content is unchanged.
Expand Down
4 changes: 2 additions & 2 deletions domainset/domainset.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ type Config struct {

// DomainSet creates a DomainSet from the configuration.
func (dsc Config) DomainSet() (DomainSet, error) {
data, err := mmap.ReadFile[string](dsc.Path)
data, close, err := mmap.ReadFile[string](dsc.Path)
if err != nil {
return nil, fmt.Errorf("failed to load domain set %s: %w", dsc.Name, err)
}
defer mmap.Unmap(data)
defer close()

var dsb Builder

Expand Down
16 changes: 8 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,28 @@ go 1.22.2

require (
github.com/database64128/tfo-go/v2 v2.2.1
github.com/gofiber/contrib/fiberzap/v2 v2.1.3
github.com/gofiber/contrib/fiberzap/v2 v2.1.4
github.com/gofiber/fiber/v2 v2.52.5
github.com/oschwald/geoip2-golang v1.11.0
go.uber.org/zap v1.27.0
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
golang.org/x/net v0.26.0
golang.org/x/sys v0.21.0
golang.org/x/sys v0.22.0
lukechampine.com/blake3 v1.3.0
)

require (
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/google/uuid v1.5.0 // indirect
github.com/klauspost/compress v1.17.6 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/oschwald/maxminddb-golang v1.13.0 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/oschwald/maxminddb-golang v1.13.1 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.52.0 // indirect
github.com/valyala/fasthttp v1.55.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
)
32 changes: 16 additions & 16 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ github.com/database64128/tfo-go/v2 v2.2.1 h1:IFctPnetEQtGo7gI84QfR1pAbi6TRPkxCFy
github.com/database64128/tfo-go/v2 v2.2.1/go.mod h1:SI59G6MmmzSm9/fSRTiyYyyInHp4WEF9lTldnm3mxmA=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gofiber/contrib/fiberzap/v2 v2.1.3 h1:znIDjHJUyhp11h5w8AaABCtEJejxjiCe47O0OC5We/g=
github.com/gofiber/contrib/fiberzap/v2 v2.1.3/go.mod h1:9KrEpG4A8g1Y4J7OS5WYq6rDyy+sXAEDSgGdCGPnH1Y=
github.com/gofiber/contrib/fiberzap/v2 v2.1.4 h1:GCtCQnT4Cr9az4qab2Ozmqsomkxm4Ei86MfKk/1p5+0=
github.com/gofiber/contrib/fiberzap/v2 v2.1.4/go.mod h1:PkdXgUzw+oj4m6ksfKJ0Hs3H7iPhwvhfI4b2LSA9hhA=
github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yGMo=
github.com/gofiber/fiber/v2 v2.52.5/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI=
github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
Expand All @@ -23,19 +23,19 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/oschwald/geoip2-golang v1.11.0 h1:hNENhCn1Uyzhf9PTmquXENiWS6AlxAEnBII6r8krA3w=
github.com/oschwald/geoip2-golang v1.11.0/go.mod h1:P9zG+54KPEFOliZ29i7SeYZ/GM6tfEL+rgSn03hYuUo=
github.com/oschwald/maxminddb-golang v1.13.0 h1:R8xBorY71s84yO06NgTmQvqvTvlS/bnYZrrWX1MElnU=
github.com/oschwald/maxminddb-golang v1.13.0/go.mod h1:BU0z8BfFVhi1LQaonTwwGQlsHUEu9pWNdMfmq4ztm0o=
github.com/oschwald/maxminddb-golang v1.13.1 h1:G3wwjdN9JmIK2o/ermkHM+98oX5fS+k5MbwsmL4MRQE=
github.com/oschwald/maxminddb-golang v1.13.1/go.mod h1:K4pgV9N/GcK694KSTmVSDTODk4IsCNThNdTmnaBZ/F8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.52.0 h1:wqBQpxH71XW0e2g+Og4dzQM8pk34aFYlA1Ga8db7gU0=
github.com/valyala/fasthttp v1.52.0/go.mod h1:hf5C4QnVMkNXMspnsUlfM3WitlgYflyhHYoKol/szxQ=
github.com/valyala/fasthttp v1.55.0 h1:Zkefzgt6a7+bVKHnu/YaYSOPfNYNisSVBo/unVCf8k8=
github.com/valyala/fasthttp v1.55.0/go.mod h1:NkY9JtkrpPKmgwV3HTaS2HWaJss9RSIsRVfcxxoHiOM=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
Expand All @@ -51,8 +51,8 @@ golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
Expand Down
48 changes: 48 additions & 0 deletions mmap/mmap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package mmap

import (
"errors"
"io"
"os"
"unsafe"
)

// ReadFile maps the named file into memory for reading.
// On success, it returns the mapped data as a byte slice or a string,
// and a function that unmaps the data.
func ReadFile[T ~[]byte | ~string](name string) (data T, close func() error, err error) {
f, err := os.Open(name)
if err != nil {
return
}
defer f.Close()

fs, err := f.Stat()
if err != nil {
return
}

size := fs.Size()
if size == 0 {
return
}

addr, close, err := readFile(f, uintptr(size))
if err != nil {
if errors.Is(err, errors.ErrUnsupported) {
return readFileFallback[T](f, size)
}
return
}

b := unsafe.Slice((*byte)(addr), size)
return *(*T)(unsafe.Pointer(&b)), close, nil
}

func readFileFallback[T ~[]byte | ~string](f *os.File, size int64) (data T, close func() error, err error) {
b := make([]byte, size)
if _, err = io.ReadFull(f, b); err != nil {
return
}
return *(*T)(unsafe.Pointer(&b)), func() error { return nil }, nil
}
22 changes: 0 additions & 22 deletions mmap/mmap_generic.go

This file was deleted.

23 changes: 23 additions & 0 deletions mmap/mmap_stub.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//go:build !unix && !windows

package mmap

import (
"errors"
"os"
"unsafe"
)

type mmapUnsupportError struct{}

func (mmapUnsupportError) Error() string {
return "mmap is not supported on this platform"
}

func (mmapUnsupportError) Is(target error) bool {
return target == errors.ErrUnsupported
}

func readFile(_ *os.File, _ uintptr) (addr unsafe.Pointer, close func() error, err error) {
return nil, nil, mmapUnsupportError{}
}
8 changes: 4 additions & 4 deletions mmap/mmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@ func TestReadFile(t *testing.T) {
t.Fatal(err)
}

t.Logf("Created temporary test file: %s", name)
t.Logf("Created temporary test file: %q", name)

data, err := ReadFile[string](name)
data, close, err := ReadFile[string](name)
if err != nil {
t.Fatal(err)
}
if data != name {
t.Errorf("Expected file content %s, got %s", name, data)
t.Errorf("Expected file content %q, got %q", name, data)
}

if err = Unmap(data); err != nil {
if err = close(); err != nil {
t.Fatal(err)
}
}
31 changes: 31 additions & 0 deletions mmap/mmap_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//go:build unix

package mmap

import (
"os"
"unsafe"

"golang.org/x/sys/unix"
)

func readFile(f *os.File, size uintptr) (addr unsafe.Pointer, close func() error, err error) {
rawConn, err := f.SyscallConn()
if err != nil {
return nil, nil, err
}

if cerr := rawConn.Control(func(fd uintptr) {
addr, err = unix.MmapPtr(int(fd), 0, nil, size, unix.PROT_READ, unix.MAP_SHARED)
}); cerr != nil {
return nil, nil, cerr
}

if err != nil {
return nil, nil, err
}

return addr, func() error {
return unix.MunmapPtr(addr, size)
}, nil
}
25 changes: 0 additions & 25 deletions mmap/mmap_unix_fast.go

This file was deleted.

27 changes: 0 additions & 27 deletions mmap/mmap_unix_generic.go

This file was deleted.

53 changes: 0 additions & 53 deletions mmap/mmap_unixwindows.go

This file was deleted.

Loading

0 comments on commit d88ced6

Please sign in to comment.