summaryrefslogtreecommitdiff
path: root/vendor/codeberg.org/gruf/go-mmap/open.go
blob: c12a091d312f4e801b5d0f2cb88c7c0e57ac03f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package mmap

import (
	"io"
	"io/fs"
	"os"
	"runtime"
	"syscall"
)

// MmapThreshold defines the threshold file size (in bytes) for which
// a call to OpenRead() will deem as big enough for a file to be worth
// opening using an `mmap` syscall. This is a runtime initialized number
// based on the number of available CPUs as in concurrent conditions Go
// can make optimizations for blocking `read` syscalls which scales with
// the number of available goroutines it can have running at once.
var MmapThreshold = int64(runtime.NumCPU() * syscall.Getpagesize())

// FileReader defines the base interface
// of a readable file, whether accessed
// via `read` or `mmap` syscalls.
type FileReader interface {
	fs.File
	io.ReaderAt
	io.WriterTo
	io.Seeker
	Name() string
}

// Threshold is a receiving type for OpenRead()
// that allows defining a custom MmapThreshold.
type Threshold struct{ At int64 }

// OpenRead: see mmap.OpenRead().
func (t Threshold) OpenRead(path string) (FileReader, error) {
	stat, err := stat(path)
	if err != nil {
		return nil, err
	}
	if stat.Size() >= t.At {
		return openMmap(path, stat)
	} else {
		return os.OpenFile(path, syscall.O_RDONLY, 0)
	}
}

// OpenRead will open the file as read only (erroring if it does
// not already exist). If the file at path is beyond 'MmapThreshold'
// it will be opened for reads using an `mmap` syscall, by calling
// MmappedRead(path). Else, it will be opened using os.OpenFile().
//
// Please note that the reader returned by this function is not
// guaranteed to be concurrency-safe. Calls returned by os.OpenFile()
// follow the usual standard library concurrency guarantees, but the
// reader returned by MmappedRead() provides no concurrent protection.
//
// Also note that this may not always be faster! If the file you need
// to open will be immediately drained to another file, TCP or Unix
// connection, then the standard library will used optimized syscalls.
func OpenRead(path string) (FileReader, error) {
	return Threshold{MmapThreshold}.OpenRead(path)
}