Skip to content

Commit

Permalink
Merge pull request #1715 from ipfs/mfs-redo
Browse files Browse the repository at this point in the history
mfs redo
  • Loading branch information
jbenet committed Sep 23, 2015
2 parents 47d6836 + 748103b commit 2a2b237
Show file tree
Hide file tree
Showing 14 changed files with 1,057 additions and 557 deletions.
9 changes: 0 additions & 9 deletions core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ import (
rp "github.com/ipfs/go-ipfs/exchange/reprovide"

mount "github.com/ipfs/go-ipfs/fuse/mount"
ipnsfs "github.com/ipfs/go-ipfs/ipnsfs"
merkledag "github.com/ipfs/go-ipfs/merkledag"
namesys "github.com/ipfs/go-ipfs/namesys"
path "github.com/ipfs/go-ipfs/path"
Expand Down Expand Up @@ -104,8 +103,6 @@ type IpfsNode struct {
Ping *ping.PingService
Reprovider *rp.Reprovider // the value reprovider system

IpnsFs *ipnsfs.Filesystem

proc goprocess.Process
ctx context.Context

Expand Down Expand Up @@ -267,12 +264,6 @@ func (n *IpfsNode) teardown() error {
closers = append(closers, mount.Closer(n.Mounts.Ipns))
}

// Filesystem needs to be closed before network, dht, and blockservice
// so it can use them as its shutting down
if n.IpnsFs != nil {
closers = append(closers, n.IpnsFs)
}

if n.Blocks != nil {
closers = append(closers, n.Blocks)
}
Expand Down
9 changes: 0 additions & 9 deletions fuse/ipns/ipns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@ import (
fstest "github.com/ipfs/go-ipfs/Godeps/_workspace/src/bazil.org/fuse/fs/fstestutil"
racedet "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-detect-race"

context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
core "github.com/ipfs/go-ipfs/core"
coremock "github.com/ipfs/go-ipfs/core/mock"
nsfs "github.com/ipfs/go-ipfs/ipnsfs"
u "github.com/ipfs/go-ipfs/util"
ci "github.com/ipfs/go-ipfs/util/testutil/ci"
)
Expand Down Expand Up @@ -105,13 +103,6 @@ func setupIpnsTest(t *testing.T, node *core.IpfsNode) (*core.IpfsNode, *fstest.M
if err != nil {
t.Fatal(err)
}

ipnsfs, err := nsfs.NewFilesystem(context.Background(), node.DAG, node.Namesys, node.Pinning, node.PrivateKey)
if err != nil {
t.Fatal(err)
}

node.IpnsFs = ipnsfs
}

fs, err := NewFileSystem(node, node.PrivateKey, "", "")
Expand Down
168 changes: 105 additions & 63 deletions fuse/ipns/ipns_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ import (

key "github.com/ipfs/go-ipfs/blocks/key"
core "github.com/ipfs/go-ipfs/core"
nsfs "github.com/ipfs/go-ipfs/ipnsfs"
dag "github.com/ipfs/go-ipfs/merkledag"
mfs "github.com/ipfs/go-ipfs/mfs"
ci "github.com/ipfs/go-ipfs/p2p/crypto"
path "github.com/ipfs/go-ipfs/path"
ft "github.com/ipfs/go-ipfs/unixfs"
)

Expand All @@ -33,10 +34,15 @@ type FileSystem struct {

// NewFileSystem constructs new fs using given core.IpfsNode instance.
func NewFileSystem(ipfs *core.IpfsNode, sk ci.PrivKey, ipfspath, ipnspath string) (*FileSystem, error) {
root, err := CreateRoot(ipfs, []ci.PrivKey{sk}, ipfspath, ipnspath)

kmap := map[string]ci.PrivKey{
"local": sk,
}
root, err := CreateRoot(ipfs, kmap, ipfspath, ipnspath)
if err != nil {
return nil, err
}

return &FileSystem{Ipfs: ipfs, RootNode: root}, nil
}

Expand All @@ -56,53 +62,95 @@ func (f *FileSystem) Destroy() {
// Root is the root object of the filesystem tree.
type Root struct {
Ipfs *core.IpfsNode
Keys []ci.PrivKey
Keys map[string]ci.PrivKey

// Used for symlinking into ipfs
IpfsRoot string
IpnsRoot string
LocalDirs map[string]fs.Node
Roots map[string]*nsfs.KeyRoot
Roots map[string]*keyRoot

LocalLinks map[string]*Link
}

func ipnsPubFunc(ipfs *core.IpfsNode, k ci.PrivKey) mfs.PubFunc {
return func(ctx context.Context, key key.Key) error {
return ipfs.Namesys.Publish(ctx, k, path.FromKey(key))
}
}

func loadRoot(ctx context.Context, rt *keyRoot, ipfs *core.IpfsNode, name string) (fs.Node, error) {
p, err := path.ParsePath("/ipns/" + name)
if err != nil {
log.Errorf("mkpath %s: %s", name, err)
return nil, err
}

node, err := core.Resolve(ctx, ipfs, p)
if err != nil {
log.Errorf("looking up %s: %s", p, err)
return nil, err
}

root, err := mfs.NewRoot(ctx, ipfs.DAG, node, ipnsPubFunc(ipfs, rt.k))
if err != nil {
return nil, err
}

rt.root = root

fs *nsfs.Filesystem
LocalLink *Link
switch val := root.GetValue().(type) {
case *mfs.Directory:
return &Directory{dir: val}, nil
case *mfs.File:
return &File{fi: val}, nil
default:
return nil, errors.New("unrecognized type")
}

panic("not reached")
}

func CreateRoot(ipfs *core.IpfsNode, keys []ci.PrivKey, ipfspath, ipnspath string) (*Root, error) {
type keyRoot struct {
k ci.PrivKey
alias string
root *mfs.Root
}

func CreateRoot(ipfs *core.IpfsNode, keys map[string]ci.PrivKey, ipfspath, ipnspath string) (*Root, error) {
ldirs := make(map[string]fs.Node)
roots := make(map[string]*nsfs.KeyRoot)
for _, k := range keys {
roots := make(map[string]*keyRoot)
links := make(map[string]*Link)
for alias, k := range keys {
pkh, err := k.GetPublic().Hash()
if err != nil {
return nil, err
}
name := key.Key(pkh).B58String()
root, err := ipfs.IpnsFs.GetRoot(name)

kr := &keyRoot{k: k, alias: alias}
fsn, err := loadRoot(ipfs.Context(), kr, ipfs, name)
if err != nil {
return nil, err
}

roots[name] = root
roots[name] = kr
ldirs[name] = fsn

switch val := root.GetValue().(type) {
case *nsfs.Directory:
ldirs[name] = &Directory{dir: val}
case *nsfs.File:
ldirs[name] = &File{fi: val}
default:
return nil, errors.New("unrecognized type")
// set up alias symlink
links[alias] = &Link{
Target: name,
}
}

return &Root{
fs: ipfs.IpnsFs,
Ipfs: ipfs,
IpfsRoot: ipfspath,
IpnsRoot: ipnspath,
Keys: keys,
LocalDirs: ldirs,
LocalLink: &Link{ipfs.Identity.Pretty()},
Roots: roots,
Ipfs: ipfs,
IpfsRoot: ipfspath,
IpnsRoot: ipnspath,
Keys: keys,
LocalDirs: ldirs,
LocalLinks: links,
Roots: roots,
}, nil
}

Expand All @@ -121,12 +169,8 @@ func (s *Root) Lookup(ctx context.Context, name string) (fs.Node, error) {
return nil, fuse.ENOENT
}

// Local symlink to the node ID keyspace
if name == "local" {
if s.LocalLink == nil {
return nil, fuse.ENOENT
}
return s.LocalLink, nil
if lnk, ok := s.LocalLinks[name]; ok {
return lnk, nil
}

nd, ok := s.LocalDirs[name]
Expand All @@ -152,15 +196,15 @@ func (s *Root) Lookup(ctx context.Context, name string) (fs.Node, error) {
if segments[0] == "ipfs" {
p := strings.Join(resolved.Segments()[1:], "/")
return &Link{s.IpfsRoot + "/" + p}, nil
} else {
log.Error("Invalid path.Path: ", resolved)
return nil, errors.New("invalid path from ipns record")
}

log.Error("Invalid path.Path: ", resolved)
return nil, errors.New("invalid path from ipns record")
}

func (r *Root) Close() error {
for _, kr := range r.Roots {
err := kr.Publish(r.Ipfs.Context())
for _, mr := range r.Roots {
err := mr.root.Close()
if err != nil {
return err
}
Expand All @@ -181,13 +225,9 @@ func (r *Root) Forget() {
// as well as a symlink to the peerID key
func (r *Root) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
log.Debug("Root ReadDirAll")
listing := []fuse.Dirent{
{
Name: "local",
Type: fuse.DT_Link,
},
}
for _, k := range r.Keys {

var listing []fuse.Dirent
for alias, k := range r.Keys {
pub := k.GetPublic()
hash, err := pub.Hash()
if err != nil {
Expand All @@ -197,21 +237,25 @@ func (r *Root) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
Name: key.Key(hash).Pretty(),
Type: fuse.DT_Dir,
}
listing = append(listing, ent)
link := fuse.Dirent{
Name: alias,
Type: fuse.DT_Link,
}
listing = append(listing, ent, link)
}
return listing, nil
}

// Directory is wrapper over an ipnsfs directory to satisfy the fuse fs interface
// Directory is wrapper over an mfs directory to satisfy the fuse fs interface
type Directory struct {
dir *nsfs.Directory
dir *mfs.Directory

fs.NodeRef
}

// File is wrapper over an ipnsfs file to satisfy the fuse fs interface
// File is wrapper over an mfs file to satisfy the fuse fs interface
type File struct {
fi *nsfs.File
fi *mfs.File

fs.NodeRef
}
Expand Down Expand Up @@ -249,9 +293,9 @@ func (s *Directory) Lookup(ctx context.Context, name string) (fs.Node, error) {
}

switch child := child.(type) {
case *nsfs.Directory:
case *mfs.Directory:
return &Directory{dir: child}, nil
case *nsfs.File:
case *mfs.File:
return &File{fi: child}, nil
default:
// NB: if this happens, we do not want to continue, unpredictable behaviour
Expand All @@ -263,19 +307,17 @@ func (s *Directory) Lookup(ctx context.Context, name string) (fs.Node, error) {
// ReadDirAll reads the link structure as directory entries
func (dir *Directory) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
var entries []fuse.Dirent
for _, name := range dir.dir.List() {
dirent := fuse.Dirent{Name: name}

// TODO: make dir.dir.List() return dirinfos
child, err := dir.dir.Child(name)
if err != nil {
return nil, err
}
listing, err := dir.dir.List()
if err != nil {
return nil, err
}
for _, entry := range listing {
dirent := fuse.Dirent{Name: entry.Name}

switch child.Type() {
case nsfs.TDir:
switch mfs.NodeType(entry.Type) {
case mfs.TDir:
dirent.Type = fuse.DT_Dir
case nsfs.TFile:
case mfs.TFile:
dirent.Type = fuse.DT_File
}

Expand Down Expand Up @@ -419,7 +461,7 @@ func (dir *Directory) Create(ctx context.Context, req *fuse.CreateRequest, resp
return nil, nil, err
}

fi, ok := child.(*nsfs.File)
fi, ok := child.(*mfs.File)
if !ok {
return nil, nil, errors.New("child creation failed")
}
Expand Down
9 changes: 0 additions & 9 deletions fuse/ipns/mount_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package ipns
import (
core "github.com/ipfs/go-ipfs/core"
mount "github.com/ipfs/go-ipfs/fuse/mount"
ipnsfs "github.com/ipfs/go-ipfs/ipnsfs"
)

// Mount mounts ipns at a given location, and returns a mount.Mount instance.
Expand All @@ -18,14 +17,6 @@ func Mount(ipfs *core.IpfsNode, ipnsmp, ipfsmp string) (mount.Mount, error) {

allow_other := cfg.Mounts.FuseAllowOther

if ipfs.IpnsFs == nil {
fs, err := ipnsfs.NewFilesystem(ipfs.Context(), ipfs.DAG, ipfs.Namesys, ipfs.Pinning, ipfs.PrivateKey)
if err != nil {
return nil, err
}
ipfs.IpnsFs = fs
}

fsys, err := NewFileSystem(ipfs, ipfs.PrivateKey, ipfsmp, ipnsmp)
if err != nil {
return nil, err
Expand Down
Loading

0 comments on commit 2a2b237

Please sign in to comment.