1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: Apache-2.0
13 type staleChecker struct {
18 func (sc *staleChecker) DoIfStale(fn func(), staleFunc func(time.Time) bool) {
21 if !staleFunc(sc.last) {
28 // projectnode exposes an Arvados project as a filesystem directory.
29 type projectnode struct {
36 func (pn *projectnode) load() {
37 fs := pn.FS().(*customFileSystem)
41 pn.err = fs.RequestAndDecode(&resp, "GET", "arvados/v1/users/current", nil, nil)
47 // Note: the "filters" slice's backing array might be reused
48 // by append(filters,...) below. This isn't goroutine safe,
49 // but all accesses are in the same goroutine, so it's OK.
50 filters := []Filter{{"owner_uuid", "=", pn.uuid}}
51 params := ResourceListParams{
56 var resp CollectionList
57 pn.err = fs.RequestAndDecode(&resp, "GET", "arvados/v1/collections", nil, params)
61 if len(resp.Items) == 0 {
64 for _, i := range resp.Items {
66 if !permittedName(coll.Name) {
69 pn.inode.Child(coll.Name, func(inode) (inode, error) {
70 return deferredCollectionFS(fs, pn, coll), nil
73 params.Filters = append(filters, Filter{"uuid", ">", resp.Items[len(resp.Items)-1].UUID})
76 filters = append(filters, Filter{"group_class", "=", "project"})
77 params.Filters = filters
80 pn.err = fs.RequestAndDecode(&resp, "GET", "arvados/v1/groups", nil, params)
84 if len(resp.Items) == 0 {
87 for _, group := range resp.Items {
88 if !permittedName(group.Name) {
91 pn.inode.Child(group.Name, func(inode) (inode, error) {
92 return fs.newProjectNode(pn, group.Name, group.UUID), nil
95 params.Filters = append(filters, Filter{"uuid", ">", resp.Items[len(resp.Items)-1].UUID})
100 func (pn *projectnode) Readdir() ([]os.FileInfo, error) {
101 pn.staleChecker.DoIfStale(pn.load, pn.FS().(*customFileSystem).Stale)
105 return pn.inode.Readdir()
108 func (pn *projectnode) Child(name string, replace func(inode) (inode, error)) (inode, error) {
109 pn.staleChecker.DoIfStale(pn.load, pn.FS().(*customFileSystem).Stale)
115 return pn.inode.Child(name, nil)
117 return pn.inode.Child(name, func(existing inode) (inode, error) {
118 if repl, err := replace(existing); err != nil {
120 } else if repl == nil {
126 return existing, ErrInvalidArgument
127 } else if existing != nil {
129 return existing, ErrInvalidArgument
130 } else if repl.FileInfo().IsDir() {
132 // TODO: repl.SetParent(pn, name), etc.
133 return existing, ErrInvalidArgument
136 return existing, ErrInvalidArgument