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.

80 lines
2.1 KiB

  1. package filer
  2. import (
  3. "bytes"
  4. "code.google.com/p/weed-fs/go/glog"
  5. "github.com/syndtr/goleveldb/leveldb"
  6. "github.com/syndtr/goleveldb/leveldb/util"
  7. )
  8. /*
  9. The entry in level db has this format:
  10. key: genKey(dirId, fileName)
  11. value: []byte(fid)
  12. And genKey(dirId, fileName) use first 4 bytes to store dirId, and rest for fileName
  13. */
  14. type FileListInLevelDb struct {
  15. db *leveldb.DB
  16. }
  17. func NewFileListInLevelDb(dir string) (fl *FileListInLevelDb, err error) {
  18. fl = &FileListInLevelDb{}
  19. if fl.db, err = leveldb.OpenFile(dir, nil); err != nil {
  20. return
  21. }
  22. return
  23. }
  24. func genKey(dirId DirectoryId, fileName string) []byte {
  25. ret := make([]byte, 0, 4+len(fileName))
  26. for i := 3; i >= 0; i-- {
  27. ret = append(ret, byte(dirId>>(uint(i)*8)))
  28. }
  29. ret = append(ret, []byte(fileName)...)
  30. return ret
  31. }
  32. func (fl *FileListInLevelDb) CreateFile(dirId DirectoryId, fileName string, fid string) (err error) {
  33. glog.V(4).Infoln("directory", dirId, "fileName", fileName, "fid", fid)
  34. return fl.db.Put(genKey(dirId, fileName), []byte(fid), nil)
  35. }
  36. func (fl *FileListInLevelDb) DeleteFile(dirId DirectoryId, fileName string) (fid string, err error) {
  37. if fid, err = fl.FindFile(dirId, fileName); err != nil {
  38. return
  39. }
  40. err = fl.db.Delete(genKey(dirId, fileName), nil)
  41. return fid, err
  42. }
  43. func (fl *FileListInLevelDb) FindFile(dirId DirectoryId, fileName string) (fid string, err error) {
  44. data, e := fl.db.Get(genKey(dirId, fileName), nil)
  45. if e != nil {
  46. return "", e
  47. }
  48. return string(data), nil
  49. }
  50. func (fl *FileListInLevelDb) ListFiles(dirId DirectoryId, lastFileName string, limit int) (files []FileEntry) {
  51. glog.V(4).Infoln("directory", dirId, "lastFileName", lastFileName, "limit", limit)
  52. dirKey := genKey(dirId, "")
  53. iter := fl.db.NewIterator(&util.Range{Start: genKey(dirId, lastFileName)}, nil)
  54. limitCounter := 0
  55. for iter.Next() {
  56. key := iter.Key()
  57. if !bytes.HasPrefix(key, dirKey) {
  58. break
  59. }
  60. fileName := string(key[len(dirKey):])
  61. if fileName == lastFileName {
  62. continue
  63. }
  64. limitCounter++
  65. if limit > 0 {
  66. if limitCounter > limit {
  67. break
  68. }
  69. }
  70. files = append(files, FileEntry{Name: fileName, Id: FileId(string(iter.Value()))})
  71. }
  72. iter.Release()
  73. return
  74. }