aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--weed/filer2/configuration.go6
-rw-r--r--weed/filer2/redis/redis_store.go172
-rw-r--r--weed/server/filer_server.go1
3 files changed, 179 insertions, 0 deletions
diff --git a/weed/filer2/configuration.go b/weed/filer2/configuration.go
index 0112a883b..16c0f3fd0 100644
--- a/weed/filer2/configuration.go
+++ b/weed/filer2/configuration.go
@@ -74,6 +74,12 @@ hosts=[
"localhost:9042",
]
+[redis]
+enabled = true
+address = "localhost:6379"
+password = ""
+db = 0
+
`
)
diff --git a/weed/filer2/redis/redis_store.go b/weed/filer2/redis/redis_store.go
new file mode 100644
index 000000000..cb8381bf5
--- /dev/null
+++ b/weed/filer2/redis/redis_store.go
@@ -0,0 +1,172 @@
+package redis
+
+import (
+ "fmt"
+ "github.com/chrislusf/seaweedfs/weed/filer2"
+ "github.com/chrislusf/seaweedfs/weed/glog"
+ "github.com/spf13/viper"
+ "github.com/go-redis/redis"
+ "sort"
+ "strings"
+)
+
+const (
+ DIR_LIST_MARKER = "\x00"
+)
+
+func init() {
+ filer2.Stores = append(filer2.Stores, &RedisStore{})
+}
+
+type RedisStore struct {
+ Client *redis.Client
+}
+
+func (store *RedisStore) GetName() string {
+ return "redis"
+}
+
+func (store *RedisStore) Initialize(viper *viper.Viper) (err error) {
+ return store.initialize(
+ viper.GetString("address"),
+ viper.GetString("password"),
+ viper.GetInt("database"),
+ )
+}
+
+func (store *RedisStore) initialize(hostPort string, password string, database int) (err error) {
+ store.Client = redis.NewClient(&redis.Options{
+ Addr: hostPort,
+ Password: password,
+ DB: database,
+ })
+ return
+}
+
+func (store *RedisStore) InsertEntry(entry *filer2.Entry) (err error) {
+
+ value, err := entry.EncodeAttributesAndChunks()
+ if err != nil {
+ return fmt.Errorf("encoding %s %+v: %v", entry.FullPath, entry.Attr, err)
+ }
+
+ _, err = store.Client.Set(string(entry.FullPath), value, 0).Result()
+
+ if err != nil {
+ return fmt.Errorf("persisting %s : %v", entry.FullPath, err)
+ }
+
+ dir, name := entry.FullPath.DirAndName()
+ if name != "" {
+ _, err = store.Client.SAdd(genDirectoryListKey(dir), name).Result()
+ if err != nil {
+ return fmt.Errorf("persisting %s in parent dir: %v", entry.FullPath, err)
+ }
+ }
+
+ return nil
+}
+
+func (store *RedisStore) UpdateEntry(entry *filer2.Entry) (err error) {
+
+ return store.InsertEntry(entry)
+}
+
+func (store *RedisStore) FindEntry(fullpath filer2.FullPath) (entry *filer2.Entry, err error) {
+
+ data, err := store.Client.Get(string(fullpath)).Result()
+ if err == redis.Nil {
+ return nil, filer2.ErrNotFound
+ }
+
+ if err != nil {
+ return nil, fmt.Errorf("get %s : %v", entry.FullPath, err)
+ }
+
+ entry = &filer2.Entry{
+ FullPath: fullpath,
+ }
+ err = entry.DecodeAttributesAndChunks([]byte(data))
+ if err != nil {
+ return entry, fmt.Errorf("decode %s : %v", entry.FullPath, err)
+ }
+
+ return entry, nil
+}
+
+func (store *RedisStore) DeleteEntry(fullpath filer2.FullPath) (entry *filer2.Entry, err error) {
+
+ entry, err = store.FindEntry(fullpath)
+ if err != nil {
+ return nil, nil
+ }
+
+ _, err = store.Client.Del(string(fullpath)).Result()
+
+ if err != nil {
+ return entry, fmt.Errorf("delete %s : %v", entry.FullPath, err)
+ }
+
+ dir, name := fullpath.DirAndName()
+ if name != "" {
+ _, err = store.Client.SRem(genDirectoryListKey(dir), name).Result()
+ if err != nil {
+ return nil, fmt.Errorf("delete %s in parent dir: %v", entry.FullPath, err)
+ }
+ }
+
+ return entry, nil
+}
+
+func (store *RedisStore) ListDirectoryEntries(fullpath filer2.FullPath, startFileName string, inclusive bool,
+ limit int) (entries []*filer2.Entry, err error) {
+
+ members, err := store.Client.SMembers(genDirectoryListKey(string(fullpath))).Result()
+ if err != nil {
+ return nil, fmt.Errorf("list %s : %v", fullpath, err)
+ }
+
+ // skip
+ if startFileName != "" {
+ var t []string
+ for _, m := range members {
+ if strings.Compare(m, startFileName) >= 0 {
+ if m == startFileName {
+ if inclusive {
+ t = append(t, m)
+ }
+ } else {
+ t = append(t, m)
+ }
+ }
+ }
+ members = t
+ }
+
+ // sort
+ sort.Slice(members, func(i, j int) bool {
+ return strings.Compare(members[i], members[j]) < 0
+ })
+
+ // limit
+ if limit < len(members) {
+ members = members[:limit]
+ }
+
+ // fetch entry meta
+ for _, fileName := range members {
+ path := filer2.NewFullPath(string(fullpath), fileName)
+ entry, err := store.FindEntry(path)
+ if err != nil {
+ glog.V(0).Infof("list %s : %v", path, err)
+ } else {
+ entries = append(entries, entry)
+ }
+ }
+
+ return entries, err
+}
+
+func genDirectoryListKey(dir string) (dirList string) {
+ return dir + DIR_LIST_MARKER
+}
diff --git a/weed/server/filer_server.go b/weed/server/filer_server.go
index 6c8a2c079..012b0afbf 100644
--- a/weed/server/filer_server.go
+++ b/weed/server/filer_server.go
@@ -17,6 +17,7 @@ import (
_ "github.com/chrislusf/seaweedfs/weed/filer2/memdb"
_ "github.com/chrislusf/seaweedfs/weed/filer2/mysql"
_ "github.com/chrislusf/seaweedfs/weed/filer2/postgres"
+ _ "github.com/chrislusf/seaweedfs/weed/filer2/redis"
)
type FilerServer struct {