working on List
parent
6ac77d247e
commit
ade973d19d
19
bolt.go
19
bolt.go
|
|
@ -13,6 +13,25 @@ func NewBolt(path string) (*Bolt, error) {
|
||||||
}, err
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Bolt) List(ns []string, limits ...string) ([]string, error) {
|
||||||
|
namespace := resolveNamespace(ns)
|
||||||
|
limits = resolveLimits(limits)
|
||||||
|
found := []string{}
|
||||||
|
err := b.db.View(func(tx *bolt.Tx) error {
|
||||||
|
bucket := tx.Bucket([]byte(namespace))
|
||||||
|
if bucket == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
c := bucket.Cursor()
|
||||||
|
for k, _ := c.Seek([]byte(limits[0])); k != nil; k, _ = c.Next() {
|
||||||
|
found = append(found, string(k))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return found, err
|
||||||
|
}
|
||||||
|
|
||||||
func (b *Bolt) Get(key string, ns ...string) ([]byte, error) {
|
func (b *Bolt) Get(key string, ns ...string) ([]byte, error) {
|
||||||
namespace := resolveNamespace(ns)
|
namespace := resolveNamespace(ns)
|
||||||
var result []byte
|
var result []byte
|
||||||
|
|
|
||||||
5
cache.go
5
cache.go
|
|
@ -1,6 +1,7 @@
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -25,6 +26,10 @@ func NewCache(path ...string) (*Cache, error) {
|
||||||
return c, err
|
return c, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Cache) List(ns []string, limits ...string) ([]string, error) {
|
||||||
|
return nil, errors.New("not impl")
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Cache) Get(key string, ns ...string) ([]byte, error) {
|
func (c *Cache) Get(key string, ns ...string) ([]byte, error) {
|
||||||
namespace := resolveNamespace(ns)
|
namespace := resolveNamespace(ns)
|
||||||
v, ok := c.db.Get(path.Join(namespace, key))
|
v, ok := c.db.Get(path.Join(namespace, key))
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"local/args"
|
||||||
|
"local/storage"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
as := args.NewArgSet()
|
||||||
|
as.Append(args.STRING, "addr", "addr of store", "")
|
||||||
|
as.Append(args.STRING, "db", "type of store", "map")
|
||||||
|
as.Append(args.STRING, "user", "user of store", "")
|
||||||
|
as.Append(args.STRING, "pass", "pass of store", "")
|
||||||
|
as.Append(args.STRING, "do", "[get set]", "get")
|
||||||
|
as.Append(args.STRING, "k", "key", "key")
|
||||||
|
as.Append(args.STRING, "v", "value", "value")
|
||||||
|
if err := as.Parse(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
db, err := storage.New(
|
||||||
|
storage.TypeFromString(as.Get("db").GetString()),
|
||||||
|
as.Get("addr").GetString(),
|
||||||
|
as.Get("user").GetString(),
|
||||||
|
as.Get("pass").GetString(),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
var b []byte
|
||||||
|
switch strings.ToLower(as.Get("do").GetString()) {
|
||||||
|
case "get":
|
||||||
|
b, err = db.Get(as.Get("k").GetString())
|
||||||
|
case "set":
|
||||||
|
err = db.Set(as.Get("k").GetString(), []byte(as.Get("v").GetString()))
|
||||||
|
case "cli":
|
||||||
|
reader := bufio.NewReader(os.Stdin)
|
||||||
|
for {
|
||||||
|
fmt.Print("> ")
|
||||||
|
line, err := reader.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
s := strings.Split(line, " ")
|
||||||
|
s[len(s)-1] = strings.TrimSpace(s[len(s)-1])
|
||||||
|
for len(s) < 3 {
|
||||||
|
s = append(s, "")
|
||||||
|
}
|
||||||
|
start := time.Now()
|
||||||
|
switch strings.ToLower(s[0]) {
|
||||||
|
case "get":
|
||||||
|
b, err := db.Get(s[1])
|
||||||
|
stop := time.Now()
|
||||||
|
log.Printf("(%v) %v: %s => %s", stop.Sub(start), err, s[1], b)
|
||||||
|
case "set":
|
||||||
|
err := db.Set(s[1], []byte(s[2]))
|
||||||
|
stop := time.Now()
|
||||||
|
log.Printf("(%v) %v: %s", stop.Sub(start), err, s[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.Fatal("-do not in [get set]")
|
||||||
|
}
|
||||||
|
stop := time.Now()
|
||||||
|
log.Printf("(%v) %v: %s", stop.Sub(start), err, b)
|
||||||
|
}
|
||||||
16
db.go
16
db.go
|
|
@ -8,6 +8,7 @@ import (
|
||||||
type DB interface {
|
type DB interface {
|
||||||
Get(string, ...string) ([]byte, error)
|
Get(string, ...string) ([]byte, error)
|
||||||
Set(string, []byte, ...string) error
|
Set(string, []byte, ...string) error
|
||||||
|
List([]string, ...string) ([]string, error)
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,3 +58,18 @@ func resolveNamespace(ns []string) string {
|
||||||
}
|
}
|
||||||
return namespace
|
return namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func resolveLimits(input []string) []string {
|
||||||
|
output := []string{"", ""}
|
||||||
|
if len(input) > 0 {
|
||||||
|
output[0] = input[0]
|
||||||
|
} else {
|
||||||
|
output[0] = " "
|
||||||
|
}
|
||||||
|
if len(input) > 1 {
|
||||||
|
output[1] = input[1]
|
||||||
|
} else {
|
||||||
|
output[1] = "}}}}}}}}}}}}}"
|
||||||
|
}
|
||||||
|
return output[:]
|
||||||
|
}
|
||||||
|
|
|
||||||
16
db_test.go
16
db_test.go
|
|
@ -15,6 +15,14 @@ type mock struct {
|
||||||
m map[string][]byte
|
m map[string][]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mock *mock) List(ns []string, limits ...string) ([]string, error) {
|
||||||
|
keys := []string{}
|
||||||
|
for k := range mock.m {
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
return keys, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (mock *mock) Get(key string, ns ...string) ([]byte, error) {
|
func (mock *mock) Get(key string, ns ...string) ([]byte, error) {
|
||||||
namespace := resolveNamespace(ns)
|
namespace := resolveNamespace(ns)
|
||||||
v, ok := mock.m[path.Join(namespace, key)]
|
v, ok := mock.m[path.Join(namespace, key)]
|
||||||
|
|
@ -143,6 +151,14 @@ func TestImplementations(t *testing.T) {
|
||||||
t.Errorf("cannot get %T: %v", db, err)
|
t.Errorf("cannot get %T: %v", db, err)
|
||||||
} else if !bytes.Equal(v, validValue) {
|
} else if !bytes.Equal(v, validValue) {
|
||||||
t.Errorf("wrong get %T: %q vs %q", db, v, validValue)
|
t.Errorf("wrong get %T: %q vs %q", db, v, validValue)
|
||||||
|
} else if keys, err := db.List(nil); err != nil || len(keys) < 1 {
|
||||||
|
t.Errorf("cannot List(): %v", err)
|
||||||
|
} else if keys[0] != validKey {
|
||||||
|
t.Errorf("List()[0] != %s: %s", validKey, keys[0])
|
||||||
|
} else if keys, err := db.List(nil, validKey[:1]); err != nil || len(keys) < 1 {
|
||||||
|
t.Errorf("cannot List(prefix): %v", err)
|
||||||
|
} else if keys[0] != validKey {
|
||||||
|
t.Errorf("List(prefix)[0] != %s: %s", validKey, keys[0])
|
||||||
} else {
|
} else {
|
||||||
t.Logf("%25T GET: %s", db, v)
|
t.Logf("%25T GET: %s", db, v)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
13
leveldb.go
13
leveldb.go
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/syndtr/goleveldb/leveldb"
|
"github.com/syndtr/goleveldb/leveldb"
|
||||||
"github.com/syndtr/goleveldb/leveldb/filter"
|
"github.com/syndtr/goleveldb/leveldb/filter"
|
||||||
"github.com/syndtr/goleveldb/leveldb/opt"
|
"github.com/syndtr/goleveldb/leveldb/opt"
|
||||||
|
"github.com/syndtr/goleveldb/leveldb/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LevelDB struct {
|
type LevelDB struct {
|
||||||
|
|
@ -21,6 +22,18 @@ func NewLevelDB(path string) (*LevelDB, error) {
|
||||||
}, err
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ldb *LevelDB) List(ns []string, limits ...string) ([]string, error) {
|
||||||
|
keys := []string{}
|
||||||
|
r := util.BytesPrefix([]byte{})
|
||||||
|
it := ldb.db.NewIterator(r, nil)
|
||||||
|
defer it.Release()
|
||||||
|
for it.Next() {
|
||||||
|
keys = append(keys, string(it.Key()))
|
||||||
|
}
|
||||||
|
err := it.Error()
|
||||||
|
return keys, err
|
||||||
|
}
|
||||||
|
|
||||||
func (ldb *LevelDB) Get(key string, ns ...string) ([]byte, error) {
|
func (ldb *LevelDB) Get(key string, ns ...string) ([]byte, error) {
|
||||||
namespace := resolveNamespace(ns)
|
namespace := resolveNamespace(ns)
|
||||||
snapshot, err := ldb.db.GetSnapshot()
|
snapshot, err := ldb.db.GetSnapshot()
|
||||||
|
|
|
||||||
5
map.go
5
map.go
|
|
@ -1,6 +1,7 @@
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -28,6 +29,10 @@ func (m *Map) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Map) List(ns []string, limits ...string) ([]string, error) {
|
||||||
|
return nil, errors.New("not impl")
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Map) Get(key string, ns ...string) ([]byte, error) {
|
func (m *Map) Get(key string, ns ...string) ([]byte, error) {
|
||||||
namespace := resolveNamespace(ns)
|
namespace := resolveNamespace(ns)
|
||||||
if _, ok := (*m)[namespace]; !ok {
|
if _, ok := (*m)[namespace]; !ok {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
|
|
@ -47,6 +48,10 @@ func NewMemcache(addr string, addrs ...string) (*Memcache, error) {
|
||||||
return &Memcache{db: db}, nil
|
return &Memcache{db: db}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mc *Memcache) List(ns []string, limits ...string) ([]string, error) {
|
||||||
|
return nil, errors.New("not impl")
|
||||||
|
}
|
||||||
|
|
||||||
func (mc *Memcache) Get(key string, ns ...string) ([]byte, error) {
|
func (mc *Memcache) Get(key string, ns ...string) ([]byte, error) {
|
||||||
namespace := resolveNamespace(ns)
|
namespace := resolveNamespace(ns)
|
||||||
v, err := mc.db.Get(path.Join(namespace, key))
|
v, err := mc.db.Get(path.Join(namespace, key))
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
|
|
@ -69,6 +70,10 @@ func NewMemcacheCluster(addr string, addrs ...string) (*MemcacheCluster, error)
|
||||||
return &MemcacheCluster{db: db}, nil
|
return &MemcacheCluster{db: db}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mc *MemcacheCluster) List(ns []string, limits ...string) ([]string, error) {
|
||||||
|
return nil, errors.New("not impl")
|
||||||
|
}
|
||||||
|
|
||||||
func (mc *MemcacheCluster) Get(key string, ns ...string) ([]byte, error) {
|
func (mc *MemcacheCluster) Get(key string, ns ...string) ([]byte, error) {
|
||||||
namespace := resolveNamespace(ns)
|
namespace := resolveNamespace(ns)
|
||||||
v, err := mc.db.Get(path.Join(namespace, key))
|
v, err := mc.db.Get(path.Join(namespace, key))
|
||||||
|
|
|
||||||
5
minio.go
5
minio.go
|
|
@ -2,6 +2,7 @@ package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
|
@ -17,6 +18,10 @@ func NewMinio(addr, user, pass string) (*Minio, error) {
|
||||||
return &Minio{db: db}, err
|
return &Minio{db: db}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Minio) List(ns []string, limits ...string) ([]string, error) {
|
||||||
|
return nil, errors.New("not impl")
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Minio) Get(key string, ns ...string) ([]byte, error) {
|
func (m *Minio) Get(key string, ns ...string) ([]byte, error) {
|
||||||
namespace := resolveNamespace(ns)
|
namespace := resolveNamespace(ns)
|
||||||
obj, err := m.db.GetObject(namespace, key, minio.GetObjectOptions{})
|
obj, err := m.db.GetObject(namespace, key, minio.GetObjectOptions{})
|
||||||
|
|
|
||||||
5
mongo.go
5
mongo.go
|
|
@ -2,6 +2,7 @@ package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -53,6 +54,10 @@ func NewMongo(addr string, auth ...string) (*Mongo, error) {
|
||||||
return &Mongo{db: db}, nil
|
return &Mongo{db: db}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mg *Mongo) List(ns []string, limits ...string) ([]string, error) {
|
||||||
|
return nil, errors.New("not impl")
|
||||||
|
}
|
||||||
|
|
||||||
func (mg *Mongo) Get(key string, ns ...string) ([]byte, error) {
|
func (mg *Mongo) Get(key string, ns ...string) ([]byte, error) {
|
||||||
namespace := resolveNamespace(ns)
|
namespace := resolveNamespace(ns)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||||
|
|
|
||||||
6
redis.go
6
redis.go
|
|
@ -3,7 +3,6 @@ package storage
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gomodule/redigo/redis"
|
"github.com/gomodule/redigo/redis"
|
||||||
|
|
@ -33,9 +32,12 @@ func (m *Redis) Close() error {
|
||||||
return m.client.Close()
|
return m.client.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Redis) List(ns []string, limits ...string) ([]string, error) {
|
||||||
|
return nil, errors.New("not impl")
|
||||||
|
}
|
||||||
|
|
||||||
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 = resolveNamespace(append(ns, key))
|
||||||
log.Println(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
|
||||||
|
|
|
||||||
6
riak.go
6
riak.go
|
|
@ -1,6 +1,8 @@
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
riak "github.com/basho/riak-go-client"
|
riak "github.com/basho/riak-go-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -28,6 +30,10 @@ func NewRiak(addr string, addrs ...string) (*Riak, error) {
|
||||||
}, err
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Riak) List(ns []string, limits ...string) ([]string, error) {
|
||||||
|
return nil, errors.New("not impl")
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Riak) Get(key string, ns ...string) ([]byte, error) {
|
func (r *Riak) Get(key string, ns ...string) ([]byte, error) {
|
||||||
namespace := resolveNamespace(ns)
|
namespace := resolveNamespace(ns)
|
||||||
obj := &riak.Object{}
|
obj := &riak.Object{}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue