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:
| M | jira/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