mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2025-10-15 05:14:51 +08:00
releasing 0.58 to handle control+c interrupts.
compilable now. but FUSE mount is not working.
This commit is contained in:
71
go/filer/client_operations.go
Normal file
71
go/filer/client_operations.go
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package filer
|
||||||
|
|
||||||
|
import ()
|
||||||
|
|
||||||
|
import (
|
||||||
|
"code.google.com/p/weed-fs/go/util"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ApiRequest struct {
|
||||||
|
Command string //"listFiles", "listDirectories"
|
||||||
|
DirectoryId DirectoryId
|
||||||
|
FileName string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListFilesResult struct {
|
||||||
|
Files []FileEntry
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func ListFiles(server string, directoryId DirectoryId, fileName string) (*ListFilesResult, error) {
|
||||||
|
var ret ListFilesResult
|
||||||
|
if err := call(server, ApiRequest{Command: "listFiles", DirectoryId: directoryId, FileName: fileName}, &ret); err == nil {
|
||||||
|
if ret.Error != "" {
|
||||||
|
return nil, errors.New(ret.Error)
|
||||||
|
}
|
||||||
|
return &ret, nil
|
||||||
|
} else {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListDirectoriesResult struct {
|
||||||
|
Directories []DirectoryEntry
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func ListDirectories(server string, directoryId DirectoryId) (*ListDirectoriesResult, error) {
|
||||||
|
var ret ListDirectoriesResult
|
||||||
|
if err := call(server, ApiRequest{Command: "listDirectories", DirectoryId: directoryId}, &ret); err == nil {
|
||||||
|
if ret.Error != "" {
|
||||||
|
return nil, errors.New(ret.Error)
|
||||||
|
}
|
||||||
|
return &ret, nil
|
||||||
|
} else {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func call(server string, request ApiRequest, ret interface{}) error {
|
||||||
|
b, err := json.Marshal(request)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("error:", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
values := make(url.Values)
|
||||||
|
values.Add("request", string(b))
|
||||||
|
jsonBlob, err := util.Post("http://"+server+"/__api__", values)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(jsonBlob, ret)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@@ -1,58 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@@ -3,5 +3,5 @@ package util
|
|||||||
import ()
|
import ()
|
||||||
|
|
||||||
const (
|
const (
|
||||||
VERSION = "0.57 beta"
|
VERSION = "0.58"
|
||||||
)
|
)
|
||||||
|
108
go/weed/mount.go
108
go/weed/mount.go
@@ -1,16 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
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 {
|
type MountOptions struct {
|
||||||
@@ -40,105 +30,9 @@ var cmdMount = &Command{
|
|||||||
These 2 requirements can be achieved with one command "weed server -filer=true"
|
These 2 requirements can be achieved with one command "weed server -filer=true"
|
||||||
|
|
||||||
This uses bazil.org/fuse, whichenables writing FUSE file systems on
|
This uses bazil.org/fuse, whichenables writing FUSE file systems on
|
||||||
FreeBSD, Linux, and OS X.
|
Linux, and OS X.
|
||||||
|
|
||||||
On OS X, it requires OSXFUSE (http://osxfuse.github.com/).
|
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
|
|
||||||
}
|
|
||||||
|
15
go/weed/mount_notsupported.go
Normal file
15
go/weed/mount_notsupported.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// +build !linux
|
||||||
|
// +build !darwin
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func runMount(cmd *Command, args []string) bool {
|
||||||
|
fmt.Printf("Mount is not supported on %s %s\n", runtime.GOOS, runtime.GOARCH)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
112
go/weed/mount_std.go
Normal file
112
go/weed/mount_std.go
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
// +build linux darwin
|
||||||
|
|
||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
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)<<48 + fileId.Key
|
||||||
|
ret = append(ret, fuse.Dirent{Inode: fileInode, Name: f.Name, Type: fuse.DT_File})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
@@ -26,6 +26,7 @@ func NewFilerServer(r *http.ServeMux, port int, master string, dir string, colle
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r.HandleFunc("/__api__", fs.filerApiHandler)
|
||||||
r.HandleFunc("/", fs.filerHandler)
|
r.HandleFunc("/", fs.filerHandler)
|
||||||
|
|
||||||
return fs, nil
|
return fs, nil
|
||||||
|
20
go/weed/weed_server/filer_server_handlers_api.go
Normal file
20
go/weed/weed_server/filer_server_handlers_api.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package weed_server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (fs *FilerServer) filerApiHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.Method {
|
||||||
|
case "GET":
|
||||||
|
fs.GetOrHeadHandler(w, r, true)
|
||||||
|
case "HEAD":
|
||||||
|
fs.GetOrHeadHandler(w, r, false)
|
||||||
|
case "DELETE":
|
||||||
|
fs.DeleteHandler(w, r)
|
||||||
|
case "PUT":
|
||||||
|
fs.PostHandler(w, r)
|
||||||
|
case "POST":
|
||||||
|
fs.PostHandler(w, r)
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user