File: file.go

package info (click to toggle)
golang-github-tinylib-msgp 1.2.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 836 kB
  • sloc: makefile: 47
file content (93 lines) | stat: -rw-r--r-- 2,527 bytes parent folder | download | duplicates (2)
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
//go:build (linux || darwin || dragonfly || freebsd || illumos || netbsd || openbsd) && !appengine && !tinygo
// +build linux darwin dragonfly freebsd illumos netbsd openbsd
// +build !appengine
// +build !tinygo

package msgp

import (
	"os"
	"syscall"
)

// ReadFile reads a file into 'dst' using
// a read-only memory mapping. Consequently,
// the file must be mmap-able, and the
// Unmarshaler should never write to
// the source memory. (Methods generated
// by the msgp tool obey that constraint, but
// user-defined implementations may not.)
//
// Reading and writing through file mappings
// is only efficient for large files; small
// files are best read and written using
// the ordinary streaming interfaces.
func ReadFile(dst Unmarshaler, file *os.File) error {
	stat, err := file.Stat()
	if err != nil {
		return err
	}
	data, err := syscall.Mmap(int(file.Fd()), 0, int(stat.Size()), syscall.PROT_READ, syscall.MAP_SHARED)
	if err != nil {
		return err
	}
	adviseRead(data)
	_, err = dst.UnmarshalMsg(data)
	uerr := syscall.Munmap(data)
	if err == nil {
		err = uerr
	}
	return err
}

// MarshalSizer is the combination
// of the Marshaler and Sizer
// interfaces.
type MarshalSizer interface {
	Marshaler
	Sizer
}

// WriteFile writes a file from 'src' using
// memory mapping. It overwrites the entire
// contents of the previous file.
// The mapping size is calculated
// using the `Msgsize()` method
// of 'src', so it must produce a result
// equal to or greater than the actual encoded
// size of the object. Otherwise,
// a fault (SIGBUS) will occur.
//
// Reading and writing through file mappings
// is only efficient for large files; small
// files are best read and written using
// the ordinary streaming interfaces.
//
// NOTE: The performance of this call
// is highly OS- and filesystem-dependent.
// Users should take care to test that this
// performs as expected in a production environment.
// (Linux users should run a kernel and filesystem
// that support fallocate(2) for the best results.)
func WriteFile(src MarshalSizer, file *os.File) error {
	sz := src.Msgsize()
	err := fallocate(file, int64(sz))
	if err != nil {
		return err
	}
	data, err := syscall.Mmap(int(file.Fd()), 0, sz, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED)
	if err != nil {
		return err
	}
	adviseWrite(data)
	chunk := data[:0]
	chunk, err = src.MarshalMsg(chunk)
	if err != nil {
		return err
	}
	uerr := syscall.Munmap(data)
	if uerr != nil {
		return uerr
	}
	return file.Truncate(int64(len(chunk)))
}