13111: Clear up some type assertions.
[arvados.git] / sdk / go / arvados / fs_site.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: Apache-2.0
4
5 package arvados
6
7 import (
8         "os"
9         "time"
10 )
11
12 type siteFileSystem struct {
13         fileSystem
14 }
15
16 // SiteFileSystem returns a FileSystem that maps collections and other
17 // Arvados objects onto a filesystem layout.
18 //
19 // This is experimental: the filesystem layout is not stable, and
20 // there are significant known bugs and shortcomings. For example,
21 // writes are not persisted until Sync() is called.
22 func (c *Client) SiteFileSystem(kc keepClient) FileSystem {
23         fs := &siteFileSystem{
24                 fileSystem: fileSystem{
25                         fsBackend: keepBackend{apiClient: c, keepClient: kc},
26                 },
27         }
28         root := &treenode{
29                 fs: fs,
30                 fileinfo: fileinfo{
31                         name:    "/",
32                         mode:    os.ModeDir | 0755,
33                         modTime: time.Now(),
34                 },
35                 inodes: make(map[string]inode),
36         }
37         root.parent = root
38         root.Child("by_id", func(inode) inode {
39                 var vn inode
40                 vn = &vdirnode{
41                         inode: &treenode{
42                                 fs:     fs,
43                                 parent: root,
44                                 inodes: make(map[string]inode),
45                                 fileinfo: fileinfo{
46                                         name:    "by_id",
47                                         modTime: time.Now(),
48                                         mode:    0755 | os.ModeDir,
49                                 },
50                         },
51                         create: fs.mountCollection,
52                 }
53                 return vn
54         })
55         fs.root = root
56         return fs
57 }
58
59 func (fs *siteFileSystem) newDirnode(parent inode, name string, perm os.FileMode, modTime time.Time) (node inode, err error) {
60         return nil, ErrInvalidOperation
61 }
62
63 func (fs *siteFileSystem) newFilenode(parent inode, name string, perm os.FileMode, modTime time.Time) (node inode, err error) {
64         return nil, ErrInvalidOperation
65 }
66
67 func (fs *siteFileSystem) mountCollection(parent inode, id string) inode {
68         var coll Collection
69         err := fs.RequestAndDecode(&coll, "GET", "arvados/v1/collections/"+id, nil, nil)
70         if err != nil {
71                 return nil
72         }
73         cfs, err := coll.FileSystem(fs, fs)
74         if err != nil {
75                 return nil
76         }
77         root := cfs.rootnode()
78         root.SetParent(parent)
79         root.(*dirnode).fileinfo.name = id
80         return root
81 }
82
83 // vdirnode wraps an inode by ignoring any requests to add/replace
84 // children, and calling a create() func when a non-existing child is
85 // looked up.
86 //
87 // create() can return either a new node, which will be added to the
88 // treenode, or nil for ENOENT.
89 type vdirnode struct {
90         inode
91         create func(parent inode, name string) inode
92 }
93
94 func (vn *vdirnode) Child(name string, _ func(inode) inode) inode {
95         return vn.inode.Child(name, func(existing inode) inode {
96                 if existing != nil {
97                         return existing
98                 } else {
99                         n := vn.create(vn, name)
100                         if n != nil {
101                                 n.SetParent(vn)
102                         }
103                         return n
104                 }
105         })
106 }