issues

Github, Jira, Gitlab issues from Plan 9's acme
Log | Files | Refs | README | LICENSE

commit 945b3fc34aaeca2019e8045bb23d2c1c5fe62539
parent e5a62a4140f5672204ab4c7774683b13c6b61b3c
Author: Oliver Lowe <o@olowe.co>
Date:   Wed, 11 Jun 2025 13:52:42 +1000

jira: cache dir entries

The cache assumes files will never be removed which is incorrect.
But clients - the Jira program - can just restart to clear the cache

Diffstat:
Mjira/fs.go | 67++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 66 insertions(+), 1 deletion(-)

diff --git a/jira/fs.go b/jira/fs.go @@ -7,12 +7,14 @@ import ( "os" "path" "strings" + "sync" "time" ) type FS struct { Client *Client root *fid + cache *dirCache } const ( @@ -250,6 +252,15 @@ func (fsys *FS) Open(name string) (fs.File, error) { return nil, fmt.Errorf("make root file: %w", err) } } + if fsys.cache == nil { + var err error + fsys.cache = &dirCache{} + fsys.cache.root, err = makeRoot(fsys.Client) + if err != nil { + return nil, fmt.Errorf("make cache root file: %w", err) + } + } + if fsys.Client.Debug { fmt.Fprintln(os.Stderr, "open", name) } @@ -264,13 +275,23 @@ func (fsys *FS) Open(name string) (fs.File, error) { elems = elems[1:] } + if f := fsys.cache.lookup(elems); f != nil { + if fsys.Client.Debug { + fmt.Fprintln(os.Stderr, "cachehit", name) + } + g := *f + g.children = nil + return &g, nil + } + f := fsys.root - for _, elem := range elems { + for i, elem := range elems { dir, err := find(f, elem) if err != nil { return nil, &fs.PathError{"open", name, err} } f = dir + fsys.cache.put(elems[:i], *dir) } g := *f return &g, nil @@ -297,6 +318,50 @@ func makeRoot(client *Client) (*fid, error) { return root, nil } +type dirCache struct { + mu sync.Mutex + root *fid +} + +func (cache *dirCache) lookup(wnames []string) *fid { + cache.mu.Lock() + defer cache.mu.Unlock() + + next := cache.root + for _, name := range wnames { + match := qfind(next, name) + if match == nil { + return nil + } + next = match + } + return next +} + +func (cache *dirCache) put(wnames []string, f fid) (ok bool) { + parent := cache.lookup(wnames) + if parent == nil { + return false + } + + cache.mu.Lock() + defer cache.mu.Unlock() + parent.children = append(parent.children, &f) + return true +} + +func qfind(dir *fid, name string) *fid { + if !dir.IsDir() { + return nil + } + for _, d := range dir.children { + if d.Name() == name { + return d.(*fid) + } + } + return nil +} + func find(dir *fid, name string) (*fid, error) { if !dir.IsDir() { return nil, fs.ErrNotExist