move resolve into package

master
Bel LaPointe 2021-02-21 12:39:15 -06:00
parent ff8b908ee7
commit 7f2d451ca4
15 changed files with 205 additions and 175 deletions

14
bolt.go
View File

@ -1,6 +1,10 @@
package storage package storage
import "github.com/boltdb/bolt" import (
"local/storage/resolve"
"github.com/boltdb/bolt"
)
type Bolt struct { type Bolt struct {
db *bolt.DB db *bolt.DB
@ -14,8 +18,8 @@ func NewBolt(path string) (*Bolt, error) {
} }
func (b *Bolt) List(ns []string, limits ...string) ([]string, error) { func (b *Bolt) List(ns []string, limits ...string) ([]string, error) {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
limits = resolveLimits(limits) limits = resolve.Limits(limits)
found := []string{} found := []string{}
err := b.db.View(func(tx *bolt.Tx) error { err := b.db.View(func(tx *bolt.Tx) error {
bucket := tx.Bucket([]byte(namespace)) bucket := tx.Bucket([]byte(namespace))
@ -33,7 +37,7 @@ func (b *Bolt) List(ns []string, limits ...string) ([]string, error) {
} }
func (b *Bolt) Get(key string, ns ...string) ([]byte, error) { func (b *Bolt) Get(key string, ns ...string) ([]byte, error) {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
var result []byte var result []byte
err := b.db.View(func(tx *bolt.Tx) error { err := b.db.View(func(tx *bolt.Tx) error {
bkt := tx.Bucket([]byte(namespace)) bkt := tx.Bucket([]byte(namespace))
@ -50,7 +54,7 @@ func (b *Bolt) Get(key string, ns ...string) ([]byte, error) {
} }
func (b *Bolt) Set(key string, value []byte, ns ...string) error { func (b *Bolt) Set(key string, value []byte, ns ...string) error {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
return b.db.Update(func(tx *bolt.Tx) error { return b.db.Update(func(tx *bolt.Tx) error {
bkt, err := tx.CreateBucketIfNotExists([]byte(namespace)) bkt, err := tx.CreateBucketIfNotExists([]byte(namespace))
if err != nil { if err != nil {

View File

@ -1,6 +1,7 @@
package storage package storage
import ( import (
"local/storage/resolve"
"os" "os"
"path" "path"
"strings" "strings"
@ -27,8 +28,8 @@ func NewCache(path ...string) (*Cache, error) {
} }
func (c *Cache) List(ns []string, limits ...string) ([]string, error) { func (c *Cache) List(ns []string, limits ...string) ([]string, error) {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
limits = resolveLimits(limits) limits = resolve.Limits(limits)
limits[0] = path.Join(namespace, limits[0]) limits[0] = path.Join(namespace, limits[0])
limits[1] = path.Join(namespace, limits[1]) limits[1] = path.Join(namespace, limits[1])
m := c.db.Items() m := c.db.Items()
@ -42,7 +43,7 @@ func (c *Cache) List(ns []string, limits ...string) ([]string, error) {
} }
func (c *Cache) Get(key string, ns ...string) ([]byte, error) { func (c *Cache) Get(key string, ns ...string) ([]byte, error) {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
v, ok := c.db.Get(path.Join(namespace, key)) v, ok := c.db.Get(path.Join(namespace, key))
if !ok { if !ok {
return nil, ErrNotFound return nil, ErrNotFound
@ -55,7 +56,7 @@ func (c *Cache) Get(key string, ns ...string) ([]byte, error) {
} }
func (c *Cache) Set(key string, value []byte, ns ...string) error { func (c *Cache) Set(key string, value []byte, ns ...string) error {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
c.db.Set(path.Join(namespace, key), value, 0) c.db.Set(path.Join(namespace, key), value, 0)
return nil return nil
} }

51
db.go
View File

@ -3,8 +3,6 @@ package storage
import ( import (
"fmt" "fmt"
"io" "io"
"strconv"
"strings"
) )
type DBStream interface { type DBStream interface {
@ -60,52 +58,3 @@ func New(key Type, params ...string) (db DB, err error) {
} }
return return
} }
func resolveNamespace(ns []string) string {
namespace := DefaultNamespace
if len(ns) > 0 {
segments := []string{}
for i := range ns {
if ns[i] != "" {
segments = append(segments, ns[i])
}
}
namespace = strings.Join(segments, ".")
}
return namespace
}
func resolveLimits(input []string) []string {
return []string{
resolveLimitsStart(input),
resolveLimitsStop(input),
resolveLimitsLimit(input),
resolveLimitsAscending(input),
}
}
func resolveLimitsStart(input []string) string {
if len(input) > 0 {
return input[0]
}
return " "
}
func resolveLimitsStop(input []string) string {
if len(input) > 1 {
return input[1]
}
return "}}}}}}"
}
func resolveLimitsLimit(input []string) string {
if len(input) > 2 {
v, _ := strconv.Atoi(input[2])
return strconv.Itoa(v)
}
return "0"
}
func resolveLimitsAscending(input []string) string {
return strconv.FormatBool(len(input) < 4 || input[3] != "-")
}

View File

@ -3,6 +3,7 @@ package storage
import ( import (
"bytes" "bytes"
"io/ioutil" "io/ioutil"
"local/storage/resolve"
"log" "log"
"net" "net"
"os" "os"
@ -17,8 +18,8 @@ type mock struct {
} }
func (mock *mock) List(ns []string, limits ...string) ([]string, error) { func (mock *mock) List(ns []string, limits ...string) ([]string, error) {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
limits = resolveLimits(limits) limits = resolve.Limits(limits)
keys := []string{} keys := []string{}
for k := range mock.m { for k := range mock.m {
if k >= limits[0] && k <= limits[1] { if k >= limits[0] && k <= limits[1] {
@ -29,7 +30,7 @@ func (mock *mock) List(ns []string, limits ...string) ([]string, error) {
} }
func (mock *mock) Get(key string, ns ...string) ([]byte, error) { func (mock *mock) Get(key string, ns ...string) ([]byte, error) {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
v, ok := mock.m[path.Join(namespace, key)] v, ok := mock.m[path.Join(namespace, key)]
if ok { if ok {
return v, nil return v, nil
@ -38,7 +39,7 @@ func (mock *mock) Get(key string, ns ...string) ([]byte, error) {
} }
func (mock *mock) Set(key string, value []byte, ns ...string) error { func (mock *mock) Set(key string, value []byte, ns ...string) error {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
mock.m[path.Join(namespace, key)] = value mock.m[path.Join(namespace, key)] = value
return nil return nil
} }
@ -313,77 +314,3 @@ func recoverDeferred(c Type, t *testing.T, wg *sync.WaitGroup) {
} }
defer wg.Done() defer wg.Done()
} }
func TestResolveLimitsStart(t *testing.T) {
cases := map[string]struct {
in string
out string
}{
"explicit": {in: "no", out: "no"},
}
for name, c := range cases {
input := strings.Split(c.in, ",")
out := resolveLimitsStart(input)
if out != c.out {
t.Errorf("%v: got %v, want %v from %v", name, out, c.out, c.in)
}
}
}
func TestResolveLimitsStop(t *testing.T) {
cases := map[string]struct {
in string
out string
}{
"short arr": {in: "", out: "}}}}}}"},
"explicit": {in: ",no", out: "no"},
}
for name, c := range cases {
input := strings.Split(c.in, ",")
out := resolveLimitsStop(input)
if out != c.out {
t.Errorf("%v: got %v, want %v from %v", name, out, c.out, c.in)
}
}
}
func TestResolveLimitsLimit(t *testing.T) {
cases := map[string]struct {
in string
out string
}{
"15": {in: ",,15", out: "15"},
"0 set": {in: ",,0", out: "0"},
"0 default": {in: ",,", out: "0"},
}
for name, c := range cases {
input := strings.Split(c.in, ",")
out := resolveLimitsLimit(input)
if out != c.out {
t.Errorf("%v: got %v, want %v from %v", name, out, c.out, c.in)
}
}
}
func TestResolveLimitsAscending(t *testing.T) {
cases := map[string]struct {
in string
out string
}{
"desc": {in: "a,b,c,-", out: "false"},
"asc": {in: "a,b,c,+", out: "true"},
"default asc prev": {in: "a,b,c,", out: "true"},
"default asc empty": {in: ",,,", out: "true"},
}
for name, c := range cases {
input := strings.Split(c.in, ",")
out := resolveLimitsAscending(input)
if out != c.out {
t.Errorf("%v: got %v, want %v from %v", name, out, c.out, c.in)
}
}
}

View File

@ -4,6 +4,8 @@ import (
"bytes" "bytes"
"io" "io"
"io/ioutil" "io/ioutil"
"local/storage/resolve"
"log"
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
@ -29,7 +31,7 @@ func NewFiles(root string) (*Files, error) {
} }
func (b *Files) List(ns []string, limits ...string) ([]string, error) { func (b *Files) List(ns []string, limits ...string) ([]string, error) {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
files := make([]string, 0) files := make([]string, 0)
err := filepath.Walk(b.root, func(p string, info os.FileInfo, err error) error { err := filepath.Walk(b.root, func(p string, info os.FileInfo, err error) error {
if err != nil { if err != nil {
@ -46,7 +48,7 @@ func (b *Files) List(ns []string, limits ...string) ([]string, error) {
}) })
return files, err return files, err
/* /*
limits = resolveLimits(limits) limits = resolve.Limits(limits)
*/ */
} }
@ -59,12 +61,13 @@ func (b *Files) Get(key string, ns ...string) ([]byte, error) {
} }
func (b *Files) GetStream(key string, ns ...string) (io.Reader, error) { func (b *Files) GetStream(key string, ns ...string) (io.Reader, error) {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
path := path.Join(b.root, namespace, key) path := path.Join(b.root, namespace, key)
return os.Open(path) return os.Open(path)
} }
func (b *Files) Set(key string, value []byte, ns ...string) error { func (b *Files) Set(key string, value []byte, ns ...string) error {
log.Println("files.Set", ns, key, "to", len(value), value == nil)
r := bytes.NewReader(value) r := bytes.NewReader(value)
if value == nil { if value == nil {
r = nil r = nil
@ -73,10 +76,12 @@ func (b *Files) Set(key string, value []byte, ns ...string) error {
} }
func (b *Files) SetStream(key string, r io.Reader, ns ...string) error { func (b *Files) SetStream(key string, r io.Reader, ns ...string) error {
namespace := resolveNamespace(ns) log.Println("files.SetStream", ns, key, "to", r, r == nil)
namespace := resolve.Namespace(ns)
dir := path.Join(b.root, namespace) dir := path.Join(b.root, namespace)
path := path.Join(dir, key)
if r == nil { if r == nil {
err := os.Remove(path.Join(dir, key)) err := os.Remove(path)
if os.IsNotExist(err) { if os.IsNotExist(err) {
err = nil err = nil
} }
@ -85,7 +90,6 @@ func (b *Files) SetStream(key string, r io.Reader, ns ...string) error {
if err := os.MkdirAll(dir, os.ModePerm); err != nil { if err := os.MkdirAll(dir, os.ModePerm); err != nil {
return err return err
} }
path := path.Join(dir, key)
f, err := os.Create(path) f, err := os.Create(path)
if err != nil { if err != nil {
return err return err

View File

@ -1,6 +1,7 @@
package storage package storage
import ( import (
"local/storage/resolve"
"path" "path"
"strconv" "strconv"
"strings" "strings"
@ -39,7 +40,7 @@ func NewLevelDB(path string) (*LevelDB, error) {
} }
func (ldb *LevelDB) Get(key string, ns ...string) ([]byte, error) { func (ldb *LevelDB) Get(key string, ns ...string) ([]byte, error) {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
snapshot, err := ldb.db.GetSnapshot() snapshot, err := ldb.db.GetSnapshot()
if err != nil { if err != nil {
return nil, err return nil, err
@ -57,7 +58,7 @@ func (ldb *LevelDB) Get(key string, ns ...string) ([]byte, error) {
} }
func (ldb *LevelDB) Set(key string, value []byte, ns ...string) error { func (ldb *LevelDB) Set(key string, value []byte, ns ...string) error {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
key = path.Join(namespace, key) key = path.Join(namespace, key)
batch := &leveldb.Batch{} batch := &leveldb.Batch{}
if value != nil { if value != nil {
@ -73,8 +74,8 @@ func (ldb *LevelDB) Close() error {
} }
func (ldb *LevelDB) List(ns []string, limits ...string) ([]string, error) { func (ldb *LevelDB) List(ns []string, limits ...string) ([]string, error) {
namespace := path.Join(resolveNamespace(ns)) namespace := path.Join(resolve.Namespace(ns))
limits = resolveLimits(limits) limits = resolve.Limits(limits)
it, next := ldb.getIterator(namespace, limits) it, next := ldb.getIterator(namespace, limits)
defer it.Release() defer it.Release()
keys := ldb.useIterator(it, next, namespace, limits) keys := ldb.useIterator(it, next, namespace, limits)
@ -99,7 +100,7 @@ func (ldb *LevelDB) getIterator(namespace string, limits []string) (iterator.Ite
} }
func (ldb *LevelDB) useIterator(it iterator.Iterator, next func() bool, namespace string, limits []string) []string { func (ldb *LevelDB) useIterator(it iterator.Iterator, next func() bool, namespace string, limits []string) []string {
limits = resolveLimits(limits) limits = resolve.Limits(limits)
n, _ := strconv.Atoi(limits[2]) n, _ := strconv.Atoi(limits[2])
m := 0 m := 0

9
map.go
View File

@ -2,6 +2,7 @@ package storage
import ( import (
"fmt" "fmt"
"local/storage/resolve"
"sync" "sync"
) )
@ -40,8 +41,8 @@ func (m *Map) Close() error {
func (m *Map) List(ns []string, limits ...string) ([]string, error) { func (m *Map) List(ns []string, limits ...string) ([]string, error) {
m.lock.RLock() m.lock.RLock()
defer m.lock.RUnlock() defer m.lock.RUnlock()
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
limits = resolveLimits(limits) limits = resolve.Limits(limits)
keys := []string{} keys := []string{}
if _, ok := m.m[namespace]; !ok { if _, ok := m.m[namespace]; !ok {
@ -59,7 +60,7 @@ func (m *Map) List(ns []string, limits ...string) ([]string, error) {
func (m *Map) Get(key string, ns ...string) ([]byte, error) { func (m *Map) Get(key string, ns ...string) ([]byte, error) {
m.lock.RLock() m.lock.RLock()
defer m.lock.RUnlock() defer m.lock.RUnlock()
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
if _, ok := m.m[namespace]; !ok { if _, ok := m.m[namespace]; !ok {
return nil, ErrNotFound return nil, ErrNotFound
} }
@ -72,7 +73,7 @@ func (m *Map) Get(key string, ns ...string) ([]byte, error) {
func (m *Map) Set(key string, value []byte, ns ...string) error { func (m *Map) Set(key string, value []byte, ns ...string) error {
m.lock.Lock() m.lock.Lock()
defer m.lock.Unlock() defer m.lock.Unlock()
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
if value == nil { if value == nil {
if _, ok := m.m[namespace]; !ok { if _, ok := m.m[namespace]; !ok {
return nil return nil

View File

@ -2,6 +2,7 @@ package storage
import ( import (
"errors" "errors"
"local/storage/resolve"
"net" "net"
"path" "path"
@ -53,7 +54,7 @@ func (mc *Memcache) List(ns []string, limits ...string) ([]string, error) {
} }
func (mc *Memcache) Get(key string, ns ...string) ([]byte, error) { func (mc *Memcache) Get(key string, ns ...string) ([]byte, error) {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
v, err := mc.db.Get(path.Join(namespace, key)) v, err := mc.db.Get(path.Join(namespace, key))
if err != nil { if err != nil {
return nil, err return nil, err
@ -65,7 +66,7 @@ func (mc *Memcache) Get(key string, ns ...string) ([]byte, error) {
} }
func (mc *Memcache) Set(key string, value []byte, ns ...string) error { func (mc *Memcache) Set(key string, value []byte, ns ...string) error {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
return mc.db.Set(&memcache.Item{ return mc.db.Set(&memcache.Item{
Key: path.Join(namespace, key), Key: path.Join(namespace, key),
Value: value, Value: value,

View File

@ -2,6 +2,7 @@ package storage
import ( import (
"errors" "errors"
"local/storage/resolve"
"net" "net"
"path" "path"
@ -75,13 +76,13 @@ func (mc *MemcacheCluster) List(ns []string, limits ...string) ([]string, error)
} }
func (mc *MemcacheCluster) Get(key string, ns ...string) ([]byte, error) { func (mc *MemcacheCluster) Get(key string, ns ...string) ([]byte, error) {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
v, err := mc.db.Get(path.Join(namespace, key)) v, err := mc.db.Get(path.Join(namespace, key))
return v.Value, err return v.Value, err
} }
func (mc *MemcacheCluster) Set(key string, value []byte, ns ...string) error { func (mc *MemcacheCluster) Set(key string, value []byte, ns ...string) error {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
return mc.db.Set(&memcache.Item{ return mc.db.Set(&memcache.Item{
Key: path.Join(namespace, key), Key: path.Join(namespace, key),
Value: value, Value: value,

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"local/storage/resolve"
"net/url" "net/url"
"sort" "sort"
"strings" "strings"
@ -27,8 +28,8 @@ func NewMinio(addr, user, pass string) (*Minio, error) {
} }
func (m *Minio) List(ns []string, limits ...string) ([]string, error) { func (m *Minio) List(ns []string, limits ...string) ([]string, error) {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
limits = resolveLimits(limits) limits = resolve.Limits(limits)
done := make(chan struct{}) done := make(chan struct{})
defer close(done) defer close(done)
keys := []string{} keys := []string{}
@ -51,7 +52,7 @@ func (m *Minio) List(ns []string, limits ...string) ([]string, error) {
} }
func (m *Minio) Get(key string, ns ...string) ([]byte, error) { func (m *Minio) Get(key string, ns ...string) ([]byte, error) {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
obj, err := m.db.GetObject(namespace, key, minio.GetObjectOptions{}) obj, err := m.db.GetObject(namespace, key, minio.GetObjectOptions{})
if err == nil { if err == nil {
var stat minio.ObjectInfo var stat minio.ObjectInfo
@ -68,7 +69,7 @@ func (m *Minio) Get(key string, ns ...string) ([]byte, error) {
} }
func (m *Minio) Set(key string, value []byte, ns ...string) error { func (m *Minio) Set(key string, value []byte, ns ...string) error {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
if ok, err := m.db.BucketExists(namespace); err != nil { if ok, err := m.db.BucketExists(namespace); err != nil {
return err return err
} else if !ok { } else if !ok {

View File

@ -3,6 +3,7 @@ package storage
import ( import (
"context" "context"
"errors" "errors"
"local/storage/resolve"
"strings" "strings"
"time" "time"
@ -55,8 +56,8 @@ func NewMongo(addr string, auth ...string) (*Mongo, error) {
} }
func (mg *Mongo) List(ns []string, limits ...string) ([]string, error) { func (mg *Mongo) List(ns []string, limits ...string) ([]string, error) {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
limits = resolveLimits(limits) limits = resolve.Limits(limits)
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel() defer cancel()
collection := mg.db.Database(DefaultNamespace).Collection(namespace) collection := mg.db.Database(DefaultNamespace).Collection(namespace)
@ -88,7 +89,7 @@ func (mg *Mongo) List(ns []string, limits ...string) ([]string, error) {
} }
func (mg *Mongo) Get(key string, ns ...string) ([]byte, error) { func (mg *Mongo) Get(key string, ns ...string) ([]byte, error) {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel() defer cancel()
collection := mg.db.Database(DefaultNamespace).Collection(namespace) collection := mg.db.Database(DefaultNamespace).Collection(namespace)
@ -118,7 +119,7 @@ func (mg *Mongo) Get(key string, ns ...string) ([]byte, error) {
} }
func (mg *Mongo) Set(key string, value []byte, ns ...string) error { func (mg *Mongo) Set(key string, value []byte, ns ...string) error {
namespace := resolveNamespace(ns) namespace := resolve.Namespace(ns)
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel() defer cancel()
collection := mg.db.Database(DefaultNamespace).Collection(namespace) collection := mg.db.Database(DefaultNamespace).Collection(namespace)

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"io" "io"
"io/ioutil" "io/ioutil"
"local/storage/resolve"
"os" "os"
"path" "path"
"time" "time"
@ -46,7 +47,7 @@ func (rc *RClone) Get(key string, ns ...string) ([]byte, error) {
func (rc *RClone) GetStream(key string, ns ...string) (io.Reader, error) { func (rc *RClone) GetStream(key string, ns ...string) (io.Reader, error) {
namespace := rc.ns namespace := rc.ns
if len(ns) > 0 { if len(ns) > 0 {
namespace = path.Join(rc.ns, resolveNamespace(ns)) namespace = path.Join(rc.ns, resolve.Namespace(ns))
} }
key = path.Join(namespace, key) key = path.Join(namespace, key)
@ -71,7 +72,7 @@ func (rc *RClone) Set(key string, value []byte, ns ...string) error {
func (rc *RClone) SetStream(key string, r io.Reader, ns ...string) error { func (rc *RClone) SetStream(key string, r io.Reader, ns ...string) error {
namespace := rc.ns namespace := rc.ns
if len(ns) > 0 { if len(ns) > 0 {
namespace = path.Join(rc.ns, resolveNamespace(ns)) namespace = path.Join(rc.ns, resolve.Namespace(ns))
} }
key = path.Join(namespace, key) key = path.Join(namespace, key)
@ -87,7 +88,7 @@ func (rc *RClone) SetStream(key string, r io.Reader, ns ...string) error {
func (rc *RClone) Del(key string, ns ...string) error { func (rc *RClone) Del(key string, ns ...string) error {
namespace := rc.ns namespace := rc.ns
if len(ns) > 0 { if len(ns) > 0 {
namespace = path.Join(rc.ns, resolveNamespace(ns)) namespace = path.Join(rc.ns, resolve.Namespace(ns))
} }
key = path.Join(namespace, key) key = path.Join(namespace, key)
@ -112,9 +113,9 @@ func (rc *RClone) Close() error {
func (rc *RClone) List(ns []string, limits ...string) ([]string, error) { func (rc *RClone) List(ns []string, limits ...string) ([]string, error) {
namespace := rc.ns namespace := rc.ns
if len(ns) > 0 { if len(ns) > 0 {
namespace = path.Join(rc.ns, resolveNamespace(ns)) namespace = path.Join(rc.ns, resolve.Namespace(ns))
} }
limits = resolveLimits(limits) limits = resolve.Limits(limits)
f, err := fs.NewFs(namespace) f, err := fs.NewFs(namespace)
if err != nil { if err != nil {

View File

@ -3,6 +3,7 @@ package storage
import ( import (
"errors" "errors"
"fmt" "fmt"
"local/storage/resolve"
"time" "time"
"github.com/gomodule/redigo/redis" "github.com/gomodule/redigo/redis"
@ -33,9 +34,9 @@ func (m *Redis) Close() error {
} }
func (m *Redis) List(ns []string, limits ...string) ([]string, error) { func (m *Redis) List(ns []string, limits ...string) ([]string, error) {
limits = resolveLimits(limits) limits = resolve.Limits(limits)
limits[0] = resolveNamespace(append(ns, limits[0])) limits[0] = resolve.Namespace(append(ns, limits[0]))
limits[1] = resolveNamespace(append(ns, limits[1])) limits[1] = resolve.Namespace(append(ns, limits[1]))
resp, err := m.client.Do("KEYS", "*") resp, err := m.client.Do("KEYS", "*")
if err != nil { if err != nil {
@ -65,7 +66,7 @@ func (m *Redis) List(ns []string, limits ...string) ([]string, error) {
} }
func (m *Redis) Get(key string, ns ...string) ([]byte, error) { func (m *Redis) Get(key string, ns ...string) ([]byte, error) {
key = resolveNamespace(append(ns, key)) key = resolve.Namespace(append(ns, key))
resp, err := m.client.Do("GET", key) resp, err := m.client.Do("GET", key)
if err != nil { if err != nil {
return nil, err return nil, err
@ -81,7 +82,7 @@ func (m *Redis) Get(key string, ns ...string) ([]byte, error) {
} }
func (m *Redis) Set(key string, value []byte, ns ...string) error { func (m *Redis) Set(key string, value []byte, ns ...string) error {
namespace := resolveNamespace(append(ns, key)) namespace := resolve.Namespace(append(ns, key))
_, err := m.client.Do("SET", namespace, value) _, err := m.client.Do("SET", namespace, value)
return err return err
} }

57
resolve/resolve.go Executable file
View File

@ -0,0 +1,57 @@
package resolve
import (
"strconv"
"strings"
)
var DefaultNamespace = "namespace"
func Namespace(ns []string) string {
namespace := DefaultNamespace
if len(ns) > 0 {
segments := []string{}
for i := range ns {
if ns[i] != "" {
segments = append(segments, ns[i])
}
}
namespace = strings.Join(segments, ".")
}
return namespace
}
func Limits(input []string) []string {
return []string{
LimitsStart(input),
LimitsStop(input),
LimitsLimit(input),
LimitsAscending(input),
}
}
func LimitsStart(input []string) string {
if len(input) > 0 {
return input[0]
}
return " "
}
func LimitsStop(input []string) string {
if len(input) > 1 {
return input[1]
}
return "}}}}}}"
}
func LimitsLimit(input []string) string {
if len(input) > 2 {
v, _ := strconv.Atoi(input[2])
return strconv.Itoa(v)
}
return "0"
}
func LimitsAscending(input []string) string {
return strconv.FormatBool(len(input) < 4 || input[3] != "-")
}

80
resolve/resolve_test.go Executable file
View File

@ -0,0 +1,80 @@
package resolve
import (
"strings"
"testing"
)
func TestResolveLimitsStart(t *testing.T) {
cases := map[string]struct {
in string
out string
}{
"explicit": {in: "no", out: "no"},
}
for name, c := range cases {
input := strings.Split(c.in, ",")
out := LimitsStart(input)
if out != c.out {
t.Errorf("%v: got %v, want %v from %v", name, out, c.out, c.in)
}
}
}
func TestResolveLimitsStop(t *testing.T) {
cases := map[string]struct {
in string
out string
}{
"short arr": {in: "", out: "}}}}}}"},
"explicit": {in: ",no", out: "no"},
}
for name, c := range cases {
input := strings.Split(c.in, ",")
out := LimitsStop(input)
if out != c.out {
t.Errorf("%v: got %v, want %v from %v", name, out, c.out, c.in)
}
}
}
func TestResolveLimitsLimit(t *testing.T) {
cases := map[string]struct {
in string
out string
}{
"15": {in: ",,15", out: "15"},
"0 set": {in: ",,0", out: "0"},
"0 default": {in: ",,", out: "0"},
}
for name, c := range cases {
input := strings.Split(c.in, ",")
out := LimitsLimit(input)
if out != c.out {
t.Errorf("%v: got %v, want %v from %v", name, out, c.out, c.in)
}
}
}
func TestResolveLimitsAscending(t *testing.T) {
cases := map[string]struct {
in string
out string
}{
"desc": {in: "a,b,c,-", out: "false"},
"asc": {in: "a,b,c,+", out: "true"},
"default asc prev": {in: "a,b,c,", out: "true"},
"default asc empty": {in: ",,,", out: "true"},
}
for name, c := range cases {
input := strings.Split(c.in, ",")
out := LimitsAscending(input)
if out != c.out {
t.Errorf("%v: got %v, want %v from %v", name, out, c.out, c.in)
}
}
}