file_system.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. package fileSystem
  2. import (
  3. "fmt"
  4. "path/filepath"
  5. "strings"
  6. "time"
  7. etcdErr "github.com/coreos/etcd/error"
  8. )
  9. type FileSystem struct {
  10. Root *Node
  11. EventHistory *EventHistory
  12. WatcherHub *watcherHub
  13. Index uint64
  14. Term uint64
  15. }
  16. func New() *FileSystem {
  17. return &FileSystem{
  18. Root: newDir("/", 0, 0, nil, ""),
  19. WatcherHub: newWatchHub(1000),
  20. }
  21. }
  22. func (fs *FileSystem) InternalGet(path string, index uint64, term uint64) (*Node, error) {
  23. fmt.Println("GET: ", path)
  24. path = filepath.Clean("/" + path)
  25. // update file system known index and term
  26. fs.Index, fs.Term = index, term
  27. walkFunc := func(parent *Node, dirName string) (*Node, error) {
  28. child, ok := parent.Children[dirName]
  29. if ok {
  30. return child, nil
  31. }
  32. return nil, etcdErr.NewError(100, "get")
  33. }
  34. f, err := fs.walk(path, walkFunc)
  35. if err != nil {
  36. return nil, err
  37. }
  38. return f, nil
  39. }
  40. func (fs *FileSystem) Set(path string, value string, expireTime time.Time, index uint64, term uint64) error {
  41. path = filepath.Clean("/" + path)
  42. // update file system known index and term
  43. fs.Index, fs.Term = index, term
  44. dir, name := filepath.Split(path)
  45. // walk through the path and get the last directory node
  46. d, err := fs.walk(dir, fs.checkDir)
  47. if err != nil {
  48. return err
  49. }
  50. f := newFile(name, value, fs.Index, fs.Term, d, "", expireTime)
  51. err = d.Add(f)
  52. if err == nil {
  53. if expireTime != Permanent {
  54. go f.Expire()
  55. }
  56. }
  57. return err
  58. }
  59. func (fs *FileSystem) TestAndSet() {
  60. }
  61. func (fs *FileSystem) TestIndexAndSet() {
  62. }
  63. func (fs *FileSystem) Delete(path string, recurisive bool, index uint64, term uint64) error {
  64. n, err := fs.InternalGet(path, index, term)
  65. if err != nil {
  66. return err
  67. }
  68. return n.Remove(recurisive)
  69. }
  70. // walk function walks all the path and apply the walkFunc on each directory
  71. func (fs *FileSystem) walk(path string, walkFunc func(prev *Node, component string) (*Node, error)) (*Node, error) {
  72. components := strings.Split(path, "/")
  73. curr := fs.Root
  74. var err error
  75. for i := 1; i < len(components); i++ {
  76. if len(components[i]) == 0 { // ignore empty string
  77. return curr, nil
  78. }
  79. curr, err = walkFunc(curr, components[i])
  80. if err != nil {
  81. return nil, err
  82. }
  83. }
  84. return curr, nil
  85. }
  86. // checkDir function will check whether the component is a directory under parent node.
  87. // If it is a directory, this function will return the pointer to that node.
  88. // If it does not exist, this function will create a new directory and return the pointer to that node.
  89. // If it is a file, this function will return error.
  90. func (fs *FileSystem) checkDir(parent *Node, dirName string) (*Node, error) {
  91. subDir, ok := parent.Children[dirName]
  92. if ok {
  93. return subDir, nil
  94. }
  95. n := newDir(filepath.Join(parent.Path, dirName), fs.Index, fs.Term, parent, parent.ACL)
  96. parent.Children[dirName] = n
  97. return n, nil
  98. }