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.

141 lines
3.1 KiB

  1. package redis
  2. import (
  3. "fmt"
  4. "github.com/chrislusf/seaweedfs/weed/filer2"
  5. "github.com/chrislusf/seaweedfs/weed/glog"
  6. "github.com/go-redis/redis"
  7. "sort"
  8. "strings"
  9. )
  10. const (
  11. DIR_LIST_MARKER = "\x00"
  12. )
  13. type UniversalRedisStore struct {
  14. Client redis.UniversalClient
  15. }
  16. func (store *UniversalRedisStore) InsertEntry(entry *filer2.Entry) (err error) {
  17. value, err := entry.EncodeAttributesAndChunks()
  18. if err != nil {
  19. return fmt.Errorf("encoding %s %+v: %v", entry.FullPath, entry.Attr, err)
  20. }
  21. _, err = store.Client.Set(string(entry.FullPath), value, 0).Result()
  22. if err != nil {
  23. return fmt.Errorf("persisting %s : %v", entry.FullPath, err)
  24. }
  25. dir, name := entry.FullPath.DirAndName()
  26. if name != "" {
  27. _, err = store.Client.SAdd(genDirectoryListKey(dir), name).Result()
  28. if err != nil {
  29. return fmt.Errorf("persisting %s in parent dir: %v", entry.FullPath, err)
  30. }
  31. }
  32. return nil
  33. }
  34. func (store *UniversalRedisStore) UpdateEntry(entry *filer2.Entry) (err error) {
  35. return store.InsertEntry(entry)
  36. }
  37. func (store *UniversalRedisStore) FindEntry(fullpath filer2.FullPath) (entry *filer2.Entry, err error) {
  38. data, err := store.Client.Get(string(fullpath)).Result()
  39. if err == redis.Nil {
  40. return nil, filer2.ErrNotFound
  41. }
  42. if err != nil {
  43. return nil, fmt.Errorf("get %s : %v", fullpath, err)
  44. }
  45. entry = &filer2.Entry{
  46. FullPath: fullpath,
  47. }
  48. err = entry.DecodeAttributesAndChunks([]byte(data))
  49. if err != nil {
  50. return entry, fmt.Errorf("decode %s : %v", entry.FullPath, err)
  51. }
  52. return entry, nil
  53. }
  54. func (store *UniversalRedisStore) DeleteEntry(fullpath filer2.FullPath) (err error) {
  55. _, err = store.Client.Del(string(fullpath)).Result()
  56. if err != nil {
  57. return fmt.Errorf("delete %s : %v", fullpath, err)
  58. }
  59. dir, name := fullpath.DirAndName()
  60. if name != "" {
  61. _, err = store.Client.SRem(genDirectoryListKey(dir), name).Result()
  62. if err != nil {
  63. return fmt.Errorf("delete %s in parent dir: %v", fullpath, err)
  64. }
  65. }
  66. return nil
  67. }
  68. func (store *UniversalRedisStore) ListDirectoryEntries(fullpath filer2.FullPath, startFileName string, inclusive bool,
  69. limit int) (entries []*filer2.Entry, err error) {
  70. members, err := store.Client.SMembers(genDirectoryListKey(string(fullpath))).Result()
  71. if err != nil {
  72. return nil, fmt.Errorf("list %s : %v", fullpath, err)
  73. }
  74. // skip
  75. if startFileName != "" {
  76. var t []string
  77. for _, m := range members {
  78. if strings.Compare(m, startFileName) >= 0 {
  79. if m == startFileName {
  80. if inclusive {
  81. t = append(t, m)
  82. }
  83. } else {
  84. t = append(t, m)
  85. }
  86. }
  87. }
  88. members = t
  89. }
  90. // sort
  91. sort.Slice(members, func(i, j int) bool {
  92. return strings.Compare(members[i], members[j]) < 0
  93. })
  94. // limit
  95. if limit < len(members) {
  96. members = members[:limit]
  97. }
  98. // fetch entry meta
  99. for _, fileName := range members {
  100. path := filer2.NewFullPath(string(fullpath), fileName)
  101. entry, err := store.FindEntry(path)
  102. if err != nil {
  103. glog.V(0).Infof("list %s : %v", path, err)
  104. } else {
  105. entries = append(entries, entry)
  106. }
  107. }
  108. return entries, err
  109. }
  110. func genDirectoryListKey(dir string) (dirList string) {
  111. return dir + DIR_LIST_MARKER
  112. }