From 328aa48c6a666e15033f34e072e40a6ba41c6d36 Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Mon, 12 May 2014 22:57:23 -0700 Subject: [PATCH] Can compile now. not working just yet. --- go/filer/directory.go | 4 +- go/filer/filer.go | 4 +- go/filer/operations.go | 58 +++++++++++++++++ go/weed/mount.go | 144 +++++++++++++++++++++++++++++++++++++++++ go/weed/weed.go | 3 +- 5 files changed, 209 insertions(+), 4 deletions(-) create mode 100644 go/filer/operations.go create mode 100644 go/weed/mount.go diff --git a/go/filer/directory.go b/go/filer/directory.go index 2eefed9c1..956a2f504 100644 --- a/go/filer/directory.go +++ b/go/filer/directory.go @@ -11,8 +11,10 @@ type DirectoryEntry struct { type DirectoryManager interface { FindDirectory(dirPath string) (DirectoryId, error) - ListDirectories(dirPath string) (dirNames []DirectoryEntry, err error) + ListDirectories(dirPath string) (dirs []DirectoryEntry, err error) MakeDirectory(currentDirPath string, dirName string) (DirectoryId, error) MoveUnderDirectory(oldDirPath string, newParentDirPath string) error DeleteDirectory(dirPath string) error + //functions used by FUSE + FindDirectoryById(DirectoryId, error) } diff --git a/go/filer/filer.go b/go/filer/filer.go index a42d9ed8c..8d2da901b 100644 --- a/go/filer/filer.go +++ b/go/filer/filer.go @@ -5,8 +5,8 @@ import () type FileId string //file id on weedfs type FileEntry struct { - Name string //file name without path - Id FileId + Name string `json:"name,omitempty"` //file name without path + Id FileId `json:"fid,omitempty"` } type Filer interface { diff --git a/go/filer/operations.go b/go/filer/operations.go new file mode 100644 index 000000000..7e89b534d --- /dev/null +++ b/go/filer/operations.go @@ -0,0 +1,58 @@ +package filer + +import () + +import ( + "code.google.com/p/weed-fs/go/util" + "encoding/json" + "errors" + _ "fmt" + "net/url" + "strconv" +) + +type ListFilesResult struct { + Files []FileEntry + Error string `json:"error,omitempty"` +} + +func ListFiles(server string, directoryId DirectoryId, fileName string) (*ListFilesResult, error) { + values := make(url.Values) + values.Add("directoryId", strconv.Itoa(int(directoryId))) + jsonBlob, err := util.Post("http://"+server+"/dir/lookup", values) + if err != nil { + return nil, err + } + var ret ListFilesResult + err = json.Unmarshal(jsonBlob, &ret) + if err != nil { + return nil, err + } + if ret.Error != "" { + return nil, errors.New(ret.Error) + } + return &ret, nil +} + +type ListDirectoriesResult struct { + Directories []DirectoryEntry + Error string `json:"error,omitempty"` +} + +func ListDirectories(server string, directoryId DirectoryId) (*ListDirectoriesResult, error) { + values := make(url.Values) + values.Add("directoryId", strconv.Itoa(int(directoryId))) + jsonBlob, err := util.Post("http://"+server+"/dir/lookup", values) + if err != nil { + return nil, err + } + var ret ListDirectoriesResult + err = json.Unmarshal(jsonBlob, &ret) + if err != nil { + return nil, err + } + if ret.Error != "" { + return nil, errors.New(ret.Error) + } + return &ret, nil +} diff --git a/go/weed/mount.go b/go/weed/mount.go new file mode 100644 index 000000000..51b5e6919 --- /dev/null +++ b/go/weed/mount.go @@ -0,0 +1,144 @@ +package main + +import ( + "bazil.org/fuse" + "bazil.org/fuse/fs" + "code.google.com/p/weed-fs/go/filer" + "code.google.com/p/weed-fs/go/glog" + "code.google.com/p/weed-fs/go/storage" + "code.google.com/p/weed-fs/go/util" + "fmt" + "os" + "os/signal" + "runtime" +) + +type MountOptions struct { + filer *string + dir *string +} + +var ( + mountOptions MountOptions +) + +func init() { + cmdMount.Run = runMount // break init cycle + cmdMount.IsDebug = cmdMount.Flag.Bool("debug", false, "verbose debug information") + mountOptions.filer = cmdMount.Flag.String("filer", "localhost:8888", "weedfs filer location") + mountOptions.dir = cmdMount.Flag.String("dir", "", "mount weed filer to this directory") +} + +var cmdMount = &Command{ + UsageLine: "mount -filer=localhost:8888 -dir=/some/dir", + Short: "mount weed filer to a directory as file system in userspace(FUSE)", + Long: `mount weed file system to userspace. + + Pre-requisites: + 1) have a weed file system running + 2) have a "weed filer" running + These 2 requirements can be achieved with one command "weed server -filer=true" + + This uses bazil.org/fuse, whichenables writing FUSE file systems on + FreeBSD, Linux, and OS X. + + On OS X, it requires OSXFUSE (http://osxfuse.github.com/). + + `, +} + +func runMount(cmd *Command, args []string) bool { + fmt.Printf("This is Weed File System version %s %s %s\n", util.VERSION, runtime.GOOS, runtime.GOARCH) + if *mountOptions.dir == "" { + fmt.Printf("Please specify the mount directory via \"-dir\"") + return false + } + + c, err := fuse.Mount(*mountOptions.dir) + if err != nil { + glog.Fatal(err) + return false + } + + signalChan := make(chan os.Signal, 1) + signal.Notify(signalChan, os.Interrupt) + go func() { + for _ = range signalChan { + // sig is a ^C, handle it + fuse.Unmount(*mountOptions.dir) + c.Close() + os.Exit(0) + } + }() + + err = fs.Serve(c, WFS{}) + if err != nil { + fuse.Unmount(*mountOptions.dir) + } + + // check if the mount process has an error to report + <-c.Ready + if err := c.MountError; err != nil { + glog.Fatal(err) + } + + return true +} + +type File struct { + FileId filer.FileId + Name string +} + +func (File) Attr() fuse.Attr { + return fuse.Attr{Mode: 0444} +} +func (File) ReadAll(intr fs.Intr) ([]byte, fuse.Error) { + return []byte("hello, world\n"), nil +} + +type Dir struct { + DirectoryId filer.DirectoryId + Name string +} + +func (dir Dir) Attr() fuse.Attr { + return fuse.Attr{Inode: 1, Mode: os.ModeDir | 0555} +} + +func (dir Dir) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) { + files_result, e := filer.ListFiles(*mountOptions.filer, dir.DirectoryId, name) + if e != nil { + return nil, fuse.ENOENT + } + if len(files_result.Files) > 0 { + return File{files_result.Files[0].Id, files_result.Files[0].Name}, nil + } + return nil, fmt.Errorf("File Not Found for %s", name) +} + +type WFS struct{} + +func (WFS) Root() (fs.Node, fuse.Error) { + return Dir{}, nil +} + +func (dir *Dir) ReadDir(intr fs.Intr) ([]fuse.Dirent, fuse.Error) { + ret := make([]fuse.Dirent, 0) + if dirs, e := filer.ListDirectories(*mountOptions.filer, dir.DirectoryId); e == nil { + for _, d := range dirs.Directories { + dirId := uint64(d.Id) + ret = append(ret, fuse.Dirent{Inode: dirId, Name: d.Name, Type: fuse.DT_Dir}) + } + } + if files, e := filer.ListFiles(*mountOptions.filer, dir.DirectoryId, ""); e == nil { + for _, f := range files.Files { + if fileId, e := storage.ParseFileId(string(f.Id)); e == nil { + fileInode := uint64(fileId.VolumeId)<<32 + fileId.Key + ret = append(ret, fuse.Dirent{Inode: fileInode, Name: f.Name, Type: fuse.DT_File}) + } + + } + } + return ret, nil +} diff --git a/go/weed/weed.go b/go/weed/weed.go index 418d89276..c739d8e93 100644 --- a/go/weed/weed.go +++ b/go/weed/weed.go @@ -21,16 +21,17 @@ var server *string var commands = []*Command{ cmdBenchmark, cmdCompact, - cmdFiler, cmdFix, cmdServer, cmdMaster, + cmdFiler, cmdUpload, cmdDownload, cmdShell, cmdVersion, cmdVolume, cmdExport, + cmdMount, } var exitStatus = 0