Skip to content

Commit

Permalink
refactorings
Browse files Browse the repository at this point in the history
Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
  • Loading branch information
butonic committed Sep 10, 2020
1 parent f9ec24a commit 3db04b9
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 201 deletions.
36 changes: 3 additions & 33 deletions pkg/storage/fs/ocis/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import (
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/cs3org/reva/pkg/appctx"
"github.com/cs3org/reva/pkg/mime"
"github.com/google/uuid"
"github.com/pkg/errors"
"github.com/pkg/xattr"
)
Expand All @@ -46,32 +45,8 @@ type Node struct {
Exists bool
}

// CreateDir creates a new child directory node with a new id and the given name
// owner is optional
// TODO use in tree CreateDir
// TODO beware the below implementation allows creating two nodes with the same name
// TODO also create link to parent
func (n *Node) CreateDir(pw *Path, name string, owner *userpb.UserId) (c *Node, err error) {
c = &Node{
pw: pw,
ParentID: n.ID,
ID: uuid.New().String(),
Name: name,
}

// create a directory node
nodePath := filepath.Join(pw.Root, "nodes", c.ID)
if err = os.MkdirAll(nodePath, 0700); err != nil {
return nil, errors.Wrap(err, "ocisfs: error creating node child dir")
}

err = c.writeMetadata(nodePath, owner)

c.Exists = true
return
}

