commit - e5a62a4140f5672204ab4c7774683b13c6b61b3c
commit + 945b3fc34aaeca2019e8045bb23d2c1c5fe62539
blob - 3a531ebc795d1e6953d190f8568f80d575231fb7
blob + ea3453f98d1c04f44361e39ac177fbc6f0036798
--- jira/fs.go
+++ jira/fs.go
"os"
"path"
"strings"
+ "sync"
"time"
)
type FS struct {
Client *Client
root *fid
+ cache *dirCache
}
const (
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)
}
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
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