core.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. package core
  2. import (
  3. "context"
  4. "flag"
  5. "log"
  6. "os"
  7. "os/signal"
  8. "os/user"
  9. "path/filepath"
  10. "runtime"
  11. "strconv"
  12. "syscall"
  13. "dev.hexasoftware.com/hxs/prettylog"
  14. "github.com/jacobsa/fuse"
  15. "github.com/jacobsa/fuse/fuseutil"
  16. )
  17. // Core struct
  18. type Core struct {
  19. Config Config
  20. Drivers map[string]DriverFactory
  21. CurrentFS Driver
  22. }
  23. // New create a New cloudmount core
  24. func New() *Core {
  25. // TODO: friendly panics
  26. usr, err := user.Current()
  27. if err != nil {
  28. panic(err)
  29. }
  30. uid, err := strconv.Atoi(usr.Uid)
  31. if err != nil {
  32. panic(err)
  33. }
  34. gid, err := strconv.Atoi(usr.Gid)
  35. if err != nil {
  36. panic(gid)
  37. }
  38. return &Core{
  39. Drivers: map[string]DriverFactory{},
  40. Config: Config{
  41. HomeDir: filepath.Join(usr.HomeDir, ".cloudmount"),
  42. UID: uint32(uid),
  43. GID: uint32(gid),
  44. VerboseLog: false,
  45. Daemonize: false,
  46. },
  47. }
  48. }
  49. // Init to be run after configuration
  50. func (c *Core) Init() (err error) {
  51. fsFactory, ok := c.Drivers[c.Config.CloudFSDriver]
  52. if !ok {
  53. log.Fatal("CloudFS not supported")
  54. }
  55. c.CurrentFS = fsFactory(c) // Factory
  56. return
  57. }
  58. func (c *Core) Mount() {
  59. // Start Selected driveFS
  60. c.CurrentFS.Start()
  61. //////////////
  62. // Server
  63. /////////
  64. ctx := context.Background()
  65. server := fuseutil.NewFileSystemServer(c.CurrentFS)
  66. mountPath := flag.Arg(0)
  67. var err error
  68. var mfs *fuse.MountedFileSystem
  69. if c.Config.VerboseLog {
  70. mfs, err = fuse.Mount(mountPath, server, &fuse.MountConfig{DebugLogger: prettylog.New("fuse"), ErrorLogger: prettylog.New("fuse-err")})
  71. } else {
  72. mfs, err = fuse.Mount(mountPath, server, &fuse.MountConfig{})
  73. }
  74. if err != nil {
  75. log.Fatal("Failed mounting path", flag.Arg(0), err)
  76. }
  77. // Signal handling to refresh Drives
  78. sigs := make(chan os.Signal, 2)
  79. signal.Notify(sigs, syscall.SIGUSR1, syscall.SIGHUP, syscall.SIGINT, os.Interrupt, syscall.SIGTERM)
  80. go func() {
  81. for sig := range sigs {
  82. log.Println("Signal:", sig)
  83. switch sig {
  84. case syscall.SIGUSR1:
  85. log.Println("Manually Refresh drive")
  86. go c.CurrentFS.Refresh()
  87. case syscall.SIGHUP:
  88. log.Println("GC")
  89. mem := runtime.MemStats{}
  90. runtime.ReadMemStats(&mem)
  91. log.Printf("Mem: %.2fMB", float64(mem.Alloc)/1024/1024)
  92. runtime.GC()
  93. runtime.ReadMemStats(&mem)
  94. log.Printf("After gc: Mem: %.2fMB", float64(mem.Alloc)/1024/1024)
  95. case os.Interrupt:
  96. log.Println("Graceful unmount")
  97. fuse.Unmount(mountPath)
  98. os.Exit(1)
  99. case syscall.SIGTERM:
  100. log.Println("Graceful unmount")
  101. fuse.Unmount(mountPath)
  102. os.Exit(1)
  103. }
  104. }
  105. }()
  106. if err := mfs.Join(ctx); err != nil {
  107. log.Fatalf("Joining: %v", err)
  108. }
  109. }