diff --git a/weed/command/mount_std.go b/weed/command/mount_std.go index 61f8119f7..a87068675 100644 --- a/weed/command/mount_std.go +++ b/weed/command/mount_std.go @@ -56,6 +56,8 @@ func (WFS) Root() (fs.Node, error) { return &Dir{Path: "/"}, nil } +var fileIdMap = make(map[uint64]filer.FileId) + type Dir struct { Id uint64 Path string @@ -71,7 +73,7 @@ func (dir *Dir) Attr(context context.Context, attr *fuse.Attr) error { func (dir *Dir) Lookup(ctx context.Context, name string) (fs.Node, error) { if dirent, ok := dir.DirentMap[name]; ok { if dirent.Type == fuse.DT_File { - return &File{dirent.Inode, dirent.Name}, nil + return &File{Id: dirent.Inode, FileId: fileIdMap[dirent.Inode], Name: dirent.Name}, nil } return &Dir{ Id: dirent.Inode, @@ -101,20 +103,45 @@ func (dir *Dir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { dirent := fuse.Dirent{Inode: fileInode, Name: f.Name, Type: fuse.DT_File} ret = append(ret, dirent) dir.DirentMap[f.Name] = &dirent + fileIdMap[fileInode] = f.Id } } } return ret, nil } +func (dir *Dir) Remove(ctx context.Context, req *fuse.RemoveRequest) error { + name := path.Join(dir.Path, req.Name) + err := filer.DeleteDirectoryOrFile(*mountOptions.filer, name, req.Dir) + if err != nil { + fmt.Printf("Delete file %s [ERROR] %s\n", name, err) + } + return err +} + type File struct { - Id uint64 - // FileId filer.FileId - Name string + Id uint64 + FileId filer.FileId + Name string } func (file *File) Attr(context context.Context, attr *fuse.Attr) error { attr.Inode = file.Id - attr.Mode = 0000 - return nil + attr.Mode = 0444 + ret, err := filer.GetFileSize(*mountOptions.filer, string(file.FileId)) + if err == nil { + attr.Size = ret.Size + } else { + fmt.Printf("Get file %s attr [ERROR] %s\n", file.Name, err) + } + return err +} + +func (file *File) ReadAll(ctx context.Context) ([]byte, error) { + ret, err := filer.GetFileContent(*mountOptions.filer, string(file.FileId)) + if err == nil { + return ret.Content, nil + } + fmt.Printf("Get file %s content [ERROR] %s\n", file.Name, err) + return nil, err } diff --git a/weed/filer/client_operations.go b/weed/filer/client_operations.go index 13e4854a4..95dd26396 100644 --- a/weed/filer/client_operations.go +++ b/weed/filer/client_operations.go @@ -4,16 +4,16 @@ import ( "encoding/json" "errors" "fmt" + "net/url" "github.com/chrislusf/seaweedfs/weed/util" - - "net/url" ) type ApiRequest struct { - Command string //"listFiles", "listDirectories" + Command string //"listFiles", "listDirectories", "getFileSize" Directory string FileName string + FileId string } type ListFilesResult struct { @@ -21,16 +21,47 @@ type ListFilesResult struct { Error string `json:"error,omitempty"` } -func ListFiles(server string, directory string, fileName string) (*ListFilesResult, error) { - var ret ListFilesResult - if err := call(server, ApiRequest{Command: "listFiles", Directory: directory, FileName: fileName}, &ret); err == nil { +func ListFiles(server string, directory string, fileName string) (ret *ListFilesResult, err error) { + ret = new(ListFilesResult) + if err = call(server, ApiRequest{Command: "listFiles", Directory: directory, FileName: fileName}, ret); err == nil { + if ret.Error != "" { + return nil, errors.New(ret.Error) + } + return ret, nil + } + return nil, err +} + +type GetFileSizeResult struct { + Size uint64 + Error string `json:"error,omitempty"` +} + +func GetFileSize(server string, fileId string) (ret *GetFileSizeResult, err error) { + ret = new(GetFileSizeResult) + if err = call(server, ApiRequest{Command: "getFileSize", FileId: fileId}, ret); err == nil { if ret.Error != "" { return nil, errors.New(ret.Error) } - return &ret, nil - } else { - return nil, err + return ret, nil } + return nil, err +} + +type GetFileContentResult struct { + Content []byte + Error string `json:"error,omitempty"` +} + +func GetFileContent(server string, fileId string) (ret *GetFileContentResult, err error) { + ret = new(GetFileContentResult) + if err = call(server, ApiRequest{Command: "getFileContent", FileId: fileId}, ret); err == nil { + if ret.Error != "" { + return nil, errors.New(ret.Error) + } + return ret, nil + } + return nil, err } type ListDirectoriesResult struct { @@ -38,16 +69,23 @@ type ListDirectoriesResult struct { Error string `json:"error,omitempty"` } -func ListDirectories(server string, directory string) (*ListDirectoriesResult, error) { - var ret ListDirectoriesResult - if err := call(server, ApiRequest{Command: "listDirectories", Directory: directory}, &ret); err == nil { +func ListDirectories(server string, directory string) (ret *ListDirectoriesResult, err error) { + ret = new(ListDirectoriesResult) + if err := call(server, ApiRequest{Command: "listDirectories", Directory: directory}, ret); err == nil { if ret.Error != "" { return nil, errors.New(ret.Error) } - return &ret, nil - } else { - return nil, err + return ret, nil + } + return nil, err +} + +func DeleteDirectoryOrFile(server string, path string, isDir bool) error { + destUrl := fmt.Sprintf("http://%s%s", server, path) + if isDir { + destUrl += "/?recursive=true" } + return util.Delete(destUrl, "") } func call(server string, request ApiRequest, ret interface{}) error { diff --git a/weed/server/filer_server_handlers_api.go b/weed/server/filer_server_handlers_api.go index f2a64e6cb..f07aab88a 100644 --- a/weed/server/filer_server_handlers_api.go +++ b/weed/server/filer_server_handlers_api.go @@ -3,9 +3,12 @@ package weed_server import ( "encoding/json" "net/http" + "strconv" "github.com/chrislusf/seaweedfs/weed/filer" "github.com/chrislusf/seaweedfs/weed/glog" + "github.com/chrislusf/seaweedfs/weed/operation" + "github.com/chrislusf/seaweedfs/weed/util" ) func (fs *FilerServer) apiHandler(w http.ResponseWriter, r *http.Request) { @@ -32,5 +35,39 @@ func (fs *FilerServer) apiHandler(w http.ResponseWriter, r *http.Request) { res.Error = err.Error() } writeJsonQuiet(w, r, http.StatusOK, res) + case "getFileSize": + res := filer.GetFileSizeResult{} + server, err := operation.LookupFileId(fs.getMasterNode(), apiRequest.FileId) + if err != nil { + res.Error = err.Error() + writeJsonQuiet(w, r, http.StatusOK, res) + return + } + head, err := util.Head(server) + if err != nil { + res.Error = err.Error() + writeJsonQuiet(w, r, http.StatusOK, res) + return + } + res.Size, err = strconv.ParseUint(head.Get("Content-Length"), 10, 0) + if err != nil { + res.Error = err.Error() + } + writeJsonQuiet(w, r, http.StatusOK, res) + case "getFileContent": + res := filer.GetFileContentResult{} + server, err := operation.LookupFileId(fs.getMasterNode(), apiRequest.FileId) + if err != nil { + res.Error = err.Error() + writeJsonQuiet(w, r, http.StatusOK, res) + return + } + res.Content, err = util.Get(server) + if err != nil { + res.Error = err.Error() + writeJsonQuiet(w, r, http.StatusOK, res) + return + } + writeJsonQuiet(w, r, http.StatusOK, res) } } diff --git a/weed/server/filer_server_handlers_write.go b/weed/server/filer_server_handlers_write.go index 80f222ce6..07452cd77 100644 --- a/weed/server/filer_server_handlers_write.go +++ b/weed/server/filer_server_handlers_write.go @@ -532,7 +532,7 @@ func (fs *FilerServer) doUpload(urlLocation string, w http.ResponseWriter, r *ht } // curl -X DELETE http://localhost:8888/path/to -// curl -X DELETE http://localhost:8888/path/to?recursive=true +// curl -X DELETE http://localhost:8888/path/to/?recursive=true func (fs *FilerServer) DeleteHandler(w http.ResponseWriter, r *http.Request) { var err error var fid string diff --git a/weed/util/http_util.go b/weed/util/http_util.go index f3e97f6f1..086584af7 100644 --- a/weed/util/http_util.go +++ b/weed/util/http_util.go @@ -74,6 +74,17 @@ func Get(url string) ([]byte, error) { return b, nil } +func Head(url string) (http.Header, error) { + r, err := client.Head(url) + if err != nil { + return nil, err + } + if r.StatusCode >= 400 { + return nil, fmt.Errorf("%s: %s", url, r.Status) + } + return r.Header, nil +} + func Delete(url string, jwt security.EncodedJwt) error { req, err := http.NewRequest("DELETE", url, nil) if jwt != "" {