From aad261f6bb852c4824bef740e27dd5e10957e031 Mon Sep 17 00:00:00 2001 From: Jeromy Date: Sat, 9 Jan 2016 09:17:29 -0800 Subject: [PATCH] WIP License: MIT Signed-off-by: Jeromy --- core/commands/files/files.go | 9 +++++- mfs/dir.go | 12 ++----- mfs/mfs_test.go | 50 +++++++++++++++++++++++++++++ mfs/ops.go | 61 ++++++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 11 deletions(-) diff --git a/core/commands/files/files.go b/core/commands/files/files.go index 3c3da7623f7b..6a74205003ea 100644 --- a/core/commands/files/files.go +++ b/core/commands/files/files.go @@ -495,7 +495,14 @@ Warning: } if flush { - defer fi.Close() + defer func() { + fi.Close() + err := mfs.FlushPath(nd.FilesRoot, path) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + }() } else { defer fi.Sync() } diff --git a/mfs/dir.go b/mfs/dir.go index 2b95bce1820b..b1f4cb8ec878 100644 --- a/mfs/dir.go +++ b/mfs/dir.go @@ -376,22 +376,14 @@ func (d *Directory) Path() string { func (d *Directory) GetNode() (*dag.Node, error) { d.lock.Lock() + defer d.lock.Unlock() err := d.sync() - if err != nil { - d.lock.Unlock() - return nil, err - } - - ncp := d.node.Copy() - d.lock.Unlock() - - err = d.parent.closeChild(d.name, ncp) if err != nil { return nil, err } - return ncp, nil + return d.node.Copy(), nil } func (d *Directory) Lock() { diff --git a/mfs/mfs_test.go b/mfs/mfs_test.go index ff6c9d03c679..6fe61d612646 100644 --- a/mfs/mfs_test.go +++ b/mfs/mfs_test.go @@ -675,3 +675,53 @@ func TestMfsStress(t *testing.T) { } } } + +func TestFlushing(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + _, rt := setupRoot(ctx, t) + + dir := rt.GetValue().(*Directory) + c := mkdirP(t, dir, "a/b/c") + d := mkdirP(t, dir, "a/b/d") + e := mkdirP(t, dir, "a/b/e") + + data := []byte("this is a test\n") + nd1 := &dag.Node{Data: ft.FilePBData(data, uint64(len(data)))} + + if err := c.AddChild("TEST", nd1); err != nil { + t.Fatal(err) + } + if err := d.AddChild("TEST", nd1); err != nil { + t.Fatal(err) + } + if err := e.AddChild("TEST", nd1); err != nil { + t.Fatal(err) + } + + if err := FlushPath(rt, "/a/b/c/TEST"); err != nil { + t.Fatal(err) + } + + if err := FlushPath(rt, "/a/b/d/TEST"); err != nil { + t.Fatal(err) + } + + if err := FlushPath(rt, "/a/b/e/TEST"); err != nil { + t.Fatal(err) + } + + rnd, err := dir.GetNode() + if err != nil { + t.Fatal(err) + } + + rnk, err := rnd.Key() + if err != nil { + t.Fatal(err) + } + + if rnk.B58String() != "QmWcvrHUFk7LQRrA4WqKjqy7ZyRGFLVagtgNxbEodTEzQ4" { + t.Fatal("dag looks wrong") + } +} diff --git a/mfs/ops.go b/mfs/ops.go index 75c5d6a844b1..6edc9dd76a39 100644 --- a/mfs/ops.go +++ b/mfs/ops.go @@ -194,3 +194,64 @@ func DirLookup(d *Directory, pth string) (FSNode, error) { } return cur, nil } + +func FlushPath(r *Root, pth string) error { + parts := path.SplitList(strings.Trim(pth, "/")) + + d, ok := r.GetValue().(*Directory) + if !ok { + return errors.New("mfs root somehow didnt point to a directory") + } + + nd, err := flushPathRec(d, parts) + if err != nil { + return err + } + + k, err := nd.Key() + if err != nil { + return err + } + + r.repub.Update(k) + return nil +} + +func flushPathRec(d *Directory, parts []string) (*dag.Node, error) { + if len(parts) == 0 { + return d.GetNode() + } + + d.Lock() + defer d.Unlock() + + next, err := d.childUnsync(parts[0]) + if err != nil { + log.Errorf("childnode: %q %q", parts[0], err) + return nil, err + } + + switch next := next.(type) { + case *Directory: + nd, err := flushPathRec(next, parts[1:]) + if err != nil { + return nil, err + } + + newnode, err := d.node.UpdateNodeLink(parts[0], nd) + if err != nil { + return nil, err + } + + d.node = newnode + return newnode, nil + case *File: + if len(parts) > 1 { + return nil, fmt.Errorf("%s is a file, not a directory", parts[0]) + } + + return next.GetNode() + default: + return nil, fmt.Errorf("unrecognized FSNode type: %#v", next) + } +}