You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
2.8 KiB

7 years ago
7 years ago
7 years ago
6 years ago
  1. package filesys
  2. import (
  3. "fmt"
  4. "sync"
  5. "time"
  6. "bazil.org/fuse"
  7. "bazil.org/fuse/fs"
  8. "github.com/chrislusf/seaweedfs/weed/glog"
  9. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  10. "github.com/chrislusf/seaweedfs/weed/util"
  11. "github.com/karlseguin/ccache"
  12. )
  13. type Option struct {
  14. FilerGrpcAddress string
  15. FilerMountRootPath string
  16. Collection string
  17. Replication string
  18. TtlSec int32
  19. ChunkSizeLimit int64
  20. DataCenter string
  21. DirListingLimit int
  22. EntryCacheTtl time.Duration
  23. }
  24. type WFS struct {
  25. option *Option
  26. listDirectoryEntriesCache *ccache.Cache
  27. // contains all open handles
  28. handles []*FileHandle
  29. pathToHandleIndex map[string]int
  30. pathToHandleLock sync.Mutex
  31. }
  32. func NewSeaweedFileSystem(option *Option) *WFS {
  33. return &WFS{
  34. option: option,
  35. listDirectoryEntriesCache: ccache.New(ccache.Configure().MaxSize(int64(option.DirListingLimit) + 200).ItemsToPrune(100)),
  36. pathToHandleIndex: make(map[string]int),
  37. }
  38. }
  39. func (wfs *WFS) Root() (fs.Node, error) {
  40. return &Dir{Path: wfs.option.FilerMountRootPath, wfs: wfs}, nil
  41. }
  42. func (wfs *WFS) withFilerClient(fn func(filer_pb.SeaweedFilerClient) error) error {
  43. grpcConnection, err := util.GrpcDial(wfs.option.FilerGrpcAddress)
  44. if err != nil {
  45. return fmt.Errorf("fail to dial %s: %v", wfs.option.FilerGrpcAddress, err)
  46. }
  47. defer grpcConnection.Close()
  48. client := filer_pb.NewSeaweedFilerClient(grpcConnection)
  49. return fn(client)
  50. }
  51. func (wfs *WFS) AcquireHandle(file *File, uid, gid uint32) (fileHandle *FileHandle) {
  52. wfs.pathToHandleLock.Lock()
  53. defer wfs.pathToHandleLock.Unlock()
  54. fullpath := file.fullpath()
  55. index, found := wfs.pathToHandleIndex[fullpath]
  56. if found && wfs.handles[index] != nil {
  57. glog.V(4).Infoln(fullpath, "found fileHandle id", index)
  58. return wfs.handles[index]
  59. }
  60. fileHandle = newFileHandle(file, uid, gid)
  61. if found && wfs.handles[index] != nil {
  62. glog.V(4).Infoln(fullpath, "reuse previous fileHandle id", index)
  63. wfs.handles[index] = fileHandle
  64. fileHandle.handle = uint64(index)
  65. return
  66. }
  67. for i, h := range wfs.handles {
  68. if h == nil {
  69. wfs.handles[i] = fileHandle
  70. fileHandle.handle = uint64(i)
  71. wfs.pathToHandleIndex[fullpath] = i
  72. glog.V(4).Infoln(fullpath, "reuse fileHandle id", fileHandle.handle)
  73. return
  74. }
  75. }
  76. wfs.handles = append(wfs.handles, fileHandle)
  77. fileHandle.handle = uint64(len(wfs.handles) - 1)
  78. glog.V(4).Infoln(fullpath, "new fileHandle id", fileHandle.handle)
  79. wfs.pathToHandleIndex[fullpath] = int(fileHandle.handle)
  80. return
  81. }
  82. func (wfs *WFS) ReleaseHandle(handleId fuse.HandleID) {
  83. wfs.pathToHandleLock.Lock()
  84. defer wfs.pathToHandleLock.Unlock()
  85. glog.V(4).Infoln("releasing handle id", handleId, "current handles lengh", len(wfs.handles))
  86. if int(handleId) < len(wfs.handles) {
  87. wfs.handles[int(handleId)] = nil
  88. }
  89. return
  90. }