diff options
Diffstat (limited to 'weed/filesys/file.go')
| -rw-r--r-- | weed/filesys/file.go | 145 |
1 files changed, 103 insertions, 42 deletions
diff --git a/weed/filesys/file.go b/weed/filesys/file.go index e4c79c055..1fb7d53b1 100644 --- a/weed/filesys/file.go +++ b/weed/filesys/file.go @@ -1,75 +1,136 @@ package filesys import ( - "context" - "fmt" - "bazil.org/fuse" - "github.com/chrislusf/seaweedfs/weed/filer" "bazil.org/fuse/fs" + "context" + "github.com/chrislusf/seaweedfs/weed/filer2" "github.com/chrislusf/seaweedfs/weed/glog" "github.com/chrislusf/seaweedfs/weed/pb/filer_pb" + "os" + "path/filepath" + "time" ) var _ = fs.Node(&File{}) -// var _ = fs.NodeOpener(&File{}) -// var _ = fs.NodeFsyncer(&File{}) -var _ = fs.Handle(&File{}) -var _ = fs.HandleReadAller(&File{}) -// var _ = fs.HandleReader(&File{}) -var _ = fs.HandleWriter(&File{}) +var _ = fs.NodeOpener(&File{}) +var _ = fs.NodeFsyncer(&File{}) +var _ = fs.NodeSetattrer(&File{}) type File struct { - FileId filer.FileId - Name string - wfs *WFS + Chunks []*filer_pb.FileChunk + Name string + dir *Dir + wfs *WFS + attributes *filer_pb.FuseAttributes + isOpen bool } func (file *File) Attr(context context.Context, attr *fuse.Attr) error { - attr.Mode = 0444 - return file.wfs.withFilerClient(func(client filer_pb.SeaweedFilerClient) error { - request := &filer_pb.GetFileAttributesRequest{ - Name: file.Name, - ParentDir: "", //TODO add parent folder - FileId: string(file.FileId), - } + fullPath := filepath.Join(file.dir.Path, file.Name) + + if file.attributes == nil || !file.isOpen { + item := file.wfs.listDirectoryEntriesCache.Get(fullPath) + if item != nil { + entry := item.Value().(*filer_pb.Entry) + file.Chunks = entry.Chunks + file.attributes = entry.Attributes + glog.V(1).Infof("file attr read cached %v attributes", file.Name) + } else { + err := file.wfs.withFilerClient(func(client filer_pb.SeaweedFilerClient) error { + + request := &filer_pb.GetEntryAttributesRequest{ + Name: file.Name, + ParentDir: file.dir.Path, + } - glog.V(1).Infof("read file size: %v", request) - resp, err := client.GetFileAttributes(context, request) - if err != nil { - return err + resp, err := client.GetEntryAttributes(context, request) + if err != nil { + glog.V(0).Infof("file attr read file %v: %v", request, err) + return err + } + + file.attributes = resp.Attributes + file.Chunks = resp.Chunks + + glog.V(1).Infof("file attr %v %+v: %d", fullPath, file.attributes, filer2.TotalSize(file.Chunks)) + + return nil + }) + + if err != nil { + return err + } } + } + + attr.Mode = os.FileMode(file.attributes.FileMode) + attr.Size = filer2.TotalSize(file.Chunks) + attr.Mtime = time.Unix(file.attributes.Mtime, 0) + attr.Gid = file.attributes.Gid + attr.Uid = file.attributes.Uid - attr.Size = resp.Attributes.FileSize + return nil - return nil - }) } -func (file *File) ReadAll(ctx context.Context) (content []byte, err error) { +func (file *File) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenResponse) (fs.Handle, error) { - err = file.wfs.withFilerClient(func(client filer_pb.SeaweedFilerClient) error { + fullPath := filepath.Join(file.dir.Path, file.Name) - request := &filer_pb.GetFileContentRequest{ - FileId: string(file.FileId), - } + glog.V(3).Infof("%v file open %+v", fullPath, req) + + file.isOpen = true + + return &FileHandle{ + f: file, + dirtyPages: newDirtyPages(file), + RequestId: req.Header.ID, + NodeId: req.Header.Node, + Uid: req.Uid, + Gid: req.Gid, + }, nil + +} + +func (file *File) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse.SetattrResponse) error { + fullPath := filepath.Join(file.dir.Path, file.Name) - glog.V(1).Infof("read file content: %v", request) - resp, err := client.GetFileContent(ctx, request) - if err != nil { - return err + glog.V(3).Infof("%v file setattr %+v", fullPath, req) + if req.Valid.Size() { + + glog.V(3).Infof("%v file setattr set size=%v", fullPath, req.Size) + if req.Size == 0 { + // fmt.Printf("truncate %v \n", fullPath) + file.Chunks = nil } + file.attributes.FileSize = req.Size + } + if req.Valid.Mode() { + file.attributes.FileMode = uint32(req.Mode) + } + + if req.Valid.Uid() { + file.attributes.Uid = req.Uid + } - content = resp.Content + if req.Valid.Gid() { + file.attributes.Gid = req.Gid + } - return nil - }) + if req.Valid.Mtime() { + file.attributes.Mtime = req.Mtime.Unix() + } + + return nil - return content, err } -func (file *File) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) error { - fmt.Printf("write file %+v\n", req) +func (file *File) Fsync(ctx context.Context, req *fuse.FsyncRequest) error { + // fsync works at OS level + // write the file chunks to the filer + glog.V(3).Infof("%s/%s fsync file %+v", file.dir.Path, file.Name, req) + return nil } |
