add simple support for kv scan

This commit is contained in:
siddontang 2014-05-23 11:44:50 +08:00
parent 7e88d0b563
commit 81a5587c99
3 changed files with 87 additions and 7 deletions

View File

@ -15,6 +15,10 @@ const (
zScoreType zScoreType
) )
const (
defaultScanCount int = 20
)
const ( const (
//we don't support too many databases //we don't support too many databases
MaxDBNumber uint8 = 16 MaxDBNumber uint8 = 16

View File

@ -35,6 +35,17 @@ func (db *DB) decodeKVKey(ek []byte) ([]byte, error) {
return ek[2:], nil return ek[2:], nil
} }
func (db *DB) encodeKVMinKey() []byte {
ek := db.encodeKVKey(nil)
return ek
}
func (db *DB) encodeKVMaxKey() []byte {
ek := db.encodeKVKey(nil)
ek[len(ek)-1] = kvType + 1
return ek
}
func (db *DB) incr(key []byte, delta int64) (int64, error) { func (db *DB) incr(key []byte, delta int64) (int64, error) {
if err := checkKeySize(key); err != nil { if err := checkKeySize(key); err != nil {
return 0, err return 0, err
@ -265,13 +276,8 @@ func (db *DB) KvFlush() (drop int64, err error) {
t.Lock() t.Lock()
defer t.Unlock() defer t.Unlock()
minKey := make([]byte, 2) minKey := db.encodeKVMinKey()
minKey[0] = db.index maxKey := db.encodeKVMaxKey()
minKey[1] = kvType
maxKey := make([]byte, 2)
maxKey[0] = db.index
maxKey[1] = kvType + 1
it := db.db.Iterator(minKey, maxKey, leveldb.RangeROpen, 0, -1) it := db.db.Iterator(minKey, maxKey, leveldb.RangeROpen, 0, -1)
for ; it.Valid(); it.Next() { for ; it.Valid(); it.Next() {
@ -282,3 +288,37 @@ func (db *DB) KvFlush() (drop int64, err error) {
err = t.Commit() err = t.Commit()
return return
} }
func (db *DB) Scan(cursor int, count int) ([]interface{}, error) {
minKey := db.encodeKVMinKey()
maxKey := db.encodeKVMaxKey()
if count <= 0 {
count = defaultScanCount
}
v := make([]interface{}, 2)
r := make([]interface{}, 0, count)
var num int = 0
it := db.db.Iterator(minKey, maxKey, leveldb.RangeROpen, cursor, count)
for ; it.Valid(); it.Next() {
num++
if key, err := db.decodeKVKey(it.Key()); err != nil {
continue
} else {
r = append(r, key)
}
}
if num < count {
v[0] = int64(0)
} else {
v[0] = int64(cursor + count)
}
v[1] = r
return v, nil
}

View File

@ -2,6 +2,7 @@ package server
import ( import (
"github.com/siddontang/ledisdb/ledis" "github.com/siddontang/ledisdb/ledis"
"strings"
) )
func getCommand(c *client) error { func getCommand(c *client) error {
@ -203,6 +204,40 @@ func mgetCommand(c *client) error {
return nil return nil
} }
func scanCommand(c *client) error {
args := c.args
if len(args) != 1 && len(args) != 3 {
return ErrCmdParams
}
var offset int64
var count int64
var err error
if offset, err = ledis.StrInt64(args[0], nil); err != nil {
return err
}
//now we only support count
if len(args) == 3 {
if strings.ToLower(ledis.String(args[1])) != "count" {
return ErrCmdParams
}
if count, err = ledis.StrInt64(args[2], nil); err != nil {
return err
}
}
if v, err := c.db.Scan(int(offset), int(count)); err != nil {
return err
} else {
c.writeArray(v)
}
return nil
}
func init() { func init() {
register("decr", decrCommand) register("decr", decrCommand)
register("decrby", decrbyCommand) register("decrby", decrbyCommand)
@ -216,4 +251,5 @@ func init() {
register("mset", msetCommand) register("mset", msetCommand)
register("set", setCommand) register("set", setCommand)
register("setnx", setnxCommand) register("setnx", setnxCommand)
register("scan", scanCommand)
} }