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.

157 lines
3.6 KiB

  1. package weed_server
  2. import (
  3. "code.google.com/p/weed-fs/go/glog"
  4. "errors"
  5. "github.com/syndtr/goleveldb/leveldb"
  6. "github.com/syndtr/goleveldb/leveldb/util"
  7. "net/http"
  8. "strings"
  9. )
  10. /*
  11. 1. level db is only for local instance
  12. 2. db stores two types of pairs
  13. <path/to/dir, sub folder names>
  14. <path/to/file, file id>
  15. So, to list a directory, just get the directory entry, and iterate the current directory files
  16. Care must be taken to maintain the <dir, sub dirs> and <file, fileid> pairs.
  17. 3.
  18. */
  19. type FilerServer struct {
  20. port string
  21. master string
  22. collection string
  23. db *leveldb.DB
  24. }
  25. func NewFilerServer(r *http.ServeMux, master string, dir string) (fs *FilerServer, err error) {
  26. fs = &FilerServer{
  27. master: master,
  28. collection: "",
  29. port: ":8888",
  30. }
  31. if fs.db, err = leveldb.OpenFile(dir, nil); err != nil {
  32. return
  33. }
  34. r.HandleFunc("/", fs.filerHandler)
  35. glog.V(0).Infoln("file server started on port ", fs.port)
  36. return fs, nil
  37. }
  38. func (fs *FilerServer) CreateFile(fullFileName string, fid string) (err error) {
  39. fs.ensureFileFolder(fullFileName)
  40. return fs.db.Put([]byte(fullFileName), []byte(fid), nil)
  41. }
  42. func (fs *FilerServer) FindFile(fullFileName string) (fid string, err error) {
  43. return fs.findEntry(fullFileName)
  44. }
  45. func (fs *FilerServer) ListDirectories(fullpath string) (dirs []string, err error) {
  46. data, e := fs.db.Get([]byte(fullpath), nil)
  47. if e != nil {
  48. return nil, e
  49. }
  50. return strings.Split(string(data), ":"), nil
  51. }
  52. func (fs *FilerServer) ListFiles(fullpath string, start, limit int) (files []string) {
  53. if !strings.HasSuffix(fullpath, "/") {
  54. fullpath += "/"
  55. }
  56. iter := fs.db.NewIterator(&util.Range{Start: []byte(fullpath)}, nil)
  57. startCounter, limitCounter := -1, 0
  58. for iter.Next() {
  59. startCounter++
  60. if startCounter < start {
  61. continue
  62. }
  63. limitCounter++
  64. if limit > 0 {
  65. if limitCounter > limit {
  66. break
  67. }
  68. }
  69. key := string(iter.Key())
  70. if !strings.HasPrefix(key, fullpath) {
  71. break
  72. }
  73. fileName := key[len(fullpath):]
  74. if strings.Contains(fileName, "/") {
  75. break
  76. }
  77. files = append(files, fileName)
  78. }
  79. iter.Release()
  80. return
  81. }
  82. func (fs *FilerServer) Delete(fullpath string, isForceDirectoryRemoval bool) (fid string, isFile bool, err error) {
  83. val, e := fs.findEntry(fullpath)
  84. if e != nil {
  85. return "", false, e
  86. }
  87. if strings.Contains(val, ",") {
  88. return val, true, fs.db.Delete([]byte(fullpath), nil)
  89. }
  90. // deal with directory
  91. if !strings.HasSuffix(fullpath, "/") {
  92. fullpath += "/"
  93. }
  94. iter := fs.db.NewIterator(&util.Range{Start: []byte(fullpath)}, nil)
  95. counter := 0
  96. for iter.Next() {
  97. counter++
  98. if counter > 0 {
  99. break
  100. }
  101. }
  102. iter.Release()
  103. if counter > 0 {
  104. return "", false, errors.New("Force Deletion Not Supported Yet")
  105. }
  106. return "", false, fs.db.Delete([]byte(fullpath), nil)
  107. }
  108. func (fs *FilerServer) findEntry(fullpath string) (value string, err error) {
  109. data, e := fs.db.Get([]byte(fullpath), nil)
  110. if e != nil {
  111. return "", e
  112. }
  113. return string(data), nil
  114. }
  115. func (fs *FilerServer) ensureFileFolder(fullFileName string) (err error) {
  116. parts := strings.Split(fullFileName, "/")
  117. path := "/"
  118. for i := 1; i < len(parts)-1; i++ {
  119. sub := parts[i]
  120. if sub == "" {
  121. continue
  122. }
  123. if err = fs.ensureFolderHasEntry(path, sub); err != nil {
  124. return
  125. }
  126. path = path + sub + "/"
  127. }
  128. return nil
  129. }
  130. func (fs *FilerServer) ensureFolderHasEntry(path string, sub string) (err error) {
  131. val, e := fs.findEntry(path)
  132. if e == leveldb.ErrNotFound {
  133. return fs.db.Put([]byte(path), []byte(sub), nil)
  134. } else if e != nil {
  135. return e
  136. }
  137. for _, v := range strings.Split(val, ":") {
  138. if v == sub {
  139. return nil
  140. }
  141. }
  142. return fs.db.Put([]byte(path), []byte(val+":"+sub), nil)
  143. }