diff --git a/ledis/t_hash.go b/ledis/t_hash.go index 5186c04..1478a21 100644 --- a/ledis/t_hash.go +++ b/ledis/t_hash.go @@ -232,13 +232,13 @@ func (db *DB) HMset(key []byte, args ...FVPair) error { return err } -func (db *DB) HMget(key []byte, args ...[]byte) ([]interface{}, error) { +func (db *DB) HMget(key []byte, args ...[]byte) ([][]byte, error) { var ek []byte it := db.db.NewIterator() defer it.Close() - r := make([]interface{}, len(args)) + r := make([][]byte, len(args)) for i := 0; i < len(args); i++ { if err := checkHashKFSize(key, args[i]); err != nil { return nil, err @@ -344,7 +344,7 @@ func (db *DB) HIncrBy(key []byte, field []byte, delta int64) (int64, error) { return n, err } -func (db *DB) HGetAll(key []byte) ([]interface{}, error) { +func (db *DB) HGetAll(key []byte) ([]FVPair, error) { if err := checkKeySize(key); err != nil { return nil, err } @@ -352,16 +352,16 @@ func (db *DB) HGetAll(key []byte) ([]interface{}, error) { start := db.hEncodeStartKey(key) stop := db.hEncodeStopKey(key) - v := make([]interface{}, 0, 16) + v := make([]FVPair, 0, 16) it := db.db.RangeLimitIterator(start, stop, leveldb.RangeROpen, 0, -1) for ; it.Valid(); it.Next() { - _, k, err := db.hDecodeHashKey(it.Key()) + _, f, err := db.hDecodeHashKey(it.Key()) if err != nil { return nil, err } - v = append(v, k) - v = append(v, it.Value()) + + v = append(v, FVPair{Field: f, Value: it.Value()}) } it.Close() @@ -369,7 +369,7 @@ func (db *DB) HGetAll(key []byte) ([]interface{}, error) { return v, nil } -func (db *DB) HKeys(key []byte) ([]interface{}, error) { +func (db *DB) HKeys(key []byte) ([][]byte, error) { if err := checkKeySize(key); err != nil { return nil, err } @@ -377,15 +377,15 @@ func (db *DB) HKeys(key []byte) ([]interface{}, error) { start := db.hEncodeStartKey(key) stop := db.hEncodeStopKey(key) - v := make([]interface{}, 0, 16) + v := make([][]byte, 0, 16) it := db.db.RangeLimitIterator(start, stop, leveldb.RangeROpen, 0, -1) for ; it.Valid(); it.Next() { - _, k, err := db.hDecodeHashKey(it.Key()) + _, f, err := db.hDecodeHashKey(it.Key()) if err != nil { return nil, err } - v = append(v, k) + v = append(v, f) } it.Close() @@ -393,7 +393,7 @@ func (db *DB) HKeys(key []byte) ([]interface{}, error) { return v, nil } -func (db *DB) HValues(key []byte) ([]interface{}, error) { +func (db *DB) HValues(key []byte) ([][]byte, error) { if err := checkKeySize(key); err != nil { return nil, err } @@ -401,10 +401,15 @@ func (db *DB) HValues(key []byte) ([]interface{}, error) { start := db.hEncodeStartKey(key) stop := db.hEncodeStopKey(key) - v := make([]interface{}, 0, 16) + v := make([][]byte, 0, 16) it := db.db.RangeLimitIterator(start, stop, leveldb.RangeROpen, 0, -1) for ; it.Valid(); it.Next() { + _, _, err := db.hDecodeHashKey(it.Key()) + if err != nil { + return nil, err + } + v = append(v, it.Value()) } @@ -477,7 +482,7 @@ func (db *DB) HScan(key []byte, field []byte, count int, inclusive bool) ([]FVPa count = defaultScanCount } - v := make([]FVPair, 0, 2*count) + v := make([]FVPair, 0, count) rangeType := leveldb.RangeROpen if !inclusive { diff --git a/ledis/t_hash_test.go b/ledis/t_hash_test.go index a663c2e..b18a616 100644 --- a/ledis/t_hash_test.go +++ b/ledis/t_hash_test.go @@ -46,11 +46,11 @@ func TestDBHash(t *testing.T) { ay, _ := db.HMget(key, []byte("a"), []byte("b")) - if v1, _ := ay[0].([]byte); string(v1) != "hello world 1" { + if v1 := ay[0]; string(v1) != "hello world 1" { t.Fatal(string(v1)) } - if v2, _ := ay[1].([]byte); string(v2) != "hello world 2" { + if v2 := ay[1]; string(v2) != "hello world 2" { t.Fatal(string(v2)) } diff --git a/ledis/t_kv.go b/ledis/t_kv.go index 3008fb8..5d4c4fc 100644 --- a/ledis/t_kv.go +++ b/ledis/t_kv.go @@ -201,8 +201,8 @@ func (db *DB) IncryBy(key []byte, increment int64) (int64, error) { return db.incr(key, increment) } -func (db *DB) MGet(keys ...[]byte) ([]interface{}, error) { - values := make([]interface{}, len(keys)) +func (db *DB) MGet(keys ...[]byte) ([][]byte, error) { + values := make([][]byte, len(keys)) it := db.db.NewIterator() defer it.Close() diff --git a/ledis/t_kv_test.go b/ledis/t_kv_test.go index 9088bd1..6c5e7e0 100644 --- a/ledis/t_kv_test.go +++ b/ledis/t_kv_test.go @@ -33,11 +33,11 @@ func TestDBKV(t *testing.T) { ay, _ := db.MGet(key1, key2) - if v1, _ := ay[0].([]byte); string(v1) != "hello world 1" { + if v1 := ay[0]; string(v1) != "hello world 1" { t.Fatal(string(v1)) } - if v2, _ := ay[1].([]byte); string(v2) != "hello world 2" { + if v2 := ay[1]; string(v2) != "hello world 2" { t.Fatal(string(v2)) } diff --git a/ledis/t_list.go b/ledis/t_list.go index e5d2f42..1d3c91e 100644 --- a/ledis/t_list.go +++ b/ledis/t_list.go @@ -317,20 +317,20 @@ 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) { +func (db *DB) LRange(key []byte, start int32, stop int32) ([][]byte, error) { if err := checkKeySize(key); err != nil { return nil, err } - v := make([]interface{}, 0, 16) - var startSeq int32 var stopSeq int32 if start > stop { - return []interface{}{}, nil + return [][]byte{}, nil } + v := make([][]byte, 0, 16) + var headSeq int32 var tailSeq int32 var err error diff --git a/ledis/t_zset.go b/ledis/t_zset.go index a4ea355..681996b 100644 --- a/ledis/t_zset.go +++ b/ledis/t_zset.go @@ -534,38 +534,21 @@ func (db *DB) zRemRange(t *tx, key []byte, min int64, max int64, offset int, lim return num, nil } -func (db *DB) zReverse(s []interface{}, withScores bool) []interface{} { - if withScores { - for i, j := 0, len(s)-2; i < j; i, j = i+2, j-2 { - s[i], s[j] = s[j], s[i] - s[i+1], s[j+1] = s[j+1], s[i+1] - } - } else { - for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { - s[i], s[j] = s[j], s[i] - } - } - - return s -} - -func (db *DB) zRange(key []byte, min int64, max int64, withScores bool, offset int, limit int, reverse bool) ([]interface{}, error) { +func (db *DB) zRange(key []byte, min int64, max int64, offset int, limit int, reverse bool) ([]ScorePair, error) { if len(key) > MaxKeySize { return nil, errKeySize } if offset < 0 { - return []interface{}{}, nil + return []ScorePair{}, nil } nv := 64 if limit > 0 { nv = limit } - if withScores { - nv = 2 * nv - } - v := make([]interface{}, 0, nv) + + v := make([]ScorePair, 0, nv) var it *leveldb.RangeLimitIterator @@ -584,16 +567,14 @@ func (db *DB) zRange(key []byte, min int64, max int64, withScores bool, offset i continue } - if withScores { - v = append(v, m, s) - } else { - v = append(v, m) - } + v = append(v, ScorePair{Member: m, Score: s}) } it.Close() if reverse && (offset == 0 && limit < 0) { - v = db.zReverse(v, withScores) + for i, j := 0, len(v)-1; i < j; i, j = i+1, j-1 { + v[i], v[j] = v[j], v[i] + } } return v, nil @@ -650,15 +631,15 @@ func (db *DB) ZClear(key []byte) (int64, error) { return rmCnt, err } -func (db *DB) ZRange(key []byte, start int, stop int, withScores bool) ([]interface{}, error) { - return db.ZRangeGeneric(key, start, stop, withScores, false) +func (db *DB) ZRange(key []byte, start int, stop int) ([]ScorePair, error) { + return db.ZRangeGeneric(key, start, stop, false) } //min and max must be inclusive //if no limit, set offset = 0 and count = -1 func (db *DB) ZRangeByScore(key []byte, min int64, max int64, - withScores bool, offset int, count int) ([]interface{}, error) { - return db.ZRangeByScoreGeneric(key, min, max, withScores, offset, count, false) + offset int, count int) ([]ScorePair, error) { + return db.ZRangeByScoreGeneric(key, min, max, offset, count, false) } func (db *DB) ZRank(key []byte, member []byte) (int64, error) { @@ -699,8 +680,8 @@ func (db *DB) ZRemRangeByScore(key []byte, min int64, max int64) (int64, error) return rmCnt, err } -func (db *DB) ZRevRange(key []byte, start int, stop int, withScores bool) ([]interface{}, error) { - return db.ZRangeGeneric(key, start, stop, withScores, true) +func (db *DB) ZRevRange(key []byte, start int, stop int) ([]ScorePair, error) { + return db.ZRangeGeneric(key, start, stop, true) } func (db *DB) ZRevRank(key []byte, member []byte) (int64, error) { @@ -709,27 +690,25 @@ func (db *DB) ZRevRank(key []byte, member []byte) (int64, error) { //min and max must be inclusive //if no limit, set offset = 0 and count = -1 -func (db *DB) ZRevRangeByScore(key []byte, min int64, max int64, - withScores bool, offset int, count int) ([]interface{}, error) { - return db.ZRangeByScoreGeneric(key, min, max, withScores, offset, count, true) +func (db *DB) ZRevRangeByScore(key []byte, min int64, max int64, offset int, count int) ([]ScorePair, error) { + return db.ZRangeByScoreGeneric(key, min, max, offset, count, true) } -func (db *DB) ZRangeGeneric(key []byte, start int, stop int, - withScores bool, reverse bool) ([]interface{}, error) { +func (db *DB) ZRangeGeneric(key []byte, start int, stop int, reverse bool) ([]ScorePair, error) { offset, limit, err := db.zParseLimit(key, start, stop) if err != nil { return nil, err } - return db.zRange(key, MinScore, MaxScore, withScores, offset, limit, reverse) + return db.zRange(key, MinScore, MaxScore, offset, limit, reverse) } //min and max must be inclusive //if no limit, set offset = 0 and count = -1 func (db *DB) ZRangeByScoreGeneric(key []byte, min int64, max int64, - withScores bool, offset int, count int, reverse bool) ([]interface{}, error) { + offset int, count int, reverse bool) ([]ScorePair, error) { - return db.zRange(key, min, max, withScores, offset, count, reverse) + return db.zRange(key, min, max, offset, count, reverse) } func (db *DB) zFlush() (drop int64, err error) { diff --git a/ledis/t_zset_test.go b/ledis/t_zset_test.go index 2b637e6..4b08136 100644 --- a/ledis/t_zset_test.go +++ b/ledis/t_zset_test.go @@ -145,15 +145,13 @@ func TestZSetOrder(t *testing.T) { } } - if qMembs, err := db.ZRange(key, 0, endPos, false); err != nil { + if qMembs, err := db.ZRange(key, 0, endPos); err != nil { t.Fatal(err) } else if len(qMembs) != membCnt { t.Fatal(fmt.Sprintf("%d vs %d", len(qMembs), membCnt)) } else { for i := 0; i < membCnt; i++ { - if memb, ok := qMembs[i].([]byte); !ok { - t.Fatal(ok) - } else if string(memb) != membs[i] { + if string(qMembs[i].Member) != membs[i] { t.Fatal(fmt.Sprintf("[%s] vs [%s]", qMembs[i], membs[i])) } } @@ -182,7 +180,7 @@ func TestZSetOrder(t *testing.T) { t.Fatal(pos) } - if qMembs, err := db.ZRangeByScore(key, 999, 0XFFFF, false, 0, membCnt); err != nil { + if qMembs, err := db.ZRangeByScore(key, 999, 0XFFFF, 0, membCnt); err != nil { t.Fatal(err) } else if len(qMembs) != 1 { t.Fatal(len(qMembs)) @@ -203,12 +201,12 @@ func TestZSetOrder(t *testing.T) { t.Fatal(pos) } - if datas, _ := db.ZRange(key, 0, endPos, true); len(datas) != 12 { + if datas, _ := db.ZRange(key, 0, endPos); len(datas) != 6 { t.Fatal(len(datas)) } else { scores := []int64{0, 1, 2, 5, 6, 999} - for i := 1; i < len(datas); i += 2 { - if s, ok := datas[i].(int64); !ok || s != scores[(i-1)/2] { + for i := 0; i < len(datas); i++ { + if datas[i].Score != scores[i] { t.Fatal(fmt.Sprintf("[%d]=%d", i, datas[i])) } } diff --git a/server/client.go b/server/client.go index 21412a3..e2d6865 100644 --- a/server/client.go +++ b/server/client.go @@ -245,6 +245,62 @@ func (c *client) writeArray(ay []interface{}) { } } +func (c *client) writeSliceArray(ay [][]byte) { + c.wb.WriteByte('*') + if ay == nil { + c.wb.Write(NullArray) + c.wb.Write(Delims) + } else { + c.wb.Write(ledis.Slice(strconv.Itoa(len(ay)))) + c.wb.Write(Delims) + + for i := 0; i < len(ay); i++ { + c.writeBulk(ay[i]) + } + } +} + +func (c *client) writeFVPairArray(ay []ledis.FVPair) { + c.wb.WriteByte('*') + if ay == nil { + c.wb.Write(NullArray) + c.wb.Write(Delims) + } else { + c.wb.Write(ledis.Slice(strconv.Itoa(len(ay) * 2))) + c.wb.Write(Delims) + + for i := 0; i < len(ay); i++ { + c.writeBulk(ay[i].Field) + c.writeBulk(ay[i].Value) + } + } +} + +func (c *client) writeScorePairArray(ay []ledis.ScorePair, withScores bool) { + c.wb.WriteByte('*') + if ay == nil { + c.wb.Write(NullArray) + c.wb.Write(Delims) + } else { + if withScores { + c.wb.Write(ledis.Slice(strconv.Itoa(len(ay) * 2))) + c.wb.Write(Delims) + } else { + c.wb.Write(ledis.Slice(strconv.Itoa(len(ay)))) + c.wb.Write(Delims) + + } + + for i := 0; i < len(ay); i++ { + c.writeBulk(ay[i].Member) + + if withScores { + c.writeBulk(ledis.StrPutInt64(ay[i].Score)) + } + } + } +} + func (c *client) writeBulkFrom(n int64, rb io.Reader) { c.wb.WriteByte('$') c.wb.Write(ledis.Slice(strconv.FormatInt(n, 10))) diff --git a/server/cmd_hash.go b/server/cmd_hash.go index 23873b1..1dd36e0 100644 --- a/server/cmd_hash.go +++ b/server/cmd_hash.go @@ -141,7 +141,7 @@ func hmgetCommand(c *client) error { if v, err := c.db.HMget(args[0], args[1:]...); err != nil { return err } else { - c.writeArray(v) + c.writeSliceArray(v) } return nil @@ -156,7 +156,7 @@ func hgetallCommand(c *client) error { if v, err := c.db.HGetAll(args[0]); err != nil { return err } else { - c.writeArray(v) + c.writeFVPairArray(v) } return nil @@ -171,7 +171,7 @@ func hkeysCommand(c *client) error { if v, err := c.db.HKeys(args[0]); err != nil { return err } else { - c.writeArray(v) + c.writeSliceArray(v) } return nil @@ -186,7 +186,7 @@ func hvalsCommand(c *client) error { if v, err := c.db.HValues(args[0]); err != nil { return err } else { - c.writeArray(v) + c.writeSliceArray(v) } return nil diff --git a/server/cmd_kv.go b/server/cmd_kv.go index f70a508..d924e4e 100644 --- a/server/cmd_kv.go +++ b/server/cmd_kv.go @@ -197,7 +197,7 @@ func mgetCommand(c *client) error { if v, err := c.db.MGet(args...); err != nil { return err } else { - c.writeArray(v) + c.writeSliceArray(v) } return nil diff --git a/server/cmd_list.go b/server/cmd_list.go index 58d64f3..0992f56 100644 --- a/server/cmd_list.go +++ b/server/cmd_list.go @@ -122,7 +122,7 @@ func lrangeCommand(c *client) error { if v, err := c.db.LRange(args[0], int32(start), int32(stop)); err != nil { return err } else { - c.writeArray(v) + c.writeSliceArray(v) } return nil diff --git a/server/cmd_zset.go b/server/cmd_zset.go index 4004134..4411113 100644 --- a/server/cmd_zset.go +++ b/server/cmd_zset.go @@ -312,16 +312,10 @@ func zrangeGeneric(c *client, reverse bool) error { withScores = true } - if datas, err := c.db.ZRangeGeneric(key, start, stop, withScores, reverse); err != nil { + if datas, err := c.db.ZRangeGeneric(key, start, stop, reverse); err != nil { return err } else { - if withScores { - for i := len(datas) - 1; i > 0; i -= 2 { - v, _ := datas[i].(int64) - datas[i] = ledis.StrPutInt64(v) - } - } - c.writeArray(datas) + c.writeScorePairArray(datas, withScores) } return nil } @@ -383,16 +377,10 @@ func zrangebyscoreGeneric(c *client, reverse bool) error { return nil } - if datas, err := c.db.ZRangeByScoreGeneric(key, min, max, withScores, offset, count, reverse); err != nil { + if datas, err := c.db.ZRangeByScoreGeneric(key, min, max, offset, count, reverse); err != nil { return err } else { - if withScores { - for i := len(datas) - 1; i > 0; i -= 2 { - v, _ := datas[i].(int64) - datas[i] = ledis.StrPutInt64(v) - } - } - c.writeArray(datas) + c.writeScorePairArray(datas, withScores) } return nil