Chris Lu
11 years ago
5 changed files with 209 additions and 4 deletions
-
4go/filer/directory.go
-
4go/filer/filer.go
-
58go/filer/operations.go
-
144go/weed/mount.go
-
3go/weed/weed.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 |
|||
} |
@ -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 |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue