Add Read/Write to the MMap interface

This commit is contained in:
Kovid Goyal 2023-02-28 19:01:15 +05:30
parent 944e036611
commit 5b46d990a2
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 87 additions and 3 deletions

View File

@ -53,6 +53,9 @@ type MMap interface {
FileSystemName() string FileSystemName() string
Stat() (fs.FileInfo, error) Stat() (fs.FileInfo, error)
Flush() error Flush() error
Seek(offset int64, whence int) (ret int64, err error)
Read(b []byte) (n int, err error)
Write(b []byte) (n int, err error)
} }
type AccessFlags int type AccessFlags int
@ -106,9 +109,11 @@ func truncate_or_unlink(ans *os.File, size uint64) (err error) {
const NUM_BYTES_FOR_SIZE = 4 const NUM_BYTES_FOR_SIZE = 4
var ErrRegionTooSmall = errors.New("mmaped region too small")
func WriteWithSize(self MMap, b []byte, at int) error { func WriteWithSize(self MMap, b []byte, at int) error {
if len(self.Slice()) < at+len(b)+NUM_BYTES_FOR_SIZE { if len(self.Slice()) < at+len(b)+NUM_BYTES_FOR_SIZE {
return io.ErrShortBuffer return ErrRegionTooSmall
} }
binary.BigEndian.PutUint32(self.Slice()[at:], uint32(len(b))) binary.BigEndian.PutUint32(self.Slice()[at:], uint32(len(b)))
copy(self.Slice()[at+NUM_BYTES_FOR_SIZE:], b) copy(self.Slice()[at+NUM_BYTES_FOR_SIZE:], b)
@ -118,12 +123,12 @@ func WriteWithSize(self MMap, b []byte, at int) error {
func ReadWithSize(self MMap, at int) ([]byte, error) { func ReadWithSize(self MMap, at int) ([]byte, error) {
s := self.Slice()[at:] s := self.Slice()[at:]
if len(s) < NUM_BYTES_FOR_SIZE { if len(s) < NUM_BYTES_FOR_SIZE {
return nil, io.ErrShortBuffer return nil, ErrRegionTooSmall
} }
size := int(binary.BigEndian.Uint32(self.Slice()[at : at+NUM_BYTES_FOR_SIZE])) size := int(binary.BigEndian.Uint32(self.Slice()[at : at+NUM_BYTES_FOR_SIZE]))
s = s[NUM_BYTES_FOR_SIZE:] s = s[NUM_BYTES_FOR_SIZE:]
if len(s) < size { if len(s) < size {
return nil, io.ErrShortBuffer return nil, ErrRegionTooSmall
} }
return s[:size], nil return s[:size], nil
} }
@ -158,6 +163,41 @@ func ReadWithSizeAndUnlink(name string, file_callback ...func(fs.FileInfo) error
return ans, nil return ans, nil
} }
func Read(self MMap, b []byte) (n int, err error) {
pos, _ := self.Seek(0, io.SeekCurrent)
if pos < 0 {
pos = 0
}
s := self.Slice()
sz := int64(len(s))
if pos >= sz {
return 0, io.EOF
}
n = copy(b, s[pos:])
self.Seek(int64(n), io.SeekCurrent)
return
}
func Write(self MMap, b []byte) (n int, err error) {
if len(b) == 0 {
return 0, nil
}
pos, _ := self.Seek(0, io.SeekCurrent)
if pos < 0 {
pos = 0
}
s := self.Slice()
if pos >= int64(len(s)) {
return 0, io.ErrShortWrite
}
n = copy(s[pos:], b)
self.Seek(int64(n), io.SeekCurrent)
if n < len(b) {
return n, io.ErrShortWrite
}
return n, nil
}
func test_integration_with_python(args []string) (rc int, err error) { func test_integration_with_python(args []string) (rc int, err error) {
switch args[0] { switch args[0] {
default: default:

View File

@ -7,6 +7,7 @@ import (
"crypto/sha256" "crypto/sha256"
"errors" "errors"
"fmt" "fmt"
"io"
"io/fs" "io/fs"
"os" "os"
"path/filepath" "path/filepath"
@ -21,6 +22,7 @@ var _ = fmt.Print
type file_based_mmap struct { type file_based_mmap struct {
f *os.File f *os.File
pos int64
region []byte region []byte
unlinked bool unlinked bool
special_name string special_name string
@ -42,6 +44,26 @@ func file_mmap(f *os.File, size uint64, access AccessFlags, truncate bool, speci
return &file_based_mmap{f: f, region: region, special_name: special_name}, nil return &file_based_mmap{f: f, region: region, special_name: special_name}, nil
} }
func (self *file_based_mmap) Seek(offset int64, whence int) (ret int64, err error) {
switch whence {
case io.SeekStart:
self.pos = offset
case os.SEEK_END:
self.pos = int64(len(self.region)) + offset
case os.SEEK_CUR:
self.pos += offset
}
return self.pos, nil
}
func (self *file_based_mmap) Read(b []byte) (n int, err error) {
return Read(self, b)
}
func (self *file_based_mmap) Write(b []byte) (n int, err error) {
return Write(self, b)
}
func (self *file_based_mmap) Stat() (fs.FileInfo, error) { func (self *file_based_mmap) Stat() (fs.FileInfo, error) {
return self.f.Stat() return self.f.Stat()
} }

View File

@ -6,6 +6,7 @@ package shm
import ( import (
"errors" "errors"
"fmt" "fmt"
"io"
"io/fs" "io/fs"
"os" "os"
"strings" "strings"
@ -65,6 +66,7 @@ func shm_open(name string, flags, perm int) (ans *os.File, err error) {
type syscall_based_mmap struct { type syscall_based_mmap struct {
f *os.File f *os.File
pos int64
region []byte region []byte
unlinked bool unlinked bool
} }
@ -117,6 +119,26 @@ func (self *syscall_based_mmap) Unlink() (err error) {
return shm_unlink(self.Name()) return shm_unlink(self.Name())
} }
func (self *syscall_based_mmap) Seek(offset int64, whence int) (ret int64, err error) {
switch whence {
case io.SeekStart:
self.pos = offset
case os.SEEK_END:
self.pos = int64(len(self.region)) + offset
case os.SEEK_CUR:
self.pos += offset
}
return self.pos, nil
}
func (self *syscall_based_mmap) Read(b []byte) (n int, err error) {
return Read(self, b)
}
func (self *syscall_based_mmap) Write(b []byte) (n int, err error) {
return Write(self, b)
}
func (self *syscall_based_mmap) IsFileSystemBacked() bool { return false } func (self *syscall_based_mmap) IsFileSystemBacked() bool { return false }
func (self *syscall_based_mmap) FileSystemName() string { return "" } func (self *syscall_based_mmap) FileSystemName() string { return "" }