mfs: make `Root` value a `Directory`
Make `Root` value explicitly a `Directory` structure instead of the `FSNode` interface (which also allowed the `File` type). This helps to make the code easier to reason about: the root of an MFS layout is always a directory, not a (single) file. Rename `GetValue()` to `GetDirectory()` to also make it more explicit, the renamed function now returns a `Directory` so there is no need for type assertions that were previously done on the `FSNode` interface to check that it was actually a `Directory`. `NewRoot()` now doesn't allow to create `Root` structures from DAG nodes that contain UnixFS files. License: MIT Signed-off-by: Lucas Molas <schomatis@gmail.com>
Lucas Molas committed
Jun 29, 2018 at 10:57 UTC
08922d239d3c866ea886d5e6ebec8cb4f9ba94a4
6 files changed
+33
-51
core/corerepo/gc.go
+1
-1
@@ -71,7 +71,7 @@ func NewGC(n *core.IpfsNode) (*GC, error) {
71
}
72
73
func BestEffortRoots(filesRoot *mfs.Root) ([]*cid.Cid, error) {
74
- rootDag, err := filesRoot.GetValue().GetNode()
74
+ rootDag, err := filesRoot.GetDirectory().GetNode()
75
if err != nil {
76
return nil, err
77
}
core/coreunix/add.go
+4
-6
@@ -144,7 +144,7 @@ func (adder *Adder) RootNode() (ipld.Node, error) {
144
if err != nil {
145
return nil, err
146
}
147
- root, err := mr.GetValue().GetNode()
147
+ root, err := mr.GetDirectory().GetNode()
148
if err != nil {
149
return nil, err
150
}
@@ -199,7 +199,8 @@ func (adder *Adder) Finalize() (ipld.Node, error) {
199
if err != nil {
200
return nil, err
201
}
202
- root := mr.GetValue()
202
+ var root mfs.FSNode
203
+ root = mr.GetDirectory()
204
205
err = root.Flush()
206
if err != nil {
@@ -224,10 +225,7 @@ func (adder *Adder) Finalize() (ipld.Node, error) {
225
return nil, err
226
}
227
227
- dir, ok := mr.GetValue().(*mfs.Directory)
228
- if !ok {
229
- return nil, fmt.Errorf("root is not a directory")
230
- }
228
+ dir := mr.GetDirectory()
229
230
root, err = dir.Child(name)
231
if err != nil {
fuse/ipns/ipns_unix.go
+1
-8
@@ -118,14 +118,7 @@ func loadRoot(ctx context.Context, rt *keyRoot, ipfs *core.IpfsNode, name string
118
119
rt.root = root
120
121
- switch val := root.GetValue().(type) {
122
- case *mfs.Directory:
123
- return &Directory{dir: val}, nil
124
- case *mfs.File:
125
- return &FileNode{fi: val}, nil
126
- default:
127
- return nil, errors.New("unrecognized type")
128
- }
121
+ return &Directory{dir: root.GetDirectory()}, nil
122
}
123
124
type keyRoot struct {
mfs/mfs_test.go
+11
-11
@@ -213,7 +213,7 @@ func TestBasic(t *testing.T) {
213
defer cancel()
214
ds, rt := setupRoot(ctx, t)
215
216
- rootdir := rt.GetValue().(*Directory)
216
+ rootdir := rt.GetDirectory()
217
218
// test making a basic dir
219
_, err := rootdir.Mkdir("a")
@@ -243,7 +243,7 @@ func TestMkdir(t *testing.T) {
243
defer cancel()
244
_, rt := setupRoot(ctx, t)
245
246
- rootdir := rt.GetValue().(*Directory)
246
+ rootdir := rt.GetDirectory()
247
248
dirsToMake := []string{"a", "B", "foo", "bar", "cats", "fish"}
249
sort.Strings(dirsToMake) // sort for easy comparing later
@@ -281,7 +281,7 @@ func TestDirectoryLoadFromDag(t *testing.T) {
281
defer cancel()
282
ds, rt := setupRoot(ctx, t)
283
284
- rootdir := rt.GetValue().(*Directory)
284
+ rootdir := rt.GetDirectory()
285
286
nd := getRandFile(t, ds, 1000)
287
err := ds.Add(ctx, nd)
@@ -373,7 +373,7 @@ func TestMfsFile(t *testing.T) {
373
defer cancel()
374
ds, rt := setupRoot(ctx, t)
375
376
- rootdir := rt.GetValue().(*Directory)
376
+ rootdir := rt.GetDirectory()
377
378
fisize := 1000
379
nd := getRandFile(t, ds, 1000)
@@ -686,7 +686,7 @@ func actorReadFile(d *Directory) error {
686
}
687
688
func testActor(rt *Root, iterations int, errs chan error) {
689
- d := rt.GetValue().(*Directory)
689
+ d := rt.GetDirectory()
690
for i := 0; i < iterations; i++ {
691
switch rand.Intn(5) {
692
case 0:
@@ -763,7 +763,7 @@ func TestConcurrentWriteAndFlush(t *testing.T) {
763
defer cancel()
764
ds, rt := setupRoot(ctx, t)
765
766
- d := mkdirP(t, rt.GetValue().(*Directory), "foo/bar/baz")
766
+ d := mkdirP(t, rt.GetDirectory(), "foo/bar/baz")
767
fn := fileNodeFromReader(t, ds, bytes.NewBuffer(nil))
768
err := d.AddChild("file", fn)
769
if err != nil {
@@ -786,7 +786,7 @@ func TestConcurrentWriteAndFlush(t *testing.T) {
786
}()
787
788
for i := 0; i < nloops; i++ {
789
- _, err := rt.GetValue().GetNode()
789
+ _, err := rt.GetDirectory().GetNode()
790
if err != nil {
791
t.Fatal(err)
792
}
@@ -800,7 +800,7 @@ func TestFlushing(t *testing.T) {
800
defer cancel()
801
_, rt := setupRoot(ctx, t)
802
803
- dir := rt.GetValue().(*Directory)
803
+ dir := rt.GetDirectory()
804
c := mkdirP(t, dir, "a/b/c")
805
d := mkdirP(t, dir, "a/b/d")
806
e := mkdirP(t, dir, "a/b/e")
@@ -901,7 +901,7 @@ func TestConcurrentReads(t *testing.T) {
901
902
ds, rt := setupRoot(ctx, t)
903
904
- rootdir := rt.GetValue().(*Directory)
904
+ rootdir := rt.GetDirectory()
905
906
path := "a/b/c"
907
d := mkdirP(t, rootdir, path)
@@ -976,7 +976,7 @@ func TestConcurrentWrites(t *testing.T) {
976
977
ds, rt := setupRoot(ctx, t)
978
979
- rootdir := rt.GetValue().(*Directory)
979
+ rootdir := rt.GetDirectory()
980
981
path := "a/b/c"
982
d := mkdirP(t, rootdir, path)
@@ -1011,7 +1011,7 @@ func TestFileDescriptors(t *testing.T) {
1011
defer cancel()
1012
1013
ds, rt := setupRoot(ctx, t)
1014
- dir := rt.GetValue().(*Directory)
1014
+ dir := rt.GetDirectory()
1015
1016
nd := dag.NodeWithData(ft.FilePBData(nil, 0))
1017
fi, err := NewFile("test", nd, dir, ds)
mfs/ops.go
+5
-7
@@ -1,7 +1,6 @@
1
package mfs
2
3
import (
4
- "errors"
4
"fmt"
5
"os"
6
gopath "path"
@@ -129,7 +128,7 @@ func Mkdir(r *Root, pth string, opts MkdirOpts) error {
128
return fmt.Errorf("cannot create directory '/': Already exists")
129
}
130
132
- cur := r.GetValue().(*Directory)
131
+ cur := r.GetDirectory()
132
for i, d := range parts[:len(parts)-1] {
133
fsn, err := cur.Child(d)
134
if err == os.ErrNotExist && opts.Mkparents {
@@ -172,12 +171,11 @@ func Mkdir(r *Root, pth string, opts MkdirOpts) error {
171
return nil
172
}
173
174
+// Lookup extracts the root directory and performs a lookup under it.
175
+// TODO: Now that the root is always a directory, can this function
176
+// be collapsed with `DirLookup`? Or at least be made a method of `Root`?
177
func Lookup(r *Root, path string) (FSNode, error) {
176
- dir, ok := r.GetValue().(*Directory)
177
- if !ok {
178
- log.Errorf("root not a dir: %#v", r.GetValue())
179
- return nil, errors.New("root was not a directory")
180
- }
178
+ dir := r.GetDirectory()
179
180
return DirLookup(dir, path)
181
}
mfs/system.go
+11
-18
@@ -53,8 +53,8 @@ type Root struct {
53
// node is the merkledag root.
54
node *dag.ProtoNode
55
56
- // val represents the node. It can either be a File or a Directory.
57
- val FSNode
56
+ // Root directory of the MFS layout.
57
+ dir *Directory
58
59
repub *Republisher
60
@@ -90,33 +90,29 @@ func NewRoot(parent context.Context, ds ipld.DAGService, node *dag.ProtoNode, pf
90
91
switch pbn.GetType() {
92
case ft.TDirectory, ft.THAMTShard:
93
- rval, err := NewDirectory(parent, node.String(), node, root, ds)
93
+ newDir, err := NewDirectory(parent, node.String(), node, root, ds)
94
if err != nil {
95
return nil, err
96
}
97
98
- root.val = rval
98
+ root.dir = newDir
99
case ft.TFile, ft.TMetadata, ft.TRaw:
100
- fi, err := NewFile(node.String(), node, root, ds)
101
- if err != nil {
102
- return nil, err
103
- }
104
- root.val = fi
100
+ return nil, fmt.Errorf("root can't be a file (unixfs type: %s)", pbn.GetType())
101
default:
102
return nil, fmt.Errorf("unrecognized unixfs type: %s", pbn.GetType())
103
}
104
return root, nil
105
}
106
111
-// GetValue returns the value of Root.
112
-func (kr *Root) GetValue() FSNode {
113
- return kr.val
107
+// GetDirectory returns the root directory.
108
+func (kr *Root) GetDirectory() *Directory {
109
+ return kr.dir
110
}
111
112
// Flush signals that an update has occurred since the last publish,
113
// and updates the Root republisher.
114
func (kr *Root) Flush() error {
119
- nd, err := kr.GetValue().GetNode()
115
+ nd, err := kr.GetDirectory().GetNode()
116
if err != nil {
117
return err
118
}
@@ -136,10 +132,7 @@ func (kr *Root) Flush() error {
132
// A better implemented mfs system (one that does smarter internal caching and
133
// refcounting) shouldnt need this method.
134
func (kr *Root) FlushMemFree(ctx context.Context) error {
139
- dir, ok := kr.GetValue().(*Directory)
140
- if !ok {
141
- return fmt.Errorf("invalid mfs structure, root should be a directory")
142
- }
135
+ dir := kr.GetDirectory()
136
137
if err := dir.Flush(); err != nil {
138
return err
@@ -172,7 +165,7 @@ func (kr *Root) closeChild(name string, nd ipld.Node, sync bool) error {
165
}
166
167
func (kr *Root) Close() error {
175
- nd, err := kr.GetValue().GetNode()
168
+ nd, err := kr.GetDirectory().GetNode()
169
if err != nil {
170
return err
171
}