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.9 KiB

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