func (n *Node) writeMetadata(nodePath string, owner *userpb.UserId) (err error) {
func (n *Node) writeMetadata(owner *userpb.UserId) (err error) {
nodePath := filepath.Join(n.pw.Root, "nodes", n.ID)
if err = xattr.Set(nodePath, "user.ocis.parentid", []byte(n.ParentID)); err != nil {
return errors.Wrap(err, "ocisfs: could not set parentid attribute")
}
Expand Down Expand Up @@ -113,12 +88,7 @@ func ReadNode(ctx context.Context, pw *Path, id string) (n *Node, err error) {
}

var root *Node
if pw.EnableHome {
root, err = pw.HomeNode(ctx)
} else {
root, err = pw.RootNode(ctx)
}
if err != nil {
if root, err = pw.HomeOrRootNode(ctx); err != nil {
return
}
parentID := n.ParentID
Expand Down
62 changes: 12 additions & 50 deletions pkg/storage/fs/ocis/ocis.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"io"
"net/url"
"os"
"path"
"path/filepath"
"strings"

Expand Down Expand Up @@ -152,20 +151,14 @@ func (fs *ocisfs) CreateHome(ctx context.Context) (err error) {
if n, err = fs.pw.RootNode(ctx); err != nil {
return
}
u := user.ContextMustGetUser(ctx)
layout := templates.WithUser(u, fs.pw.UserLayout)

segments := strings.Split(layout, "/")
for i := range segments {
if n, err = n.Child(segments[i]); err != nil {
return
}
_, err = fs.pw.WalkPath(ctx, n, fs.pw.mustGetUserLayout(ctx), func(ctx context.Context, n *Node) error {
if !n.Exists {
if err = fs.tp.CreateDir(ctx, n); err != nil {
return
if err := fs.tp.CreateDir(ctx, n); err != nil {
return err
}
}
}
return nil
})
return
}

Expand Down Expand Up @@ -195,43 +188,11 @@ func (fs *ocisfs) CreateDir(ctx context.Context, fn string) (err error) {
return fs.tp.CreateDir(ctx, node)
}

// The share folder, aka "/Shares", is a virtual thing.
func (fs *ocisfs) isShareFolder(ctx context.Context, p string) bool {
// TODO what about a folder '/Sharesabc' ... would also match
return strings.HasPrefix(p, fs.pw.ShareFolder)
}

func (fs *ocisfs) isShareFolderRoot(ctx context.Context, p string) bool {
return path.Clean(p) == fs.pw.ShareFolder
}

func (fs *ocisfs) isShareFolderChild(ctx context.Context, p string) bool {
p = path.Clean(p)
vals := strings.Split(p, fs.pw.ShareFolder+"/")
return len(vals) > 1 && vals[1] != ""
}
func (fs *ocisfs) getInternalHome(ctx context.Context) (string, error) {
if !fs.pw.EnableHome {
return "", errtypes.NotSupported("ocisfs: get home not enabled")
}

u, ok := user.ContextGetUser(ctx)
if !ok {
return "", errtypes.InternalError("ocisfs: wrap: no user in ctx and home is enabled")
}

relativeHome := templates.WithUser(u, fs.pw.UserLayout)
return relativeHome, nil
}

// TODO there really is no difference between the /Shares folder and normal nodes
// we can store it is a node
// but when home is enabled the "/Shares" folder should not be listed ...
// so when listing home we need to check that flag and add the shared node

// /Shares/mounted1
// /Shares/mounted1/foo/bar
// references should go into a Shares folder
// CreateReference creates a reference as a node folder with the target stored in extended attributes
// There is no difference between the /Shares folder and normal nodes because the storage is not supposed to be accessible without the storage provider.
// In effect everything is a shadow namespace.
// To mimic the eos end owncloud driver we only allow references as children of the "/Shares" folder
// TODO when home support is enabled should the "/Shares" folder still be listed?
func (fs *ocisfs) CreateReference(ctx context.Context, p string, targetURI *url.URL) (err error) {

p = strings.Trim(p, "/")
Expand Down Expand Up @@ -260,6 +221,7 @@ func (fs *ocisfs) CreateReference(ctx context.Context, p string, targetURI *url.
}

if n.Exists {
// TODO append increasing number to mountpoint name
return errtypes.AlreadyExists(p)
}

Expand All @@ -269,7 +231,7 @@ func (fs *ocisfs) CreateReference(ctx context.Context, p string, targetURI *url.

internal := filepath.Join(fs.pw.Root, "nodes", n.ID)
if err = xattr.Set(internal, referenceAttr, []byte(targetURI.String())); err != nil {
return errors.Wrapf(err, "ocfs: error setting the target %s on the reference file %s", targetURI.String(), internal)
return errors.Wrapf(err, "ocisfs: error setting the target %s on the reference file %s", targetURI.String(), internal)
}
return nil
}
Expand Down
92 changes: 39 additions & 53 deletions pkg/storage/fs/ocis/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ package ocis
import (
"context"
"fmt"
"os"
"path/filepath"
"strings"

Expand All @@ -37,7 +36,7 @@ type Path struct {
// ocis fs works on top of a dir of uuid nodes
Root string `mapstructure:"root"`

// UserLayout describles the relative path from the storages root node to the users home node.
// UserLayout describes the relative path from the storage's root node to the users home node.
UserLayout string `mapstructure:"user_layout"`

// TODO NodeLayout option to save nodes as eg. nodes/1d/d8/1dd84abf-9466-4e14-bb86-02fc4ea3abcf
Expand Down Expand Up @@ -65,25 +64,16 @@ func (pw *Path) NodeFromResource(ctx context.Context, ref *provider.Reference) (
func (pw *Path) NodeFromPath(ctx context.Context, fn string) (node *Node, err error) {
log := appctx.GetLogger(ctx)
log.Debug().Interface("fn", fn).Msg("NodeFromPath()")
if pw.EnableHome {
node, err = pw.HomeNode(ctx)
} else {
node, err = pw.RootNode(ctx)
}
if err != nil {

if node, err = pw.HomeOrRootNode(ctx); err != nil {
return
}

if fn != "/" {
// walk the path
segments := strings.Split(strings.TrimLeft(fn, "/"), "/")
for i := range segments {
if node, err = node.Child(segments[i]); err != nil {
log.Error().Err(err).Interface("node", node).Str("segment", segments[i]).Msg("NodeFromPath()")
break
}
log.Debug().Interface("node", node).Str("segment", segments[i]).Msg("NodeFromPath()")
}
node, err = pw.WalkPath(ctx, node, fn, func(ctx context.Context, n *Node) error {
log.Debug().Interface("node", node).Msg("NodeFromPath() walk")
return nil
})
}

return
Expand All @@ -100,12 +90,7 @@ func (pw *Path) NodeFromID(ctx context.Context, id *provider.ResourceId) (n *Nod
// Path returns the path for node
func (pw *Path) Path(ctx context.Context, n *Node) (p string, err error) {
var root *Node
if pw.EnableHome {
root, err = pw.HomeNode(ctx)
} else {
root, err = pw.RootNode(ctx)
}
if err != nil {
if root, err = pw.HomeOrRootNode(ctx); err != nil {
return
}
for n.ID != root.ID {
Expand All @@ -122,30 +107,7 @@ func (pw *Path) Path(ctx context.Context, n *Node) (p string, err error) {
return
}

// readRootLink reads the symbolic link and extracts the node id
func (pw *Path) readRootLink(root string) (node *Node, err error) {
// A root symlink looks like `../nodes/76455834-769e-412a-8a01-68f265365b79`
link, err := os.Readlink(root)
if os.IsNotExist(err) {
err = errtypes.NotFound(root)
return
}

// extract the nodeID
if strings.HasPrefix(link, "../nodes/") {
node = &Node{
pw: pw,
ID: filepath.Base(link),
ParentID: "root",
Exists: true,
}
} else {
err = fmt.Errorf("ocisfs: expected '../nodes/ prefix, got' %+v", link)
}
return
}

// RootNode returns the root node of a tree
// RootNode returns the root node of the storage
func (pw *Path) RootNode(ctx context.Context) (node *Node, err error) {
return &Node{
pw: pw,
Expand All @@ -165,14 +127,38 @@ func (pw *Path) HomeNode(ctx context.Context) (node *Node, err error) {
if node, err = pw.RootNode(ctx); err != nil {
return
}
u := user.ContextMustGetUser(ctx)
layout := templates.WithUser(u, pw.UserLayout)
node, err = pw.WalkPath(ctx, node, pw.mustGetUserLayout(ctx), nil)
return
}

segments := strings.Split(layout, "/")
// WalkPath calls n.Child(segment) on every path segment in p starting at the node r
// If a function f is given it will be executed for every segment node, but not the root node r
func (pw *Path) WalkPath(ctx context.Context, r *Node, p string, f func(ctx context.Context, n *Node) error) (*Node, error) {
segments := strings.Split(strings.Trim(p, "/"), "/")
var err error
for i := range segments {
if node, err = node.Child(segments[i]); err != nil {
return
if r, err = r.Child(segments[i]); err != nil {
return r, err
}
if f != nil {
if err = f(ctx, r); err != nil {
return r, err
}
}
}
return
return r, nil
}

// HomeOrRootNode returns the users home node when home support is enabled.
// it returns the storages root node otherwise
func (pw *Path) HomeOrRootNode(ctx context.Context) (node *Node, err error) {
if pw.EnableHome {
return pw.HomeNode(ctx)
}
return pw.RootNode(ctx)
}

func (pw *Path) mustGetUserLayout(ctx context.Context) string {
u := user.ContextMustGetUser(ctx)
return templates.WithUser(u, pw.UserLayout)
}
14 changes: 10 additions & 4 deletions pkg/storage/fs/ocis/persistence.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ package ocis

import (
"context"
"net/url"
"os"

provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
Expand All @@ -33,7 +32,7 @@ type TreePersistence interface {
ListFolder(ctx context.Context, node *Node) ([]*Node, error)
//CreateHome(owner *userpb.UserId) (n *Node, err error)
CreateDir(ctx context.Context, node *Node) (err error)
CreateReference(ctx context.Context, node *Node, targetURI *url.URL) error
//CreateReference(ctx context.Context, node *Node, targetURI *url.URL) error
Move(ctx context.Context, oldNode *Node, newNode *Node) (err error)
Delete(ctx context.Context, node *Node) (err error)

Expand All @@ -47,7 +46,14 @@ type PathWrapper interface {
NodeFromPath(ctx context.Context, fn string) (node *Node, err error)
Path(ctx context.Context, node *Node) (path string, err error)

// HomeNode returns the currently logged in users home node
// requires EnableHome to be true
HomeNode(ctx context.Context) (node *Node, err error)

// RootNode returns the storage root node
RootNode(ctx context.Context) (node *Node, err error)
// Root returns the internal root of the storage
Root() string

// HomeOrRootNode returns the users home node when home support is enabled.
// it returns the storages root node otherwise
HomeOrRootNode(ctx context.Context) (node *Node, err error)
}
Loading

0 comments on commit 3db04b9

Please sign in to comment.