lib9p

Go 9P library.
Log | Files | Refs | LICENSE

commit d5ed46010c01c045ca6f35aba4b81ef019337e0a
parent 1d8bcf63fb2ef276c5dfeb7e911d997f4f2e02d2
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Mon, 22 Jan 2024 08:51:06 +0900

delete client fid and embed it to File

Diffstat:
Mclient/client.go | 10+++++-----
Mclient/client_test.go | 2+-
Mclient/fid.go | 58+++++++++++++++++++++++-----------------------------------
Mclient/file.go | 36+++++++++++++++++++-----------------
Mclient/fs.go | 38+++++++++++++++++++-------------------
5 files changed, 67 insertions(+), 77 deletions(-)

diff --git a/client/client.go b/client/client.go @@ -21,8 +21,8 @@ type Client struct { // Uname is used to communicate with a server. uname string - // FPool is the fidPool which hold the list of open fids. - fPool *fidPool + // FPool is the filePool which hold the list of outstanding files. + fPool *filePool // RPool is the set of all outstanding requests. rPool *reqPool @@ -30,8 +30,8 @@ type Client struct { // Txc is used to send a reqest to the multiplexer goroutine txc chan<- *req - // RootFid is the fid of the root of the file system. - rootFid *fid + // Root is the root file of the file system. + root *File // Wg is the WaitGroup of all goroutines evoked by this client and its // descendants. @@ -52,7 +52,7 @@ func NewClient(ctx context.Context, mSize uint32, uname string, r io.Reader, w i msize: mSize, mSizeLock: new(sync.Mutex), uname: uname, - fPool: allocClientFidPool(), + fPool: newFilePool(), rPool: newReqPool(), wg: new(sync.WaitGroup), done: ctx.Done(), diff --git a/client/client_test.go b/client/client_test.go @@ -59,7 +59,7 @@ func newClientForTest(ctx context.Context, msize uint32, uname string) (*Client, msize: msize, mSizeLock: new(sync.Mutex), uname: uname, - fPool: allocClientFidPool(), + fPool: newFilePool(), rPool: newReqPool(), wg: new(sync.WaitGroup), } diff --git a/client/fid.go b/client/fid.go @@ -7,35 +7,22 @@ import ( "git.mtkn.jp/lib9p" ) -// fid represents the Fid in the client side. -type fid struct { - fid uint32 - omode lib9p.OpenMode // -1 for not open - offset uint64 - file *File -} - -func newClientFid(id uint32) *fid { - return &fid{ - fid: id, - omode: -1, - offset: 0, - } -} - -type fidPool struct { - m map[uint32]*fid +type filePool struct { + m map[uint32]*File *sync.Mutex } -func allocClientFidPool() *fidPool { - return &fidPool{ - make(map[uint32]*fid), +func newFilePool() *filePool { + return &filePool{ + make(map[uint32]*File), new(sync.Mutex), } } -func (pool *fidPool) lookup(fid uint32) (*fid, bool) { +func (pool *filePool) lookup(fid uint32) (*File, bool) { + if fid == lib9p.NOFID { + return nil, false + } pool.Lock() defer pool.Unlock() f, ok := pool.m[fid] @@ -43,8 +30,8 @@ func (pool *fidPool) lookup(fid uint32) (*fid, bool) { } // NextFid does not lock pool. Lock it before calling this function. -func (pool *fidPool) nextFid() (uint32, error) { - for i := uint32(0); i < i+1; i++ { +func (pool *filePool) nextFid() (uint32, error) { + for i := uint32(0); i < lib9p.NOFID; i++ { if _, ok := pool.m[i]; !ok { return i, nil } @@ -52,41 +39,42 @@ func (pool *fidPool) nextFid() (uint32, error) { return 0, fmt.Errorf("run out of fid") } -func (pool *fidPool) add() (*fid, error) { +func (pool *filePool) add() (*File, error) { pool.Lock() defer pool.Unlock() fid, err := pool.nextFid() if err != nil { return nil, err } - if _, ok := pool.m[fid]; ok { - return nil, fmt.Errorf("fid already in use.") + f := &File{ + fid: fid, + omode: -1, + offset: 0, } - f := newClientFid(fid) pool.m[fid] = f return f, nil } -func (pool *fidPool) delete(fid uint32) { +func (pool *filePool) delete(fid uint32) { pool.Lock() defer pool.Unlock() delete(pool.m, fid) } -func (pool *fidPool) String() string { +func (pool *filePool) String() string { pool.Lock() // TODO: need? defer pool.Unlock() s := "{" - for fnum, fstruct := range pool.m { - if fstruct.file == nil { - s += fmt.Sprintf(" [%d]<nil>", fnum) + for fid, file := range pool.m { + if file == nil { // TODO: need? + s += fmt.Sprintf(" [%d]<nil>", fid) continue } - st, err := fstruct.file.Stat() + st, err := file.Stat() if err != nil { panic(err) } - s += fmt.Sprintf(" [%d]%v", fnum, st.Name()) + s += fmt.Sprintf(" [%d]%v", fid, st.Name()) } s += "}" return s diff --git a/client/file.go b/client/file.go @@ -12,7 +12,9 @@ import ( type File struct { name string path string // must not contain trailing slash. - fid *fid + fid uint32 + omode lib9p.OpenMode + offset uint64 qid lib9p.Qid iounit uint32 fs *FS @@ -24,7 +26,7 @@ func (cf *File) Stat() (*lib9p.FileInfo, error) { if err != nil { return nil, err } - st, err := cf.fs.c.Stat(tag, cf.fid.fid) + st, err := cf.fs.c.Stat(tag, cf.fid) cf.fs.tPool.delete(tag) if err != nil { return nil, err @@ -38,7 +40,7 @@ func (cf *File) WStat(stat *lib9p.Stat) error { if err != nil { return err } - err = cf.fs.c.Wstat(tag, cf.fid.fid, stat) + err = cf.fs.c.Wstat(tag, cf.fid, stat) cf.fs.tPool.delete(tag) return err } @@ -49,21 +51,21 @@ func (cf *File) Close() error { if err != nil { return err } - err = cf.fs.c.Clunk(tag, cf.fid.fid) + err = cf.fs.c.Clunk(tag, cf.fid) cf.fs.tPool.delete(tag) - cf.fs.c.fPool.delete(cf.fid.fid) - cf.fid = nil + cf.fs.c.fPool.delete(cf.fid) + cf.fid = lib9p.NOFID return err } func (cf *File) Read(b []byte) (int, error) { - if cf.fid.omode == -1 { + if cf.omode == -1 { return 0, errors.New("not open") } if len(b) == 0 { return 0, nil } - if cf.fid.omode&3 != lib9p.OREAD && cf.fid.omode&3 != lib9p.ORDWR { + if cf.omode&3 != lib9p.OREAD && cf.omode&3 != lib9p.ORDWR { return 0, lib9p.ErrPerm } count := len(b) @@ -79,13 +81,13 @@ func (cf *File) Read(b []byte) (int, error) { if err != nil { return 0, err } - buf, err := cf.fs.c.Read(tag, cf.fid.fid, cf.fid.offset, c) + buf, err := cf.fs.c.Read(tag, cf.fid, cf.offset, c) cf.fs.tPool.delete(tag) var i int for i = 0; i < len(buf); i++ { b[cur+i] = buf[i] } - cf.fid.offset += uint64(i) + cf.offset += uint64(i) cur += i if err != nil { return cur, err @@ -100,13 +102,13 @@ func (cf *File) Read(b []byte) (int, error) { } func (cf *File) Write(b []byte) (int, error) { - if cf.fid.omode == -1 { + if cf.omode == -1 { return 0, errors.New("not open") } if len(b) == 0 { return 0, nil } - if cf.fid.omode&3 != lib9p.OWRITE && cf.fid.omode&3 != lib9p.ORDWR { + if cf.omode&3 != lib9p.OWRITE && cf.omode&3 != lib9p.ORDWR { return 0, lib9p.ErrPerm } count := len(b) @@ -122,9 +124,9 @@ func (cf *File) Write(b []byte) (int, error) { if err != nil { return 0, err } - n, err := cf.fs.c.Write(tag, cf.fid.fid, cf.fid.offset, c, b[cur:cur+int(c)]) + n, err := cf.fs.c.Write(tag, cf.fid, cf.offset, c, b[cur:cur+int(c)]) cf.fs.tPool.delete(tag) - cf.fid.offset += uint64(n) + cf.offset += uint64(n) cur += int(n) if err != nil { return cur, err @@ -138,7 +140,7 @@ func (cf *File) ReadDir(n int) ([]fs.DirEntry, error) { if cf.qid.Type&lib9p.QTDIR == 0 { return nil, errors.New("not a directory") } - if cf.fid.omode == -1 { + if cf.omode == -1 { return nil, errors.New("not open") } var ( @@ -152,14 +154,14 @@ func (cf *File) ReadDir(n int) ([]fs.DirEntry, error) { if err != nil { break } - data, err = cf.fs.c.Read(tag, cf.fid.fid, cf.fid.offset, cf.iounit) + data, err = cf.fs.c.Read(tag, cf.fid, cf.offset, cf.iounit) cf.fs.tPool.delete(tag) if err != nil { break } else if len(data) == 0 { break } - cf.fid.offset += uint64(len(data)) + cf.offset += uint64(len(data)) for len(data) > 0 { st := lib9p.NewStat(data) data = data[2+st.Size():] diff --git a/client/fs.go b/client/fs.go @@ -33,14 +33,14 @@ func (fsys *FS) OpenFile(name string, flag int) (lib9p.File, error) { if err != nil { return nil, err } - qid, iounit, err = fsys.c.Open(tag, f.fid.fid, lib9p.FlagToMode(flag)) + qid, iounit, err = fsys.c.Open(tag, f.fid, lib9p.FlagToMode(flag)) fsys.tPool.delete(tag) if err != nil { f.Close() return nil, fmt.Errorf("open: %v", err) } } - f.fid.omode = lib9p.FlagToMode(flag) + f.omode = lib9p.FlagToMode(flag) f.qid = qid f.iounit = iounit return f, nil @@ -66,9 +66,9 @@ func CleanPath(name string) string { // returns the corresponding file. // returned file is not open. func (fsys *FS) walkFile(name string) (*File, error) { - fid, err := fsys.c.fPool.add() + f, err := fsys.c.fPool.add() if err != nil { - return nil, fmt.Errorf("add fid: %v", err) + return nil, fmt.Errorf("add file: %v", err) } var wname []string if name != "." { @@ -78,31 +78,27 @@ func (fsys *FS) walkFile(name string) (*File, error) { if err != nil { return nil, err } - wqid, err := fsys.c.Walk(tag, fsys.c.rootFid.fid, fid.fid, wname) + wqid, err := fsys.c.Walk(tag, fsys.c.root.fid, f.fid, wname) fsys.tPool.delete(tag) if err != nil { return nil, fmt.Errorf("walk: %v", err) } if len(wqid) < len(wname) { - fsys.c.fPool.delete(fid.fid) + fsys.c.fPool.delete(f.fid) return nil, fmt.Errorf("not found") } var qid lib9p.Qid if name == "." { - qid = lib9p.Qid{} + qid = lib9p.Qid{} // TODO: ?? why it is not fsys.c.root.qid? } else if len(wqid) > 0 { qid = wqid[len(wqid)-1] } else { return nil, fmt.Errorf("invalid wqid: %v", wqid) } - f := &File{ - name: path.Base(name), - path: name, - fid: fid, - qid: qid, - fs: fsys, - } - fid.file = f + f.name = path.Base(name) + f.path = name + f.qid = qid + f.fs = fsys return f, nil } @@ -138,19 +134,23 @@ func Mount(ctx context.Context, r io.Reader, w io.Writer, uname, aname string) ( cfs.c.setMSize(rmSize) } // TODO: auth - fid, err := cfs.c.fPool.add() + f, err := cfs.c.fPool.add() if err != nil { - return nil, fmt.Errorf("add fid: %v", err) + return nil, fmt.Errorf("add file: %v", err) } tag, err := cfs.tPool.add() if err != nil { return nil, err } - _, err = cfs.c.Attach(tag, fid.fid, lib9p.NOFID, uname, aname) + qid, err := cfs.c.Attach(tag, f.fid, lib9p.NOFID, uname, aname) cfs.tPool.delete(tag) if err != nil { return nil, fmt.Errorf("attach: %v", err) } - cfs.c.rootFid = fid + f.name = "." + f.path = "." + f.qid = qid + f.fs = cfs + cfs.c.root = f return cfs, nil }