|
|
@ -40,8 +40,9 @@ func newFileHandle(file *File, uid, gid uint32) *FileHandle { |
|
|
|
Uid: uid, |
|
|
|
Gid: gid, |
|
|
|
} |
|
|
|
if fh.f.entry != nil { |
|
|
|
fh.f.entry.Attributes.FileSize = filer.FileSize(fh.f.entry) |
|
|
|
entry := fh.f.getEntry() |
|
|
|
if entry != nil { |
|
|
|
entry.Attributes.FileSize = filer.FileSize(entry) |
|
|
|
} |
|
|
|
|
|
|
|
return fh |
|
|
@ -104,22 +105,27 @@ func (fh *FileHandle) readFromDirtyPages(buff []byte, startOffset int64) (maxSto |
|
|
|
|
|
|
|
func (fh *FileHandle) readFromChunks(buff []byte, offset int64) (int64, error) { |
|
|
|
|
|
|
|
fileSize := int64(filer.FileSize(fh.f.entry)) |
|
|
|
entry := fh.f.getEntry() |
|
|
|
if entry == nil { |
|
|
|
return 0, io.EOF |
|
|
|
} |
|
|
|
|
|
|
|
fileSize := int64(filer.FileSize(entry)) |
|
|
|
|
|
|
|
if fileSize == 0 { |
|
|
|
glog.V(1).Infof("empty fh %v", fh.f.fullpath()) |
|
|
|
return 0, io.EOF |
|
|
|
} |
|
|
|
|
|
|
|
if offset+int64(len(buff)) <= int64(len(fh.f.entry.Content)) { |
|
|
|
totalRead := copy(buff, fh.f.entry.Content[offset:]) |
|
|
|
if offset+int64(len(buff)) <= int64(len(entry.Content)) { |
|
|
|
totalRead := copy(buff, entry.Content[offset:]) |
|
|
|
glog.V(4).Infof("file handle read cached %s [%d,%d] %d", fh.f.fullpath(), offset, offset+int64(totalRead), totalRead) |
|
|
|
return int64(totalRead), nil |
|
|
|
} |
|
|
|
|
|
|
|
var chunkResolveErr error |
|
|
|
if fh.f.entryViewCache == nil { |
|
|
|
fh.f.entryViewCache, chunkResolveErr = filer.NonOverlappingVisibleIntervals(fh.f.wfs.LookupFn(), fh.f.entry.Chunks) |
|
|
|
fh.f.entryViewCache, chunkResolveErr = filer.NonOverlappingVisibleIntervals(fh.f.wfs.LookupFn(), entry.Chunks) |
|
|
|
if chunkResolveErr != nil { |
|
|
|
return 0, fmt.Errorf("fail to resolve chunk manifest: %v", chunkResolveErr) |
|
|
|
} |
|
|
@ -158,8 +164,13 @@ func (fh *FileHandle) Write(ctx context.Context, req *fuse.WriteRequest, resp *f |
|
|
|
copy(data, req.Data) |
|
|
|
} |
|
|
|
|
|
|
|
fh.f.entry.Content = nil |
|
|
|
fh.f.entry.Attributes.FileSize = uint64(max(req.Offset+int64(len(data)), int64(fh.f.entry.Attributes.FileSize))) |
|
|
|
entry := fh.f.getEntry() |
|
|
|
if entry == nil { |
|
|
|
return fuse.EIO |
|
|
|
} |
|
|
|
|
|
|
|
entry.Content = nil |
|
|
|
entry.Attributes.FileSize = uint64(max(req.Offset+int64(len(data)), int64(entry.Attributes.FileSize))) |
|
|
|
glog.V(4).Infof("%v write [%d,%d) %d", fh.f.fullpath(), req.Offset, req.Offset+int64(len(req.Data)), len(req.Data)) |
|
|
|
|
|
|
|
fh.dirtyPages.AddPage(req.Offset, data) |
|
|
@ -242,35 +253,40 @@ func (fh *FileHandle) doFlush(ctx context.Context, header fuse.Header) error { |
|
|
|
|
|
|
|
err := fh.f.wfs.WithFilerClient(func(client filer_pb.SeaweedFilerClient) error { |
|
|
|
|
|
|
|
if fh.f.entry.Attributes != nil { |
|
|
|
fh.f.entry.Attributes.Mime = fh.contentType |
|
|
|
if fh.f.entry.Attributes.Uid == 0 { |
|
|
|
fh.f.entry.Attributes.Uid = header.Uid |
|
|
|
entry := fh.f.getEntry() |
|
|
|
if entry == nil { |
|
|
|
return nil |
|
|
|
} |
|
|
|
|
|
|
|
if entry.Attributes != nil { |
|
|
|
entry.Attributes.Mime = fh.contentType |
|
|
|
if entry.Attributes.Uid == 0 { |
|
|
|
entry.Attributes.Uid = header.Uid |
|
|
|
} |
|
|
|
if fh.f.entry.Attributes.Gid == 0 { |
|
|
|
fh.f.entry.Attributes.Gid = header.Gid |
|
|
|
if entry.Attributes.Gid == 0 { |
|
|
|
entry.Attributes.Gid = header.Gid |
|
|
|
} |
|
|
|
if fh.f.entry.Attributes.Crtime == 0 { |
|
|
|
fh.f.entry.Attributes.Crtime = time.Now().Unix() |
|
|
|
if entry.Attributes.Crtime == 0 { |
|
|
|
entry.Attributes.Crtime = time.Now().Unix() |
|
|
|
} |
|
|
|
fh.f.entry.Attributes.Mtime = time.Now().Unix() |
|
|
|
fh.f.entry.Attributes.FileMode = uint32(os.FileMode(fh.f.entry.Attributes.FileMode) &^ fh.f.wfs.option.Umask) |
|
|
|
fh.f.entry.Attributes.Collection = fh.dirtyPages.collection |
|
|
|
fh.f.entry.Attributes.Replication = fh.dirtyPages.replication |
|
|
|
entry.Attributes.Mtime = time.Now().Unix() |
|
|
|
entry.Attributes.FileMode = uint32(os.FileMode(entry.Attributes.FileMode) &^ fh.f.wfs.option.Umask) |
|
|
|
entry.Attributes.Collection = fh.dirtyPages.collection |
|
|
|
entry.Attributes.Replication = fh.dirtyPages.replication |
|
|
|
} |
|
|
|
|
|
|
|
request := &filer_pb.CreateEntryRequest{ |
|
|
|
Directory: fh.f.dir.FullPath(), |
|
|
|
Entry: fh.f.entry, |
|
|
|
Entry: entry, |
|
|
|
Signatures: []int32{fh.f.wfs.signature}, |
|
|
|
} |
|
|
|
|
|
|
|
glog.V(4).Infof("%s set chunks: %v", fh.f.fullpath(), len(fh.f.entry.Chunks)) |
|
|
|
for i, chunk := range fh.f.entry.Chunks { |
|
|
|
glog.V(4).Infof("%s set chunks: %v", fh.f.fullpath(), len(entry.Chunks)) |
|
|
|
for i, chunk := range entry.Chunks { |
|
|
|
glog.V(4).Infof("%s chunks %d: %v [%d,%d)", fh.f.fullpath(), i, chunk.GetFileIdString(), chunk.Offset, chunk.Offset+int64(chunk.Size)) |
|
|
|
} |
|
|
|
|
|
|
|
manifestChunks, nonManifestChunks := filer.SeparateManifestChunks(fh.f.entry.Chunks) |
|
|
|
manifestChunks, nonManifestChunks := filer.SeparateManifestChunks(entry.Chunks) |
|
|
|
|
|
|
|
chunks, _ := filer.CompactFileChunks(fh.f.wfs.LookupFn(), nonManifestChunks) |
|
|
|
chunks, manifestErr := filer.MaybeManifestize(fh.f.wfs.saveDataAsChunk(fh.f.fullpath()), chunks) |
|
|
@ -278,7 +294,7 @@ func (fh *FileHandle) doFlush(ctx context.Context, header fuse.Header) error { |
|
|
|
// not good, but should be ok
|
|
|
|
glog.V(0).Infof("MaybeManifestize: %v", manifestErr) |
|
|
|
} |
|
|
|
fh.f.entry.Chunks = append(chunks, manifestChunks...) |
|
|
|
entry.Chunks = append(chunks, manifestChunks...) |
|
|
|
|
|
|
|
fh.f.wfs.mapPbIdFromLocalToFiler(request.Entry) |
|
|
|
defer fh.f.wfs.mapPbIdFromFilerToLocal(request.Entry) |
|
|
|