vfs: Implement Create support (#13)
* vfs: Implement Create support Signed-off-by: Xuanwo <github@xuanwo.io> * Format code Signed-off-by: Xuanwo <github@xuanwo.io>
This commit is contained in:
parent
0b64b1feef
commit
a1d9d0c129
|
@ -95,6 +95,11 @@ func fillAttrOut(i *vfs.Inode, out *fuse.AttrOut) fuse.Status {
|
|||
return fuse.OK
|
||||
}
|
||||
|
||||
func fillOpenOut(fh *vfs.FileHandle, out *fuse.OpenOut) fuse.Status {
|
||||
out.Fh = fh.ID
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func parseError(err error) fuse.Status {
|
||||
switch {
|
||||
case errors.Is(err, services.ErrObjectNotExist):
|
||||
|
@ -303,7 +308,15 @@ func (fs *FS) Create(cancel <-chan struct{}, input *fuse.CreateIn, name string,
|
|||
return fuse.EINVAL
|
||||
}
|
||||
|
||||
// Implement me
|
||||
i, fh, err := fs.fs.Create(ino.ID, name)
|
||||
if err != nil {
|
||||
fs.logger.Error("create", zap.Error(err))
|
||||
return fuse.EAGAIN
|
||||
}
|
||||
fs.logger.Info("start fill open out")
|
||||
fillOpenOut(fh, &out.OpenOut)
|
||||
fs.logger.Info("start fill entry out")
|
||||
fillEntryOut(i, &out.EntryOut)
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
|
@ -320,7 +333,12 @@ func (fs *FS) Open(cancel <-chan struct{}, input *fuse.OpenIn, out *fuse.OpenOut
|
|||
return fuse.ENOENT
|
||||
}
|
||||
|
||||
panic("implement me")
|
||||
fh, err := fs.fs.CreateFileHandle(ino)
|
||||
if err != nil {
|
||||
fs.logger.Error("create file handle", zap.Error(err))
|
||||
return
|
||||
}
|
||||
return fillOpenOut(fh, out)
|
||||
}
|
||||
|
||||
func (fs *FS) Read(cancel <-chan struct{}, input *fuse.ReadIn, buf []byte) (fuse.ReadResult, fuse.Status) {
|
||||
|
@ -344,7 +362,12 @@ func (fs *FS) SetLkw(cancel <-chan struct{}, input *fuse.LkIn) (code fuse.Status
|
|||
}
|
||||
|
||||
func (fs *FS) Release(cancel <-chan struct{}, input *fuse.ReleaseIn) {
|
||||
panic("implement me")
|
||||
err := fs.fs.DeleteFileHandle(input.Fh)
|
||||
if err != nil {
|
||||
fs.logger.Error("release",
|
||||
zap.Uint64("file_handle", input.Fh),
|
||||
zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *FS) Write(cancel <-chan struct{}, input *fuse.WriteIn, data []byte) (written uint32, code fuse.Status) {
|
||||
|
@ -356,7 +379,8 @@ func (fs *FS) CopyFileRange(cancel <-chan struct{}, input *fuse.CopyFileRangeIn)
|
|||
}
|
||||
|
||||
func (fs *FS) Flush(cancel <-chan struct{}, input *fuse.FlushIn) fuse.Status {
|
||||
panic("implement me")
|
||||
// FIXME: maybe we need to write data here.
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func (fs *FS) Fsync(cancel <-chan struct{}, input *fuse.FsyncIn) (code fuse.Status) {
|
||||
|
|
|
@ -2,9 +2,11 @@ package vfs
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/beyondstorage/beyond-fs/meta"
|
||||
"github.com/beyondstorage/go-storage/v4/types"
|
||||
"sync"
|
||||
|
||||
"github.com/beyondstorage/go-storage/v4/types"
|
||||
|
||||
"github.com/beyondstorage/beyond-fs/meta"
|
||||
)
|
||||
|
||||
type dirHandleMap struct {
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package vfs
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/beyondstorage/beyond-fs/meta"
|
||||
)
|
||||
|
||||
type fileHandleMap struct {
|
||||
lock sync.Mutex
|
||||
m map[uint64]*FileHandle
|
||||
}
|
||||
|
||||
func newFileHandleMap() *fileHandleMap {
|
||||
return &fileHandleMap{
|
||||
m: make(map[uint64]*FileHandle),
|
||||
}
|
||||
}
|
||||
|
||||
func (fhm *fileHandleMap) Get(id uint64) *FileHandle {
|
||||
fhm.lock.Lock()
|
||||
defer fhm.lock.Unlock()
|
||||
|
||||
return fhm.m[id]
|
||||
}
|
||||
|
||||
func (fhm *fileHandleMap) Set(id uint64, dh *FileHandle) {
|
||||
fhm.lock.Lock()
|
||||
defer fhm.lock.Unlock()
|
||||
|
||||
fhm.m[id] = dh
|
||||
}
|
||||
|
||||
func (fhm *fileHandleMap) Delete(id uint64) {
|
||||
fhm.lock.Lock()
|
||||
defer fhm.lock.Unlock()
|
||||
|
||||
delete(fhm.m, id)
|
||||
}
|
||||
|
||||
type FileHandle struct {
|
||||
ID uint64
|
||||
|
||||
ino *Inode
|
||||
fs *FS
|
||||
meta meta.Service
|
||||
}
|
57
vfs/fs.go
57
vfs/fs.go
|
@ -1,7 +1,9 @@
|
|||
package vfs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
_ "github.com/beyondstorage/go-service-fs/v3"
|
||||
_ "github.com/beyondstorage/go-service-s3/v2"
|
||||
|
@ -32,6 +34,7 @@ type FS struct {
|
|||
meta meta.Service
|
||||
|
||||
dhm *dirHandleMap
|
||||
fhm *fileHandleMap
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
|
@ -57,6 +60,7 @@ func NewFS(cfg *Config) (fs *FS, err error) {
|
|||
meta: metaSrv,
|
||||
|
||||
dhm: newDirHandleMap(),
|
||||
fhm: newFileHandleMap(),
|
||||
logger: cfg.Logger,
|
||||
}
|
||||
|
||||
|
@ -71,6 +75,39 @@ func NewFS(cfg *Config) (fs *FS, err error) {
|
|||
return fs, err
|
||||
}
|
||||
|
||||
func (fs *FS) Create(parent uint64, name string) (ino *Inode, fh *FileHandle, err error) {
|
||||
// FIXME: we need to handle file exists.
|
||||
p, err := fs.GetInode(parent)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
path := p.GetEntryPath(name)
|
||||
_, err = fs.s.Write(path, bytes.NewReader([]byte{}), 0)
|
||||
if err != nil {
|
||||
fs.logger.Error("write", zap.String("path", path), zap.Error(err))
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
o := fs.s.Create(path)
|
||||
o.Path = path
|
||||
o.Mode = types.ModeRead
|
||||
o.SetContentLength(0)
|
||||
o.SetLastModified(time.Now())
|
||||
|
||||
ino = newInode(parent, o)
|
||||
err = fs.SetInode(ino)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fh, err = fs.CreateFileHandle(ino)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (fs *FS) Delete(parent uint64, name string) (err error) {
|
||||
ino, err := fs.GetEntry(parent, name)
|
||||
if err != nil {
|
||||
|
@ -95,6 +132,26 @@ func (fs *FS) DeleteDir(path string) (err error) {
|
|||
panic("implement me")
|
||||
}
|
||||
|
||||
func (fs *FS) CreateFileHandle(ino *Inode) (fh *FileHandle, err error) {
|
||||
fh = &FileHandle{
|
||||
ID: NextHandle(),
|
||||
ino: ino,
|
||||
fs: fs,
|
||||
meta: fs.meta,
|
||||
}
|
||||
fs.fhm.Set(fh.ID, fh)
|
||||
return fh, nil
|
||||
}
|
||||
|
||||
func (fs *FS) GetFileHandle(fhid uint64) (fh *FileHandle, err error) {
|
||||
return fs.fhm.Get(fhid), nil
|
||||
}
|
||||
|
||||
func (fs *FS) DeleteFileHandle(fhid uint64) (err error) {
|
||||
fs.fhm.Delete(fhid)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fs *FS) CreateDirHandle(ino *Inode) (dh *DirHandle, err error) {
|
||||
it, err := fs.s.List(ino.Path, pairs.WithListMode(types.ListModeDir))
|
||||
if err != nil {
|
||||
|
|
11
vfs/inode.go
11
vfs/inode.go
|
@ -1,10 +1,12 @@
|
|||
package vfs
|
||||
|
||||
import (
|
||||
"github.com/beyondstorage/go-storage/v4/types"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/beyondstorage/go-storage/v4/types"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/tinylib/msgp
|
||||
|
@ -27,6 +29,13 @@ func (ino *Inode) IsDir() bool {
|
|||
return ino.Mode&uint32(os.ModeDir) != 0
|
||||
}
|
||||
|
||||
func (ino *Inode) GetEntryPath(name string) string {
|
||||
if ino.Path == "" {
|
||||
return name
|
||||
}
|
||||
return fmt.Sprintf("%s/%s", ino.Path, name)
|
||||
}
|
||||
|
||||
func newInode(parent uint64, o *types.Object) *Inode {
|
||||
ino := &Inode{
|
||||
ID: NextInodeID(),
|
||||
|
|
Loading…
Reference in New Issue