vfs: don't use embedded methods for read/write handles for clarity

This commit is contained in:
Nick Craig-Wood 2020-03-19 14:55:07 +00:00
parent 3c14a893fb
commit 8c37262e05
2 changed files with 61 additions and 25 deletions

View File

@ -3,7 +3,6 @@ package vfs
import ( import (
"context" "context"
"fmt" "fmt"
"io"
"io/ioutil" "io/ioutil"
"os" "os"
"runtime" "runtime"
@ -20,7 +19,7 @@ import (
// It will be open to a temporary file which, when closed, will be // It will be open to a temporary file which, when closed, will be
// transferred to the remote. // transferred to the remote.
type RWFileHandle struct { type RWFileHandle struct {
*os.File fd *os.File
mu sync.Mutex mu sync.Mutex
closed bool // set if handle has been closed closed bool // set if handle has been closed
file *File file *File
@ -31,16 +30,6 @@ type RWFileHandle struct {
changed bool // file contents was changed in any other way changed bool // file contents was changed in any other way
} }
// Check interfaces
var (
_ io.Reader = (*RWFileHandle)(nil)
_ io.ReaderAt = (*RWFileHandle)(nil)
_ io.Writer = (*RWFileHandle)(nil)
_ io.WriterAt = (*RWFileHandle)(nil)
_ io.Seeker = (*RWFileHandle)(nil)
_ io.Closer = (*RWFileHandle)(nil)
)
func newRWFileHandle(d *Dir, f *File, flags int) (fh *RWFileHandle, err error) { func newRWFileHandle(d *Dir, f *File, flags int) (fh *RWFileHandle, err error) {
// if O_CREATE and O_EXCL are set and if path already exists, then return EEXIST // if O_CREATE and O_EXCL are set and if path already exists, then return EEXIST
if flags&(os.O_CREATE|os.O_EXCL) == os.O_CREATE|os.O_EXCL && f.exists() { if flags&(os.O_CREATE|os.O_EXCL) == os.O_CREATE|os.O_EXCL && f.exists() {
@ -172,7 +161,7 @@ func (fh *RWFileHandle) openPending(truncate bool) (err error) {
return errors.Wrap(err, "cache open file failed") return errors.Wrap(err, "cache open file failed")
} }
} }
fh.File = fd fh.fd = fd
fh.opened = true fh.opened = true
fh.file.addRWOpen() fh.file.addRWOpen()
fh.d.addObject(fh.file) // make sure the directory has this object in it now fh.d.addObject(fh.file) // make sure the directory has this object in it now
@ -242,7 +231,7 @@ func (fh *RWFileHandle) flushWrites(closeFile bool) error {
} }
if writer && fh.opened { if writer && fh.opened {
fi, err := fh.File.Stat() fi, err := fh.fd.Stat()
if err != nil { if err != nil {
fs.Errorf(fh.logPrefix(), "Failed to stat cache file: %v", err) fs.Errorf(fh.logPrefix(), "Failed to stat cache file: %v", err)
} else { } else {
@ -252,7 +241,7 @@ func (fh *RWFileHandle) flushWrites(closeFile bool) error {
// Close the underlying file // Close the underlying file
if fh.opened && closeFile { if fh.opened && closeFile {
err := fh.File.Close() err := fh.fd.Close()
if err != nil { if err != nil {
err = errors.Wrap(err, "failed to close cache file") err = errors.Wrap(err, "failed to close cache file")
return err return err
@ -371,7 +360,7 @@ func (fh *RWFileHandle) Size() int64 {
if !fh.opened { if !fh.opened {
return fh.file.Size() return fh.file.Size()
} }
fi, err := fh.File.Stat() fi, err := fh.fd.Stat()
if err != nil { if err != nil {
return 0 return 0
} }
@ -405,14 +394,14 @@ func (fh *RWFileHandle) readFn(read func() (int, error)) (n int, err error) {
// Read bytes from the file // Read bytes from the file
func (fh *RWFileHandle) Read(b []byte) (n int, err error) { func (fh *RWFileHandle) Read(b []byte) (n int, err error) {
return fh.readFn(func() (int, error) { return fh.readFn(func() (int, error) {
return fh.File.Read(b) return fh.fd.Read(b)
}) })
} }
// ReadAt bytes from the file at off // ReadAt bytes from the file at off
func (fh *RWFileHandle) ReadAt(b []byte, off int64) (n int, err error) { func (fh *RWFileHandle) ReadAt(b []byte, off int64) (n int, err error) {
return fh.readFn(func() (int, error) { return fh.readFn(func() (int, error) {
return fh.File.ReadAt(b, off) return fh.fd.ReadAt(b, off)
}) })
} }
@ -429,7 +418,7 @@ func (fh *RWFileHandle) Seek(offset int64, whence int) (ret int64, err error) {
if err = fh.openPending(false); err != nil { if err = fh.openPending(false); err != nil {
return ret, err return ret, err
} }
return fh.File.Seek(offset, whence) return fh.fd.Seek(offset, whence)
} }
// writeFn general purpose write call // writeFn general purpose write call
@ -452,7 +441,7 @@ func (fh *RWFileHandle) writeFn(write func() error) (err error) {
if err != nil { if err != nil {
return err return err
} }
fi, err := fh.File.Stat() fi, err := fh.fd.Stat()
if err != nil { if err != nil {
return errors.Wrap(err, "failed to stat cache file") return errors.Wrap(err, "failed to stat cache file")
} }
@ -463,7 +452,7 @@ func (fh *RWFileHandle) writeFn(write func() error) (err error) {
// Write bytes to the file // Write bytes to the file
func (fh *RWFileHandle) Write(b []byte) (n int, err error) { func (fh *RWFileHandle) Write(b []byte) (n int, err error) {
err = fh.writeFn(func() error { err = fh.writeFn(func() error {
n, err = fh.File.Write(b) n, err = fh.fd.Write(b)
return err return err
}) })
return n, err return n, err
@ -476,7 +465,7 @@ func (fh *RWFileHandle) WriteAt(b []byte, off int64) (n int, err error) {
return fh.Write(b) return fh.Write(b)
} }
err = fh.writeFn(func() error { err = fh.writeFn(func() error {
n, err = fh.File.WriteAt(b, off) n, err = fh.fd.WriteAt(b, off)
return err return err
}) })
return n, err return n, err
@ -485,7 +474,7 @@ func (fh *RWFileHandle) WriteAt(b []byte, off int64) (n int, err error) {
// WriteString a string to the file // WriteString a string to the file
func (fh *RWFileHandle) WriteString(s string) (n int, err error) { func (fh *RWFileHandle) WriteString(s string) (n int, err error) {
err = fh.writeFn(func() error { err = fh.writeFn(func() error {
n, err = fh.File.WriteString(s) n, err = fh.fd.WriteString(s)
return err return err
}) })
return n, err return n, err
@ -503,7 +492,7 @@ func (fh *RWFileHandle) Truncate(size int64) (err error) {
} }
fh.changed = true fh.changed = true
fh.file.setSize(size) fh.file.setSize(size)
return fh.File.Truncate(size) return fh.fd.Truncate(size)
} }
// Sync commits the current contents of the file to stable storage. Typically, // Sync commits the current contents of the file to stable storage. Typically,
@ -521,9 +510,45 @@ func (fh *RWFileHandle) Sync() error {
if fh.flags&accessModeMask == os.O_RDONLY { if fh.flags&accessModeMask == os.O_RDONLY {
return nil return nil
} }
return fh.File.Sync() return fh.fd.Sync()
} }
func (fh *RWFileHandle) logPrefix() string { func (fh *RWFileHandle) logPrefix() string {
return fmt.Sprintf("%s(%p)", fh.file.Path(), fh) return fmt.Sprintf("%s(%p)", fh.file.Path(), fh)
} }
// Chdir changes the current working directory to the file, which must
// be a directory.
func (fh *RWFileHandle) Chdir() error {
return ENOSYS
}
// Chmod changes the mode of the file to mode.
func (fh *RWFileHandle) Chmod(mode os.FileMode) error {
return ENOSYS
}
// Chown changes the numeric uid and gid of the named file.
func (fh *RWFileHandle) Chown(uid, gid int) error {
return ENOSYS
}
// Fd returns the integer Unix file descriptor referencing the open file.
func (fh *RWFileHandle) Fd() uintptr {
return fh.fd.Fd()
}
// Name returns the name of the file from the underlying Object.
func (fh *RWFileHandle) Name() string {
return fh.file.String()
}
// Readdir reads the contents of the directory associated with file.
func (fh *RWFileHandle) Readdir(n int) ([]os.FileInfo, error) {
return nil, ENOSYS
}
// Readdirnames reads the contents of the directory associated with file.
func (fh *RWFileHandle) Readdirnames(n int) (names []string, err error) {
return nil, ENOSYS
}

View File

@ -18,6 +18,17 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
// Check interfaces
var (
_ io.Reader = (*RWFileHandle)(nil)
_ io.ReaderAt = (*RWFileHandle)(nil)
_ io.Writer = (*RWFileHandle)(nil)
_ io.WriterAt = (*RWFileHandle)(nil)
_ io.Seeker = (*RWFileHandle)(nil)
_ io.Closer = (*RWFileHandle)(nil)
_ Handle = (*RWFileHandle)(nil)
)
func cleanup(t *testing.T, r *fstest.Run, vfs *VFS) { func cleanup(t *testing.T, r *fstest.Run, vfs *VFS) {
assert.NoError(t, vfs.CleanUp()) assert.NoError(t, vfs.CleanUp())
vfs.Shutdown() vfs.Shutdown()