diff --git a/ledis/client.go b/ledis/client.go index 2a57c53..6b9b1ed 100644 --- a/ledis/client.go +++ b/ledis/client.go @@ -176,7 +176,7 @@ func (c *client) writeStatus(status string) { func (c *client) writeInteger(n int64) { c.wb.WriteByte(':') - c.wb.Write(Slice(strconv.FormatInt(n, 10))) + c.wb.Write(StrPutInt64(n)) c.wb.Write(Delims) } diff --git a/ledis/cmd_hash.go b/ledis/cmd_hash.go index 1e00854..1fe2c18 100644 --- a/ledis/cmd_hash.go +++ b/ledis/cmd_hash.go @@ -111,7 +111,17 @@ func hmsetCommand(c *client) error { return ErrCmdParams } - if err := c.db.HMset(args[0], args[1:]); err != nil { + key := args[0] + + args = args[1:] + + kvs := make([]FVPair, len(args)/2) + for i := 0; i < len(kvs); i++ { + kvs[i].Field = args[2*i] + kvs[i].Value = args[2*i+1] + } + + if err := c.db.HMset(key, kvs...); err != nil { return err } else { c.writeStatus(OK) diff --git a/ledis/cmd_kv.go b/ledis/cmd_kv.go index 877b5b5..b41f853 100644 --- a/ledis/cmd_kv.go +++ b/ledis/cmd_kv.go @@ -152,7 +152,7 @@ func delCommand(c *client) error { return ErrCmdParams } - if n, err := c.db.Del(args); err != nil { + if n, err := c.db.Del(args...); err != nil { return err } else { c.writeInteger(n) @@ -167,7 +167,13 @@ func msetCommand(c *client) error { return ErrCmdParams } - if err := c.db.MSet(args); err != nil { + kvs := make([]KVPair, len(args)/2) + for i := 0; i < len(kvs); i++ { + kvs[i].Key = args[2*i] + kvs[i].Value = args[2*i+1] + } + + if err := c.db.MSet(kvs...); err != nil { return err } else { c.writeStatus(OK) @@ -186,7 +192,7 @@ func mgetCommand(c *client) error { return ErrCmdParams } - if v, err := c.db.MGet(args); err != nil { + if v, err := c.db.MGet(args...); err != nil { return err } else { c.writeArray(v) diff --git a/ledis/cmd_list.go b/ledis/cmd_list.go index 213d432..18847ef 100644 --- a/ledis/cmd_list.go +++ b/ledis/cmd_list.go @@ -8,7 +8,7 @@ func lpushCommand(c *client) error { return ErrCmdParams } - if n, err := c.db.LPush(args[0], args[1:]); err != nil { + if n, err := c.db.LPush(args[0], args[1:]...); err != nil { return err } else { c.writeInteger(n) @@ -23,7 +23,7 @@ func rpushCommand(c *client) error { return ErrCmdParams } - if n, err := c.db.RPush(args[0], args[1:]); err != nil { + if n, err := c.db.RPush(args[0], args[1:]...); err != nil { return err } else { c.writeInteger(n) diff --git a/ledis/cmd_zset.go b/ledis/cmd_zset.go index 9e21be1..f30f8de 100644 --- a/ledis/cmd_zset.go +++ b/ledis/cmd_zset.go @@ -23,18 +23,19 @@ func zaddCommand(c *client) error { } args = args[1:] - params := make([]interface{}, len(args)) - for i := 0; i < len(params); i += 2 { - score, err := StrInt64(args[i], nil) + + params := make([]ScorePair, len(args)/2) + for i := 0; i < len(params); i++ { + score, err := StrInt64(args[2*i], nil) if err != nil { return err } - params[i] = score - params[i+1] = args[i+1] + params[i].Score = score + params[i].Member = args[2*i+1] } - if n, err := c.db.ZAdd(key, params); err != nil { + if n, err := c.db.ZAdd(key, params...); err != nil { return err } else { c.writeInteger(n) @@ -79,7 +80,7 @@ func zremCommand(c *client) error { return ErrCmdParams } - if n, err := c.db.ZRem(args[0], args[1:]); err != nil { + if n, err := c.db.ZRem(args[0], args[1:]...); err != nil { return err } else { c.writeInteger(n) diff --git a/ledis/t_hash.go b/ledis/t_hash.go index daedfc2..7ed6914 100644 --- a/ledis/t_hash.go +++ b/ledis/t_hash.go @@ -6,6 +6,11 @@ import ( "github.com/siddontang/go-leveldb/leveldb" ) +type FVPair struct { + Field []byte + Value []byte +} + var errHashKey = errors.New("invalid hash key") var errHSizeKey = errors.New("invalid hsize key") @@ -129,19 +134,19 @@ func (db *DB) HGet(key []byte, field []byte) ([]byte, error) { return db.db.Get(encode_hash_key(key, field)) } -func (db *DB) HMset(key []byte, args [][]byte) error { +func (db *DB) HMset(key []byte, args ...FVPair) error { t := db.hashTx t.Lock() defer t.Unlock() var num int64 = 0 - for i := 0; i < len(args); i += 2 { - ek := encode_hash_key(key, args[i]) + for i := 0; i < len(args); i++ { + ek := encode_hash_key(key, args[i].Field) if v, _ := db.db.Get(ek); v == nil { num++ } - t.Put(ek, args[i+1]) + t.Put(ek, args[i].Value) } if _, err := db.hIncrSize(key, num); err != nil { diff --git a/ledis/t_kv.go b/ledis/t_kv.go index b4c27f9..f30af86 100644 --- a/ledis/t_kv.go +++ b/ledis/t_kv.go @@ -4,6 +4,11 @@ import ( "errors" ) +type KVPair struct { + Key []byte + Value []byte +} + var errKVKey = errors.New("invalid encode kv key") func encode_kv_key(key []byte) []byte { @@ -54,7 +59,11 @@ func (db *DB) DecrBy(key []byte, decrement int64) (int64, error) { return db.incr(key, -decrement) } -func (db *DB) Del(keys [][]byte) (int64, error) { +func (db *DB) Del(keys ...[]byte) (int64, error) { + if len(keys) == 0 { + return 0, nil + } + for i := range keys { keys[i] = encode_kv_key(keys[i]) } @@ -121,7 +130,7 @@ func (db *DB) IncryBy(key []byte, increment int64) (int64, error) { return db.incr(key, increment) } -func (db *DB) MGet(keys [][]byte) ([]interface{}, error) { +func (db *DB) MGet(keys ...[]byte) ([]interface{}, error) { values := make([]interface{}, len(keys)) for i := range keys { @@ -137,15 +146,19 @@ func (db *DB) MGet(keys [][]byte) ([]interface{}, error) { return values, nil } -func (db *DB) MSet(args [][]byte) error { +func (db *DB) MSet(args ...KVPair) error { + if len(args) == 0 { + return nil + } + t := db.kvTx t.Lock() defer t.Unlock() - for i := 0; i < len(args); i += 2 { - key := encode_kv_key(args[i]) - value := args[i+1] + for i := 0; i < len(args); i++ { + key := encode_kv_key(args[i].Key) + value := args[i].Value t.Put(key, value) diff --git a/ledis/t_list.go b/ledis/t_list.go index 270331f..ab65c82 100644 --- a/ledis/t_list.go +++ b/ledis/t_list.go @@ -70,12 +70,18 @@ func decode_list_key(ek []byte) (key []byte, seq int32, err error) { return } -func (db *DB) lpush(key []byte, args [][]byte, whereSeq int32) (int64, error) { +func (db *DB) lpush(key []byte, whereSeq int32, args ...[]byte) (int64, error) { + metaKey := encode_lmeta_key(key) + + if len(args) == 0 { + _, _, size, err := db.lGetMeta(metaKey) + return int64(size), err + } + t := db.listTx t.Lock() defer t.Unlock() - metaKey := encode_lmeta_key(key) headSeq, tailSeq, size, err := db.lGetMeta(metaKey) if err != nil { @@ -234,8 +240,8 @@ func (db *DB) LPop(key []byte) ([]byte, error) { return db.lpop(key, listHeadSeq) } -func (db *DB) LPush(key []byte, args [][]byte) (int64, error) { - return db.lpush(key, args, listHeadSeq) +func (db *DB) LPush(key []byte, args ...[]byte) (int64, error) { + return db.lpush(key, listHeadSeq, args...) } func (db *DB) LRange(key []byte, start int32, stop int32) ([]interface{}, error) { @@ -286,8 +292,8 @@ func (db *DB) RPop(key []byte) ([]byte, error) { return db.lpop(key, listTailSeq) } -func (db *DB) RPush(key []byte, args [][]byte) (int64, error) { - return db.lpush(key, args, listTailSeq) +func (db *DB) RPush(key []byte, args ...[]byte) (int64, error) { + return db.lpush(key, listTailSeq, args...) } func (db *DB) LClear(key []byte) (int64, error) { diff --git a/ledis/t_zset.go b/ledis/t_zset.go index b46d397..a7b305e 100644 --- a/ledis/t_zset.go +++ b/ledis/t_zset.go @@ -5,7 +5,6 @@ import ( "encoding/binary" "errors" "github.com/siddontang/go-leveldb/leveldb" - "strconv" ) const ( @@ -13,6 +12,11 @@ const ( MaxScore int64 = 1<<63 - 1 ) +type ScorePair struct { + Score int64 + Member []byte +} + var errZSizeKey = errors.New("invalid zsize key") var errZSetKey = errors.New("invalid zset key") var errZScoreKey = errors.New("invalid zscore key") @@ -207,15 +211,19 @@ func (db *DB) zDelItem(key []byte, member []byte, skipDelScore bool) (int64, err return 1, nil } -func (db *DB) ZAdd(key []byte, args []interface{}) (int64, error) { +func (db *DB) ZAdd(key []byte, args ...ScorePair) (int64, error) { + if len(args) == 0 { + return 0, nil + } + t := db.zsetTx t.Lock() defer t.Unlock() var num int64 = 0 - for i := 0; i < len(args); i += 2 { - score := args[i].(int64) - member := args[i+1].([]byte) + for i := 0; i < len(args); i++ { + score := args[i].Score + member := args[i].Member if n, err := db.zSetItem(key, score, member); err != nil { return 0, err @@ -266,17 +274,21 @@ func (db *DB) ZScore(key []byte, member []byte) ([]byte, error) { return nil, err } - return Slice(strconv.FormatInt(score, 10)), nil + return StrPutInt64(score), nil } -func (db *DB) ZRem(key []byte, args [][]byte) (int64, error) { +func (db *DB) ZRem(key []byte, members ...[]byte) (int64, error) { + if len(members) == 0 { + return 0, nil + } + t := db.zsetTx t.Lock() defer t.Unlock() var num int64 = 0 - for i := 0; i < len(args); i++ { - if n, err := db.zDelItem(key, args[i], false); err != nil { + for i := 0; i < len(members); i++ { + if n, err := db.zDelItem(key, members[i], false); err != nil { return 0, err } else if n == 1 { num++ @@ -323,7 +335,7 @@ func (db *DB) ZIncrBy(key []byte, delta int64, member []byte) ([]byte, error) { t.Put(encode_zscore_key(key, member, score), []byte{}) err = t.Commit() - return Slice(strconv.FormatInt(score, 10)), err + return StrPutInt64(score), err } func (db *DB) ZCount(key []byte, min int64, max int64) (int64, error) { @@ -479,7 +491,7 @@ func (db *DB) zRange(key []byte, min int64, max int64, withScores bool, offset i v = append(v, m) if withScores { - v = append(v, Slice(strconv.FormatInt(s, 10))) + v = append(v, StrPutInt64(s)) } } diff --git a/ledis/util.go b/ledis/util.go index a5a1289..9140a52 100644 --- a/ledis/util.go +++ b/ledis/util.go @@ -63,5 +63,5 @@ func StrInt64(v []byte, err error) (int64, error) { } func StrPutInt64(v int64) []byte { - return Slice(strconv.FormatInt(v, 10)) + return strconv.AppendInt(nil, v, 10) }